From 46712500a9a0f434c6af02c17a3f5e842d6800a2 Mon Sep 17 00:00:00 2001 From: Andy Li Date: Wed, 1 Feb 2017 17:49:09 +0800 Subject: [PATCH 1/8] Imported Upstream version 3.4.0 --- .merlin | 4 + .travis.yml | 85 - CONTRIBUTING.md | 18 +- Makefile | 257 +- Makefile.win | 30 +- README.md | 50 +- analyzer.ml | 1667 ---- appveyor.yml | 66 - ast.ml | 772 -- codegen.ml | 1958 ----- common.ml | 1078 --- extra/CHANGES.txt | 168 +- extra/ImportAll.hx | 52 +- extra/LICENSE.txt | 470 +- extra/all.hxml | 10 + extra/bintray.tpl.json | 27 + extra/choco/haxe.nuspec | 27 + extra/deploy_key.enc | Bin 0 -> 3264 bytes extra/extract.hxml | 8 +- extra/extract.patch | 3 + extra/haxeci_sec.gpg.enc | Bin 0 -> 6608 bytes extra/haxeci_ssh.enc | Bin 0 -> 3264 bytes extra/haxelib_src/.dockerignore | 7 + .../.ebextensions/cloudwatch.config | 26 + .../.ebextensions/docker_volumes.config | 7 + extra/haxelib_src/.ebextensions/nginx.config | 7 + extra/haxelib_src/.travis.yml | 117 +- extra/haxelib_src/.vscode/settings.json | 6 + extra/haxelib_src/.vscode/tasks.json | 18 + extra/haxelib_src/CHANGES.md | 15 + extra/haxelib_src/Dockerfile | 74 + extra/haxelib_src/Dockerrun.aws.json | 13 + extra/haxelib_src/Package.hx | 63 - extra/haxelib_src/README.md | 94 +- extra/haxelib_src/apache2.conf | 64 + extra/haxelib_src/appveyor.yml | 18 +- extra/haxelib_src/ci.hxml | 2 + extra/haxelib_src/client.hxml | 3 + ...{legacyhaxelib.hxml => client_legacy.hxml} | 2 +- .../{test.hxml => client_tests.hxml} | 10 +- extra/haxelib_src/deploy.json | 42 + extra/haxelib_src/deploy_key.enc | Bin 0 -> 3264 bytes extra/haxelib_src/haxelib.hxml | 3 - extra/haxelib_src/haxelib.hxproj | 52 - extra/haxelib_src/haxelib.json | 8 +- extra/haxelib_src/haxelib.sh | 3 - extra/haxelib_src/haxelib_script.sh | 4 - extra/haxelib_src/integration_tests.hxml | 5 + extra/haxelib_src/legacyhaxelib.sh | 3 - extra/haxelib_src/package.hxml | 2 + extra/haxelib_src/package.sh | 2 - extra/haxelib_src/prepare.hxml | 5 - extra/haxelib_src/prepare_tests.hxml | 2 + extra/haxelib_src/run.bat | 3 - extra/haxelib_src/run.n | Bin 0 -> 203260 bytes extra/haxelib_src/schema.json | 61 +- extra/haxelib_src/server.hxml | 7 + extra/haxelib_src/server_api.hxml | 6 + extra/haxelib_src/server_each.hxml | 12 + extra/haxelib_src/server_legacy.hxml | 8 + extra/haxelib_src/server_tasks.hxml | 4 + extra/haxelib_src/server_tests.hxml | 10 + extra/haxelib_src/server_website.hxml | 3 + extra/haxelib_src/site.bat | 4 - extra/haxelib_src/site.hxml | 21 - extra/haxelib_src/site.sh | 49 - extra/haxelib_src/src/Package.hx | 69 + .../src/{tools => }/haxelib/Data.hx | 167 +- .../src/{tools => }/haxelib/SemVer.hx | 317 +- .../src/{tools => }/haxelib/SiteApi.hx | 11 +- .../src/{tools => }/haxelib/Validator.hx | 111 +- extra/haxelib_src/src/haxelib/client/Cli.hx | 46 + .../haxelib => haxelib/client}/ConvertXml.hx | 51 +- .../haxelib_src/src/haxelib/client/FsUtils.hx | 131 + .../{tools/haxelib => haxelib/client}/Main.hx | 1468 ++-- extra/haxelib_src/src/haxelib/client/Vcs.hx | 378 + .../src/haxelib/server/FileStorage.hx | 284 + extra/haxelib_src/src/haxelib/server/Paths.hx | 54 + extra/haxelib_src/src/haxelib/server/Repo.hx | 368 + .../haxelib => haxelib/server}/SiteDb.hx | 63 +- .../src/{tools => }/legacyhaxelib/.htaccess | 0 .../src/{tools => }/legacyhaxelib/Data.hx | 2 +- .../src/{tools => }/legacyhaxelib/Main.hx | 4 +- .../src/{tools => }/legacyhaxelib/Site.hx | 57 +- .../src/{tools => }/legacyhaxelib/SiteApi.hx | 9 +- .../src/{tools => }/legacyhaxelib/SiteDb.hx | 2 +- .../src/{tools => }/legacyhaxelib/haxelib.css | 0 .../{tools => }/legacyhaxelib/haxelib.hxml | 6 +- .../haxelib_src/src/legacyhaxelib/haxelib.sh | 2 + extra/haxelib_src/src/legacyhaxelib/site.hxml | 5 + .../src/{tools => }/legacyhaxelib/website.mtt | 0 extra/haxelib_src/src/tools/haxelib/Paths.hx | 19 - .../haxelib_src/src/tools/haxelib/Rebuild.hx | 46 - extra/haxelib_src/src/tools/haxelib/Repo.hx | 325 - extra/haxelib_src/src/tools/haxelib/Site.hx | 313 - .../haxelib_src/src/tools/haxelib/Template.hx | 72 - extra/haxelib_src/src/tools/haxelib/Vcs.hx | 399 - .../haxelib_src/src/tools/haxelib/haxelib.css | 216 - .../src/tools/haxelib/tmpl/documentation.mtt | 14 - .../src/tools/haxelib/tmpl/error.mtt | 5 - .../src/tools/haxelib/tmpl/index.mtt | 24 - .../src/tools/haxelib/tmpl/layout.mtt | 38 - .../src/tools/haxelib/tmpl/list.mtt | 12 - .../src/tools/haxelib/tmpl/project.mtt | 27 - .../src/tools/haxelib/tmpl/tag.mtt | 16 - .../src/tools/haxelib/tmpl/user.mtt | 16 - .../src/tools/legacyhaxelib/haxelib.sh | 2 - .../src/tools/legacyhaxelib/site.hxml | 5 - extra/haxelib_src/src/website/Server.hx | 88 + extra/haxelib_src/src/website/Tasks.hx | 58 + .../src/website/api/DocumentationApi.hx | 22 + .../haxelib_src/src/website/api/ProjectApi.hx | 237 + .../src/website/api/ProjectListApi.hx | 73 + extra/haxelib_src/src/website/api/UserApi.hx | 69 + .../controller/DocumentationController.hx | 36 + .../src/website/controller/HomeController.hx | 193 + .../website/controller/ProjectController.hx | 185 + .../src/website/controller/RSSController.hx | 86 + .../src/website/controller/UserController.hx | 35 + .../src/website/homepage-example.txt | 12 + extra/haxelib_src/src/website/model/SiteDb.hx | 7 + .../src/website/tasks/HaxelibCacheTasks.hx | 29 + extra/haxelib_src/test.sh | 3 - extra/haxelib_src/test/HaxelibTests.hx | 65 +- extra/haxelib_src/test/IntegrationTests.hx | 174 + extra/haxelib_src/test/Prepare.hx | 52 + extra/haxelib_src/test/RunCi.hx | 386 + extra/haxelib_src/test/TestBase.hx | 33 + extra/haxelib_src/test/WebsiteTests.hx | 44 + extra/haxelib_src/test/docker-compose-dev.yml | 27 + extra/haxelib_src/test/docker-compose.yml | 25 + .../test/libraries/UseCp/haxelib.json | 11 + .../libraries/UseCp/lib/src}/bar/Bar.hx | 0 .../libraries/UseGitDep}/foo/Foo.hx | 0 .../test/libraries/UseGitDep/haxelib.json | 13 + .../test/libraries/UseGitDep/haxelib.xml | 7 + .../test/libraries/UseGitDep/tag_haxelib.json | 13 + .../test/libraries/libBar/bar/Bar.hx | 9 + .../libraries/libBar/haxelib.json | 0 .../libraries/libBar/haxelib.xml | 0 .../test/libraries/libBar2/bar/Bar.hx | 9 + .../test/libraries/libBar2/haxelib.json | 10 + .../test/libraries/libBar2/haxelib.xml | 7 + .../test/libraries/libFoo/foo/Foo.hx | 9 + .../libraries/libFoo/haxelib.json | 2 +- .../libraries/libFoo/haxelib.xml | 0 extra/haxelib_src/test/tests/TestCli.hx | 46 - extra/haxelib_src/test/tests/TestData.hx | 60 +- extra/haxelib_src/test/tests/TestGit.hx | 9 + extra/haxelib_src/test/tests/TestHg.hx | 9 + extra/haxelib_src/test/tests/TestInstall.hx | 101 + .../test/tests/TestRemoveSymlinks.hx | 41 +- .../test/tests/TestRemoveSymlinksBroken.hx | 9 + extra/haxelib_src/test/tests/TestSemVer.hx | 22 +- extra/haxelib_src/test/tests/TestVcs.hx | 35 +- .../haxelib_src/test/tests/TestVcsNotFound.hx | 36 +- .../test/tests/integration/TestDev.hx | 136 + .../test/tests/integration/TestEmpty.hx | 78 + .../test/tests/integration/TestInfo.hx | 66 + .../test/tests/integration/TestList.hx | 116 + .../test/tests/integration/TestSet.hx | 77 + .../test/tests/integration/TestSimple.hx | 91 + .../test/tests/integration/TestUpdate.hx | 69 + .../test/tests/integration/TestUpgrade.hx | 79 + .../test/tests/integration/TestUser.hx | 49 + .../controller/DocumentationControllerTest.hx | 48 + .../website/controller/HomeControllerTest.hx | 137 + .../controller/ProjectControllerTest.hx | 158 + .../website/controller/RSSControllerTest.hx | 46 + .../website/controller/UserControllerTest.hx | 73 + extra/haxelib_src/testing/PrepareServer.hx | 131 - extra/haxelib_src/testing/installSeveral.hxml | 3 - .../{src/tools/haxelib => www}/.htaccess | 8 + extra/haxelib_src/www/bower.json | 23 + extra/haxelib_src/www/css/haxelib.css | 164 + extra/haxelib_src/www/css/style.css | 741 ++ .../dbconfig.json} | 10 +- .../www/documentation-files/api.md | 5 + .../creating-a-haxelib-package.md | 91 + .../www/documentation-files/faq.md | 3 + .../www/documentation-files/index.md | 24 + .../www/documentation-files/installation.md | 4 + .../documentation-files/per-project-setup.md | 45 + .../documentation-files/tips-and-tricks.md | 3 + .../www/documentation-files/using-haxelib.md | 618 ++ extra/haxelib_src/www/favicon.ico | Bin 0 -> 1150 bytes .../www/img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes .../www/img/glyphicons-halflings.png | Bin 0 -> 12799 bytes .../www/img/haxe-logo-horizontal-on-dark.png | Bin 0 -> 1566 bytes .../www/img/haxe-logo-horizontal-on-dark.svg | 154 + .../www/img/haxe-logo-horizontal.svg | 153 + .../www/img/haxe-logo-vertical.svg | 119 + extra/haxelib_src/www/img/haxe-logo.png | Bin 0 -> 5072 bytes extra/haxelib_src/www/img/haxe-logo.svg | 103 + extra/haxelib_src/www/img/homepage_banner.jpg | Bin 0 -> 94785 bytes extra/haxelib_src/www/img/logo_small.png | Bin 0 -> 665 bytes extra/haxelib_src/www/robots.txt | 7 + .../view/documentation/documentationPage.html | 13 + extra/haxelib_src/www/view/home/homepage.html | 58 + .../www/view/home/projectList.html | 26 + extra/haxelib_src/www/view/home/search.html | 48 + extra/haxelib_src/www/view/home/tagList.html | 30 + extra/haxelib_src/www/view/layout.html | 167 + extra/haxelib_src/www/view/project/docs.html | 2 + extra/haxelib_src/www/view/project/file.html | 73 + .../haxelib_src/www/view/project/version.html | 96 + .../www/view/project/versionList.html | 41 + extra/haxelib_src/www/view/user/list.html | 28 + extra/haxelib_src/www/view/user/profile.html | 33 + extra/images/Banner.bmp | Bin 26682 -> 25820 bytes extra/images/Wizard.bmp | Bin 155406 -> 154544 bytes extra/installer.nsi | 2 +- extra/release-checklist.txt | 16 +- extra/setup.cpp | 33 +- gencpp.ml | 5732 ------------- haxe.hxproj | 276 +- libs/.editorconfig | 11 + libs/.travis.yml | 23 + libs/Makefile | 5 +- libs/README.md | 5 + libs/extc/LICENSE | 41 +- libs/extc/Makefile | 8 +- libs/extc/extc.ml | 4 +- libs/extc/extc_stubs.c | 310 +- libs/extc/process.ml | 4 +- libs/extc/process_stubs.c | 123 +- libs/extc/test.ml | 2 +- libs/extc/zlib/README.txt | 1 - libs/extc/zlib/zconf.h | 332 - libs/extc/zlib/zlib.h | 1357 --- libs/extc/zlib/zlib.lib | Bin 109512 -> 0 bytes libs/extlib/IO.ml | 2 +- libs/extlib/IO.mli | 2 +- libs/extlib/LICENSE | 670 +- libs/extlib/Makefile | 2 +- libs/extlib/README.txt | 2 +- libs/extlib/base64.ml | 2 +- libs/extlib/base64.mli | 2 +- libs/extlib/bitSet.ml | 2 +- libs/extlib/bitSet.mli | 2 +- libs/extlib/dllist.ml | 2 +- libs/extlib/dllist.mli | 2 +- libs/extlib/dynArray.ml | 2 +- libs/extlib/dynArray.mli | 2 +- libs/extlib/enum.ml | 2 +- libs/extlib/enum.mli | 2 +- libs/extlib/extArray.ml | 2 +- libs/extlib/extArray.mli | 2 +- libs/extlib/extHashtbl.ml | 2 +- libs/extlib/extHashtbl.mli | 2 +- libs/extlib/extLib.ml | 2 +- libs/extlib/extList.ml | 2 +- libs/extlib/extList.mli | 2 +- libs/extlib/extString.ml | 2 +- libs/extlib/extString.mli | 2 +- libs/extlib/global.ml | 2 +- libs/extlib/global.mli | 2 +- libs/extlib/install.ml | 2 +- libs/extlib/multiArray.ml | 2 +- libs/extlib/multiArray.mli | 2 +- libs/extlib/optParse.ml | 2 +- libs/extlib/optParse.mli | 2 +- libs/extlib/option.ml | 2 +- libs/extlib/option.mli | 2 +- libs/extlib/pMap.ml | 2 +- libs/extlib/pMap.mli | 2 +- libs/extlib/rbuffer.ml | 50 +- libs/extlib/refList.ml | 2 +- libs/extlib/refList.mli | 2 +- libs/extlib/sMap.ml | 169 + libs/extlib/sMap.mli | 83 + libs/extlib/std.ml | 2 +- libs/extlib/std.mli | 2 +- libs/extlib/uChar.ml | 2 +- libs/extlib/uChar.mli | 2 +- libs/extlib/uTF8.ml | 2 +- libs/extlib/uTF8.mli | 2 +- libs/extlib/unzip.ml | 2 +- libs/extlib/unzip.mli | 2 +- libs/ilib/ilData.mli | 2 +- libs/ilib/ilMeta.mli | 2 +- libs/ilib/ilMetaDebug.ml | 2 +- libs/ilib/ilMetaReader.ml | 2 +- libs/ilib/ilMetaTools.ml | 2 +- libs/ilib/ilMetaWriter.ml | 2 +- libs/ilib/peData.ml | 2 +- libs/ilib/peDataDebug.ml | 2 +- libs/ilib/peReader.ml | 2 +- libs/ilib/peWriter.ml | 2 +- libs/javalib/Makefile | 2 +- libs/javalib/jData.ml | 4 +- libs/javalib/jReader.ml | 44 +- libs/javalib/jWriter.ml | 180 +- libs/neko/binast.ml | 2 +- libs/neko/nast.ml | 2 +- libs/neko/nxml.ml | 2 +- libs/objsize/Makefile | 6 +- libs/ocamake/ocamake.ml | 8 +- libs/pcre/Makefile | 27 + libs/pcre/pcre.ml | 1034 +++ libs/pcre/pcre_stubs.c | 737 ++ libs/swflib/LICENSE | 41 +- libs/swflib/Makefile | 8 +- libs/swflib/actionScript.ml | 2 +- libs/swflib/as3.mli | 2 +- libs/swflib/as3code.ml | 2 +- libs/swflib/as3hl.mli | 2 +- libs/swflib/as3hlparse.ml | 4 +- libs/swflib/as3parse.ml | 4 +- libs/swflib/png.ml | 2 +- libs/swflib/png.mli | 2 +- libs/swflib/swf.ml | 2 +- libs/swflib/swfParser.ml | 4 +- libs/swflib/swfPic.ml | 2 +- libs/xml-light/Makefile | 8 +- main.ml | 1749 ---- matcher.ml | 1454 ---- src/context/common.ml | 1149 +++ src/context/meta.ml | 430 + src/display/display.ml | 926 ++ src/display/displayOutput.ml | 803 ++ src/display/displayTypes.ml | 59 + src/generators/codegen.ml | 889 ++ genas3.ml => src/generators/genas3.ml | 132 +- gencommon.ml => src/generators/gencommon.ml | 4975 ++++------- src/generators/gencpp.ml | 7566 +++++++++++++++++ gencs.ml => src/generators/gencs.ml | 663 +- src/generators/genhl.ml | 3719 ++++++++ genjava.ml => src/generators/genjava.ml | 427 +- genjs.ml => src/generators/genjs.ml | 447 +- src/generators/genlua.ml | 2108 +++++ genneko.ml => src/generators/genneko.ml | 47 +- genphp.ml => src/generators/genphp.ml | 200 +- src/generators/genphp7.ml | 3513 ++++++++ genpy.ml => src/generators/genpy.ml | 392 +- genswf.ml => src/generators/genswf.ml | 130 +- genswf9.ml => src/generators/genswf9.ml | 109 +- genxml.ml => src/generators/genxml.ml | 56 +- src/generators/hl2c.ml | 1410 +++ src/generators/hlcode.ml | 659 ++ src/generators/hlinterp.ml | 2853 +++++++ src/generators/hlopt.ml | 834 ++ src/globals.ml | 64 + src/json.ml | 104 + src/macro/hlmacro.ml | 554 ++ interp.ml => src/macro/interp.ml | 2872 +------ src/macro/macroApi.ml | 1872 ++++ src/macro/macroContext.ml | 765 ++ src/main.ml | 963 +++ src/optimization/analyzer.ml | 1060 +++ src/optimization/analyzerConfig.ml | 140 + src/optimization/analyzerTexpr.ml | 1132 +++ src/optimization/analyzerTexprTransformer.ml | 745 ++ src/optimization/analyzerTypes.ml | 526 ++ dce.ml => src/optimization/dce.ml | 272 +- filters.ml => src/optimization/filters.ml | 535 +- optimizer.ml => src/optimization/optimizer.ml | 952 +-- src/optimization/optimizerTexpr.ml | 306 + src/path.ml | 148 + src/server.ml | 637 ++ src/syntax/ast.ml | 869 ++ lexer.mll => src/syntax/lexer.mll | 75 +- parser.ml => src/syntax/parser.ml | 630 +- src/typing/abstract.ml | 67 + src/typing/error.ml | 94 + src/typing/matcher.ml | 1441 ++++ src/typing/overloads.ml | 261 + type.ml => src/typing/type.ml | 1074 ++- src/typing/typecore.ml | 730 ++ src/typing/typeload.ml | 4189 +++++++++ typer.ml => src/typing/typer.ml | 3658 ++++---- std/Any.hx | 37 + std/Array.hx | 13 +- std/Class.hx | 4 +- std/Date.hx | 12 +- std/DateTools.hx | 33 +- std/EReg.hx | 8 +- std/Enum.hx | 4 +- std/EnumValue.hx | 4 +- std/IntIterator.hx | 4 +- std/Lambda.hx | 30 +- std/List.hx | 93 +- std/Map.hx | 7 +- std/Math.hx | 13 +- std/Reflect.hx | 8 +- std/Std.hx | 2 +- std/StdTypes.hx | 88 +- std/String.hx | 38 +- std/StringBuf.hx | 2 +- std/StringTools.hx | 228 +- std/Sys.hx | 34 +- std/Type.hx | 44 +- std/UInt.hx | 34 +- std/Xml.hx | 94 +- std/cpp/ArrayBase.hx | 23 +- std/cpp/AtomicInt.hx | 18 + std/cpp/AutoCast.hx | 24 + std/cpp/Callable.hx | 56 +- std/cpp/CastCharStar.hx | 23 +- std/cpp/Char.hx | 23 +- std/cpp/ConstCharStar.hx | 25 +- std/cpp/ConstPointer.hx | 75 +- std/cpp/EnumBase.hx | 31 + std/{js/html/Point.hx => cpp/FILE.hx} | 11 +- std/cpp/FastIterator.hx | 2 +- std/cpp/Finalizable.hx | 14 + std/cpp/Float32.hx | 23 +- std/cpp/Float64.hx | 23 +- std/cpp/Function.hx | 60 +- std/cpp/Int16.hx | 23 +- std/cpp/Int32.hx | 23 +- std/cpp/Int64.hx | 23 +- std/cpp/Int8.hx | 23 +- std/cpp/Lib.hx | 67 +- std/cpp/NativeArc.hx | 12 + std/cpp/NativeArray.hx | 89 +- std/cpp/NativeFile.hx | 64 + std/cpp/NativeGc.hx | 22 + std/cpp/NativeMath.hx | 31 + std/cpp/NativeProcess.hx | 40 + std/cpp/NativeRandom.hx | 23 + std/cpp/NativeSocket.hx | 155 + std/cpp/NativeSsl.hx | 114 + std/cpp/NativeString.hx | 49 +- std/cpp/NativeSys.hx | 113 + std/cpp/NativeXml.hx | 862 +- std/cpp/NativeXmlImport.cpp | 365 + std/cpp/Object.hx | 38 +- std/cpp/ObjectType.hx | 19 + std/cpp/Pointer.hx | 88 +- std/cpp/Prime.hx | 15 +- std/cpp/Random.hx | 15 +- std/cpp/RawConstPointer.hx | 27 +- std/cpp/RawPointer.hx | 25 +- std/{js/html/BarInfo.hx => cpp/Reference.hx} | 11 +- std/cpp/SizeT.hx | 27 + std/{js/html/DOMWindow.hx => cpp/Star.hx} | 10 +- std/cpp/StdString.hx | 22 + std/cpp/StdStringRef.hx | 17 + std/cpp/Stdio.hx | 45 + std/cpp/Stdlib.hx | 62 + std/cpp/UInt16.hx | 23 +- std/cpp/UInt32.hx | 23 +- std/cpp/UInt64.hx | 23 +- std/cpp/UInt8.hx | 23 +- std/cpp/VarArg.hx | 28 + std/cpp/VirtualArray.hx | 76 + std/cpp/Void.hx | 23 +- std/cpp/_std/Date.hx | 2 +- std/cpp/_std/EReg.hx | 46 +- std/cpp/_std/Reflect.hx | 23 +- std/cpp/_std/Std.hx | 2 +- std/cpp/_std/StringBuf.hx | 85 +- std/cpp/_std/Sys.hx | 98 +- std/cpp/_std/Type.hx | 17 +- std/cpp/_std/haxe/Int64.hx | 216 +- std/cpp/_std/haxe/Resource.hx | 2 +- std/cpp/_std/haxe/Utf8.hx | 55 +- std/cpp/_std/haxe/ds/IntMap.hx | 7 +- std/cpp/_std/haxe/ds/ObjectMap.hx | 3 +- std/cpp/_std/haxe/ds/StringMap.hx | 4 +- std/cpp/_std/haxe/ds/WeakMap.hx | 3 +- std/cpp/_std/haxe/zip/Compress.hx | 23 +- std/cpp/_std/haxe/zip/Uncompress.hx | 19 +- std/cpp/_std/sys/FileSystem.hx | 56 +- std/cpp/_std/sys/db/Mysql.hx | 65 +- std/cpp/_std/sys/db/Sqlite.hx | 47 +- std/cpp/_std/sys/io/File.hx | 19 +- std/cpp/_std/sys/io/FileInput.hx | 24 +- std/cpp/_std/sys/io/FileOutput.hx | 23 +- std/cpp/_std/sys/io/Process.hx | 36 +- std/cpp/_std/sys/net/Host.hx | 30 +- std/cpp/_std/sys/net/Socket.hx | 429 +- std/cpp/_std/sys/net/UdpSocket.hx | 60 + std/cpp/_std/sys/ssl/Certificate.hx | 115 + std/cpp/_std/sys/ssl/Digest.hx | 19 + std/cpp/_std/sys/ssl/Key.hx | 36 + std/cpp/_std/sys/ssl/Socket.hx | 268 + std/cpp/abi/Abi.hx | 23 +- std/cpp/abi/CDecl.hx | 23 +- std/cpp/abi/FastCall.hx | 23 +- std/cpp/abi/StdCall.hx | 23 +- std/cpp/abi/ThisCall.hx | 23 +- std/cpp/abi/Winapi.hx | 23 +- std/cpp/cppia/Host.hx | 38 +- std/cpp/cppia/HostClasses.hx | 50 +- std/cpp/cppia/Module.hx | 35 + std/cpp/link/StaticMysql.hx | 26 + std/cpp/link/StaticRegexp.hx | 26 + std/cpp/link/StaticSqlite.hx | 26 + std/cpp/link/StaticStd.hx | 26 + std/cpp/link/StaticZlib.hx | 27 + std/cpp/net/Poll.hx | 28 +- std/cpp/net/ThreadServer.hx | 83 +- std/cpp/objc/NSData.hx | 51 + std/cpp/objc/NSDictionary.hx | 44 + .../html/DOMPlugin.hx => cpp/objc/NSError.hx} | 13 +- std/cpp/objc/NSLog.hx | 33 + std/cpp/objc/NSObject.hx | 44 + std/cpp/objc/NSString.hx | 45 + std/cpp/objc/ObjcBlock.hx | 27 + std/cpp/objc/Protocol.hx | 27 + std/cpp/rtti/FieldIntegerLookup.hx | 2 +- std/cpp/rtti/FieldNumericIntegerLookup.hx | 2 +- std/cpp/vm/Debugger.hx | 6 +- std/cpp/vm/Deque.hx | 2 +- std/cpp/vm/ExecutionTrace.hx | 23 +- std/cpp/vm/Gc.hx | 28 +- std/cpp/vm/Lock.hx | 2 +- std/cpp/vm/Mutex.hx | 2 +- std/cpp/vm/Profiler.hx | 2 +- std/cpp/vm/Thread.hx | 12 +- std/cpp/vm/Tls.hx | 2 +- std/cpp/vm/Unsafe.hx | 23 +- std/cpp/vm/WeakRef.hx | 2 +- std/cpp/zip/Compress.hx | 25 +- std/cpp/zip/Flush.hx | 25 +- std/cpp/zip/Uncompress.hx | 25 +- std/cs/Boot.hx | 6 +- std/cs/Flags.hx | 25 +- std/cs/Lib.hx | 11 +- std/cs/NativeArray.hx | 2 +- std/cs/Out.hx | 2 +- std/cs/Pointer.hx | 2 +- std/cs/Ref.hx | 2 +- std/cs/StdTypes.hx | 16 +- std/cs/_std/Array.hx | 2 +- std/cs/_std/Date.hx | 30 +- std/cs/_std/EReg.hx | 2 +- std/cs/_std/Math.hx | 2 +- std/cs/_std/Reflect.hx | 9 +- std/cs/_std/Std.hx | 33 +- std/cs/_std/String.hx | 2 +- std/cs/_std/StringBuf.hx | 2 +- std/cs/_std/Sys.hx | 61 +- std/cs/_std/Type.hx | 56 +- std/cs/_std/haxe/Int64.hx | 14 +- std/cs/_std/haxe/Resource.hx | 6 +- std/cs/_std/haxe/ds/IntMap.hx | 37 +- std/cs/_std/haxe/ds/ObjectMap.hx | 6 +- std/cs/_std/haxe/ds/StringMap.hx | 2 +- std/cs/_std/sys/FileSystem.hx | 17 +- std/cs/_std/sys/db/Sqlite.hx | 23 +- std/cs/_std/sys/io/File.hx | 2 +- std/cs/_std/sys/io/FileInput.hx | 2 +- std/cs/_std/sys/io/FileOutput.hx | 2 +- std/cs/_std/sys/io/Process.hx | 83 +- std/cs/_std/sys/net/Host.hx | 29 +- std/cs/_std/sys/net/Socket.hx | 41 +- std/cs/db/AdoNet.hx | 30 +- std/cs/internal/BoxedPointer.hx | 23 +- std/cs/internal/Exceptions.hx | 4 +- std/cs/internal/FieldLookup.hx | 72 +- std/cs/internal/Function.hx | 7 +- std/cs/internal/HxObject.hx | 2 +- std/cs/internal/Iterator.hx | 7 +- std/cs/internal/Null.hx | 85 +- std/cs/internal/Runtime.hx | 21 +- std/cs/internal/StringExt.hx | 2 +- std/cs/io/NativeInput.hx | 6 +- std/cs/io/NativeOutput.hx | 7 +- std/cs/types/Char16.hx | 23 +- std/cs/types/Int16.hx | 23 +- std/cs/types/Int64.hx | 23 +- std/cs/types/Int8.hx | 23 +- std/cs/types/UInt16.hx | 23 +- std/cs/types/UInt64.hx | 23 +- std/cs/types/UInt8.hx | 23 +- std/flash/Boot.hx | 18 +- std/flash/Lib.hx | 6 +- std/flash/Memory.hx | 2 +- std/flash/NativeXml.hx | 2 +- std/flash/Vector.hx | 2 +- std/flash/_std/EReg.hx | 2 +- std/flash/_std/Reflect.hx | 2 +- std/flash/_std/Std.hx | 2 +- std/flash/_std/Type.hx | 4 +- std/flash/_std/haxe/Json.hx | 2 +- std/flash/_std/haxe/Resource.hx | 2 +- std/flash/_std/haxe/ds/IntMap.hx | 76 +- std/flash/_std/haxe/ds/ObjectMap.hx | 23 +- std/flash/_std/haxe/ds/StringMap.hx | 2 +- std/flash/_std/haxe/ds/UnsafeStringMap.hx | 77 +- std/flash/_std/haxe/ds/WeakMap.hx | 23 +- std/flash/_std/haxe/zip/Compress.hx | 2 +- std/flash/_std/haxe/zip/Uncompress.hx | 2 +- std/flash/accessibility/Accessibility.hx | 2 +- std/flash/accessibility/ISearchableText.hx | 2 +- .../accessibility/ISimpleTextSelection.hx | 4 +- std/flash/automation/Configuration.hx | 2 +- .../automation/KeyboardAutomationAction.hx | 4 +- std/flash/automation/MouseAutomationAction.hx | 16 +- std/flash/automation/StageCapture.hx | 13 +- std/flash/automation/StageCaptureEvent.hx | 9 +- std/flash/concurrent/Condition.hx | 4 +- std/flash/concurrent/Mutex.hx | 2 +- std/flash/desktop/Clipboard.hx | 4 +- std/flash/display/AVLoader.hx | 5 + std/flash/display/BitmapData.hx | 8 +- std/flash/display/DisplayObject.hx | 14 +- std/flash/display/DisplayObjectContainer.hx | 4 +- std/flash/display/FrameLabel.hx | 4 +- std/flash/display/Graphics.hx | 4 +- std/flash/display/Loader.hx | 6 +- std/flash/display/LoaderInfo.hx | 42 +- std/flash/display/MovieClip.hx | 18 +- std/flash/display/SWFVersion.hx | 24 +- std/flash/display/Scene.hx | 6 +- std/flash/display/Shader.hx | 2 +- std/flash/display/ShaderInput.hx | 4 +- std/flash/display/ShaderJob.hx | 2 +- std/flash/display/ShaderParameter.hx | 4 +- std/flash/display/Shape.hx | 2 +- std/flash/display/Sprite.hx | 4 +- std/flash/display/Stage.hx | 24 +- std/flash/display/Stage3D.hx | 4 +- std/flash/display3D/Context3D.hx | 18 +- std/flash/display3D/Context3DClearMask.hx | 8 +- std/flash/display3D/Context3DProfile.hx | 1 + std/flash/display3D/textures/VideoTexture.hx | 4 +- std/flash/errors/DRMManagerError.hx | 2 +- std/flash/errors/Error.hx | 4 +- std/flash/events/AVDictionaryDataEvent.hx | 6 +- std/flash/events/AVHTTPStatusEvent.hx | 4 +- std/flash/events/AVLoadInfoEvent.hx | 4 +- std/flash/events/AVManifestLoadEvent.hx | 10 +- std/flash/events/AVPauseAtPeriodEndEvent.hx | 4 +- std/flash/events/AVPlayStateEvent.hx | 4 +- std/flash/events/AVStatusEvent.hx | 40 +- std/flash/events/AVStreamSwitchEvent.hx | 16 +- std/flash/events/AccelerometerEvent.hx | 2 +- std/flash/events/ActivityEvent.hx | 2 +- std/flash/events/AsyncErrorEvent.hx | 2 +- std/flash/events/ContextMenuEvent.hx | 4 +- std/flash/events/DRMAuthenticateEvent.hx | 18 +- .../events/DRMAuthenticationCompleteEvent.hx | 2 +- .../events/DRMAuthenticationErrorEvent.hx | 2 +- std/flash/events/DRMDeviceGroupErrorEvent.hx | 8 +- std/flash/events/DRMDeviceGroupEvent.hx | 4 +- std/flash/events/DRMErrorEvent.hx | 10 +- std/flash/events/DRMLicenseRequestEvent.hx | 2 +- std/flash/events/DRMMetadataEvent.hx | 6 +- .../events/DRMReturnVoucherCompleteEvent.hx | 2 +- .../events/DRMReturnVoucherErrorEvent.hx | 2 +- std/flash/events/DRMStatusEvent.hx | 2 +- std/flash/events/DataEvent.hx | 4 +- std/flash/events/ErrorEvent.hx | 4 +- std/flash/events/Event.hx | 98 +- std/flash/events/FocusEvent.hx | 8 +- std/flash/events/FullScreenEvent.hx | 8 +- std/flash/events/GameInputEvent.hx | 8 +- std/flash/events/GeolocationEvent.hx | 2 +- std/flash/events/GestureEvent.hx | 6 +- std/flash/events/HTTPStatusEvent.hx | 6 +- std/flash/events/IMEEvent.hx | 4 +- std/flash/events/IOErrorEvent.hx | 8 +- std/flash/events/KeyboardEvent.hx | 4 +- std/flash/events/MouseEvent.hx | 42 +- std/flash/events/NetDataEvent.hx | 6 +- std/flash/events/NetMonitorEvent.hx | 4 +- std/flash/events/NetStatusEvent.hx | 2 +- std/flash/events/OutputProgressEvent.hx | 2 +- std/flash/events/PressAndTapGestureEvent.hx | 6 +- std/flash/events/ProgressEvent.hx | 4 +- std/flash/events/SampleDataEvent.hx | 2 +- std/flash/events/SecurityErrorEvent.hx | 2 +- std/flash/events/ShaderEvent.hx | 2 +- std/flash/events/SoftKeyboardEvent.hx | 8 +- std/flash/events/SoftKeyboardTrigger.hx | 4 +- .../events/StageVideoAvailabilityEvent.hx | 8 +- std/flash/events/StageVideoEvent.hx | 14 +- std/flash/events/StatusEvent.hx | 2 +- std/flash/events/SyncEvent.hx | 2 +- std/flash/events/TextEvent.hx | 4 +- std/flash/events/ThrottleEvent.hx | 6 +- std/flash/events/TimerEvent.hx | 4 +- std/flash/events/TouchEvent.hx | 34 +- std/flash/events/TransformGestureEvent.hx | 8 +- std/flash/events/UncaughtErrorEvent.hx | 4 +- std/flash/events/VideoEvent.hx | 12 +- std/flash/events/VideoTextureEvent.hx | 8 +- std/flash/external/ExternalInterface.hx | 4 +- std/flash/geom/Matrix3D.hx | 2 +- std/flash/geom/Point.hx | 2 +- std/flash/geom/Transform.hx | 6 +- std/flash/geom/Vector3D.hx | 10 +- std/flash/globalization/Collator.hx | 6 +- std/flash/globalization/CurrencyFormatter.hx | 10 +- .../globalization/CurrencyParseResult.hx | 4 +- std/flash/globalization/DateTimeFormatter.hx | 6 +- std/flash/globalization/LocaleID.hx | 6 +- std/flash/globalization/NumberFormatter.hx | 6 +- std/flash/globalization/NumberParseResult.hx | 6 +- std/flash/globalization/StringTools.hx | 6 +- std/flash/media/AVABRParameters.hx | 6 +- std/flash/media/AVABRProfileInfo.hx | 6 +- std/flash/media/AVCaptionStyle.hx | 78 +- std/flash/media/AVCuePoint.hx | 4 +- std/flash/media/AVInsertionResult.hx | 4 +- std/flash/media/AVPeriodInfo.hx | 20 +- std/flash/media/AVPlayState.hx | 20 +- std/flash/media/AVResult.hx | 202 +- std/flash/media/AVSegmentedSource.hx | 29 +- std/flash/media/AVStream.hx | 34 +- std/flash/media/AVTagData.hx | 4 +- std/flash/media/AVTimeline.hx | 16 +- std/flash/media/AVTrackInfo.hx | 22 +- std/flash/media/AVURLLoader.hx | 2 +- std/flash/media/AVURLStream.hx | 2 +- std/flash/media/AudioDecoder.hx | 12 +- std/flash/media/Camera.hx | 34 +- std/flash/media/H264Level.hx | 32 +- std/flash/media/H264Profile.hx | 4 +- std/flash/media/H264VideoStreamSettings.hx | 4 +- std/flash/media/Microphone.hx | 18 +- std/flash/media/Sound.hx | 14 +- std/flash/media/SoundChannel.hx | 6 +- std/flash/media/StageVideo.hx | 6 +- std/flash/media/StageVideoAvailability.hx | 4 +- .../media/StageVideoAvailabilityReason.hx | 10 +- std/flash/media/Video.hx | 4 +- std/flash/media/VideoCodec.hx | 6 +- std/flash/media/VideoStatus.hx | 6 +- std/flash/media/VideoStreamSettings.hx | 14 +- std/flash/net/FileReference.hx | 14 +- std/flash/net/FileReferenceList.hx | 2 +- std/flash/net/GroupSpecifier.hx | 2 +- std/flash/net/LocalConnection.hx | 4 +- std/flash/net/NetConnection.hx | 20 +- std/flash/net/NetGroup.hx | 10 +- std/flash/net/NetGroupInfo.hx | 16 +- std/flash/net/NetGroupReceiveMode.hx | 4 +- std/flash/net/NetGroupReplicationStrategy.hx | 4 +- std/flash/net/NetGroupSendMode.hx | 4 +- std/flash/net/NetGroupSendResult.hx | 6 +- std/flash/net/NetStream.hx | 38 +- std/flash/net/NetStreamAppendBytesAction.hx | 6 +- std/flash/net/NetStreamInfo.hx | 50 +- std/flash/net/NetStreamMulticastInfo.hx | 38 +- std/flash/net/ObjectEncoding.hx | 6 +- std/flash/net/SecureSocket.hx | 6 +- std/flash/net/SharedObject.hx | 6 +- std/flash/net/SharedObjectFlushStatus.hx | 4 +- std/flash/net/Socket.hx | 6 +- std/flash/net/URLRequestMethod.hx | 12 +- std/flash/net/URLStream.hx | 8 +- std/flash/net/XMLSocket.hx | 2 +- std/flash/net/drm/AddToDeviceGroupSetting.hx | 6 +- std/flash/net/drm/AuthenticationMethod.hx | 4 +- std/flash/net/drm/DRMAuthenticationContext.hx | 2 +- std/flash/net/drm/DRMContentData.hx | 8 +- std/flash/net/drm/DRMDeviceGroup.hx | 6 +- std/flash/net/drm/DRMManager.hx | 2 +- std/flash/net/drm/DRMManagerSession.hx | 8 +- std/flash/net/drm/DRMPlaybackTimeWindow.hx | 6 +- std/flash/net/drm/DRMStoreVoucherContext.hx | 6 + std/flash/net/drm/DRMVoucher.hx | 18 +- .../net/drm/DRMVoucherDownloadContext.hx | 2 +- std/flash/net/drm/DRMVoucherStoreContext.hx | 2 +- std/flash/net/drm/LoadVoucherSetting.hx | 6 +- std/flash/net/drm/VoucherAccessInfo.hx | 10 +- std/flash/printing/PrintJob.hx | 12 +- std/flash/profiler/Telemetry.hx | 11 + std/flash/sampler/ClassFactory.hx | 8 +- std/flash/sampler/DeleteObjectSample.hx | 4 +- std/flash/sampler/NewObjectSample.hx | 8 +- std/flash/sampler/Sample.hx | 4 +- std/flash/sampler/StackFrame.hx | 8 +- std/flash/security/CertificateStatus.hx | 18 +- std/flash/security/X500DistinguishedName.hx | 12 +- std/flash/security/X509Certificate.hx | 26 +- std/flash/sensors/Accelerometer.hx | 4 +- std/flash/sensors/Geolocation.hx | 4 +- std/flash/system/ApplicationDomain.hx | 6 +- std/flash/system/ApplicationInstaller.hx | 2 +- std/flash/system/AuthorizedFeatures.hx | 2 + std/flash/system/AuthorizedFeaturesLoader.hx | 2 +- std/flash/system/Capabilities.hx | 68 +- std/flash/system/IME.hx | 2 +- std/flash/system/MessageChannel.hx | 4 +- std/flash/system/MessageChannelState.hx | 6 +- std/flash/system/Security.hx | 14 +- std/flash/system/SecurityDomain.hx | 4 +- std/flash/system/System.hx | 14 +- std/flash/system/Worker.hx | 8 +- std/flash/system/WorkerDomain.hx | 4 +- std/flash/text/Font.hx | 6 +- std/flash/text/StaticText.hx | 2 +- std/flash/text/StyleSheet.hx | 2 +- std/flash/text/TextField.hx | 24 +- std/flash/text/TextFormat.hx | 2 +- std/flash/text/TextSnapshot.hx | 2 +- std/flash/text/engine/ContentElement.hx | 12 +- std/flash/text/engine/GroupElement.hx | 2 +- std/flash/text/engine/TextBlock.hx | 8 +- std/flash/text/engine/TextJustifier.hx | 2 +- std/flash/text/engine/TextLine.hx | 38 +- std/flash/text/engine/TextLineMirrorRegion.hx | 12 +- std/flash/text/ime/IIMEClient.hx | 10 +- std/flash/trace/Trace.hx | 14 +- std/flash/ui/ContextMenu.hx | 2 +- std/flash/ui/GameInput.hx | 4 +- std/flash/ui/GameInputControl.hx | 10 +- std/flash/ui/GameInputDevice.hx | 8 +- std/flash/ui/Keyboard.hx | 560 +- std/flash/ui/Mouse.hx | 4 +- std/flash/ui/MouseCursor.hx | 10 +- std/flash/ui/Multitouch.hx | 8 +- std/flash/utils/ByteArray.hx | 2 +- std/flash/utils/Dictionary.hx | 2 +- std/flash/utils/IDataInput.hx | 2 +- std/flash/utils/Namespace.hx | 4 +- std/flash/utils/ObjectInput.hx | 2 +- std/flash/utils/QName.hx | 4 +- std/flash/utils/RegExp.hx | 14 +- std/flash/utils/Timer.hx | 4 +- std/flash/xml/XMLNode.hx | 8 +- std/haxe/CallStack.hx | 47 +- std/haxe/Constraints.hx | 17 +- std/haxe/DynamicAccess.hx | 2 +- std/haxe/EntryPoint.hx | 147 + std/haxe/EnumFlags.hx | 4 +- std/haxe/EnumTools.hx | 58 +- std/haxe/Http.hx | 151 +- std/haxe/Int32.hx | 58 +- std/haxe/Int64.hx | 37 +- std/haxe/Int64Helper.hx | 109 + std/haxe/Json.hx | 22 +- std/haxe/Log.hx | 26 +- std/haxe/MainLoop.hx | 164 + std/haxe/PosInfos.hx | 2 +- std/haxe/Resource.hx | 2 +- std/haxe/Serializer.hx | 92 +- std/haxe/Template.hx | 21 +- std/haxe/Timer.hx | 32 +- std/haxe/Ucs2.hx | 4 +- std/haxe/Unserializer.hx | 71 +- std/haxe/Utf8.hx | 8 +- std/haxe/crypto/Adler32.hx | 2 +- std/haxe/crypto/Base64.hx | 2 +- std/haxe/crypto/BaseCode.hx | 4 +- std/haxe/crypto/Crc32.hx | 2 +- std/haxe/crypto/Hmac.hx | 2 +- std/haxe/crypto/Md5.hx | 24 +- std/haxe/crypto/Sha1.hx | 9 +- std/haxe/crypto/Sha224.hx | 42 +- std/haxe/crypto/Sha256.hx | 35 +- std/haxe/ds/ArraySort.hx | 2 +- std/haxe/ds/BalancedTree.hx | 5 +- std/haxe/ds/Either.hx | 2 +- std/haxe/ds/EnumValueMap.hx | 2 +- std/haxe/ds/GenericStack.hx | 9 +- std/haxe/ds/HashMap.hx | 36 +- std/haxe/ds/IntMap.hx | 4 +- std/haxe/ds/ListSort.hx | 6 +- std/haxe/ds/ObjectMap.hx | 4 +- std/haxe/ds/Option.hx | 4 +- std/haxe/ds/StringMap.hx | 4 +- std/haxe/ds/Vector.hx | 134 +- std/haxe/ds/WeakMap.hx | 4 +- std/haxe/extern/AsVar.hx | 31 + std/haxe/extern/EitherType.hx | 14 +- std/haxe/extern/Rest.hx | 12 +- std/haxe/format/JsonParser.hx | 8 +- std/haxe/format/JsonPrinter.hx | 12 +- std/haxe/io/ArrayBufferView.hx | 23 +- std/haxe/io/BufferInput.hx | 2 +- std/haxe/io/Bytes.hx | 53 +- std/haxe/io/BytesBuffer.hx | 8 +- std/haxe/io/BytesData.hx | 30 +- std/haxe/io/BytesInput.hx | 12 +- std/haxe/io/BytesOutput.hx | 8 +- std/haxe/io/Eof.hx | 4 +- std/haxe/io/Error.hx | 2 +- std/haxe/io/FPHelper.hx | 23 +- std/haxe/io/Float32Array.hx | 2 +- std/haxe/io/Float64Array.hx | 2 +- std/haxe/io/Input.hx | 84 +- std/haxe/io/Int32Array.hx | 2 +- std/haxe/io/Output.hx | 16 +- std/haxe/io/Path.hx | 39 +- std/haxe/io/StringInput.hx | 2 +- std/haxe/io/UInt16Array.hx | 2 +- std/haxe/io/UInt32Array.hx | 2 +- std/haxe/io/UInt8Array.hx | 2 +- std/haxe/macro/CompilationServer.hx | 84 + std/haxe/macro/Compiler.hx | 203 +- std/haxe/macro/ComplexTypeTools.hx | 18 +- std/haxe/macro/Context.hl.hx | 243 + std/haxe/macro/Context.hx | 193 +- std/haxe/macro/ExampleJSGenerator.hx | 2 +- std/haxe/macro/Expr.hx | 616 +- std/haxe/macro/ExprTools.hx | 37 +- std/haxe/macro/Format.hx | 2 +- std/haxe/macro/JSGenApi.hx | 2 +- std/haxe/macro/MacroStringTools.hx | 19 +- std/haxe/macro/MacroType.hx | 2 +- std/haxe/macro/PositionTools.hx | 25 +- std/haxe/macro/Printer.hx | 48 +- std/haxe/macro/Tools.hx | 26 +- std/haxe/macro/Type.hx | 723 +- std/haxe/macro/TypeTools.hx | 43 +- std/haxe/macro/TypedExprTools.hx | 15 +- std/haxe/remoting/AMFConnection.hx | 5 +- std/haxe/remoting/AsyncAdapter.hx | 2 +- std/haxe/remoting/AsyncConnection.hx | 5 +- std/haxe/remoting/AsyncDebugConnection.hx | 2 +- std/haxe/remoting/AsyncProxy.hx | 2 +- std/haxe/remoting/Connection.hx | 2 +- std/haxe/remoting/Context.hx | 7 +- std/haxe/remoting/ContextAll.hx | 2 +- std/haxe/remoting/DelayedConnection.hx | 2 +- std/haxe/remoting/ExternalConnection.hx | 8 +- std/haxe/remoting/FlashJsConnection.hx | 2 +- std/haxe/remoting/HttpAsyncConnection.hx | 5 +- std/haxe/remoting/HttpConnection.hx | 9 +- std/haxe/remoting/LocalConnection.hx | 5 +- std/haxe/remoting/Proxy.hx | 6 +- std/haxe/remoting/SocketConnection.hx | 5 +- std/haxe/remoting/SocketProtocol.hx | 21 +- std/haxe/remoting/SocketWrapper.hx | 4 +- std/haxe/remoting/SyncSocketConnection.hx | 3 +- std/haxe/rtti/CType.hx | 276 +- std/haxe/rtti/Meta.hx | 46 +- std/haxe/rtti/Rtti.hx | 4 +- std/haxe/rtti/XmlParser.hx | 8 +- std/haxe/unit/TestCase.hx | 49 +- std/haxe/unit/TestResult.hx | 15 +- std/haxe/unit/TestRunner.hx | 49 +- std/haxe/unit/TestStatus.hx | 35 +- std/haxe/web/Dispatch.hx | 2 +- std/haxe/web/Request.hx | 6 +- std/haxe/xml/Check.hx | 2 +- std/haxe/xml/Fast.hx | 103 +- std/haxe/xml/Parser.hx | 101 +- std/haxe/xml/Printer.hx | 58 +- std/haxe/xml/Proxy.hx | 15 +- std/haxe/zip/Compress.hx | 2 +- std/haxe/zip/Entry.hx | 2 +- std/haxe/zip/FlushMode.hx | 2 +- std/haxe/zip/Huffman.hx | 2 +- std/haxe/zip/InflateImpl.hx | 2 +- std/haxe/zip/Reader.hx | 4 +- std/haxe/zip/Tools.hx | 2 +- std/haxe/zip/Uncompress.hx | 2 +- std/haxe/zip/Writer.hx | 2 +- std/hl/Abstract.hx | 25 + std/hl/Api.hx | 41 + std/hl/BaseType.hx | 67 + std/hl/Boot.hx | 29 + std/hl/Bytes.hx | 216 + std/hl/BytesAccess.hx | 51 + std/hl/F32.hx | 24 + std/hl/F64.hx | 24 + std/hl/Format.hx | 68 + std/hl/Gc.hx | 47 + std/hl/NativeArray.hx | 78 + std/hl/Ref.hx | 39 + std/hl/Type.hx | 112 + std/hl/UI.hx | 160 + std/hl/UI16.hx | 24 + std/hl/UI8.hx | 24 + std/hl/_std/Date.hx | 144 + std/hl/_std/EReg.hx | 200 + std/hl/_std/Math.hx | 65 + std/hl/_std/Reflect.hx | 143 + std/hl/_std/Std.hx | 120 + std/hl/_std/String.hx | 225 + std/hl/_std/StringBuf.hx | 94 + std/hl/_std/Sys.hx | 173 + std/hl/_std/Type.hx | 254 + std/hl/_std/UInt.hx | 190 + std/hl/_std/haxe/Resource.hx | 57 + .../_std/haxe/ds/IntMap.hx} | 57 +- std/hl/_std/haxe/ds/ObjectMap.hx | 74 + std/hl/_std/haxe/ds/StringMap.hx | 100 + std/hl/_std/haxe/ds/Vector.hx | 89 + std/hl/_std/haxe/io/Bytes.hx | 179 + std/hl/_std/haxe/io/BytesBuffer.hx | 106 + std/hl/_std/haxe/io/FPHelper.hx | 56 + std/hl/_std/haxe/zip/Compress.hx | 69 + std/hl/_std/haxe/zip/Uncompress.hx | 74 + std/hl/_std/sys/FileSystem.hx | 115 + std/hl/_std/sys/db/Sqlite.hx | 278 + std/hl/_std/sys/io/File.hx | 87 + std/hl/_std/sys/io/FileInput.hx | 73 + std/hl/_std/sys/io/FileOutput.hx | 68 + std/hl/_std/sys/io/Process.hx | 182 + std/hl/_std/sys/net/Host.hx | 54 + std/hl/_std/sys/net/Socket.hx | 270 + std/hl/_std/sys/ssl/Certificate.hx | 130 + std/hl/_std/sys/ssl/Digest.hx | 27 + std/hl/_std/sys/ssl/Key.hx | 36 + std/hl/_std/sys/ssl/Lib.hx | 10 + std/hl/_std/sys/ssl/Socket.hx | 251 + std/hl/types/ArrayBase.hx | 146 + std/hl/types/ArrayBytes.hx | 304 + std/hl/types/ArrayDyn.hx | 223 + std/hl/types/ArrayObj.hx | 288 + std/hl/types/BytesMap.hx | 69 + std/hl/types/IntMap.hx | 69 + std/hl/types/ObjectMap.hx | 69 + std/java/Boot.hx | 6 +- std/java/Lib.hx | 6 +- std/java/NativeArray.hx | 2 +- std/java/StdTypes.hx | 10 +- std/java/_std/Array.hx | 2 +- std/java/_std/Date.hx | 2 +- std/java/_std/EReg.hx | 2 +- std/java/_std/Math.hx | 2 +- std/java/_std/Reflect.hx | 7 +- std/java/_std/Std.hx | 4 +- std/java/_std/String.hx | 2 +- std/java/_std/StringBuf.hx | 2 +- std/java/_std/Sys.hx | 41 +- std/java/_std/Type.hx | 23 +- std/java/_std/haxe/Int64.hx | 15 +- std/java/_std/haxe/Resource.hx | 2 +- std/java/_std/haxe/ds/IntMap.hx | 2 +- std/java/_std/haxe/ds/ObjectMap.hx | 2 +- std/java/_std/haxe/ds/StringMap.hx | 2 +- std/java/_std/haxe/ds/WeakMap.hx | 2 +- std/java/_std/haxe/zip/Compress.hx | 2 +- std/java/_std/haxe/zip/Uncompress.hx | 2 +- std/java/_std/sys/FileSystem.hx | 2 +- std/java/_std/sys/db/Mysql.hx | 2 +- std/java/_std/sys/db/Sqlite.hx | 23 +- std/java/_std/sys/io/File.hx | 4 +- std/java/_std/sys/io/FileInput.hx | 2 +- std/java/_std/sys/io/FileOutput.hx | 2 +- std/java/_std/sys/io/Process.hx | 68 +- std/java/_std/sys/net/Host.hx | 4 +- std/java/_std/sys/net/Socket.hx | 7 +- std/java/db/Jdbc.hx | 23 +- std/java/internal/Exceptions.hx | 15 +- std/java/internal/FieldLookup.hx | 2 +- std/java/internal/Function.hx | 2 +- std/java/internal/HxObject.hx | 3 +- std/java/internal/IEquatable.hx | 2 +- std/java/internal/Iterator.hx | 6 +- std/java/internal/Runtime.hx | 29 +- std/java/internal/StringExt.hx | 4 +- std/java/io/NativeInput.hx | 2 +- std/java/io/NativeOutput.hx | 2 +- std/java/lang/Boolean.hx | 41 +- std/java/lang/Byte.hx | 39 +- std/java/lang/Character.hx | 206 +- std/java/lang/Double.hx | 56 +- std/java/lang/Float.hx | 56 +- std/java/lang/Integer.hx | 53 +- std/java/lang/Long.hx | 53 +- std/java/lang/Short.hx | 40 +- std/java/net/SslSocket.hx | 2 +- std/java/types/Char16.hx | 23 +- std/java/types/Int16.hx | 23 +- std/java/types/Int8.hx | 23 +- std/java/vm/AtomicList.hx | 23 +- std/java/vm/Deque.hx | 23 +- std/java/vm/Gc.hx | 23 +- std/java/vm/Lock.hx | 23 +- std/java/vm/Mutex.hx | 35 +- std/java/vm/Thread.hx | 23 +- std/java/vm/Tls.hx | 23 +- std/js/Boot.hx | 10 +- std/js/Browser.hx | 2 +- std/js/Cookie.hx | 10 +- std/js/Error.hx | 2 +- std/js/JQuery.hx | 9 +- std/js/Lib.hx | 17 +- std/js/Promise.hx | 8 +- std/js/RegExp.hx | 5 +- std/js/SWFObject.hx | 5 +- std/js/Selection.hx | 2 +- std/js/XMLSocket.hx | 5 +- std/js/_std/Array.hx | 4 +- std/js/_std/Date.hx | 32 +- std/js/_std/EReg.hx | 9 +- std/js/_std/HxOverrides.hx | 26 +- std/js/_std/Math.hx | 52 +- std/js/_std/Reflect.hx | 3 +- std/js/_std/Std.hx | 8 +- std/js/_std/String.hx | 2 +- std/js/_std/Type.hx | 25 +- std/js/_std/haxe/Json.hx | 2 +- std/js/_std/haxe/ds/IntMap.hx | 9 +- std/js/_std/haxe/ds/ObjectMap.hx | 7 +- std/js/_std/haxe/ds/StringMap.hx | 4 +- std/js/_std/haxe/io/ArrayBufferView.hx | 35 +- std/js/_std/haxe/io/Bytes.hx | 9 +- std/js/_std/haxe/io/Float32Array.hx | 6 +- std/js/_std/haxe/io/Float64Array.hx | 6 +- std/js/_std/haxe/io/Int32Array.hx | 4 +- std/js/_std/haxe/io/UInt16Array.hx | 4 +- std/js/_std/haxe/io/UInt32Array.hx | 4 +- std/js/_std/haxe/io/UInt8Array.hx | 4 +- std/js/html/AlignSetting.hx | 4 +- std/js/html/AnchorElement.hx | 60 +- std/js/html/Animation.hx | 101 +- std/js/html/AnimationEffectReadOnly.hx | 48 + std/js/html/AnimationEffectTiming.hx | 37 + ....hx => AnimationEffectTimingProperties.hx} | 23 +- std/js/html/AnimationEffectTimingReadOnly.hx | 78 + std/js/html/AnimationEvent.hx | 23 +- std/js/html/AnimationEventInit.hx | 4 +- std/js/html/AnimationPlayState.hx | 4 +- std/js/html/AnimationTimeline.hx | 15 +- std/js/html/AppletElement.hx | 4 +- std/js/html/ApplicationCache.hx | 4 +- std/js/html/AreaElement.hx | 44 +- std/js/html/ArrayBuffer.hx | 7 +- std/js/html/ArrayBufferView.hx | 11 +- std/js/html/Attr.hx | 11 +- std/js/html/Audio.hx | 4 +- std/js/html/AudioChannel.hx | 5 +- std/js/html/AudioContextState.hx | 32 + std/js/html/AudioElement.hx | 11 +- std/js/html/AudioStreamTrack.hx | 4 +- std/js/html/AudioTrack.hx | 4 +- std/js/html/AudioTrackList.hx | 4 +- std/js/html/BRElement.hx | 15 +- std/js/html/BarProp.hx | 4 +- std/js/html/BaseElement.hx | 19 +- std/js/html/BatteryManager.hx | 43 +- std/js/html/BeforeUnloadEvent.hx | 11 +- std/js/html/BinaryType.hx | 4 +- std/js/html/Blob.hx | 23 +- std/js/html/BlobPropertyBag.hx | 4 +- std/js/html/BodyElement.hx | 37 +- std/js/html/BroadcastChannel.hx | 61 + std/js/html/ButtonElement.hx | 72 +- std/js/html/CDATASection.hx | 11 +- std/js/html/CSS.hx | 12 +- ...ServiceWorkerClient.hx => CSSAnimation.hx} | 10 +- std/js/html/CSSCharsetRule.hx | 4 +- std/js/html/CSSFontFaceRule.hx | 4 +- std/js/html/CSSImportRule.hx | 4 +- std/js/html/CSSMediaRule.hx | 15 +- std/js/html/CSSPageRule.hx | 19 +- std/js/html/CSSPrimitiveValue.hx | 156 +- ...aEncryptedEvent.hx => CSSPseudoElement.hx} | 15 +- std/js/html/CSSRule.hx | 11 +- std/js/html/CSSRuleList.hx | 11 +- std/js/html/CSSStyleDeclaration.hx | 11 +- std/js/html/CSSStyleRule.hx | 11 +- std/js/html/CSSStyleSheet.hx | 11 +- std/js/html/CSSTransition.hx | 32 + std/js/html/CSSUnknownRule.hx | 4 +- std/js/html/CSSValue.hx | 44 +- std/js/html/CSSValueList.hx | 19 +- std/js/html/CanvasElement.hx | 31 +- std/js/html/CanvasGradient.hx | 15 +- std/js/html/CanvasPattern.hx | 15 +- std/js/html/CanvasRenderingContext2D.hx | 23 +- std/js/html/CanvasWindingRule.hx | 4 +- std/js/html/CaretPosition.hx | 19 +- std/js/html/CharacterData.hx | 39 +- std/js/html/ChromeFilePropertyBag.hx | 4 +- std/js/html/Client.hx | 59 + std/js/html/ClientQueryOptions.hx | 31 + std/js/html/Clients.hx | 52 + std/js/html/ClipboardEvent.hx | 15 +- std/js/html/ClipboardEventInit.hx | 4 +- std/js/html/CloseEvent.hx | 140 +- std/js/html/CloseEventInit.hx | 4 +- std/js/html/CommandEvent.hx | 4 +- std/js/html/Comment.hx | 11 +- std/js/html/CompositeOperation.hx | 32 + std/js/html/CompositionEvent.hx | 12 +- ...Options.hx => ComputedTimingProperties.hx} | 14 +- std/js/html/Console.hx | 102 +- std/js/html/ContentElement.hx | 19 +- std/js/html/ConvertCoordinateOptions.hx | 4 +- std/js/html/Coordinates.hx | 39 +- std/js/html/Crypto.hx | 15 +- std/js/html/CryptoKey.hx | 27 +- std/js/html/CustomEvent.hx | 21 +- std/js/html/CustomEventInit.hx | 4 +- std/js/html/DListElement.hx | 15 +- std/js/html/DOMApplicationCache.hx | 27 - std/js/html/DOMCoreException.hx | 27 - std/js/html/DOMCursor.hx | 4 +- std/js/html/DOMElement.hx | 48 +- std/js/html/DOMError.hx | 15 +- std/js/html/DOMException.hx | 14 +- std/js/html/DOMImplementation.hx | 27 +- std/js/html/DOMMatrix.hx | 55 +- std/js/html/DOMMatrixReadOnly.hx | 118 +- std/js/html/DOMMimeType.hx | 27 - std/js/html/DOMMimeTypeArray.hx | 27 - std/js/html/DOMParser.hx | 11 +- std/js/html/DOMPluginArray.hx | 27 - std/js/html/DOMPoint.hx | 11 +- std/js/html/DOMPointInit.hx | 4 +- std/js/html/DOMPointReadOnly.hx | 27 +- std/js/html/DOMQuad.hx | 4 +- std/js/html/DOMRect.hx | 11 +- std/js/html/DOMRectList.hx | 4 +- std/js/html/DOMRectReadOnly.hx | 43 +- std/js/html/DOMRequest.hx | 7 +- std/js/html/DOMRequestReadyState.hx | 4 +- std/js/html/DOMSelection.hx | 27 - std/js/html/DOMStringList.hx | 23 +- std/js/html/DOMStringMap.hx | 11 +- std/js/html/DOMTokenList.hx | 36 +- std/js/html/DOMTransaction.hx | 4 +- std/js/html/DOMTransactionEvent.hx | 4 +- std/js/html/DOMTransactionEventInit.hx | 4 +- std/js/html/DataElement.hx | 15 +- std/js/html/DataListElement.hx | 15 +- std/js/html/DataTransfer.hx | 47 +- std/js/html/DataView.hx | 23 +- std/js/html/DedicatedWorkerGlobalScope.hx | 15 +- std/js/html/DesktopNotification.hx | 4 +- std/js/html/DesktopNotificationCenter.hx | 4 +- std/js/html/DeviceAcceleration.hx | 23 +- std/js/html/DeviceAccelerationInit.hx | 4 +- std/js/html/DeviceMotionEvent.hx | 28 +- std/js/html/DeviceMotionEventInit.hx | 4 +- std/js/html/DeviceOrientationEvent.hx | 28 +- std/js/html/DeviceOrientationEventInit.hx | 4 +- std/js/html/DeviceRotationRate.hx | 11 +- std/js/html/DeviceRotationRateInit.hx | 4 +- std/js/html/DirectionSetting.hx | 4 +- std/js/html/Directory.hx | 11 +- std/js/html/DirectoryElement.hx | 4 +- std/js/html/DivElement.hx | 15 +- std/js/html/Document.hx | 295 +- std/js/html/DocumentFragment.hx | 23 +- std/js/html/DocumentTimeline.hx | 37 + std/js/html/DocumentType.hx | 24 +- std/js/html/DragEvent.hx | 12 +- .../{ClientRectList.hx => DragEventInit.hx} | 12 +- std/js/html/DummyInterface.hx | 5 +- std/js/html/DummyInterfaceWorkers.hx | 4 +- std/js/html/Element.hx | 11 +- std/js/html/ElementRegistrationOptions.hx | 4 +- std/js/html/EmbedElement.hx | 35 +- std/js/html/ErrorEvent.hx | 31 +- std/js/html/ErrorEventInit.hx | 4 +- std/js/html/Event.hx | 76 +- std/js/html/EventInit.hx | 4 +- std/js/html/EventListener.hx | 11 +- std/js/html/EventModifierInit.hx | 43 + std/js/html/EventSource.hx | 35 +- std/js/html/EventSourceInit.hx | 4 +- std/js/html/EventTarget.hx | 23 +- std/js/html/Exception.hx | 5 +- std/js/html/ExtendableEvent.hx | 41 + .../{DOMURL.hx => ExtendableEventInit.hx} | 11 +- std/js/html/ExtendableMessageEvent.hx | 65 + std/js/html/ExtendableMessageEventInit.hx | 35 + std/js/html/External.hx | 4 +- std/js/html/FetchEvent.hx | 61 + ...eyNeededEventInit.hx => FetchEventInit.hx} | 11 +- std/js/html/FieldSetElement.hx | 11 +- std/js/html/File.hx | 23 +- std/js/html/FileList.hx | 11 +- std/js/html/FileMode.hx | 4 +- std/js/html/FilePropertyBag.hx | 4 +- std/js/html/FileReader.hx | 87 +- std/js/html/FileReaderSync.hx | 11 +- std/js/html/FillMode.hx | 34 + std/js/html/Float32Array.hx | 11 +- std/js/html/Float64Array.hx | 11 +- std/js/html/FocusEvent.hx | 15 +- std/js/html/FocusEventInit.hx | 4 +- std/js/html/FontElement.hx | 4 +- std/js/html/FontFace.hx | 51 +- std/js/html/FontFaceDescriptors.hx | 5 +- std/js/html/FontFaceLoadStatus.hx | 4 +- std/js/html/FontFaceSet.hx | 37 +- std/js/html/FontFaceSetIterator.hx | 32 + ...ptions.hx => FontFaceSetIteratorResult.hx} | 9 +- std/js/html/FontFaceSetLoadStatus.hx | 4 +- std/js/html/FormData.hx | 60 +- std/js/html/FormDataIterator.hx | 32 + std/js/html/FormElement.hx | 15 +- std/js/html/FrameElement.hx | 4 +- std/js/html/FrameSetElement.hx | 21 +- .../html/{MediaWaitingFor.hx => FrameType.hx} | 11 +- std/js/html/Gamepad.hx | 39 +- std/js/html/GamepadButton.hx | 19 +- std/js/html/GamepadMappingType.hx | 4 +- std/js/html/Geolocation.hx | 23 +- std/js/html/GetUserMediaRequest.hx | 4 +- std/js/html/HRElement.hx | 11 +- std/js/html/HTMLAllCollection.hx | 4 +- std/js/html/HTMLCollection.hx | 23 +- std/js/html/HTMLDocument.hx | 11 +- std/js/html/HTMLFormControlsCollection.hx | 11 +- std/js/html/HTMLOptionsCollection.hx | 11 +- std/js/html/HTMLPropertiesCollection.hx | 4 +- std/js/html/HashChangeEvent.hx | 12 +- std/js/html/HashChangeEventInit.hx | 4 +- std/js/html/HeadElement.hx | 11 +- std/js/html/Headers.hx | 92 + .../{SessionType.hx => HeadersIterator.hx} | 11 +- std/js/html/HeadingElement.hx | 15 +- std/js/html/History.hx | 50 +- std/js/html/HitRegionOptions.hx | 5 +- std/js/html/HtmlElement.hx | 15 +- std/js/html/IFrameElement.hx | 69 +- std/js/html/Image.hx | 4 +- std/js/html/ImageBitmap.hx | 55 + std/js/html/ImageBitmapRenderingContext.hx | 44 + std/js/html/ImageCapture.hx | 4 +- std/js/html/ImageData.hx | 23 +- std/js/html/ImageElement.hx | 95 +- std/js/html/InputElement.hx | 41 +- std/js/html/InputEvent.hx | 15 +- std/js/html/InputEventInit.hx | 4 +- std/js/html/Int16Array.hx | 8 +- std/js/html/Int32Array.hx | 8 +- std/js/html/Int8Array.hx | 8 +- std/js/html/IterationCompositeOperation.hx | 31 + std/js/html/KeyEvent.hx | 5 +- std/js/html/KeyboardEvent.hx | 66 +- std/js/html/KeyboardEventInit.hx | 10 +- std/js/html/KeyframeEffect.hx | 39 + std/js/html/KeyframeEffectReadOnly.hx | 62 + std/js/html/LIElement.hx | 19 +- std/js/html/LabelElement.hx | 23 +- std/js/html/LegendElement.hx | 11 +- std/js/html/LifecycleCallbacks.hx | 4 +- std/js/html/LinkElement.hx | 62 +- std/js/html/LocalMediaStream.hx | 15 +- std/js/html/Location.hx | 61 +- std/js/html/MapElement.hx | 19 +- std/js/html/MediaElement.hx | 152 +- std/js/html/MediaError.hx | 47 +- std/js/html/MediaKeyMessageEventInit.hx | 32 - std/js/html/MediaKeyMessageType.hx | 32 - std/js/html/MediaKeySession.hx | 42 - std/js/html/MediaKeyStatusMapIterator.hx | 32 + std/js/html/MediaKeySystemAccess.hx | 33 - std/js/html/MediaKeySystemOptions.hx | 36 - std/js/html/MediaList.hx | 4 +- std/js/html/MediaQueryList.hx | 11 +- std/js/html/MediaRecorder.hx | 48 +- std/js/html/MediaRecorderOptions.hx | 7 +- std/js/html/MediaSource.hx | 45 +- std/js/html/MediaSourceEndOfStreamError.hx | 4 +- std/js/html/MediaSourceReadyState.hx | 4 +- std/js/html/MediaStream.hx | 38 +- std/js/html/MediaStreamConstraints.hx | 15 +- std/js/html/MediaStreamError.hx | 6 +- std/js/html/MediaStreamTrack.hx | 31 +- std/js/html/MediaTrackConstraintSet.hx | 42 + std/js/html/MediaTrackConstraints.hx | 38 + std/js/html/MenuElement.hx | 4 +- std/js/html/MenuItemElement.hx | 4 +- std/js/html/MessageChannel.hx | 50 + std/js/html/MessageEvent.hx | 32 +- std/js/html/MessageEventInit.hx | 4 +- std/js/html/MessagePort.hx | 11 +- std/js/html/MessagePortList.hx | 4 +- std/js/html/MetaElement.hx | 11 +- std/js/html/MeterElement.hx | 11 +- std/js/html/MimeType.hx | 4 +- std/js/html/MimeTypeArray.hx | 4 +- std/js/html/ModElement.hx | 15 +- std/js/html/MouseEvent.hx | 91 +- std/js/html/MouseEventInit.hx | 12 +- std/js/html/MouseScrollEvent.hx | 12 +- std/js/html/MutationEvent.hx | 11 +- std/js/html/MutationObserver.hx | 11 +- std/js/html/MutationObserverInit.hx | 6 +- std/js/html/MutationRecord.hx | 11 +- std/js/html/NamedNodeMap.hx | 43 +- std/js/html/Navigator.hx | 54 +- std/js/html/Node.hx | 194 +- std/js/html/NodeFilter.hx | 36 +- std/js/html/NodeIterator.hx | 118 +- std/js/html/NodeList.hx | 19 +- std/js/html/Notification.hx | 69 +- std/js/html/NotificationDirection.hx | 4 +- ...eWorkerClients.hx => NotificationEvent.hx} | 14 +- std/js/html/NotificationEventInit.hx | 31 + std/js/html/NotificationOptions.hx | 4 +- std/js/html/NotificationPermission.hx | 4 +- std/js/html/NotifyPaintEvent.hx | 4 +- std/js/html/OListElement.hx | 35 +- std/js/html/ObjectElement.hx | 111 +- std/js/html/ObjectURLOptions.hx | 4 +- std/js/html/OptGroupElement.hx | 19 +- std/js/html/OptionElement.hx | 11 +- std/js/html/OrientationLockType.hx | 37 + std/js/html/OrientationType.hx | 33 + std/js/html/OutputElement.hx | 13 +- std/js/html/PageTransitionEvent.hx | 11 +- std/js/html/PageTransitionEventInit.hx | 4 +- std/js/html/PaintRequest.hx | 4 +- std/js/html/PaintRequestList.hx | 4 +- std/js/html/ParagraphElement.hx | 11 +- std/js/html/ParamElement.hx | 27 +- std/js/html/Path2D.hx | 17 +- std/js/html/Performance.hx | 23 +- std/js/html/PerformanceEntry.hx | 27 +- std/js/html/PerformanceMark.hx | 37 + std/js/html/PerformanceMeasure.hx | 37 + std/js/html/PerformanceNavigation.hx | 51 +- std/js/html/PerformanceResourceTiming.hx | 15 +- std/js/html/PerformanceTiming.hx | 91 +- .../{MediaKeyError.hx => PermissionState.hx} | 12 +- std/js/html/PermissionStatus.hx | 48 + std/js/html/Permissions.hx | 47 + std/js/html/PictureElement.hx | 11 +- std/js/html/PlaybackDirection.hx | 33 + std/js/html/Plugin.hx | 11 +- std/js/html/PluginArray.hx | 11 +- std/js/html/PointerEvent.hx | 11 +- std/js/html/PointerEventInit.hx | 4 +- std/js/html/PopStateEvent.hx | 11 +- std/js/html/PopStateEventInit.hx | 4 +- std/js/html/PopupBlockedEvent.hx | 4 +- std/js/html/PopupBlockedEventInit.hx | 4 +- std/js/html/Position.hx | 19 +- std/js/html/PositionError.hx | 44 +- std/js/html/PositionOptions.hx | 29 +- std/js/html/PreElement.hx | 15 +- std/js/html/ProcessingInstruction.hx | 11 +- std/js/html/ProgressElement.hx | 23 +- std/js/html/ProgressEvent.hx | 23 +- std/js/html/ProgressEventInit.hx | 4 +- std/js/html/PropertyNodeList.hx | 4 +- std/js/html/QuoteElement.hx | 15 +- std/js/html/RGBColor.hx | 4 +- std/js/html/RadioNodeList.hx | 15 +- std/js/html/Range.hx | 35 +- std/js/html/RecordErrorEvent.hx | 4 +- std/js/html/RecordErrorEventInit.hx | 4 +- std/js/html/RecordingState.hx | 4 +- std/js/html/Rect.hx | 4 +- std/js/html/ReferrerPolicy.hx | 35 + std/js/html/Request.hx | 102 + std/js/html/RequestCache.hx | 34 + std/js/html/RequestCredentials.hx | 32 + std/js/html/RequestInit.hx | 38 + std/js/html/RequestMode.hx | 33 + ...{AnimationEffect.hx => RequestRedirect.hx} | 12 +- std/js/html/Response.hx | 98 + std/js/html/ResponseInit.hx | 32 + std/js/html/ResponseType.hx | 35 + std/js/html/Screen.hx | 12 +- ...eyMessageEvent.hx => ScreenOrientation.hx} | 17 +- std/js/html/ScriptElement.hx | 12 +- std/js/html/ScrollAreaEvent.hx | 5 +- std/js/html/ScrollIntoViewOptions.hx | 4 +- std/js/html/ScrollOptions.hx | 4 +- .../{CSSMatrix.hx => ScrollRestoration.hx} | 12 +- std/js/html/ScrollToOptions.hx | 4 +- std/js/html/SelectElement.hx | 95 +- std/js/html/Selection.hx | 84 +- std/js/html/SelectionMode.hx | 4 +- std/js/html/ServiceWorker.hx | 56 + std/js/html/ServiceWorkerGlobalScope.hx | 63 +- std/js/html/ServiceWorkerRegistration.hx | 75 + std/js/html/ServiceWorkerState.hx | 41 + std/js/html/ShadowElement.hx | 11 +- std/js/html/ShadowRoot.hx | 19 +- std/js/html/SharedWorker.hx | 15 +- std/js/html/SharedWorkerGlobalScope.hx | 19 +- std/js/html/SimpleGestureEvent.hx | 5 +- std/js/html/SourceBuffer.hx | 47 +- std/js/html/SourceBufferAppendMode.hx | 4 +- std/js/html/SourceBufferList.hx | 15 +- std/js/html/SourceElement.hx | 31 +- std/js/html/SpanElement.hx | 11 +- std/js/html/SpeechGrammar.hx | 19 +- std/js/html/SpeechGrammarList.hx | 27 +- std/js/html/SpeechInputEvent.hx | 27 - std/js/html/SpeechInputResult.hx | 27 - std/js/html/SpeechInputResultList.hx | 27 - std/js/html/SpeechRecognition.hx | 91 +- std/js/html/SpeechRecognitionAlternative.hx | 19 +- std/js/html/SpeechRecognitionError.hx | 19 +- std/js/html/SpeechRecognitionErrorCode.hx | 4 +- std/js/html/SpeechRecognitionErrorInit.hx | 4 +- std/js/html/SpeechRecognitionEvent.hx | 31 +- std/js/html/SpeechRecognitionEventInit.hx | 8 +- std/js/html/SpeechRecognitionResult.hx | 22 +- std/js/html/SpeechRecognitionResultList.hx | 15 +- std/js/html/SpeechSynthesis.hx | 43 +- std/js/html/SpeechSynthesisErrorCode.hx | 40 + std/js/html/SpeechSynthesisErrorEvent.hx | 45 + std/js/html/SpeechSynthesisErrorEventInit.hx | 31 + std/js/html/SpeechSynthesisEvent.hx | 30 +- std/js/html/SpeechSynthesisEventInit.hx | 5 +- std/js/html/SpeechSynthesisUtterance.hx | 63 +- std/js/html/SpeechSynthesisVoice.hx | 27 +- std/js/html/Storage.hx | 35 +- std/js/html/StorageEvent.hx | 12 +- std/js/html/StorageEventInit.hx | 4 +- std/js/html/StyleElement.hx | 27 +- std/js/html/StyleSheet.hx | 39 +- std/js/html/StyleSheetList.hx | 11 +- std/js/html/SubtleCrypto.hx | 59 +- std/js/html/SupportedType.hx | 4 +- std/js/html/TableCaptionElement.hx | 15 +- std/js/html/TableCellElement.hx | 63 +- std/js/html/TableColElement.hx | 11 +- std/js/html/TableElement.hx | 99 +- std/js/html/TableRowElement.hx | 51 +- std/js/html/TableSectionElement.hx | 39 +- std/js/html/TemplateElement.hx | 4 +- std/js/html/Text.hx | 15 +- std/js/html/TextAreaElement.hx | 11 +- std/js/html/TextDecodeOptions.hx | 4 +- std/js/html/TextDecoder.hx | 23 +- std/js/html/TextDecoderOptions.hx | 4 +- std/js/html/TextEncoder.hx | 19 +- std/js/html/TextMetrics.hx | 15 +- std/js/html/TextTrack.hx | 5 +- std/js/html/TextTrackCue.hx | 19 +- std/js/html/TextTrackCueList.hx | 4 +- std/js/html/TextTrackKind.hx | 4 +- std/js/html/TextTrackList.hx | 4 +- std/js/html/TextTrackMode.hx | 4 +- std/js/html/TimeElement.hx | 15 +- std/js/html/TimeEvent.hx | 11 +- std/js/html/TimeRanges.hx | 23 +- std/js/html/TitleElement.hx | 15 +- std/js/html/Touch.hx | 13 +- std/js/html/TouchEvent.hx | 12 +- std/js/html/TouchEventInit.hx | 33 + std/js/html/TouchInit.hx | 41 + std/js/html/TouchList.hx | 23 +- std/js/html/TrackElement.hx | 65 +- std/js/html/TrackEvent.hx | 4 +- std/js/html/TrackEventInit.hx | 4 +- std/js/html/TransitionEvent.hx | 23 +- std/js/html/TransitionEventInit.hx | 4 +- std/js/html/TreeWalker.hx | 130 +- std/js/html/UIEvent.hx | 51 +- std/js/html/UIEventInit.hx | 4 +- std/js/html/UListElement.hx | 19 +- std/js/html/URL.hx | 64 +- std/js/html/URLSearchParams.hx | 51 +- ...okenList.hx => URLSearchParamsIterator.hx} | 12 +- std/js/html/Uint16Array.hx | 8 +- std/js/html/Uint32Array.hx | 8 +- std/js/html/Uint8Array.hx | 11 +- std/js/html/Uint8ClampedArray.hx | 8 +- std/js/html/UncaughtRejectionObserver.hx | 32 + std/js/html/UnknownElement.hx | 11 +- std/js/html/VTTCue.hx | 13 +- std/js/html/VTTRegion.hx | 4 +- std/js/html/ValidityState.hx | 51 +- std/js/html/VideoElement.hx | 35 +- std/js/html/VideoPlaybackQuality.hx | 27 +- std/js/html/VideoStreamTrack.hx | 4 +- std/js/html/VideoTrack.hx | 4 +- std/js/html/VideoTrackList.hx | 4 +- std/js/html/VisibilityState.hx | 4 +- std/js/html/WebSocket.hx | 11 +- std/js/html/WheelEvent.hx | 52 +- std/js/html/WheelEventInit.hx | 4 +- std/js/html/Window.hx | 327 +- std/js/html/WindowClient.hx | 54 + std/js/html/Worker.hx | 23 +- ...iaKeys.hx => WorkerDebuggerGlobalScope.hx} | 23 +- std/js/html/WorkerGlobalScope.hx | 68 +- std/js/html/WorkerLocation.hx | 13 +- std/js/html/WorkerNavigator.hx | 12 +- std/js/html/XMLDocument.hx | 15 +- std/js/html/XMLHttpRequest.hx | 45 +- std/js/html/XMLHttpRequestEventTarget.hx | 11 +- std/js/html/XMLHttpRequestResponseType.hx | 4 +- std/js/html/XMLHttpRequestUpload.hx | 4 +- std/js/html/XMLSerializer.hx | 4 +- .../XMLStylesheetProcessingInstruction.hx | 4 +- std/js/html/XPathEvaluator.hx | 4 +- std/js/html/XPathExpression.hx | 11 +- std/js/html/XPathNSResolver.hx | 4 +- std/js/html/XPathResult.hx | 40 +- std/js/html/XSLTProcessor.hx | 11 +- std/js/html/audio/AnalyserNode.hx | 47 +- std/js/html/audio/AudioBuffer.hx | 39 +- std/js/html/audio/AudioBufferSourceNode.hx | 48 +- std/js/html/audio/AudioContext.hx | 146 +- std/js/html/audio/AudioDestinationNode.hx | 15 +- std/js/html/audio/AudioListener.hx | 19 +- std/js/html/audio/AudioNode.hx | 47 +- std/js/html/audio/AudioParam.hx | 43 +- std/js/html/audio/AudioProcessingEvent.hx | 11 +- std/js/html/audio/BiquadFilterNode.hx | 107 +- std/js/html/audio/BiquadFilterType.hx | 4 +- std/js/html/audio/ChannelCountMode.hx | 4 +- std/js/html/audio/ChannelInterpretation.hx | 4 +- std/js/html/audio/ChannelMergerNode.hx | 4 +- std/js/html/audio/ChannelSplitterNode.hx | 4 +- std/js/html/audio/ConvolverNode.hx | 19 +- std/js/html/audio/DelayNode.hx | 13 +- std/js/html/audio/DistanceModelType.hx | 4 +- std/js/html/audio/DynamicsCompressorNode.hx | 37 +- std/js/html/audio/GainNode.hx | 15 +- .../html/audio/MediaElementAudioSourceNode.hx | 11 +- .../audio/MediaStreamAudioDestinationNode.hx | 15 +- .../html/audio/MediaStreamAudioSourceNode.hx | 11 +- .../html/audio/OfflineAudioCompletionEvent.hx | 11 +- std/js/html/audio/OfflineAudioContext.hx | 19 +- std/js/html/audio/OscillatorNode.hx | 35 +- std/js/html/audio/OscillatorType.hx | 4 +- std/js/html/audio/OverSampleType.hx | 4 +- std/js/html/audio/PannerNode.hx | 55 +- std/js/html/audio/PanningModelType.hx | 4 +- std/js/html/audio/PeriodicWave.hx | 11 +- std/js/html/audio/ScriptProcessorNode.hx | 17 +- std/js/html/audio/StereoPannerNode.hx | 15 +- std/js/html/audio/WaveShaperNode.hx | 19 +- std/js/html/compat/ArrayBuffer.hx | 22 +- std/js/html/compat/DataView.hx | 16 +- std/js/html/compat/Float32Array.hx | 24 +- std/js/html/compat/Float64Array.hx | 22 +- std/js/html/compat/Uint8Array.hx | 22 +- std/js/html/idb/Cursor.hx | 35 +- std/js/html/idb/CursorDirection.hx | 4 +- std/js/html/idb/CursorWithValue.hx | 13 +- std/js/html/idb/Database.hx | 56 +- std/js/html/idb/Factory.hx | 11 +- std/js/html/idb/FileHandle.hx | 12 +- std/js/html/idb/FileMetadataParameters.hx | 4 +- std/js/html/idb/FileRequest.hx | 4 +- std/js/html/idb/Index.hx | 63 +- std/js/html/idb/IndexParameters.hx | 5 +- std/js/html/idb/KeyRange.hx | 57 +- std/js/html/idb/MutableFile.hx | 11 +- std/js/html/idb/ObjectStore.hx | 85 +- std/js/html/idb/ObjectStoreParameters.hx | 4 +- std/js/html/idb/OpenDBOptions.hx | 4 +- std/js/html/idb/OpenDBRequest.hx | 19 +- std/js/html/idb/Request.hx | 41 +- std/js/html/idb/RequestReadyState.hx | 4 +- std/js/html/idb/Transaction.hx | 39 +- std/js/html/idb/TransactionMode.hx | 6 +- std/js/html/idb/VersionChangeEvent.hx | 11 +- std/js/html/idb/VersionChangeEventInit.hx | 4 +- .../{ClientRect.hx => rtc/AnswerOptions.hx} | 13 +- std/js/html/rtc/Certificate.hx | 43 + std/js/html/rtc/Configuration.hx | 7 +- std/js/html/rtc/DataChannel.hx | 6 +- std/js/html/rtc/DataChannelInit.hx | 4 +- std/js/html/rtc/DataChannelState.hx | 4 +- std/js/html/rtc/DataChannelType.hx | 4 +- std/js/html/rtc/IceCandidate.hx | 23 +- std/js/html/rtc/IceCandidateInit.hx | 4 +- std/js/html/rtc/IceConnectionState.hx | 4 +- std/js/html/rtc/IceGatheringState.hx | 4 +- std/js/html/rtc/IdentityAssertion.hx | 14 +- std/js/html/rtc/IdentityAssertionResult.hx | 31 + std/js/html/rtc/IdentityProvider.hx | 32 + std/js/html/rtc/IdentityProviderRegistrar.hx | 31 + .../IdentityValidationResult.hx} | 11 +- std/js/html/rtc/OfferAnswerOptions.hx | 29 + std/js/html/rtc/OfferOptions.hx | 5 +- std/js/html/rtc/PeerConnection.hx | 29 +- std/js/html/rtc/RtpParameters.hx | 33 + std/js/html/rtc/RtpReceiver.hx | 4 +- std/js/html/rtc/RtpSender.hx | 6 +- std/js/html/rtc/SdpType.hx | 5 +- std/js/html/rtc/SessionDescription.hx | 19 +- std/js/html/rtc/SessionDescriptionInit.hx | 4 +- std/js/html/rtc/SignalingState.hx | 4 +- std/js/html/rtc/StatsReport.hx | 11 +- std/js/html/svg/AElement.hx | 15 +- std/js/html/svg/AltGlyphElement.hx | 19 +- std/js/html/svg/Angle.hx | 39 +- std/js/html/svg/AnimateElement.hx | 11 +- std/js/html/svg/AnimateMotionElement.hx | 11 +- std/js/html/svg/AnimateTransformElement.hx | 11 +- std/js/html/svg/AnimatedAngle.hx | 11 +- std/js/html/svg/AnimatedBoolean.hx | 11 +- std/js/html/svg/AnimatedEnumeration.hx | 11 +- std/js/html/svg/AnimatedInteger.hx | 11 +- std/js/html/svg/AnimatedLength.hx | 11 +- std/js/html/svg/AnimatedLengthList.hx | 11 +- std/js/html/svg/AnimatedNumber.hx | 11 +- std/js/html/svg/AnimatedNumberList.hx | 11 +- .../html/svg/AnimatedPreserveAspectRatio.hx | 11 +- std/js/html/svg/AnimatedRect.hx | 11 +- std/js/html/svg/AnimatedString.hx | 19 +- std/js/html/svg/AnimatedTransformList.hx | 11 +- std/js/html/svg/AnimationElement.hx | 11 +- std/js/html/svg/BoundingBoxOptions.hx | 4 +- std/js/html/svg/CircleElement.hx | 11 +- std/js/html/svg/ClipPathElement.hx | 11 +- .../svg/ComponentTransferFunctionElement.hx | 4 +- std/js/html/svg/DefsElement.hx | 11 +- std/js/html/svg/DescElement.hx | 11 +- std/js/html/svg/Document.hx | 4 +- std/js/html/svg/Element.hx | 11 +- std/js/html/svg/EllipseElement.hx | 11 +- std/js/html/svg/FEBlendElement.hx | 4 +- std/js/html/svg/FEColorMatrixElement.hx | 4 +- std/js/html/svg/FEComponentTransferElement.hx | 4 +- std/js/html/svg/FECompositeElement.hx | 4 +- std/js/html/svg/FEConvolveMatrixElement.hx | 4 +- std/js/html/svg/FEDiffuseLightingElement.hx | 4 +- std/js/html/svg/FEDisplacementMapElement.hx | 4 +- std/js/html/svg/FEDistantLightElement.hx | 4 +- std/js/html/svg/FEDropShadowElement.hx | 4 +- std/js/html/svg/FEFloodElement.hx | 4 +- std/js/html/svg/FEFuncAElement.hx | 4 +- std/js/html/svg/FEFuncBElement.hx | 4 +- std/js/html/svg/FEFuncGElement.hx | 4 +- std/js/html/svg/FEFuncRElement.hx | 4 +- std/js/html/svg/FEGaussianBlurElement.hx | 4 +- std/js/html/svg/FEImageElement.hx | 4 +- std/js/html/svg/FEMergeElement.hx | 4 +- std/js/html/svg/FEMergeNodeElement.hx | 4 +- std/js/html/svg/FEMorphologyElement.hx | 4 +- std/js/html/svg/FEOffsetElement.hx | 4 +- std/js/html/svg/FEPointLightElement.hx | 4 +- std/js/html/svg/FESpecularLightingElement.hx | 4 +- std/js/html/svg/FESpotLightElement.hx | 4 +- std/js/html/svg/FETileElement.hx | 4 +- std/js/html/svg/FETurbulenceElement.hx | 4 +- std/js/html/svg/FilterElement.hx | 11 +- std/js/html/svg/ForeignObjectElement.hx | 11 +- std/js/html/svg/GElement.hx | 11 +- std/js/html/svg/GradientElement.hx | 11 +- std/js/html/svg/GraphicsElement.hx | 4 +- std/js/html/svg/IFrameElement.hx | 42 - std/js/html/svg/ImageElement.hx | 11 +- std/js/html/svg/Length.hx | 11 +- std/js/html/svg/LengthList.hx | 11 +- std/js/html/svg/LineElement.hx | 11 +- std/js/html/svg/LinearGradientElement.hx | 11 +- std/js/html/svg/MPathElement.hx | 11 +- std/js/html/svg/MarkerElement.hx | 4 +- std/js/html/svg/MaskElement.hx | 11 +- std/js/html/svg/Matrix.hx | 11 +- std/js/html/svg/MetadataElement.hx | 4 +- std/js/html/svg/Number.hx | 11 +- std/js/html/svg/NumberList.hx | 11 +- std/js/html/svg/PathElement.hx | 11 +- std/js/html/svg/PathSeg.hx | 4 +- std/js/html/svg/PathSegArcAbs.hx | 4 +- std/js/html/svg/PathSegArcRel.hx | 4 +- std/js/html/svg/PathSegClosePath.hx | 4 +- std/js/html/svg/PathSegCurvetoCubicAbs.hx | 4 +- std/js/html/svg/PathSegCurvetoCubicRel.hx | 4 +- .../html/svg/PathSegCurvetoCubicSmoothAbs.hx | 4 +- .../html/svg/PathSegCurvetoCubicSmoothRel.hx | 4 +- std/js/html/svg/PathSegCurvetoQuadraticAbs.hx | 4 +- std/js/html/svg/PathSegCurvetoQuadraticRel.hx | 4 +- .../svg/PathSegCurvetoQuadraticSmoothAbs.hx | 4 +- .../svg/PathSegCurvetoQuadraticSmoothRel.hx | 4 +- std/js/html/svg/PathSegLinetoAbs.hx | 4 +- std/js/html/svg/PathSegLinetoHorizontalAbs.hx | 4 +- std/js/html/svg/PathSegLinetoHorizontalRel.hx | 4 +- std/js/html/svg/PathSegLinetoRel.hx | 4 +- std/js/html/svg/PathSegLinetoVerticalAbs.hx | 4 +- std/js/html/svg/PathSegLinetoVerticalRel.hx | 4 +- std/js/html/svg/PathSegList.hx | 4 +- std/js/html/svg/PathSegMovetoAbs.hx | 4 +- std/js/html/svg/PathSegMovetoRel.hx | 4 +- std/js/html/svg/PatternElement.hx | 11 +- std/js/html/svg/Point.hx | 11 +- std/js/html/svg/PointList.hx | 4 +- std/js/html/svg/PolygonElement.hx | 11 +- std/js/html/svg/PolylineElement.hx | 11 +- std/js/html/svg/PreserveAspectRatio.hx | 11 +- std/js/html/svg/RadialGradientElement.hx | 11 +- std/js/html/svg/Rect.hx | 11 +- std/js/html/svg/RectElement.hx | 11 +- std/js/html/svg/SVGElement.hx | 12 +- std/js/html/svg/ScriptElement.hx | 11 +- std/js/html/svg/SetElement.hx | 11 +- std/js/html/svg/StopElement.hx | 11 +- std/js/html/svg/StringList.hx | 11 +- std/js/html/svg/StyleElement.hx | 12 +- std/js/html/svg/SwitchElement.hx | 11 +- std/js/html/svg/SymbolElement.hx | 11 +- std/js/html/svg/TSpanElement.hx | 11 +- std/js/html/svg/TextContentElement.hx | 4 +- std/js/html/svg/TextElement.hx | 11 +- std/js/html/svg/TextPathElement.hx | 4 +- std/js/html/svg/TextPositioningElement.hx | 11 +- std/js/html/svg/TitleElement.hx | 11 +- std/js/html/svg/Transform.hx | 11 +- std/js/html/svg/TransformList.hx | 11 +- std/js/html/svg/UnitTypes.hx | 4 +- std/js/html/svg/UseElement.hx | 11 +- std/js/html/svg/ViewElement.hx | 11 +- std/js/html/svg/ZoomAndPan.hx | 4 +- std/js/html/svg/ZoomEvent.hx | 4 +- std/js/html/webgl/ActiveInfo.hx | 23 +- std/js/html/webgl/Buffer.hx | 11 +- std/js/html/webgl/ContextAttributes.hx | 5 +- std/js/html/webgl/ContextEvent.hx | 15 +- std/js/html/webgl/ContextEventInit.hx | 4 +- std/js/html/webgl/DebugRendererInfo.hx | 27 - std/js/html/webgl/DebugShaders.hx | 27 - std/js/html/webgl/DepthTexture.hx | 27 - .../html/webgl/EXTTextureFilterAnisotropic.hx | 27 - std/js/html/webgl/ExtensionBlendMinMax.hx | 13 +- .../html/webgl/ExtensionColorBufferFloat.hx | 13 +- .../webgl/ExtensionColorBufferHalfFloat.hx | 13 +- .../webgl/ExtensionCompressedTextureATC.hx | 13 +- .../webgl/ExtensionCompressedTextureES3.hx | 48 + .../webgl/ExtensionCompressedTextureETC1.hx | 13 +- .../webgl/ExtensionCompressedTexturePVRTC.hx | 13 +- .../webgl/ExtensionCompressedTextureS3TC.hx | 13 +- .../html/webgl/ExtensionDebugRendererInfo.hx | 13 +- std/js/html/webgl/ExtensionDebugShaders.hx | 17 +- std/js/html/webgl/ExtensionDepthTexture.hx | 13 +- .../html/webgl/ExtensionDisjointTimerQuery.hx | 93 + std/js/html/webgl/ExtensionDrawBuffers.hx | 19 +- .../html/webgl/ExtensionElementIndexUint.hx | 13 +- std/js/html/webgl/ExtensionFragDepth.hx | 13 +- std/js/html/webgl/ExtensionInstancedArrays.hx | 31 +- std/js/html/webgl/ExtensionLoseContext.hx | 21 +- std/js/html/webgl/ExtensionSRGB.hx | 13 +- .../html/webgl/ExtensionShaderTextureLod.hx | 13 +- .../webgl/ExtensionStandardDerivatives.hx | 13 +- .../ExtensionTextureFilterAnisotropic.hx | 13 +- std/js/html/webgl/ExtensionTextureFloat.hx | 13 +- .../html/webgl/ExtensionTextureFloatLinear.hx | 13 +- .../html/webgl/ExtensionTextureHalfFloat.hx | 13 +- .../webgl/ExtensionTextureHalfFloatLinear.hx | 13 +- .../html/webgl/ExtensionVertexArrayObject.hx | 67 + std/js/html/webgl/Framebuffer.hx | 11 +- std/js/html/webgl/GL.hx | 2 +- std/js/html/webgl/LoseContext.hx | 27 - std/js/html/webgl/OESStandardDerivatives.hx | 27 - std/js/html/webgl/OESTextureFloat.hx | 27 - std/js/html/webgl/OESVertexArrayObject.hx | 27 - std/js/html/webgl/Program.hx | 11 +- std/js/html/webgl/Renderbuffer.hx | 11 +- std/js/html/webgl/RenderingContext.hx | 17 +- std/js/html/webgl/Shader.hx | 11 +- std/js/html/webgl/ShaderPrecisionFormat.hx | 23 +- std/js/html/webgl/Texture.hx | 11 +- ...tensionVertexArray.hx => TimerQueryEXT.hx} | 21 +- std/js/html/webgl/UniformLocation.hx | 11 +- std/js/html/webgl/VertexArrayObjectOES.hx | 18 +- std/js/jquery/Callbacks.hx | 53 + std/js/jquery/Deferred.hx | 79 + std/js/jquery/Event.hx | 70 + std/js/jquery/Helper.hx | 16 + std/js/jquery/JQuery.hx | 1097 +++ std/js/jquery/JqEltsIterator.hx | 21 + std/js/jquery/JqIterator.hx | 21 + std/js/jquery/JqXHR.hx | 46 + std/js/jquery/Promise.hx | 46 + std/js/swfobject/SWFObject.hx | 128 + std/lua/Bit.hx | 41 + std/lua/Boot.hx | 393 + std/lua/Coroutine.hx | 120 + std/lua/Debug.hx | 156 + std/lua/Ffi.hx | 61 + std/lua/FileHandle.hx | 38 + std/lua/HaxeIterator.hx | 42 + std/lua/Io.hx | 127 + std/lua/Jit.hx | 21 + std/lua/Lib.hx | 81 + std/lua/LocaleCategory.hx | 10 + std/lua/Lua.hx | 215 + std/lua/Map.hx | 89 + std/lua/Math.hx | 43 + std/lua/NativeIterator.hx | 47 + std/lua/NativeStringTools.hx | 140 + std/lua/Os.hx | 127 + std/lua/Package.hx | 70 + std/lua/PairTools.hx | 59 + std/lua/Result.hx | 5 + std/lua/Table.hx | 34 + std/lua/TableTools.hx | 15 + std/lua/Thread.hx | 30 + std/lua/Time.hx | 6 + std/lua/UserData.hx | 2 + std/lua/_lua/_hx_anon.lua | 28 + std/lua/_lua/_hx_apply.lua | 6 + std/lua/_lua/_hx_classes.lua | 13 + std/lua/_lua/_hx_tab_array.lua | 12 + std/lua/_std/Array.hx | 219 + std/lua/_std/Date.hx | 68 + std/lua/_std/EReg.hx | 163 + std/lua/_std/Math.hx | 77 + std/lua/_std/Reflect.hx | 157 + std/lua/_std/Std.hx | 94 + std/lua/_std/String.hx | 129 + std/lua/_std/StringBuf.hx | 111 + std/lua/_std/Sys.hx | 123 + std/lua/_std/Type.hx | 207 + std/lua/_std/haxe/Json.hx | 35 + std/lua/_std/haxe/Utf8.hx | 250 + std/lua/_std/haxe/ds/IntMap.hx | 86 + std/lua/_std/haxe/ds/ObjectMap.hx | 99 + std/lua/_std/haxe/ds/StringMap.hx | 95 + std/lua/_std/sys/FileSystem.hx | 124 + std/lua/_std/sys/io/File.hx | 76 + std/lua/_std/sys/io/FileInput.hx | 89 + std/lua/_std/sys/io/FileOutput.hx | 54 + std/lua/_std/sys/io/Process.hx | 186 + std/lua/lib/environ/Environ.hx | 30 + std/lua/lib/lrexlib/Rex.hx | 89 + .../lib/luasocket/Socket.hx} | 12 +- std/lua/lib/luv/Async.hx | 30 + std/lua/lib/luv/Check.hx | 31 + std/lua/lib/luv/Handle.hx | 36 + std/lua/lib/luv/Idle.hx | 31 + std/lua/lib/luv/Loop.hx | 14 + std/lua/lib/luv/Misc.hx | 102 + std/lua/lib/luv/Pipe.hx | 38 + std/lua/lib/luv/Poll.hx | 32 + std/lua/lib/luv/Prepare.hx | 32 + std/lua/lib/luv/Process.hx | 40 + std/lua/lib/luv/Request.hx | 28 + std/lua/lib/luv/Signal.hx | 33 + std/lua/lib/luv/Stream.hx | 41 + std/lua/lib/luv/Thread.hx | 34 + std/lua/lib/luv/Timer.hx | 35 + std/lua/lib/luv/Tty.hx | 41 + std/lua/lib/luv/Work.hx | 30 + std/lua/lib/luv/fs/FileDescriptor.hx | 25 + std/lua/lib/luv/fs/FileSystem.hx | 177 + std/lua/lib/luv/fs/FileSystemEvent.hx | 39 + std/lua/lib/luv/fs/FileSystemPoll.hx | 32 + std/lua/lib/luv/fs/Open.hx | 39 + std/lua/lib/luv/net/Dns.hx | 41 + std/lua/lib/luv/net/Tcp.hx | 38 + std/lua/lib/luv/net/Udp.hx | 43 + std/neko/Boot.hx | 3 +- std/neko/Lib.hx | 11 +- std/neko/NativeArray.hx | 2 +- std/neko/NativeString.hx | 2 +- std/neko/NativeXml.hx | 19 +- std/neko/Random.hx | 18 +- std/neko/Web.hx | 28 +- std/neko/_std/Array.hx | 2 +- std/neko/_std/Date.hx | 2 +- std/neko/_std/EReg.hx | 2 +- std/neko/_std/Math.hx | 81 +- std/neko/_std/Reflect.hx | 2 +- std/neko/_std/Std.hx | 2 +- std/neko/_std/String.hx | 3 +- std/neko/_std/StringBuf.hx | 2 +- std/neko/_std/Sys.hx | 72 +- std/neko/_std/Type.hx | 7 +- std/neko/_std/haxe/Utf8.hx | 2 +- std/neko/_std/haxe/ds/IntMap.hx | 2 +- std/neko/_std/haxe/ds/ObjectMap.hx | 2 +- std/neko/_std/haxe/ds/StringMap.hx | 2 +- std/neko/_std/haxe/zip/Compress.hx | 2 +- std/neko/_std/haxe/zip/Uncompress.hx | 2 +- std/neko/_std/sys/FileSystem.hx | 18 +- std/neko/_std/sys/db/Mysql.hx | 2 +- std/neko/_std/sys/db/Sqlite.hx | 2 +- std/neko/_std/sys/io/File.hx | 2 +- std/neko/_std/sys/io/FileInput.hx | 2 +- std/neko/_std/sys/io/FileOutput.hx | 2 +- std/neko/_std/sys/io/Process.hx | 12 +- std/neko/_std/sys/net/Host.hx | 5 +- std/neko/_std/sys/net/Socket.hx | 20 +- std/neko/_std/sys/net/UdpSocket.hx | 6 +- std/neko/_std/sys/ssl/Certificate.hx | 131 + std/neko/_std/sys/ssl/Digest.hx | 22 + std/neko/_std/sys/ssl/Key.hx | 34 + std/neko/_std/sys/ssl/Socket.hx | 289 + std/neko/net/Poll.hx | 2 +- std/neko/net/ProxyDetect.hx | 2 +- std/neko/net/ServerLoop.hx | 18 +- std/neko/net/ThreadRemotingServer.hx | 2 +- std/neko/net/ThreadServer.hx | 83 +- std/neko/vm/Deque.hx | 23 +- std/neko/vm/Gc.hx | 14 +- std/neko/vm/Loader.hx | 14 +- std/neko/vm/Lock.hx | 19 +- std/neko/vm/Module.hx | 8 +- std/neko/vm/Mutex.hx | 29 +- std/neko/vm/Thread.hx | 12 +- std/neko/vm/Tls.hx | 20 +- std/neko/vm/Ui.hx | 26 +- std/neko/zip/Compress.hx | 25 +- std/neko/zip/Flush.hx | 25 +- std/neko/zip/Uncompress.hx | 25 +- std/php/Boot.hx | 84 +- std/php/BytesData.hx | 94 + std/php/Exception.hx | 2 +- std/php/HException.hx | 2 +- std/php/IteratorAggregate.hx | 2 +- std/php/Lib.hx | 49 +- std/php/NativeArray.hx | 2 +- std/php/NativeString.hx | 2 +- std/php/NativeXml.hx | 2 +- std/php/Session.hx | 8 +- std/php/Web.hx | 41 +- std/php/_std/Date.hx | 2 +- std/php/_std/EReg.hx | 4 +- std/php/_std/List.hx | 2 +- std/php/_std/Math.hx | 2 +- std/php/_std/Reflect.hx | 16 +- std/php/_std/Std.hx | 44 +- std/php/_std/StringBuf.hx | 2 +- std/php/_std/StringTools.hx | 102 +- std/php/_std/Sys.hx | 50 +- std/php/_std/Type.hx | 5 +- std/php/_std/haxe/Json.hx | 9 +- std/php/_std/haxe/Resource.hx | 14 +- std/php/_std/haxe/Utf8.hx | 2 +- std/php/_std/haxe/ds/IntMap.hx | 2 +- std/php/_std/haxe/ds/ObjectMap.hx | 2 +- std/php/_std/haxe/ds/StringMap.hx | 2 +- std/php/_std/haxe/zip/Compress.hx | 55 + std/php/_std/haxe/zip/Uncompress.hx | 45 + std/php/_std/sys/FileSystem.hx | 6 +- std/php/_std/sys/db/Mysql.hx | 2 +- std/php/_std/sys/db/Sqlite.hx | 2 +- std/php/_std/sys/io/File.hx | 2 +- std/php/_std/sys/io/FileInput.hx | 2 +- std/php/_std/sys/io/FileOutput.hx | 2 +- std/php/_std/sys/io/Process.hx | 34 +- std/php/_std/sys/net/Host.hx | 5 +- std/php/_std/sys/net/Socket.hx | 4 +- std/php/db/PDO.hx | 10 +- std/php/net/SslSocket.hx | 2 +- std/php7/ArrayAccess.hx | 13 + std/php7/Boot.hx | 850 ++ std/php7/Closure.hx | 12 + std/php7/Const.hx | 302 + std/php7/Error.hx | 42 + std/php7/ErrorException.hx | 40 + std/php7/Exception.hx | 42 + std/php7/Global.hx | 1160 +++ .../IteratorAggregate.hx} | 17 +- std/php7/Lib.hx | 152 + std/php7/NativeArray.hx | 67 + std/php7/NativeAssocArray.hx | 40 + std/php7/NativeIndexedArray.hx | 44 + std/php7/NativeString.hx | 31 + std/php7/Ref.hx | 7 + std/php7/Resource.hx | 7 + std/php7/RuntimeException.hx | 4 + std/php7/Scalar.hx | 9 + std/php7/Session.hx | 171 + std/php7/SessionHandlerInterface.hx | 14 + std/php7/StdClass.hx | 7 + std/php7/SuperGlobal.hx | 60 + std/php7/Syntax.hx | 127 + std/php7/Throwable.hx | 16 + std/php7/Traversable.hx | 7 + std/php7/Web.hx | 420 + std/php7/_std/Array.hx | 245 + std/php7/_std/Date.hx | 96 + std/php7/_std/EReg.hx | 137 + std/php7/_std/Math.hx | 59 + std/php7/_std/Reflect.hx | 174 + std/php7/_std/Std.hx | 94 + std/php7/_std/StringBuf.hx | 60 + std/php7/_std/StringTools.hx | 205 + std/php7/_std/Sys.hx | 145 + std/php7/_std/Type.hx | 361 + std/php7/_std/haxe/CallStack.hx | 142 + std/php7/_std/haxe/Json.hx | 114 + std/php7/_std/haxe/Resource.hx | 68 + std/php7/_std/haxe/Utf8.hx | 88 + std/php7/_std/haxe/crypto/Md5.hx | 39 + std/php7/_std/haxe/crypto/Sha1.hx | 39 + std/php7/_std/haxe/crypto/Sha224.hx | 39 + std/php7/_std/haxe/crypto/Sha256.hx | 39 + std/php7/_std/haxe/ds/IntMap.hx | 98 + std/php7/_std/haxe/ds/ObjectMap.hx | 82 + std/php7/_std/haxe/ds/StringMap.hx | 74 + std/php7/_std/haxe/io/Bytes.hx | 206 + std/php7/_std/haxe/io/BytesBuffer.hx | 89 + std/php7/_std/haxe/io/BytesData.hx | 88 + std/php7/_std/haxe/io/BytesInput.hx | 79 + std/php7/_std/haxe/io/BytesOutput.hx | 57 + std/php7/_std/haxe/io/FPHelper.hx | 61 + std/php7/_std/haxe/zip/Compress.hx | 55 + std/php7/_std/haxe/zip/Uncompress.hx | 45 + std/php7/_std/sys/FileSystem.hx | 112 + std/php7/_std/sys/db/Mysql.hx | 238 + std/php7/_std/sys/db/Sqlite.hx | 192 + std/php7/_std/sys/io/File.hx | 63 + std/php7/_std/sys/io/FileInput.hx | 87 + std/php7/_std/sys/io/FileOutput.hx | 76 + std/php7/_std/sys/io/Process.hx | 213 + std/php7/_std/sys/net/Host.hx | 61 + std/php7/_std/sys/net/Socket.hx | 174 + std/php7/db/Mysqli.hx | 71 + std/php7/db/Mysqli_driver.hx | 16 + std/php7/db/Mysqli_result.hx | 40 + std/php7/db/Mysqli_stmt.hx | 35 + std/php7/db/Mysqli_warning.hx | 10 + std/php7/db/PDO.hx | 107 + std/php7/db/PDOException.hx | 8 + std/php7/db/PDOStatement.hx | 26 + std/php7/db/SQLite3.hx | 28 + std/php7/db/SQLite3Result.hx | 14 + std/php7/db/SQLite3Stmt.hx | 16 + std/php7/net/SslSocket.hx | 31 + std/php7/reflection/ReflectionClass.hx | 64 + .../reflection/ReflectionFunctionAbstract.hx | 35 + std/php7/reflection/ReflectionMethod.hx | 35 + std/php7/reflection/ReflectionProperty.hx | 28 + std/php7/reflection/Reflector.hx | 6 + std/python/Boot.hx | 7 +- std/python/Bytearray.hx | 2 +- std/python/Bytes.hx | 2 +- std/python/Dict.hx | 2 +- std/python/Exceptions.hx | 2 +- std/python/HaxeIterable.hx | 2 +- std/python/HaxeIterator.hx | 2 +- std/python/KwArgs.hx | 8 +- std/python/Lib.hx | 23 +- std/python/NativeArrayTools.hx | 2 +- std/python/NativeIterable.hx | 12 +- std/python/NativeIterator.hx | 10 +- std/python/NativeStringTools.hx | 2 +- std/python/Set.hx | 2 +- std/python/Syntax.hx | 3 +- std/python/Tuple.hx | 2 +- std/python/VarArgs.hx | 8 +- std/python/_std/Array.hx | 2 +- std/python/_std/Date.hx | 7 +- std/python/_std/EReg.hx | 118 +- std/python/_std/Math.hx | 2 +- std/python/_std/Reflect.hx | 3 +- std/python/_std/Std.hx | 3 +- std/python/_std/String.hx | 124 +- std/python/_std/StringBuf.hx | 55 +- std/python/_std/Sys.hx | 23 +- std/python/_std/Type.hx | 40 +- std/python/_std/haxe/Json.hx | 2 +- std/python/_std/haxe/Resource.hx | 29 +- std/python/_std/haxe/ds/IntMap.hx | 2 +- std/python/_std/haxe/ds/ObjectMap.hx | 2 +- std/python/_std/haxe/ds/StringMap.hx | 2 +- std/python/_std/sys/FileSystem.hx | 4 +- std/python/_std/sys/io/File.hx | 7 +- std/python/_std/sys/io/FileInput.hx | 2 +- std/python/_std/sys/io/FileOutput.hx | 2 +- std/python/_std/sys/io/Process.hx | 26 +- std/python/_std/sys/net/Host.hx | 50 +- std/python/_std/sys/net/Socket.hx | 23 +- std/python/internal/AnonObject.hx | 2 +- std/python/internal/ArrayImpl.hx | 42 +- std/python/internal/EnumImpl.hx | 2 +- std/python/internal/HxException.hx | 2 +- std/python/internal/HxOverrides.hx | 2 +- std/python/internal/Internal.hx | 2 +- std/python/internal/StringImpl.hx | 27 +- std/python/internal/UBuiltins.hx | 4 +- std/python/io/FileBytesInput.hx | 2 +- std/python/io/FileBytesOutput.hx | 2 +- std/python/io/FileTextInput.hx | 2 +- std/python/io/FileTextOutput.hx | 2 +- std/python/io/IFileInput.hx | 2 +- std/python/io/IFileOutput.hx | 2 +- std/python/io/IInput.hx | 2 +- std/python/io/IOutput.hx | 2 +- std/python/io/IoTools.hx | 2 +- std/python/io/NativeBytesInput.hx | 2 +- std/python/io/NativeBytesOutput.hx | 2 +- std/python/io/NativeInput.hx | 24 +- std/python/io/NativeOutput.hx | 11 +- std/python/io/NativeTextInput.hx | 2 +- std/python/io/NativeTextOutput.hx | 2 +- std/python/lib/Builtins.hx | 2 +- std/python/lib/Codecs.hx | 2 +- std/python/lib/FileDescriptor.hx | 2 +- std/python/lib/FileObject.hx | 2 +- std/python/lib/Functools.hx | 2 +- std/python/lib/Glob.hx | 2 +- std/python/lib/Inspect.hx | 3 +- std/python/lib/Io.hx | 2 +- std/python/lib/Json.hx | 2 +- std/python/lib/Math.hx | 2 +- std/python/lib/Msvcrt.hx | 2 +- std/python/lib/Os.hx | 2 +- std/python/lib/Pprint.hx | 2 +- std/python/lib/Random.hx | 2 +- std/python/lib/Re.hx | 2 +- std/python/lib/Select.hx | 2 +- std/python/lib/Shutil.hx | 2 +- std/python/lib/Subprocess.hx | 6 +- std/python/lib/Sys.hx | 7 +- std/python/lib/Tempfile.hx | 2 +- std/python/lib/Termios.hx | 2 +- std/python/lib/ThreadLowLevel.hx | 2 +- std/python/lib/Threading.hx | 40 + std/python/lib/Time.hx | 5 +- std/python/lib/Timeit.hx | 5 + std/python/lib/Traceback.hx | 2 +- std/python/lib/Tty.hx | 2 +- std/python/lib/codecs/Codec.hx | 2 +- std/python/lib/codecs/StreamReader.hx | 2 +- std/python/lib/codecs/StreamReaderWriter.hx | 2 +- std/python/lib/codecs/StreamWriter.hx | 2 +- std/python/lib/datetime/Datetime.hx | 4 +- std/python/lib/datetime/Timedelta.hx | 2 +- std/python/lib/datetime/Timezone.hx | 2 +- std/python/lib/datetime/Tzinfo.hx | 2 +- std/python/lib/io/BlockingIOError.hx | 2 +- std/python/lib/io/BufferedIOBase.hx | 2 +- std/python/lib/io/BufferedRWPair.hx | 2 +- std/python/lib/io/BufferedRandom.hx | 2 +- std/python/lib/io/BufferedReader.hx | 2 +- std/python/lib/io/BufferedWriter.hx | 2 +- std/python/lib/io/BytesIO.hx | 2 +- std/python/lib/io/FileIO.hx | 2 +- std/python/lib/io/IOBase.hx | 2 +- std/python/lib/io/RawIOBase.hx | 2 +- std/python/lib/io/StringIO.hx | 2 +- std/python/lib/io/TextIOBase.hx | 2 +- std/python/lib/io/TextIOWrapper.hx | 2 +- std/python/lib/io/UnsupportedOperation.hx | 2 +- std/python/lib/json/JSONDecoder.hx | 2 +- std/python/lib/json/JSONEncoder.hx | 2 +- std/python/lib/net/Address.hx | 2 +- std/python/lib/net/Socket.hx | 174 +- std/python/lib/os/Path.hx | 2 +- std/python/lib/subprocess/Popen.hx | 5 +- std/python/lib/threading/Lock.hx | 29 + std/python/lib/threading/RLock.hx | 29 + std/python/lib/threading/Thread.hx | 19 +- std/python/lib/time/StructTime.hx | 30 + std/python/lib/urllib/Parse.hx | 2 +- std/python/lib/xml/etree/ElementTree.hx | 2 +- std/sys/FileStat.hx | 54 +- std/sys/FileSystem.hx | 2 +- std/sys/db/Connection.hx | 2 +- std/sys/db/Manager.hx | 12 +- std/sys/db/Mysql.hx | 2 +- std/sys/db/Object.hx | 3 +- std/sys/db/RecordInfos.hx | 6 +- std/sys/db/RecordMacros.hx | 45 +- std/sys/db/ResultSet.hx | 2 +- std/sys/db/Sqlite.hx | 2 +- std/sys/db/TableCreate.hx | 3 +- std/sys/db/Transaction.hx | 2 +- std/sys/db/Types.hx | 58 +- std/sys/io/File.hx | 2 +- std/sys/io/FileInput.hx | 4 +- std/sys/io/FileOutput.hx | 4 +- std/sys/io/FileSeek.hx | 2 +- std/sys/io/Process.hx | 55 +- std/sys/net/Address.hx | 5 +- std/sys/net/Host.hx | 7 +- std/sys/net/Socket.hx | 20 +- std/sys/net/UdpSocket.hx | 2 +- std/sys/ssl/Certificate.hx | 39 + std/sys/ssl/Digest.hx | 11 + std/sys/ssl/DigestAlgorithm.hx | 12 + std/sys/ssl/Key.hx | 11 + std/sys/ssl/Socket.hx | 50 + tests/README.md | 8 +- tests/RunCi.hx | 880 +- tests/TestMakefile.hx | 76 + tests/TestMakefile.hxml | 2 + tests/benchs/mandelbrot/Mandelbrot.hx | 153 + tests/benchs/mandelbrot/Readme.md | 32 + tests/benchs/mandelbrot/compile-cpp.hxml | 7 + tests/benchs/mandelbrot/compile-cppia.hxml | 9 + tests/benchs/mandelbrot/compile-java.hxml | 7 + tests/benchs/mandelbrot/compile-js.hxml | 7 + tests/benchs/mandelbrot/compile-neko.hxml | 7 + tests/benchs/mandelbrot/compile-php.hxml | 7 + tests/benchs/{ => mtnetwork}/MTNetwork.hx | 0 tests/display/build.hxml | 4 + tests/display/src/DisplayTestCase.hx | 97 + tests/display/src/DisplayTestContext.hx | 181 + tests/display/src/File.hx | 62 + tests/display/src/Macro.hx | 63 + tests/display/src/Main.hx | 24 + tests/display/src/ModuleSymbolEntry.hx | 22 + tests/display/src/SignatureHelp.hx | 18 + tests/display/src/Types.hx | 15 + tests/display/src/cases/Abstract.hx | 16 + tests/display/src/cases/Basic.hx | 100 + tests/display/src/cases/BuildMacro.hx | 34 + tests/display/src/cases/Completion.hx | 48 + tests/display/src/cases/DocumentSymbols.hx | 102 + tests/display/src/cases/IImport.hx | 59 + tests/display/src/cases/Issue5141.hx | 36 + tests/display/src/cases/Issue5166.hx | 14 + tests/display/src/cases/Issue5171.hx | 14 + tests/display/src/cases/Issue5172.hx | 21 + tests/display/src/cases/Issue5173.hx | 22 + tests/display/src/cases/Issue5684.hx | 15 + tests/display/src/cases/Issue5712.hx | 21 + tests/display/src/cases/Issue5729.hx | 20 + tests/display/src/cases/Issue5775.hx | 15 + tests/display/src/cases/Issue5796.hx | 17 + tests/display/src/cases/Metadata.hx | 113 + tests/display/src/cases/PropertyAccessors.hx | 20 + tests/display/src/cases/Signature.hx | 188 + .../display/src/cases/StructureCompletion.hx | 56 + tests/display/src/cases/Super.hx | 36 + tests/display/src/cases/Toplevel.hx | 150 + tests/display/src/cases/Type.hx | 10 + tests/misc/compile.hxml | 1 + tests/misc/cppObjc/TestObjc.hx | 202 + tests/misc/cppObjc/build.hxml | 4 + tests/misc/cppObjc/native/Makefile | 20 + tests/misc/cppObjc/native/include/test.h | 59 + tests/misc/cppObjc/native/test.m | 82 + tests/misc/eventLoop/Main.hx | 57 + tests/misc/eventLoop/all.hxml | 19 + .../misc/eventLoop/eventLoop.hxproj | 107 +- tests/misc/eventLoop/test.html | 1 + tests/misc/projects/Issue1138/compile1.hxml | 4 + .../projects/Issue1138/compile1.hxml.stderr | 1 + tests/misc/projects/Issue1138/compile2.hxml | 4 + .../projects/Issue1138/compile2.hxml.stderr | 1 + .../projects/Issue1138/compile3-fail.hxml | 4 + .../Issue1138/compile3-fail.hxml.stderr | 1 + .../projects/Issue1138/compile4-fail.hxml | 3 + .../Issue1138/compile4-fail.hxml.stderr | 1 + tests/misc/projects/Issue1138/src1/C.hx | 7 + tests/misc/projects/Issue1138/src1/D.hx | 5 + tests/misc/projects/Issue1138/src1/import.hx | 2 + tests/misc/projects/Issue1138/src1/p2/C2.hx | 10 + .../misc/projects/Issue1138/src1/p2/import.hx | 1 + tests/misc/projects/Issue1138/src2/B.hx | 3 + tests/misc/projects/Issue1138/src2/import.hx | 1 + tests/misc/projects/Issue1138/src2/p2/A.hx | 8 + tests/misc/projects/Issue1138/src3/Main.hx | 3 + tests/misc/projects/Issue1138/src3/import.hx | 1 + tests/misc/projects/Issue1310/Main1.hx | 20 + .../projects/Issue1310/compile1-fail.hxml | 2 + .../Issue1310/compile1-fail.hxml.stderr | 2 + tests/misc/projects/Issue1968/compile.hxml | 2 +- .../projects/Issue1968/compile.hxml.stderr | 2 +- tests/misc/projects/Issue2087/Main.hx | 5 + .../compile-fail.hxml | 0 .../Issue2087/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue2148/Main1.hx | 11 + .../projects/Issue2148/compile1-fail.hxml | 2 + .../Issue2148/compile1-fail.hxml.stderr | 2 + tests/misc/projects/Issue2232/Main1.hx | 8 + tests/misc/projects/Issue2232/Main2.hx | 8 + .../projects/Issue2232/compile1-fail.hxml | 3 + .../Issue2232/compile1-fail.hxml.stderr | 2 + .../projects/Issue2232/compile2-fail.hxml | 3 + .../Issue2232/compile2-fail.hxml.stderr | 1 + .../Issue2263/import-completion.hxml.stderr | 8 +- .../subtype-static-completion.hxml.stderr | 4 +- .../Issue2263/type-completion.hxml.stderr | 4 +- tests/misc/projects/Issue2278/Macro.hx | 21 + tests/misc/projects/Issue2278/Main.hx | 19 + tests/misc/projects/Issue2278/MyTools.hx | 5 + .../projects/Issue2278/compile.hxml.disabled | 2 + .../projects/Issue2278/compile.hxml.stderr | 8 + tests/misc/projects/Issue2508/Main.hx | 70 + tests/misc/projects/Issue2508/compile.hxml | 2 + .../projects/Issue2508/compile.hxml.stderr | 10 + tests/misc/projects/Issue2538/Main.hx | 18 + .../misc/projects/Issue2538/compile-fail.hxml | 3 + .../Issue2538/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue2991/compile.hxml | 2 +- .../projects/Issue2991/compile.hxml.stderr | 2 +- tests/misc/projects/Issue2993/compile.hxml | 2 +- .../projects/Issue2993/compile.hxml.stderr | 2 +- tests/misc/projects/Issue2995/position.hxml | 2 +- .../projects/Issue2995/position.hxml.stderr | 2 +- tests/misc/projects/Issue2995/usage.hxml | 2 +- .../misc/projects/Issue2995/usage.hxml.stderr | 4 +- .../projects/Issue2996/compile1.hxml.stderr | 2 +- .../projects/Issue2996/compile2.hxml.stderr | 2 +- tests/misc/projects/Issue2997/Main.hx | 12 + tests/misc/projects/Issue2997/compile1.hxml | 1 + .../projects/Issue2997/compile1.hxml.stderr | 3 + tests/misc/projects/Issue3192/Main1.hx | 5 + .../projects/Issue3192/compile1-fail.hxml | 2 + .../Issue3192/compile1-fail.hxml.stderr | 3 + .../Issue3238/default-value-fail.hxml.stderr | 2 +- .../Issue3238/non-extern-fail.hxml.stderr | 2 +- .../Issue3238/not-last-fail.hxml.stderr | 2 +- .../Issue3238/optional-fail.hxml.stderr | 2 +- tests/misc/projects/Issue3298/Test.hx | 2 +- tests/misc/projects/Issue3310/Test.hx | 2 +- .../Issue3361/compile1-fail.hxml.stderr | 1 + .../Issue3361/compile2-fail.hxml.stderr | 1 + .../Issue3417/compile-fail.hxml.stderr | 3 +- tests/misc/projects/Issue3621/Main1.hx | 16 + .../misc/projects/Issue3621/compile-fail.hxml | 3 + .../Issue3621/compile-fail.hxml.stderr | 1 + .../Issue3710/compile-1-fail.hxml.stderr | 2 +- .../Issue3710/compile-2-fail.hxml.stderr | 2 +- tests/misc/projects/Issue3781/Main.hx | 2 +- .../Issue3782/compile-fail.hxml.disabled | 3 + tests/misc/projects/Issue3802/Main.hx | 7 + .../misc/projects/Issue3802/compile-fail.hxml | 1 + .../Issue3802/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue3907/Main.hx | 7 + tests/misc/projects/Issue3907/compile.hxml | 1 + .../projects/Issue3907/compile.hxml.stderr | 4 + .../projects/Issue3931/compile1.hxml.stderr | 4 +- .../projects/Issue3931/compile2.hxml.stderr | 4 +- tests/misc/projects/Issue3956/Main.hx | 10 + tests/misc/projects/Issue3956/compile.hxml | 3 + .../projects/Issue3956/compile.hxml.stderr | 2 + tests/misc/projects/Issue3975/Main.hx | 6 + .../misc/projects/Issue3975/compile-fail.hxml | 2 + .../Issue3975/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue4114/Main1.hx | 3 + tests/misc/projects/Issue4114/Main2.hx | 7 + .../projects/Issue4114/compile1-fail.hxml | 2 + .../Issue4114/compile1-fail.hxml.stderr | 1 + .../projects/Issue4114/compile2-fail.hxml | 2 + .../Issue4114/compile2-fail.hxml.stderr | 1 + tests/misc/projects/Issue4160/compile.hxml | 2 + .../projects/Issue4160/compile.hxml.stderr | 1 + tests/misc/projects/Issue4160/test/Main.hx | 51 + tests/misc/projects/Issue4218/Main.hx | 12 + tests/misc/projects/Issue4218/build.hxml | 3 + tests/misc/projects/Issue4247/Main.hx | 11 + .../misc/projects/Issue4247/compile-fail.hxml | 2 + .../Issue4247/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue4250/Main.hx | 14 + .../misc/projects/Issue4250/compile-fail.hxml | 2 + .../Issue4250/compile-fail.hxml.stderr | 5 + tests/misc/projects/Issue4265/Main.hx | 10 + tests/misc/projects/Issue4265/compile.hxml | 3 + .../projects/Issue4265/compile.hxml.stderr | 1 + tests/misc/projects/Issue4270/EmptyString.hx | 5 + tests/misc/projects/Issue4270/MultiChar.hx | 5 + tests/misc/projects/Issue4270/SingleChar.hx | 5 + tests/misc/projects/Issue4270/Test.hx | 28 + tests/misc/projects/Issue4270/test.hxml | 1 + tests/misc/projects/Issue4293/OnAbstract.hx | 3 + tests/misc/projects/Issue4293/OnClass.hx | 3 + tests/misc/projects/Issue4293/OnEnum.hx | 3 + tests/misc/projects/Issue4293/OnEnumCtor.hx | 3 + tests/misc/projects/Issue4293/OnField.hx | 3 + tests/misc/projects/Issue4293/OnTypedef.hx | 1 + .../Issue4293/compile-abstract-fail.hxml | 1 + .../compile-abstract-fail.hxml.stderr | 1 + .../Issue4293/compile-class-fail.hxml | 1 + .../Issue4293/compile-class-fail.hxml.stderr | 1 + .../Issue4293/compile-enum-ctor-fail.hxml | 1 + .../compile-enum-ctor-fail.hxml.stderr | 1 + .../projects/Issue4293/compile-enum-fail.hxml | 1 + .../Issue4293/compile-enum-fail.hxml.stderr | 1 + .../Issue4293/compile-field-fail.hxml | 1 + .../Issue4293/compile-field-fail.hxml.stderr | 1 + .../Issue4293/compile-typedef-fail.hxml | 1 + .../compile-typedef-fail.hxml.stderr | 1 + tests/misc/projects/Issue4364/Main.hx | 24 + .../misc/projects/Issue4364/compile-fail.hxml | 3 + .../Issue4364/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue4370/Test.hx | 12 + .../misc/projects/Issue4370/compile-fail.hxml | 1 + .../Issue4370/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue4378/Main.hx | 17 + .../misc/projects/Issue4378/compile-fail.hxml | 2 + .../Issue4378/compile-fail.hxml.stderr | 4 + tests/misc/projects/Issue4399/Main.hx | 19 + tests/misc/projects/Issue4399/compile.hxml | 3 + .../projects/Issue4399/compile.hxml.stderr | 1 + tests/misc/projects/Issue4404/compile1.hxml | 4 + tests/misc/projects/Issue4404/src/Base.hx | 4 + tests/misc/projects/Issue4404/src/Child.hx | 3 + .../misc/projects/Issue4404/src/ChildChild.hx | 4 + .../projects/Issue4404/src/ContainerBase.hx | 6 + .../projects/Issue4404/src/ContainerChild.hx | 7 + tests/misc/projects/Issue4404/src/Empty.hx | 0 tests/misc/projects/Issue4404/src/Macro.hx | 19 + tests/misc/projects/Issue4404/src/Main.hx | 10 + tests/misc/projects/Issue4448/Main1.hx | 21 + .../projects/Issue4448/compile1-fail.hxml | 2 + .../Issue4448/compile1-fail.hxml.stderr | 3 + tests/misc/projects/Issue4454/Main.hx | 20 + tests/misc/projects/Issue4454/compile.hxml | 2 + .../projects/Issue4454/compile.hxml.stderr | 1 + tests/misc/projects/Issue4456/Main.hx | 34 + tests/misc/projects/Issue4456/compile.hxml | 3 + .../projects/Issue4456/compile.hxml.stderr | 1 + tests/misc/projects/Issue4466/Main.hx | 6 + .../misc/projects/Issue4466/compile-fail.hxml | 2 + .../Issue4466/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue4540/Main.hx | 7 + .../misc/projects/Issue4540/compile-fail.hxml | 2 + .../Issue4540/compile-fail.hxml.stderr | 4 + tests/misc/projects/Issue4563/Main.hx | 15 + tests/misc/projects/Issue4563/compile.hxml | 3 + .../projects/Issue4563/compile.hxml.stderr | 1 + tests/misc/projects/Issue4580/Main.hx | 3 + .../misc/projects/Issue4580/compile-fail.hxml | 2 + .../Issue4580/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue4651/CompServer.hx | 16 + tests/misc/projects/Issue4651/Main.hx | 4 + tests/misc/projects/Issue4651/Main.hx.stdin | 1 + .../Issue4651/compile-server.hxml.disabled | 4 + .../Issue4651/compile-server.hxml.stderr | 3 + tests/misc/projects/Issue4651/compile.hxml | 1 + .../projects/Issue4651/compile.hxml.stderr | 3 + tests/misc/projects/Issue4660/Include.hx | 5 + tests/misc/projects/Issue4660/Test.hx | 22 + tests/misc/projects/Issue4660/compile.hxml | 1 + tests/misc/projects/Issue4660/include.js | 1 + tests/misc/projects/Issue4662/Main.hx | 1 + tests/misc/projects/Issue4662/Test.hx | 18 + tests/misc/projects/Issue4662/_pkg/A.hx | 3 + tests/misc/projects/Issue4662/compile.hxml | 1 + tests/misc/projects/Issue4671/Main1.hx | 6 + tests/misc/projects/Issue4671/Main2.hx | 6 + .../projects/Issue4671/compile1-fail.hxml | 2 + .../Issue4671/compile1-fail.hxml.stderr | 1 + .../projects/Issue4671/compile2-fail.hxml | 2 + .../Issue4671/compile2-fail.hxml.stderr | 1 + tests/misc/projects/Issue4679/Main.hx | 32 + tests/misc/projects/Issue4679/compile.hxml | 2 + .../projects/Issue4679/compile.hxml.stderr | 3 + tests/misc/projects/Issue4689/Main.hx | 21 + .../misc/projects/Issue4689/compile-fail.hxml | 2 + .../Issue4689/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue4712/Main.hx | 12 + tests/misc/projects/Issue4712/compile.hxml | 2 + .../projects/Issue4712/compile.hxml.stderr | 1 + tests/misc/projects/Issue4720/Main.hx | 70 + tests/misc/projects/Issue4720/compile.hxml | 2 + .../projects/Issue4720/compile.hxml.stderr | 18 + tests/misc/projects/Issue4723/Test.hx | 9 + tests/misc/projects/Issue4723/compile.hxml | 3 + tests/misc/projects/Issue4742/Main.hx | 6 + .../misc/projects/Issue4742/compile-fail.hxml | 3 + .../Issue4742/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue4754/Main1.hx | 5 + .../projects/Issue4754/compile1-fail.hxml | 2 + .../Issue4754/compile1-fail.hxml.stderr | 1 + tests/misc/projects/Issue4761/Main1.hx | 6 + .../projects/Issue4761/compile1-fail.hxml | 2 + .../Issue4761/compile1-fail.hxml.stderr | 1 + tests/misc/projects/Issue4764/Main1.hx | 12 + .../projects/Issue4764/compile1-fail.hxml | 2 + .../Issue4764/compile1-fail.hxml.stderr | 1 + tests/misc/projects/Issue4766/Main1.hx | 15 + .../projects/Issue4766/compile1-fail.hxml | 2 + .../Issue4766/compile1-fail.hxml.stderr | 1 + tests/misc/projects/Issue4775/Main1.hx | 11 + .../projects/Issue4775/compile1-fail.hxml | 2 + .../Issue4775/compile1-fail.hxml.stderr | 2 + tests/misc/projects/Issue4790/Main.hx | 5 + .../projects/Issue4790/builder/Builder.hx | 26 + .../projects/Issue4790/compile.hxml.disabled | 3 + .../misc/projects/Issue4790/consts/Consts.hx | 5 + tests/misc/projects/Issue4790/user1/User1.hx | 13 + tests/misc/projects/Issue4790/user2/User2.hx | 5 + tests/misc/projects/Issue4803/Main.hx | 9 + .../misc/projects/Issue4803/compile-fail.hxml | 3 + .../Issue4803/compile-fail.hxml.stderr | 7 + tests/misc/projects/Issue4816/Main1.hx | 6 + .../projects/Issue4816/compile1-fail.hxml | 2 + .../Issue4816/compile1-fail.hxml.stderr | 1 + tests/misc/projects/Issue4825/Macro.hx | 6 + tests/misc/projects/Issue4825/Main.hx | 9 + tests/misc/projects/Issue4825/compile.hxml | 2 + tests/misc/projects/Issue4904/Main.hx | 10 + .../misc/projects/Issue4904/compile-fail.hxml | 2 + .../Issue4904/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue4907/Main.hx | 15 + .../misc/projects/Issue4907/compile-fail.hxml | 2 + .../Issue4907/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue4954/Main.hx | 9 + .../misc/projects/Issue4954/compile-fail.hxml | 2 + .../Issue4954/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue4957/Main.hx | 18 + .../misc/projects/Issue4957/compile-fail.hxml | 2 + .../Issue4957/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue4982/Main.hx | 9 + .../misc/projects/Issue4982/compile-fail.hxml | 2 + .../Issue4982/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue5005/Main.hx | 5 + tests/misc/projects/Issue5005/compile.hxml | 2 + tests/misc/projects/Issue5010/Main.hx | 15 + .../misc/projects/Issue5010/compile-fail.hxml | 2 + .../Issue5010/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue5118/Main.hx | 11 + tests/misc/projects/Issue5118/compile1.hxml | 1 + .../projects/Issue5118/compile1.hxml.stderr | 3 + tests/misc/projects/Issue5118/compile2.hxml | 1 + .../projects/Issue5118/compile2.hxml.stderr | 3 + tests/misc/projects/Issue5122/Main.hx | 9 + tests/misc/projects/Issue5122/compile.hxml | 1 + .../projects/Issue5122/compile.hxml.stderr | 3 + tests/misc/projects/Issue5123/Main.hx | 11 + tests/misc/projects/Issue5123/compile.hxml | 1 + .../projects/Issue5123/compile.hxml.stderr | 3 + tests/misc/projects/Issue5125/Main.hx | 10 + tests/misc/projects/Issue5125/compile.hxml | 1 + .../projects/Issue5125/compile.hxml.stderr | 3 + tests/misc/projects/Issue5126/Main.hx | 4 + .../misc/projects/Issue5126/compile-fail.hxml | 3 + .../Issue5126/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue5128/Main.hx | 3 + tests/misc/projects/Issue5128/compile.hxml | 1 + .../projects/Issue5128/compile.hxml.stderr | 3 + tests/misc/projects/Issue5134/Main.hx | 23 + .../misc/projects/Issue5134/compile-fail.hxml | 1 + .../Issue5134/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue5145/Main.hx | 69 + tests/misc/projects/Issue5145/compile.hxml | 2 + tests/misc/projects/Issue5152/Main.hx | 6 + tests/misc/projects/Issue5152/compile.hxml | 1 + .../projects/Issue5152/compile.hxml.stderr | 3 + tests/misc/projects/Issue5206/Main.hx | 18 + .../misc/projects/Issue5206/compile-fail.hxml | 2 + .../Issue5206/compile-fail.hxml.stderr | 8 + tests/misc/projects/Issue5268/Main.hx | 19 + .../misc/projects/Issue5268/compile-fail.hxml | 2 + .../Issue5268/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue5321/Chest.hx | 1 + tests/misc/projects/Issue5321/Main.hx | 5 + tests/misc/projects/Issue5321/Test.hx | 16 + tests/misc/projects/Issue5321/compile.hxml | 2 + tests/misc/projects/Issue5375/Main.hx | 16 + .../misc/projects/Issue5375/compile-fail.hxml | 2 + .../Issue5375/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue5559/Build.hx | 5 + tests/misc/projects/Issue5559/Main.hx | 5 + tests/misc/projects/Issue5559/OtherClass.hx | 5 + tests/misc/projects/Issue5559/build.hxml | 4 + tests/misc/projects/Issue5559/import.hx | 1 + tests/misc/projects/Issue5644/Main.hx | 9 + tests/misc/projects/Issue5644/User.hx | 1 + .../misc/projects/Issue5644/compile-fail.hxml | 3 + .../Issue5644/compile-fail.hxml.stderr | 2 + tests/misc/projects/Issue5833/Main.hx | 9 + .../misc/projects/Issue5833/compile-fail.hxml | 3 + .../Issue5833/compile-fail.hxml.stderr | 1 + tests/misc/projects/Issue5856/Main.hx | 11 + tests/misc/projects/Issue5856/compile.hxml | 3 + tests/misc/projects/Issue5888/Main.hx | 11 + .../misc/projects/Issue5888/compile-fail.hxml | 3 + .../Issue5888/compile-fail.hxml.stderr | 1 + .../projects/display-package/compile1.hxml | 2 + .../display-package/compile1.hxml.stderr | 0 .../projects/display-package/compile2.hxml | 2 + .../display-package/compile2.hxml.stderr | 1 + .../projects/display-package/compile3.hxml | 1 + .../display-package/compile3.hxml.stderr | 1 + tests/misc/projects/display-package/src/C1.hx | 0 .../projects/display-package/src/pack/C2.hx | 0 .../projects/display-type/compile.hxml.stderr | 2 +- tests/misc/src/Main.hx | 14 +- tests/optimization/run.hxml | 6 +- tests/optimization/src/Macro.hx | 7 +- tests/optimization/src/Test.hx | 43 +- tests/optimization/src/TestAnalyzer.hx | 228 +- tests/optimization/src/TestBaseMacro.hx | 8 + tests/optimization/src/TestJs.hx | 432 +- tests/optimization/src/TestLocalDce.hx | 6 +- tests/optimization/src/TestNullChecker.hx | 83 +- tests/optimization/src/issues/Issue2236.hx | 53 +- tests/optimization/src/issues/Issue3713.hx | 5 +- tests/optimization/src/issues/Issue4223.hx | 64 + tests/optimization/src/issues/Issue4690.hx | 52 + tests/optimization/src/issues/Issue5477.hx | 16 + tests/optimization/src/issues/Issue5509.hx | 14 + tests/optimization/src/issues/Issue5745.hx | 25 + tests/optimization/src/issues/Issue5855.hx | 25 + tests/optimization/src/issues/Issue5931.hx | 23 + tests/sys/args.xml | 58 - tests/sys/compile-each.hxml | 10 +- tests/sys/compile-hl.hxml | 13 + tests/sys/compile-lua.hxml | 14 + tests/sys/compile-neko.hxml | 8 +- tests/sys/compile-php7.hxml | 16 + tests/sys/compile.hxml | 2 + tests/sys/lua | 1 + tests/sys/run.hxml | 1 + tests/sys/src/ExitCode.c | 10 + tests/sys/src/ExitCode.hx | 60 +- tests/sys/src/FileNames.hx | 38 +- tests/sys/src/TestArguments.hx | 73 +- tests/sys/src/TestCommandBase.hx | 153 + tests/sys/src/TestFileSystem.hx | 17 + tests/sys/src/TestSys.hx | 183 +- tests/sys/src/io/TestProcess.hx | 161 +- tests/unit/compile-as3.hxml | 2 +- tests/unit/compile-cpp.hxml | 5 +- tests/unit/compile-cppia-host.hxml | 2 + tests/unit/compile-cppia.hxml | 8 +- tests/unit/compile-cs-travis.hxml | 3 +- tests/unit/compile-cs-unsafe-travis.hxml | 2 +- tests/unit/compile-cs-unsafe.hxml | 2 +- tests/unit/compile-cs.hxml | 2 +- tests/unit/compile-each.hxml | 3 +- tests/unit/compile-flash9.hxml | 2 +- tests/unit/compile-hl.hxml | 5 + tests/unit/compile-java.hxml | 3 +- tests/unit/compile-js.hxml | 2 +- tests/unit/compile-lua.hxml | 3 + tests/unit/compile-macro.hxml | 2 +- tests/unit/compile-neko.hxml | 5 +- tests/unit/compile-php.hxml | 5 +- tests/unit/compile-php7.hxml | 5 + tests/unit/compile-python.hxml | 2 +- tests/unit/compile-saucelabs-runner.hxml | 2 +- tests/unit/compile.hxml | 2 + tests/unit/native_cs/src/haxe/test/Base.cs | 10 + tests/unit/native_cs/src/haxe/test/MyClass.cs | 1 + .../src/haxe/test/StaticAndInstanceClash.cs | 1 + tests/unit/src/RunSauceLabs.hx | 75 +- tests/unit/src/scripthost/Issue5351.hx | 41 + tests/unit/src/unit/HelperMacros.hx | 54 + tests/unit/src/unit/MyAbstract.hx | 18 +- tests/unit/src/unit/MyClass.hx | 2 +- tests/unit/src/unit/MyMacro.hx | 21 +- tests/unit/src/unit/MySpodClass.hx | 51 +- tests/unit/src/unit/Test.hx | 143 +- tests/unit/src/unit/TestBasetypes.hx | 12 +- tests/unit/src/unit/TestBytes.hx | 4 +- tests/unit/src/unit/TestCSharp.hx | 106 +- tests/unit/src/unit/TestDCE.hx | 36 +- tests/unit/src/unit/TestGADT.hx | 6 +- tests/unit/src/unit/TestGeneric.hx | 10 +- tests/unit/src/unit/TestHL.hx | 25 + tests/unit/src/unit/TestIO.hx | 1 - tests/unit/src/unit/TestInt64.hx | 166 +- tests/unit/src/unit/TestJQuery.hx | 39 + tests/unit/src/unit/TestJava.hx | 20 +- tests/unit/src/unit/TestJson.hx | 196 +- tests/unit/src/unit/TestLua.hx | 62 + tests/unit/src/unit/TestMain.hx | 160 + tests/unit/src/unit/TestMatch.hx | 84 +- tests/unit/src/unit/TestMeta.hx | 11 +- tests/unit/src/unit/TestMisc.hx | 4 +- tests/unit/src/unit/TestOrder.hx | 2 +- tests/unit/src/unit/TestOverloads.hx | 4 +- tests/unit/src/unit/TestPhp.hx | 142 +- tests/unit/src/unit/TestPython.hx | 18 +- tests/unit/src/unit/TestReflect.hx | 18 +- tests/unit/src/unit/TestResource.hx | 3 + tests/unit/src/unit/TestSerialize.hx | 16 +- tests/unit/src/unit/TestSpecification.hx | 8 +- tests/unit/src/unit/TestSpod.hx | 110 +- tests/unit/src/unit/TestType.hx | 121 +- tests/unit/src/unit/TestUInt.hx | 110 +- tests/unit/src/unit/TestUnspecified.hx | 8 +- tests/unit/src/unit/TestXML.hx | 8 +- tests/unit/src/unit/UnitBuilder.hx | 2 +- tests/unit/src/unit/hxcpp_issues/Issue189.hx | 2 +- .../unit/hxcpp_issues/Issue193.hx.disabled | 16 +- tests/unit/src/unit/hxcpp_issues/Issue225.hx | 8 +- tests/unit/src/unit/hxcpp_issues/Issue352.hx | 14 + tests/unit/src/unit/hxcpp_issues/String.hx | 2 +- tests/unit/src/unit/issues/Issue1497.hx | 4 +- tests/unit/src/unit/issues/Issue1827.hx | 115 + tests/unit/src/unit/issues/Issue1925.hx | 4 +- tests/unit/src/unit/issues/Issue1997.hx | 16 +- tests/unit/src/unit/issues/Issue2042.hx | 2 - tests/unit/src/unit/issues/Issue2044.hx | 2 +- .../{Issue2061.hx.disabled => Issue2061.hx} | 0 tests/unit/src/unit/issues/Issue2063.hx | 18 +- tests/unit/src/unit/issues/Issue2085.hx | 10 +- tests/unit/src/unit/issues/Issue2130.hx | 42 +- tests/unit/src/unit/issues/Issue2157.hx | 22 +- tests/unit/src/unit/issues/Issue2184.hx | 2 +- tests/unit/src/unit/issues/Issue2224.hx | 24 +- tests/unit/src/unit/issues/Issue2235.hx | 14 +- tests/unit/src/unit/issues/Issue2236.hx | 42 +- tests/unit/src/unit/issues/Issue2244.hx | 11 + tests/unit/src/unit/issues/Issue2281.hx | 4 +- tests/unit/src/unit/issues/Issue2282.hx | 4 +- tests/unit/src/unit/issues/Issue2343.hx | 10 +- tests/unit/src/unit/issues/Issue2380.hx | 4 +- tests/unit/src/unit/issues/Issue2396.hx | 60 +- tests/unit/src/unit/issues/Issue2401.hx | 4 +- tests/unit/src/unit/issues/Issue2409.hx | 4 +- tests/unit/src/unit/issues/Issue2478.hx | 6 +- .../src/unit/issues/Issue2508.hx.disabled | 4 +- tests/unit/src/unit/issues/Issue2521.hx | 2 + tests/unit/src/unit/issues/Issue2540.hx | 4 +- tests/unit/src/unit/issues/Issue2580.hx | 4 +- tests/unit/src/unit/issues/Issue2581.hx | 28 +- tests/unit/src/unit/issues/Issue2584.hx | 14 +- tests/unit/src/unit/issues/Issue2587.hx | 25 + tests/unit/src/unit/issues/Issue2607.hx | 10 +- tests/unit/src/unit/issues/Issue2614.hx | 10 +- tests/unit/src/unit/issues/Issue2619.hx | 2 +- tests/unit/src/unit/issues/Issue2625.hx | 4 +- tests/unit/src/unit/issues/Issue2627.hx | 8 +- tests/unit/src/unit/issues/Issue2633.hx | 18 +- tests/unit/src/unit/issues/Issue2639.hx | 12 +- tests/unit/src/unit/issues/Issue2653.hx | 6 +- tests/unit/src/unit/issues/Issue2661.hx | 4 +- tests/unit/src/unit/issues/Issue2664.hx | 20 +- .../src/unit/issues/Issue2668.hx.disabled | 4 +- tests/unit/src/unit/issues/Issue2675.hx | 7 +- tests/unit/src/unit/issues/Issue2685.hx | 4 +- tests/unit/src/unit/issues/Issue2696.hx | 8 +- tests/unit/src/unit/issues/Issue2698.hx | 12 +- tests/unit/src/unit/issues/Issue2712.hx | 10 +- tests/unit/src/unit/issues/Issue2735.hx | 6 +- tests/unit/src/unit/issues/Issue2736.hx | 41 +- tests/unit/src/unit/issues/Issue2750.hx | 24 +- tests/unit/src/unit/issues/Issue2763.hx | 2 +- tests/unit/src/unit/issues/Issue2766.hx | 12 +- tests/unit/src/unit/issues/Issue2767.hx | 24 + tests/unit/src/unit/issues/Issue2776.hx | 7 +- tests/unit/src/unit/issues/Issue2778.hx | 20 +- tests/unit/src/unit/issues/Issue2786.hx | 24 +- tests/unit/src/unit/issues/Issue2792.hx | 50 +- tests/unit/src/unit/issues/Issue2809.hx | 1 + tests/unit/src/unit/issues/Issue2810.hx | 26 +- tests/unit/src/unit/issues/Issue2813.hx | 2 +- tests/unit/src/unit/issues/Issue2844.hx | 2 +- tests/unit/src/unit/issues/Issue2859.hx | 22 +- tests/unit/src/unit/issues/Issue2861.hx | 2 +- tests/unit/src/unit/issues/Issue2871.hx | 6 +- tests/unit/src/unit/issues/Issue2902.hx | 6 +- tests/unit/src/unit/issues/Issue2907.hx | 2 +- tests/unit/src/unit/issues/Issue2914.hx | 2 +- tests/unit/src/unit/issues/Issue2937.hx | 2 +- tests/unit/src/unit/issues/Issue2939.hx | 2 +- tests/unit/src/unit/issues/Issue2951.hx | 38 +- tests/unit/src/unit/issues/Issue2958.hx | 26 +- tests/unit/src/unit/issues/Issue2963.hx | 4 +- tests/unit/src/unit/issues/Issue2979.hx | 12 +- tests/unit/src/unit/issues/Issue2980.hx | 2 +- tests/unit/src/unit/issues/Issue2982.hx | 10 +- tests/unit/src/unit/issues/Issue2988.hx | 15 +- tests/unit/src/unit/issues/Issue2989.hx | 3 +- tests/unit/src/unit/issues/Issue2999.hx | 1 - tests/unit/src/unit/issues/Issue3005.hx | 8 +- tests/unit/src/unit/issues/Issue3008.hx | 2 +- tests/unit/src/unit/issues/Issue3023.hx | 2 +- tests/unit/src/unit/issues/Issue3024.hx | 12 +- tests/unit/src/unit/issues/Issue3029.hx | 4 +- .../src/unit/issues/Issue3033.hx.disabled | 10 +- tests/unit/src/unit/issues/Issue3042.hx | 8 +- tests/unit/src/unit/issues/Issue3054.hx | 3 +- tests/unit/src/unit/issues/Issue3061.hx | 4 +- tests/unit/src/unit/issues/Issue3063.hx | 8 +- tests/unit/src/unit/issues/Issue3071.hx | 96 +- tests/unit/src/unit/issues/Issue3081.hx | 10 +- tests/unit/src/unit/issues/Issue3088.hx | 120 +- tests/unit/src/unit/issues/Issue3089.hx | 6 +- tests/unit/src/unit/issues/Issue3090.hx | 2 +- tests/unit/src/unit/issues/Issue3110.hx | 2 +- tests/unit/src/unit/issues/Issue3113.hx | 10 +- tests/unit/src/unit/issues/Issue3115.hx | 14 +- tests/unit/src/unit/issues/Issue3132.hx | 4 +- tests/unit/src/unit/issues/Issue3133.hx | 10 +- tests/unit/src/unit/issues/Issue3138.hx | 16 +- tests/unit/src/unit/issues/Issue3150.hx | 2 +- tests/unit/src/unit/issues/Issue3181.hx | 2 +- tests/unit/src/unit/issues/Issue3183.hx | 6 +- tests/unit/src/unit/issues/Issue3192.hx | 17 + tests/unit/src/unit/issues/Issue3197.hx | 24 +- tests/unit/src/unit/issues/Issue3198.hx | 38 +- tests/unit/src/unit/issues/Issue3214.hx | 2 +- tests/unit/src/unit/issues/Issue3217.hx | 6 +- tests/unit/src/unit/issues/Issue3218.hx | 2 +- tests/unit/src/unit/issues/Issue3244.hx | 4 +- tests/unit/src/unit/issues/Issue3254.hx | 14 + tests/unit/src/unit/issues/Issue3280.hx | 12 +- tests/unit/src/unit/issues/Issue3292.hx | 36 +- tests/unit/src/unit/issues/Issue3333.hx | 4 +- tests/unit/src/unit/issues/Issue3338.hx | 10 +- tests/unit/src/unit/issues/Issue3344.hx | 8 +- tests/unit/src/unit/issues/Issue3345.hx | 6 +- tests/unit/src/unit/issues/Issue3346.hx | 18 +- tests/unit/src/unit/issues/Issue3347.hx | 30 +- tests/unit/src/unit/issues/Issue3360.hx | 42 +- tests/unit/src/unit/issues/Issue3361.hx | 33 + tests/unit/src/unit/issues/Issue3365.hx | 12 +- tests/unit/src/unit/issues/Issue3370.hx | 44 +- tests/unit/src/unit/issues/Issue3383.hx | 4 + tests/unit/src/unit/issues/Issue3387.hx | 14 +- tests/unit/src/unit/issues/Issue3388.hx | 18 +- tests/unit/src/unit/issues/Issue3390.hx | 14 +- tests/unit/src/unit/issues/Issue3391.hx | 4 +- tests/unit/src/unit/issues/Issue3396.hx | 12 +- tests/unit/src/unit/issues/Issue3400.hx | 12 +- tests/unit/src/unit/issues/Issue3431.hx | 12 +- tests/unit/src/unit/issues/Issue3440.hx | 1 - tests/unit/src/unit/issues/Issue3448.hx | 6 +- tests/unit/src/unit/issues/Issue3450.hx | 16 + tests/unit/src/unit/issues/Issue3460.hx | 13 + tests/unit/src/unit/issues/Issue3461.hx | 4 +- tests/unit/src/unit/issues/Issue3480.hx | 12 +- tests/unit/src/unit/issues/Issue3486.hx | 10 +- tests/unit/src/unit/issues/Issue3494.hx | 24 +- tests/unit/src/unit/issues/Issue3499.hx | 17 + tests/unit/src/unit/issues/Issue3504.hx | 6 +- tests/unit/src/unit/issues/Issue3507.hx | 13 +- tests/unit/src/unit/issues/Issue3512.hx | 10 +- tests/unit/src/unit/issues/Issue3513.hx | 12 +- tests/unit/src/unit/issues/Issue3516.hx | 14 +- tests/unit/src/unit/issues/Issue3528.hx | 23 + tests/unit/src/unit/issues/Issue3535.hx | 55 + tests/unit/src/unit/issues/Issue3543.hx | 8 +- tests/unit/src/unit/issues/Issue3554.hx | 14 +- tests/unit/src/unit/issues/Issue3557.hx | 2 +- tests/unit/src/unit/issues/Issue3560.hx | 15 + tests/unit/src/unit/issues/Issue3563.hx | 23 + tests/unit/src/unit/issues/Issue3577.hx | 22 +- tests/unit/src/unit/issues/Issue3585.hx | 28 +- tests/unit/src/unit/issues/Issue3586.hx | 12 +- tests/unit/src/unit/issues/Issue3588.hx | 12 +- tests/unit/src/unit/issues/Issue3592.hx | 40 +- tests/unit/src/unit/issues/Issue3596.hx | 4 +- tests/unit/src/unit/issues/Issue3615.hx | 12 +- tests/unit/src/unit/issues/Issue3616.hx | 24 +- tests/unit/src/unit/issues/Issue3635.hx | 4 +- tests/unit/src/unit/issues/Issue3639.hx | 1 + tests/unit/src/unit/issues/Issue3680.hx | 26 +- tests/unit/src/unit/issues/Issue3681.hx | 34 +- tests/unit/src/unit/issues/Issue3702.hx | 32 + tests/unit/src/unit/issues/Issue3711.hx | 6 +- tests/unit/src/unit/issues/Issue3713.hx | 12 +- tests/unit/src/unit/issues/Issue3714.hx | 16 +- tests/unit/src/unit/issues/Issue3717.hx | 18 +- tests/unit/src/unit/issues/Issue3732.hx | 2 +- tests/unit/src/unit/issues/Issue3753.hx | 34 +- tests/unit/src/unit/issues/Issue3762.hx | 30 + tests/unit/src/unit/issues/Issue3777.hx | 14 +- tests/unit/src/unit/issues/Issue3781.hx | 22 + tests/unit/src/unit/issues/Issue3804.hx | 12 + tests/unit/src/unit/issues/Issue3806.hx | 12 +- tests/unit/src/unit/issues/Issue3846.hx | 12 +- tests/unit/src/unit/issues/Issue3852.hx | 104 +- tests/unit/src/unit/issues/Issue3860.hx | 8 +- tests/unit/src/unit/issues/Issue3861.hx | 2 - tests/unit/src/unit/issues/Issue3892.hx | 4 +- tests/unit/src/unit/issues/Issue3894.hx | 2 +- tests/unit/src/unit/issues/Issue3914.hx | 114 +- tests/unit/src/unit/issues/Issue3921.hx | 24 +- tests/unit/src/unit/issues/Issue3935.hx | 34 + tests/unit/src/unit/issues/Issue3946.hx | 12 +- tests/unit/src/unit/issues/Issue3967.hx | 4 +- tests/unit/src/unit/issues/Issue3987.hx | 13 + tests/unit/src/unit/issues/Issue4002.hx | 18 +- tests/unit/src/unit/issues/Issue4045.hx | 36 +- tests/unit/src/unit/issues/Issue4084.hx | 17 - tests/unit/src/unit/issues/Issue4085.hx | 16 +- tests/unit/src/unit/issues/Issue4086.hx | 17 + tests/unit/src/unit/issues/Issue4089.hx | 16 + tests/unit/src/unit/issues/Issue4094.hx | 64 +- tests/unit/src/unit/issues/Issue4103.hx | 16 + tests/unit/src/unit/issues/Issue4121.hx | 21 + tests/unit/src/unit/issues/Issue4122.hx | 24 + tests/unit/src/unit/issues/Issue4130.hx | 162 +- tests/unit/src/unit/issues/Issue4158.hx | 23 + tests/unit/src/unit/issues/Issue4180.hx | 26 + tests/unit/src/unit/issues/Issue4196.hx | 12 + tests/unit/src/unit/issues/Issue4203.hx | 28 + .../src/unit/issues/Issue4203.hx.disabled | 29 + tests/unit/src/unit/issues/Issue4222.hx | 22 + tests/unit/src/unit/issues/Issue4232.hx | 18 + tests/unit/src/unit/issues/Issue4246.hx | 10 + tests/unit/src/unit/issues/Issue4254.hx | 9 + tests/unit/src/unit/issues/Issue4260.hx | 13 + tests/unit/src/unit/issues/Issue4273.hx | 17 + tests/unit/src/unit/issues/Issue4277.hx | 12 + tests/unit/src/unit/issues/Issue4284.hx | 19 + tests/unit/src/unit/issues/Issue4285.hx | 12 + tests/unit/src/unit/issues/Issue4295.hx | 10 + tests/unit/src/unit/issues/Issue4306.hx | 42 + tests/unit/src/unit/issues/Issue4310.hx | 14 + tests/unit/src/unit/issues/Issue4312.hx | 12 + tests/unit/src/unit/issues/Issue4313.hx | 27 + tests/unit/src/unit/issues/Issue4322.hx | 20 + tests/unit/src/unit/issues/Issue4323.hx | 20 + tests/unit/src/unit/issues/Issue4324.hx | 20 + .../src/unit/issues/Issue4327.hx.disabled | 18 + tests/unit/src/unit/issues/Issue4329.hx | 18 + tests/unit/src/unit/issues/Issue4337.hx | 13 + tests/unit/src/unit/issues/Issue4343.hx | 22 + tests/unit/src/unit/issues/Issue4353.hx | 37 + tests/unit/src/unit/issues/Issue4357.hx | 13 + tests/unit/src/unit/issues/Issue4359.hx | 8 + tests/unit/src/unit/issues/Issue4360.hx | 21 + tests/unit/src/unit/issues/Issue4384.hx | 20 + tests/unit/src/unit/issues/Issue4388.hx | 22 + tests/unit/src/unit/issues/Issue4397.hx | 15 + tests/unit/src/unit/issues/Issue4407.hx | 2 +- tests/unit/src/unit/issues/Issue4419.hx | 23 + tests/unit/src/unit/issues/Issue4421.hx | 21 + tests/unit/src/unit/issues/Issue4426.hx | 50 + tests/unit/src/unit/issues/Issue4436.hx | 19 + tests/unit/src/unit/issues/Issue4445.hx | 17 + tests/unit/src/unit/issues/Issue4450.hx | 8 + tests/unit/src/unit/issues/Issue4457.hx | 2 +- tests/unit/src/unit/issues/Issue4466.hx | 10 + tests/unit/src/unit/issues/Issue4473.hx | 67 + tests/unit/src/unit/issues/Issue4501.hx | 11 + tests/unit/src/unit/issues/Issue4526.hx | 68 + tests/unit/src/unit/issues/Issue4535.hx | 6 + tests/unit/src/unit/issues/Issue4551.hx | 13 + tests/unit/src/unit/issues/Issue4557.hx | 25 + .../src/unit/issues/Issue4564.hx.disabled | 22 + tests/unit/src/unit/issues/Issue4578.hx | 43 + tests/unit/src/unit/issues/Issue4579.hx | 20 + tests/unit/src/unit/issues/Issue4581.hx | 11 + tests/unit/src/unit/issues/Issue4591.hx | 9 + tests/unit/src/unit/issues/Issue4592.hx | 15 + tests/unit/src/unit/issues/Issue4593.hx | 15 + tests/unit/src/unit/issues/Issue4608.hx | 15 + tests/unit/src/unit/issues/Issue4617.hx | 42 + tests/unit/src/unit/issues/Issue4644.hx | 24 + tests/unit/src/unit/issues/Issue4653.hx | 29 + tests/unit/src/unit/issues/Issue4666.hx | 11 + tests/unit/src/unit/issues/Issue4667.hx | 9 + tests/unit/src/unit/issues/Issue4668.hx | 22 + tests/unit/src/unit/issues/Issue4672.hx | 24 + tests/unit/src/unit/issues/Issue4675.hx | 14 + tests/unit/src/unit/issues/Issue4677.hx | 10 + tests/unit/src/unit/issues/Issue4681.hx | 115 + tests/unit/src/unit/issues/Issue4690.hx | 18 + tests/unit/src/unit/issues/Issue4695.hx | 27 + tests/unit/src/unit/issues/Issue4702.hx | 12 + tests/unit/src/unit/issues/Issue4703.hx | 25 + tests/unit/src/unit/issues/Issue4723.hx | 25 + tests/unit/src/unit/issues/Issue4729.hx | 18 + tests/unit/src/unit/issues/Issue4740.hx | 14 + tests/unit/src/unit/issues/Issue4743.hx | 20 + tests/unit/src/unit/issues/Issue4751.hx | 29 + tests/unit/src/unit/issues/Issue4757.hx | 31 + tests/unit/src/unit/issues/Issue4772.hx | 13 + tests/unit/src/unit/issues/Issue4777.hx | 11 + tests/unit/src/unit/issues/Issue4798.hx | 18 + tests/unit/src/unit/issues/Issue4809.hx | 14 + tests/unit/src/unit/issues/Issue4810.hx | 10 + tests/unit/src/unit/issues/Issue4819.hx | 31 + tests/unit/src/unit/issues/Issue4841.hx | 10 + tests/unit/src/unit/issues/Issue4842.hx | 16 + tests/unit/src/unit/issues/Issue4843.hx | 13 + tests/unit/src/unit/issues/Issue4862.hx | 28 + tests/unit/src/unit/issues/Issue4867.hx | 21 + tests/unit/src/unit/issues/Issue4870.hx | 11 + tests/unit/src/unit/issues/Issue4878.hx | 24 + tests/unit/src/unit/issues/Issue4885.hx | 23 + tests/unit/src/unit/issues/Issue4886.hx | 22 + tests/unit/src/unit/issues/Issue4889.hx | 12 + tests/unit/src/unit/issues/Issue4904.hx | 22 + tests/unit/src/unit/issues/Issue4910.hx | 27 + tests/unit/src/unit/issues/Issue4917.hx | 25 + tests/unit/src/unit/issues/Issue4918.hx | 15 + tests/unit/src/unit/issues/Issue4940.hx | 39 + tests/unit/src/unit/issues/Issue4949.hx | 20 + tests/unit/src/unit/issues/Issue4953.hx | 21 + tests/unit/src/unit/issues/Issue4962.hx | 15 + tests/unit/src/unit/issues/Issue4966.hx | 37 + tests/unit/src/unit/issues/Issue4969.hx | 33 + tests/unit/src/unit/issues/Issue4973.hx | 11 + tests/unit/src/unit/issues/Issue4977.hx | 31 + tests/unit/src/unit/issues/Issue4979.hx | 13 + tests/unit/src/unit/issues/Issue4986.hx | 12 + tests/unit/src/unit/issues/Issue4987.hx | 18 + tests/unit/src/unit/issues/Issue4988.hx | 20 + tests/unit/src/unit/issues/Issue4997.hx | 13 + tests/unit/src/unit/issues/Issue5000.hx | 8 + tests/unit/src/unit/issues/Issue5015.hx | 9 + tests/unit/src/unit/issues/Issue5016.hx | 11 + tests/unit/src/unit/issues/Issue5025.hx | 22 + tests/unit/src/unit/issues/Issue5027.hx | 8 + tests/unit/src/unit/issues/Issue5028.hx | 13 + tests/unit/src/unit/issues/Issue5029.hx | 10 + tests/unit/src/unit/issues/Issue5030.hx | 23 + tests/unit/src/unit/issues/Issue5031.hx | 38 + tests/unit/src/unit/issues/Issue5044.hx | 14 + tests/unit/src/unit/issues/Issue5053.hx | 20 + tests/unit/src/unit/issues/Issue5064.hx | 24 + tests/unit/src/unit/issues/Issue5073.hx | 15 + tests/unit/src/unit/issues/Issue5078.hx | 13 + tests/unit/src/unit/issues/Issue5082.hx | 37 + tests/unit/src/unit/issues/Issue5086.hx | 26 + tests/unit/src/unit/issues/Issue5090.hx | 8 + tests/unit/src/unit/issues/Issue5108.hx | 20 + .../src/unit/issues/Issue5110.hx.disabled | 18 + tests/unit/src/unit/issues/Issue5113.hx | 41 + tests/unit/src/unit/issues/Issue5124.hx | 24 + tests/unit/src/unit/issues/Issue5135.hx | 21 + tests/unit/src/unit/issues/Issue5162.hx | 25 + tests/unit/src/unit/issues/Issue5179.hx | 21 + tests/unit/src/unit/issues/Issue5184.hx | 38 + tests/unit/src/unit/issues/Issue5192.hx | 9 + tests/unit/src/unit/issues/Issue5192_Test.hx | 10 + tests/unit/src/unit/issues/Issue5218.hx | 12 + tests/unit/src/unit/issues/Issue5221.hx | 11 + tests/unit/src/unit/issues/Issue5226.hx | 33 + tests/unit/src/unit/issues/Issue5231.hx | 25 + tests/unit/src/unit/issues/Issue5234.hx | 15 + tests/unit/src/unit/issues/Issue5242.hx | 47 + tests/unit/src/unit/issues/Issue5248.hx | 23 + tests/unit/src/unit/issues/Issue5249.hx | 15 + tests/unit/src/unit/issues/Issue5253.hx | 12 + tests/unit/src/unit/issues/Issue5260.hx | 8 + tests/unit/src/unit/issues/Issue5270.hx | 19 + tests/unit/src/unit/issues/Issue5274.hx | 16 + tests/unit/src/unit/issues/Issue5288.hx | 9 + tests/unit/src/unit/issues/Issue5290.hx | 17 + tests/unit/src/unit/issues/Issue5293.hx | 8 + tests/unit/src/unit/issues/Issue5303.hx | 9 + tests/unit/src/unit/issues/Issue5309.hx | 15 + tests/unit/src/unit/issues/Issue5322.hx | 36 + tests/unit/src/unit/issues/Issue5323.hx | 17 + tests/unit/src/unit/issues/Issue5340.hx | 31 + tests/unit/src/unit/issues/Issue5351.hx | 50 + tests/unit/src/unit/issues/Issue5358.hx | 15 + tests/unit/src/unit/issues/Issue5383.hx | 19 + tests/unit/src/unit/issues/Issue5385.hx | 26 + tests/unit/src/unit/issues/Issue5389.hx | 17 + tests/unit/src/unit/issues/Issue5392.hx | 16 + tests/unit/src/unit/issues/Issue5425.hx | 10 + tests/unit/src/unit/issues/Issue5432.hx | 25 + tests/unit/src/unit/issues/Issue5455.hx | 13 + tests/unit/src/unit/issues/Issue5466.hx | 17 + tests/unit/src/unit/issues/Issue5469.hx | 15 + tests/unit/src/unit/issues/Issue5470.hx | 10 + tests/unit/src/unit/issues/Issue5477.hx | 167 + tests/unit/src/unit/issues/Issue5481.hx | 17 + tests/unit/src/unit/issues/Issue5505.hx | 13 + tests/unit/src/unit/issues/Issue5507.hx | 15 + tests/unit/src/unit/issues/Issue5508.hx | 28 + tests/unit/src/unit/issues/Issue5520.hx | 27 + tests/unit/src/unit/issues/Issue5540.hx | 16 + tests/unit/src/unit/issues/Issue5543.hx | 17 + tests/unit/src/unit/issues/Issue5544.hx | 31 + tests/unit/src/unit/issues/Issue5555.hx | 46 + tests/unit/src/unit/issues/Issue5556.hx | 17 + tests/unit/src/unit/issues/Issue5557.hx | 11 + tests/unit/src/unit/issues/Issue5558.hx | 19 + tests/unit/src/unit/issues/Issue5565.hx | 9 + tests/unit/src/unit/issues/Issue5569.hx | 18 + tests/unit/src/unit/issues/Issue5572.hx | 29 + tests/unit/src/unit/issues/Issue5584.hx | 17 + tests/unit/src/unit/issues/Issue5608.hx | 13 + tests/unit/src/unit/issues/Issue5693.hx | 19 + tests/unit/src/unit/issues/Issue5705.hx | 17 + tests/unit/src/unit/issues/Issue5737.hx | 22 + tests/unit/src/unit/issues/Issue5742.hx | 21 + tests/unit/src/unit/issues/Issue5747.hx | 10 + tests/unit/src/unit/issues/Issue5757.hx | 19 + tests/unit/src/unit/issues/Issue5764.hx | 11 + tests/unit/src/unit/issues/Issue5783.hx | 13 + tests/unit/src/unit/issues/Issue5848.hx | 40 + tests/unit/src/unit/issues/Issue5851.hx | 12 + tests/unit/src/unit/issues/Issue5873.hx | 25 + tests/unit/src/unit/issues/Issue5894.hx | 19 + tests/unit/src/unit/issues/Issue5911.hx | 13 + tests/unit/src/unit/issues/Issue5919.hx | 11 + tests/unit/src/unit/issues/Issue5923.hx | 18 + tests/unit/src/unit/issues/Issue5945.hx | 11 + tests/unit/src/unit/issues/Issue5957.hx | 17 + tests/unit/src/unit/issues/Issue5973.hx | 38 + .../src/unit/issues/misc/Issue1497Macro.hx | 18 +- .../src/unit/issues/misc/Issue2003Macro.hx | 30 +- .../src/unit/issues/misc/Issue3008Class.hx | 4 +- .../src/unit/issues/misc/Issue3133Class.hx | 4 +- .../src/unit/issues/misc/Issue3183Macro.hx | 3 +- .../src/unit/issues/misc/Issue3460Macro.hx | 16 + .../src/unit/issues/misc/Issue3560Macro.hx | 11 + .../src/unit/issues/misc/Issue4121Macro.hx | 14 + .../src/unit/issues/misc/Issue4306Macro.hx | 44 + .../src/unit/issues/misc/Issue4419External.js | 1 + .../src/unit/issues/misc/Issue4653Macro.hx | 11 + .../src/unit/issues/misc/Issue4666Macro.hx | 7 + .../src/unit/issues/misc/Issue5429Macro.hx | 14 + tests/unit/src/unitstd/Array.unit.hx | 4 +- tests/unit/src/unitstd/Date.unit.hx | 16 +- tests/unit/src/unitstd/EReg.unit.hx | 6 + .../unit/src/unitstd/EvaluationOrder.unit.hx | 32 +- tests/unit/src/unitstd/Float.unit.hx | 53 + tests/unit/src/unitstd/Https.unit.hx | 4 + tests/unit/src/unitstd/Issue3067.hx | 18 +- tests/unit/src/unitstd/Map.unit.hx | 4 +- tests/unit/src/unitstd/Math.unit.hx | 37 +- tests/unit/src/unitstd/Reflect.unit.hx | 11 +- tests/unit/src/unitstd/Ssl.unit.hx | 105 + tests/unit/src/unitstd/Std.unit.hx | 22 +- tests/unit/src/unitstd/String.unit.hx | 2 + tests/unit/src/unitstd/StringTools.unit.hx | 2 +- tests/unit/src/unitstd/Type.unit.hx | 2 + tests/unit/src/unitstd/haxe/CallStack.unit.hx | 12 +- .../src/unitstd/haxe/DynamicAccess.unit.hx | 4 +- tests/unit/src/unitstd/haxe/Utf8.unit.hx | 17 +- tests/unit/src/unitstd/haxe/ds/Vector.unit.hx | 94 +- .../unitstd/haxe/extern/EitherType.unit.hx | 4 +- .../src/unitstd/haxe/io/BytesBuffer.unit.hx | 6 +- .../unit/src/unitstd/haxe/io/FPHelper.unit.hx | 11 + .../src/unitstd/haxe/zip/Compress.unit.hx | 33 + tests/unit/unit-js.html | 19 +- tests/unit/unit.html | 4 + tests/unit/unit.hxproj | 2 +- .../site.hxproj => tests/unit/unit_hl.hxproj | 107 +- typecore.ml | 525 -- typeload.ml | 3277 ------- 3186 files changed, 130046 insertions(+), 45558 deletions(-) create mode 100644 .merlin delete mode 100644 .travis.yml delete mode 100644 analyzer.ml delete mode 100644 appveyor.yml delete mode 100644 ast.ml delete mode 100644 codegen.ml delete mode 100644 common.ml create mode 100644 extra/bintray.tpl.json create mode 100644 extra/choco/haxe.nuspec create mode 100644 extra/deploy_key.enc create mode 100644 extra/haxeci_sec.gpg.enc create mode 100644 extra/haxeci_ssh.enc create mode 100644 extra/haxelib_src/.dockerignore create mode 100644 extra/haxelib_src/.ebextensions/cloudwatch.config create mode 100644 extra/haxelib_src/.ebextensions/docker_volumes.config create mode 100644 extra/haxelib_src/.ebextensions/nginx.config create mode 100644 extra/haxelib_src/.vscode/settings.json create mode 100644 extra/haxelib_src/.vscode/tasks.json create mode 100644 extra/haxelib_src/CHANGES.md create mode 100644 extra/haxelib_src/Dockerfile create mode 100644 extra/haxelib_src/Dockerrun.aws.json delete mode 100644 extra/haxelib_src/Package.hx create mode 100644 extra/haxelib_src/apache2.conf create mode 100644 extra/haxelib_src/ci.hxml create mode 100644 extra/haxelib_src/client.hxml rename extra/haxelib_src/{legacyhaxelib.hxml => client_legacy.hxml} (54%) rename extra/haxelib_src/{test.hxml => client_tests.hxml} (67%) create mode 100644 extra/haxelib_src/deploy.json create mode 100644 extra/haxelib_src/deploy_key.enc delete mode 100644 extra/haxelib_src/haxelib.hxml delete mode 100644 extra/haxelib_src/haxelib.hxproj delete mode 100755 extra/haxelib_src/haxelib.sh delete mode 100755 extra/haxelib_src/haxelib_script.sh create mode 100644 extra/haxelib_src/integration_tests.hxml delete mode 100755 extra/haxelib_src/legacyhaxelib.sh create mode 100755 extra/haxelib_src/package.hxml delete mode 100755 extra/haxelib_src/package.sh delete mode 100644 extra/haxelib_src/prepare.hxml create mode 100644 extra/haxelib_src/prepare_tests.hxml delete mode 100644 extra/haxelib_src/run.bat create mode 100644 extra/haxelib_src/run.n create mode 100644 extra/haxelib_src/server.hxml create mode 100644 extra/haxelib_src/server_api.hxml create mode 100644 extra/haxelib_src/server_each.hxml create mode 100644 extra/haxelib_src/server_legacy.hxml create mode 100644 extra/haxelib_src/server_tasks.hxml create mode 100644 extra/haxelib_src/server_tests.hxml create mode 100644 extra/haxelib_src/server_website.hxml delete mode 100644 extra/haxelib_src/site.bat delete mode 100644 extra/haxelib_src/site.hxml delete mode 100755 extra/haxelib_src/site.sh create mode 100644 extra/haxelib_src/src/Package.hx rename extra/haxelib_src/src/{tools => }/haxelib/Data.hx (66%) rename extra/haxelib_src/src/{tools => }/haxelib/SemVer.hx (50%) rename extra/haxelib_src/src/{tools => }/haxelib/SiteApi.hx (90%) rename extra/haxelib_src/src/{tools => }/haxelib/Validator.hx (63%) create mode 100644 extra/haxelib_src/src/haxelib/client/Cli.hx rename extra/haxelib_src/src/{tools/haxelib => haxelib/client}/ConvertXml.hx (51%) create mode 100644 extra/haxelib_src/src/haxelib/client/FsUtils.hx rename extra/haxelib_src/src/{tools/haxelib => haxelib/client}/Main.hx (50%) create mode 100644 extra/haxelib_src/src/haxelib/client/Vcs.hx create mode 100644 extra/haxelib_src/src/haxelib/server/FileStorage.hx create mode 100644 extra/haxelib_src/src/haxelib/server/Paths.hx create mode 100644 extra/haxelib_src/src/haxelib/server/Repo.hx rename extra/haxelib_src/src/{tools/haxelib => haxelib/server}/SiteDb.hx (77%) rename extra/haxelib_src/src/{tools => }/legacyhaxelib/.htaccess (100%) rename extra/haxelib_src/src/{tools => }/legacyhaxelib/Data.hx (99%) rename extra/haxelib_src/src/{tools => }/legacyhaxelib/Main.hx (99%) rename extra/haxelib_src/src/{tools => }/legacyhaxelib/Site.hx (87%) rename extra/haxelib_src/src/{tools => }/legacyhaxelib/SiteApi.hx (98%) rename extra/haxelib_src/src/{tools => }/legacyhaxelib/SiteDb.hx (99%) rename extra/haxelib_src/src/{tools => }/legacyhaxelib/haxelib.css (100%) rename extra/haxelib_src/src/{tools => }/legacyhaxelib/haxelib.hxml (58%) create mode 100644 extra/haxelib_src/src/legacyhaxelib/haxelib.sh create mode 100644 extra/haxelib_src/src/legacyhaxelib/site.hxml rename extra/haxelib_src/src/{tools => }/legacyhaxelib/website.mtt (100%) delete mode 100644 extra/haxelib_src/src/tools/haxelib/Paths.hx delete mode 100644 extra/haxelib_src/src/tools/haxelib/Rebuild.hx delete mode 100644 extra/haxelib_src/src/tools/haxelib/Repo.hx delete mode 100644 extra/haxelib_src/src/tools/haxelib/Site.hx delete mode 100644 extra/haxelib_src/src/tools/haxelib/Template.hx delete mode 100644 extra/haxelib_src/src/tools/haxelib/Vcs.hx delete mode 100644 extra/haxelib_src/src/tools/haxelib/haxelib.css delete mode 100644 extra/haxelib_src/src/tools/haxelib/tmpl/documentation.mtt delete mode 100644 extra/haxelib_src/src/tools/haxelib/tmpl/error.mtt delete mode 100644 extra/haxelib_src/src/tools/haxelib/tmpl/index.mtt delete mode 100644 extra/haxelib_src/src/tools/haxelib/tmpl/layout.mtt delete mode 100644 extra/haxelib_src/src/tools/haxelib/tmpl/list.mtt delete mode 100644 extra/haxelib_src/src/tools/haxelib/tmpl/project.mtt delete mode 100644 extra/haxelib_src/src/tools/haxelib/tmpl/tag.mtt delete mode 100644 extra/haxelib_src/src/tools/haxelib/tmpl/user.mtt delete mode 100644 extra/haxelib_src/src/tools/legacyhaxelib/haxelib.sh delete mode 100644 extra/haxelib_src/src/tools/legacyhaxelib/site.hxml create mode 100644 extra/haxelib_src/src/website/Server.hx create mode 100644 extra/haxelib_src/src/website/Tasks.hx create mode 100644 extra/haxelib_src/src/website/api/DocumentationApi.hx create mode 100644 extra/haxelib_src/src/website/api/ProjectApi.hx create mode 100644 extra/haxelib_src/src/website/api/ProjectListApi.hx create mode 100644 extra/haxelib_src/src/website/api/UserApi.hx create mode 100644 extra/haxelib_src/src/website/controller/DocumentationController.hx create mode 100644 extra/haxelib_src/src/website/controller/HomeController.hx create mode 100644 extra/haxelib_src/src/website/controller/ProjectController.hx create mode 100644 extra/haxelib_src/src/website/controller/RSSController.hx create mode 100644 extra/haxelib_src/src/website/controller/UserController.hx create mode 100644 extra/haxelib_src/src/website/homepage-example.txt create mode 100644 extra/haxelib_src/src/website/model/SiteDb.hx create mode 100644 extra/haxelib_src/src/website/tasks/HaxelibCacheTasks.hx delete mode 100755 extra/haxelib_src/test.sh create mode 100644 extra/haxelib_src/test/IntegrationTests.hx create mode 100644 extra/haxelib_src/test/Prepare.hx create mode 100644 extra/haxelib_src/test/RunCi.hx create mode 100644 extra/haxelib_src/test/TestBase.hx create mode 100644 extra/haxelib_src/test/WebsiteTests.hx create mode 100644 extra/haxelib_src/test/docker-compose-dev.yml create mode 100644 extra/haxelib_src/test/docker-compose.yml create mode 100644 extra/haxelib_src/test/libraries/UseCp/haxelib.json rename extra/haxelib_src/{testing/libraries/libBar => test/libraries/UseCp/lib/src}/bar/Bar.hx (100%) rename extra/haxelib_src/{testing/libraries/libFoo => test/libraries/UseGitDep}/foo/Foo.hx (100%) create mode 100644 extra/haxelib_src/test/libraries/UseGitDep/haxelib.json create mode 100644 extra/haxelib_src/test/libraries/UseGitDep/haxelib.xml create mode 100644 extra/haxelib_src/test/libraries/UseGitDep/tag_haxelib.json create mode 100644 extra/haxelib_src/test/libraries/libBar/bar/Bar.hx rename extra/haxelib_src/{testing => test}/libraries/libBar/haxelib.json (100%) rename extra/haxelib_src/{testing => test}/libraries/libBar/haxelib.xml (100%) create mode 100644 extra/haxelib_src/test/libraries/libBar2/bar/Bar.hx create mode 100644 extra/haxelib_src/test/libraries/libBar2/haxelib.json create mode 100644 extra/haxelib_src/test/libraries/libBar2/haxelib.xml create mode 100644 extra/haxelib_src/test/libraries/libFoo/foo/Foo.hx rename extra/haxelib_src/{testing => test}/libraries/libFoo/haxelib.json (95%) rename extra/haxelib_src/{testing => test}/libraries/libFoo/haxelib.xml (100%) delete mode 100644 extra/haxelib_src/test/tests/TestCli.hx create mode 100644 extra/haxelib_src/test/tests/TestGit.hx create mode 100644 extra/haxelib_src/test/tests/TestHg.hx create mode 100644 extra/haxelib_src/test/tests/TestInstall.hx create mode 100644 extra/haxelib_src/test/tests/TestRemoveSymlinksBroken.hx create mode 100644 extra/haxelib_src/test/tests/integration/TestDev.hx create mode 100644 extra/haxelib_src/test/tests/integration/TestEmpty.hx create mode 100644 extra/haxelib_src/test/tests/integration/TestInfo.hx create mode 100644 extra/haxelib_src/test/tests/integration/TestList.hx create mode 100644 extra/haxelib_src/test/tests/integration/TestSet.hx create mode 100644 extra/haxelib_src/test/tests/integration/TestSimple.hx create mode 100644 extra/haxelib_src/test/tests/integration/TestUpdate.hx create mode 100644 extra/haxelib_src/test/tests/integration/TestUpgrade.hx create mode 100644 extra/haxelib_src/test/tests/integration/TestUser.hx create mode 100644 extra/haxelib_src/test/website/controller/DocumentationControllerTest.hx create mode 100644 extra/haxelib_src/test/website/controller/HomeControllerTest.hx create mode 100644 extra/haxelib_src/test/website/controller/ProjectControllerTest.hx create mode 100644 extra/haxelib_src/test/website/controller/RSSControllerTest.hx create mode 100644 extra/haxelib_src/test/website/controller/UserControllerTest.hx delete mode 100644 extra/haxelib_src/testing/PrepareServer.hx delete mode 100644 extra/haxelib_src/testing/installSeveral.hxml rename extra/haxelib_src/{src/tools/haxelib => www}/.htaccess (67%) create mode 100644 extra/haxelib_src/www/bower.json create mode 100644 extra/haxelib_src/www/css/haxelib.css create mode 100644 extra/haxelib_src/www/css/style.css rename extra/haxelib_src/{src/tools/haxelib/dbconfig.json.example => www/dbconfig.json} (69%) create mode 100644 extra/haxelib_src/www/documentation-files/api.md create mode 100644 extra/haxelib_src/www/documentation-files/creating-a-haxelib-package.md create mode 100644 extra/haxelib_src/www/documentation-files/faq.md create mode 100644 extra/haxelib_src/www/documentation-files/index.md create mode 100644 extra/haxelib_src/www/documentation-files/installation.md create mode 100644 extra/haxelib_src/www/documentation-files/per-project-setup.md create mode 100644 extra/haxelib_src/www/documentation-files/tips-and-tricks.md create mode 100644 extra/haxelib_src/www/documentation-files/using-haxelib.md create mode 100644 extra/haxelib_src/www/favicon.ico create mode 100644 extra/haxelib_src/www/img/glyphicons-halflings-white.png create mode 100644 extra/haxelib_src/www/img/glyphicons-halflings.png create mode 100644 extra/haxelib_src/www/img/haxe-logo-horizontal-on-dark.png create mode 100644 extra/haxelib_src/www/img/haxe-logo-horizontal-on-dark.svg create mode 100644 extra/haxelib_src/www/img/haxe-logo-horizontal.svg create mode 100644 extra/haxelib_src/www/img/haxe-logo-vertical.svg create mode 100644 extra/haxelib_src/www/img/haxe-logo.png create mode 100644 extra/haxelib_src/www/img/haxe-logo.svg create mode 100644 extra/haxelib_src/www/img/homepage_banner.jpg create mode 100644 extra/haxelib_src/www/img/logo_small.png create mode 100644 extra/haxelib_src/www/robots.txt create mode 100644 extra/haxelib_src/www/view/documentation/documentationPage.html create mode 100644 extra/haxelib_src/www/view/home/homepage.html create mode 100644 extra/haxelib_src/www/view/home/projectList.html create mode 100644 extra/haxelib_src/www/view/home/search.html create mode 100644 extra/haxelib_src/www/view/home/tagList.html create mode 100644 extra/haxelib_src/www/view/layout.html create mode 100644 extra/haxelib_src/www/view/project/docs.html create mode 100644 extra/haxelib_src/www/view/project/file.html create mode 100644 extra/haxelib_src/www/view/project/version.html create mode 100644 extra/haxelib_src/www/view/project/versionList.html create mode 100644 extra/haxelib_src/www/view/user/list.html create mode 100644 extra/haxelib_src/www/view/user/profile.html delete mode 100644 gencpp.ml create mode 100755 libs/.editorconfig create mode 100644 libs/.travis.yml create mode 100644 libs/README.md delete mode 100644 libs/extc/zlib/README.txt delete mode 100644 libs/extc/zlib/zconf.h delete mode 100644 libs/extc/zlib/zlib.h delete mode 100644 libs/extc/zlib/zlib.lib mode change 100755 => 100644 libs/extlib/extList.ml create mode 100644 libs/extlib/sMap.ml create mode 100644 libs/extlib/sMap.mli create mode 100644 libs/pcre/Makefile create mode 100644 libs/pcre/pcre.ml create mode 100644 libs/pcre/pcre_stubs.c delete mode 100644 main.ml delete mode 100644 matcher.ml create mode 100644 src/context/common.ml create mode 100644 src/context/meta.ml create mode 100644 src/display/display.ml create mode 100644 src/display/displayOutput.ml create mode 100644 src/display/displayTypes.ml create mode 100644 src/generators/codegen.ml rename genas3.ml => src/generators/genas3.ml (90%) rename gencommon.ml => src/generators/gencommon.ml (72%) create mode 100644 src/generators/gencpp.ml rename gencs.ml => src/generators/gencs.ml (90%) create mode 100644 src/generators/genhl.ml rename genjava.ml => src/generators/genjava.ml (92%) rename genjs.ml => src/generators/genjs.ml (80%) create mode 100644 src/generators/genlua.ml rename genneko.ml => src/generators/genneko.ml (95%) rename genphp.ml => src/generators/genphp.ml (91%) create mode 100644 src/generators/genphp7.ml rename genpy.ml => src/generators/genpy.ml (86%) rename genswf.ml => src/generators/genswf.ml (90%) rename genswf9.ml => src/generators/genswf9.ml (95%) rename genxml.ml => src/generators/genxml.ml (91%) create mode 100644 src/generators/hl2c.ml create mode 100644 src/generators/hlcode.ml create mode 100644 src/generators/hlinterp.ml create mode 100644 src/generators/hlopt.ml create mode 100644 src/globals.ml create mode 100644 src/json.ml create mode 100644 src/macro/hlmacro.ml rename interp.ml => src/macro/interp.ml (50%) create mode 100644 src/macro/macroApi.ml create mode 100644 src/macro/macroContext.ml create mode 100644 src/main.ml create mode 100644 src/optimization/analyzer.ml create mode 100644 src/optimization/analyzerConfig.ml create mode 100644 src/optimization/analyzerTexpr.ml create mode 100644 src/optimization/analyzerTexprTransformer.ml create mode 100644 src/optimization/analyzerTypes.ml rename dce.ml => src/optimization/dce.ml (76%) rename filters.ml => src/optimization/filters.ml (70%) rename optimizer.ml => src/optimization/optimizer.ml (67%) create mode 100644 src/optimization/optimizerTexpr.ml create mode 100644 src/path.ml create mode 100644 src/server.ml create mode 100644 src/syntax/ast.ml rename lexer.mll => src/syntax/lexer.mll (85%) rename parser.ml => src/syntax/parser.ml (70%) create mode 100644 src/typing/abstract.ml create mode 100644 src/typing/error.ml create mode 100644 src/typing/matcher.ml create mode 100644 src/typing/overloads.ml rename type.ml => src/typing/type.ml (65%) create mode 100644 src/typing/typecore.ml create mode 100644 src/typing/typeload.ml rename typer.ml => src/typing/typer.ml (58%) create mode 100644 std/Any.hx create mode 100644 std/cpp/AtomicInt.hx create mode 100644 std/cpp/AutoCast.hx create mode 100644 std/cpp/EnumBase.hx rename std/{js/html/Point.hx => cpp/FILE.hx} (85%) create mode 100644 std/cpp/Finalizable.hx create mode 100644 std/cpp/NativeArc.hx create mode 100644 std/cpp/NativeFile.hx create mode 100644 std/cpp/NativeGc.hx create mode 100644 std/cpp/NativeMath.hx create mode 100644 std/cpp/NativeProcess.hx create mode 100644 std/cpp/NativeRandom.hx create mode 100644 std/cpp/NativeSocket.hx create mode 100644 std/cpp/NativeSsl.hx create mode 100644 std/cpp/NativeSys.hx create mode 100644 std/cpp/NativeXmlImport.cpp create mode 100644 std/cpp/ObjectType.hx rename std/{js/html/BarInfo.hx => cpp/Reference.hx} (85%) create mode 100644 std/cpp/SizeT.hx rename std/{js/html/DOMWindow.hx => cpp/Star.hx} (85%) create mode 100644 std/cpp/StdString.hx create mode 100644 std/cpp/StdStringRef.hx create mode 100644 std/cpp/Stdio.hx create mode 100644 std/cpp/Stdlib.hx create mode 100644 std/cpp/VarArg.hx create mode 100644 std/cpp/VirtualArray.hx create mode 100644 std/cpp/_std/sys/net/UdpSocket.hx create mode 100644 std/cpp/_std/sys/ssl/Certificate.hx create mode 100644 std/cpp/_std/sys/ssl/Digest.hx create mode 100644 std/cpp/_std/sys/ssl/Key.hx create mode 100644 std/cpp/_std/sys/ssl/Socket.hx create mode 100644 std/cpp/cppia/Module.hx create mode 100644 std/cpp/objc/NSData.hx create mode 100644 std/cpp/objc/NSDictionary.hx rename std/{js/html/DOMPlugin.hx => cpp/objc/NSError.hx} (85%) create mode 100644 std/cpp/objc/NSLog.hx create mode 100644 std/cpp/objc/NSObject.hx create mode 100644 std/cpp/objc/NSString.hx create mode 100644 std/cpp/objc/ObjcBlock.hx create mode 100644 std/cpp/objc/Protocol.hx create mode 100644 std/flash/display/AVLoader.hx create mode 100644 std/flash/net/drm/DRMStoreVoucherContext.hx create mode 100644 std/flash/profiler/Telemetry.hx create mode 100644 std/haxe/EntryPoint.hx create mode 100644 std/haxe/Int64Helper.hx create mode 100644 std/haxe/MainLoop.hx create mode 100644 std/haxe/extern/AsVar.hx create mode 100644 std/haxe/macro/CompilationServer.hx create mode 100644 std/haxe/macro/Context.hl.hx create mode 100644 std/hl/Abstract.hx create mode 100644 std/hl/Api.hx create mode 100644 std/hl/BaseType.hx create mode 100644 std/hl/Boot.hx create mode 100644 std/hl/Bytes.hx create mode 100644 std/hl/BytesAccess.hx create mode 100644 std/hl/F32.hx create mode 100644 std/hl/F64.hx create mode 100644 std/hl/Format.hx create mode 100644 std/hl/Gc.hx create mode 100644 std/hl/NativeArray.hx create mode 100644 std/hl/Ref.hx create mode 100644 std/hl/Type.hx create mode 100644 std/hl/UI.hx create mode 100644 std/hl/UI16.hx create mode 100644 std/hl/UI8.hx create mode 100644 std/hl/_std/Date.hx create mode 100644 std/hl/_std/EReg.hx create mode 100644 std/hl/_std/Math.hx create mode 100644 std/hl/_std/Reflect.hx create mode 100644 std/hl/_std/Std.hx create mode 100644 std/hl/_std/String.hx create mode 100644 std/hl/_std/StringBuf.hx create mode 100644 std/hl/_std/Sys.hx create mode 100644 std/hl/_std/Type.hx create mode 100644 std/hl/_std/UInt.hx create mode 100644 std/hl/_std/haxe/Resource.hx rename std/{js/html/webgl/CompressedTextureS3TC.hx => hl/_std/haxe/ds/IntMap.hx} (50%) create mode 100644 std/hl/_std/haxe/ds/ObjectMap.hx create mode 100644 std/hl/_std/haxe/ds/StringMap.hx create mode 100644 std/hl/_std/haxe/ds/Vector.hx create mode 100644 std/hl/_std/haxe/io/Bytes.hx create mode 100644 std/hl/_std/haxe/io/BytesBuffer.hx create mode 100644 std/hl/_std/haxe/io/FPHelper.hx create mode 100644 std/hl/_std/haxe/zip/Compress.hx create mode 100644 std/hl/_std/haxe/zip/Uncompress.hx create mode 100644 std/hl/_std/sys/FileSystem.hx create mode 100644 std/hl/_std/sys/db/Sqlite.hx create mode 100644 std/hl/_std/sys/io/File.hx create mode 100644 std/hl/_std/sys/io/FileInput.hx create mode 100644 std/hl/_std/sys/io/FileOutput.hx create mode 100644 std/hl/_std/sys/io/Process.hx create mode 100644 std/hl/_std/sys/net/Host.hx create mode 100644 std/hl/_std/sys/net/Socket.hx create mode 100644 std/hl/_std/sys/ssl/Certificate.hx create mode 100644 std/hl/_std/sys/ssl/Digest.hx create mode 100644 std/hl/_std/sys/ssl/Key.hx create mode 100644 std/hl/_std/sys/ssl/Lib.hx create mode 100644 std/hl/_std/sys/ssl/Socket.hx create mode 100644 std/hl/types/ArrayBase.hx create mode 100644 std/hl/types/ArrayBytes.hx create mode 100644 std/hl/types/ArrayDyn.hx create mode 100644 std/hl/types/ArrayObj.hx create mode 100644 std/hl/types/BytesMap.hx create mode 100644 std/hl/types/IntMap.hx create mode 100644 std/hl/types/ObjectMap.hx mode change 100755 => 100644 std/js/Boot.hx mode change 100755 => 100644 std/js/_std/Type.hx create mode 100644 std/js/html/AnimationEffectReadOnly.hx create mode 100644 std/js/html/AnimationEffectTiming.hx rename std/js/html/{AnimationPlayer.hx => AnimationEffectTimingProperties.hx} (69%) create mode 100644 std/js/html/AnimationEffectTimingReadOnly.hx create mode 100644 std/js/html/AudioContextState.hx create mode 100644 std/js/html/BroadcastChannel.hx rename std/js/html/{ServiceWorkerClient.hx => CSSAnimation.hx} (82%) rename std/js/html/{MediaEncryptedEvent.hx => CSSPseudoElement.hx} (71%) create mode 100644 std/js/html/CSSTransition.hx create mode 100644 std/js/html/Client.hx create mode 100644 std/js/html/ClientQueryOptions.hx create mode 100644 std/js/html/Clients.hx create mode 100644 std/js/html/CompositeOperation.hx rename std/js/html/{CreateFileOptions.hx => ComputedTimingProperties.hx} (74%) delete mode 100644 std/js/html/DOMApplicationCache.hx delete mode 100644 std/js/html/DOMCoreException.hx delete mode 100644 std/js/html/DOMMimeType.hx delete mode 100644 std/js/html/DOMMimeTypeArray.hx delete mode 100644 std/js/html/DOMPluginArray.hx delete mode 100644 std/js/html/DOMSelection.hx create mode 100644 std/js/html/DocumentTimeline.hx rename std/js/html/{ClientRectList.hx => DragEventInit.hx} (84%) create mode 100644 std/js/html/EventModifierInit.hx create mode 100644 std/js/html/ExtendableEvent.hx rename std/js/html/{DOMURL.hx => ExtendableEventInit.hx} (86%) create mode 100644 std/js/html/ExtendableMessageEvent.hx create mode 100644 std/js/html/ExtendableMessageEventInit.hx create mode 100644 std/js/html/FetchEvent.hx rename std/js/html/{MediaKeyNeededEventInit.hx => FetchEventInit.hx} (81%) create mode 100644 std/js/html/FillMode.hx create mode 100644 std/js/html/FontFaceSetIterator.hx rename std/js/html/{GetNotificationOptions.hx => FontFaceSetIteratorResult.hx} (85%) create mode 100644 std/js/html/FormDataIterator.hx rename std/js/html/{MediaWaitingFor.hx => FrameType.hx} (83%) create mode 100644 std/js/html/Headers.hx rename std/js/html/{SessionType.hx => HeadersIterator.hx} (83%) create mode 100644 std/js/html/ImageBitmap.hx create mode 100644 std/js/html/ImageBitmapRenderingContext.hx create mode 100644 std/js/html/IterationCompositeOperation.hx create mode 100644 std/js/html/KeyframeEffect.hx create mode 100644 std/js/html/KeyframeEffectReadOnly.hx delete mode 100644 std/js/html/MediaKeyMessageEventInit.hx delete mode 100644 std/js/html/MediaKeyMessageType.hx delete mode 100644 std/js/html/MediaKeySession.hx create mode 100644 std/js/html/MediaKeyStatusMapIterator.hx delete mode 100644 std/js/html/MediaKeySystemAccess.hx delete mode 100644 std/js/html/MediaKeySystemOptions.hx create mode 100644 std/js/html/MediaTrackConstraintSet.hx create mode 100644 std/js/html/MediaTrackConstraints.hx create mode 100644 std/js/html/MessageChannel.hx rename std/js/html/{ServiceWorkerClients.hx => NotificationEvent.hx} (77%) create mode 100644 std/js/html/NotificationEventInit.hx create mode 100644 std/js/html/OrientationLockType.hx create mode 100644 std/js/html/OrientationType.hx create mode 100644 std/js/html/PerformanceMark.hx create mode 100644 std/js/html/PerformanceMeasure.hx rename std/js/html/{MediaKeyError.hx => PermissionState.hx} (82%) create mode 100644 std/js/html/PermissionStatus.hx create mode 100644 std/js/html/Permissions.hx create mode 100644 std/js/html/PlaybackDirection.hx create mode 100644 std/js/html/ReferrerPolicy.hx create mode 100644 std/js/html/Request.hx create mode 100644 std/js/html/RequestCache.hx create mode 100644 std/js/html/RequestCredentials.hx create mode 100644 std/js/html/RequestInit.hx create mode 100644 std/js/html/RequestMode.hx rename std/js/html/{AnimationEffect.hx => RequestRedirect.hx} (83%) create mode 100644 std/js/html/Response.hx create mode 100644 std/js/html/ResponseInit.hx create mode 100644 std/js/html/ResponseType.hx rename std/js/html/{MediaKeyMessageEvent.hx => ScreenOrientation.hx} (71%) rename std/js/html/{CSSMatrix.hx => ScrollRestoration.hx} (84%) create mode 100644 std/js/html/ServiceWorker.hx create mode 100644 std/js/html/ServiceWorkerRegistration.hx create mode 100644 std/js/html/ServiceWorkerState.hx delete mode 100644 std/js/html/SpeechInputEvent.hx delete mode 100644 std/js/html/SpeechInputResult.hx delete mode 100644 std/js/html/SpeechInputResultList.hx create mode 100644 std/js/html/SpeechSynthesisErrorCode.hx create mode 100644 std/js/html/SpeechSynthesisErrorEvent.hx create mode 100644 std/js/html/SpeechSynthesisErrorEventInit.hx create mode 100644 std/js/html/TouchEventInit.hx create mode 100644 std/js/html/TouchInit.hx rename std/js/html/{DOMSettableTokenList.hx => URLSearchParamsIterator.hx} (81%) create mode 100644 std/js/html/UncaughtRejectionObserver.hx create mode 100644 std/js/html/WindowClient.hx rename std/js/html/{MediaKeys.hx => WorkerDebuggerGlobalScope.hx} (58%) rename std/js/html/{ClientRect.hx => rtc/AnswerOptions.hx} (84%) create mode 100644 std/js/html/rtc/Certificate.hx create mode 100644 std/js/html/rtc/IdentityAssertionResult.hx create mode 100644 std/js/html/rtc/IdentityProvider.hx create mode 100644 std/js/html/rtc/IdentityProviderRegistrar.hx rename std/js/html/{webgl/VertexArray.hx => rtc/IdentityValidationResult.hx} (82%) create mode 100644 std/js/html/rtc/OfferAnswerOptions.hx create mode 100644 std/js/html/rtc/RtpParameters.hx delete mode 100644 std/js/html/svg/IFrameElement.hx delete mode 100644 std/js/html/webgl/DebugRendererInfo.hx delete mode 100644 std/js/html/webgl/DebugShaders.hx delete mode 100644 std/js/html/webgl/DepthTexture.hx delete mode 100644 std/js/html/webgl/EXTTextureFilterAnisotropic.hx create mode 100644 std/js/html/webgl/ExtensionCompressedTextureES3.hx create mode 100644 std/js/html/webgl/ExtensionDisjointTimerQuery.hx create mode 100644 std/js/html/webgl/ExtensionVertexArrayObject.hx delete mode 100644 std/js/html/webgl/LoseContext.hx delete mode 100644 std/js/html/webgl/OESStandardDerivatives.hx delete mode 100644 std/js/html/webgl/OESTextureFloat.hx delete mode 100644 std/js/html/webgl/OESVertexArrayObject.hx rename std/js/html/webgl/{ExtensionVertexArray.hx => TimerQueryEXT.hx} (61%) create mode 100644 std/js/jquery/Callbacks.hx create mode 100644 std/js/jquery/Deferred.hx create mode 100644 std/js/jquery/Event.hx create mode 100644 std/js/jquery/Helper.hx create mode 100644 std/js/jquery/JQuery.hx create mode 100644 std/js/jquery/JqEltsIterator.hx create mode 100644 std/js/jquery/JqIterator.hx create mode 100644 std/js/jquery/JqXHR.hx create mode 100644 std/js/jquery/Promise.hx create mode 100644 std/js/swfobject/SWFObject.hx create mode 100644 std/lua/Bit.hx create mode 100644 std/lua/Boot.hx create mode 100644 std/lua/Coroutine.hx create mode 100644 std/lua/Debug.hx create mode 100644 std/lua/Ffi.hx create mode 100644 std/lua/FileHandle.hx create mode 100644 std/lua/HaxeIterator.hx create mode 100644 std/lua/Io.hx create mode 100644 std/lua/Jit.hx create mode 100644 std/lua/Lib.hx create mode 100644 std/lua/LocaleCategory.hx create mode 100644 std/lua/Lua.hx create mode 100644 std/lua/Map.hx create mode 100644 std/lua/Math.hx create mode 100644 std/lua/NativeIterator.hx create mode 100644 std/lua/NativeStringTools.hx create mode 100644 std/lua/Os.hx create mode 100644 std/lua/Package.hx create mode 100644 std/lua/PairTools.hx create mode 100644 std/lua/Result.hx create mode 100644 std/lua/Table.hx create mode 100644 std/lua/TableTools.hx create mode 100644 std/lua/Thread.hx create mode 100644 std/lua/Time.hx create mode 100644 std/lua/UserData.hx create mode 100644 std/lua/_lua/_hx_anon.lua create mode 100644 std/lua/_lua/_hx_apply.lua create mode 100644 std/lua/_lua/_hx_classes.lua create mode 100644 std/lua/_lua/_hx_tab_array.lua create mode 100644 std/lua/_std/Array.hx create mode 100644 std/lua/_std/Date.hx create mode 100644 std/lua/_std/EReg.hx create mode 100644 std/lua/_std/Math.hx create mode 100644 std/lua/_std/Reflect.hx create mode 100644 std/lua/_std/Std.hx create mode 100644 std/lua/_std/String.hx create mode 100644 std/lua/_std/StringBuf.hx create mode 100644 std/lua/_std/Sys.hx create mode 100644 std/lua/_std/Type.hx create mode 100644 std/lua/_std/haxe/Json.hx create mode 100644 std/lua/_std/haxe/Utf8.hx create mode 100644 std/lua/_std/haxe/ds/IntMap.hx create mode 100644 std/lua/_std/haxe/ds/ObjectMap.hx create mode 100644 std/lua/_std/haxe/ds/StringMap.hx create mode 100644 std/lua/_std/sys/FileSystem.hx create mode 100644 std/lua/_std/sys/io/File.hx create mode 100644 std/lua/_std/sys/io/FileInput.hx create mode 100644 std/lua/_std/sys/io/FileOutput.hx create mode 100644 std/lua/_std/sys/io/Process.hx create mode 100644 std/lua/lib/environ/Environ.hx create mode 100644 std/lua/lib/lrexlib/Rex.hx rename std/{js/html/DOMFormData.hx => lua/lib/luasocket/Socket.hx} (84%) create mode 100644 std/lua/lib/luv/Async.hx create mode 100644 std/lua/lib/luv/Check.hx create mode 100644 std/lua/lib/luv/Handle.hx create mode 100644 std/lua/lib/luv/Idle.hx create mode 100644 std/lua/lib/luv/Loop.hx create mode 100644 std/lua/lib/luv/Misc.hx create mode 100644 std/lua/lib/luv/Pipe.hx create mode 100644 std/lua/lib/luv/Poll.hx create mode 100644 std/lua/lib/luv/Prepare.hx create mode 100644 std/lua/lib/luv/Process.hx create mode 100644 std/lua/lib/luv/Request.hx create mode 100644 std/lua/lib/luv/Signal.hx create mode 100644 std/lua/lib/luv/Stream.hx create mode 100644 std/lua/lib/luv/Thread.hx create mode 100644 std/lua/lib/luv/Timer.hx create mode 100644 std/lua/lib/luv/Tty.hx create mode 100644 std/lua/lib/luv/Work.hx create mode 100644 std/lua/lib/luv/fs/FileDescriptor.hx create mode 100644 std/lua/lib/luv/fs/FileSystem.hx create mode 100644 std/lua/lib/luv/fs/FileSystemEvent.hx create mode 100644 std/lua/lib/luv/fs/FileSystemPoll.hx create mode 100644 std/lua/lib/luv/fs/Open.hx create mode 100644 std/lua/lib/luv/net/Dns.hx create mode 100644 std/lua/lib/luv/net/Tcp.hx create mode 100644 std/lua/lib/luv/net/Udp.hx create mode 100644 std/neko/_std/sys/ssl/Certificate.hx create mode 100644 std/neko/_std/sys/ssl/Digest.hx create mode 100644 std/neko/_std/sys/ssl/Key.hx create mode 100644 std/neko/_std/sys/ssl/Socket.hx create mode 100644 std/php/BytesData.hx mode change 100755 => 100644 std/php/_std/haxe/ds/StringMap.hx create mode 100644 std/php/_std/haxe/zip/Compress.hx create mode 100644 std/php/_std/haxe/zip/Uncompress.hx create mode 100644 std/php7/ArrayAccess.hx create mode 100644 std/php7/Boot.hx create mode 100644 std/php7/Closure.hx create mode 100644 std/php7/Const.hx create mode 100644 std/php7/Error.hx create mode 100644 std/php7/ErrorException.hx create mode 100644 std/php7/Exception.hx create mode 100644 std/php7/Global.hx rename std/{js/html/Clipboard.hx => php7/IteratorAggregate.hx} (76%) create mode 100644 std/php7/Lib.hx create mode 100644 std/php7/NativeArray.hx create mode 100644 std/php7/NativeAssocArray.hx create mode 100644 std/php7/NativeIndexedArray.hx create mode 100644 std/php7/NativeString.hx create mode 100644 std/php7/Ref.hx create mode 100644 std/php7/Resource.hx create mode 100644 std/php7/RuntimeException.hx create mode 100644 std/php7/Scalar.hx create mode 100644 std/php7/Session.hx create mode 100644 std/php7/SessionHandlerInterface.hx create mode 100644 std/php7/StdClass.hx create mode 100644 std/php7/SuperGlobal.hx create mode 100644 std/php7/Syntax.hx create mode 100644 std/php7/Throwable.hx create mode 100644 std/php7/Traversable.hx create mode 100644 std/php7/Web.hx create mode 100644 std/php7/_std/Array.hx create mode 100644 std/php7/_std/Date.hx create mode 100644 std/php7/_std/EReg.hx create mode 100644 std/php7/_std/Math.hx create mode 100644 std/php7/_std/Reflect.hx create mode 100644 std/php7/_std/Std.hx create mode 100644 std/php7/_std/StringBuf.hx create mode 100644 std/php7/_std/StringTools.hx create mode 100644 std/php7/_std/Sys.hx create mode 100644 std/php7/_std/Type.hx create mode 100644 std/php7/_std/haxe/CallStack.hx create mode 100644 std/php7/_std/haxe/Json.hx create mode 100644 std/php7/_std/haxe/Resource.hx create mode 100644 std/php7/_std/haxe/Utf8.hx create mode 100644 std/php7/_std/haxe/crypto/Md5.hx create mode 100644 std/php7/_std/haxe/crypto/Sha1.hx create mode 100644 std/php7/_std/haxe/crypto/Sha224.hx create mode 100644 std/php7/_std/haxe/crypto/Sha256.hx create mode 100644 std/php7/_std/haxe/ds/IntMap.hx create mode 100644 std/php7/_std/haxe/ds/ObjectMap.hx create mode 100644 std/php7/_std/haxe/ds/StringMap.hx create mode 100644 std/php7/_std/haxe/io/Bytes.hx create mode 100644 std/php7/_std/haxe/io/BytesBuffer.hx create mode 100644 std/php7/_std/haxe/io/BytesData.hx create mode 100644 std/php7/_std/haxe/io/BytesInput.hx create mode 100644 std/php7/_std/haxe/io/BytesOutput.hx create mode 100644 std/php7/_std/haxe/io/FPHelper.hx create mode 100644 std/php7/_std/haxe/zip/Compress.hx create mode 100644 std/php7/_std/haxe/zip/Uncompress.hx create mode 100644 std/php7/_std/sys/FileSystem.hx create mode 100644 std/php7/_std/sys/db/Mysql.hx create mode 100644 std/php7/_std/sys/db/Sqlite.hx create mode 100644 std/php7/_std/sys/io/File.hx create mode 100644 std/php7/_std/sys/io/FileInput.hx create mode 100644 std/php7/_std/sys/io/FileOutput.hx create mode 100644 std/php7/_std/sys/io/Process.hx create mode 100644 std/php7/_std/sys/net/Host.hx create mode 100644 std/php7/_std/sys/net/Socket.hx create mode 100644 std/php7/db/Mysqli.hx create mode 100644 std/php7/db/Mysqli_driver.hx create mode 100644 std/php7/db/Mysqli_result.hx create mode 100644 std/php7/db/Mysqli_stmt.hx create mode 100644 std/php7/db/Mysqli_warning.hx create mode 100644 std/php7/db/PDO.hx create mode 100644 std/php7/db/PDOException.hx create mode 100644 std/php7/db/PDOStatement.hx create mode 100644 std/php7/db/SQLite3.hx create mode 100644 std/php7/db/SQLite3Result.hx create mode 100644 std/php7/db/SQLite3Stmt.hx create mode 100644 std/php7/net/SslSocket.hx create mode 100644 std/php7/reflection/ReflectionClass.hx create mode 100644 std/php7/reflection/ReflectionFunctionAbstract.hx create mode 100644 std/php7/reflection/ReflectionMethod.hx create mode 100644 std/php7/reflection/ReflectionProperty.hx create mode 100644 std/php7/reflection/Reflector.hx create mode 100644 std/python/lib/Threading.hx create mode 100644 std/python/lib/Timeit.hx create mode 100644 std/python/lib/threading/Lock.hx create mode 100644 std/python/lib/threading/RLock.hx create mode 100644 std/python/lib/time/StructTime.hx create mode 100644 std/sys/ssl/Certificate.hx create mode 100644 std/sys/ssl/Digest.hx create mode 100644 std/sys/ssl/DigestAlgorithm.hx create mode 100644 std/sys/ssl/Key.hx create mode 100644 std/sys/ssl/Socket.hx create mode 100644 tests/TestMakefile.hx create mode 100644 tests/TestMakefile.hxml create mode 100644 tests/benchs/mandelbrot/Mandelbrot.hx create mode 100644 tests/benchs/mandelbrot/Readme.md create mode 100644 tests/benchs/mandelbrot/compile-cpp.hxml create mode 100644 tests/benchs/mandelbrot/compile-cppia.hxml create mode 100644 tests/benchs/mandelbrot/compile-java.hxml create mode 100644 tests/benchs/mandelbrot/compile-js.hxml create mode 100644 tests/benchs/mandelbrot/compile-neko.hxml create mode 100644 tests/benchs/mandelbrot/compile-php.hxml rename tests/benchs/{ => mtnetwork}/MTNetwork.hx (100%) create mode 100644 tests/display/build.hxml create mode 100644 tests/display/src/DisplayTestCase.hx create mode 100644 tests/display/src/DisplayTestContext.hx create mode 100644 tests/display/src/File.hx create mode 100644 tests/display/src/Macro.hx create mode 100644 tests/display/src/Main.hx create mode 100644 tests/display/src/ModuleSymbolEntry.hx create mode 100644 tests/display/src/SignatureHelp.hx create mode 100644 tests/display/src/Types.hx create mode 100644 tests/display/src/cases/Abstract.hx create mode 100644 tests/display/src/cases/Basic.hx create mode 100644 tests/display/src/cases/BuildMacro.hx create mode 100644 tests/display/src/cases/Completion.hx create mode 100644 tests/display/src/cases/DocumentSymbols.hx create mode 100644 tests/display/src/cases/IImport.hx create mode 100644 tests/display/src/cases/Issue5141.hx create mode 100644 tests/display/src/cases/Issue5166.hx create mode 100644 tests/display/src/cases/Issue5171.hx create mode 100644 tests/display/src/cases/Issue5172.hx create mode 100644 tests/display/src/cases/Issue5173.hx create mode 100644 tests/display/src/cases/Issue5684.hx create mode 100644 tests/display/src/cases/Issue5712.hx create mode 100644 tests/display/src/cases/Issue5729.hx create mode 100644 tests/display/src/cases/Issue5775.hx create mode 100644 tests/display/src/cases/Issue5796.hx create mode 100644 tests/display/src/cases/Metadata.hx create mode 100644 tests/display/src/cases/PropertyAccessors.hx create mode 100644 tests/display/src/cases/Signature.hx create mode 100644 tests/display/src/cases/StructureCompletion.hx create mode 100644 tests/display/src/cases/Super.hx create mode 100644 tests/display/src/cases/Toplevel.hx create mode 100644 tests/display/src/cases/Type.hx create mode 100644 tests/misc/cppObjc/TestObjc.hx create mode 100644 tests/misc/cppObjc/build.hxml create mode 100644 tests/misc/cppObjc/native/Makefile create mode 100644 tests/misc/cppObjc/native/include/test.h create mode 100644 tests/misc/cppObjc/native/test.m create mode 100644 tests/misc/eventLoop/Main.hx create mode 100644 tests/misc/eventLoop/all.hxml rename extra/haxelib_src/src/tools/legacyhaxelib/haxelib.hxproj => tests/misc/eventLoop/eventLoop.hxproj (72%) create mode 100644 tests/misc/eventLoop/test.html create mode 100644 tests/misc/projects/Issue1138/compile1.hxml create mode 100644 tests/misc/projects/Issue1138/compile1.hxml.stderr create mode 100644 tests/misc/projects/Issue1138/compile2.hxml create mode 100644 tests/misc/projects/Issue1138/compile2.hxml.stderr create mode 100644 tests/misc/projects/Issue1138/compile3-fail.hxml create mode 100644 tests/misc/projects/Issue1138/compile3-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue1138/compile4-fail.hxml create mode 100644 tests/misc/projects/Issue1138/compile4-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue1138/src1/C.hx create mode 100644 tests/misc/projects/Issue1138/src1/D.hx create mode 100644 tests/misc/projects/Issue1138/src1/import.hx create mode 100644 tests/misc/projects/Issue1138/src1/p2/C2.hx create mode 100644 tests/misc/projects/Issue1138/src1/p2/import.hx create mode 100644 tests/misc/projects/Issue1138/src2/B.hx create mode 100644 tests/misc/projects/Issue1138/src2/import.hx create mode 100644 tests/misc/projects/Issue1138/src2/p2/A.hx create mode 100644 tests/misc/projects/Issue1138/src3/Main.hx create mode 100644 tests/misc/projects/Issue1138/src3/import.hx create mode 100644 tests/misc/projects/Issue1310/Main1.hx create mode 100644 tests/misc/projects/Issue1310/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue1310/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue2087/Main.hx rename tests/misc/projects/{Issue3782 => Issue2087}/compile-fail.hxml (100%) create mode 100644 tests/misc/projects/Issue2087/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue2148/Main1.hx create mode 100644 tests/misc/projects/Issue2148/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue2148/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue2232/Main1.hx create mode 100644 tests/misc/projects/Issue2232/Main2.hx create mode 100644 tests/misc/projects/Issue2232/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue2232/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue2232/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue2232/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue2278/Macro.hx create mode 100644 tests/misc/projects/Issue2278/Main.hx create mode 100644 tests/misc/projects/Issue2278/MyTools.hx create mode 100644 tests/misc/projects/Issue2278/compile.hxml.disabled create mode 100644 tests/misc/projects/Issue2278/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue2508/Main.hx create mode 100644 tests/misc/projects/Issue2508/compile.hxml create mode 100644 tests/misc/projects/Issue2508/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue2538/Main.hx create mode 100644 tests/misc/projects/Issue2538/compile-fail.hxml create mode 100644 tests/misc/projects/Issue2538/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue2997/Main.hx create mode 100644 tests/misc/projects/Issue2997/compile1.hxml create mode 100644 tests/misc/projects/Issue2997/compile1.hxml.stderr create mode 100644 tests/misc/projects/Issue3192/Main1.hx create mode 100644 tests/misc/projects/Issue3192/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue3192/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue3621/Main1.hx create mode 100644 tests/misc/projects/Issue3621/compile-fail.hxml create mode 100644 tests/misc/projects/Issue3621/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue3782/compile-fail.hxml.disabled create mode 100644 tests/misc/projects/Issue3802/Main.hx create mode 100644 tests/misc/projects/Issue3802/compile-fail.hxml create mode 100644 tests/misc/projects/Issue3802/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue3907/Main.hx create mode 100644 tests/misc/projects/Issue3907/compile.hxml create mode 100644 tests/misc/projects/Issue3907/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue3956/Main.hx create mode 100644 tests/misc/projects/Issue3956/compile.hxml create mode 100644 tests/misc/projects/Issue3956/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue3975/Main.hx create mode 100644 tests/misc/projects/Issue3975/compile-fail.hxml create mode 100644 tests/misc/projects/Issue3975/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4114/Main1.hx create mode 100644 tests/misc/projects/Issue4114/Main2.hx create mode 100644 tests/misc/projects/Issue4114/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue4114/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4114/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue4114/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4160/compile.hxml create mode 100644 tests/misc/projects/Issue4160/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue4160/test/Main.hx create mode 100644 tests/misc/projects/Issue4218/Main.hx create mode 100644 tests/misc/projects/Issue4218/build.hxml create mode 100644 tests/misc/projects/Issue4247/Main.hx create mode 100644 tests/misc/projects/Issue4247/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4247/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4250/Main.hx create mode 100644 tests/misc/projects/Issue4250/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4250/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4265/Main.hx create mode 100644 tests/misc/projects/Issue4265/compile.hxml create mode 100644 tests/misc/projects/Issue4265/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue4270/EmptyString.hx create mode 100644 tests/misc/projects/Issue4270/MultiChar.hx create mode 100644 tests/misc/projects/Issue4270/SingleChar.hx create mode 100644 tests/misc/projects/Issue4270/Test.hx create mode 100644 tests/misc/projects/Issue4270/test.hxml create mode 100644 tests/misc/projects/Issue4293/OnAbstract.hx create mode 100644 tests/misc/projects/Issue4293/OnClass.hx create mode 100644 tests/misc/projects/Issue4293/OnEnum.hx create mode 100644 tests/misc/projects/Issue4293/OnEnumCtor.hx create mode 100644 tests/misc/projects/Issue4293/OnField.hx create mode 100644 tests/misc/projects/Issue4293/OnTypedef.hx create mode 100644 tests/misc/projects/Issue4293/compile-abstract-fail.hxml create mode 100644 tests/misc/projects/Issue4293/compile-abstract-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4293/compile-class-fail.hxml create mode 100644 tests/misc/projects/Issue4293/compile-class-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4293/compile-enum-ctor-fail.hxml create mode 100644 tests/misc/projects/Issue4293/compile-enum-ctor-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4293/compile-enum-fail.hxml create mode 100644 tests/misc/projects/Issue4293/compile-enum-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4293/compile-field-fail.hxml create mode 100644 tests/misc/projects/Issue4293/compile-field-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4293/compile-typedef-fail.hxml create mode 100644 tests/misc/projects/Issue4293/compile-typedef-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4364/Main.hx create mode 100644 tests/misc/projects/Issue4364/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4364/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4370/Test.hx create mode 100644 tests/misc/projects/Issue4370/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4370/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4378/Main.hx create mode 100644 tests/misc/projects/Issue4378/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4378/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4399/Main.hx create mode 100644 tests/misc/projects/Issue4399/compile.hxml create mode 100644 tests/misc/projects/Issue4399/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue4404/compile1.hxml create mode 100644 tests/misc/projects/Issue4404/src/Base.hx create mode 100644 tests/misc/projects/Issue4404/src/Child.hx create mode 100644 tests/misc/projects/Issue4404/src/ChildChild.hx create mode 100644 tests/misc/projects/Issue4404/src/ContainerBase.hx create mode 100644 tests/misc/projects/Issue4404/src/ContainerChild.hx create mode 100644 tests/misc/projects/Issue4404/src/Empty.hx create mode 100644 tests/misc/projects/Issue4404/src/Macro.hx create mode 100644 tests/misc/projects/Issue4404/src/Main.hx create mode 100644 tests/misc/projects/Issue4448/Main1.hx create mode 100644 tests/misc/projects/Issue4448/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue4448/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4454/Main.hx create mode 100644 tests/misc/projects/Issue4454/compile.hxml create mode 100644 tests/misc/projects/Issue4454/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue4456/Main.hx create mode 100644 tests/misc/projects/Issue4456/compile.hxml create mode 100644 tests/misc/projects/Issue4456/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue4466/Main.hx create mode 100644 tests/misc/projects/Issue4466/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4466/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4540/Main.hx create mode 100644 tests/misc/projects/Issue4540/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4540/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4563/Main.hx create mode 100644 tests/misc/projects/Issue4563/compile.hxml create mode 100644 tests/misc/projects/Issue4563/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue4580/Main.hx create mode 100644 tests/misc/projects/Issue4580/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4580/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4651/CompServer.hx create mode 100644 tests/misc/projects/Issue4651/Main.hx create mode 100644 tests/misc/projects/Issue4651/Main.hx.stdin create mode 100644 tests/misc/projects/Issue4651/compile-server.hxml.disabled create mode 100644 tests/misc/projects/Issue4651/compile-server.hxml.stderr create mode 100644 tests/misc/projects/Issue4651/compile.hxml create mode 100644 tests/misc/projects/Issue4651/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue4660/Include.hx create mode 100644 tests/misc/projects/Issue4660/Test.hx create mode 100644 tests/misc/projects/Issue4660/compile.hxml create mode 100644 tests/misc/projects/Issue4660/include.js create mode 100644 tests/misc/projects/Issue4662/Main.hx create mode 100644 tests/misc/projects/Issue4662/Test.hx create mode 100644 tests/misc/projects/Issue4662/_pkg/A.hx create mode 100644 tests/misc/projects/Issue4662/compile.hxml create mode 100644 tests/misc/projects/Issue4671/Main1.hx create mode 100644 tests/misc/projects/Issue4671/Main2.hx create mode 100644 tests/misc/projects/Issue4671/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue4671/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4671/compile2-fail.hxml create mode 100644 tests/misc/projects/Issue4671/compile2-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4679/Main.hx create mode 100644 tests/misc/projects/Issue4679/compile.hxml create mode 100644 tests/misc/projects/Issue4679/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue4689/Main.hx create mode 100644 tests/misc/projects/Issue4689/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4689/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4712/Main.hx create mode 100644 tests/misc/projects/Issue4712/compile.hxml create mode 100644 tests/misc/projects/Issue4712/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue4720/Main.hx create mode 100644 tests/misc/projects/Issue4720/compile.hxml create mode 100644 tests/misc/projects/Issue4720/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue4723/Test.hx create mode 100644 tests/misc/projects/Issue4723/compile.hxml create mode 100644 tests/misc/projects/Issue4742/Main.hx create mode 100644 tests/misc/projects/Issue4742/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4742/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4754/Main1.hx create mode 100644 tests/misc/projects/Issue4754/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue4754/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4761/Main1.hx create mode 100644 tests/misc/projects/Issue4761/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue4761/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4764/Main1.hx create mode 100644 tests/misc/projects/Issue4764/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue4764/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4766/Main1.hx create mode 100644 tests/misc/projects/Issue4766/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue4766/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4775/Main1.hx create mode 100644 tests/misc/projects/Issue4775/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue4775/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4790/Main.hx create mode 100644 tests/misc/projects/Issue4790/builder/Builder.hx create mode 100644 tests/misc/projects/Issue4790/compile.hxml.disabled create mode 100644 tests/misc/projects/Issue4790/consts/Consts.hx create mode 100644 tests/misc/projects/Issue4790/user1/User1.hx create mode 100644 tests/misc/projects/Issue4790/user2/User2.hx create mode 100644 tests/misc/projects/Issue4803/Main.hx create mode 100644 tests/misc/projects/Issue4803/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4803/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4816/Main1.hx create mode 100644 tests/misc/projects/Issue4816/compile1-fail.hxml create mode 100644 tests/misc/projects/Issue4816/compile1-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4825/Macro.hx create mode 100644 tests/misc/projects/Issue4825/Main.hx create mode 100644 tests/misc/projects/Issue4825/compile.hxml create mode 100644 tests/misc/projects/Issue4904/Main.hx create mode 100644 tests/misc/projects/Issue4904/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4904/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4907/Main.hx create mode 100644 tests/misc/projects/Issue4907/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4907/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4954/Main.hx create mode 100644 tests/misc/projects/Issue4954/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4954/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4957/Main.hx create mode 100644 tests/misc/projects/Issue4957/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4957/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue4982/Main.hx create mode 100644 tests/misc/projects/Issue4982/compile-fail.hxml create mode 100644 tests/misc/projects/Issue4982/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5005/Main.hx create mode 100644 tests/misc/projects/Issue5005/compile.hxml create mode 100644 tests/misc/projects/Issue5010/Main.hx create mode 100644 tests/misc/projects/Issue5010/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5010/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5118/Main.hx create mode 100644 tests/misc/projects/Issue5118/compile1.hxml create mode 100644 tests/misc/projects/Issue5118/compile1.hxml.stderr create mode 100644 tests/misc/projects/Issue5118/compile2.hxml create mode 100644 tests/misc/projects/Issue5118/compile2.hxml.stderr create mode 100644 tests/misc/projects/Issue5122/Main.hx create mode 100644 tests/misc/projects/Issue5122/compile.hxml create mode 100644 tests/misc/projects/Issue5122/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue5123/Main.hx create mode 100644 tests/misc/projects/Issue5123/compile.hxml create mode 100644 tests/misc/projects/Issue5123/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue5125/Main.hx create mode 100644 tests/misc/projects/Issue5125/compile.hxml create mode 100644 tests/misc/projects/Issue5125/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue5126/Main.hx create mode 100644 tests/misc/projects/Issue5126/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5126/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5128/Main.hx create mode 100644 tests/misc/projects/Issue5128/compile.hxml create mode 100644 tests/misc/projects/Issue5128/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue5134/Main.hx create mode 100644 tests/misc/projects/Issue5134/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5134/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5145/Main.hx create mode 100644 tests/misc/projects/Issue5145/compile.hxml create mode 100644 tests/misc/projects/Issue5152/Main.hx create mode 100644 tests/misc/projects/Issue5152/compile.hxml create mode 100644 tests/misc/projects/Issue5152/compile.hxml.stderr create mode 100644 tests/misc/projects/Issue5206/Main.hx create mode 100644 tests/misc/projects/Issue5206/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5206/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5268/Main.hx create mode 100644 tests/misc/projects/Issue5268/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5268/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5321/Chest.hx create mode 100644 tests/misc/projects/Issue5321/Main.hx create mode 100644 tests/misc/projects/Issue5321/Test.hx create mode 100644 tests/misc/projects/Issue5321/compile.hxml create mode 100644 tests/misc/projects/Issue5375/Main.hx create mode 100644 tests/misc/projects/Issue5375/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5375/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5559/Build.hx create mode 100644 tests/misc/projects/Issue5559/Main.hx create mode 100644 tests/misc/projects/Issue5559/OtherClass.hx create mode 100644 tests/misc/projects/Issue5559/build.hxml create mode 100644 tests/misc/projects/Issue5559/import.hx create mode 100644 tests/misc/projects/Issue5644/Main.hx create mode 100644 tests/misc/projects/Issue5644/User.hx create mode 100644 tests/misc/projects/Issue5644/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5644/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5833/Main.hx create mode 100644 tests/misc/projects/Issue5833/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5833/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/Issue5856/Main.hx create mode 100644 tests/misc/projects/Issue5856/compile.hxml create mode 100644 tests/misc/projects/Issue5888/Main.hx create mode 100644 tests/misc/projects/Issue5888/compile-fail.hxml create mode 100644 tests/misc/projects/Issue5888/compile-fail.hxml.stderr create mode 100644 tests/misc/projects/display-package/compile1.hxml create mode 100644 tests/misc/projects/display-package/compile1.hxml.stderr create mode 100644 tests/misc/projects/display-package/compile2.hxml create mode 100644 tests/misc/projects/display-package/compile2.hxml.stderr create mode 100644 tests/misc/projects/display-package/compile3.hxml create mode 100644 tests/misc/projects/display-package/compile3.hxml.stderr create mode 100644 tests/misc/projects/display-package/src/C1.hx create mode 100644 tests/misc/projects/display-package/src/pack/C2.hx create mode 100644 tests/optimization/src/issues/Issue4223.hx create mode 100644 tests/optimization/src/issues/Issue4690.hx create mode 100644 tests/optimization/src/issues/Issue5477.hx create mode 100644 tests/optimization/src/issues/Issue5509.hx create mode 100644 tests/optimization/src/issues/Issue5745.hx create mode 100644 tests/optimization/src/issues/Issue5855.hx create mode 100644 tests/optimization/src/issues/Issue5931.hx delete mode 100644 tests/sys/args.xml create mode 100644 tests/sys/compile-hl.hxml create mode 100644 tests/sys/compile-lua.hxml create mode 100644 tests/sys/compile-php7.hxml create mode 120000 tests/sys/lua create mode 100644 tests/sys/src/ExitCode.c create mode 100644 tests/sys/src/TestCommandBase.hx create mode 100644 tests/unit/compile-hl.hxml create mode 100644 tests/unit/compile-lua.hxml create mode 100644 tests/unit/compile-php7.hxml create mode 100644 tests/unit/src/scripthost/Issue5351.hx create mode 100644 tests/unit/src/unit/HelperMacros.hx create mode 100644 tests/unit/src/unit/TestHL.hx create mode 100644 tests/unit/src/unit/TestJQuery.hx create mode 100644 tests/unit/src/unit/TestLua.hx create mode 100644 tests/unit/src/unit/TestMain.hx create mode 100644 tests/unit/src/unit/hxcpp_issues/Issue352.hx create mode 100644 tests/unit/src/unit/issues/Issue1827.hx rename tests/unit/src/unit/issues/{Issue2061.hx.disabled => Issue2061.hx} (100%) create mode 100644 tests/unit/src/unit/issues/Issue2244.hx create mode 100644 tests/unit/src/unit/issues/Issue2587.hx create mode 100644 tests/unit/src/unit/issues/Issue2767.hx create mode 100644 tests/unit/src/unit/issues/Issue3192.hx create mode 100644 tests/unit/src/unit/issues/Issue3254.hx create mode 100644 tests/unit/src/unit/issues/Issue3361.hx create mode 100644 tests/unit/src/unit/issues/Issue3450.hx create mode 100644 tests/unit/src/unit/issues/Issue3460.hx create mode 100644 tests/unit/src/unit/issues/Issue3499.hx create mode 100644 tests/unit/src/unit/issues/Issue3528.hx create mode 100644 tests/unit/src/unit/issues/Issue3535.hx create mode 100644 tests/unit/src/unit/issues/Issue3560.hx create mode 100644 tests/unit/src/unit/issues/Issue3563.hx create mode 100644 tests/unit/src/unit/issues/Issue3702.hx create mode 100644 tests/unit/src/unit/issues/Issue3762.hx create mode 100644 tests/unit/src/unit/issues/Issue3781.hx create mode 100644 tests/unit/src/unit/issues/Issue3804.hx create mode 100644 tests/unit/src/unit/issues/Issue3935.hx create mode 100644 tests/unit/src/unit/issues/Issue3987.hx delete mode 100644 tests/unit/src/unit/issues/Issue4084.hx create mode 100644 tests/unit/src/unit/issues/Issue4086.hx create mode 100644 tests/unit/src/unit/issues/Issue4089.hx create mode 100644 tests/unit/src/unit/issues/Issue4103.hx create mode 100644 tests/unit/src/unit/issues/Issue4121.hx create mode 100644 tests/unit/src/unit/issues/Issue4122.hx create mode 100644 tests/unit/src/unit/issues/Issue4158.hx create mode 100644 tests/unit/src/unit/issues/Issue4180.hx create mode 100644 tests/unit/src/unit/issues/Issue4196.hx create mode 100644 tests/unit/src/unit/issues/Issue4203.hx create mode 100644 tests/unit/src/unit/issues/Issue4203.hx.disabled create mode 100644 tests/unit/src/unit/issues/Issue4222.hx create mode 100644 tests/unit/src/unit/issues/Issue4232.hx create mode 100644 tests/unit/src/unit/issues/Issue4246.hx create mode 100644 tests/unit/src/unit/issues/Issue4254.hx create mode 100644 tests/unit/src/unit/issues/Issue4260.hx create mode 100644 tests/unit/src/unit/issues/Issue4273.hx create mode 100644 tests/unit/src/unit/issues/Issue4277.hx create mode 100644 tests/unit/src/unit/issues/Issue4284.hx create mode 100644 tests/unit/src/unit/issues/Issue4285.hx create mode 100644 tests/unit/src/unit/issues/Issue4295.hx create mode 100644 tests/unit/src/unit/issues/Issue4306.hx create mode 100644 tests/unit/src/unit/issues/Issue4310.hx create mode 100644 tests/unit/src/unit/issues/Issue4312.hx create mode 100644 tests/unit/src/unit/issues/Issue4313.hx create mode 100644 tests/unit/src/unit/issues/Issue4322.hx create mode 100644 tests/unit/src/unit/issues/Issue4323.hx create mode 100644 tests/unit/src/unit/issues/Issue4324.hx create mode 100644 tests/unit/src/unit/issues/Issue4327.hx.disabled create mode 100644 tests/unit/src/unit/issues/Issue4329.hx create mode 100644 tests/unit/src/unit/issues/Issue4337.hx create mode 100644 tests/unit/src/unit/issues/Issue4343.hx create mode 100644 tests/unit/src/unit/issues/Issue4353.hx create mode 100644 tests/unit/src/unit/issues/Issue4357.hx create mode 100644 tests/unit/src/unit/issues/Issue4359.hx create mode 100644 tests/unit/src/unit/issues/Issue4360.hx create mode 100644 tests/unit/src/unit/issues/Issue4384.hx create mode 100644 tests/unit/src/unit/issues/Issue4388.hx create mode 100644 tests/unit/src/unit/issues/Issue4397.hx create mode 100644 tests/unit/src/unit/issues/Issue4419.hx create mode 100644 tests/unit/src/unit/issues/Issue4421.hx create mode 100644 tests/unit/src/unit/issues/Issue4426.hx create mode 100644 tests/unit/src/unit/issues/Issue4436.hx create mode 100644 tests/unit/src/unit/issues/Issue4445.hx create mode 100644 tests/unit/src/unit/issues/Issue4450.hx create mode 100644 tests/unit/src/unit/issues/Issue4466.hx create mode 100644 tests/unit/src/unit/issues/Issue4473.hx create mode 100644 tests/unit/src/unit/issues/Issue4501.hx create mode 100644 tests/unit/src/unit/issues/Issue4526.hx create mode 100644 tests/unit/src/unit/issues/Issue4535.hx create mode 100644 tests/unit/src/unit/issues/Issue4551.hx create mode 100644 tests/unit/src/unit/issues/Issue4557.hx create mode 100644 tests/unit/src/unit/issues/Issue4564.hx.disabled create mode 100644 tests/unit/src/unit/issues/Issue4578.hx create mode 100644 tests/unit/src/unit/issues/Issue4579.hx create mode 100644 tests/unit/src/unit/issues/Issue4581.hx create mode 100644 tests/unit/src/unit/issues/Issue4591.hx create mode 100644 tests/unit/src/unit/issues/Issue4592.hx create mode 100644 tests/unit/src/unit/issues/Issue4593.hx create mode 100644 tests/unit/src/unit/issues/Issue4608.hx create mode 100644 tests/unit/src/unit/issues/Issue4617.hx create mode 100644 tests/unit/src/unit/issues/Issue4644.hx create mode 100644 tests/unit/src/unit/issues/Issue4653.hx create mode 100644 tests/unit/src/unit/issues/Issue4666.hx create mode 100644 tests/unit/src/unit/issues/Issue4667.hx create mode 100644 tests/unit/src/unit/issues/Issue4668.hx create mode 100644 tests/unit/src/unit/issues/Issue4672.hx create mode 100644 tests/unit/src/unit/issues/Issue4675.hx create mode 100644 tests/unit/src/unit/issues/Issue4677.hx create mode 100644 tests/unit/src/unit/issues/Issue4681.hx create mode 100644 tests/unit/src/unit/issues/Issue4690.hx create mode 100644 tests/unit/src/unit/issues/Issue4695.hx create mode 100644 tests/unit/src/unit/issues/Issue4702.hx create mode 100644 tests/unit/src/unit/issues/Issue4703.hx create mode 100644 tests/unit/src/unit/issues/Issue4723.hx create mode 100644 tests/unit/src/unit/issues/Issue4729.hx create mode 100644 tests/unit/src/unit/issues/Issue4740.hx create mode 100644 tests/unit/src/unit/issues/Issue4743.hx create mode 100644 tests/unit/src/unit/issues/Issue4751.hx create mode 100644 tests/unit/src/unit/issues/Issue4757.hx create mode 100644 tests/unit/src/unit/issues/Issue4772.hx create mode 100644 tests/unit/src/unit/issues/Issue4777.hx create mode 100644 tests/unit/src/unit/issues/Issue4798.hx create mode 100644 tests/unit/src/unit/issues/Issue4809.hx create mode 100644 tests/unit/src/unit/issues/Issue4810.hx create mode 100644 tests/unit/src/unit/issues/Issue4819.hx create mode 100644 tests/unit/src/unit/issues/Issue4841.hx create mode 100644 tests/unit/src/unit/issues/Issue4842.hx create mode 100644 tests/unit/src/unit/issues/Issue4843.hx create mode 100644 tests/unit/src/unit/issues/Issue4862.hx create mode 100644 tests/unit/src/unit/issues/Issue4867.hx create mode 100644 tests/unit/src/unit/issues/Issue4870.hx create mode 100644 tests/unit/src/unit/issues/Issue4878.hx create mode 100644 tests/unit/src/unit/issues/Issue4885.hx create mode 100644 tests/unit/src/unit/issues/Issue4886.hx create mode 100644 tests/unit/src/unit/issues/Issue4889.hx create mode 100644 tests/unit/src/unit/issues/Issue4904.hx create mode 100644 tests/unit/src/unit/issues/Issue4910.hx create mode 100644 tests/unit/src/unit/issues/Issue4917.hx create mode 100644 tests/unit/src/unit/issues/Issue4918.hx create mode 100644 tests/unit/src/unit/issues/Issue4940.hx create mode 100644 tests/unit/src/unit/issues/Issue4949.hx create mode 100644 tests/unit/src/unit/issues/Issue4953.hx create mode 100644 tests/unit/src/unit/issues/Issue4962.hx create mode 100644 tests/unit/src/unit/issues/Issue4966.hx create mode 100644 tests/unit/src/unit/issues/Issue4969.hx create mode 100644 tests/unit/src/unit/issues/Issue4973.hx create mode 100644 tests/unit/src/unit/issues/Issue4977.hx create mode 100644 tests/unit/src/unit/issues/Issue4979.hx create mode 100644 tests/unit/src/unit/issues/Issue4986.hx create mode 100644 tests/unit/src/unit/issues/Issue4987.hx create mode 100644 tests/unit/src/unit/issues/Issue4988.hx create mode 100644 tests/unit/src/unit/issues/Issue4997.hx create mode 100644 tests/unit/src/unit/issues/Issue5000.hx create mode 100644 tests/unit/src/unit/issues/Issue5015.hx create mode 100644 tests/unit/src/unit/issues/Issue5016.hx create mode 100644 tests/unit/src/unit/issues/Issue5025.hx create mode 100644 tests/unit/src/unit/issues/Issue5027.hx create mode 100644 tests/unit/src/unit/issues/Issue5028.hx create mode 100644 tests/unit/src/unit/issues/Issue5029.hx create mode 100644 tests/unit/src/unit/issues/Issue5030.hx create mode 100644 tests/unit/src/unit/issues/Issue5031.hx create mode 100644 tests/unit/src/unit/issues/Issue5044.hx create mode 100644 tests/unit/src/unit/issues/Issue5053.hx create mode 100644 tests/unit/src/unit/issues/Issue5064.hx create mode 100644 tests/unit/src/unit/issues/Issue5073.hx create mode 100644 tests/unit/src/unit/issues/Issue5078.hx create mode 100644 tests/unit/src/unit/issues/Issue5082.hx create mode 100644 tests/unit/src/unit/issues/Issue5086.hx create mode 100644 tests/unit/src/unit/issues/Issue5090.hx create mode 100644 tests/unit/src/unit/issues/Issue5108.hx create mode 100644 tests/unit/src/unit/issues/Issue5110.hx.disabled create mode 100644 tests/unit/src/unit/issues/Issue5113.hx create mode 100644 tests/unit/src/unit/issues/Issue5124.hx create mode 100644 tests/unit/src/unit/issues/Issue5135.hx create mode 100644 tests/unit/src/unit/issues/Issue5162.hx create mode 100644 tests/unit/src/unit/issues/Issue5179.hx create mode 100644 tests/unit/src/unit/issues/Issue5184.hx create mode 100644 tests/unit/src/unit/issues/Issue5192.hx create mode 100644 tests/unit/src/unit/issues/Issue5192_Test.hx create mode 100644 tests/unit/src/unit/issues/Issue5218.hx create mode 100644 tests/unit/src/unit/issues/Issue5221.hx create mode 100644 tests/unit/src/unit/issues/Issue5226.hx create mode 100644 tests/unit/src/unit/issues/Issue5231.hx create mode 100644 tests/unit/src/unit/issues/Issue5234.hx create mode 100644 tests/unit/src/unit/issues/Issue5242.hx create mode 100644 tests/unit/src/unit/issues/Issue5248.hx create mode 100644 tests/unit/src/unit/issues/Issue5249.hx create mode 100644 tests/unit/src/unit/issues/Issue5253.hx create mode 100644 tests/unit/src/unit/issues/Issue5260.hx create mode 100644 tests/unit/src/unit/issues/Issue5270.hx create mode 100644 tests/unit/src/unit/issues/Issue5274.hx create mode 100644 tests/unit/src/unit/issues/Issue5288.hx create mode 100644 tests/unit/src/unit/issues/Issue5290.hx create mode 100644 tests/unit/src/unit/issues/Issue5293.hx create mode 100644 tests/unit/src/unit/issues/Issue5303.hx create mode 100644 tests/unit/src/unit/issues/Issue5309.hx create mode 100644 tests/unit/src/unit/issues/Issue5322.hx create mode 100644 tests/unit/src/unit/issues/Issue5323.hx create mode 100644 tests/unit/src/unit/issues/Issue5340.hx create mode 100644 tests/unit/src/unit/issues/Issue5351.hx create mode 100644 tests/unit/src/unit/issues/Issue5358.hx create mode 100644 tests/unit/src/unit/issues/Issue5383.hx create mode 100644 tests/unit/src/unit/issues/Issue5385.hx create mode 100644 tests/unit/src/unit/issues/Issue5389.hx create mode 100644 tests/unit/src/unit/issues/Issue5392.hx create mode 100644 tests/unit/src/unit/issues/Issue5425.hx create mode 100644 tests/unit/src/unit/issues/Issue5432.hx create mode 100644 tests/unit/src/unit/issues/Issue5455.hx create mode 100644 tests/unit/src/unit/issues/Issue5466.hx create mode 100644 tests/unit/src/unit/issues/Issue5469.hx create mode 100644 tests/unit/src/unit/issues/Issue5470.hx create mode 100644 tests/unit/src/unit/issues/Issue5477.hx create mode 100644 tests/unit/src/unit/issues/Issue5481.hx create mode 100644 tests/unit/src/unit/issues/Issue5505.hx create mode 100644 tests/unit/src/unit/issues/Issue5507.hx create mode 100644 tests/unit/src/unit/issues/Issue5508.hx create mode 100644 tests/unit/src/unit/issues/Issue5520.hx create mode 100644 tests/unit/src/unit/issues/Issue5540.hx create mode 100644 tests/unit/src/unit/issues/Issue5543.hx create mode 100644 tests/unit/src/unit/issues/Issue5544.hx create mode 100644 tests/unit/src/unit/issues/Issue5555.hx create mode 100644 tests/unit/src/unit/issues/Issue5556.hx create mode 100644 tests/unit/src/unit/issues/Issue5557.hx create mode 100644 tests/unit/src/unit/issues/Issue5558.hx create mode 100644 tests/unit/src/unit/issues/Issue5565.hx create mode 100644 tests/unit/src/unit/issues/Issue5569.hx create mode 100644 tests/unit/src/unit/issues/Issue5572.hx create mode 100644 tests/unit/src/unit/issues/Issue5584.hx create mode 100644 tests/unit/src/unit/issues/Issue5608.hx create mode 100644 tests/unit/src/unit/issues/Issue5693.hx create mode 100644 tests/unit/src/unit/issues/Issue5705.hx create mode 100644 tests/unit/src/unit/issues/Issue5737.hx create mode 100644 tests/unit/src/unit/issues/Issue5742.hx create mode 100644 tests/unit/src/unit/issues/Issue5747.hx create mode 100644 tests/unit/src/unit/issues/Issue5757.hx create mode 100644 tests/unit/src/unit/issues/Issue5764.hx create mode 100644 tests/unit/src/unit/issues/Issue5783.hx create mode 100644 tests/unit/src/unit/issues/Issue5848.hx create mode 100644 tests/unit/src/unit/issues/Issue5851.hx create mode 100644 tests/unit/src/unit/issues/Issue5873.hx create mode 100644 tests/unit/src/unit/issues/Issue5894.hx create mode 100644 tests/unit/src/unit/issues/Issue5911.hx create mode 100644 tests/unit/src/unit/issues/Issue5919.hx create mode 100644 tests/unit/src/unit/issues/Issue5923.hx create mode 100644 tests/unit/src/unit/issues/Issue5945.hx create mode 100644 tests/unit/src/unit/issues/Issue5957.hx create mode 100644 tests/unit/src/unit/issues/Issue5973.hx create mode 100644 tests/unit/src/unit/issues/misc/Issue3460Macro.hx create mode 100644 tests/unit/src/unit/issues/misc/Issue3560Macro.hx create mode 100644 tests/unit/src/unit/issues/misc/Issue4121Macro.hx create mode 100644 tests/unit/src/unit/issues/misc/Issue4306Macro.hx create mode 100644 tests/unit/src/unit/issues/misc/Issue4419External.js create mode 100644 tests/unit/src/unit/issues/misc/Issue4653Macro.hx create mode 100644 tests/unit/src/unit/issues/misc/Issue4666Macro.hx create mode 100644 tests/unit/src/unit/issues/misc/Issue5429Macro.hx create mode 100644 tests/unit/src/unitstd/Float.unit.hx create mode 100644 tests/unit/src/unitstd/Https.unit.hx create mode 100644 tests/unit/src/unitstd/Ssl.unit.hx create mode 100644 tests/unit/src/unitstd/haxe/io/FPHelper.unit.hx create mode 100644 tests/unit/src/unitstd/haxe/zip/Compress.unit.hx rename extra/haxelib_src/site.hxproj => tests/unit/unit_hl.hxproj (64%) delete mode 100644 typecore.ml delete mode 100644 typeload.ml diff --git a/.merlin b/.merlin new file mode 100644 index 00000000..b303a900 --- /dev/null +++ b/.merlin @@ -0,0 +1,4 @@ +S src/** +B src/** +S libs/** +B libs/** diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 81f58f53..00000000 --- a/.travis.yml +++ /dev/null @@ -1,85 +0,0 @@ -language: cpp - -os: - - linux - - osx - -env: - global: - # make variables - - OCAMLC=ocamlc.opt - - OCAMLOPT=ocamlopt.opt - - ADD_REVISION=1 - # SAUCE_USERNAME - - secure: SjyKefmjUEXi0IKHGGpcbLAajU0mLHONg8aA8LoY7Q9nAkSN6Aql+fzS38Boq7w1jWn+2FOpr+4jy0l6wVd/bftsF+huFfYpFJmdh8BlKmE0K71zZAral0H1c7YxkuQpPiJCIFGXqtkvev7SWTy0z31u7kuuQeEyW27boXe5cDA= - # SAUCE_ACCESS_KEY - - secure: sUvWUjCyPuWht4seNa4f2VG9DkvXkhZyLZfjJO9TUAHB2JndS16E2j/qrvKEjycyH6w8tU/B9vnjDRvvGrYXxEXcBEwsJVfkorFnRl9uwGCGIYrzjMhssEl3fMYZK7P304f+gAp5ULrDBX2gIaKeSa8lUNRtz2PsZOieE4kMdhk= - matrix: - - TEST=third-party - - TEST=macro - - TEST=neko - - TEST=js - - TEST=php - - TEST=cpp - - TEST=flash9 - - TEST=as3 - - TEST=java - - TEST=cs - - TEST=python - -matrix: - # fast_finish: true #https://github.com/travis-ci/travis-ci/issues/1696 - -before_script: - - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then - mysql -u root -e "CREATE DATABASE haxe_test;"; - fi - -install: - # For our forks that do not have mult-os enabled... - - if [ -z "${TRAVIS_OS_NAME}" ]; then - export TRAVIS_OS_NAME=linux; - fi - # Install haxe and neko dependencies - - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then - travis_retry sudo apt-get update -qq; - travis_retry sudo apt-get install ocaml-native-compilers zlib1g-dev libgc-dev -qq; - fi - - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then - travis_retry brew update; - travis_retry brew install caskroom/cask/brew-cask; - travis_retry brew install ocaml camlp4; - fi - # Install neko - - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then - travis_retry git clone https://github.com/HaxeFoundation/neko.git ~/neko; - cd ~/neko && make os=${TRAVIS_OS_NAME} -s && sudo make install -s; - cd $TRAVIS_BUILD_DIR; - fi - - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then - travis_retry brew install neko --HEAD; - fi - -script: - - make -s - - make tools -s - - sudo make install -s - - cd tests/ - - mkdir ~/haxelib && haxelib setup ~/haxelib - - haxe -version - - haxe RunCi.hxml - - neko RunCi.n - -branches: - except: - # A hack to prevent building for tags, assuming they all start with a number. - # https://github.com/travis-ci/travis-ci/issues/1532 - - /^[0-9]/ - -notifications: - webhooks: - urls: - - https://webhooks.gitter.im/e/95a5fa471c27beee8e7c - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: false # default: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 14209630..ea1b2fc1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,11 +1,21 @@ -Things to check before/while filing an issue: +## Things to check before/while filing an issue: -- Check if you actually suspect that there's an issue in the Haxe code. If you find yourself writing "How do I..." you may want to consider a different communication channel. Refer to http://haxe.org/community/community-support.html for more information. +- Check if you actually suspect that there's an issue in the Haxe code. If you find yourself writing "How do I..." you may want to consider a different communication channel. Refer to https://haxe.org/community/community-support.html for more information. - Reduce your code to a minimal example (see http://sscce.org/). In particular avoid library dependencies: If you cannot reproduce your issue without using a specific library, it might not be a Haxe issue to begin with. - Check if your problems are already resolved in the Haxe development version (for builds see http://builds.haxe.org/). -- Most targets produce readable code. If you suspect the generated code to be wrong, try checking the output. Note that you can add `-D dump=pretty` to your compilation parameters and find the code which is passed to the generators in a `dump` sub directory. +- Most targets produce readable code. If you suspect the generated code to be wrong, try checking the output. Note that you can add `-D dump=pretty` to your compilation parameters and find the code which is passed to the generators in a `dump` subdirectory. -Other remarks: +## Is this the right repository to report the issue? + +This repository is about the Haxe compiler itself and the Haxe standard library. Here's an overview of repositories that are part of the Haxe ecosystem: + +* The haxelib command line tool or lib.haxe.org: +* Something on try.haxe.org: +* Something under haxe.org/manual: +* Something on api.haxe.org: For content this is probably the right repository. If it's about the representation, try instead. +* Something else on haxe.org: + +## Other remarks: - Sometimes people try to be particularly helpful by not only including broken parts in their code, but also "similar" code which is working. More often than not this is more distracting than helpful. If you want to highlight something like this, consider adding the working code commented out. - We do not require a classic "What do you see/what do you expect?" form, but in some cases it is hard to figure out where you think the actual problem is otherwise. diff --git a/Makefile b/Makefile index e912e15a..56edba64 100644 --- a/Makefile +++ b/Makefile @@ -10,23 +10,40 @@ # .SUFFIXES : .ml .mli .cmo .cmi .cmx .mll .mly -INSTALL_DIR=/usr +INSTALL_DIR=$(DESTDIR)/usr INSTALL_BIN_DIR=$(INSTALL_DIR)/bin INSTALL_LIB_DIR=$(INSTALL_DIR)/lib/haxe +INSTALL_STD_DIR=$(INSTALL_LIB_DIR)/std +PACKAGE_OUT_DIR=out +PACKAGE_SRC_EXTENSION=.tar.gz + +PLATFORM?=unix OUTPUT=haxe EXTENSION= OCAMLOPT?=ocamlopt OCAMLC?=ocamlc LFLAGS= +STATICLINK?=0 -CFLAGS= -g -I libs/extlib -I libs/extc -I libs/neko -I libs/javalib -I libs/ziplib -I libs/swflib -I libs/xml-light -I libs/ttflib -I libs/ilib -I libs/objsize +CFLAGS= -bin-annot +ALL_CFLAGS= $(CFLAGS) -g -w -3 -I libs/extlib -I libs/extc -I libs/neko -I libs/javalib -I libs/ziplib -I libs/swflib -I libs/xml-light -I libs/ttflib -I libs/ilib -I libs/objsize -I libs/pcre \ + -I src -I src/context -I src/generators -I src/macro -I src/optimization -I src/syntax -I src/typing -I src/display LIBS=unix str libs/extlib/extLib libs/xml-light/xml-light libs/swflib/swflib \ libs/extc/extc libs/neko/neko libs/javalib/java libs/ziplib/zip \ - libs/ttflib/ttf libs/ilib/il libs/objsize/objsize + libs/ttflib/ttf libs/ilib/il libs/objsize/objsize libs/pcre/pcre + + +ifneq ($(STATICLINK),0) +LIB_PARAMS= -cclib '-Wl,-Bstatic -lpcre -lz -Wl,-Bdynamic ' + +else +LIB_PARAMS?= -cclib -lpcre -cclib -lz + +endif -NATIVE_LIBS=-cclib libs/extc/extc_stubs.o -cclib libs/extc/process_stubs.o -cclib -lz -cclib libs/objsize/c_objsize.o +NATIVE_LIBS=-cclib libs/extc/extc_stubs.o -cclib libs/extc/process_stubs.o -cclib libs/objsize/c_objsize.o -cclib libs/pcre/pcre_stubs.o -ccopt -L/usr/local/lib $(LIB_PARAMS) ifeq ($(BYTECODE),1) TARGET_FLAG = bytecode @@ -41,22 +58,36 @@ else MODULE_EXT = cmx endif -CC_CMD = $(COMPILER) $(CFLAGS) -c $< +CC_CMD = $(COMPILER) $(ALL_CFLAGS) -c $< -CC_PARSER_CMD = $(COMPILER) -pp camlp4o $(CFLAGS) -c parser.ml +CC_PARSER_CMD = $(COMPILER) -pp camlp4o $(ALL_CFLAGS) -c src/syntax/parser.ml RELDIR=../../.. -MODULES=ast type lexer common genxml parser typecore optimizer typeload \ - codegen gencommon genas3 gencpp genjs genneko genphp \ - genswf9 genswf genjava gencs genpy interp dce analyzer filters typer matcher version main +MODULES=json version globals path context/meta syntax/ast display/displayTypes typing/type typing/error \ + syntax/lexer context/common generators/genxml \ + syntax/parser typing/abstract typing/typecore display/display optimization/optimizerTexpr \ + optimization/optimizer typing/overloads typing/typeload generators/codegen generators/gencommon generators/genas3 \ + generators/gencpp generators/genjs generators/genneko generators/genphp generators/genphp7 generators/genswf9 \ + generators/genswf generators/genjava generators/gencs generators/genpy macro/macroApi macro/interp generators/hlcode generators/hlopt generators/hlinterp generators/hl2c \ + generators/genlua \ + optimization/dce optimization/analyzerConfig optimization/analyzerTypes optimization/analyzerTexpr \ + optimization/analyzerTexprTransformer optimization/analyzer generators/genhl \ + optimization/filters macro/hlmacro macro/macroContext typing/typer typing/matcher display/displayOutput server main ADD_REVISION?=0 BRANCH=$(shell echo $$APPVEYOR_REPO_NAME | grep -q /haxe && echo $$APPVEYOR_REPO_BRANCH || echo $$TRAVIS_REPO_SLUG | grep -q /haxe && echo $$TRAVIS_BRANCH || git rev-parse --abbrev-ref HEAD) COMMIT_SHA=$(shell git rev-parse --short HEAD) -COMMIT_DATE=$(shell git show -s --format=%ci HEAD | grep -oh ....-..-..) -PACKAGE_FILE_NAME=haxe_$(COMMIT_DATE)_$(BRANCH)_$(COMMIT_SHA) +COMMIT_DATE=$(shell \ + if [ "$$(uname)" = "Darwin" ]; then \ + date -u -r $$(git show -s --format=%ct HEAD) +%Y%m%d%H%M%S; \ + else \ + date -u -d @$$(git show -s --format=%ct HEAD) +%Y%m%d%H%M%S; \ + fi \ +) +PACKAGE_FILE_NAME=haxe_$(COMMIT_DATE)_$(COMMIT_SHA) +HAXE_VERSION=$(shell $(OUTPUT) -version 2>&1 | awk '{print $$1;}') # using $(CURDIR) on Windows will not work since it might be a Cygwin path ifdef SYSTEMROOT @@ -65,7 +96,7 @@ else export HAXE_STD_PATH=$(CURDIR)/std endif -all: libs haxe +all: libs haxe tools libs: make -C libs/extlib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG) @@ -78,31 +109,28 @@ libs: make -C libs/xml-light OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG) make -C libs/ttflib OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG) make -C libs/objsize OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG) + make -C libs/pcre OCAMLOPT=$(OCAMLOPT) OCAMLC=$(OCAMLC) $(TARGET_FLAG) -haxe: $(MODULES:=.$(MODULE_EXT)) - $(COMPILER) -o $(OUTPUT) $(NATIVE_LIBS) $(NATIVE_LIB_FLAG) $(LFLAGS) $(LIBS:=.$(LIB_EXT)) $(MODULES:=.$(MODULE_EXT)) +haxe: $(MODULES:%=src/%.$(MODULE_EXT)) + $(COMPILER) -o $(OUTPUT) $(NATIVE_LIBS) $(NATIVE_LIB_FLAG) $(LFLAGS) $(LIBS:=.$(LIB_EXT)) $(MODULES:%=src/%.$(MODULE_EXT)) haxelib: - (cd $(CURDIR)/extra/haxelib_src && $(CURDIR)/$(OUTPUT) haxelib.hxml && nekotools boot bin/haxelib.n) - cp extra/haxelib_src/bin/haxelib$(EXTENSION) haxelib$(EXTENSION) + (cd $(CURDIR)/extra/haxelib_src && $(CURDIR)/$(OUTPUT) client.hxml && nekotools boot run.n) + mv extra/haxelib_src/run$(EXTENSION) haxelib$(EXTENSION) tools: haxelib -install: - -rm -f $(INSTALL_LIB_DIR) - -mkdir -p $(INSTALL_LIB_DIR) - rm -rf $(INSTALL_LIB_DIR)/std - cp -rf std $(INSTALL_LIB_DIR)/std +install: uninstall + mkdir -p $(INSTALL_BIN_DIR) + mkdir -p $(INSTALL_LIB_DIR)/lib + cp -rf std $(INSTALL_STD_DIR) cp -rf extra $(INSTALL_LIB_DIR) - -mkdir -p $(INSTALL_LIB_DIR)/lib - rm -f $(INSTALL_BIN_DIR)/haxe cp haxe $(INSTALL_LIB_DIR) ln -s $(INSTALL_LIB_DIR)/haxe $(INSTALL_BIN_DIR)/haxe + cp haxelib $(INSTALL_LIB_DIR) + ln -s $(INSTALL_LIB_DIR)/haxelib $(INSTALL_BIN_DIR)/haxelib chmod -R a+rx $(INSTALL_LIB_DIR) chmod 777 $(INSTALL_LIB_DIR)/lib - # cp extra/haxelib_src/haxelib_script.sh $(INSTALL_DIR)/bin/haxelib - echo "#!/bin/sh" > $(INSTALL_BIN_DIR)/haxelib - echo "exec haxe -cp $(INSTALL_LIB_DIR)/extra/haxelib_src/src --run tools.haxelib.Main \"\$$@\"" >> $(INSTALL_BIN_DIR)/haxelib chmod a+rx $(INSTALL_BIN_DIR)/haxe $(INSTALL_BIN_DIR)/haxelib # will install native version of the tools instead of script ones @@ -111,88 +139,185 @@ install_tools: tools chmod a+rx $(INSTALL_BIN_DIR)/haxelib uninstall: - rm -rf $(INSTALL_BIN_DIR)/haxe $(INSTALL_BIN_DIR)/haxelib $(INSTALL_LIB_DIR) + rm -rf $(INSTALL_BIN_DIR)/haxe $(INSTALL_BIN_DIR)/haxelib + if [ -d "$(INSTALL_LIB_DIR)/lib" ] && find "$(INSTALL_LIB_DIR)/lib" -mindepth 1 -print -quit | grep -q .; then \ + echo "The local haxelib repo at $(INSTALL_LIB_DIR)/lib will not be removed. Remove it manually if you want."; \ + find $(INSTALL_LIB_DIR)/ ! -name 'lib' -mindepth 1 -maxdepth 1 -exec rm -rf {} +; \ + else \ + rm -rf $(INSTALL_LIB_DIR); \ + fi + # Modules -analyzer.$(MODULE_EXT): ast.$(MODULE_EXT) type.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) +# context + +src/context/common.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/display/displayTypes.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT) + +src/context/meta.$(MODULE_EXT): src/globals.$(MODULE_EXT) + +# display + +src/display/display.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/path.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/display/displayTypes.$(MODULE_EXT) + +src/display/displayTypes.$(MODULE_EXT) : src/globals.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) + +src/display/displayOutput.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/typer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/display/display.$(MODULE_EXT) + +# generators + +src/generators/codegen.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/generators/genxml.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) + +src/generators/genas3.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) + +src/generators/gencommon.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/typing/error.$(MODULE_EXT) src/typing/overloads.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT) + +src/generators/gencpp.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) + +src/generators/gencs.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/generators/gencommon.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT) + +src/generators/genjava.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/generators/gencommon.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) + +src/generators/genjs.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) + +src/generators/genneko.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) -codegen.$(MODULE_EXT): optimizer.$(MODULE_EXT) typeload.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) genxml.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT) +src/generators/genlua.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) -common.$(MODULE_EXT): type.$(MODULE_EXT) ast.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT) +src/generators/genphp.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) -dce.$(MODULE_EXT): ast.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) type.$(MODULE_EXT) +src/generators/genpy.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) -filters.$(MODULE_EXT): ast.$(MODULE_EXT) analyzer.$(MODULE_EXT) common.$(MODULE_EXT) type.$(MODULE_EXT) dce.$(MODULE_EXT) codegen.$(MODULE_EXT) typecore.$(MODULE_EXT) +src/generators/genswf.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/generators/genswf9.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) -genas3.$(MODULE_EXT): type.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) +src/generators/hlinterp.$(MODULE_EXT): src/context/common.$(MODULE_EXT) src/generators/hlcode.$(MODULE_EXT) src/macro/interp.$(MODULE_EXT) src/generators/hlopt.$(MODULE_EXT) src/macro/macroApi.$(MODULE_EXT) -gencommon.$(MODULE_EXT): type.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT) +src/generators/genphp7.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) -gencpp.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) gencommon.$(MODULE_EXT) +src/generators/hl2c.$(MODULE_EXT): src/generators/hlcode.$(MODULE_EXT) src/context/common.$(MODULE_EXT) -gencs.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) gencommon.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT) +src/generators/hlopt.$(MODULE_EXT): src/generators/hlcode.$(MODULE_EXT) -genjava.$(MODULE_EXT): type.$(MODULE_EXT) gencommon.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) +src/generators/genhl.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/generators/hlcode.$(MODULE_EXT) src/generators/hlinterp.$(MODULE_EXT) src/generators/hl2c.$(MODULE_EXT) src/generators/hlopt.$(MODULE_EXT) -genjs.$(MODULE_EXT): type.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) +src/generators/genswf9.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) -genneko.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) +src/generators/genxml.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) -genphp.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) +# macro -genpy.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) +src/macro/interp.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/typing/error.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/generators/genneko.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/generators/genswf.$(MODULE_EXT) src/generators/genjava.$(MODULE_EXT) src/generators/gencs.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT) src/macro/macroApi.$(MODULE_EXT) libs/pcre/pcre.$(LIB_EXT) -genswf.$(MODULE_EXT): type.$(MODULE_EXT) genswf9.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT) +src/macro/macroContext.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/typing/error.$(MODULE_EXT) src/optimization/optimizerTexpr.$(MODULE_EXT) src/typing/overloads.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/typeload.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/optimization/optimizer.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/macro/interp.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/optimization/filters.$(MODULE_EXT) src/generators/genjs.$(MODULE_EXT) src/display/display.$(MODULE_EXT) src/macro/hlmacro.$(MODULE_EXT) src/macro/macroApi.$(MODULE_EXT) -genswf9.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) +src/macro/hlmacro.$(MODULE_EXT): src/generators/hlinterp.$(MODULE_EXT) src/generators/genhl.$(MODULE_EXT) src/macro/macroApi.$(MODULE_EXT) -genxml.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT) +src/macro/macroApi.$(MODULE_EXT): src/generators/genjs.$(MODULE_EXT) src/generators/gencs.$(MODULE_EXT) src/generators/genjava.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) -interp.$(MODULE_EXT): typecore.$(MODULE_EXT) type.$(MODULE_EXT) lexer.$(MODULE_EXT) genneko.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) genswf.$(MODULE_EXT) genjava.$(MODULE_EXT) gencs.$(MODULE_EXT) parser.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT) +# optimization -matcher.$(MODULE_EXT): optimizer.$(MODULE_EXT) codegen.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) typer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT) +src/optimization/analyzer.$(MODULE_EXT): src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/optimization/optimizer.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/optimization/analyzerConfig.$(MODULE_EXT) src/optimization/analyzerTypes.$(MODULE_EXT) src/optimization/analyzerTexpr.$(MODULE_EXT) src/optimization/analyzerTexprTransformer.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) -main.$(MODULE_EXT): filters.$(MODULE_EXT) matcher.$(MODULE_EXT) typer.$(MODULE_EXT) typeload.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) interp.$(MODULE_EXT) genxml.$(MODULE_EXT) genswf.$(MODULE_EXT) genphp.$(MODULE_EXT) genneko.$(MODULE_EXT) genjs.$(MODULE_EXT) gencpp.$(MODULE_EXT) genas3.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) gencommon.$(MODULE_EXT) genjava.$(MODULE_EXT) gencs.$(MODULE_EXT) genpy.$(MODULE_EXT) version.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT) +src/optimization/analyzerConfig.$(MODULE_EXT): src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/context/common.$(MODULE_EXT) -optimizer.$(MODULE_EXT): typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT) +src/optimization/analyzerTexpr.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/typing/error.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/optimization/analyzerConfig.$(MODULE_EXT) src/optimization/optimizerTexpr.$(MODULE_EXT) src/generators/genphp7.$(MODULE_EXT) -parser.$(MODULE_EXT): parser.ml lexer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT) +src/optimization/analyzerTexprTransformer.$(MODULE_EXT): src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/typing/error.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/optimization/analyzerConfig.$(MODULE_EXT) src/optimization/analyzerTypes.$(MODULE_EXT) src/optimization/analyzerTexpr.$(MODULE_EXT) + +src/optimization/analyzerTypes.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/optimization/analyzerConfig.$(MODULE_EXT) + +src/optimization/dce.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/error.$(MODULE_EXT) src/path.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) + +src/optimization/filters.$(MODULE_EXT): src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/typing/error.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/optimization/analyzer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/optimization/dce.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) + +src/optimization/optimizer.$(MODULE_EXT): src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/optimization/optimizerTexpr.$(MODULE_EXT) src/display/display.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) + +src/optimization/optimizerTexpr.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) + +# syntax + +src/syntax/ast.$(MODULE_EXT): src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) + +src/syntax/lexer.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/syntax/lexer.ml src/syntax/ast.$(MODULE_EXT) + +src/syntax/parser.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/path.$(MODULE_EXT) src/syntax/parser.ml src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) $(CC_PARSER_CMD) -type.$(MODULE_EXT): ast.$(MODULE_EXT) +# typing + +src/typing/abstract.$(MODULE_EXT): src/context/meta.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/error.$(MODULE_EXT) + +src/typing/error.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) -typecore.$(MODULE_EXT): type.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT) +src/typing/matcher.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/typing/error.$(MODULE_EXT) src/optimization/optimizer.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/typer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) -typeload.$(MODULE_EXT): typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT) +src/typing/overloads.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) -typer.$(MODULE_EXT): typeload.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) interp.$(MODULE_EXT) genneko.$(MODULE_EXT) genjs.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) filters.$(MODULE_EXT) gencommon.$(MODULE_EXT) +src/typing/type.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/json.$(MODULE_EXT) -lexer.$(MODULE_EXT): lexer.ml +src/typing/typecore.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) -lexer.$(MODULE_EXT): ast.$(MODULE_EXT) +src/typing/typeload.$(MODULE_EXT): src/globals.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/optimization/optimizerTexpr.$(MODULE_EXT) src/typing/overloads.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/optimization/optimizer.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/json.$(MODULE_EXT) src/display/display.$(MODULE_EXT) -ast.$(MODULE_EXT): +src/typing/typer.$(MODULE_EXT): src/typing/abstract.$(MODULE_EXT) src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/typing/error.$(MODULE_EXT) src/optimization/optimizerTexpr.$(MODULE_EXT) src/typing/overloads.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/typeload.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/optimization/optimizer.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/macro/interp.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/optimization/filters.$(MODULE_EXT) src/generators/genjs.$(MODULE_EXT) src/display/display.$(MODULE_EXT) src/macro/macroContext.$(MODULE_EXT) -version.$(MODULE_EXT): - $(MAKE) -f Makefile.version_extra -s ADD_REVISION=$(ADD_REVISION) BRANCH=$(BRANCH) COMMIT_SHA=$(COMMIT_SHA) COMMIT_DATE=$(COMMIT_DATE) > version.ml - $(COMPILER) $(CFLAGS) -c version.ml +# main + +src/main.$(MODULE_EXT): src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/typing/error.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/path.$(MODULE_EXT) src/optimization/filters.$(MODULE_EXT) src/typing/matcher.$(MODULE_EXT) src/typing/typer.$(MODULE_EXT) src/typing/typeload.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/optimization/optimizer.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/macro/interp.$(MODULE_EXT) src/generators/genxml.$(MODULE_EXT) src/generators/genswf.$(MODULE_EXT) src/generators/genphp.$(MODULE_EXT) src/generators/genphp7.$(MODULE_EXT) src/generators/genneko.$(MODULE_EXT) src/generators/genjs.$(MODULE_EXT) src/generators/genlua.$(MODULE_EXT) src/generators/gencpp.$(MODULE_EXT) src/generators/genas3.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/generators/genjava.$(MODULE_EXT) src/generators/gencs.$(MODULE_EXT) src/generators/genpy.$(MODULE_EXT) src/generators/genhl.$(MODULE_EXT) src/display/display.$(MODULE_EXT) src/server.$(MODULE_EXT) src/display/displayOutput.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT) + +src/globals.$(MODULE_EXT): src/version.$(MODULE_EXT) + +src/path.$(MODULE_EXT): src/globals.$(MODULE_EXT) + +src/server.$(MODULE_EXT): src/context/meta.$(MODULE_EXT) src/globals.$(MODULE_EXT) src/path.$(MODULE_EXT) src/typing/typer.$(MODULE_EXT) src/typing/typeload.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/context/common.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/display/displayOutput.$(MODULE_EXT) + +src/version.$(MODULE_EXT): + $(MAKE) -f Makefile.version_extra -s --no-print-directory ADD_REVISION=$(ADD_REVISION) BRANCH=$(BRANCH) COMMIT_SHA=$(COMMIT_SHA) COMMIT_DATE=$(COMMIT_DATE) > src/version.ml + $(COMPILER) $(ALL_CFLAGS) -c src/version.ml # Package -package_bin: - mkdir -p out +package_src: + mkdir -p $(PACKAGE_OUT_DIR) + # use git-archive-all since we have submodules + # https://github.com/Kentzo/git-archive-all + curl -s https://raw.githubusercontent.com/Kentzo/git-archive-all/1.15/git_archive_all.py -o extra/git_archive_all.py + python extra/git_archive_all.py $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_src$(PACKAGE_SRC_EXTENSION) + +package_unix: + mkdir -p $(PACKAGE_OUT_DIR) rm -rf $(PACKAGE_FILE_NAME) $(PACKAGE_FILE_NAME).tar.gz # Copy the package contents to $(PACKAGE_FILE_NAME) mkdir -p $(PACKAGE_FILE_NAME) cp -r $(OUTPUT) haxelib$(EXTENSION) std extra/LICENSE.txt extra/CONTRIB.txt extra/CHANGES.txt $(PACKAGE_FILE_NAME) # archive - tar -zcf out/$(PACKAGE_FILE_NAME).tar.gz $(PACKAGE_FILE_NAME) + tar -zcf $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_bin.tar.gz $(PACKAGE_FILE_NAME) rm -r $(PACKAGE_FILE_NAME) +package_bin: package_$(PLATFORM) + +install_dox: + haxelib git hxparse https://github.com/Simn/hxparse master src + haxelib git hxtemplo https://github.com/Simn/hxtemplo + haxelib git hxargs https://github.com/Simn/hxargs + haxelib git markdown https://github.com/dpeek/haxe-markdown master src + haxelib git hxcpp https://github.com/HaxeFoundation/hxcpp + haxelib git hxjava https://github.com/HaxeFoundation/hxjava + haxelib git hxcs https://github.com/HaxeFoundation/hxcs + haxelib git dox https://github.com/HaxeFoundation/dox + +package_doc: + mkdir -p $(PACKAGE_OUT_DIR) + cd $$(haxelib path dox | head -n 1) && haxe run.hxml && haxe gen.hxml + haxelib run dox -theme haxe_api -D website "http://haxe.org/" --title "Haxe API" -o $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_doc.zip -D version "$$(haxe -version 2>&1)" -i $$(haxelib path dox | head -n 1)bin/xml -ex microsoft -ex javax -ex cs.internal -D source-path https://github.com/HaxeFoundation/haxe/blob/$(BRANCH)/std/ + +deploy_doc: + scp $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_doc.zip www-haxe@api.haxe.org:/data/haxeapi/www/v/dev/api-latest.zip + ssh www-haxe@api.haxe.org "cd /data/haxeapi/www/v/dev && find . ! -name 'api-latest.zip' -maxdepth 1 -mindepth 1 -exec rm -rf {} + && unzip -q -o api-latest.zip" + # Clean -clean: clean_libs clean_haxe clean_tools +clean: clean_libs clean_haxe clean_tools clean_package clean_libs: make -C libs/extlib clean @@ -205,13 +330,17 @@ clean_libs: make -C libs/xml-light clean make -C libs/ttflib clean make -C libs/objsize clean + make -C libs/pcre clean clean_haxe: - rm -f $(MODULES:=.obj) $(MODULES:=.o) $(MODULES:=.cmx) $(MODULES:=.cmi) $(MODULES:=.cmo) lexer.ml $(OUTPUT) + rm -f -r $(MODULES:%=src/%.obj) $(MODULES:%=src/%.o) $(MODULES:%=src/%.cmx) $(MODULES:%=src/%.cmi) $(MODULES:%=src/%.cmo) $(MODULES:%=src/%.cmt) src/syntax/lexer.ml src/version.ml $(OUTPUT) clean_tools: rm -f $(OUTPUT) haxelib +clean_package: + rm -rf $(PACKAGE_OUT_DIR) + # SUFFIXES .ml.cmx: diff --git a/Makefile.win b/Makefile.win index d00c42c4..05c46e8f 100644 --- a/Makefile.win +++ b/Makefile.win @@ -1,7 +1,8 @@ +PLATFORM=win include Makefile - OUTPUT=haxe.exe EXTENSION=.exe +PACKAGE_SRC_EXTENSION=.zip OCAMLOPT=ocamlopt.opt @@ -31,21 +32,32 @@ FILTER=sed '/File/{ N; s/File "\([^"]\+\)", line \([0-9]\+\), characters \([0-9- endif ifdef FILTER -CC_CMD=($(OCAMLOPT) $(CFLAGS) -c $< 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1) -CC_PARSER_CMD=($(OCAMLOPT) -pp camlp4o $(CFLAGS) -c parser.ml 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1) +CC_CMD=($(OCAMLOPT) $(ALL_CFLAGS) -c $< 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1) +CC_PARSER_CMD=($(OCAMLOPT) -pp camlp4o $(ALL_CFLAGS) -c src/syntax/parser.ml 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1) endif -package_bin: +PACKAGE_FILES=$(OUTPUT) haxelib$(EXTENSION) std "$$(cygpath -w "$$(which zlib1.dll)")" "$$(cygpath -w "$$(which libpcre-1.dll)")" + +package_win: mkdir -p out rm -rf $(PACKAGE_FILE_NAME) $(PACKAGE_FILE_NAME).zip temp.zip # Copy the package contents to $(PACKAGE_FILE_NAME) # Using poor man's cp (zip then unzip), because cp in cygwin is quite broken mkdir -p $(PACKAGE_FILE_NAME) - 7za a -y -tzip -mx0 temp.zip $(OUTPUT) haxelib$(EXTENSION) std > log.txt || type log.txt - cd extra && 7za a -y -tzip -mx0 ../temp.zip LICENSE.txt CONTRIB.txt CHANGES.txt > log.txt || type log.txt - 7za x -y temp.zip -o$(PACKAGE_FILE_NAME) > log.txt || type log.txt + 7z a -y -tzip -mx0 temp.zip $(PACKAGE_FILES) > log.txt || type log.txt + cd extra && 7z a -y -tzip -mx0 ../temp.zip LICENSE.txt CONTRIB.txt CHANGES.txt > log.txt || type log.txt + 7z x -y temp.zip -o$(PACKAGE_FILE_NAME) > log.txt || type log.txt rm temp.zip # archive - 7za a -r -tzip out/$(PACKAGE_FILE_NAME).zip $(PACKAGE_FILE_NAME) > log.txt || type log.txt + 7z a -r -tzip out/$(PACKAGE_FILE_NAME)_bin.zip $(PACKAGE_FILE_NAME) > log.txt || type log.txt rm -r $(PACKAGE_FILE_NAME) - rm log.txt extra/log.txt \ No newline at end of file + rm log.txt extra/log.txt + +package_choco: + mkdir -p OUTPUT + 7z x -y out/$(PACKAGE_FILE_NAME)_bin.zip -oout > log.txt || type log.txt + mv out/$(PACKAGE_FILE_NAME) out/choco + sed -e 's/@SNAPSHOT_VERSION@/$(HAXE_VERSION)-SNAP$(COMMIT_DATE)/g' extra/choco/haxe.nuspec > out/choco/haxe.nuspec + cd out/choco && choco pack + mv out/choco/haxe.*.nupkg out + rm -rf out/choco diff --git a/README.md b/README.md index 51bf386e..a85db2d9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# [Haxe logo](http://haxe.org) - [The Cross-Platform Toolkit](http://haxe.org) +# [Haxe logo](https://haxe.org) - [The Cross-Platform Toolkit](https://haxe.org) [![TravisCI Build Status](https://travis-ci.org/HaxeFoundation/haxe.svg?branch=development)](https://travis-ci.org/HaxeFoundation/haxe) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/HaxeFoundation/haxe?branch=development&svg=true)](https://ci.appveyor.com/project/HaxeFoundation/haxe) [![SauceLabs Test Status](https://saucelabs.com/buildstatus/haxe)](https://saucelabs.com/u/haxe) @@ -22,31 +22,34 @@ Haxe allows you to compile for the following targets: * NekoVM * PHP * Python + * Lua + * [HashLink](http://hashlink.haxe.org/) You can try Haxe directly from your browser at [try.haxe.org](http://try.haxe.org)! -For more information about Haxe, head to the [offical Haxe website](http://haxe.org). +For more information about Haxe, head to the [offical Haxe website](https://haxe.org). ## License The Haxe project has several licenses, covering different parts of the projects. * The Haxe compiler is released under the GNU General Public License version 2 or any later version. - * The Haxe libraries are released under a "two-clause" BSD license. - * The Neko runtime is licensed under the GNU Lesser General Public License version 2.1 or any later version. + * The Haxe standard library is released under the MIT license. + * The Neko virtual machine is released under the MIT license. Its bundled runtime libraries (ndll) and tools are released under open source licenses as described in https://github.com/HaxeFoundation/neko/blob/master/LICENSE -For the complete Haxe licenses, please see http://haxe.org/foundation/open-source.html or [extra/LICENSE.txt](extra/LICENSE.txt). +For the complete Haxe licenses, please see https://haxe.org/foundation/open-source.html or [extra/LICENSE.txt](extra/LICENSE.txt). ## Installing Haxe -The latest stable release is [Haxe 3.2.0-rc2](http://haxe.org/download/version/3.2.0-rc.2/). Pre-built binaries are available for your platform: +The latest stable release is available at [https://haxe.org/download/](https://haxe.org/download/). Pre-built binaries are available for your platform: - * **[Windows installer](http://haxe.org/download/file/3.2.0-rc.2/haxe-3.2.0-rc2-win.exe)** - * **[Windows binaries](http://haxe.org/download/file/3.2.0-rc.2/haxe-3.2.0-rc2-win.zip)** - * **[OSX installer](http://haxe.org/download/file/3.2.0-rc.2/haxe-3.2.0-rc2-osx-installer.pkg)** - * **[OSX binaries](http://haxe.org/download/file/3.2.0-rc.2/haxe-3.2.0-rc2-osx.tar.gz)** - * **[Linux 32-bit binaries](http://haxe.org/download/file/3.2.0-rc.2/haxe-3.2.0-rc2-linux32.tar.gz)** - * **[Linux 64-bit binaries](http://haxe.org/download/file/3.2.0-rc.2/haxe-3.2.0-rc2-linux64.tar.gz)** + * **[Windows installer](https://haxe.org/download/file/latest/haxe-latest-win.exe/)** + * **[Windows binaries](https://haxe.org/download/file/latest/haxe-latest-win.zip/)** + * **[OSX installer](https://haxe.org/download/file/latest/haxe-latest-osx-installer.pkg/)** + * **[OSX binaries](https://haxe.org/download/file/latest/haxe-latest-osx.tar.gz/)** + * **[Linux Software Packages](https://haxe.org/download/linux/)** + * **[Linux 32-bit binaries](https://haxe.org/download/file/latest/haxe-latest-linux32.tar.gz/)** + * **[Linux 64-bit binaries](https://haxe.org/download/file/latest/haxe-latest-linux64.tar.gz/)** Automated development builds are available from [build.haxe.org](http://build.haxe.org). @@ -57,24 +60,29 @@ Automated development builds are available from [build.haxe.org](http://build.ha git clone --recursive git://github.com/HaxeFoundation/haxe.git cd haxe - 2. Follow the [documentation on building Haxe for your platform](http://haxe.org/documentation/introduction/building-haxe.html). + 2. Follow the [documentation on building Haxe for your platform](https://haxe.org/documentation/introduction/building-haxe.html). ## Using Haxe -For information on on using Haxe, consult the [Haxe documentation](http://haxe.org/documentation): +For information on on using Haxe, consult the [Haxe documentation](https://haxe.org/documentation/): - * [Haxe Introduction](http://haxe.org/documentation/introduction), an introduction to the Haxe toolkit - * [The Haxe Manual](http://haxe.org/manual), the reference manual for the Haxe language + * [Haxe Introduction](https://haxe.org/documentation/introduction/), an introduction to the Haxe toolkit + * [The Haxe Manual](https://haxe.org/manual/), the reference manual for the Haxe language + * [Haxe Code Cookbook](http://code.haxe.org), code snippets / learning resource * [Haxe API](http://api.haxe.org), documentation for the Haxe standard and native APIs - * [Haxelib](http://lib.haxe.org), a repository of Haxe libraries for a variety of needs + * [Haxelib](https://lib.haxe.org), a repository of Haxe libraries for a variety of needs ## Community You can get help and talk with fellow Haxers from around the world via: + * [Haxe on Stack Overflow](http://stackoverflow.com/questions/tagged/haxe) * the [official Haxe Google Group](https://groups.google.com/forum/#!forum/haxelang) + * [#Haxe on Twitter](https://twitter.com/hashtag/haxe?src=hash) * the [Haxe IRC chatroom](http://unic0rn.github.io/tiramisu/haxe), #haxe on chat.freenode.net +:+1: Get notified of the latest Haxe news, follow us on [Twitter](https://twitter.com/haxelang), [Facebook](https://www.facebook.com/haxe.org) or [Google+](https://plus.google.com/+HaxeOrg) + ## Version compatibility Haxe | neko @@ -82,3 +90,11 @@ Haxe | neko 2.* | 1.* 3.0.0 | 2.0.0 3.1.3 | 2.0.0 +3.2.0 | 2.0.0 +3.3.0 | 2.1.0 +3.4.0 | 2.1.0 + + +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for more. Thank you! diff --git a/analyzer.ml b/analyzer.ml deleted file mode 100644 index e5933e37..00000000 --- a/analyzer.ml +++ /dev/null @@ -1,1667 +0,0 @@ -open Ast -open Type -open Common -open Typecore - -let s_expr = s_expr (s_type (print_context())) -let s_expr_pretty = s_expr_pretty "" (s_type (print_context())) -let debug e = print_endline (s_expr e) -let debug_pretty s e = Printf.printf "%s %s\n" s (s_expr_pretty e) - -let flag_no_check = "no_check" -let flag_check = "check" -let flag_no_const_propagation = "no_const_propagation" -let flag_const_propagation = "const_propagation" -let flag_no_local_dce = "no_local_dce" -let flag_local_dce = "local_dce" -let flag_ignore = "ignore" -let flag_no_simplification = "no_simplification" -let flag_check_has_effect = "check_has_effect" -let flag_no_check_has_effect = "no_check_has_effect" - -let has_analyzer_option meta s = - try - let rec loop ml = match ml with - | (Meta.Analyzer,el,_) :: ml -> - if List.exists (fun (e,p) -> - match e with - | EConst(Ident s2) when s = s2 -> true - | _ -> false - ) el then - true - else - loop ml - | _ :: ml -> - loop ml - | [] -> - false - in - loop meta - with Not_found -> - false - -let is_ignored meta = - try - let rec loop ml = match ml with - | (Meta.Analyzer,el,_) :: ml -> - if List.exists (fun (e,p) -> - match e with - | EConst(Ident s2) when flag_ignore = s2 -> true - | _ -> false - ) el then - true - else - loop ml - | (Meta.HasUntyped,_,_) :: _ -> - true - | _ :: ml -> - loop ml - | [] -> - false - in - loop meta - with Not_found -> - false - -let rec get_type_meta t = match t with - | TMono r -> - begin match !r with - | None -> raise Not_found - | Some t -> get_type_meta t - end - | TLazy f -> - get_type_meta (!f()) - | TInst(c,_) -> - c.cl_meta - | TEnum(en,_) -> - en.e_meta - | TAbstract(a,_) -> - a.a_meta - | TType(t,_) -> - t.t_meta - | TAnon _ | TFun _ | TDynamic _ -> - raise Not_found - -let type_has_analyzer_option t s = - try - has_analyzer_option (get_type_meta t) s - with Not_found -> - false - -let is_enum_type t = match follow t with - | TEnum(_) -> true - | _ -> false - -let rec awkward_get_enum_index com e = match e.eexpr with - | TArray(e1,{eexpr = TConst(TInt i)}) when com.platform = Js && Int32.to_int i = 1 && is_enum_type e1.etype -> - e1 - | TCall({eexpr = TField(e1, FDynamic "__Index")},[]) when com.platform = Cpp && is_enum_type e1.etype -> - e1 - | TField(e1,FDynamic "index") when com.platform = Neko && is_enum_type e1.etype -> - e1 - | TParenthesis e1 | TCast(e1,None) | TMeta(_,e1) -> - awkward_get_enum_index com e1 - | _ -> - raise Not_found - -(* - This module simplifies the AST by introducing temporary variables for complex expressions in many places. - In particular, it ensures that no branching can occur in value-places so that we can later insert SSA PHI - nodes without worrying about their placement. -*) -module Simplifier = struct - let mk_block_context com = - let block_el = ref [] in - let push e = block_el := e :: !block_el in - let assign ev e = - let mk_assign e2 = match e2.eexpr with - | TBreak | TContinue | TThrow _ | TReturn _ -> e2 - | _ -> mk (TBinop(OpAssign,ev,e2)) e2.etype e2.epos - in - let rec loop e = match e.eexpr with - | TBlock el -> - begin match List.rev el with - | e1 :: el -> - let el = List.rev ((loop e1) :: el) in - {e with eexpr = TBlock el} - | _ -> - mk_assign e - end - | TIf(e1,e2,eo) -> - let e2 = loop e2 in - let eo = match eo with None -> None | Some e3 -> Some (loop e3) in - {e with eexpr = TIf(e1,e2,eo)} - | TSwitch(e1,cases,edef) -> - let cases = List.map (fun (el,e) -> - let e = loop e in - el,e - ) cases in - let edef = match edef with None -> None | Some edef -> Some (loop edef) in - {e with eexpr = TSwitch(e1,cases,edef)} - | TTry(e1,catches) -> - let e1 = loop e1 in - let catches = List.map (fun (v,e) -> - let e = loop e in - v,e - ) catches in - {e with eexpr = TTry(e1,catches)} - | TParenthesis e1 | TMeta(_,e1) -> - loop e1 (* this is still weird, have to review *) -(* | TBinop(OpAssign,({eexpr = TLocal _} as e1),e2) -> - push e; - mk_assign e1 *) -(* | TBinop(OpAssignOp op,({eexpr = TLocal _} as e1),e2) -> - push e; - mk_assign e1 *) - | _ -> - mk_assign e - in - loop e - in - let declare_temp t eo p = - let v = alloc_var "tmp" t in - v.v_meta <- [Meta.CompilerGenerated,[],p]; - let e_v = mk (TLocal v) t p in - let declare e_init = - let e = mk (TVar (v,e_init)) com.basic.tvoid p in - push e; - in - let e_v = match eo with - | None -> - declare None; - e_v - | Some e1 -> - begin match e1.eexpr with - | TThrow _ | TReturn _ | TBreak | TContinue -> - e1 - | _ -> - let rec loop e_v e = match e.eexpr with - | TParenthesis e1 -> - loop {e_v with eexpr = TParenthesis e_v} e1 - | TMeta(m,e1) -> - loop {e_v with eexpr = TMeta(m,e_v)} e1 - | _ -> - e_v,e - in - let e_v',e1 = loop e_v e1 in - let e1 = assign e_v e1 in - begin match e1.eexpr with - | TBinop(OpAssign,{eexpr = TLocal v1},e2) when v == v1 -> - declare (Some e2) - | _ -> - declare None; - push e1 - end; - e_v' - end - in - e_v - in - let rec push_block () = - let cur = !block_el in - block_el := []; - fun () -> - let added = !block_el in - block_el := cur; - List.rev added - and block f el = - let close = push_block() in - List.iter (fun e -> - push (f e) - ) el; - close() - in - block,declare_temp,fun () -> !block_el - - let apply com e = - let block,declare_temp,close_block = mk_block_context com in - let skip_binding ?(allow_tlocal=false) e = - let rec loop e = - match e.eexpr with - | TConst _ | TTypeExpr _ | TFunction _ -> () - | TLocal _ when allow_tlocal -> () - | TParenthesis e1 | TCast(e1,None) -> Type.iter loop e - | TField(_,(FStatic(c,cf) | FInstance(c,_,cf))) when has_analyzer_option cf.cf_meta flag_no_simplification || has_analyzer_option c.cl_meta flag_no_simplification -> () - | TField({eexpr = TLocal _},_) when allow_tlocal -> () - | TCall({eexpr = TField(_,(FStatic(c,cf) | FInstance(c,_,cf)))},el) when has_analyzer_option cf.cf_meta flag_no_simplification || has_analyzer_option c.cl_meta flag_no_simplification -> () - | TCall({eexpr = TLocal { v_name = "__cpp__" } },_) -> () - | TField(_,FEnum _) -> () - | TField(_,FDynamic _) -> () - | _ when (try ignore(awkward_get_enum_index com e); true with Not_found -> false) -> () - | _ -> raise Exit - in - try - loop e; - true - with Exit -> - begin match follow e.etype with - | TAbstract({a_path = [],"Void"},_) -> true - | TInst ({ cl_path = [],"Array" }, _) when com.platform = Cpp -> true - | _ -> false - end - in - let has_unbound = ref false in - let rec loop e = match e.eexpr with - | TCall({eexpr = TLocal v | TField({eexpr = TLocal v},_)},_) | TField({eexpr = TLocal v},_) | TLocal v when Meta.has Meta.Unbound v.v_meta && v.v_name <> "`trace" -> - has_unbound := true; - e - | TBlock el -> - {e with eexpr = TBlock (block loop el)} - | TCall({eexpr = TField(_,(FStatic(c,cf) | FInstance(c,_,cf)))},el) when has_analyzer_option cf.cf_meta flag_no_simplification || has_analyzer_option c.cl_meta flag_no_simplification -> - e - | TField(_,(FStatic(c,cf) | FInstance(c,_,cf))) when has_analyzer_option cf.cf_meta flag_no_simplification || has_analyzer_option c.cl_meta flag_no_simplification -> - e - | TCall(e1,el) -> - let rec is_valid_call_target e = match e.eexpr with - | TFunction _ | TField _ | TLocal _ | TConst (TSuper) -> - true - | TParenthesis e1 | TCast(e1,None) | TMeta(_,e1) -> - is_valid_call_target e1 - | _ -> - false - in - let e1 = if is_valid_call_target e1 then - loop e1 - else - bind e1 - in - let check e t = - if type_has_analyzer_option t flag_no_simplification then e - else bind e - in - let el = match e1.eexpr,follow e1.etype with - | TConst TSuper,_ when com.platform = Java || com.platform = Cs -> - (* they hate you if you mess up the super call *) - el - | _,TFun _ | TConst TSuper,_ -> - Codegen.UnificationCallback.check_call check el e1.etype - | _ -> - (* too dangerous *) - List.map loop el - in - {e with eexpr = TCall(e1,el)} - | TNew(c,tl,el) -> - {e with eexpr = TNew(c,tl,ordered_list el)} - | TArrayDecl el -> - {e with eexpr = TArrayDecl (ordered_list el)} - | TObjectDecl fl -> - let el = ordered_list (List.map snd fl) in - {e with eexpr = TObjectDecl (List.map2 (fun (n,_) e -> n,e) fl el)} - | TBinop(OpBoolAnd | OpBoolOr as op,e1,e2) -> - let e1 = loop e1 in - let e_then = mk (TBlock (block loop [e2])) e2.etype e2.epos in - let e_if,e_else = if op = OpBoolOr then - mk (TUnop(Not,Prefix,e1)) com.basic.tbool e.epos,mk (TConst (TBool(true))) com.basic.tbool e.epos - else - e1,mk (TConst (TBool(false))) com.basic.tbool e.epos - in - loop (mk (TIf(e_if,e_then,Some e_else)) com.basic.tbool e.epos) - | TBinop((OpAssign | OpAssignOp _) as op,{eexpr = TArray(e11,e12)},e2) -> - let e1 = match ordered_list [e11;e12] with - | [e1;e2] -> - {e with eexpr = TArray(e1,e2)} - | _ -> - assert false - in - let e2 = bind e2 in - {e with eexpr = TBinop(op,e1,e2)} - | TBinop((OpAssign | OpAssignOp _) as op,e1,e2) -> - let e2 = bind ~allow_tlocal:true e2 in - let e1 = loop e1 in - {e with eexpr = TBinop(op,e1,e2)} - | TBinop(op,e1,e2) -> - begin match ordered_list [e1;e2] with - | [e1;e2] -> - {e with eexpr = TBinop(op,e1,e2)} - | _ -> - assert false - end - | TArray(e1,e2) -> - begin match ordered_list [e1;e2] with - | [e1;e2] -> - {e with eexpr = TArray(e1,e2)} - | _ -> - assert false - end - | TWhile(e1,e2,flag) when (match e1.eexpr with TConst(TBool true) | TParenthesis {eexpr = TConst(TBool true)} -> false | _ -> true) -> - let p = e.epos in - let e_break = mk TBreak t_dynamic p in - let e_not = mk (TUnop(Not,Prefix,Codegen.mk_parent e1)) e1.etype e1.epos in - let e_if eo = mk (TIf(e_not,e_break,eo)) com.basic.tvoid p in - let rec map_continue e = match e.eexpr with - | TContinue -> - (e_if (Some e)) - | TWhile _ | TFor _ -> - e - | _ -> - Type.map_expr map_continue e - in - let e2 = if flag = NormalWhile then e2 else map_continue e2 in - let e_if = e_if None in - let e_if = mk (TMeta((Meta.Custom ":whileCond",[],e_if.epos), e_if)) e_if.etype e_if.epos in - let e_block = if flag = NormalWhile then Type.concat e_if e2 else Type.concat e2 e_if in - let e_true = mk (TConst (TBool true)) com.basic.tbool p in - let e = mk (TWhile(Codegen.mk_parent e_true,e_block,NormalWhile)) e.etype p in - loop e - | TFor(v,e1,e2) -> - let e1 = bind e1 in - let e2 = loop e2 in - {e with eexpr = TFor(v,e1,e2)} - | TIf(e1,e2,eo) -> - let e1 = bind e1 in - let e2 = loop e2 in - let eo = match eo with None -> None | Some e -> Some (loop e) in - {e with eexpr = TIf(e1,e2,eo)} - | TSwitch (e1,cases,eo) -> - let e1 = bind e1 in - let cases = List.map (fun (el,e) -> - let el = List.map loop el in - let e = loop e in - el,e - ) cases in - let eo = match eo with None -> None | Some e -> Some (loop e) in - {e with eexpr = TSwitch(e1,cases,eo)} - | TVar(v,Some e1) -> - let e1 = match e1.eexpr with - | TFunction _ -> loop e1 - | TArrayDecl [{eexpr = TFunction _}] -> loop e1 - | _ -> bind ~allow_tlocal:true e1 - in - {e with eexpr = TVar(v,Some e1)} - | TUnop((Neg | NegBits | Not) as op,flag,e1) -> - let e1 = bind e1 in - {e with eexpr = TUnop(op,flag,e1)} - | TField(e1,fa) -> - let e1 = bind ~allow_tlocal:true e1 in - {e with eexpr = TField(e1,fa)} - | TReturn (Some ({eexpr = TThrow _ | TReturn _} as e1)) -> - loop e1 (* this is a bit hackish *) - | TReturn (Some e1) -> - let e1 = bind e1 in - {e with eexpr = TReturn (Some e1)} - | TThrow e1 -> - let e1 = bind e1 in - {e with eexpr = TThrow e1} - | TCast(e1,mto) -> - let e1 = bind ~allow_tlocal:true e1 in - {e with eexpr = TCast(e1,mto)} - | _ -> - Type.map_expr loop e - and bind ?(allow_tlocal=false) e = - let e = loop e in - if skip_binding ~allow_tlocal e then - e - else - declare_temp e.etype (Some e) e.epos - and ordered_list el = - if List.for_all (skip_binding ~allow_tlocal:true) el then - List.map loop el - else - List.map bind el - in - let e = loop e in - !has_unbound,match close_block() with - | [] -> - e - | el -> - mk (TBlock (List.rev (e :: el))) e.etype e.epos - - let unapply com e = - let var_map = ref IntMap.empty in - let rec get_assignment_to v e = match e.eexpr with - | TBinop(OpAssign,{eexpr = TLocal v2},e2) when v == v2 -> Some e2 - | TBlock [e] -> get_assignment_to v e - | TIf(e1,e2,Some e3) -> - begin match get_assignment_to v e2,get_assignment_to v e3 with - | Some e2,Some e3 -> Some ({e with eexpr = TIf(e1,e2,Some e3)}) - | _ -> None - end - | _ -> None - in - let if_or_op e e1 e2 e3 = match e1.eexpr,e3.eexpr with - | TUnop(Not,Prefix,e1),TConst (TBool true) -> {e with eexpr = TBinop(OpBoolOr,e1,e2)} - | _,TConst (TBool false) -> {e with eexpr = TBinop(OpBoolAnd,e1,e2)} - | _ -> {e with eexpr = TIf(e1,e2,Some e3)} - in - let rec loop e = match e.eexpr with - | TBlock el -> - let rec loop2 el = match el with - | e :: el -> - begin match e.eexpr with - | TVar(v,Some e1) when Meta.has Meta.CompilerGenerated v.v_meta -> - if el = [] then - [loop e1] - else begin - var_map := IntMap.add v.v_id (loop e1) !var_map; - loop2 el - end - | TVar(v,None) when not (com.platform = Php) -> - begin match el with - | {eexpr = TBinop(OpAssign,{eexpr = TLocal v2},e2)} :: el when v == v2 -> - let e = {e with eexpr = TVar(v,Some e2)} in - loop2 (e :: el) - | ({eexpr = TIf(e1,e2,Some e3)} as e_if) :: el -> - let e1 = loop e1 in - let e2 = loop e2 in - let e3 = loop e3 in - begin match get_assignment_to v e2,get_assignment_to v e3 with - | Some e2,Some e3 -> - let e_if = if_or_op e_if (loop e1) (loop e2) (loop e3) in - let e = {e with eexpr = TVar(v,Some e_if)} in - loop2 (e :: el) - | _ -> - let e_if = {e_if with eexpr = TIf(e1,e2,Some e3)} in - e :: e_if :: loop2 el - end - | _ -> - let e = loop e in - e :: loop2 el - end - | TReturn (Some e1) when (match follow e1.etype with TAbstract({a_path=[],"Void"},_) -> true | _ -> false) -> - [(loop e1);{e with eexpr = TReturn None}] - | _ -> - let e = loop e in - e :: loop2 el - end - | [] -> - [] - in - let el = loop2 el in - {e with eexpr = TBlock el} - | TLocal v when Meta.has Meta.CompilerGenerated v.v_meta -> - begin try IntMap.find v.v_id !var_map - with Not_found -> e end - | TWhile(e1,e2,flag) -> - let e1 = loop e1 in - let e2 = loop e2 in - let extract_cond e = match e.eexpr with - | TIf({eexpr = TUnop(Not,_,e1)},_,_) -> e1 - | TBreak -> raise Exit (* can happen due to optimization, not so easy to deal with because there might be other breaks/continues *) - | _ -> assert false - in - let e1,e2,flag = try - begin match e2.eexpr with - | TBlock el -> - begin match el with - | {eexpr = TMeta((Meta.Custom ":whileCond",_,_),e1)} :: el -> - let e1 = extract_cond e1 in - e1,{e2 with eexpr = TBlock el},NormalWhile - | _ -> - e1,e2,flag - (* issue 3844 *) -(* begin match List.rev el with - | {eexpr = TMeta((Meta.Custom ":whileCond",_,_),e1)} :: el -> - let e1 = extract_cond e1 in - e1,{e2 with eexpr = TBlock (List.rev el)},DoWhile - | _ -> - e1,e2,flag - end *) - end - | _ -> - e1,e2,flag - end with Exit -> - e1,e2,flag - in - {e with eexpr = TWhile(e1,e2,flag)} - | TIf(e1,e2,Some e3) -> - let e1 = loop e1 in - let e2 = loop e2 in - let e3 = loop e3 in - if_or_op e e1 e2 e3 - | _ -> - Type.map_expr loop e - in - loop e -end - -module Ssa = struct - - type var_map = tvar IntMap.t - - type condition = - | Equal of tvar * texpr - | NotEqual of tvar * texpr - - type node_data = { - nd_pos: pos; - mutable nd_var_map : var_map; - mutable nd_terminates : bool; - } - - type join_node = { - mutable branches : node_data list; - } - - type ssa_context = { - com : Common.context; - mutable cleanup : (unit -> unit) list; - mutable cur_data : node_data; - mutable var_conds : (condition list) IntMap.t; - mutable loop_stack : (join_node * join_node) list; - mutable exception_stack : join_node list; - mutable block_depth : int; - } - - let s_cond = function - | Equal(v,e) -> Printf.sprintf "%s == %s" v.v_name (s_expr_pretty e) - | NotEqual(v,e) -> Printf.sprintf "%s != %s" v.v_name (s_expr_pretty e) - - let s_conds conds = - String.concat " && " (List.map s_cond conds) - - let mk_loc v p = mk (TLocal v) v.v_type p - - let mk_phi = - let v_phi = alloc_var "__ssa_phi__" t_dynamic in - (fun vl p -> - let e = mk (TCall(mk_loc v_phi p,(List.map (fun (v,p) -> mk_loc v p) vl))) t_dynamic p in - e - ) - - (* TODO: make sure this is conservative *) - let can_throw e = - let rec loop e = match e.eexpr with - | TConst _ | TLocal _ | TTypeExpr _ | TFunction _ | TBlock _ -> () - | TCall _ | TNew _ | TThrow _ | TCast(_,Some _) -> raise Exit - | _ -> Type.iter loop e - in - try - loop e; false - with Exit -> - true - - let mk_join_node() = { - branches = [] - } - - let mk_node_data p = { - nd_pos = p; - nd_var_map = IntMap.empty; - nd_terminates = false; - } - - let add_branch join branch p = - join.branches <- {branch with nd_pos = p} :: join.branches - - let branch ctx p = - let old_map = ctx.cur_data.nd_var_map in - let old_term = ctx.cur_data.nd_terminates in - ctx.cur_data.nd_terminates <- false; - (fun join -> - add_branch join ctx.cur_data p; - ctx.cur_data.nd_var_map <- old_map; - ctx.cur_data.nd_terminates <- old_term; - ) - - let terminate ctx = - ctx.cur_data.nd_terminates <- true - - let set_loop_join ctx join_top join_bottom = - ctx.loop_stack <- (join_top,join_bottom) :: ctx.loop_stack; - (fun () -> - ctx.loop_stack <- List.tl ctx.loop_stack - ) - - let set_exception_join ctx join = - ctx.exception_stack <- join :: ctx.exception_stack; - (fun () -> - ctx.exception_stack <- List.tl ctx.exception_stack; - ) - - let create_v_extra v = - match v.v_extra with - | Some (_,Some _) -> - () - | Some (tl,None) -> - let e_extra = mk (TObjectDecl []) t_dynamic null_pos in - v.v_extra <- Some (tl,Some e_extra) - | None -> - let e_extra = mk (TObjectDecl []) t_dynamic null_pos in - v.v_extra <- Some ([],Some e_extra) - - let set_v_extra_value v s e = match v.v_extra with - | Some (tl, Some {eexpr = TObjectDecl fl}) -> - let rec loop fl = match fl with - | (s',_) :: fl when s' = s -> - (s,e) :: fl - | f1 :: fl -> - f1 :: loop fl - | [] -> - [s,e] - in - let e_extra = mk (TObjectDecl (loop fl)) t_dynamic null_pos in - v.v_extra <- Some (tl, Some e_extra) - | _ -> - assert false - - let get_origin_var v = match v.v_extra with - | Some (_,Some {eexpr = TObjectDecl fl}) -> - begin match List.assoc "origin_var" fl with - | {eexpr = TLocal v'} -> v' - | _ -> raise Not_found - end - | _ -> - raise Not_found - - let set_origin_var v v_origin p = - let ev = mk_loc v_origin p in - set_v_extra_value v "origin_var" ev - - let get_var_value v = match v.v_extra with - | Some (_,Some {eexpr = TObjectDecl fl}) -> - List.assoc "var_value" fl - | _ -> - raise Not_found - - let set_var_value v e = - set_v_extra_value v "var_value" e - - let get_var_usage_count v = match v.v_extra with - | Some (_,Some {eexpr = TObjectDecl fl}) -> - begin try - begin match List.assoc "usage_count" fl with - | {eexpr = TConst (TInt i32)} -> Int32.to_int i32 - | _ -> 0 - end - with Not_found -> - 0 - end - | _ -> - raise Not_found - - let set_var_usage_count v i = - let e = mk (TConst (TInt (Int32.of_int i))) t_dynamic null_pos in - set_v_extra_value v "usage_count" e - - let declare_var ctx v p = - let old = v.v_extra in - ctx.cleanup <- (fun () -> - v.v_extra <- old - ) :: ctx.cleanup; - ctx.cur_data.nd_var_map <- IntMap.add v.v_id v ctx.cur_data.nd_var_map; - v.v_meta <- ((Meta.Custom ":blockDepth",[EConst (Int (string_of_int ctx.block_depth)),p],p)) :: v.v_meta; - v.v_extra <- None; - create_v_extra v; - set_origin_var v v p - - let assign_var ctx v e p = - if v.v_capture then - v - else begin - let i = match v.v_extra with - | Some (l,eo) -> - v.v_extra <- Some (("",t_dynamic) :: l,eo); - List.length l + 1 - | _ -> - error "Something went wrong" p - in - let v' = alloc_var (Printf.sprintf "%s<%i>" v.v_name i) v.v_type in - create_v_extra v'; - v'.v_meta <- [(Meta.Custom ":ssa"),[],p]; - set_origin_var v' v p; - ctx.cur_data.nd_var_map <- IntMap.add v.v_id v' ctx.cur_data.nd_var_map; - set_var_value v' e; - v' - end - - let get_var ctx v p = - try - IntMap.find v.v_id ctx.cur_data.nd_var_map - with Not_found -> - if not (has_meta Meta.Unbound v.v_meta) then - error (Printf.sprintf "Unbound variable %s" v.v_name) p; - v - - let close_join_node ctx node p = - let terminates = ref true in - let branches = List.filter (fun branch -> - if branch.nd_terminates then false - else begin - terminates := false; - true - end - ) node.branches in - match branches with - | [] -> - () - | branch :: branches -> - let vars = ref (IntMap.map (fun v -> [v,branch.nd_pos]) branch.nd_var_map) in - let rec handle_branch branch = - IntMap.iter (fun i v -> - try - let vl = IntMap.find i !vars in - if not (List.exists (fun (v',_) -> v == v') vl) then - vars := IntMap.add i ((v,p) :: vl) !vars - with Not_found -> - () - ) branch.nd_var_map; - in - List.iter handle_branch branches; - ctx.cur_data.nd_terminates <- !terminates; - IntMap.iter (fun i vl -> match vl with - | [v,p] -> - ctx.cur_data.nd_var_map <- IntMap.add i v ctx.cur_data.nd_var_map; - | (v',_) :: _ -> - let v = get_origin_var v' in - ignore(assign_var ctx v (mk_phi vl p) p) - | _ -> - assert false - ) !vars - - let invert_cond = function - | Equal(v,e) -> NotEqual(v,e) - | NotEqual(v,e) -> Equal(v,e) - - let invert_conds = - List.map invert_cond - - let rec eval_cond ctx e = match e.eexpr with - | TBinop(OpNotEq,{eexpr = TLocal v},e1) -> - [NotEqual(v,e1)] - | TBinop(OpEq,{eexpr = TLocal v},e1) -> - [Equal(v,e1)] - | TUnop(Not,_,e1) -> - invert_conds (eval_cond ctx e1) - | TLocal v -> - begin try eval_cond ctx (get_var_value v) - with Not_found -> [] end - | _ -> - [] - - let append_cond ctx v cond p = - begin try - let conds = IntMap.find v.v_id ctx.var_conds in - ctx.var_conds <- IntMap.add v.v_id (cond :: conds) ctx.var_conds - with Not_found -> - ctx.var_conds <- IntMap.add v.v_id [cond] ctx.var_conds - end - -(* let apply_cond ctx = function - | Equal({v_extra = Some(_,Some {eexpr = TLocal v})} as v0,e1) -> - let v' = assign_var ctx v (mk_loc v0 e1.epos) e1.epos in - append_cond ctx v' (Equal(v',e1)) e1.epos - | NotEqual({v_extra = Some(_,Some {eexpr = TLocal v})} as v0,e1) -> - let v' = assign_var ctx v (mk_loc v0 e1.epos) e1.epos in - append_cond ctx v' (NotEqual(v',e1)) e1.epos - | _ -> () - - let apply_not_null_cond ctx v p = - apply_cond ctx (NotEqual(v,(mk (TConst TNull) t_dynamic p))) *) - - let apply com e = - let rec handle_if ctx f econd eif eelse = - let econd = loop ctx econd in - (* let cond = eval_cond ctx econd in *) - let join = mk_join_node() in - let close = branch ctx eif.epos in - (* List.iter (apply_cond ctx) cond; *) - let eif = loop ctx eif in - close join; - let eelse = match eelse with - | None -> - (* let cond = invert_conds cond in *) - (* List.iter (apply_cond ctx) cond; *) - add_branch join ctx.cur_data e.epos; - None - | Some e -> - let close = branch ctx e.epos in - (* let cond = invert_conds cond in *) - (* List.iter (apply_cond ctx) cond; *) - let eelse = loop ctx e in - close join; - Some eelse - in - close_join_node ctx join e.epos; - f econd eif eelse - and handle_loop_body ctx e = - let join_top = mk_join_node() in - let join_bottom = mk_join_node() in - let unset = set_loop_join ctx join_top join_bottom in - let close = branch ctx e.epos in - ignore(loop ctx e); (* TODO: I don't know if this is sane. *) - close join_top; - add_branch join_top ctx.cur_data e.epos; - close_join_node ctx join_top e.epos; - let ebody = loop ctx e in - ctx.cur_data.nd_terminates <- false; - unset(); - close_join_node ctx join_bottom e.epos; - ebody - and loop ctx e = match e.eexpr with - (* var declarations *) - | TVar(v,eo) -> - declare_var ctx v e.epos; - let eo = match eo with - | None -> None - | Some e -> - let e = loop ctx e in - set_var_value v e; - Some e - in - {e with eexpr = TVar(v,eo)} - | TFunction tf -> - let close = branch ctx e.epos in - List.iter (fun (v,co) -> - declare_var ctx v e.epos; -(* match co with - | Some TNull when (match v.v_type with TType({t_path=["haxe"],"PosInfos"},_) -> false | _ -> true) -> () - | _ -> apply_not_null_cond ctx v e.epos *) - ) tf.tf_args; - let e' = loop ctx tf.tf_expr in - close (mk_join_node()); - {e with eexpr = TFunction {tf with tf_expr = e'}} - (* var modifications *) - | TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) when v.v_name <> "this" -> - let e2 = loop ctx e2 in - let _ = assign_var ctx v e2 e1.epos in - {e with eexpr = TBinop(OpAssign,e1,e2)} - | TBinop(OpAssignOp op,({eexpr = TLocal v} as e1),e2) -> - let e1 = loop ctx e1 in - let e2 = loop ctx e2 in - let e_op = mk (TBinop(op,e1,e2)) e.etype e.epos in - let _ = assign_var ctx v e_op e1.epos in - {e with eexpr = TBinop(OpAssignOp op,e1,e2)} - | TUnop((Increment | Decrement as op),flag,({eexpr = TLocal v} as e1)) -> - let op = match op with Increment -> OpAdd | Decrement -> OpSub | _ -> assert false in - let e_one = mk (TConst (TInt (Int32.of_int 1))) com.basic.tint e.epos in - let e1 = loop ctx e1 in - let e_op = mk (TBinop(op,e1,e_one)) e.etype e.epos in - let _ = assign_var ctx v e_op e1.epos in - e - (* var user *) - | TLocal v -> - let v = get_var ctx v e.epos in - {e with eexpr = TLocal v} - (* control flow *) - | TIf(econd,eif,eelse) -> - let f econd eif eelse = {e with eexpr = TIf(econd,eif,eelse)} in - handle_if ctx f econd eif eelse - | TSwitch(e1,cases,edef) -> - let e1 = loop ctx e1 in - let join = mk_join_node() in - let cases = List.map (fun (el,e) -> - let close = branch ctx e.epos in - let el = List.map (loop ctx) el in - let e = loop ctx e in - close join; - el,e - ) cases in - let edef = match edef with - | Some e -> - let close = branch ctx e.epos in - let e = loop ctx e in - close join; - Some e - | None -> - begin match e1.eexpr with - | TMeta((Meta.Exhaustive,_,_),_) - | TParenthesis({eexpr = TMeta((Meta.Exhaustive,_,_),_)}) -> - () - | _ -> - add_branch join ctx.cur_data e.epos; - end; - None - in - close_join_node ctx join e.epos; - let e = {e with eexpr = TSwitch(e1,cases,edef)} in - e - | TWhile(econd,ebody,mode) -> - let econd = loop ctx econd in - let ebody = handle_loop_body ctx ebody in - let e = {e with eexpr = TWhile(econd,ebody,mode)} in - e - | TFor(v,e1,ebody) -> - declare_var ctx v e.epos; - (* apply_not_null_cond ctx v e1.epos; *) - let v' = IntMap.find v.v_id ctx.cur_data.nd_var_map in - let e1 = loop ctx e1 in - let ebody = handle_loop_body ctx ebody in - let e = {e with eexpr = TFor(v',e1,ebody)} in - e - | TTry(e1,catches) -> - let join_ex = mk_join_node() in - let join_bottom = mk_join_node() in - let unset = set_exception_join ctx join_ex in - let e1 = loop ctx e1 in - unset(); - add_branch join_bottom ctx.cur_data e.epos; - close_join_node ctx join_ex e.epos; - let catches = List.map (fun (v,e) -> - declare_var ctx v e.epos; - (* apply_not_null_cond ctx v e.epos; *) - let close = branch ctx e.epos in - let e = loop ctx e in - close join_bottom; - v,e - ) catches in - close_join_node ctx join_bottom e.epos; - let e = {e with eexpr = TTry(e1,catches)} in - e - | TBreak -> - begin match ctx.loop_stack with - | [] -> error "Break outside loop" e.epos - | (_,join) :: _ -> add_branch join ctx.cur_data e.epos - end; - terminate ctx; - e - | TContinue -> - begin match ctx.loop_stack with - | [] -> error "Continue outside loop" e.epos - | (join,_) :: _ -> add_branch join ctx.cur_data e.epos - end; - terminate ctx; - e - | TThrow e1 -> - let e1 = loop ctx e1 in - begin match ctx.exception_stack with - | join :: _ -> add_branch join ctx.cur_data e.epos - | _ -> () - end; - terminate ctx; - {e with eexpr = TThrow e1} - | TReturn eo -> - let eo = match eo with None -> None | Some e -> Some (loop ctx e) in - terminate ctx; - {e with eexpr = TReturn eo} - | TBlock el -> - let rec loop2 el = match el with - | [] -> - [] - | e :: el -> - if ctx.cur_data.nd_terminates then begin - (* ctx.com.warning (Printf.sprintf "Unreachable code: %s" (s_expr_pretty e)) e.epos; *) - [] - end else - let e = loop ctx e in - e :: (loop2 el) - in - ctx.block_depth <- ctx.block_depth + 1; - let el = loop2 el in - ctx.block_depth <- ctx.block_depth - 1; - {e with eexpr = TBlock(el)} - | _ -> - begin match ctx.exception_stack with - | join :: _ when can_throw e -> add_branch join ctx.cur_data e.epos - | _ -> () - end; - Type.map_expr (loop ctx) e - in - let ctx = { - com = com; - cur_data = mk_node_data e.epos; - var_conds = IntMap.empty; - loop_stack = []; - exception_stack = []; - cleanup = []; - block_depth = 0; - } in - let e = loop ctx e in - e,ctx - - let unapply com e = - let rec loop e = match e.eexpr with - | TFor(v,e1,e2) when Meta.has (Meta.Custom ":ssa") v.v_meta -> - let v' = get_origin_var v in - let e1 = loop e1 in - let e2 = loop e2 in - {e with eexpr = TFor(v',e1,e2)} - | TLocal v when Meta.has (Meta.Custom ":ssa") v.v_meta -> - let v' = get_origin_var v in - {e with eexpr = TLocal v'} - | TBlock el -> - let rec filter e = match e.eexpr with - | TMeta((Meta.Custom ":ssa",_,_),_) -> - false - | _ -> - true - in - let el = List.filter filter el in - let el = List.map loop el in - {e with eexpr = TBlock el} - | _ -> - Type.map_expr loop e - in - loop e -end - -module ConstPropagation = struct - open Ssa - - let expr_eq e1 e2 = match e1.eexpr,e2.eexpr with - | TConst ct1, TConst ct2 -> - ct1 = ct2 - | _ -> - false - - let get_block_depth v = try - let i = match Meta.get (Meta.Custom ":blockDepth") v.v_meta with - | _,[EConst(Int s),_],_ -> int_of_string s - | _ -> raise Not_found - in - i - with Not_found -> - -1 - - let can_be_inlined com v0 e = type_iseq v0.v_type e.etype && match e.eexpr with - | TConst ct -> - begin match ct with - | TThis | TSuper -> false - (* Some targets don't like seeing null in certain places and won't even compile. We have to detect `if (x != null) - in order for this to work. *) - | TNull when (match com.platform with Php | Cpp -> true | _ -> false) -> false - | _ -> true - end - | TLocal v -> - not (Meta.has Meta.CompilerGenerated v.v_meta) && - begin try - let v' = Ssa.get_origin_var v in - begin match v'.v_extra with - | Some ([],_) -> get_block_depth v <= get_block_depth v0 - | _ -> false - end - with Not_found -> - false - end - | TEnumParameter _ when not (com.platform = Php) -> - Ssa.get_var_usage_count v0 <= 1 - | _ -> - false - - let semi_awkward_enum_value ssa e i = match e.eexpr with - | TCall({eexpr = TField(_,FEnum _)},el) -> (try List.nth el i with Failure _ -> raise Not_found) - | _ -> raise Not_found - - let rec local ssa force v e = - begin try - if v.v_capture then raise Not_found; - if type_has_analyzer_option v.v_type flag_no_const_propagation then raise Not_found; - begin match follow v.v_type with - | TDynamic _ -> raise Not_found - | _ -> () - end; - let e = Ssa.get_var_value v in - let old = v.v_extra in - v.v_extra <- None; - let e = value ssa force e in - v.v_extra <- old; - Ssa.set_var_value v e; - e - with Not_found -> - e - end - - (* force must only be true if the value is not used in the output *) - and value ssa force e = match e.eexpr with - | TUnop((Increment | Decrement),_,_) - | TBinop(OpAssignOp _,_,_) - | TBinop(OpAssign,_,_) -> - e - | TBinop(op,e1,e2) -> - let e1 = value ssa force e1 in - let e2 = value ssa force e2 in - let e = {e with eexpr = TBinop(op,e1,e2)} in - let e' = Optimizer.optimize_binop e op e1 e2 in - if e == e' then - e - else - value ssa force e' - | TUnop(op,flag,e1) -> - let e1 = value ssa force e1 in - let e = {e with eexpr = TUnop(op,flag,e1)} in - let e' = Optimizer.optimize_unop e op flag e1 in - if e == e' then - e - else - value ssa force e' - | TCall (({eexpr = TLocal {v_name = "__ssa_phi__"}} as ephi),el) -> - let el = List.map (value ssa force) el in - begin match el with - | [] -> assert false - | e1 :: el -> - if List.for_all (fun e2 -> expr_eq e1 e2) el then - value ssa force e1 - else - {e with eexpr = TCall(ephi, e1 :: el)} - end - | TParenthesis e1 | TMeta(_,e1) -> - value ssa force e1 - | TLocal v -> - let e' = local ssa force v e in - if force || can_be_inlined ssa.com v e' then - e' - else - e - | TEnumParameter(e1,ef,i) -> - let ev = value ssa true e1 in - begin try - value ssa force (semi_awkward_enum_value ssa ev i) - with Not_found -> - e - end - | _ -> - e - - (* TODO: the name is quite accurate *) - let awkward_get_enum_index ssa e = - let e = awkward_get_enum_index ssa.com e in - let ev = (value ssa true e) in - match ev.eexpr with - | TField(_,FEnum(_,ef)) -> TInt (Int32.of_int ef.ef_index) - | TCall({eexpr = TField(_,FEnum(_,ef))},_) -> TInt (Int32.of_int ef.ef_index) - | _ -> raise Not_found - - let apply ssa e = - let rec loop e = match e.eexpr with - | TLocal v when not (Meta.has Meta.Unbound v.v_meta) -> - set_var_usage_count v (get_var_usage_count v + 1); - | _ -> - Type.iter loop e - in - loop e; - let had_function = ref false in - let rec loop e = match e.eexpr with - | TFunction _ when !had_function -> - e - | TFunction tf -> - had_function := true; - {e with eexpr = TFunction {tf with tf_expr = loop tf.tf_expr}} - | TLocal v -> - let e' = local ssa false v e in - if can_be_inlined ssa.com v e' then - e' - else - e - | TCall({eexpr = TField(_,(FStatic(_,cf) | FInstance(_,_,cf) | FAnon cf))},el) when has_analyzer_option cf.cf_meta flag_no_const_propagation -> - e - | TCall(e1,el) -> - let e1 = loop e1 in - let check e t = - if type_has_analyzer_option t flag_no_const_propagation then e - else loop e - in - let el = Codegen.UnificationCallback.check_call check el e1.etype in - {e with eexpr = TCall(e1,el)} -(* | TField(e1,fa) -> - let e1' = loop e1 in - let fa = if e1' != e1 then - begin try quick_field e1'.etype (field_name fa) - with Not_found -> fa end - else - fa - in - {e with eexpr = TField(e1',fa)} *) - | TUnop((Increment | Decrement),_,_) -> - e - | TBinop(OpAssignOp op,e1,e2) -> - let e2 = loop e2 in - {e with eexpr = TBinop(OpAssignOp op,e1,e2)} - | TBinop(OpAssign,({eexpr = TLocal _} as e1),e2) -> - let e2 = loop e2 in - {e with eexpr = TBinop(OpAssign,e1,e2)} - | TBinop(op,e1,e2) -> - let e1 = loop e1 in - let e2 = loop e2 in - let e = {e with eexpr = TBinop(op,e1,e2)} in - let e' = Optimizer.optimize_binop e op e1 e2 in - e' - | TUnop(op,flag,e1) -> - let e1 = loop e1 in - let e = {e with eexpr = TUnop(op,flag,e1)} in - let e' = Optimizer.optimize_unop e op flag e1 in - e' - | TIf(e1,e2,eo) -> - let e1 = loop e1 in - let e2 = loop e2 in - let rec check_const e1 = match e1.eexpr with - | TConst (TBool true) -> - e2 - | TConst (TBool false) -> - begin match eo with - | None -> - mk (TConst TNull) t_dynamic e.epos - | Some e -> - loop e - end - | TParenthesis e1 -> - check_const e1 - | _ -> - let eo = match eo with None -> None | Some e -> Some (loop e) in - {e with eexpr = TIf(e1,e2,eo)} - in - check_const e1 - | TSwitch(e1,cases,edef) -> - let e1 = loop e1 in - let rec check_constant e = match e.eexpr with - | TConst ct -> ct - | TParenthesis e1 | TCast(e1,None) | TMeta(_,e1) -> check_constant e1 - | _ -> awkward_get_enum_index ssa e - in - begin try - let ct = check_constant e1 in - begin try - let _,e = List.find (fun (el,_) -> - List.exists (fun e -> match e.eexpr with - | TConst ct2 -> ct = ct2 - | _ -> false - ) el - ) cases in - loop e - with Not_found -> - begin match edef with None -> raise Not_found | Some e -> loop e end - end - with Not_found -> - let cases = List.map (fun (el,e) -> el,loop e) cases in - let edef = match edef with None -> None | Some e -> Some (loop e) in - {e with eexpr = TSwitch(e1,cases,edef)} - end - | _ -> - Type.map_expr loop e - in - loop e -end - -module EffectChecker = struct - let run com is_var_expression e = - let has_effect e = match e.eexpr with - | TVar _ -> true - | _ -> Optimizer.has_side_effect e - in - let e = if is_var_expression then - (* var initialization expressions are like assignments, so let's cheat a bit here *) - snd (Simplifier.apply com (Codegen.binop OpAssign (mk (TConst TNull) t_dynamic e.epos) e e.etype e.epos)) - else e - in - let rec loop e = match e.eexpr with - | TBlock el -> - List.iter (fun e -> - if not (has_effect e) then com.warning "This expression has no effect" e.epos - ) el - | _ -> - Type.iter loop e - in - loop e -end - -module Checker = struct - open Ssa - - let apply ssa e = - let given_warnings = ref PMap.empty in - let add_pos p = - given_warnings := PMap.add p true !given_warnings - in - let resolve_value v = - let e' = Ssa.get_var_value v in - begin match e'.eexpr with - | TLocal v' when v == v' -> e' - | _ -> e' - end - in - let rec is_null_expr e = match e.eexpr with - | TConst TNull -> - true - | TLocal v -> - (try is_null_expr (resolve_value v) with Not_found -> false) - | _ -> - false - in - let can_be_null v = - not (has_meta Meta.NotNull v.v_meta) - && try not (List.exists (fun cond -> match cond with - | NotEqual(v',e) when v == v' && is_null_expr e -> true - | _ -> false - ) (IntMap.find v.v_id ssa.var_conds)) with Not_found -> true - in - let return b p = - if b then add_pos p; - b - in - let rec can_be_null_expr vstack e = - if PMap.mem e.epos !given_warnings then - false - else match e.eexpr with - | TConst TNull -> - add_pos e.epos; - true - | TBinop((OpAssign | OpAssignOp _),_,e1) -> - can_be_null_expr vstack e1 - | TBinop _ | TUnop _ -> - false - | TConst _ | TTypeExpr _ | TNew _ | TObjectDecl _ | TArrayDecl _ | TEnumParameter _ | TFunction _ | TVar _ -> - false - | TFor _ | TWhile _ | TIf _ | TSwitch _ | TTry _ | TReturn _ | TBreak | TContinue | TThrow _ -> - assert false - | TField _ | TBlock _ | TArray _ -> - false (* TODO *) - | TCall ({eexpr = TLocal {v_name = "__ssa_phi__"}},el) -> - List.exists (can_be_null_expr vstack) el - | TLocal v -> - if List.mem v.v_id vstack then - false (* not really, but let's not be a nuisance *) - else - return (can_be_null v && (try can_be_null_expr (v.v_id :: vstack) (resolve_value v) with Not_found -> true)) e.epos; - | TMeta(_,e1) | TParenthesis e1 | TCast(e1,_) -> - can_be_null_expr vstack e1 - | TCall(e1,_) -> - begin match follow e1.etype with - | TFun(_,r) -> return (is_explicit_null r) e1.epos - | _ -> false - end - in - let check_null e p = - if can_be_null_expr [] e then begin - ssa.com.warning "Possible null exception" p; - end - in - let rec loop e = match e.eexpr with - | TField(e1,fa) -> - let e1 = loop e1 in - check_null e1 e.epos; - {e with eexpr = TField(e1,fa)} - | TMeta((Meta.Analyzer,[EConst(Ident "testIsNull"),_],_),e1) -> - if not (can_be_null_expr [] e) then error "Analyzer did not find a possible null exception" e.epos; - e - | TMeta((Meta.Analyzer,[EConst(Ident "testIsNotNull"),_],_),e1) -> - if (can_be_null_expr [] e) then error "Analyzer found a possible null exception" e.epos; - e - | _ -> - Type.map_expr loop e - in - loop e; -end - -let rec lrev_iter f el = match el with - | e :: el -> - lrev_iter f el; - f e - | [] -> - () - -let rev_iter f e = match e.eexpr with - | TConst _ - | TLocal _ - | TBreak - | TContinue - | TTypeExpr _ -> - () - | TArray (e1,e2) - | TBinop (_,e1,e2) - | TFor (_,e1,e2) - | TWhile (e1,e2,_) -> - f e2; - f e1; - | TThrow e - | TField (e,_) - | TEnumParameter (e,_,_) - | TParenthesis e - | TCast (e,_) - | TUnop (_,_,e) - | TMeta(_,e) -> - f e - | TArrayDecl el - | TNew (_,_,el) - | TBlock el -> - lrev_iter f el - | TObjectDecl fl -> - lrev_iter (fun (_,e) -> f e) fl - | TCall (e,el) -> - f e; - lrev_iter f el - | TVar (v,eo) -> - (match eo with None -> () | Some e -> f e) - | TFunction fu -> - f fu.tf_expr - | TIf (e,e1,e2) -> - (match e2 with None -> () | Some e -> f e); - f e1; - f e; - | TSwitch (e,cases,def) -> - (match def with None -> () | Some e -> f e); - lrev_iter (fun (el,e2) -> lrev_iter f el; f e2) cases; - f e; - | TTry (e,catches) -> - lrev_iter (fun (_,e) -> f e) catches; - f e; - | TReturn eo -> - (match eo with None -> () | Some e -> f e) - -module LocalDce = struct - let apply e = - let is_used v = Meta.has Meta.Used v.v_meta || type_has_analyzer_option v.v_type flag_no_local_dce || v.v_capture in - let is_ref_type t = match t with - | TType({t_path = ["cs"],("Ref" | "Out")},_) -> true - | _ -> false - in - let rec use v = - if not (Meta.has Meta.Used v.v_meta) then begin - v.v_meta <- (Meta.Used,[],Ast.null_pos) :: v.v_meta; - try use (Ssa.get_origin_var v) with Not_found -> () - end - in - let rec has_side_effect e = - let rec loop e = - match e.eexpr with - | TLocal v when Meta.has Meta.CompilerGenerated v.v_meta -> (try loop (Ssa.get_var_value v) with Not_found -> ()) - | TBinop((OpAssign | OpAssignOp _),{eexpr = TLocal v},e2) when is_used v || has_side_effect e2 || is_ref_type v.v_type -> raise Exit - | TVar(v,None) when is_used v -> raise Exit - | TVar(v,Some e1) when is_used v || has_side_effect e1 -> raise Exit - | TConst _ | TLocal _ | TTypeExpr _ | TFunction _ -> () - | TCall ({ eexpr = TField(_,FStatic({ cl_path = ([],"Std") },{ cf_name = "string" })) },args) -> Type.iter loop e - | TCall (({eexpr = TLocal {v_name = "__ssa_phi__"}}),el) -> () - | TCall ({eexpr = TField(_,FEnum _)},_) -> Type.iter loop e - | TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit - | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit - | TFor _ -> raise Exit - | TArray _ | TEnumParameter _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ - | TField _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TBlock _ | TObjectDecl _ | TVar _ -> Type.iter loop e - in - try - loop e; - false - with Exit -> - true - in - let rec collect e = match e.eexpr with - | TLocal v -> - use v - | TVar(v,_) when not (is_used v) -> - (* TODO: this is probably dangerous *) - () - | _ -> - rev_iter collect e - in - let rec loop need_val e = - match e.eexpr with - | TLocal v -> - use v; - e - | TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) -> - let e2 = loop false e2 in - if not (is_used v) && not (is_ref_type v.v_type) then - e2 - else - {e with eexpr = TBinop(OpAssign,{e1 with eexpr = TLocal v},e2)} - | TVar(v,Some e1) when not (is_used v) -> - let e1 = if has_side_effect e1 then loop true e1 else e1 in - e1 - | TWhile(e1,e2,flag) -> - collect e2; - let e2 = loop false e2 in - let e1 = loop false e1 in - {e with eexpr = TWhile(e1,e2,flag)} - | TFor(v,e1,e2) -> - collect e2; - let e2 = loop false e2 in - let e1 = loop false e1 in - {e with eexpr = TFor(v,e1,e2)} - | TBlock el -> - let rec block el = match el with - | e :: el -> - let el = block el in - if not need_val && not (has_side_effect e) then - el - else begin - let e = loop false e in - e :: el - end - | [] -> - [] - in - {e with eexpr = TBlock (block el)} - | TCall(e1, el) -> - let el = List.rev_map (loop true) (List.rev el) in - let e1 = loop false e1 in - {e with eexpr = TCall(e1,el)} - | TIf(e1,e2,e3) -> - let e3 = match e3 with None -> None | Some e -> Some (loop need_val e) in - let e2 = loop need_val e2 in - let e1 = loop false e1 in - {e with eexpr = TIf(e1,e2,e3)} - | TArrayDecl el -> - let el = List.rev_map (loop true) (List.rev el) in - {e with eexpr = TArrayDecl el} - | TObjectDecl fl -> - let fl = List.rev_map (fun (s,e) -> s,loop true e) (List.rev fl) in - {e with eexpr = TObjectDecl fl} - | _ -> - Type.map_expr (loop false) e - in - loop false e -end - -module Config = struct - - type analyzer_config = { - analyzer_use : bool; - simplifier_apply : bool; - ssa_apply : bool; - const_propagation : bool; - check : bool; - check_has_effect : bool; - local_dce : bool; - ssa_unapply : bool; - simplifier_unapply : bool; - } - - let get_base_config com = - { - analyzer_use = true; - simplifier_apply = true; - ssa_apply = true; - const_propagation = not (Common.raw_defined com "analyzer-no-const-propagation"); - check_has_effect = (Common.raw_defined com "analyzer-check-has-effect"); - check = not (Common.raw_defined com "analyzer-no-check"); - local_dce = not (Common.raw_defined com "analyzer-no-local-dce") && not (Common.defined com Define.As3); - ssa_unapply = not (Common.raw_defined com "analyzer-no-ssa-unapply"); - simplifier_unapply = not (Common.raw_defined com "analyzer-no-simplify-unapply"); - } - - let update_config_from_meta config meta = - List.fold_left (fun config meta -> match meta with - | (Meta.Analyzer,el,_) -> - List.fold_left (fun config e -> match fst e with - | EConst (Ident s) when s = flag_no_check -> { config with check = false} - | EConst (Ident s) when s = flag_check -> { config with check = true} - | EConst (Ident s) when s = flag_no_const_propagation -> { config with const_propagation = false} - | EConst (Ident s) when s = flag_const_propagation -> { config with const_propagation = true} - | EConst (Ident s) when s = flag_no_local_dce -> { config with local_dce = false} - | EConst (Ident s) when s = flag_local_dce -> { config with local_dce = true} - | EConst (Ident s) when s = flag_no_check_has_effect -> { config with check_has_effect = false} - | EConst (Ident s) when s = flag_check_has_effect -> { config with check_has_effect = true} - | _ -> config - ) config el - | _ -> - config - ) config meta - - let get_class_config com c = - let config = get_base_config com in - update_config_from_meta config c.cl_meta - - let get_field_config com c cf = - let config = get_class_config com c in - update_config_from_meta config cf.cf_meta -end - -module Run = struct - - open Config - - let run_on_expr com config is_var_expression e = - let do_simplify = (not (Common.defined com Define.NoSimplify) ) && match com.platform with - | Cpp when Common.defined com Define.Cppia -> false - | Cpp | Python -> true - | _ -> false - in - let with_timer s f = - let timer = timer s in - let r = f() in - timer(); - r - in - try - let has_unbound,e = if do_simplify || config.analyzer_use then - with_timer "analyzer-simplify-apply" (fun () -> Simplifier.apply com e) - else - false,e - in - let e = if config.analyzer_use && not has_unbound then begin - if config.check_has_effect then EffectChecker.run com is_var_expression e; - let e,ssa = with_timer "analyzer-ssa-apply" (fun () -> Ssa.apply com e) in - let e = if config.const_propagation then with_timer "analyzer-const-propagation" (fun () -> ConstPropagation.apply ssa e) else e in - (* let e = if config.check then with_timer "analyzer-checker" (fun () -> Checker.apply ssa e) else e in *) - let e = if config.local_dce && config.analyzer_use && not has_unbound && not is_var_expression then with_timer "analyzer-local-dce" (fun () -> LocalDce.apply e) else e in - let e = if config.ssa_unapply then with_timer "analyzer-ssa-unapply" (fun () -> Ssa.unapply com e) else e in - List.iter (fun f -> f()) ssa.Ssa.cleanup; - e - end else - e - in - let e = if not do_simplify && not (Common.raw_defined com "analyzer-no-simplify-unapply") then - with_timer "analyzer-simplify-unapply" (fun () -> Simplifier.unapply com e) - else - e - in - e - with Exit -> - e - - let run_on_field ctx config cf = - match cf.cf_expr with - | Some e when not (is_ignored cf.cf_meta) && not (Codegen.is_removable_field ctx cf) -> - let config = update_config_from_meta config cf.cf_meta in - let is_var_expression = match cf.cf_kind with - | Var _ -> true - | _ -> false - in - cf.cf_expr <- Some (run_on_expr ctx.com config is_var_expression e); - | _ -> () - - let run_on_class ctx config c = - let config = update_config_from_meta config c.cl_meta in - let process_field cf = run_on_field ctx config cf in - List.iter process_field c.cl_ordered_fields; - List.iter process_field c.cl_ordered_statics; - (match c.cl_constructor with - | None -> () - | Some f -> process_field f); - (match c.cl_init with - | None -> () - | Some e -> - (* never optimize init expressions (too messy) *) - c.cl_init <- Some (run_on_expr ctx.com {config with analyzer_use = false} false e)) - - let run_on_type ctx config t = - match t with - | TClassDecl c when (is_ignored c.cl_meta) -> () - | TClassDecl c -> run_on_class ctx config c - | TEnumDecl _ -> () - | TTypeDecl _ -> () - | TAbstractDecl _ -> () - - let run_on_types ctx types = - let com = ctx.com in - let config = get_base_config com in - List.iter (run_on_type ctx config) types - -end diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index e3849d49..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,66 +0,0 @@ -version: "{build}" - -platform: - - Win32 - -environment: - global: - NEKO_ROOT: C:/projects/neko - HAXELIB_ROOT: C:/projects/haxelib - CYG_ARCH: x86 - CYG_ROOT: C:/cygwin - CYG_SETUP: C:/cygwin/setup-x86.exe - MINGW_ARCH: i686 - WODI: wodi32 - ADD_REVISION: 1 - OCAMLOPT: ocamlopt.opt - matrix: - - TEST: "neko,cs,java,macro" - - TEST: "cpp" - -skip_tags: true - -install: - - 'git submodule update --init --recursive' - - cinst 7zip.commandline -y - # Install ocaml using wodi - - appveyor DownloadFile "http://cygwin.com/setup-%CYG_ARCH%.exe" -FileName "%CYG_ROOT%\setup.exe" - - '%CYG_ROOT%/setup.exe -g -q -R "%CYG_ROOT%" -P dos2unix -P diffutils -P cpio -P make -P patch -P mingw64-%MINGW_ARCH%-gcc-core -P mingw64-%MINGW_ARCH%-gcc-g++ > log.txt || type log.txt' - - '%CYG_ROOT%/bin/bash -lc "cygcheck -dc cygwin" > log.txt || type log.txt' - # The archive is a dropbox hosted version of https://github.com/fdopen/godi-repo/issues/7#issuecomment-98480339 - - '%CYG_ROOT%/bin/bash -lc "wget -q https://dl.dropboxusercontent.com/u/2661116/wodi/%WODI%.tar.xz -O /tmp/%WODI%.tar.xz" > log.txt || type log.txt' - - '%CYG_ROOT%/bin/bash -lc "cd /tmp && rm -rf %WODI% && tar -xf %WODI%.tar.xz && bash %WODI%/install.sh" > log.txt || type log.txt' - - '%CYG_ROOT%/bin/bash -lc "godi_add godi-zip" > log.txt || type log.txt' - - 'set PATH=%PATH%;%CYG_ROOT%/opt/%WODI%/bin' - # Install neko - - cinst make -y - - 'git clone --recursive https://github.com/HaxeFoundation/neko.git %NEKO_ROOT%' - - 'cd %NEKO_ROOT%' - - set PATH=%PATH%;%NEKO_ROOT%/bin - - msbuild neko_vc10.sln /verbosity:minimal /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" > log.txt || type log.txt - - msbuild libs/libs_vc10.sln /verbosity:minimal /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" > log.txt || type log.txt - - copy /y libs\include\gc\gc.dll bin - - cd %NEKO_ROOT%/src - - neko ../boot/nekoc tools/install.neko - - neko tools/install -nolibs > log.txt || type log.txt - - neko -version - -build_script: - - 'cd %APPVEYOR_BUILD_FOLDER%' - - 'set PATH=%PATH%;%APPVEYOR_BUILD_FOLDER%' - - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -s -f Makefile.win"' - - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -s -f Makefile.win tools"' - - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -s -f Makefile.win package_bin"' - - dir %APPVEYOR_BUILD_FOLDER%\out - - cd %APPVEYOR_BUILD_FOLDER%/tests/ - - mkdir "%HAXELIB_ROOT%" - - haxelib setup "%HAXELIB_ROOT%" - -test_script: - - cd %APPVEYOR_BUILD_FOLDER%/tests/ - - haxe -version - - haxe RunCi.hxml - - neko RunCi.n - -artifacts: - - path: out/haxe_*.zip diff --git a/ast.ml b/ast.ml deleted file mode 100644 index bcd6b95e..00000000 --- a/ast.ml +++ /dev/null @@ -1,772 +0,0 @@ -(* - * Copyright (C)2005-2013 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. - *) - -type pos = { - pfile : string; - pmin : int; - pmax : int; -} - -module IntMap = Map.Make(struct type t = int let compare a b = a - b end) - -module Meta = struct - type strict_meta = - | Abi - | Abstract - | Access - | Accessor - | Allow - | Analyzer - | Annotation - | ArrayAccess - | Ast - | AutoBuild - | Bind - | Bitmap - | BridgeProperties - | Build - | BuildXml - | Callable - | Class - | ClassCode - | Commutative - | CompilerGenerated - | CoreApi - | CoreType - | CppFileCode - | CppInclude - | CppNamespaceCode - | CsNative - | Dce - | Debug - | Decl - | DefParam - | Delegate - | Depend - | Deprecated - | DirectlyUsed - | DynamicObject - | Enum - | EnumConstructorParam - | Event - | Exhaustive - | Expose - | Extern - | FakeEnum - | File - | Final - | FlatEnum - | Font - | Forward - | From - | FunctionCode - | FunctionTailCode - | Generic - | GenericBuild - | GenericInstance - | Getter - | Hack - | HasUntyped - | HaxeGeneric - | HeaderClassCode - | HeaderCode - | HeaderInclude - | HeaderNamespaceCode - | HxGen - | IfFeature - | Impl - | PythonImport - | ImplicitCast - | Include - | InitPackage - | Internal - | IsVar - | JavaCanonical - | JavaNative - | JsRequire - | Keep - | KeepInit - | KeepSub - | LibType - | Meta - | Macro - | MaybeUsed - | MergeBlock - | MultiType - | Native - | NativeChildren - | NativeGen - | NativeGeneric - | NativeProperty - | NoCompletion - | NoDebug - | NoDoc - | NoExpr - | NoImportGlobal - | NonVirtual - | NoPackageRestrict - | NoPrivateAccess - | NoStack - | NotNull - | NoUsing - | Ns - | Op - | Optional - | Overload - | PrivateAccess - | Property - | Protected - | Public - | PublicFields - | QuotedField - | ReadOnly - | RealPath - | Remove - | Require - | RequiresAssign - (* | Resolve *) - | ReplaceReflection - | Rtti - | Runtime - | RuntimeValue - | SelfCall - | Setter - | SkipCtor - | SkipReflection - | Sound - | SourceFile - | StoredTypedExpr - | Strict - | Struct - | StructAccess - | SuppressWarnings - | This - | Throws - | To - | ToString - | Transient - | ValueUsed - | Volatile - | Unbound - | UnifyMinDynamic - | Unreflective - | Unsafe - | Usage - | Used - | Value - | Void - | Last - (* do not put any custom metadata after Last *) - | Dollar of string - | Custom of string - - let has m ml = List.exists (fun (m2,_,_) -> m = m2) ml - let get m ml = List.find (fun (m2,_,_) -> m = m2) ml - - let to_string_ref = ref (fun _ -> assert false) - let to_string (m : strict_meta) : string = !to_string_ref m -end - -type keyword = - | Function - | Class - | Var - | If - | Else - | While - | Do - | For - | Break - | Continue - | Return - | Extends - | Implements - | Import - | Switch - | Case - | Default - | Static - | Public - | Private - | Try - | Catch - | New - | This - | Throw - | Extern - | Enum - | In - | Interface - | Untyped - | Cast - | Override - | Typedef - | Dynamic - | Package - | Inline - | Using - | Null - | True - | False - | Abstract - | Macro - -type binop = - | OpAdd - | OpMult - | OpDiv - | OpSub - | OpAssign - | OpEq - | OpNotEq - | OpGt - | OpGte - | OpLt - | OpLte - | OpAnd - | OpOr - | OpXor - | OpBoolAnd - | OpBoolOr - | OpShl - | OpShr - | OpUShr - | OpMod - | OpAssignOp of binop - | OpInterval - | OpArrow - -type unop = - | Increment - | Decrement - | Not - | Neg - | NegBits - -type constant = - | Int of string - | Float of string - | String of string - | Ident of string - | Regexp of string * string - -type token = - | Eof - | Const of constant - | Kwd of keyword - | Comment of string - | CommentLine of string - | Binop of binop - | Unop of unop - | Semicolon - | Comma - | BrOpen - | BrClose - | BkOpen - | BkClose - | POpen - | PClose - | Dot - | DblDot - | Arrow - | IntInterval of string - | Sharp of string - | Question - | At - | Dollar of string - -type unop_flag = - | Prefix - | Postfix - -type while_flag = - | NormalWhile - | DoWhile - -type type_path = { - tpackage : string list; - tname : string; - tparams : type_param_or_const list; - tsub : string option; -} - -and type_param_or_const = - | TPType of complex_type - | TPExpr of expr - -and complex_type = - | CTPath of type_path - | CTFunction of complex_type list * complex_type - | CTAnonymous of class_field list - | CTParent of complex_type - | CTExtend of type_path list * class_field list - | CTOptional of complex_type - -and func = { - f_params : type_param list; - f_args : (string * bool * complex_type option * expr option) list; - f_type : complex_type option; - f_expr : expr option; -} - -and expr_def = - | EConst of constant - | EArray of expr * expr - | EBinop of binop * expr * expr - | EField of expr * string - | EParenthesis of expr - | EObjectDecl of (string * expr) list - | EArrayDecl of expr list - | ECall of expr * expr list - | ENew of type_path * expr list - | EUnop of unop * unop_flag * expr - | EVars of (string * complex_type option * expr option) list - | EFunction of string option * func - | EBlock of expr list - | EFor of expr * expr - | EIn of expr * expr - | EIf of expr * expr * expr option - | EWhile of expr * expr * while_flag - | ESwitch of expr * (expr list * expr option * expr option) list * expr option option - | ETry of expr * (string * complex_type * expr) list - | EReturn of expr option - | EBreak - | EContinue - | EUntyped of expr - | EThrow of expr - | ECast of expr * complex_type option - | EDisplay of expr * bool - | EDisplayNew of type_path - | ETernary of expr * expr * expr - | ECheckType of expr * complex_type - | EMeta of metadata_entry * expr - -and expr = expr_def * pos - -and type_param = { - tp_name : string; - tp_params : type_param list; - tp_constraints : complex_type list; -} - -and documentation = string option - -and metadata_entry = (Meta.strict_meta * expr list * pos) -and metadata = metadata_entry list - -and access = - | APublic - | APrivate - | AStatic - | AOverride - | ADynamic - | AInline - | AMacro - -and class_field_kind = - | FVar of complex_type option * expr option - | FFun of func - | FProp of string * string * complex_type option * expr option - -and class_field = { - cff_name : string; - cff_doc : documentation; - cff_pos : pos; - mutable cff_meta : metadata; - mutable cff_access : access list; - mutable cff_kind : class_field_kind; -} - -type enum_flag = - | EPrivate - | EExtern - -type class_flag = - | HInterface - | HExtern - | HPrivate - | HExtends of type_path - | HImplements of type_path - -type abstract_flag = - | APrivAbstract - | AFromType of complex_type - | AToType of complex_type - | AIsType of complex_type - -type enum_constructor = { - ec_name : string; - ec_doc : documentation; - ec_meta : metadata; - ec_args : (string * bool * complex_type) list; - ec_pos : pos; - ec_params : type_param list; - ec_type : complex_type option; -} - -type ('a,'b) definition = { - d_name : string; - d_doc : documentation; - d_params : type_param list; - d_meta : metadata; - d_flags : 'a list; - d_data : 'b; -} - -type import_mode = - | INormal - | IAsName of string - | IAll - -type type_def = - | EClass of (class_flag, class_field list) definition - | EEnum of (enum_flag, enum_constructor list) definition - | ETypedef of (enum_flag, complex_type) definition - | EAbstract of (abstract_flag, class_field list) definition - | EImport of (string * pos) list * import_mode - | EUsing of type_path - -type type_decl = type_def * pos - -type package = string list * type_decl list - -exception Error of string * pos - -let is_lower_ident i = - let rec loop p = - match String.unsafe_get i p with - | 'a'..'z' -> true - | '_' -> if p + 1 < String.length i then loop (p + 1) else true - | _ -> false - in - loop 0 - -let pos = snd - -let rec is_postfix (e,_) op = match op with - | Increment | Decrement -> true - | Not | Neg | NegBits -> false - -let is_prefix = function - | Increment | Decrement -> true - | Not | Neg | NegBits -> true - -let base_class_name = snd - -let null_pos = { pfile = "?"; pmin = -1; pmax = -1 } - -let punion p p2 = - { - pfile = p.pfile; - pmin = min p.pmin p2.pmin; - pmax = max p.pmax p2.pmax; - } - -let rec punion_el el = match el with - | [] -> - null_pos - | (_,p) :: [] -> - p - | (_,p) :: el -> - punion p (punion_el el) - -let s_type_path (p,s) = match p with [] -> s | _ -> String.concat "." p ^ "." ^ s - -let parse_path s = - match List.rev (ExtString.String.nsplit s ".") with - | [] -> failwith "Invalid empty path" - | x :: l -> List.rev l, x - -let s_escape ?(hex=true) s = - let b = Buffer.create (String.length s) in - for i = 0 to (String.length s) - 1 do - match s.[i] with - | '\n' -> Buffer.add_string b "\\n" - | '\t' -> Buffer.add_string b "\\t" - | '\r' -> Buffer.add_string b "\\r" - | '"' -> Buffer.add_string b "\\\"" - | '\\' -> Buffer.add_string b "\\\\" - | c when int_of_char c < 32 && hex -> Buffer.add_string b (Printf.sprintf "\\x%.2X" (int_of_char c)) - | c -> Buffer.add_char b c - done; - Buffer.contents b - -let s_constant = function - | Int s -> s - | Float s -> s - | String s -> "\"" ^ s_escape s ^ "\"" - | Ident s -> s - | Regexp (r,o) -> "~/" ^ r ^ "/" - -let s_access = function - | APublic -> "public" - | APrivate -> "private" - | AStatic -> "static" - | AOverride -> "override" - | ADynamic -> "dynamic" - | AInline -> "inline" - | AMacro -> "macro" - -let s_keyword = function - | Function -> "function" - | Class -> "class" - | Static -> "static" - | Var -> "var" - | If -> "if" - | Else -> "else" - | While -> "while" - | Do -> "do" - | For -> "for" - | Break -> "break" - | Return -> "return" - | Continue -> "continue" - | Extends -> "extends" - | Implements -> "implements" - | Import -> "import" - | Switch -> "switch" - | Case -> "case" - | Default -> "default" - | Private -> "private" - | Public -> "public" - | Try -> "try" - | Catch -> "catch" - | New -> "new" - | This -> "this" - | Throw -> "throw" - | Extern -> "extern" - | Enum -> "enum" - | In -> "in" - | Interface -> "interface" - | Untyped -> "untyped" - | Cast -> "cast" - | Override -> "override" - | Typedef -> "typedef" - | Dynamic -> "dynamic" - | Package -> "package" - | Inline -> "inline" - | Using -> "using" - | Null -> "null" - | True -> "true" - | False -> "false" - | Abstract -> "abstract" - | Macro -> "macro" - -let rec s_binop = function - | OpAdd -> "+" - | OpMult -> "*" - | OpDiv -> "/" - | OpSub -> "-" - | OpAssign -> "=" - | OpEq -> "==" - | OpNotEq -> "!=" - | OpGte -> ">=" - | OpLte -> "<=" - | OpGt -> ">" - | OpLt -> "<" - | OpAnd -> "&" - | OpOr -> "|" - | OpXor -> "^" - | OpBoolAnd -> "&&" - | OpBoolOr -> "||" - | OpShr -> ">>" - | OpUShr -> ">>>" - | OpShl -> "<<" - | OpMod -> "%" - | OpAssignOp op -> s_binop op ^ "=" - | OpInterval -> "..." - | OpArrow -> "=>" - -let s_unop = function - | Increment -> "++" - | Decrement -> "--" - | Not -> "!" - | Neg -> "-" - | NegBits -> "~" - -let s_token = function - | Eof -> "" - | Const c -> s_constant c - | Kwd k -> s_keyword k - | Comment s -> "/*"^s^"*/" - | CommentLine s -> "//"^s - | Binop o -> s_binop o - | Unop o -> s_unop o - | Semicolon -> ";" - | Comma -> "," - | BkOpen -> "[" - | BkClose -> "]" - | BrOpen -> "{" - | BrClose -> "}" - | POpen -> "(" - | PClose -> ")" - | Dot -> "." - | DblDot -> ":" - | Arrow -> "->" - | IntInterval s -> s ^ "..." - | Sharp s -> "#" ^ s - | Question -> "?" - | At -> "@" - | Dollar v -> "$" ^ v - -let unescape s = - let b = Buffer.create 0 in - let rec loop esc i = - if i = String.length s then - () - else - let c = s.[i] in - if esc then begin - let inext = ref (i + 1) in - (match c with - | 'n' -> Buffer.add_char b '\n' - | 'r' -> Buffer.add_char b '\r' - | 't' -> Buffer.add_char b '\t' - | '"' | '\'' | '\\' -> Buffer.add_char b c - | '0'..'3' -> - let c = (try char_of_int (int_of_string ("0o" ^ String.sub s i 3)) with _ -> raise Exit) in - Buffer.add_char b c; - inext := !inext + 2; - | 'x' -> - let c = (try char_of_int (int_of_string ("0x" ^ String.sub s (i+1) 2)) with _ -> raise Exit) in - Buffer.add_char b c; - inext := !inext + 2; - | 'u' -> - let (u, a) = - try - (int_of_string ("0x" ^ String.sub s (i+1) 4), 4) - with _ -> try - assert (s.[i+1] = '{'); - let l = String.index_from s (i+3) '}' - (i+2) in - let u = int_of_string ("0x" ^ String.sub s (i+2) l) in - assert (u <= 0x10FFFF); - (u, l+2) - with _ -> - raise Exit - in - let ub = UTF8.Buf.create 0 in - UTF8.Buf.add_char ub (UChar.uchar_of_int u); - Buffer.add_string b (UTF8.Buf.contents ub); - inext := !inext + a; - | _ -> - raise Exit); - loop false !inext; - end else - match c with - | '\\' -> loop true (i + 1) - | c -> - Buffer.add_char b c; - loop false (i + 1) - in - loop false 0; - Buffer.contents b - - -let map_expr loop (e,p) = - let opt f o = - match o with None -> None | Some v -> Some (f v) - in - let rec tparam = function - | TPType t -> TPType (ctype t) - | TPExpr e -> TPExpr (loop e) - and cfield f = - { f with cff_kind = (match f.cff_kind with - | FVar (t,e) -> FVar (opt ctype t, opt loop e) - | FFun f -> FFun (func f) - | FProp (get,set,t,e) -> FProp (get,set,opt ctype t,opt loop e)) - } - and ctype = function - | CTPath t -> CTPath (tpath t) - | CTFunction (cl,c) -> CTFunction (List.map ctype cl, ctype c) - | CTAnonymous fl -> CTAnonymous (List.map cfield fl) - | CTParent t -> CTParent (ctype t) - | CTExtend (tl,fl) -> CTExtend (List.map tpath tl, List.map cfield fl) - | CTOptional t -> CTOptional (ctype t) - and tparamdecl t = - { tp_name = t.tp_name; tp_constraints = List.map ctype t.tp_constraints; tp_params = List.map tparamdecl t.tp_params } - and func f = - { - f_params = List.map tparamdecl f.f_params; - f_args = List.map (fun (n,o,t,e) -> n,o,opt ctype t,opt loop e) f.f_args; - f_type = opt ctype f.f_type; - f_expr = opt loop f.f_expr; - } - and tpath t = { t with tparams = List.map tparam t.tparams } - in - let e = (match e with - | EConst _ -> e - | EArray (e1,e2) -> EArray (loop e1, loop e2) - | EBinop (op,e1,e2) -> EBinop (op,loop e1, loop e2) - | EField (e,f) -> EField (loop e, f) - | EParenthesis e -> EParenthesis (loop e) - | EObjectDecl fl -> EObjectDecl (List.map (fun (f,e) -> f,loop e) fl) - | EArrayDecl el -> EArrayDecl (List.map loop el) - | ECall (e,el) -> ECall (loop e, List.map loop el) - | ENew (t,el) -> ENew (tpath t,List.map loop el) - | EUnop (op,f,e) -> EUnop (op,f,loop e) - | EVars vl -> EVars (List.map (fun (n,t,eo) -> n,opt ctype t,opt loop eo) vl) - | EFunction (n,f) -> EFunction (n,func f) - | EBlock el -> EBlock (List.map loop el) - | EFor (e1,e2) -> EFor (loop e1, loop e2) - | EIn (e1,e2) -> EIn (loop e1, loop e2) - | EIf (e,e1,e2) -> EIf (loop e, loop e1, opt loop e2) - | EWhile (econd,e,f) -> EWhile (loop econd, loop e, f) - | ESwitch (e,cases,def) -> ESwitch (loop e, List.map (fun (el,eg,e) -> List.map loop el, opt loop eg, opt loop e) cases, opt (opt loop) def) - | ETry (e, catches) -> ETry (loop e, List.map (fun (n,t,e) -> n,ctype t,loop e) catches) - | EReturn e -> EReturn (opt loop e) - | EBreak -> EBreak - | EContinue -> EContinue - | EUntyped e -> EUntyped (loop e) - | EThrow e -> EThrow (loop e) - | ECast (e,t) -> ECast (loop e,opt ctype t) - | EDisplay (e,f) -> EDisplay (loop e,f) - | EDisplayNew t -> EDisplayNew (tpath t) - | ETernary (e1,e2,e3) -> ETernary (loop e1,loop e2,loop e3) - | ECheckType (e,t) -> ECheckType (loop e, ctype t) - | EMeta (m,e) -> EMeta(m, loop e) - ) in - (e,p) - -let rec s_expr (e,_) = - match e with - | EConst c -> s_constant c - | EParenthesis e -> "(" ^ (s_expr e) ^ ")" - | EArrayDecl el -> "[" ^ (String.concat "," (List.map s_expr el)) ^ "]" - | EObjectDecl fl -> "{" ^ (String.concat "," (List.map (fun (n,e) -> n ^ ":" ^ (s_expr e)) fl)) ^ "}" - | EBinop (op,e1,e2) -> s_expr e1 ^ s_binop op ^ s_expr e2 - | ECall (e,el) -> s_expr e ^ "(" ^ (String.concat ", " (List.map s_expr el)) ^ ")" - | EField (e,f) -> s_expr e ^ "." ^ f - | _ -> "'???'" - -let get_value_meta meta = - try - begin match Meta.get Meta.Value meta with - | (_,[EObjectDecl values,_],_) -> List.fold_left (fun acc (s,e) -> PMap.add s e acc) PMap.empty values - | _ -> raise Not_found - end - with Not_found -> - PMap.empty - -let rec string_list_of_expr_path_raise (e,p) = - match e with - | EConst (Ident i) -> [i] - | EField (e,f) -> f :: string_list_of_expr_path_raise e - | _ -> raise Exit diff --git a/codegen.ml b/codegen.ml deleted file mode 100644 index 7b51b2af..00000000 --- a/codegen.ml +++ /dev/null @@ -1,1958 +0,0 @@ -(* - * Copyright (C)2005-2013 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. - *) - -open Ast -open Type -open Common -open Typecore - -(* -------------------------------------------------------------------------- *) -(* TOOLS *) - -let field e name t p = - mk (TField (e,try quick_field e.etype name with Not_found -> assert false)) t p - -let fcall e name el ret p = - let ft = tfun (List.map (fun e -> e.etype) el) ret in - mk (TCall (field e name ft p,el)) ret p - -let mk_parent e = - mk (TParenthesis e) e.etype e.epos - -let string com str p = - mk (TConst (TString str)) com.basic.tstring p - -let binop op a b t p = - mk (TBinop (op,a,b)) t p - -let index com e index t p = - mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) com.basic.tint p)) t p - -let maybe_cast e t = - try - type_eq EqDoNotFollowNull e.etype t; - e - with - Unify_error _ -> mk (TCast(e,None)) t e.epos - -let type_constant com c p = - let t = com.basic in - match c with - | Int s -> - if String.length s > 10 && String.sub s 0 2 = "0x" then error "Invalid hexadecimal integer" p; - (try mk (TConst (TInt (Int32.of_string s))) t.tint p - with _ -> mk (TConst (TFloat s)) t.tfloat p) - | Float f -> mk (TConst (TFloat f)) t.tfloat p - | String s -> mk (TConst (TString s)) t.tstring p - | Ident "true" -> mk (TConst (TBool true)) t.tbool p - | Ident "false" -> mk (TConst (TBool false)) t.tbool p - | Ident "null" -> mk (TConst TNull) (t.tnull (mk_mono())) p - | Ident t -> error ("Invalid constant : " ^ t) p - | Regexp _ -> error "Invalid constant" p - -let rec type_constant_value com (e,p) = - match e with - | EConst c -> - type_constant com c p - | EParenthesis e -> - type_constant_value com e - | EObjectDecl el -> - mk (TObjectDecl (List.map (fun (n,e) -> n, type_constant_value com e) el)) (TAnon { a_fields = PMap.empty; a_status = ref Closed }) p - | EArrayDecl el -> - mk (TArrayDecl (List.map (type_constant_value com) el)) (com.basic.tarray t_dynamic) p - | _ -> - error "Constant value expected" p - -let rec has_properties c = - List.exists (fun f -> - match f.cf_kind with - | Var { v_read = AccCall } -> true - | Var { v_write = AccCall } -> true - | _ when Meta.has Meta.Accessor f.cf_meta -> true - | _ -> false - ) c.cl_ordered_fields || (match c.cl_super with Some (c,_) -> has_properties c | _ -> false) - -let get_properties fields = - List.fold_left (fun acc f -> - if Meta.has Meta.Accessor f.cf_meta then - (f.cf_name, f.cf_name) :: acc - else - let acc = (match f.cf_kind with - | Var { v_read = AccCall } -> ("get_" ^ f.cf_name , "get_" ^ f.cf_name) :: acc - | _ -> acc) in - match f.cf_kind with - | Var { v_write = AccCall } -> ("set_" ^ f.cf_name , "set_" ^ f.cf_name) :: acc - | _ -> acc - ) [] fields - -let add_property_field com c = - let p = c.cl_pos in - let props = get_properties (c.cl_ordered_statics @ c.cl_ordered_fields) in - match props with - | [] -> () - | _ -> - let fields,values = List.fold_left (fun (fields,values) (n,v) -> - let cf = mk_field n com.basic.tstring p in - PMap.add n cf fields,(n, string com v p) :: values - ) (PMap.empty,[]) props in - let t = mk_anon fields in - let e = mk (TObjectDecl values) t p in - let cf = mk_field "__properties__" t p in - cf.cf_expr <- Some e; - c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics; - c.cl_ordered_statics <- cf :: c.cl_ordered_statics - -let is_removable_field ctx f = - Meta.has Meta.Extern f.cf_meta || Meta.has Meta.Generic f.cf_meta - || (match f.cf_kind with - | Var {v_read = AccRequire (s,_)} -> true - | Method MethMacro -> not ctx.in_macro - | _ -> false) - -let escape_res_name name allow_dirs = - ExtString.String.replace_chars (fun chr -> - if (chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') || (chr >= '0' && chr <= '9') || chr = '_' || chr = '.' then - Char.escaped chr - else if chr = '/' && allow_dirs then - "/" - else - "-x" ^ (string_of_int (Char.code chr))) name - -(* -------------------------------------------------------------------------- *) -(* REMOTING PROXYS *) - -let extend_remoting ctx c t p async prot = - if c.cl_super <> None then error "Cannot extend several classes" p; - (* remove forbidden packages *) - let rules = ctx.com.package_rules in - ctx.com.package_rules <- PMap.foldi (fun key r acc -> match r with Forbidden -> acc | _ -> PMap.add key r acc) rules PMap.empty; - (* parse module *) - let path = (t.tpackage,t.tname) in - let new_name = (if async then "Async_" else "Remoting_") ^ t.tname in - (* check if the proxy already exists *) - let t = (try - Typeload.load_type_def ctx p { tpackage = fst path; tname = new_name; tparams = []; tsub = None } - with - Error (Module_not_found _,p2) when p == p2 -> - (* build it *) - Common.log ctx.com ("Building proxy for " ^ s_type_path path); - let file, decls = (try - Typeload.parse_module ctx path p - with - | Not_found -> ctx.com.package_rules <- rules; error ("Could not load proxy module " ^ s_type_path path ^ (if fst path = [] then " (try using absolute path)" else "")) p - | e -> ctx.com.package_rules <- rules; raise e) in - ctx.com.package_rules <- rules; - let base_fields = [ - { cff_name = "__cnx"; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = []; cff_kind = FVar (Some (CTPath { tpackage = ["haxe";"remoting"]; tname = if async then "AsyncConnection" else "Connection"; tparams = []; tsub = None }),None) }; - { cff_name = "new"; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun { f_args = ["c",false,None,None]; f_type = None; f_expr = Some (EBinop (OpAssign,(EConst (Ident "__cnx"),p),(EConst (Ident "c"),p)),p); f_params = [] } }; - ] in - let tvoid = CTPath { tpackage = []; tname = "Void"; tparams = []; tsub = None } in - let build_field is_public acc f = - if f.cff_name = "new" then - acc - else match f.cff_kind with - | FFun fd when (is_public || List.mem APublic f.cff_access) && not (List.mem AStatic f.cff_access) -> - if List.exists (fun (_,_,t,_) -> t = None) fd.f_args then error ("Field " ^ f.cff_name ^ " type is not complete and cannot be used by RemotingProxy") p; - let eargs = [EArrayDecl (List.map (fun (a,_,_,_) -> (EConst (Ident a),p)) fd.f_args),p] in - let ftype = (match fd.f_type with Some (CTPath { tpackage = []; tname = "Void" }) -> None | _ -> fd.f_type) in - let fargs, eargs = if async then match ftype with - | Some tret -> fd.f_args @ ["__callb",true,Some (CTFunction ([tret],tvoid)),None], eargs @ [EConst (Ident "__callb"),p] - | _ -> fd.f_args, eargs @ [EConst (Ident "null"),p] - else - fd.f_args, eargs - in - let id = (EConst (String f.cff_name), p) in - let id = if prot then id else ECall ((EConst (Ident "__unprotect__"),p),[id]),p in - let expr = ECall ( - (EField ( - (ECall ((EField ((EConst (Ident "__cnx"),p),"resolve"),p),[id]),p), - "call") - ,p),eargs),p - in - let expr = if async || ftype = None then expr else (EReturn (Some expr),p) in - let fd = { - f_params = fd.f_params; - f_args = fargs; - f_type = if async then None else ftype; - f_expr = Some (EBlock [expr],p); - } in - { cff_name = f.cff_name; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun fd } :: acc - | _ -> acc - in - let decls = List.map (fun d -> - match d with - | EClass c, p when c.d_name = t.tname -> - let is_public = List.mem HExtern c.d_flags || List.mem HInterface c.d_flags in - let fields = List.rev (List.fold_left (build_field is_public) base_fields c.d_data) in - (EClass { c with d_flags = []; d_name = new_name; d_data = fields },p) - | _ -> d - ) decls in - let m = Typeload.type_module ctx (t.tpackage,new_name) file decls p in - add_dependency ctx.m.curmod m; - try - List.find (fun tdecl -> snd (t_path tdecl) = new_name) m.m_types - with Not_found -> - error ("Module " ^ s_type_path path ^ " does not define type " ^ t.tname) p - ) in - match t with - | TClassDecl c2 when c2.cl_params = [] -> ignore(c2.cl_build()); c.cl_super <- Some (c2,[]); - | _ -> error "Remoting proxy must be a class without parameters" p - -(* -------------------------------------------------------------------------- *) -(* HAXE.RTTI.GENERIC *) - -exception Generic_Exception of string * Ast.pos - -type generic_context = { - ctx : typer; - subst : (t * t) list; - name : string; - p : pos; - mutable mg : module_def option; -} - -let make_generic ctx ps pt p = - let rec loop l1 l2 = - match l1, l2 with - | [] , [] -> [] - | (x,TLazy f) :: l1, _ -> loop ((x,(!f)()) :: l1) l2 - | (_,t1) :: l1 , t2 :: l2 -> (t1,t2) :: loop l1 l2 - | _ -> assert false - in - let name = - String.concat "_" (List.map2 (fun (s,_) t -> - let s_type_path_underscore (p,s) = match p with [] -> s | _ -> String.concat "_" p ^ "_" ^ s in - let rec loop top t = match follow t with - | TInst(c,tl) -> (s_type_path_underscore c.cl_path) ^ (loop_tl tl) - | TEnum(en,tl) -> (s_type_path_underscore en.e_path) ^ (loop_tl tl) - | TAbstract(a,tl) -> (s_type_path_underscore a.a_path) ^ (loop_tl tl) - | _ when not top -> "_" (* allow unknown/incompatible types as type parameters to retain old behavior *) - | TMono _ -> raise (Generic_Exception (("Could not determine type for parameter " ^ s), p)) - | t -> raise (Generic_Exception (("Type parameter must be a class or enum instance (found " ^ (s_type (print_context()) t) ^ ")"), p)) - and loop_tl tl = match tl with - | [] -> "" - | tl -> "_" ^ String.concat "_" (List.map (loop false) tl) - in - loop true t - ) ps pt) - in - { - ctx = ctx; - subst = loop ps pt; - name = name; - p = p; - mg = None; - } - -let rec generic_substitute_type gctx t = - match t with - | TInst ({ cl_kind = KGeneric } as c2,tl2) -> - (* maybe loop, or generate cascading generics *) - let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c2) gctx.p in - let t = f (List.map (generic_substitute_type gctx) tl2) in - (match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ()); - t - | _ -> - try - generic_substitute_type gctx (List.assq t gctx.subst) - with Not_found -> - Type.map (generic_substitute_type gctx) t - -let generic_substitute_expr gctx e = - let vars = Hashtbl.create 0 in - let build_var v = - try - Hashtbl.find vars v.v_id - with Not_found -> - let v2 = alloc_var v.v_name (generic_substitute_type gctx v.v_type) in - v2.v_meta <- v.v_meta; - Hashtbl.add vars v.v_id v2; - v2 - in - let rec build_expr e = - match e.eexpr with - | TField(e1, FInstance({cl_kind = KGeneric} as c,tl,cf)) -> - let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c) gctx.p in - let t = f (List.map (generic_substitute_type gctx) tl) in - build_expr {e with eexpr = TField(e1,quick_field t cf.cf_name)} - | _ -> - map_expr_type build_expr (generic_substitute_type gctx) build_var e - in - build_expr e - -let has_ctor_constraint c = match c.cl_kind with - | KTypeParameter tl -> - List.exists (fun t -> match follow t with - | TAnon a when PMap.mem "new" a.a_fields -> true - | _ -> false - ) tl; - | _ -> false - -let get_short_name = - let i = ref (-1) in - (fun () -> - incr i; - Printf.sprintf "Hx___short___hx_type_%i" !i - ) - -let rec build_generic ctx c p tl = - let pack = fst c.cl_path in - let recurse = ref false in - let rec check_recursive t = - match follow t with - | TInst (c2,tl) -> - (match c2.cl_kind with - | KTypeParameter tl -> - if not (Typeload.is_generic_parameter ctx c2) && has_ctor_constraint c2 then - error "Type parameters with a constructor cannot be used non-generically" p; - recurse := true - | _ -> ()); - List.iter check_recursive tl; - | _ -> - () - in - List.iter check_recursive tl; - if !recurse then begin - TInst (c,tl) (* build a normal instance *) - end else begin - let gctx = make_generic ctx c.cl_params tl p in - let name = (snd c.cl_path) ^ "_" ^ gctx.name in - try - Typeload.load_instance ctx { tpackage = pack; tname = name; tparams = []; tsub = None } p false - with Error(Module_not_found path,_) when path = (pack,name) -> - let m = (try Hashtbl.find ctx.g.modules (Hashtbl.find ctx.g.types_module c.cl_path) with Not_found -> assert false) in - let ctx = { ctx with m = { ctx.m with module_types = m.m_types @ ctx.m.module_types } } in - ignore(c.cl_build()); (* make sure the super class is already setup *) - let mg = { - m_id = alloc_mid(); - m_path = (pack,name); - m_types = []; - m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake; - } in - gctx.mg <- Some mg; - let cg = mk_class mg (pack,name) c.cl_pos in - mg.m_types <- [TClassDecl cg]; - Hashtbl.add ctx.g.modules mg.m_path mg; - add_dependency mg m; - add_dependency ctx.m.curmod mg; - (* ensure that type parameters are set in dependencies *) - let dep_stack = ref [] in - let rec loop t = - if not (List.memq t !dep_stack) then begin - dep_stack := t :: !dep_stack; - match t with - | TInst (c,tl) -> add_dep c.cl_module tl - | TEnum (e,tl) -> add_dep e.e_module tl - | TType (t,tl) -> add_dep t.t_module tl - | TAbstract (a,tl) -> add_dep a.a_module tl - | TMono r -> - (match !r with - | None -> () - | Some t -> loop t) - | TLazy f -> - loop ((!f)()); - | TDynamic t2 -> - if t == t2 then () else loop t2 - | TAnon a -> - PMap.iter (fun _ f -> loop f.cf_type) a.a_fields - | TFun (args,ret) -> - List.iter (fun (_,_,t) -> loop t) args; - loop ret - end - and add_dep m tl = - add_dependency mg m; - List.iter loop tl - in - List.iter loop tl; - let build_field cf_old = - let cf_new = {cf_old with cf_pos = cf_old.cf_pos} in (* copy *) - let f () = - let t = generic_substitute_type gctx cf_old.cf_type in - ignore (follow t); - begin try (match cf_old.cf_expr with - | None -> - begin match cf_old.cf_kind with - | Method _ when not c.cl_interface && not c.cl_extern -> - display_error ctx (Printf.sprintf "Field %s has no expression (possible typing order issue)" cf_new.cf_name) cf_new.cf_pos; - display_error ctx (Printf.sprintf "While building %s" (s_type_path cg.cl_path)) p; - | _ -> - () - end - | Some e -> - cf_new.cf_expr <- Some (generic_substitute_expr gctx e) - ) with Unify_error l -> - error (error_msg (Unify l)) cf_new.cf_pos - end; - t - in - let r = exc_protect ctx (fun r -> - let t = mk_mono() in - r := (fun() -> t); - unify_raise ctx (f()) t p; - t - ) "build_generic" in - delay ctx PForce (fun() -> ignore ((!r)())); - cf_new.cf_type <- TLazy r; - cf_new - in - if c.cl_init <> None || c.cl_dynamic <> None then error "This class can't be generic" p; - List.iter (fun cf -> match cf.cf_kind with - | Method MethMacro when not ctx.in_macro -> () - | _ -> error "A generic class can't have static fields" cf.cf_pos - ) c.cl_ordered_statics; - cg.cl_super <- (match c.cl_super with - | None -> None - | Some (cs,pl) -> - let find_class subst = - let rec loop subst = match subst with - | (TInst(c,[]),t) :: subst when c == cs -> t - | _ :: subst -> loop subst - | [] -> raise Not_found - in - try - if pl <> [] then raise Not_found; - let t = loop subst in - (* extended type parameter: concrete type must have a constructor, but generic base class must not have one *) - begin match follow t,c.cl_constructor with - | TInst(cs,_),None -> - ignore(cs.cl_build()); - begin match cs.cl_constructor with - | None -> error ("Cannot use " ^ (s_type_path cs.cl_path) ^ " as type parameter because it is extended and has no constructor") p - | _ -> () - end; - | _,Some cf -> error "Generics extending type parameters cannot have constructors" cf.cf_pos - | _ -> () - end; - t - with Not_found -> - apply_params c.cl_params tl (TInst(cs,pl)) - in - let ts = follow (find_class gctx.subst) in - let cs,pl = Typeload.check_extends ctx c ts p in - match cs.cl_kind with - | KGeneric -> - (match build_generic ctx cs p pl with - | TInst (cs,pl) -> Some (cs,pl) - | _ -> assert false) - | _ -> Some(cs,pl) - ); - Typeload.add_constructor ctx cg false p; - cg.cl_kind <- KGenericInstance (c,tl); - cg.cl_meta <- (Meta.NoDoc,[],p) :: cg.cl_meta; - cg.cl_interface <- c.cl_interface; - cg.cl_constructor <- (match cg.cl_constructor, c.cl_constructor, c.cl_super with - | _, Some cf, _ -> Some (build_field cf) - | Some ctor, _, _ -> Some ctor - | None, None, None -> None - | _ -> error "Please define a constructor for this class in order to use it as generic" c.cl_pos - ); - cg.cl_implements <- List.map (fun (i,tl) -> - (match follow (generic_substitute_type gctx (TInst (i, List.map (generic_substitute_type gctx) tl))) with - | TInst (i,tl) -> i, tl - | _ -> assert false) - ) c.cl_implements; - cg.cl_ordered_fields <- List.map (fun f -> - let f = build_field f in - cg.cl_fields <- PMap.add f.cf_name f cg.cl_fields; - f - ) c.cl_ordered_fields; - (* In rare cases the class name can become too long, so let's shorten it (issue #3090). *) - if String.length (snd cg.cl_path) > 254 then begin - let n = get_short_name () in - cg.cl_meta <- (Meta.Native,[EConst(String (n)),p],p) :: cg.cl_meta; - end; - TInst (cg,[]) - end - -(* -------------------------------------------------------------------------- *) -(* HAXE.XML.PROXY *) - -let extend_xml_proxy ctx c t file p = - let t = Typeload.load_complex_type ctx p t in - let file = (try Common.find_file ctx.com file with Not_found -> file) in - add_dependency c.cl_module (create_fake_module ctx file); - let used = ref PMap.empty in - let print_results() = - PMap.iter (fun id used -> - if not used then ctx.com.warning (id ^ " is not used") p; - ) (!used) - in - let check_used = Common.defined ctx.com Define.CheckXmlProxy in - if check_used then ctx.g.hook_generate <- print_results :: ctx.g.hook_generate; - try - let rec loop = function - | Xml.Element (_,attrs,childs) -> - (try - let id = List.assoc "id" attrs in - if PMap.mem id c.cl_fields then error ("Duplicate id " ^ id) p; - let t = if not check_used then t else begin - used := PMap.add id false (!used); - let ft() = used := PMap.add id true (!used); t in - TLazy (ref ft) - end in - let f = { - cf_name = id; - cf_type = t; - cf_public = true; - cf_pos = p; - cf_doc = None; - cf_meta = no_meta; - cf_kind = Var { v_read = AccResolve; v_write = AccNo }; - cf_params = []; - cf_expr = None; - cf_overloads = []; - } in - c.cl_fields <- PMap.add id f c.cl_fields; - with - Not_found -> ()); - List.iter loop childs; - | Xml.PCData _ -> () - in - loop (Xml.parse_file file) - with - | Xml.Error e -> error ("XML error " ^ Xml.error e) p - | Xml.File_not_found f -> error ("XML File not found : " ^ f) p - -(* -------------------------------------------------------------------------- *) -(* BUILD META DATA OBJECT *) - -let build_metadata com t = - let api = com.basic in - let p, meta, fields, statics = (match t with - | TClassDecl c -> - let fields = List.map (fun f -> f.cf_name,f.cf_meta) (c.cl_ordered_fields @ (match c.cl_constructor with None -> [] | Some f -> [{ f with cf_name = "_" }])) in - let statics = List.map (fun f -> f.cf_name,f.cf_meta) c.cl_ordered_statics in - (c.cl_pos, ["",c.cl_meta],fields,statics) - | TEnumDecl e -> - (e.e_pos, ["",e.e_meta],List.map (fun n -> n, (PMap.find n e.e_constrs).ef_meta) e.e_names, []) - | TTypeDecl t -> - (t.t_pos, ["",t.t_meta],(match follow t.t_type with TAnon a -> PMap.fold (fun f acc -> (f.cf_name,f.cf_meta) :: acc) a.a_fields [] | _ -> []),[]) - | TAbstractDecl a -> - (a.a_pos, ["",a.a_meta],[],[]) - ) in - let filter l = - let l = List.map (fun (n,ml) -> n, ExtList.List.filter_map (fun (m,el,p) -> match m with Meta.Custom s when String.length s > 0 && s.[0] <> ':' -> Some (s,el,p) | _ -> None) ml) l in - List.filter (fun (_,ml) -> ml <> []) l - in - let meta, fields, statics = filter meta, filter fields, filter statics in - let make_meta_field ml = - let h = Hashtbl.create 0 in - mk (TObjectDecl (List.map (fun (f,el,p) -> - if Hashtbl.mem h f then error ("Duplicate metadata '" ^ f ^ "'") p; - Hashtbl.add h f (); - f, mk (match el with [] -> TConst TNull | _ -> TArrayDecl (List.map (type_constant_value com) el)) (api.tarray t_dynamic) p - ) ml)) t_dynamic p - in - let make_meta l = - mk (TObjectDecl (List.map (fun (f,ml) -> f,make_meta_field ml) l)) t_dynamic p - in - if meta = [] && fields = [] && statics = [] then - None - else - let meta_obj = [] in - let meta_obj = (if fields = [] then meta_obj else ("fields",make_meta fields) :: meta_obj) in - let meta_obj = (if statics = [] then meta_obj else ("statics",make_meta statics) :: meta_obj) in - let meta_obj = (try ("obj", make_meta_field (List.assoc "" meta)) :: meta_obj with Not_found -> meta_obj) in - Some (mk (TObjectDecl meta_obj) t_dynamic p) - -(* -------------------------------------------------------------------------- *) -(* MACRO TYPE *) - -let get_macro_path ctx e args p = - let rec loop e = - match fst e with - | EField (e,f) -> f :: loop e - | EConst (Ident i) -> [i] - | _ -> error "Invalid macro call" p - in - let path = match e with - | (EConst(Ident i)),_ -> - let path = try - if not (PMap.mem i ctx.curclass.cl_statics) then raise Not_found; - ctx.curclass.cl_path - with Not_found -> try - (t_infos (fst (PMap.find i ctx.m.module_globals))).mt_path - with Not_found -> - error "Invalid macro call" p - in - i :: (snd path) :: (fst path) - | _ -> - loop e - in - (match path with - | meth :: cl :: path -> (List.rev path,cl), meth, args - | _ -> error "Invalid macro call" p) - -let build_macro_type ctx pl p = - let path, field, args = (match pl with - | [TInst ({ cl_kind = KExpr (ECall (e,args),_) },_)] - | [TInst ({ cl_kind = KExpr (EArrayDecl [ECall (e,args),_],_) },_)] -> - get_macro_path ctx e args p - | _ -> - error "MacroType requires a single expression call parameter" p - ) in - let old = ctx.ret in - let t = (match ctx.g.do_macro ctx MMacroType path field args p with - | None -> mk_mono() - | Some _ -> ctx.ret - ) in - ctx.ret <- old; - t - -let build_macro_build ctx c pl cfl p = - let path, field, args = match Meta.get Meta.GenericBuild c.cl_meta with - | _,[ECall(e,args),_],_ -> get_macro_path ctx e args p - | _ -> error "genericBuild requires a single expression call parameter" p - in - let old = ctx.ret,ctx.g.get_build_infos in - ctx.g.get_build_infos <- (fun() -> Some (TClassDecl c, pl, cfl)); - let t = (match ctx.g.do_macro ctx MMacroType path field args p with - | None -> mk_mono() - | Some _ -> ctx.ret - ) in - ctx.ret <- fst old; - ctx.g.get_build_infos <- snd old; - t - -(* -------------------------------------------------------------------------- *) -(* API EVENTS *) - -let build_instance ctx mtype p = - match mtype with - | TClassDecl c -> - if ctx.pass > PBuildClass then ignore(c.cl_build()); - let build f s = - let r = exc_protect ctx (fun r -> - let t = mk_mono() in - r := (fun() -> t); - unify_raise ctx (f()) t p; - t - ) s in - delay ctx PForce (fun() -> ignore ((!r)())); - TLazy r - in - let ft = (fun pl -> - match c.cl_kind with - | KGeneric -> - build (fun () -> build_generic ctx c p pl) "build_generic" - | KMacroType -> - build (fun () -> build_macro_type ctx pl p) "macro_type" - | KGenericBuild cfl -> - build (fun () -> build_macro_build ctx c pl cfl p) "generic_build" - | _ -> - TInst (c,pl) - ) in - c.cl_params , c.cl_path , ft - | TEnumDecl e -> - e.e_params , e.e_path , (fun t -> TEnum (e,t)) - | TTypeDecl t -> - t.t_params , t.t_path , (fun tl -> TType(t,tl)) - | TAbstractDecl a -> - a.a_params, a.a_path, (fun tl -> TAbstract(a,tl)) - -let on_inherit ctx c p h = - match h with - | HExtends { tpackage = ["haxe";"remoting"]; tname = "Proxy"; tparams = [TPType(CTPath t)] } -> - extend_remoting ctx c t p false true; - false - | HExtends { tpackage = ["haxe";"remoting"]; tname = "AsyncProxy"; tparams = [TPType(CTPath t)] } -> - extend_remoting ctx c t p true true; - false - | HExtends { tpackage = ["haxe";"xml"]; tname = "Proxy"; tparams = [TPExpr(EConst (String file),p);TPType t] } -> - extend_xml_proxy ctx c t file p; - true - | _ -> - true - -(* -------------------------------------------------------------------------- *) -(* ABSTRACT CASTS *) - -module AbstractCast = struct - - let cast_stack = ref [] - - let make_static_call ctx c cf a pl args t p = - make_static_call ctx c cf (apply_params a.a_params pl) args t p - - let do_check_cast ctx tleft eright p = - let recurse cf f = - if cf == ctx.curfield || List.mem cf !cast_stack then error "Recursive implicit cast" p; - cast_stack := cf :: !cast_stack; - let r = f() in - cast_stack := List.tl !cast_stack; - r - in - let find a tl f = - let tcf,cf = f() in - if (Meta.has Meta.MultiType a.a_meta) then - mk_cast eright tleft p - else match a.a_impl with - | Some c -> recurse cf (fun () -> - let ret = make_static_call ctx c cf a tl [eright] tleft p in - { ret with eexpr = TMeta( (Meta.ImplicitCast,[],ret.epos), ret) } - ) - | None -> assert false - in - if type_iseq tleft eright.etype then - eright - else begin - let rec loop tleft tright = match follow tleft,follow tright with - | TAbstract(a1,tl1),TAbstract(a2,tl2) -> - begin try find a2 tl2 (fun () -> Abstract.find_to a2 tl2 tleft) - with Not_found -> try find a1 tl1 (fun () -> Abstract.find_from a1 tl1 eright.etype tleft) - with Not_found -> raise Not_found - end - | TAbstract(a,tl),_ -> - begin try find a tl (fun () -> Abstract.find_from a tl eright.etype tleft) - with Not_found -> - let rec loop2 tcl = match tcl with - | tc :: tcl -> - if not (type_iseq tc tleft) then loop (apply_params a.a_params tl tc) tright - else loop2 tcl - | [] -> raise Not_found - in - loop2 a.a_from - end - | _,TAbstract(a,tl) -> - begin try find a tl (fun () -> Abstract.find_to a tl tleft) - with Not_found -> - let rec loop2 tcl = match tcl with - | tc :: tcl -> - if not (type_iseq tc tright) then loop tleft (apply_params a.a_params tl tc) - else loop2 tcl - | [] -> raise Not_found - in - loop2 a.a_to - end - | _ -> - raise Not_found - in - loop tleft eright.etype - end - - let cast_or_unify_raise ctx tleft eright p = - try - if ctx.com.display <> DMNone then raise Not_found; - do_check_cast ctx tleft eright p - with Not_found -> - unify_raise ctx eright.etype tleft p; - eright - - let cast_or_unify ctx tleft eright p = - try - cast_or_unify_raise ctx tleft eright p - with Error (Unify _ as err,_) -> - if not ctx.untyped then display_error ctx (error_msg err) p; - eright - - let find_array_access_raise ctx a pl e1 e2o p = - let is_set = e2o <> None in - let ta = apply_params a.a_params pl a.a_this in - let rec loop cfl = match cfl with - | [] -> raise Not_found - | cf :: cfl when not (Ast.Meta.has Ast.Meta.ArrayAccess cf.cf_meta) -> - loop cfl - | cf :: cfl -> - let monos = List.map (fun _ -> mk_mono()) cf.cf_params in - let map t = apply_params a.a_params pl (apply_params cf.cf_params monos t) in - let check_constraints () = - List.iter2 (fun m (name,t) -> match follow t with - | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] -> - List.iter (fun tc -> match follow m with TMono _ -> raise (Unify_error []) | _ -> Type.unify m (map tc) ) constr - | _ -> () - ) monos cf.cf_params; - in - match follow (map cf.cf_type) with - | TFun([(_,_,tab);(_,_,ta1);(_,_,ta2)],r) as tf when is_set -> - begin try - Type.unify tab ta; - let e1 = cast_or_unify_raise ctx ta1 e1 p in - let e2o = match e2o with None -> None | Some e2 -> Some (cast_or_unify_raise ctx ta2 e2 p) in - check_constraints(); - cf,tf,r,e1,e2o - with Unify_error _ | Error (Unify _,_) -> - loop cfl - end - | TFun([(_,_,tab);(_,_,ta1)],r) as tf when not is_set -> - begin try - Type.unify tab ta; - let e1 = cast_or_unify_raise ctx ta1 e1 p in - check_constraints(); - cf,tf,r,e1,None - with Unify_error _ | Error (Unify _,_) -> - loop cfl - end - | _ -> loop cfl - in - loop a.a_array - - let find_array_access ctx a tl e1 e2o p = - try find_array_access_raise ctx a tl e1 e2o p - with Not_found -> match e2o with - | None -> - error (Printf.sprintf "No @:arrayAccess function accepts argument of %s" (s_type (print_context()) e1.etype)) p - | Some e2 -> - error (Printf.sprintf "No @:arrayAccess function accepts arguments of %s and %s" (s_type (print_context()) e1.etype) (s_type (print_context()) e2.etype)) p - - let find_multitype_specialization com a pl p = - let m = mk_mono() in - let tl = match Meta.get Meta.MultiType a.a_meta with - | _,[],_ -> pl - | _,el,_ -> - let relevant = Hashtbl.create 0 in - List.iter (fun e -> match fst e with - | EConst(Ident s) -> Hashtbl.replace relevant s true - | _ -> error "Type parameter expected" (pos e) - ) el; - let tl = List.map2 (fun (n,_) t -> if Hashtbl.mem relevant n || not (has_mono t) then t else t_dynamic) a.a_params pl in - if com.platform = Js && a.a_path = ([],"Map") then begin match tl with - | t1 :: _ -> - let rec loop stack t = - if List.exists (fun t2 -> fast_eq t t2) stack then - t - else begin - let stack = t :: stack in - match follow t with - | TAbstract ({ a_path = [],"Class" },_) -> - error (Printf.sprintf "Cannot use %s as key type to Map because Class is not comparable" (s_type (print_context()) t1)) p; - | TEnum(en,tl) -> - PMap.iter (fun _ ef -> ignore(loop stack ef.ef_type)) en.e_constrs; - Type.map (loop stack) t - | t -> - Type.map (loop stack) t - end - in - ignore(loop [] t1) - | _ -> assert false - end; - tl - in - let _,cf = - try - Abstract.find_to a tl m - with Not_found -> - let at = apply_params a.a_params pl a.a_this in - let st = s_type (print_context()) at in - if has_mono at then - error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p - else - error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p; - in - cf, follow m - - let handle_abstract_casts ctx e = - let rec loop ctx e = match e.eexpr with - | TNew({cl_kind = KAbstractImpl a} as c,pl,el) -> - (* a TNew of an abstract implementation is only generated if it is a multi type abstract *) - let cf,m = find_multitype_specialization ctx.com a pl e.epos in - let e = make_static_call ctx c cf a pl ((mk (TConst TNull) (TAbstract(a,pl)) e.epos) :: el) m e.epos in - {e with etype = m} - | TCall({eexpr = TField(_,FStatic({cl_path=[],"Std"},{cf_name = "string"}))},[e1]) when (match follow e1.etype with TAbstract({a_impl = Some _},_) -> true | _ -> false) -> - begin match follow e1.etype with - | TAbstract({a_impl = Some c} as a,tl) -> - begin try - let cf = PMap.find "toString" c.cl_statics in - make_static_call ctx c cf a tl [e1] ctx.t.tstring e.epos - with Not_found -> - e - end - | _ -> - assert false - end - | TCall(e1, el) -> - begin try - let rec find_abstract e = match follow e.etype,e.eexpr with - | TAbstract(a,pl),_ when Meta.has Meta.MultiType a.a_meta -> a,pl,e - | _,TCast(e1,None) -> find_abstract e1 - | _ -> raise Not_found - in - let rec find_field e1 = - match e1.eexpr with - | TCast(e2,None) -> - {e1 with eexpr = TCast(find_field e2,None)} - | TField(e2,fa) -> - let a,pl,e2 = find_abstract e2 in - let m = Abstract.get_underlying_type a pl in - let fname = field_name fa in - let el = List.map (loop ctx) el in - begin try - let fa = quick_field m fname in - let get_fun_type t = match follow t with - | TFun(_,tr) as tf -> tf,tr - | _ -> raise Not_found - in - let tf,tr = match fa with - | FStatic(_,cf) -> get_fun_type cf.cf_type - | FInstance(c,tl,cf) -> get_fun_type (apply_params c.cl_params tl cf.cf_type) - | FAnon cf -> get_fun_type cf.cf_type - | _ -> raise Not_found - in - let ef = mk (TField({e2 with etype = m},fa)) tf e2.epos in - let ecall = make_call ctx ef el tr e.epos in - if not (type_iseq ecall.etype e.etype) then - mk (TCast(ecall,None)) e.etype e.epos - else - ecall - with Not_found -> - (* quick_field raises Not_found if m is an abstract, we have to replicate the 'using' call here *) - match follow m with - | TAbstract({a_impl = Some c} as a,pl) -> - let cf = PMap.find fname c.cl_statics in - make_static_call ctx c cf a pl (e2 :: el) e.etype e.epos - | _ -> raise Not_found - end - | _ -> - raise Not_found - in - find_field e1 - with Not_found -> - Type.map_expr (loop ctx) e - end - | _ -> - Type.map_expr (loop ctx) e - in - loop ctx e -end - -module PatternMatchConversion = struct - - type cctx = { - ctx : typer; - mutable eval_stack : ((tvar * pos) * texpr) list list; - dt_lookup : dt array; - } - - let is_declared cctx v = - let rec loop sl = match sl with - | stack :: sl -> - List.exists (fun ((v2,_),_) -> v == v2) stack || loop sl - | [] -> - false - in - loop cctx.eval_stack - - let group_cases cases = - let dt_eq dt1 dt2 = match dt1,dt2 with - | DTGoto i1, DTGoto i2 when i1 = i2 -> true - (* TODO equal bindings *) - | _ -> false - in - match List.rev cases with - | [] -> [] - | [con,dt] -> [[con],dt] - | (con,dt) :: cases -> - let tmp,ldt,cases = List.fold_left (fun (tmp,ldt,acc) (con,dt) -> - if dt_eq dt ldt then - (con :: tmp,dt,acc) - else - ([con],dt,(tmp,ldt) :: acc) - ) ([con],dt,[]) cases in - match tmp with - | [] -> cases - | tmp -> ((tmp,ldt) :: cases) - - let replace_locals e = - let v_known = ref IntMap.empty in - let copy v = - let v' = alloc_var v.v_name v.v_type in - v_known := IntMap.add v.v_id v' !v_known; - v' - in - let rec loop e = match e.eexpr with - | TVar(v,e1) -> - let v' = copy v in - let e1 = match e1 with None -> None | Some e -> Some (loop e) in - {e with eexpr = TVar(v',e1)} - | TFor(v,e1,e2) -> - let v' = copy v in - let e1 = loop e1 in - let e2 = loop e2 in - {e with eexpr = TFor(v',e1,e2)} - | TTry(e1,catches) -> - let e1 = loop e1 in - let catches = List.map (fun (v,e) -> - let v' = copy v in - let e = loop e in - v',e - ) catches in - {e with eexpr = TTry(e1,catches)} - | TLocal v -> - let v' = try IntMap.find v.v_id !v_known with Not_found -> v in - {e with eexpr = TLocal v'} - | _ -> - Type.map_expr loop e - in - loop e - - let rec convert_dt cctx dt = - match dt with - | DTBind (bl,dt) -> - cctx.eval_stack <- bl :: cctx.eval_stack; - let e = convert_dt cctx dt in - cctx.eval_stack <- List.tl cctx.eval_stack; - let vl,el = List.fold_left (fun (vl,el) ((v,p),e) -> - if is_declared cctx v then - vl, (mk (TBinop(OpAssign,mk (TLocal v) v.v_type p,e)) e.etype e.epos) :: el - else - ((v,p,Some e) :: vl), el - ) ([],[e]) bl in - let el_v = List.map (fun (v,p,eo) -> mk (TVar (v,eo)) cctx.ctx.t.tvoid p) vl in - mk (TBlock (el_v @ el)) e.etype e.epos - | DTGoto i -> - convert_dt cctx (cctx.dt_lookup.(i)) - | DTExpr e -> - e - | DTGuard(e,dt1,dt2) -> - let ethen = convert_dt cctx dt1 in - mk (TIf(e,ethen,match dt2 with None -> None | Some dt -> Some (convert_dt cctx dt))) ethen.etype (punion e.epos ethen.epos) - | DTSwitch({eexpr = TMeta((Meta.Exhaustive,_,_),_)},[_,dt],None) -> - convert_dt cctx dt - | DTSwitch(e_st,cl,dto) -> - let def = match dto with None -> None | Some dt -> Some (convert_dt cctx dt) in - let cases = group_cases cl in - let cases = List.map (fun (cl,dt) -> - let e = convert_dt cctx dt in - (* The macro interpreter does not care about unique locals and - we don't run the analyzer on the output, so let's save some - time here (issue #3937) *) - let e = if cctx.ctx.in_macro then e else replace_locals e in - cl,e - ) cases in - mk (TSwitch(e_st,cases,def)) (mk_mono()) e_st.epos - - let to_typed_ast ctx dt p = - let first = dt.dt_dt_lookup.(dt.dt_first) in - let cctx = { - ctx = ctx; - dt_lookup = dt.dt_dt_lookup; - eval_stack = []; - } in - let e = convert_dt cctx first in - let e = { e with epos = p; etype = dt.dt_type} in - if dt.dt_var_init = [] then - e - else begin - let el_v = List.map (fun (v,eo) -> mk (TVar (v,eo)) cctx.ctx.t.tvoid p) dt.dt_var_init in - mk (TBlock (el_v @ [e])) dt.dt_type e.epos - end -end - -(* -------------------------------------------------------------------------- *) -(* USAGE *) - -let detect_usage com = - let usage = ref [] in - List.iter (fun t -> match t with - | TClassDecl c -> - let check_constructor c p = - try - let _,cf = get_constructor (fun cf -> cf.cf_type) c in - if Meta.has Meta.Usage cf.cf_meta then - usage := p :: !usage; - with Not_found -> - () - in - let rec expr e = match e.eexpr with - | TField(_,FEnum(_,ef)) when Meta.has Meta.Usage ef.ef_meta -> - let p = {e.epos with pmin = e.epos.pmax - (String.length ef.ef_name)} in - usage := p :: !usage; - Type.iter expr e - | TField(_,(FAnon cf | FInstance (_,_,cf) | FStatic (_,cf) | FClosure (_,cf))) when Meta.has Meta.Usage cf.cf_meta -> - let p = {e.epos with pmin = e.epos.pmax - (String.length cf.cf_name)} in - usage := p :: !usage; - Type.iter expr e - | TLocal v when Meta.has Meta.Usage v.v_meta -> - usage := e.epos :: !usage - | TVar (v,_) when com.display = DMPosition && Meta.has Meta.Usage v.v_meta -> - raise (Typecore.DisplayPosition [e.epos]) - | TFunction tf when com.display = DMPosition && List.exists (fun (v,_) -> Meta.has Meta.Usage v.v_meta) tf.tf_args -> - raise (Typecore.DisplayPosition [e.epos]) - | TTypeExpr mt when (Meta.has Meta.Usage (t_infos mt).mt_meta) -> - usage := e.epos :: !usage - | TNew (c,_,_) -> - check_constructor c e.epos; - Type.iter expr e; - | TCall({eexpr = TConst TSuper},_) -> - begin match c.cl_super with - | Some (c,_) -> - check_constructor c e.epos - | _ -> - () - end - | _ -> Type.iter expr e - in - let field cf = ignore(follow cf.cf_type); match cf.cf_expr with None -> () | Some e -> expr e in - (match c.cl_constructor with None -> () | Some cf -> field cf); - (match c.cl_init with None -> () | Some e -> expr e); - List.iter field c.cl_ordered_statics; - List.iter field c.cl_ordered_fields; - | _ -> () - ) com.types; - let usage = List.sort (fun p1 p2 -> - let c = compare p1.pfile p2.pfile in - if c <> 0 then c else compare p1.pmin p2.pmin - ) !usage in - raise (Typecore.DisplayPosition usage) - -let update_cache_dependencies com = - let rec check_t m t = match t with - | TInst(c,tl) -> - add_dependency m c.cl_module; - List.iter (check_t m) tl; - | TEnum(en,tl) -> - add_dependency m en.e_module; - List.iter (check_t m) tl; - | TType(t,tl) -> - add_dependency m t.t_module; - List.iter (check_t m) tl; - | TAbstract(a,tl) -> - add_dependency m a.a_module; - List.iter (check_t m) tl; - | TFun(targs,tret) -> - List.iter (fun (_,_,t) -> check_t m t) targs; - check_t m tret; - | TAnon an -> - PMap.iter (fun _ cf -> check_field m cf) an.a_fields - | TMono r -> - (match !r with - | Some t -> check_t m t - | _ -> ()) - | TLazy f -> - check_t m (!f()) - | TDynamic t -> - if t == t_dynamic then - () - else - check_t m t - and check_field m cf = - check_t m cf.cf_type - in - List.iter (fun t -> match t with - | TClassDecl c -> - List.iter (check_field c.cl_module) c.cl_ordered_statics; - List.iter (check_field c.cl_module) c.cl_ordered_fields; - (match c.cl_constructor with None -> () | Some cf -> check_field c.cl_module cf); - | _ -> - () - ) com.types - -(* -------------------------------------------------------------------------- *) -(* STACK MANAGEMENT EMULATION *) - -type stack_context = { - stack_var : string; - stack_exc_var : string; - stack_pos_var : string; - stack_pos : pos; - stack_expr : texpr; - stack_pop : texpr; - stack_save_pos : texpr; - stack_restore : texpr list; - stack_push : tclass -> string -> texpr; - stack_return : texpr -> texpr; -} - -let stack_context_init com stack_var exc_var pos_var tmp_var use_add p = - let t = com.basic in - let st = t.tarray t.tstring in - let stack_var = alloc_var stack_var st in - let exc_var = alloc_var exc_var st in - let pos_var = alloc_var pos_var t.tint in - let stack_e = mk (TLocal stack_var) st p in - let exc_e = mk (TLocal exc_var) st p in - let stack_pop = fcall stack_e "pop" [] t.tstring p in - let stack_push c m = - fcall stack_e "push" [ - if use_add then - binop OpAdd (string com (s_type_path c.cl_path ^ "::") p) (string com m p) t.tstring p - else - string com (s_type_path c.cl_path ^ "::" ^ m) p - ] t.tvoid p - in - let stack_return e = - let tmp = alloc_var tmp_var e.etype in - mk (TBlock [ - mk (TVar (tmp, Some e)) t.tvoid e.epos; - stack_pop; - mk (TReturn (Some (mk (TLocal tmp) e.etype e.epos))) e.etype e.epos - ]) e.etype e.epos - in - { - stack_var = stack_var.v_name; - stack_exc_var = exc_var.v_name; - stack_pos_var = pos_var.v_name; - stack_pos = p; - stack_expr = stack_e; - stack_pop = stack_pop; - stack_save_pos = mk (TVar (pos_var, Some (field stack_e "length" t.tint p))) t.tvoid p; - stack_push = stack_push; - stack_return = stack_return; - stack_restore = [ - binop OpAssign exc_e (mk (TArrayDecl []) st p) st p; - mk (TWhile ( - mk_parent (binop OpGte (field stack_e "length" t.tint p) (mk (TLocal pos_var) t.tint p) t.tbool p), - fcall exc_e "unshift" [fcall stack_e "pop" [] t.tstring p] t.tvoid p, - NormalWhile - )) t.tvoid p; - fcall stack_e "push" [index com exc_e 0 t.tstring p] t.tvoid p - ]; - } - -let stack_init com use_add = - stack_context_init com "$s" "$e" "$spos" "$tmp" use_add null_pos - -let rec stack_block_loop ctx e = - match e.eexpr with - | TFunction _ -> - e - | TReturn None | TReturn (Some { eexpr = TConst _ }) | TReturn (Some { eexpr = TLocal _ }) -> - mk (TBlock [ - ctx.stack_pop; - e; - ]) e.etype e.epos - | TReturn (Some e) -> - ctx.stack_return (stack_block_loop ctx e) - | TTry (v,cases) -> - let v = stack_block_loop ctx v in - let cases = List.map (fun (v,e) -> - let e = stack_block_loop ctx e in - let e = (match (mk_block e).eexpr with - | TBlock l -> mk (TBlock (ctx.stack_restore @ l)) e.etype e.epos - | _ -> assert false - ) in - v , e - ) cases in - mk (TTry (v,cases)) e.etype e.epos - | _ -> - map_expr (stack_block_loop ctx) e - -let stack_block ctx c m e = - match (mk_block e).eexpr with - | TBlock l -> - mk (TBlock ( - ctx.stack_push c m :: - ctx.stack_save_pos :: - List.map (stack_block_loop ctx) l - @ [ctx.stack_pop] - )) e.etype e.epos - | _ -> - assert false - -(* -------------------------------------------------------------------------- *) -(* FIX OVERRIDES *) - -(* - on some platforms which doesn't support type parameters, we must have the - exact same type for overriden/implemented function as the original one -*) - -let rec find_field com c f = - try - (match c.cl_super with - | None -> - raise Not_found - | Some ( {cl_path = (["cpp"],"FastIterator")}, _ ) -> - raise Not_found (* This is a strongly typed 'extern' and the usual rules don't apply *) - | Some (c,_) -> - find_field com c f) - with Not_found -> try - if com.platform = Cpp then (* Cpp uses delegation for interfaces *) - raise Not_found; - let rec loop = function - | [] -> - raise Not_found - | (c,_) :: l -> - try - find_field com c f - with - Not_found -> loop l - in - loop c.cl_implements - with Not_found -> - let f = PMap.find f.cf_name c.cl_fields in - (match f.cf_kind with Var { v_read = AccRequire _ } -> raise Not_found | _ -> ()); - f - -let fix_override com c f fd = - let f2 = (try Some (find_field com c f) with Not_found -> None) in - match f2,fd with - | Some (f2), Some(fd) -> - let targs, tret = (match follow f2.cf_type with TFun (args,ret) -> args, ret | _ -> assert false) in - let changed_args = ref [] in - let prefix = "_tmp_" in - let nargs = List.map2 (fun ((v,ct) as cur) (_,_,t2) -> - try - type_eq EqStrict (monomorphs c.cl_params (monomorphs f.cf_params v.v_type)) t2; - (* Flash generates type parameters with a single constraint as that constraint type, so we - have to detect this case and change the variable (issue #2712). *) - begin match follow v.v_type with - | TInst({cl_kind = KTypeParameter [tc]} as cp,_) when com.platform = Flash -> - if List.mem_assoc (snd cp.cl_path) c.cl_params then raise (Unify_error []) - | _ -> - () - end; - cur - with Unify_error _ -> - let v2 = alloc_var (prefix ^ v.v_name) t2 in - changed_args := (v,v2) :: !changed_args; - v2,ct - ) fd.tf_args targs in - let fd2 = { - tf_args = nargs; - tf_type = tret; - tf_expr = (match List.rev !changed_args with - | [] -> fd.tf_expr - | args -> - let e = fd.tf_expr in - let el = (match e.eexpr with TBlock el -> el | _ -> [e]) in - let p = (match el with [] -> e.epos | e :: _ -> e.epos) in - let el_v = List.map (fun (v,v2) -> - mk (TVar (v,Some (mk (TCast (mk (TLocal v2) v2.v_type p,None)) v.v_type p))) com.basic.tvoid p - ) args in - { e with eexpr = TBlock (el_v @ el) } - ); - } in - (* as3 does not allow wider visibility, so the base method has to be made public *) - if Common.defined com Define.As3 && f.cf_public then f2.cf_public <- true; - let targs = List.map (fun(v,c) -> (v.v_name, Option.is_some c, v.v_type)) nargs in - let fde = (match f.cf_expr with None -> assert false | Some e -> e) in - f.cf_expr <- Some { fde with eexpr = TFunction fd2 }; - f.cf_type <- TFun(targs,tret); - | Some(f2), None when c.cl_interface -> - let targs, tret = (match follow f2.cf_type with TFun (args,ret) -> args, ret | _ -> assert false) in - f.cf_type <- TFun(targs,tret) - | _ -> - () - -let fix_overrides com t = - match t with - | TClassDecl c -> - (* overrides can be removed from interfaces *) - if c.cl_interface then - c.cl_ordered_fields <- List.filter (fun f -> - try - if find_field com c f == f then raise Not_found; - c.cl_fields <- PMap.remove f.cf_name c.cl_fields; - false; - with Not_found -> - true - ) c.cl_ordered_fields; - List.iter (fun f -> - match f.cf_expr, f.cf_kind with - | Some { eexpr = TFunction fd }, Method (MethNormal | MethInline) -> - fix_override com c f (Some fd) - | None, Method (MethNormal | MethInline) when c.cl_interface -> - fix_override com c f None - | _ -> - () - ) c.cl_ordered_fields - | _ -> - () - -(* - PHP does not allow abstract classes extending other abstract classes to override any fields, so these duplicates - must be removed from the child interface -*) -let fix_abstract_inheritance com t = - match t with - | TClassDecl c when c.cl_interface -> - c.cl_ordered_fields <- List.filter (fun f -> - let b = try (find_field com c f) == f - with Not_found -> false in - if not b then c.cl_fields <- PMap.remove f.cf_name c.cl_fields; - b; - ) c.cl_ordered_fields - | _ -> () - -(* -------------------------------------------------------------------------- *) -(* MISC FEATURES *) - -let rec is_volatile t = - match t with - | TMono r -> - (match !r with - | Some t -> is_volatile t - | _ -> false) - | TLazy f -> - is_volatile (!f()) - | TType (t,tl) -> - (match t.t_path with - | _ -> is_volatile (apply_params t.t_params tl t.t_type)) - | _ -> - false - -let set_default ctx a c p = - let t = a.v_type in - let ve = mk (TLocal a) t p in - let cond = TBinop (OpEq,ve,mk (TConst TNull) t p) in - mk (TIf (mk_parent (mk cond ctx.basic.tbool p), mk (TBinop (OpAssign,ve,mk (TConst c) t p)) t p,None)) ctx.basic.tvoid p - -let bytes_serialize data = - let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" in - let tbl = Array.init (String.length b64) (fun i -> String.get b64 i) in - Base64.str_encode ~tbl data - -(* - Tells if the constructor might be called without any issue whatever its parameters -*) -let rec constructor_side_effects e = - match e.eexpr with - | TBinop (op,_,_) when op <> OpAssign -> - true - | TField (_,FEnum _) -> - false - | TUnop _ | TArray _ | TField _ | TEnumParameter _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TReturn _ | TThrow _ -> - true - | TBinop _ | TTry _ | TIf _ | TBlock _ | TVar _ - | TFunction _ | TArrayDecl _ | TObjectDecl _ - | TParenthesis _ | TTypeExpr _ | TLocal _ | TMeta _ - | TConst _ | TContinue | TBreak | TCast _ -> - try - Type.iter (fun e -> if constructor_side_effects e then raise Exit) e; - false; - with Exit -> - true - -let make_valid_filename s = - let r = Str.regexp "[^A-Za-z0-9_\\-\\.,]" in - Str.global_substitute r (fun s -> "_") s - -(* - Make a dump of the full typed AST of all types -*) -let rec create_dumpfile acc = function - | [] -> assert false - | d :: [] -> - let d = make_valid_filename d in - let ch = open_out (String.concat "/" (List.rev (d :: acc)) ^ ".dump") in - let buf = Buffer.create 0 in - buf, (fun () -> - output_string ch (Buffer.contents buf); - close_out ch) - | d :: l -> - let dir = String.concat "/" (List.rev (d :: acc)) in - if not (Sys.file_exists dir) then Unix.mkdir dir 0o755; - create_dumpfile (d :: acc) l - -let dump_types com = - let s_type = s_type (Type.print_context()) in - let params = function [] -> "" | l -> Printf.sprintf "<%s>" (String.concat "," (List.map (fun (n,t) -> n ^ " : " ^ s_type t) l)) in - let s_expr = match Common.defined_value_safe com Define.Dump with - | "pretty" -> Type.s_expr_pretty "\t" - | "legacy" -> Type.s_expr - | _ -> Type.s_expr_ast (not (Common.defined com Define.DumpIgnoreVarIds)) "\t" - in - List.iter (fun mt -> - let path = Type.t_path mt in - let buf,close = create_dumpfile [] ("dump" :: (Common.platform_name com.platform) :: fst path @ [snd path]) in - let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in - (match mt with - | Type.TClassDecl c -> - let rec print_field stat f = - print "\t%s%s%s%s" (if stat then "static " else "") (if f.cf_public then "public " else "") f.cf_name (params f.cf_params); - print "(%s) : %s" (s_kind f.cf_kind) (s_type f.cf_type); - (match f.cf_expr with - | None -> () - | Some e -> print "\n\n\t = %s" (s_expr s_type e)); - print "\n\n"; - List.iter (fun f -> print_field stat f) f.cf_overloads - in - print "%s%s%s %s%s" (if c.cl_private then "private " else "") (if c.cl_extern then "extern " else "") (if c.cl_interface then "interface" else "class") (s_type_path path) (params c.cl_params); - (match c.cl_super with None -> () | Some (c,pl) -> print " extends %s" (s_type (TInst (c,pl)))); - List.iter (fun (c,pl) -> print " implements %s" (s_type (TInst (c,pl)))) c.cl_implements; - (match c.cl_dynamic with None -> () | Some t -> print " implements Dynamic<%s>" (s_type t)); - (match c.cl_array_access with None -> () | Some t -> print " implements ArrayAccess<%s>" (s_type t)); - print "{\n"; - (match c.cl_constructor with - | None -> () - | Some f -> print_field false f); - List.iter (print_field false) c.cl_ordered_fields; - List.iter (print_field true) c.cl_ordered_statics; - (match c.cl_init with - | None -> () - | Some e -> - print "\n\n\t__init__ = "; - print "%s" (s_expr s_type e); - print "}\n"); - print "}"; - | Type.TEnumDecl e -> - print "%s%senum %s%s {\n" (if e.e_private then "private " else "") (if e.e_extern then "extern " else "") (s_type_path path) (params e.e_params); - List.iter (fun n -> - let f = PMap.find n e.e_constrs in - print "\t%s : %s;\n" f.ef_name (s_type f.ef_type); - ) e.e_names; - print "}" - | Type.TTypeDecl t -> - print "%stype %s%s = %s" (if t.t_private then "private " else "") (s_type_path path) (params t.t_params) (s_type t.t_type); - | Type.TAbstractDecl a -> - print "%sabstract %s%s {}" (if a.a_private then "private " else "") (s_type_path path) (params a.a_params); - ); - close(); - ) com.types - -let dump_dependencies com = - let buf,close = create_dumpfile [] ["dump";Common.platform_name com.platform;".dependencies"] in - let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in - let dep = Hashtbl.create 0 in - List.iter (fun m -> - print "%s:\n" m.m_extra.m_file; - PMap.iter (fun _ m2 -> - print "\t%s\n" (m2.m_extra.m_file); - let l = try Hashtbl.find dep m2.m_extra.m_file with Not_found -> [] in - Hashtbl.replace dep m2.m_extra.m_file (m :: l) - ) m.m_extra.m_deps; - ) com.Common.modules; - close(); - let buf,close = create_dumpfile [] ["dump";Common.platform_name com.platform;".dependants"] in - let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in - Hashtbl.iter (fun n ml -> - print "%s:\n" n; - List.iter (fun m -> - print "\t%s\n" (m.m_extra.m_file); - ) ml; - ) dep; - close() - -(* - Build a default safe-cast expression : - { var $t = ; if( Std.is($t,) ) $t else throw "Class cast error"; } -*) -let default_cast ?(vtmp="$t") com e texpr t p = - let api = com.basic in - let mk_texpr = function - | TClassDecl c -> TAnon { a_fields = PMap.empty; a_status = ref (Statics c) } - | TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) } - | TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) } - | TTypeDecl _ -> assert false - in - let vtmp = alloc_var vtmp e.etype in - let var = mk (TVar (vtmp,Some e)) api.tvoid p in - let vexpr = mk (TLocal vtmp) e.etype p in - let texpr = mk (TTypeExpr texpr) (mk_texpr texpr) p in - let std = (try List.find (fun t -> t_path t = ([],"Std")) com.types with Not_found -> assert false) in - let fis = (try - let c = (match std with TClassDecl c -> c | _ -> assert false) in - FStatic (c, PMap.find "is" c.cl_statics) - with Not_found -> - assert false - ) in - let std = mk (TTypeExpr std) (mk_texpr std) p in - let is = mk (TField (std,fis)) (tfun [t_dynamic;t_dynamic] api.tbool) p in - let is = mk (TCall (is,[vexpr;texpr])) api.tbool p in - let exc = mk (TThrow (mk (TConst (TString "Class cast error")) api.tstring p)) t p in - let check = mk (TIf (mk_parent is,mk (TCast (vexpr,None)) t p,Some exc)) t p in - mk (TBlock [var;check;vexpr]) t p - -(** Overload resolution **) -module Overloads = -struct - let rec simplify_t t = match t with - | TAbstract(a,_) when Meta.has Meta.CoreType a.a_meta -> - t - | TInst _ | TEnum _ -> - t - | TAbstract(a,tl) -> simplify_t (Abstract.get_underlying_type a tl) - | TType(({ t_path = [],"Null" } as t), [t2]) -> (match simplify_t t2 with - | (TAbstract(a,_) as t2) when Meta.has Meta.CoreType a.a_meta -> - TType(t, [simplify_t t2]) - | (TEnum _ as t2) -> - TType(t, [simplify_t t2]) - | t2 -> t2) - | TType(t, tl) -> - simplify_t (apply_params t.t_params tl t.t_type) - | TMono r -> (match !r with - | Some t -> simplify_t t - | None -> t_dynamic) - | TAnon _ -> t_dynamic - | TDynamic _ -> t - | TLazy f -> simplify_t (!f()) - | TFun _ -> t - - (* rate type parameters *) - let rate_tp tlfun tlarg = - let acc = ref 0 in - List.iter2 (fun f a -> if not (type_iseq f a) then incr acc) tlfun tlarg; - !acc - - (** - The rate function returns an ( int * int ) type. - The smaller the int, the best rated the caller argument is in comparison with the callee. - - The first int refers to how many "conversions" would be necessary to convert from the callee to the caller type, and - the second refers to the type parameters. - **) - let rec rate_conv cacc tfun targ = - match simplify_t tfun, simplify_t targ with - | TInst({ cl_interface = true } as cf, tlf), TInst(ca, tla) -> - (* breadth-first *) - let stack = ref [0,ca,tla] in - let cur = ref (0, ca,tla) in - let rec loop () = - match !stack with - | [] -> (let acc, ca, tla = !cur in match ca.cl_super with - | None -> raise Not_found - | Some (sup,tls) -> - cur := (acc+1,sup,List.map (apply_params ca.cl_params tla) tls); - stack := [!cur]; - loop()) - | (acc,ca,tla) :: _ when ca == cf -> - acc,tla - | (acc,ca,tla) :: s -> - stack := s @ List.map (fun (c,tl) -> (acc+1,c,List.map (apply_params ca.cl_params tla) tl)) ca.cl_implements; - loop() - in - let acc, tla = loop() in - (cacc + acc, rate_tp tlf tla) - | TInst(cf,tlf), TInst(ca,tla) -> - let rec loop acc ca tla = - if cf == ca then - acc, tla - else match ca.cl_super with - | None -> raise Not_found - | Some(sup,stl) -> - loop (acc+1) sup (List.map (apply_params ca.cl_params tla) stl) - in - let acc, tla = loop 0 ca tla in - (cacc + acc, rate_tp tlf tla) - | TEnum(ef,tlf), TEnum(ea, tla) -> - if ef != ea then raise Not_found; - (cacc, rate_tp tlf tla) - | TDynamic _, TDynamic _ -> - (cacc, 0) - | TDynamic _, _ -> - (max_int, 0) (* a function with dynamic will always be worst of all *) - | TAbstract(a, _), TDynamic _ when Meta.has Meta.CoreType a.a_meta -> - (cacc + 2, 0) (* a dynamic to a basic type will have an "unboxing" penalty *) - | _, TDynamic _ -> - (cacc + 1, 0) - | TAbstract(af,tlf), TAbstract(aa,tla) -> - (if af == aa then - (cacc, rate_tp tlf tla) - else - let ret = ref None in - if List.exists (fun t -> try - ret := Some (rate_conv (cacc+1) (apply_params af.a_params tlf t) targ); - true - with | Not_found -> - false - ) af.a_from then - Option.get !ret - else - if List.exists (fun t -> try - ret := Some (rate_conv (cacc+1) tfun (apply_params aa.a_params tla t)); - true - with | Not_found -> - false - ) aa.a_to then - Option.get !ret - else - raise Not_found) - | TType({ t_path = [], "Null" }, [tf]), TType({ t_path = [], "Null" }, [ta]) -> - rate_conv (cacc+0) tf ta - | TType({ t_path = [], "Null" }, [tf]), ta -> - rate_conv (cacc+1) tf ta - | tf, TType({ t_path = [], "Null" }, [ta]) -> - rate_conv (cacc+1) tf ta - | TFun _, TFun _ -> (* unify will make sure they are compatible *) - cacc,0 - | tfun,targ -> - raise Not_found - - let is_best arg1 arg2 = - (List.for_all2 (fun v1 v2 -> - v1 <= v2) - arg1 arg2) && (List.exists2 (fun v1 v2 -> - v1 < v2) - arg1 arg2) - - let rec rm_duplicates acc ret = match ret with - | [] -> acc - | ( el, t, _ ) :: ret when List.exists (fun (_,t2,_) -> type_iseq t t2) acc -> - rm_duplicates acc ret - | r :: ret -> - rm_duplicates (r :: acc) ret - - let s_options rated = - String.concat ",\n" (List.map (fun ((elist,t,_),rate) -> - "( " ^ (String.concat "," (List.map (fun(e,_) -> s_expr (s_type (print_context())) e) elist)) ^ " ) => " ^ - "( " ^ (String.concat "," (List.map (fun (i,i2) -> string_of_int i ^ ":" ^ string_of_int i2) rate)) ^ " ) => " ^ (s_type (print_context()) t) - ) rated) - - let count_optionals elist = - List.fold_left (fun acc (_,is_optional) -> if is_optional then acc + 1 else acc) 0 elist - - let rec fewer_optionals acc compatible = match acc, compatible with - | _, [] -> acc - | [], c :: comp -> fewer_optionals [c] comp - | (elist_acc, _, _) :: _, ((elist, _, _) as cur) :: comp -> - let acc_opt = count_optionals elist_acc in - let comp_opt = count_optionals elist in - if acc_opt = comp_opt then - fewer_optionals (cur :: acc) comp - else if acc_opt < comp_opt then - fewer_optionals acc comp - else - fewer_optionals [cur] comp - - let reduce_compatible compatible = match fewer_optionals [] (rm_duplicates [] compatible) with - | [] -> [] - | [v] -> [v] - | compatible -> - (* convert compatible into ( rate * compatible_type ) list *) - let rec mk_rate acc elist args = match elist, args with - | [], [] -> acc - | (_,true) :: elist, _ :: args -> mk_rate acc elist args - | (e,false) :: elist, (n,o,t) :: args -> - (* if the argument is an implicit cast, we need to start with a penalty *) - (* The penalty should be higher than any other implicit cast - other than Dynamic *) - (* since Dynamic has a penalty of max_int, we'll impose max_int - 1 to it *) - (match e.eexpr with - | TMeta( (Meta.ImplicitCast,_,_), _) -> - mk_rate ((max_int - 1, 0) :: acc) elist args - | _ -> - mk_rate (rate_conv 0 t e.etype :: acc) elist args) - | _ -> assert false - in - - let rated = ref [] in - List.iter (function - | (elist,TFun(args,ret),d) -> (try - rated := ( (elist,TFun(args,ret),d), mk_rate [] elist args ) :: !rated - with | Not_found -> ()) - | _ -> assert false - ) compatible; - - let rec loop best rem = match best, rem with - | _, [] -> best - | [], r1 :: rem -> loop [r1] rem - | (bover, bargs) :: b1, (rover, rargs) :: rem -> - if is_best bargs rargs then - loop best rem - else if is_best rargs bargs then - loop (loop b1 [rover,rargs]) rem - else (* equally specific *) - loop ( (rover,rargs) :: best ) rem - in - - let r = loop [] !rated in - List.map fst r -end;; - -module UnificationCallback = struct - let tf_stack = ref [] - - let check_call_params f el tl = - let rec loop acc el tl = match el,tl with - | e :: el, (n,_,t) :: tl -> - loop ((f e t) :: acc) el tl - | [], [] -> - acc - | [],_ -> - acc - | e :: el, [] -> - loop (e :: acc) el [] - in - List.rev (loop [] el tl) - - let check_call f el t = match follow t with - | TFun(args,_) -> - check_call_params f el args - | _ -> - List.map (fun e -> f e t_dynamic) el - - let rec run f e = - let f e t = - (* TODO: I don't think this should cause errors on Flash target *) - (* if not (type_iseq e.etype t) then f e t else e *) - f e t - in - let check e = match e.eexpr with - | TBinop((OpAssign | OpAssignOp _ as op),e1,e2) -> - let e2 = f e2 e1.etype in - {e with eexpr = TBinop(op,e1,e2)} - | TVar(v,Some ev) -> - let eo = Some (f ev v.v_type) in - { e with eexpr = TVar(v,eo) } - | TCall(e1,el) -> - let el = check_call f el e1.etype in - {e with eexpr = TCall(e1,el)} - | TNew(c,tl,el) -> - begin try - let tcf,_ = get_constructor (fun cf -> apply_params c.cl_params tl cf.cf_type) c in - let el = check_call f el tcf in - {e with eexpr = TNew(c,tl,el)} - with Not_found -> - e - end - | TArrayDecl el -> - begin match follow e.etype with - | TInst({cl_path=[],"Array"},[t]) -> {e with eexpr = TArrayDecl(List.map (fun e -> f e t) el)} - | _ -> e - end - | TObjectDecl fl -> - begin match follow e.etype with - | TAnon an -> - let fl = List.map (fun (n,e) -> - let e = try - let t = (PMap.find n an.a_fields).cf_type in - f e t - with Not_found -> - e - in - n,e - ) fl in - { e with eexpr = TObjectDecl fl } - | _ -> e - end - | TReturn (Some e1) -> - begin match !tf_stack with - | tf :: _ -> { e with eexpr = TReturn (Some (f e1 tf.tf_type))} - | _ -> e - end - | _ -> - e - in - match e.eexpr with - | TFunction tf -> - tf_stack := tf :: !tf_stack; - let etf = {e with eexpr = TFunction({tf with tf_expr = run f tf.tf_expr})} in - tf_stack := List.tl !tf_stack; - etf - | _ -> - check (Type.map_expr (run f) e) -end;; - -module DeprecationCheck = struct - - let curclass = ref null_class - - let warned_positions = Hashtbl.create 0 - - let print_deprecation_message com meta s p_usage = - let s = match meta with - | _,[EConst(String s),_],_ -> s - | _ -> Printf.sprintf "Usage of this %s is deprecated" s - in - if not (Hashtbl.mem warned_positions p_usage) then begin - Hashtbl.replace warned_positions p_usage true; - com.warning s p_usage; - end - - let check_meta com meta s p_usage = - try - print_deprecation_message com (Meta.get Meta.Deprecated meta) s p_usage; - with Not_found -> - () - - let check_cf com cf p = check_meta com cf.cf_meta "field" p - - let check_class com c p = if c != !curclass then check_meta com c.cl_meta "class" p - - let check_enum com en p = check_meta com en.e_meta "enum" p - - let check_ef com ef p = check_meta com ef.ef_meta "enum field" p - - let check_typedef com t p = check_meta com t.t_meta "typedef" p - - let check_module_type com mt p = match mt with - | TClassDecl c -> check_class com c p - | TEnumDecl en -> check_enum com en p - | _ -> () - - let run com = - let rec expr e = match e.eexpr with - | TField(e1,fa) -> - expr e1; - begin match fa with - | FStatic(c,cf) | FInstance(c,_,cf) -> - check_class com c e.epos; - check_cf com cf e.epos - | FAnon cf -> - check_cf com cf e.epos - | FClosure(co,cf) -> - (match co with None -> () | Some (c,_) -> check_class com c e.epos); - check_cf com cf e.epos - | FEnum(en,ef) -> - check_enum com en e.epos; - check_ef com ef e.epos; - | _ -> - () - end - | TNew(c,_,el) -> - List.iter expr el; - check_class com c e.epos; - (match c.cl_constructor with None -> () | Some cf -> check_cf com cf e.epos) - | TTypeExpr(mt) | TCast(_,Some mt) -> - check_module_type com mt e.epos - | TMeta((Meta.Deprecated,_,_) as meta,e1) -> - print_deprecation_message com meta "field" e1.epos; - expr e1; - | _ -> - Type.iter expr e - in - List.iter (fun t -> match t with - | TClassDecl c -> - curclass := c; - let field cf = match cf.cf_expr with None -> () | Some e -> expr e in - (match c.cl_constructor with None -> () | Some cf -> field cf); - (match c.cl_init with None -> () | Some e -> expr e); - List.iter field c.cl_ordered_statics; - List.iter field c.cl_ordered_fields; - | _ -> - () - ) com.types -end - -let interpolate_code com code tl f_string f_expr p = - let exprs = Array.of_list tl in - let i = ref 0 in - let err msg = - let pos = { p with pmin = p.pmin + !i } in - com.error msg pos - in - let regex = Str.regexp "[{}]" in - let rec loop m = match m with - | [] -> - () - | Str.Text txt :: tl -> - i := !i + String.length txt; - f_string txt; - loop tl - | Str.Delim a :: Str.Delim b :: tl when a = b -> - i := !i + 2; - f_string a; - loop tl - | Str.Delim "{" :: Str.Text n :: Str.Delim "}" :: tl -> - (try - let expr = Array.get exprs (int_of_string n) in - f_expr expr; - i := !i + 2 + String.length n; - loop tl - with - | Failure "int_of_string" -> - err ("Index expected. Got " ^ n) - | Invalid_argument _ -> - err ("Out-of-bounds special parameter: " ^ n)) - | Str.Delim x :: _ -> - err ("Unexpected " ^ x) - in - loop (Str.full_split regex code) diff --git a/common.ml b/common.ml deleted file mode 100644 index b98dd2b1..00000000 --- a/common.ml +++ /dev/null @@ -1,1078 +0,0 @@ -(* - * Copyright (C)2005-2013 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. - *) - -open Ast -open Type - -type package_rule = - | Forbidden - | Directory of string - | Remap of string - -type pos = Ast.pos - -type basic_types = { - mutable tvoid : t; - mutable tint : t; - mutable tfloat : t; - mutable tbool : t; - mutable tnull : t -> t; - mutable tstring : t; - mutable tarray : t -> t; -} - -type stats = { - s_files_parsed : int ref; - s_classes_built : int ref; - s_methods_typed : int ref; - s_macros_called : int ref; -} - -type platform = - | Cross - | Js - | Neko - | Flash - | Php - | Cpp - | Cs - | Java - | Python - -(** - The capture policy tells which handling we make of captured locals - (the locals which are referenced in local functions) - - See details/implementation in Codegen.captured_vars -*) -type capture_policy = - (** do nothing, let the platform handle it *) - | CPNone - (** wrap all captured variables into a single-element array to allow modifications *) - | CPWrapRef - (** similar to wrap ref, but will only apply to the locals that are declared in loops *) - | CPLoopVars - -type platform_config = { - (** has a static type system, with not-nullable basic types (Int/Float/Bool) *) - pf_static : bool; - (** has access to the "sys" package *) - pf_sys : bool; - (** local variables are block-scoped *) - pf_locals_scope : bool; - (** captured local variables are scoped *) - pf_captured_scope : bool; - (** generated locals must be absolutely unique wrt the current function *) - pf_unique_locals : bool; - (** captured variables handling (see before) *) - pf_capture_policy : capture_policy; - (** when calling a method with optional args, do we replace the missing args with "null" constants *) - pf_pad_nulls : bool; - (** add a final return to methods not having one already - prevent some compiler warnings *) - pf_add_final_return : bool; - (** does the platform natively support overloaded functions *) - pf_overload : bool; - (** does the platform generator handle pattern matching *) - pf_pattern_matching : bool; - (** can the platform use default values for non-nullable arguments *) - pf_can_skip_non_nullable_argument : bool; - (** type paths that are reserved on the platform *) - pf_reserved_type_paths : path list; -} - -type display_mode = - | DMNone - | DMDefault - | DMUsage - | DMPosition - | DMToplevel - | DMResolve of string - | DMType - -type context = { - (* config *) - version : int; - args : string list; - mutable sys_args : string list; - mutable display : display_mode; - mutable debug : bool; - mutable verbose : bool; - mutable foptimize : bool; - mutable platform : platform; - mutable config : platform_config; - mutable std_path : string list; - mutable class_path : string list; - mutable main_class : Type.path option; - mutable defines : (string,string) PMap.t; - mutable package_rules : (string,package_rule) PMap.t; - mutable error : string -> pos -> unit; - mutable warning : string -> pos -> unit; - mutable load_extern_type : (path -> pos -> (string * Ast.package) option) list; (* allow finding types which are not in sources *) - mutable filters : (unit -> unit) list; - mutable final_filters : (unit -> unit) list; - mutable defines_signature : string option; - mutable print : string -> unit; - mutable get_macros : unit -> context option; - mutable run_command : string -> int; - file_lookup_cache : (string,string option) Hashtbl.t; - mutable stored_typed_exprs : (int, texpr) PMap.t; - (* output *) - mutable file : string; - mutable flash_version : float; - mutable features : (string,bool) Hashtbl.t; - mutable modules : Type.module_def list; - mutable main : Type.texpr option; - mutable types : Type.module_type list; - mutable resources : (string,string) Hashtbl.t; - mutable neko_libs : string list; - mutable php_front : string option; - mutable php_lib : string option; - mutable php_prefix : string option; - mutable swf_libs : (string * (unit -> Swf.swf) * (unit -> ((string list * string),As3hl.hl_class) Hashtbl.t)) list; - mutable java_libs : (string * bool * (unit -> unit) * (unit -> (path list)) * (path -> ((JData.jclass * string * string) option))) list; (* (path,std,close,all_files,lookup) *) - mutable net_libs : (string * bool * (unit -> path list) * (path -> IlData.ilclass option)) list; (* (path,std,all_files,lookup) *) - mutable net_std : string list; - net_path_map : (path,string list * string list * string) Hashtbl.t; - mutable c_args : string list; - mutable js_gen : (unit -> unit) option; - (* typing *) - mutable basic : basic_types; - memory_marker : float array; -} - -exception Abort of string * Ast.pos - -let display_default = ref DMNone - -module Define = struct - - type strict_defined = - | AbsolutePath - | AdvancedTelemetry - | Analyzer - | As3 - | CheckXmlProxy - | CoreApi - | CoreApiSerialize - | Cppia - | Dce - | DceDebug - | Debug - | Display - | DllExport - | DllImport - | DocGen - | Dump - | DumpDependencies - | DumpIgnoreVarIds - | EraseGenerics - | Fdb - | FileExtension - | FlashStrict - | FlashUseStage - | ForceLibCheck - | ForceNativeProperty - | FormatWarning - | GencommonDebug - | HaxeBoot - | HaxeVer - | HxcppApiLevel - | IncludePrefix - | Interp - | JavaVer - | JsClassic - | JsEs5 - | JsUnflatten - | KeepOldOutput - | LoopUnrollMaxCost - | Macro - | MacroTimes - | NekoSource - | NekoV1 - | NetworkSandbox - | NetVer - | NetTarget - | NoCompilation - | NoCOpt - | NoDeprecationWarnings - | NoFlashOverride - | NoDebug - | NoInline - | NoOpt - | NoPatternMatching - | NoRoot - | NoSimplify - | NoSwfCompress - | NoTraces - | PhpPrefix - | RealPosition - | ReplaceFiles - | Scriptable - | ShallowExpose - | SourceMapContent - | Swc - | SwfCompressLevel - | SwfDebugPassword - | SwfDirectBlit - | SwfGpu - | SwfMetadata - | SwfPreloaderFrame - | SwfProtected - | SwfScriptTimeout - | SwfUseDoAbc - | Sys - | Unsafe - | UseNekoc - | UseRttiDoc - | Vcproj - | NoMacroCache - | Last (* must be last *) - - let infos = function - | AbsolutePath -> ("absolute_path","Print absolute file path in trace output") - | AdvancedTelemetry -> ("advanced-telemetry","Allow the SWF to be measured with Monocle tool") - | Analyzer -> ("analyzer","Use static analyzer for optimization (experimental)") - | As3 -> ("as3","Defined when outputing flash9 as3 source code") - | CheckXmlProxy -> ("check_xml_proxy","Check the used fields of the xml proxy") - | CoreApi -> ("core_api","Defined in the core api context") - | CoreApiSerialize -> ("core_api_serialize","Sets so some generated core api classes be marked with the Serializable attribute on C#") - | Cppia -> ("cppia", "Generate experimental cpp instruction assembly") - | Dce -> ("dce","The current DCE mode") - | DceDebug -> ("dce_debug","Show DCE log") - | Debug -> ("debug","Activated when compiling with -debug") - | Display -> ("display","Activated during completion") - | DllExport -> ("dll_export", "GenCPP experimental linking") - | DllImport -> ("dll_import", "GenCPP experimental linking") - | DocGen -> ("doc_gen","Do not perform any removal/change in order to correctly generate documentation") - | Dump -> ("dump","Dump the complete typed AST for internal debugging") - | DumpDependencies -> ("dump_dependencies","Dump the classes dependencies") - | DumpIgnoreVarIds -> ("dump_ignore_var_ids","Dump files do not contain variable IDs (helps with diff)") - | EraseGenerics -> ("erase_generics","Erase generic classes on C#") - | Fdb -> ("fdb","Enable full flash debug infos for FDB interactive debugging") - | FileExtension -> ("file_extension","Output filename extension for cpp source code") - | FlashStrict -> ("flash_strict","More strict typing for flash target") - | FlashUseStage -> ("flash_use_stage","Keep the SWF library initial stage") - (* force_lib_check is only here as a debug facility - compiler checking allows errors to be found more easily *) - | ForceLibCheck -> ("force_lib_check","Force the compiler to check -net-lib and -java-lib added classes (internal)") - | ForceNativeProperty -> ("force_native_property","Tag all properties with :nativeProperty metadata for 3.1 compatibility") - | FormatWarning -> ("format_warning","Print a warning for each formated string, for 2.x compatibility") - | GencommonDebug -> ("gencommon_debug","GenCommon internal") - | HaxeBoot -> ("haxe_boot","Given the name 'haxe' to the flash boot class instead of a generated name") - | HaxeVer -> ("haxe_ver","The current Haxe version value") - | HxcppApiLevel -> ("hxcpp_api_level","Provided to allow compatibility between hxcpp versions") - | IncludePrefix -> ("include_prefix","prepend path to generated include files") - | Interp -> ("interp","The code is compiled to be run with --interp") - | JavaVer -> ("java_ver", " Sets the Java version to be targeted") - | JsClassic -> ("js_classic","Don't use a function wrapper and strict mode in JS output") - | JsEs5 -> ("js_es5","Generate JS for ES5-compliant runtimes") - | JsUnflatten -> ("js_unflatten","Generate nested objects for packages and types") - | KeepOldOutput -> ("keep_old_output","Keep old source files in the output directory (for C#/Java)") - | LoopUnrollMaxCost -> ("loop_unroll_max_cost","Maximum cost (number of expressions * iterations) before loop unrolling is canceled (default 250)") - | Macro -> ("macro","Defined when we compile code in the macro context") - | MacroTimes -> ("macro_times","Display per-macro timing when used with --times") - | NetVer -> ("net_ver", " Sets the .NET version to be targeted") - | NetTarget -> ("net_target", " Sets the .NET target. Defaults to \"net\". xbox, micro (Micro Framework), compact (Compact Framework) are some valid values") - | NekoSource -> ("neko_source","Output neko source instead of bytecode") - | NekoV1 -> ("neko_v1","Keep Neko 1.x compatibility") - | NetworkSandbox -> ("network-sandbox","Use local network sandbox instead of local file access one") - | NoCompilation -> ("no-compilation","Disable final compilation for Cs, Cpp and Java") - | NoCOpt -> ("no_copt","Disable completion optimization (for debug purposes)") - | NoDebug -> ("no_debug","Remove all debug macros from cpp output") - | NoDeprecationWarnings -> ("no-deprecation-warnings","Do not warn if fields annotated with @:deprecated are used") - | NoFlashOverride -> ("no-flash-override", "Change overrides on some basic classes into HX suffixed methods, flash only") - | NoOpt -> ("no_opt","Disable optimizations") - | NoPatternMatching -> ("no_pattern_matching","Disable pattern matching") - | NoInline -> ("no_inline","Disable inlining") - | NoRoot -> ("no_root","Generate top-level types into haxe.root namespace") - | NoMacroCache -> ("no_macro_cache","Disable macro context caching") - | NoSimplify -> "no_simplify",("Disable simplification filter") - | NoSwfCompress -> ("no_swf_compress","Disable SWF output compression") - | NoTraces -> ("no_traces","Disable all trace calls") - | PhpPrefix -> ("php_prefix","Compiled with --php-prefix") - | RealPosition -> ("real_position","Disables haxe source mapping when targetting C#") - | ReplaceFiles -> ("replace_files","GenCommon internal") - | Scriptable -> ("scriptable","GenCPP internal") - | ShallowExpose -> ("shallow-expose","Expose types to surrounding scope of Haxe generated closure without writing to window object") - | SourceMapContent -> ("source-map-content","Include the hx sources as part of the JS source map") - | Swc -> ("swc","Output a SWC instead of a SWF") - | SwfCompressLevel -> ("swf_compress_level"," Set the amount of compression for the SWF output") - | SwfDebugPassword -> ("swf_debug_password", "Set a password for debugging") - | SwfDirectBlit -> ("swf_direct_blit", "Use hardware acceleration to blit graphics") - | SwfGpu -> ("swf_gpu", "Use GPU compositing features when drawing graphics") - | SwfMetadata -> ("swf_metadata", "= Include contents of as metadata in the swf") - | SwfPreloaderFrame -> ("swf_preloader_frame", "Insert empty first frame in swf") - | SwfProtected -> ("swf_protected","Compile Haxe private as protected in the SWF instead of public") - | SwfScriptTimeout -> ("swf_script_timeout", "Maximum ActionScript processing time before script stuck dialog box displays (in seconds)") - | SwfUseDoAbc -> ("swf_use_doabc", "Use DoAbc swf-tag instead of DoAbcDefine") - | Sys -> ("sys","Defined for all system platforms") - | Unsafe -> ("unsafe","Allow unsafe code when targeting C#") - | UseNekoc -> ("use_nekoc","Use nekoc compiler instead of internal one") - | UseRttiDoc -> ("use_rtti_doc","Allows access to documentation during compilation") - | Vcproj -> ("vcproj","GenCPP internal") - | Last -> assert false -end - -module MetaInfo = struct - open Meta - type meta_usage = - | TClass - | TClassField - | TAbstract - | TAbstractField - | TEnum - | TTypedef - | TAnyField - | TExpr - - type meta_parameter = - | HasParam of string - | Platform of platform - | Platforms of platform list - | UsedOn of meta_usage - | UsedOnEither of meta_usage list - | Internal - - let to_string = function - | Abi -> ":abi",("Function ABI/calling convention",[Platforms [Cpp]]) - | Abstract -> ":abstract",("Sets the underlying class implementation as 'abstract'",[Platforms [Java;Cs]]) - | Access -> ":access",("Forces private access to package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]]) - | Accessor -> ":accessor",("Used internally by DCE to mark property accessors",[UsedOn TClassField;Internal]) - | Allow -> ":allow",("Allows private access from package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]]) - | Analyzer -> ":analyzer",("Used to configure the static analyzer",[]) - | Annotation -> ":annotation",("Annotation (@interface) definitions on -java-lib imports will be annotated with this metadata. Has no effect on types compiled by Haxe",[Platform Java; UsedOn TClass]) - | ArrayAccess -> ":arrayAccess",("Allows [] access on an abstract",[UsedOnEither [TAbstract;TAbstractField]]) - | Ast -> ":ast",("Internally used to pass the AST source into the typed AST",[Internal]) - | AutoBuild -> ":autoBuild",("Extends @:build metadata to all extending and implementing classes",[HasParam "Build macro call";UsedOn TClass]) - | Bind -> ":bind",("Override Swf class declaration",[Platform Flash;UsedOn TClass]) - | Bitmap -> ":bitmap",("Embeds given bitmap data into the class (must extend flash.display.BitmapData)",[HasParam "Bitmap file path";UsedOn TClass;Platform Flash]) - | BridgeProperties -> ":bridgeProperties",("Creates native property bridges for all Haxe properties in this class",[UsedOn TClass;Platform Cs]) - | Build -> ":build",("Builds a class or enum from a macro",[HasParam "Build macro call";UsedOnEither [TClass;TEnum]]) - | BuildXml -> ":buildXml",("Specify xml data to be injected into Build.xml",[Platform Cpp]) - | Callable -> ":callable",("Abstract forwards call to its underlying type",[UsedOn TAbstract]) - | Class -> ":class",("Used internally to annotate an enum that will be generated as a class",[Platforms [Java;Cs]; UsedOn TEnum; Internal]) - | ClassCode -> ":classCode",("Used to inject platform-native code into a class",[Platforms [Java;Cs]; UsedOn TClass]) - | Commutative -> ":commutative",("Declares an abstract operator as commutative",[UsedOn TAbstractField]) - | CompilerGenerated -> ":compilerGenerated",("Marks a field as generated by the compiler. Shouldn't be used by the end user",[Platforms [Java;Cs]]) - | CoreApi -> ":coreApi",("Identifies this class as a core api class (forces Api check)",[UsedOnEither [TClass;TEnum;TTypedef;TAbstract]]) - | CoreType -> ":coreType",("Identifies an abstract as core type so that it requires no implementation",[UsedOn TAbstract]) - | CppFileCode -> ":cppFileCode",("Code to be injected into generated cpp file",[Platform Cpp]) - | CppInclude -> ":cppInclude",("File to be included in generated cpp file",[Platform Cpp]) - | CppNamespaceCode -> ":cppNamespaceCode",("",[Platform Cpp]) - | CsNative -> ":csNative",("Automatically added by -net-lib on classes generated from .NET DLL files",[Platform Cs; UsedOnEither[TClass;TEnum]; Internal]) - | Dce -> ":dce",("Forces dead code elimination even when -dce full is not specified",[UsedOnEither [TClass;TEnum]]) - | Debug -> ":debug",("Forces debug information to be generated into the Swf even without -debug",[UsedOnEither [TClass;TClassField]; Platform Flash]) - | Decl -> ":decl",("",[Platform Cpp]) - | DefParam -> ":defParam",("?",[]) - | Delegate -> ":delegate",("Automatically added by -net-lib on delegates",[Platform Cs; UsedOn TAbstract]) - | Depend -> ":depend",("",[Platform Cpp]) - | Deprecated -> ":deprecated",("Automatically added by -java-lib on class fields annotated with @Deprecated annotation. Has no effect on types compiled by Haxe",[Platform Java; UsedOnEither [TClass;TEnum;TClassField]]) - | DirectlyUsed -> ":directlyUsed",("Marks types that are directly referenced by non-extern code",[Internal]) - | DynamicObject -> ":dynamicObject",("Used internally to identify the Dynamic Object implementation",[Platforms [Java;Cs]; UsedOn TClass; Internal]) - | Enum -> ":enum",("Used internally to annotate a class that was generated from an enum",[Platforms [Java;Cs]; UsedOn TClass; Internal]) - | EnumConstructorParam -> ":enumConstructorParam",("Used internally to annotate GADT type parameters",[UsedOn TClass; Internal]) - | Event -> ":event",("Automatically added by -net-lib on events. Has no effect on types compiled by Haxe",[Platform Cs; UsedOn TClassField]) - | Exhaustive -> ":exhaustive",("",[Internal]) - | Expose -> ":expose",("Makes the class available on the window object",[HasParam "?Name=Class path";UsedOn TClass;Platform Js]) - | Extern -> ":extern",("Marks the field as extern so it is not generated",[UsedOn TClassField]) - | FakeEnum -> ":fakeEnum",("Treat enum as collection of values of the specified type",[HasParam "Type name";UsedOn TEnum]) - | File -> ":file",("Includes a given binary file into the target Swf and associates it with the class (must extend flash.utils.ByteArray)",[HasParam "File path";UsedOn TClass;Platform Flash]) - | Final -> ":final",("Prevents a class from being extended",[UsedOn TClass]) - | FlatEnum -> ":flatEnum",("Internally used to mark an enum as being flat, i.e. having no function constructors",[UsedOn TEnum; Internal]) - | Font -> ":font",("Embeds the given TrueType font into the class (must extend flash.text.Font)",[HasParam "TTF path";HasParam "Range String";UsedOn TClass]) - | Forward -> ":forward",("Forwards field access to underlying type",[HasParam "List of field names";UsedOn TAbstract]) - | From -> ":from",("Specifies that the field of the abstract is a cast operation from the type identified in the function",[UsedOn TAbstractField]) - | FunctionCode -> ":functionCode",("",[Platform Cpp]) - | FunctionTailCode -> ":functionTailCode",("",[Platform Cpp]) - | Generic -> ":generic",("Marks a class or class field as generic so each type parameter combination generates its own type/field",[UsedOnEither [TClass;TClassField]]) - | GenericBuild -> ":genericBuild",("Builds instances of a type using the specified macro",[UsedOn TClass]) - | GenericInstance -> ":genericInstance",("Internally used to mark instances of @:generic methods",[UsedOn TClassField;Internal]) - | Getter -> ":getter",("Generates a native getter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash]) - | Hack -> ":hack",("Allows extending classes marked as @:final",[UsedOn TClass]) - | HasUntyped -> (":has_untyped",("Used by the typer to mark fields that have untyped expressions",[Internal])) - | HaxeGeneric -> ":haxeGeneric",("Used internally to annotate non-native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; Internal]) - | HeaderClassCode -> ":headerClassCode",("Code to be injected into the generated class, in the header",[Platform Cpp]) - | HeaderCode -> ":headerCode",("Code to be injected into the generated header file",[Platform Cpp]) - | HeaderInclude -> ":headerInclude",("File to be included in generated header file",[Platform Cpp]) - | HeaderNamespaceCode -> ":headerNamespaceCode",("",[Platform Cpp]) - | HxGen -> ":hxGen",("Annotates that an extern class was generated by Haxe",[Platforms [Java;Cs]; UsedOnEither [TClass;TEnum]]) - | IfFeature -> ":ifFeature",("Causes a field to be kept by DCE if the given feature is part of the compilation",[HasParam "Feature name";UsedOn TClassField]) - | Impl -> ":impl",("Used internally to mark abstract implementation fields",[UsedOn TAbstractField; Internal]) - | PythonImport -> ":pythonImport",("Generates python import statement for extern classes",[Platforms [Python]; UsedOn TClass]) - | ImplicitCast -> ":implicitCast",("Generated automatically on the AST when an implicit abstract cast happens",[Internal; UsedOn TExpr]) - | Include -> ":include",("",[Platform Cpp]) - | InitPackage -> ":initPackage",("?",[]) - | Meta.Internal -> ":internal",("Generates the annotated field/class with 'internal' access",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum;TClassField]]) - | IsVar -> ":isVar",("Forces a physical field to be generated for properties that otherwise would not require one",[UsedOn TClassField]) - | JavaCanonical -> ":javaCanonical",("Used by the Java target to annotate the canonical path of the type",[HasParam "Output type package";HasParam "Output type name";UsedOnEither [TClass;TEnum]; Platform Java]) - | JavaNative -> ":javaNative",("Automatically added by -java-lib on classes generated from JAR/class files",[Platform Java; UsedOnEither[TClass;TEnum]; Internal]) - | JsRequire -> ":jsRequire",("Generate javascript module require expression for given extern",[Platform Js; UsedOn TClass]) - | Keep -> ":keep",("Causes a field or type to be kept by DCE",[]) - | KeepInit -> ":keepInit",("Causes a class to be kept by DCE even if all its field are removed",[UsedOn TClass]) - | KeepSub -> ":keepSub",("Extends @:keep metadata to all implementing and extending classes",[UsedOn TClass]) - | LibType -> ":libType",("Used by -net-lib and -java-lib to mark a class that shouldn't be checked (overrides, interfaces, etc) by the type loader",[Internal; UsedOn TClass; Platforms [Java;Cs]]) - | Meta -> ":meta",("Internally used to mark a class field as being the metadata field",[]) - | Macro -> ":macro",("(deprecated)",[]) - | MaybeUsed -> ":maybeUsed",("Internally used by DCE to mark fields that might be kept",[Internal]) - | MergeBlock -> ":mergeBlock",("Merge the annotated block into the current scope",[UsedOn TExpr]) - | MultiType -> ":multiType",("Specifies that an abstract chooses its this-type from its @:to functions",[UsedOn TAbstract; HasParam "Relevant type parameters"]) - | Native -> ":native",("Rewrites the path of a class or enum during generation",[HasParam "Output type path";UsedOnEither [TClass;TEnum]]) - | NativeChildren -> ":nativeChildren",("Annotates that all children from a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs]; UsedOn TClass]) - | NativeGen -> ":nativeGen",("Annotates that a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs;Python]; UsedOnEither[TClass;TEnum]]) - | NativeGeneric -> ":nativeGeneric",("Used internally to annotate native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; Internal]) - | NativeProperty -> ":nativeProperty",("Use native properties which will execute even with dynamic usage",[Platform Cpp]) - | NoCompletion -> ":noCompletion",("Prevents the compiler from suggesting completion on this field",[UsedOn TClassField]) - | NoDebug -> ":noDebug",("Does not generate debug information into the Swf even if -debug is set",[UsedOnEither [TClass;TClassField];Platform Flash]) - | NoDoc -> ":noDoc",("Prevents a type from being included in documentation generation",[]) - | NoExpr -> ":noExpr",("Internally used to mark abstract fields which have no expression by design",[Internal]) - | NoImportGlobal -> ":noImportGlobal",("Prevents a static field from being imported with import Class.*",[UsedOn TAnyField]) - | NonVirtual -> ":nonVirtual",("Declares function to be non-virtual in cpp",[Platform Cpp]) - | NoPackageRestrict -> ":noPackageRestrict",("Allows a module to be accessed across all targets if found on its first type",[Internal]) - | NoPrivateAccess -> ":noPrivateAccess",("Disallow private access to anything for the annotated expression",[UsedOn TExpr]) - | NoStack -> ":noStack",("",[Platform Cpp]) - | NotNull -> ":notNull",("Declares an abstract type as not accepting null values",[UsedOn TAbstract]) - | NoUsing -> ":noUsing",("Prevents a field from being used with 'using'",[UsedOn TClassField]) - | Ns -> ":ns",("Internally used by the Swf generator to handle namespaces",[Platform Flash]) - | Op -> ":op",("Declares an abstract field as being an operator overload",[HasParam "The operation";UsedOn TAbstractField]) - | Optional -> ":optional",("Marks the field of a structure as optional",[UsedOn TClassField]) - | Overload -> ":overload",("Allows the field to be called with different argument types",[HasParam "Function specification (no expression)";UsedOn TClassField]) - | Public -> ":public",("Marks a class field as being public",[UsedOn TClassField]) - | PublicFields -> ":publicFields",("Forces all class fields of inheriting classes to be public",[UsedOn TClass]) - | QuotedField -> ":quotedField",("Used internally to mark structure fields which are quoted in syntax",[Internal]) - | PrivateAccess -> ":privateAccess",("Allow private access to anything for the annotated expression",[UsedOn TExpr]) - | Protected -> ":protected",("Marks a class field as being protected",[UsedOn TClassField]) - | Property -> ":property",("Marks a property field to be compiled as a native C# property",[UsedOn TClassField;Platform Cs]) - | ReadOnly -> ":readOnly",("Generates a field with the 'readonly' native keyword",[Platform Cs; UsedOn TClassField]) - | RealPath -> ":realPath",("Internally used on @:native types to retain original path information",[Internal]) - | Remove -> ":remove",("Causes an interface to be removed from all implementing classes before generation",[UsedOn TClass]) - | Require -> ":require",("Allows access to a field only if the specified compiler flag is set",[HasParam "Compiler flag to check";UsedOn TClassField]) - | RequiresAssign -> ":requiresAssign",("Used internally to mark certain abstract operator overloads",[Internal]) - (* | Resolve -> ":resolve",("Abstract fields marked with this metadata can be used to resolve unknown fields",[UsedOn TClassField]) *) - | ReplaceReflection -> ":replaceReflection",("Used internally to specify a function that should replace its internal __hx_functionName counterpart",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum]; Internal]) - | Rtti -> ":rtti",("Adds runtime type informations",[UsedOn TClass]) - | Runtime -> ":runtime",("?",[]) - | RuntimeValue -> ":runtimeValue",("Marks an abstract as being a runtime value",[UsedOn TAbstract]) - | SelfCall -> ":selfCall",("Translates method calls into calling object directly",[UsedOn TClassField; Platform Js]) - | Setter -> ":setter",("Generates a native setter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash]) - | StoredTypedExpr -> ":storedTypedExpr",("Used internally to reference a typed expression returned from a macro",[Internal]) - | SkipCtor -> ":skipCtor",("Used internally to generate a constructor as if it were a native type (no __hx_ctor)",[Platforms [Java;Cs]; Internal]) - | SkipReflection -> ":skipReflection",("Used internally to annotate a field that shouldn't have its reflection data generated",[Platforms [Java;Cs]; UsedOn TClassField; Internal]) - | Sound -> ":sound",( "Includes a given .wav or .mp3 file into the target Swf and associates it with the class (must extend flash.media.Sound)",[HasParam "File path";UsedOn TClass;Platform Flash]) - | SourceFile -> ":sourceFile",("Source code filename for external class",[Platform Cpp]) - | Strict -> ":strict",("Used to declare a native C# attribute or a native Java metadata. Is type checked",[Platforms [Java;Cs]]) - | Struct -> ":struct",("Marks a class definition as a struct",[Platform Cs; UsedOn TClass]) - | StructAccess -> ":structAccess",("Marks an extern class as using struct access('.') not pointer('->')",[Platform Cpp; UsedOn TClass]) - | SuppressWarnings -> ":suppressWarnings",("Adds a SuppressWarnings annotation for the generated Java class",[Platform Java; UsedOn TClass]) - | Throws -> ":throws",("Adds a 'throws' declaration to the generated function",[HasParam "Type as String"; Platform Java; UsedOn TClassField]) - | This -> ":this",("Internally used to pass a 'this' expression to macros",[Internal; UsedOn TExpr]) - | To -> ":to",("Specifies that the field of the abstract is a cast operation to the type identified in the function",[UsedOn TAbstractField]) - | ToString -> ":toString",("Internally used",[Internal]) - | Transient -> ":transient",("Adds the 'transient' flag to the class field",[Platform Java; UsedOn TClassField]) - | ValueUsed -> ":valueUsed",("Internally used by DCE to mark an abstract value as used",[Internal]) - | Volatile -> ":volatile",("",[Platforms [Java;Cs]]) - | Unbound -> ":unbound", ("Compiler internal to denote unbounded global variable",[]) - | UnifyMinDynamic -> ":unifyMinDynamic",("Allows a collection of types to unify to Dynamic",[UsedOn TClassField]) - | Unreflective -> ":unreflective",("",[Platform Cpp]) - | Unsafe -> ":unsafe",("Declares a class, or a method with the C#'s 'unsafe' flag",[Platform Cs; UsedOnEither [TClass;TClassField]]) - | Usage -> ":usage",("?",[]) - | Used -> ":used",("Internally used by DCE to mark a class or field as used",[Internal]) - | Value -> ":value",("Used to store default values for fields and function arguments",[UsedOn TClassField]) - | Void -> ":void",("Use Cpp native 'void' return type",[Platform Cpp]) - | Last -> assert false - (* do not put any custom metadata after Last *) - | Dollar s -> "$" ^ s,("",[]) - | Custom s -> s,("",[]) - - let hmeta = - let h = Hashtbl.create 0 in - let rec loop i = - let m = Obj.magic i in - if m <> Last then begin - Hashtbl.add h (fst (to_string m)) m; - loop (i + 1); - end; - in - loop 0; - h - - let parse s = try Hashtbl.find hmeta (":" ^ s) with Not_found -> Custom (":" ^ s) - - let from_string s = - if s = "" then Custom "" else match s.[0] with - | ':' -> (try Hashtbl.find hmeta s with Not_found -> Custom s) - | '$' -> Dollar (String.sub s 1 (String.length s - 1)) - | _ -> Custom s -end - -let stats = - { - s_files_parsed = ref 0; - s_classes_built = ref 0; - s_methods_typed = ref 0; - s_macros_called = ref 0; - } - -let default_config = - { - pf_static = true; - pf_sys = true; - pf_locals_scope = true; - pf_captured_scope = true; - pf_unique_locals = false; - pf_capture_policy = CPNone; - pf_pad_nulls = false; - pf_add_final_return = false; - pf_overload = false; - pf_pattern_matching = false; - pf_can_skip_non_nullable_argument = true; - pf_reserved_type_paths = []; - } - -let get_config com = - let defined f = PMap.mem (fst (Define.infos f)) com.defines in - match com.platform with - | Cross -> - default_config - | Js -> - { - pf_static = false; - pf_sys = false; - pf_locals_scope = false; - pf_captured_scope = false; - pf_unique_locals = false; - pf_capture_policy = CPLoopVars; - pf_pad_nulls = false; - pf_add_final_return = false; - pf_overload = false; - pf_pattern_matching = false; - pf_can_skip_non_nullable_argument = true; - pf_reserved_type_paths = [([],"Object");([],"Error")]; - } - | Neko -> - { - pf_static = false; - pf_sys = true; - pf_locals_scope = true; - pf_captured_scope = true; - pf_unique_locals = false; - pf_capture_policy = CPNone; - pf_pad_nulls = true; - pf_add_final_return = false; - pf_overload = false; - pf_pattern_matching = false; - pf_can_skip_non_nullable_argument = true; - pf_reserved_type_paths = []; - } - | Flash when defined Define.As3 -> - { - pf_static = true; - pf_sys = false; - pf_locals_scope = false; - pf_captured_scope = true; - pf_unique_locals = true; - pf_capture_policy = CPLoopVars; - pf_pad_nulls = false; - pf_add_final_return = true; - pf_overload = false; - pf_pattern_matching = false; - pf_can_skip_non_nullable_argument = false; - pf_reserved_type_paths = []; - } - | Flash -> - { - pf_static = true; - pf_sys = false; - pf_locals_scope = true; - pf_captured_scope = true; (* handled by genSwf9 *) - pf_unique_locals = false; - pf_capture_policy = CPLoopVars; - pf_pad_nulls = false; - pf_add_final_return = false; - pf_overload = false; - pf_pattern_matching = false; - pf_can_skip_non_nullable_argument = false; - pf_reserved_type_paths = [([],"Object");([],"Error")]; - } - | Php -> - { - pf_static = false; - pf_sys = true; - pf_locals_scope = false; (* some duplicate work is done in genPhp *) - pf_captured_scope = false; - pf_unique_locals = false; - pf_capture_policy = CPNone; - pf_pad_nulls = true; - pf_add_final_return = false; - pf_overload = false; - pf_pattern_matching = false; - pf_can_skip_non_nullable_argument = true; - pf_reserved_type_paths = []; - } - | Cpp -> - { - pf_static = true; - pf_sys = true; - pf_locals_scope = true; - pf_captured_scope = true; - pf_unique_locals = false; - pf_capture_policy = CPWrapRef; - pf_pad_nulls = true; - pf_add_final_return = true; - pf_overload = false; - pf_pattern_matching = false; - pf_can_skip_non_nullable_argument = true; - pf_reserved_type_paths = []; - } - | Cs -> - { - pf_static = true; - pf_sys = true; - pf_locals_scope = false; - pf_captured_scope = true; - pf_unique_locals = true; - pf_capture_policy = CPWrapRef; - pf_pad_nulls = true; - pf_add_final_return = false; - pf_overload = true; - pf_pattern_matching = false; - pf_can_skip_non_nullable_argument = true; - pf_reserved_type_paths = []; - } - | Java -> - { - pf_static = true; - pf_sys = true; - pf_locals_scope = false; - pf_captured_scope = true; - pf_unique_locals = false; - pf_capture_policy = CPWrapRef; - pf_pad_nulls = true; - pf_add_final_return = false; - pf_overload = true; - pf_pattern_matching = false; - pf_can_skip_non_nullable_argument = true; - pf_reserved_type_paths = []; - } - | Python -> - { - pf_static = false; - pf_sys = true; - pf_locals_scope = false; - pf_captured_scope = false; - pf_unique_locals = false; - pf_capture_policy = CPLoopVars; - pf_pad_nulls = false; - pf_add_final_return = false; - pf_overload = false; - pf_pattern_matching = false; - pf_can_skip_non_nullable_argument = true; - pf_reserved_type_paths = []; - } - -let memory_marker = [|Unix.time()|] - -let create v args = - let m = Type.mk_mono() in - { - version = v; - args = args; - sys_args = args; - debug = false; - display = !display_default; - verbose = false; - foptimize = true; - features = Hashtbl.create 0; - platform = Cross; - config = default_config; - print = (fun s -> print_string s; flush stdout); - run_command = Sys.command; - std_path = []; - class_path = []; - main_class = None; - defines = PMap.add "true" "1" (if !display_default <> DMNone then PMap.add "display" "1" PMap.empty else PMap.empty); - package_rules = PMap.empty; - file = ""; - types = []; - filters = []; - final_filters = []; - modules = []; - main = None; - flash_version = 10.; - resources = Hashtbl.create 0; - php_front = None; - php_lib = None; - swf_libs = []; - java_libs = []; - net_libs = []; - net_std = []; - net_path_map = Hashtbl.create 0; - c_args = []; - neko_libs = []; - php_prefix = None; - js_gen = None; - load_extern_type = []; - defines_signature = None; - get_macros = (fun() -> None); - warning = (fun _ _ -> assert false); - error = (fun _ _ -> assert false); - basic = { - tvoid = m; - tint = m; - tfloat = m; - tbool = m; - tnull = (fun _ -> assert false); - tstring = m; - tarray = (fun _ -> assert false); - }; - file_lookup_cache = Hashtbl.create 0; - stored_typed_exprs = PMap.empty; - memory_marker = memory_marker; - } - -let log com str = - if com.verbose then com.print (str ^ "\n") - -let clone com = - let t = com.basic in - { com with - basic = { t with tvoid = t.tvoid }; - main_class = None; - features = Hashtbl.create 0; - file_lookup_cache = Hashtbl.create 0; - } - -let file_time file = - try (Unix.stat file).Unix.st_mtime with _ -> 0. - -let get_signature com = - match com.defines_signature with - | Some s -> s - | None -> - let str = String.concat "@" (PMap.foldi (fun k v acc -> - (* don't make much difference between these special compilation flags *) - match k with - | "display" | "use_rtti_doc" | "macrotimes" -> acc - | _ -> k :: v :: acc - ) com.defines []) in - let s = Digest.string str in - com.defines_signature <- Some s; - s - -let file_extension file = - match List.rev (ExtString.String.nsplit file ".") with - | e :: _ -> String.lowercase e - | [] -> "" - -let platforms = [ - Js; - Neko; - Flash; - Php; - Cpp; - Cs; - Java; - Python; -] - -let platform_name = function - | Cross -> "cross" - | Js -> "js" - | Neko -> "neko" - | Flash -> "flash" - | Php -> "php" - | Cpp -> "cpp" - | Cs -> "cs" - | Java -> "java" - | Python -> "python" - -let flash_versions = List.map (fun v -> - let maj = int_of_float v in - let min = int_of_float (mod_float (v *. 10.) 10.) in - v, string_of_int maj ^ (if min = 0 then "" else "_" ^ string_of_int min) -) [9.;10.;10.1;10.2;10.3;11.;11.1;11.2;11.3;11.4;11.5;11.6;11.7;11.8;11.9;12.0;13.0;14.0;15.0;16.0;17.0] - -let flash_version_tag = function - | 6. -> 6 - | 7. -> 7 - | 8. -> 8 - | 9. -> 9 - | 10. | 10.1 -> 10 - | 10.2 -> 11 - | 10.3 -> 12 - | 11. -> 13 - | 11.1 -> 14 - | 11.2 -> 15 - | 11.3 -> 16 - | 11.4 -> 17 - | 11.5 -> 18 - | 11.6 -> 19 - | 11.7 -> 20 - | 11.8 -> 21 - | 11.9 -> 22 - | 12.0 -> 23 - | 13.0 -> 24 - | 14.0 -> 25 - | 15.0 -> 26 - | 16.0 -> 27 - | 17.0 -> 28 - | v -> failwith ("Invalid SWF version " ^ string_of_float v) - -let raw_defined ctx v = - PMap.mem v ctx.defines - -let defined ctx v = - raw_defined ctx (fst (Define.infos v)) - -let raw_defined_value ctx k = - PMap.find k ctx.defines - -let defined_value ctx v = - raw_defined_value ctx (fst (Define.infos v)) - -let defined_value_safe ctx v = - try defined_value ctx v - with Not_found -> "" - -let raw_define ctx v = - let k,v = try ExtString.String.split v "=" with _ -> v,"1" in - ctx.defines <- PMap.add k v ctx.defines; - let k = String.concat "_" (ExtString.String.nsplit k "-") in - ctx.defines <- PMap.add k v ctx.defines; - ctx.defines_signature <- None - -let define_value ctx k v = - raw_define ctx (fst (Define.infos k) ^ "=" ^ v) - -let define ctx v = - raw_define ctx (fst (Define.infos v)) - -let init_platform com pf = - com.platform <- pf; - let name = platform_name pf in - let forbid acc p = if p = name || PMap.mem p acc then acc else PMap.add p Forbidden acc in - com.package_rules <- List.fold_left forbid com.package_rules (List.map platform_name platforms); - com.config <- get_config com; -(* if com.config.pf_static then define com "static"; *) - if com.config.pf_sys then define com Define.Sys else com.package_rules <- PMap.add "sys" Forbidden com.package_rules; - raw_define com name - -let add_feature com f = - Hashtbl.replace com.features f true - -let has_dce com = - (try defined_value com Define.Dce <> "no" with Not_found -> false) - -(* - TODO: The has_dce check is there because we mark types with @:directlyUsed in the DCE filter, - which is not run in dce=no and thus we can't know if a type is used directly or not, - so we just assume that they are. - - If we had dce filter always running (even with dce=no), we would have types marked with @:directlyUsed - and we wouldn't need to generate unnecessary imports in dce=no, but that's good enough for now. -*) -let is_directly_used com meta = - not (has_dce com) || Ast.Meta.has Ast.Meta.DirectlyUsed meta - -let rec has_feature com f = - try - Hashtbl.find com.features f - with Not_found -> - if com.types = [] then not (has_dce com) else - match List.rev (ExtString.String.nsplit f ".") with - | [] -> assert false - | [cl] -> has_feature com (cl ^ ".*") - | meth :: cl :: pack -> - let r = (try - let path = List.rev pack, cl in - (match List.find (fun t -> t_path t = path && not (Ast.Meta.has Ast.Meta.RealPath (t_infos t).mt_meta)) com.types with - | t when meth = "*" -> (match t with TAbstractDecl a -> Ast.Meta.has Ast.Meta.ValueUsed a.a_meta | _ -> - Ast.Meta.has Ast.Meta.Used (t_infos t).mt_meta) - | TClassDecl ({cl_extern = true} as c) when com.platform <> Js || cl <> "Array" && cl <> "Math" -> - Meta.has Meta.Used (try PMap.find meth c.cl_statics with Not_found -> PMap.find meth c.cl_fields).cf_meta - | TClassDecl c -> - PMap.exists meth c.cl_statics || PMap.exists meth c.cl_fields - | _ -> - false) - with Not_found -> - false - ) in - let r = r || not (has_dce com) in - Hashtbl.add com.features f r; - r - -let allow_package ctx s = - try - if (PMap.find s ctx.package_rules) = Forbidden then ctx.package_rules <- PMap.remove s ctx.package_rules - with Not_found -> - () - -let error msg p = raise (Abort (msg,p)) - -let platform ctx p = ctx.platform = p - -let add_filter ctx f = - ctx.filters <- f :: ctx.filters - -let add_final_filter ctx f = - ctx.final_filters <- f :: ctx.final_filters - -let find_file ctx f = - try - (match Hashtbl.find ctx.file_lookup_cache f with - | None -> raise Exit - | Some f -> f) - with Exit -> - raise Not_found - | Not_found -> - let rec loop had_empty = function - | [] when had_empty -> raise Not_found - | [] -> loop true [""] - | p :: l -> - let file = p ^ f in - if Sys.file_exists file then - file - else - loop (had_empty || p = "") l - in - let r = (try Some (loop false ctx.class_path) with Not_found -> None) in - Hashtbl.add ctx.file_lookup_cache f r; - (match r with - | None -> raise Not_found - | Some f -> f) - - -let get_full_path f = try Extc.get_full_path f with _ -> f - -let unique_full_path = if Sys.os_type = "Win32" || Sys.os_type = "Cygwin" then (fun f -> String.lowercase (get_full_path f)) else get_full_path - -let normalize_path p = - let l = String.length p in - if l = 0 then - "./" - else match p.[l-1] with - | '\\' | '/' -> p - | _ -> p ^ "/" - -let rec mkdir_recursive base dir_list = - match dir_list with - | [] -> () - | dir :: remaining -> - let path = match base with - | "" -> dir - | "/" -> "/" ^ dir - | _ -> base ^ "/" ^ dir - in - if not ( (path = "") || ( ((String.length path) = 2) && ((String.sub path 1 1) = ":") ) ) then - if not (Sys.file_exists path) then - Unix.mkdir path 0o755; - mkdir_recursive (if (path = "") then "/" else path) remaining - -let mkdir_from_path path = - let parts = Str.split_delim (Str.regexp "[\\/]+") path in - match parts with - | [] -> (* path was "" *) () - | _ -> - let dir_list = List.rev (List.tl (List.rev parts)) in - mkdir_recursive "" dir_list - -let mem_size v = - Objsize.size_with_headers (Objsize.objsize v [] []) - -(* ------------------------- TIMERS ----------------------------- *) - -type timer_infos = { - name : string; - mutable start : float list; - mutable total : float; -} - -let get_time = Extc.time -let htimers = Hashtbl.create 0 - -let new_timer name = - try - let t = Hashtbl.find htimers name in - t.start <- get_time() :: t.start; - t - with Not_found -> - let t = { name = name; start = [get_time()]; total = 0.; } in - Hashtbl.add htimers name t; - t - -let curtime = ref [] - -let close t = - let start = (match t.start with - | [] -> assert false - | s :: l -> t.start <- l; s - ) in - let now = get_time() in - let dt = now -. start in - t.total <- t.total +. dt; - let rec loop() = - match !curtime with - | [] -> failwith ("Timer " ^ t.name ^ " closed while not active") - | tt :: l -> curtime := l; if t != tt then loop() - in - loop(); - (* because of rounding errors while adding small times, we need to make sure that we don't have start > now *) - List.iter (fun ct -> ct.start <- List.map (fun t -> let s = t +. dt in if s > now then now else s) ct.start) !curtime - -let timer name = - let t = new_timer name in - curtime := t :: !curtime; - (function() -> close t) - -let rec close_times() = - match !curtime with - | [] -> () - | t :: _ -> close t; close_times() - -;; -Ast.Meta.to_string_ref := fun m -> fst (MetaInfo.to_string m) - -(* Taken from OCaml source typing/oprint.ml - - This is a better version of string_of_float which prints without loss of precision - so that float_of_string (float_repres x) = x for all floats x -*) -let valid_float_lexeme s = - let l = String.length s in - let rec loop i = - if i >= l then s ^ "." else - match s.[i] with - | '0' .. '9' | '-' -> loop (i+1) - | _ -> s - in loop 0 - -let float_repres f = - match classify_float f with - | FP_nan -> "nan" - | FP_infinite -> - if f < 0.0 then "neg_infinity" else "infinity" - | _ -> - let float_val = - let s1 = Printf.sprintf "%.12g" f in - if f = float_of_string s1 then s1 else - let s2 = Printf.sprintf "%.15g" f in - if f = float_of_string s2 then s2 else - Printf.sprintf "%.18g" f - in valid_float_lexeme float_val diff --git a/extra/CHANGES.txt b/extra/CHANGES.txt index eb924b2f..03f089e9 100644 --- a/extra/CHANGES.txt +++ b/extra/CHANGES.txt @@ -1,3 +1,167 @@ +2017-01-31: 3.4.0 + + General improvements and optimizations: + + all : support completion for static extensions (#5766) + all : removed neko dependency for macros, use PCRE instead + all : disabled analyzer optimizations by default, re-enable with -D analyzer-optimize + php7 : generate native `$v instanceof MyType` instead of `Std.is(v, MyType)` where possible for better performance + php7 : added @:phpNoConstructor meta for externs which do not have native php constructors and yet can be constructed + php7 : greatly reduced amount of generated tmp vars + php7 : `Array` performance improvements + hl : made various improvements + + Bugfixes: + + all : fixed `using` picking up non-static abstract functions (#5888) + all : fixed issue with side-effect detection when optimizing (#5911) + all : fixed issue with zlib bindings causing zlib_deflate errors (#5941) + php7 : Allow user-defined modules in `php` package (#5921) + php7 : Dereference some of `php.Syntax` methods if required (#5923) + php : fixed assigning a method of dynamic value to a variable (#5469) + php : fixed missing initialization of dynamic methods in classes with empty constructors (#4723) + +2016-12-24: 3.4.0-RC2 + + New features: + + js : added API documentation to HTML externs (#5868) + php : added php7 target, enabled with -D php7 + + Bugfixes: + + all : fixed top-down inference infinite recursion issue (#5848) + all : fixed regression in Compiler.include (#5847) + all : fixed Not_found exception related to try/catch (#5851) + all : fixed metadata completion showing up in trace arguments (#5775) + all : fixed problem with useless pattern detection (#5873) + all : fixed issue with toString handling in trace arguments (#5858) + all : fixed inline constructor scoping (#5855) + cpp : fixed issue with cpp.Pointer variables being eliminated (#5850) + js : added Notification API to HTML externs (#5852) + js : fixed several options structures in HTML externs (#5849) + php/cs : FileSystem.deleteFile() and FileSystem.deleteDirectory() now throw on non-existent path (#5742) + php/lua : fixed field access on `null` (#4988) + php : fixed static field access on a `Class` stored to a field (#5383) + php : fixed invalid detection of `NativeArray` by `Std.is()` (#5565) + php : fixed `stdin()`, `stdout()`, `stderr()` of `Sys` to use predefined constants for corresponding channels (#5733) + php : fixed Std.parseInt() on hexstrings for PHP7+ (#5521) + php : fixed typed cast in assign operations (#5135) + php : fixed exception thrown by `Reflect.fields(o)` when `o` is `Class` (#5608) + php : fixed json encoding of empty objects (#5015) + php : fixed checking floats for equality (#4260) + php : throw if invalid json string supplied to Json.parse() (#4592) + php : fixed ssl connections (#4581) + php : fixed writing bytes containing zero byte to MySQL & SQLite (#4489) + php : fixed call()() cases for PHP5 (#5569) + +2016-11-29: 3.4.0-RC1 + + New features: + + all : support metadata completion + all : support type-hint completion + all : added @signature display mode (#4758) + all : finalized HashLink (HL) target + + General improvements and optimizations: + + all : greatly improved support for display mode in general + all : made --times output look much nicer + all : remove calls to functions that have no side-effect + all : hid private property accessors from completion (#5678) + js : updated jQuery extern (js.jquery.*) for jQuery 1.12.4 / 3.1.0 support. + js : jQuery extern (js.jquery.*) now includes deprecated fields marked with @:deprecated. + js : no longer rewrite `o["s"]` to `o.s` (#5724) + cpp : greatly improved ObjC output and integration options + lua : greatly improved code output quality + + Bugfixes: + + all : fixed various optimization issues + all : fixed various issues with side-effect detection + all : fixed performance drain in the DCE implementation (#5716) + all : fixed issue with assignments when inlining constructors (#5340) + all : fixed major inlining issue when using compilation server (#5320) + all : fixed pattern matching evaluation order issue (#5274) + cpp : fixed various minor code generation issues + js : fixed issue regarding iterating over abstracts (#5385) + python : fixed evaluation order issue for array writing (#5366) + + Standard Library: + + all : added Any type (#5500) + all : added haxe.extern.AsVar + all : added haxe.macro.CompilationServer (experimental) + all : fixed haxe.Template.resolve (#5301) + +2016-05-27: 3.3.0-RC1 + + New features: + + all : support @:resolve on abstracts (#3753) + all : support extern abstracts and extern @:enum abstracts (#4862) + all : support completion on { if the expected type is a structure (#3907) + all : support (expr is Type) with mandatory parentheses (#2976) + all : allowed passing package dot-paths on command line (#4227) + all : support import.hx modules that define per-directory import/using directives (#1138) + all : support parsing of postfix ! operator (can be used by abstract operator overloading and macros) (#4284) + all : support parsing of ||= and &&= operators (can be used by abstract operator overloading and macros) (#4427) + all : support @:structInit classes (#4526) + all : reworked static analyzer and enabled it by default + flash : update flash externs to version 21 + hl : added HL target (interpreter and C output) + lua: added lua target + js : introduced new jQuery extern (js.jquery.*) for jQuery 1.12.4 / 2.2.4 support. (#4377) + js : introduced new SWFObject extern (js.swfobject.SWFObject) for SWFObject 2.3.20130521 (#4451) + js : added js.Lib.rethrow (#4551) + cs/java : added -D fast_cast as an experimental feature to cleanup casts + + Bugfixes: + + all : properly disallowed assigning methods to structures with read-accessors (#3975) + all : fixed a bug related to abstract + Int/Float and implicit casts (#4122) + all : disallowed duplicate type parameter names (#4293) + all : made UInt's >>> behave like >> (#2736) + all : fixed various type loading issues + all : fixed code generation problems with `inline` (#1827) + php/as3 : support run-time metadata on interfaces (#2042) + php : fixed argument passing to closures (#2587) + neko/cpp : fixed various sys.Filesystem issues with Windows drive paths (#3266) + as3 : fixed problem with covariant return types (#4222) + as3 : fixed rare problem with static initialization order (#3563) + python : fixed various reflection problems + + General improvements and optimizations: + + all : added support for determining minimal types in Map literals (#4196) + all : allowed @:native on abstracts to set the name of the implementation class (#4158) + all : allowed creating closures on abstract inline methods (#4165) + all : type parameter declarations can now have metadata (#3836) + all : optimize Math.ceil/floor on constant arguments (#4223) + all : allowed extern classes to have field names being used for both static and instance (#4376) + all : added haxe.Constraints.Constructible (#4761) + all : rewrote pattern matcher to improve output in many cases (#4940) + python : use spaces instead of tabs to indent the output (#4299) + cpp : reworked backend to improve overall code output quality and fix various issues + swf : added scene-tag to allow creating accessible SWF files + + Standard Library: + + all : added Lambda.flatten and Lambda.flatMap (#3553) + all : added haxe.Constraints.Constructible (#4761) + sys : proper quoting/escaping (can be opt-out) for Sys.command and sys.io.Process (#3603) + js : added position parameter to haxe.macro.Compiler.includeFile + js : removed -D embed-js (#4074) + js : updated HTML externs + + Macro features and changes: + + macro : added overloads field to ClassField (#3460) + macro : added Context.getLocalImports (#3560) + macro : added Context.onAfterTyping (#4714) + macro : added Context.resolveType + 2015-10-11: 3.2.1 Bugfixes: @@ -786,7 +950,7 @@ resolve environment variable in -cmd commands added flash.Vector.indexOf and lastIndexOf fixed bug in interfaces that define the method toString (Haxe/PHP) - fixed bug in haxe.io.BytesInput.readBytes in Flash9 (was throwing Eof if full buffer can't be readed) + fixed bug in haxe.io.BytesInput.readBytes in Flash9 (was throwing Eof if full buffer can't be read) fixed implements/extends special classes when they are imported StringBuf now uses an array for JS implementation (around same on FF, faster on IE) fixed assignment of field length in anonym objects (Haxe/PHP) @@ -1449,7 +1613,7 @@ fixed infinite loop in neko EReg split/replace and epsilon matching added neko native serialization support fixed syntax for multiple constraints in type parameter - added recursive type parameters contraints (T : C constraints) + added recursive type parameters constraints (T : C constraints) updated Xml handling 2006-04-17: beta 5 diff --git a/extra/ImportAll.hx b/extra/ImportAll.hx index b4a19544..b1af8034 100644 --- a/extra/ImportAll.hx +++ b/extra/ImportAll.hx @@ -1,26 +1,23 @@ /* - * Copyright (c) 2005, The Haxe Project Contributors - * 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)2005-2016 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. */ import haxe.macro.Context; @@ -32,8 +29,10 @@ class ImportAll { haxe.macro.Compiler.define("doc_gen"); } switch( pack ) { + case "php7": + if( !Context.defined("php7") ) return; case "php": - if( !Context.defined("php") ) return; + if( !Context.defined("php") || Context.defined("php7") ) return; case "neko": if( !Context.defined("neko") ) return; case "js": @@ -49,7 +48,11 @@ class ImportAll { case "cs": if( !Context.defined("cs") ) return; case "python": - if( !Context.defined("python") ) return; + if ( !Context.defined("python") ) return; + case "hl": + if( !Context.defined("hl") ) return; + case "lua": + if( !Context.defined("lua") ) return; case "tools": return; case "build-tool": @@ -70,7 +73,7 @@ class ImportAll { if( file == ".svn" || file == "_std" ) continue; var full = (pack == "") ? file : pack + "." + file; - if( StringTools.endsWith(file, ".hx") ) { + if( StringTools.endsWith(file, ".hx") && file.substr(0, file.length - 3).indexOf(".") < 0 ) { var cl = full.substr(0, full.length - 3); switch( cl ) { case "ImportAll", "neko.db.MacroManager": continue; @@ -82,6 +85,9 @@ class ImportAll { case "haxe.remoting.SyncSocketConnection": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("cpp")) ) continue; case "sys.db.Sqlite" | "sys.db.Mysql" | "cs.db.AdoNet": continue; } + if( Context.defined("php7") && cl.indexOf("php7.") == 0 ) { + cl = "php." + cl.substr("php7.".length); + } Context.getModule(cl); } else if( sys.FileSystem.isDirectory(p + "/" + file) ) run(full); diff --git a/extra/LICENSE.txt b/extra/LICENSE.txt index 0711f519..b4142af7 100644 --- a/extra/LICENSE.txt +++ b/extra/LICENSE.txt @@ -1,12 +1,12 @@ Haxe Licenses ------------- -For details about Haxe Licenses, please read http://haxe.org/doc/license +For details about Haxe Licenses, please read http://haxe.org/foundation/open-source.html -The MIT Licence : +The Haxe Standard Library MIT License : -------------------------- -Copyright (C)2005-2012 Haxe Foundation +Copyright (C)2005-2016 Haxe Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -309,467 +309,3 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS - - -The Neko LGPL License : ------------------------ - - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS diff --git a/extra/all.hxml b/extra/all.hxml index e9756dcc..73f38e22 100644 --- a/extra/all.hxml +++ b/extra/all.hxml @@ -19,6 +19,12 @@ --next +-D php7 +-php all_php7 +-xml php7.xml + +--next + -php all_php -xml php.xml @@ -44,6 +50,10 @@ -python all_python -xml python.xml +--next +-hl all_hl +-xml hl.xml + --next -xml cross.xml diff --git a/extra/bintray.tpl.json b/extra/bintray.tpl.json new file mode 100644 index 00000000..b8b893c5 --- /dev/null +++ b/extra/bintray.tpl.json @@ -0,0 +1,27 @@ +{ + "package": { + "name": "haxe", + "repo": "snapshot", + "subject": "::packageSubject::" + }, + + "version": { + "name": "::versionName::", + "desc": "::versionDesc::", + "released": "::gitDate::", + "attributes": [ + {"name": "repo", "values" : ["::gitRepo::"], "type": "string"}, + {"name": "branch", "values" : ["::gitBranch::"], "type": "string"}, + {"name": "commit", "values" : ["::gitCommit::"], "type": "string"} + ], + "gpgSign": false + }, + + "files": + [ + {"includePattern": "out/(.*)_src\\.(.*)", "uploadPattern": "::os::/::gitBranch::/haxe_::versionName::_src.$2"}, + {"includePattern": "out/(.*)_bin\\.(.*)", "uploadPattern": "::os::/::gitBranch::/haxe_::versionName::_bin.$2"}, + {"includePattern": "out/(.*)_doc\\.(.*)", "uploadPattern": "::os::/::gitBranch::/haxe_::versionName::_doc.$2"} + ], + "publish": true +} \ No newline at end of file diff --git a/extra/choco/haxe.nuspec b/extra/choco/haxe.nuspec new file mode 100644 index 00000000..f04bbf23 --- /dev/null +++ b/extra/choco/haxe.nuspec @@ -0,0 +1,27 @@ + + + + haxe + @SNAPSHOT_VERSION@ + Haxe + Haxe Foundation + Haxe Foundation + http://haxe.org/foundation/open-source.html + http://haxe.org/ + http://haxe.org/manual/introduction.html + https://groups.google.com/forum/#!forum/haxelang + https://github.com/HaxeFoundation/haxe/issues + https://github.com/HaxeFoundation/haxe + https://github.com/HaxeFoundation/haxe/tree/master/extra/choco + http://haxe.org/img/haxe-logo.svg + false + Haxe is an open source toolkit based on a modern, high level, strictly typed programming language, a cross-compiler, a complete cross-platform standard library and ways to access each platform's native capabilities. + Haxe is an open source toolkit based on a modern, high level, strictly typed programming language, a cross-compiler, a complete cross-platform standard library and ways to access each platform's native capabilities. + +This package will install haxe and haxelib. After installation, you should run `haxelib setup <path>`, where `<path>` is the haxelib repository folder for placing third-party libraries. The folder should be created manually before running the command. + haxe + + + + + \ No newline at end of file diff --git a/extra/deploy_key.enc b/extra/deploy_key.enc new file mode 100644 index 0000000000000000000000000000000000000000..96e6e322560ac93a8e6f52ebb57c447beae96a1e GIT binary patch literal 3264 zcmV;x3_tTzVQh3|WM5y7YmvQ)H8y$w$uTK&FZI59^OX3;37IQz*bSknTJ=|)qDLc% z2wCDKcjyvmJ5*rY!=~Po6%swJ1~9LLu9IG9=}p5bkmppG)E8|(8Fuzdl!tQP$we0^ zEc;!bPxsv?+YyfT?2m1Uch)4RNJkR${OsjtA7lGOy<3{!t26Adnon zq?oNrs5(&khfok}gv7p>d%9GsgAL&s@-^V&*K5iY)Gcw}IuF52{tcZ5k$x>0RhKDe zt2oCDIhtEWw=^iuea$3TRRhl-maUM?VN#tgF^jx&5Q$rOIm91n6|we7;6@V8naQH! z;zk=@9Y+#CIG=j$I+oAkFYTe=62=Up%WZUjD?${6?!Zy7&gs(XZv(4z@bu=p4r0)g z&L5ZVFt0rk_WnSYWN_Mm_)o5c_EnuvYn;Y2;>fg42=+Wxg*gX=r=ud2e^y|jtk?1i zJsDEMm#Y}fBd$bSE~2OAa-hg$GaX{Yq^231cq)ua>s$XyhP04C?^Snt$JxdE-M&r;j z_9=bIKlqRlxaHm+a%vD@he%BCmjzp8)64YqF)Pycc2O$nFRpK&Q83xT8ma$)xHX-CSYQl@ za_?8M+?REP`jU6^RP-l8yd@Ovm#0^=D_);I`TzghCp#ZG-f+r?j{b-6cQ|$5Oj2Y- zItzch>E>o20qIm!`DzsQ)QkHhH~^s_qWGzkJX9^kfYMy>>Xa@f$IJPc%M#J|?OjNz z1=?vAP{HrvwzoRa)IUYeG9EkupTyQ^FQ1;{Ch{~)R-uo6nJ{wJ04Y>w_q#N+40DiE z-#&boOFWw7Np-T|f^0gHByAq|x@%1@9+%-rLGlO`5c9xf1g8Lqs&`}lW_Jx}`P`SB z-EZ_;4fB@RUPucDtTOx7nmQJ4C#~ZI1dZNvZtY$@iY%XaP^7#FEDbi2K7|33i%Zke z2sD0{LpDcU-(g+73cUbSk|1Ph4l_|%J4wCu^$C&}b13dFN@CUe5xplg-8wR)_GmpR zgEZjs92PQ*%#B<<`Ob1Dudkg3>R4Q~G;=!MwmFxb@*>hL;+fCdDWiJDVh|EYHQfkB zEjmKcQR;E~4Xr2Ih}dwdP~ZL(P66ioA{9_usI5nW#t`~7Z{H9fd8x}JpzPKe4upix{5+`nzI-z|pCO;HLdG&KtO!UhsW) zdY4d482U5=r*Bw9WU7HE;ZYk{m{4zBazA5)Sor zcnC-jY!@&yqW~f5@N6uI1Iz6XQ=}X{%>8e72oj`r`PGsxV^mE~f>Y1`5F3$e&EZc5 zv{F*hAo$FCQzZ*D_~?5|71N{&2i6d7P_XS1ucPd?#g^5RY$ruK#mVW3$BJ*mx3>#r zu4ApAmxou1EoB8FpSJY9Oe$Rr0!|L{hv!vy!y33RCfX%U3MvDy!i_=*S>z( z(b`o+fXRAJwaBIvpaAtNCU!cL`g8KqJD&SBz)l)miF1Z;+3^x~l$u488nMsR-F4>2Pz~%e%;Ltps6;9iPSy~n0 zFfk#Wsc@yuJqy#;gqQeqc2_s=k^~!Rp-G0lOQSimwBf*mg|pKaXDFZjlHrouQ|Z7w3&lQgjbb?Zh> zv;=cqsLYFeyqNjW;7G5eWCILLxh+?zoj`w&9fh4HyfxM#uOZGTrSA{mMh6-2GS!d% z9%X$&aV*m3gow%Gv#}x+8yOj-LeP^Kw1x&yq!#MFyClkR!F5bvpr41FCu^ZeemY%Uieoims zh{G_tgJpIia1XkKe9Vi;b+w4NQG5YP+!2!qbU))JgHi*b04 zG)l!eKHL?Dn;_fe`2oDx3YvvQAm?y;$*j)r6}t3QRBlZCQXtty7@{w(T7tPp+goZ+ zR~MpzmDI@KIU+}J;&-FFupU-ujf^Gwnp36jr+sw=BBOWsCEzzS4asp3!sU2Hov4e{ z*iR^09ev4VT`!9jJJ*9mC-3$?-dR#sNl~;2Ny9$7Nc94_?8w9YVK~sg6yeZP$mtn$o)~*LvN~7^nsOvj){m_1uLG zXaIIaZE3FqygRMnb~VOwao4KAU2|pn>6}%fD6FD550L|o!RO@`zI;HZp0s_M!WioN z`2kE@y|%_(*H8$2H50@<*Sp6KA1js5C-Zx!(2!06Z->&6)$Ub{FQxn95*$jHUT=vq zuL-HEWPZ^_uHMybJqGdnbC)#`h>Dw=G&z}D7A&;Ov*}SClcBR5-)dwHNNdR5NsPH1TLPuBr!_WOvK_P(giWy67R?Y#2nX ze{^Vnv?ox(_EUj>b$tRK%#lydy@DLCzhWb6qANO`1G;T;61`FK4oGjIZONw|rjWZS;E6+Kgt?I_$;icK zuXP)JrG0v=2unF|Yyr7-v$;gzvPyaw!S}o#P21CD9LdNp$ki%JHZIt;*glX~m*anS zhR1es4_q4Q literal 0 HcmV?d00001 diff --git a/extra/extract.hxml b/extra/extract.hxml index 4ae6de90..e0b3f077 100644 --- a/extra/extract.hxml +++ b/extra/extract.hxml @@ -1,6 +1,12 @@ +# To rebuild Flash externs (quoting ncannasse): +# - Remove haxe/std/flash/DIR where DIR is all directories except _std +# - Place library.swf (extracted from playerglobal.swc) next to extract.hxml +# - Run haxe extract.hxml +# - Restore removed haxe/std/flash/DIR directories +# - Copy directories from hxclasses/flash to haxe/std/flash, overwriting restored ones -debug -swf-lib library.swf -swf test.swf -swf-version 15 --macro patchTypes("../extra/extract.patch") ---gen-hx-classes \ No newline at end of file +--gen-hx-classes diff --git a/extra/extract.patch b/extra/extract.patch index 93f847f3..a5a52a8f 100644 --- a/extra/extract.patch +++ b/extra/extract.patch @@ -1196,6 +1196,7 @@ flash.system.Worker.state : WorkerState; flash.system.MessageChannel.state : MessageChannelState; enum flash.system.WorkerState; +enum flash.system.MessageChannelState; // --- 11.6 API @@ -1219,6 +1220,8 @@ flash.display3D.Context3D.$mipfilter : Context3DMipFilter; @:require(flash11_7) flash.system.AuthorizedFeatures.enableHLSPlayback; @:require(flash11_7) flash.system.AuthorizedFeaturesLoader.loadAuthorizedFeaturesFromData; +// requires com.adobe.tvsdk.mediacore.MediaPlayer which we don't include +flash.system.AuthorizedFeatures.$enableMediaPlayerHLSPlayback__player : Dynamic; @:require(flash11_8) flash.display.DisplayObjectContainer.stopAllMovieClips @:require(flash11_8) flash.display3D.Context3D.createRectangleTexture diff --git a/extra/haxeci_sec.gpg.enc b/extra/haxeci_sec.gpg.enc new file mode 100644 index 0000000000000000000000000000000000000000..b3475db08b7cdc2b50572c36f6a0174aaf9b4264 GIT binary patch literal 6608 zcmV;>887BjVQh3|WM5xrj<2L1WK|8d#Y30jlnjFsZ*GNGnd=ohl}^7$ zSE)tgpfb*mtD~)L)}8w>+61i`zyiVwB;*MKg!=C8C-^?&n;b-SH7YeGN_Ts^96(cfL9Z&Pa z>?OS~@>*hlqrlCyIE6VJb2n_sS=kT)NVA`^@Tbv}Y7%D22RR)E3cufal;f!ixqZur zI-qSiRtfCY9zGT)NVW5=O;lGr82XV>ZYu6}$9QpAV`HjkOK8+wj)RH&YW8k^wg^ z18_eUzPdl3-RZs}SY%T;UQiIbjV%#Jly)95KFQnk@vjb9_;9*?{mCIXY%O8M=L<-W z4Z;OUb_{V#4Xszx%pY3p5{A~OQ*RVx+wJe9XZy-5ttR-kFW)GNm zPx>S_)AP7YL}H8URT0TSTAA#-m|Wa^n$*2^1}2~$?B?0qid4U{XsfeZA!Dx^`^O-&_pO!66AjuF<*tjYPeGy95DJZ}5aRzI66YGB_?^?w7 zQCd9>OJ5dD_stGe(ov3~yRKPAB^LssU_zyj`4DMq{{KU!w9Vqs6`;hPY! zPje1|XP&HOH~SquiZd*dJ_Eg4U^Z~DRoKPA`I!!D_hQKUxJGXmi$h-)tOQMPVhqBp zCM;L7*4Dm=%JblKr3q#+=*$bvQ{|TP-(pS!Itq(8PpfjqLm=QpCh;voq#;OUAfn83 z1+CvAzBBWFE4;^mI0vLsQ*(U>A1=W28g+15G8{cPus`hDtdJ%XTRJ)-)z^#!BkvP+Thmc!A>bqSS2l6e;+k&y4~Ex`^ywAyRad)%u&9hij%M^s%j~u z@>lj3ry;jU9Nv)Z-|)r6@&(+5k)Bzx>ttw~>{s^!|Efx4d>a=(FmEb%L?r#i=bo7u zIHsD<5&k!8oKRAF*O7ootkm2UduMj&McFJdcR2Z3uD141lEBAVmUWjWc3iud!@G0; z=qxtuI3;@mvezPWSy{13nY>qqQe}l^7CU=U#SgJ#&i@U{!+56AE>uJm9Ea^vTom%D zF+h$g9%V>}cz%3J#p!S_whh{N|C#G>gNH-df>m9!hPg*=>^4^7Hn9NZpY^!02}rP=mt4P51~;`)oMR z4nrsp4ZYFbe6DOjNnDYtmj-#ER2Z~>gJHU+dZ)?FD2cLBDJncNSy|1QBVrNY`x8G= zOOkl$1;@&JpPG)@ydA|u9}6DZqlGeKjZwMb3g| zIdw%)S+#DRK+mKU{1xXnAyNsOH;aUXKUD$iY;0&;(TM8Jo&r;>v?dTPyxY3b`$ZcR zwViRI3(fN z9y1o_0B6xn12qhh_v+UDN&J>Qd8B^Zro>_lk8*#;0?U%SIaBk036M+i$2gJuo4;pD z(H>k52txB*{=M9l3BlcB5~G)=Q?`4uIV^YUl6sSGA#)~2Q2@6A-b38=fk@~)$&#ei zTT7=qqHi)Vj~zGQJC7jR@`-MIHCY8iNMKsOM=0VvqOFp0fM;y3E0P@T6~kw30a-M9 zm&N~r#>1YiTxO&yTi@-c*?jRDw~YYAV{l6g7eMSw1DW>c!0A87wi{u2cT9|Cx56gz z<9IQA8q+X~PE>*D6WhhOGYE5kkl9-+OkgKnWNVOuhDWJv2=J{YgVs6cR7Z<9KK4#1 z_uqu#eo?iif2w(mnZI)NscC^VzUsAWakt+N$P1O2#D9DZ-Re&7TM{YYBT{PSWyids zpoMJZ_1xrse)EuI>57ig13T{oOgHfPgtlT0+S0;0CuX2caNs0X>Moqg<5C%ts)qmK z@a5^q0;C#Ms8PtyS5t$|cgttK{!q%$`G2pNXjtk;x!8?rIzQCVSIRe|o?gihxBX8B0p4sAog)EIOCct_~pxN{p>%^y5P zM6IP>L2yq0j9L5eN<4dFNkwDSckWw}6_Zj6YM1LEC{-F-{4*k&WeV)vn#Y0z%la;{jAhU0ZY4JD|>JSIuREYThHx_`Lb)QOS`Nf2<8p~Omu8UnbA|sI{XS~@|Ku83fhA!xD^Z=l3%(PttR2!^#xL4-!KmHZ( zT4k}kqfdciVA6iw@UbkSNe1u>(dH+?Vzlj_AIxHGIak6VWiLI0$?V8+y@dZ8_ObCY zDkqdcGdEbk6)VNvyAG@Zc)@X@<15+%USqsn0ur>qsJFK%LgfYy?lw}+9Jr630uwZV zZXk5lYV)l$AcWpu6RAwdZwj_a@)+2VCMwgCmpHy8b8z-{2{Tj|G%;&;1%6ARK9M;0 zg02c#7&1*rCq#TJ^&M*-bn=F zY9$j{>hz-xfTD)7fShM_RYGK^Qqc<@%L}gZactUkmEkG7BCmqZ^%sLD00;ObMONO3 zjPVhCGTkI1B5_ZX>rpvbrP|oByt>u41*a2B-R7I=>E3FdAs_u({$(}KE7ld${t946 zFL4PR&2VrvtB1;8GC9A{lJQ?GPnDO?Ums`qyWwWKh|BGuU%#(aq&xjS1(+#0PRLrWmsiZfljCnX4dNZ@}47X(<9aG}@??(RV6Ha$ImaY6Do(s8MLX49H zILsjhsaBq}|NGpU3a0QI1`>uahddSeUiewL`#zdi*flfj%bo7Rwcv6xPYP*zx%xBa z@emq^(X2Le1A`wX*RuK(#j~;JwfMg?#3ODb)6%>0opG0d0(tylwrkBsgKUBY9a_{4 z`O2w^_D8KrzQ70dZR>(&HHBc&FplPr(TOgzfeU zN$*K74jT`Irx8$5>?SvkhBfH6U3xVI>1f6u1W~7GK#l>QQf{Wm`eZna6gi09$tbm3 zp&C^a*O-875WgP(ecf-vF8;wV;bpvr2PdtRNxNzcma`YEj05xHc=!c_4S=WlK(XC4 zkM#71Xl^l&hIg}Xp^E2}(97bPCi;|n1eF9o@G)f%{`*RxOg zAc%I#X*(+iN^t0Sl)Mb;(^Zm9y@r}QbvN$K+WNAeAFrw87Ldc|o+r0FL?5ze1PGTx zo4n6iQ*V?&@BD*vZ6q}`bmtr~(}d&VW&Fdr$7~!sy>A3tvWL3&L)EjmICs!-s5mOD zATxPer7Ms^NS@zVe**iDe<=+1fSU|Iubt9(-Lr9)QGv}dx#|OmYKITW`%-Hp@|34 zrvny~EFdI+!*>@MDS{I74cF2E0qMLuL-N?U-c`$~tq506`lrT375GQkC`C70DblVI zu+sP-GC56u9K|}$1BIAYn$s%9w?8=SBJbFkHaw$nazXdx0x-Br$5i~Vsv~uFW8L_4RpM&2^Ms^Jy#xP)!*~=Q{dBp%z@PwO8!TjpAH%_c> zLa`4dox<2Upb=G$Fhh1H$#5ArNe@oy!;?2{BWcn3v{x`ehxJ1!eWxdJ;KVtLXU-#vE&oT4}y-6pKTyP?g-vTP*dIbz2b)3rArfL|N zr(NetCBQU^g-!a2dUo8QP_IacXjtuGhf+4uW#-;f(qlWjOdL$>QLEdJa*3iXUynzi zP!S{u<_>&tbJ6?*u1n3lYavH@T_KavcN2Ie#6-Ee=0Z%qb}Zo&mf;@!j|(h0(P=4o zs~KRI1ya(H@_j`v*MZTsw74?CAkjyKkJQj`-HVczytbm54NKS+MNK!cCE@4G2xxkEe=o zIA8kDRliuB29g?BQPost{JHt^-!mRS<+HkEQCuprsN@Disv3_@)7CpsS1jtoTnjUT zS>=`_mOMidD>`sa3lD5-Kbp*obQ=J=IIC@|k|M$0X}b4K)j zKVDc$2*-$tI5zIiI{r{*8#6P(}r?`MmmlDQQ`o80VYX>;4}otPHc6wYt7?5_2bgvShkglnd5>}MhC3l~PRD7fmw zPrShH-1N=fgD-F-Ug3VaXJN-!1eR1+S@Z%ToWZIuQtQ(>jkS`e7m!|sGB=5WK40buSIFw{L-ZjJ z&u0A*^-BGhn`9742q>gwYm{#Vg2N!if-1ac`+1RIO&Tdp<$8h7p%6qYFlPfBgBg3u zM#onJ;MGgMN#kFvjeGhmRi0r1*Malya^Vm0s)d zE*Kxf(@t#8@{ITE1;Vf_F11b~L;`|WP2iNydzDwe3k`7*|3ooYc2($>+8*-gxU_h) zzC+L_!Z8z9{Te+}XTcE$$-+j};rGM+Nq2_BTgxgBJG7&%IwRCwF} z1tUeay?aWah;bOK(S19$O1`9z&6ey!EFzhc`M;Dmkx=tKdJh$KCR{2xMLD@**p@MO z#0=TRoU&0e7k5PuD%f4sUjvhi%>%)%60z-sjb)}fo9^EsMP!;v_r(TCsu;U5kXFDZiMi?ovTf zdCLpfCASD?Fl;XU5xZtp-tXv<8nwP7*TtanlLfT3hHKyNh`m#VguP8Ummh6VhDuTP zlf*(^VelZxw>!#5=uZC@s+}~HenL)s@wsq{BpZ3NdIDB;F)BYtOLxr(u)|*sy8X@&rg7->MA<3t}!kH38ysp@Gb-cr_>?*;>K z>=nvZ(_LV^@|7sUU8SDr#IcJf!orRssh4|I{)M?MIwV8Ei-sBo_x|<@+;_=fKb2M}Qn zU_8^ySxo(GkZa(NNEj%Et3V6e5A0qHvz8v z%5j`e3UCvV*F3|mj=z$vEeOH13!(7#SvvXu7l39DZKsLxJ?c%^EAhqMv1~dXMhA|s zp$Z=}Y>t?@s;l{))Vmup>-=8-Xt8x7pK0n4hSfz>_S>%*Np?AD-zqiL&%g#YQ9*v~jaD z3^Xuis3P=Z1Hwm@tC?DEDq8gWB+VV=MI$`Hm%;0Qj^3y}LYw0l%Il=Fu?vf1@HVF= OPCQW*GIvu4UPb*CrrVYP literal 0 HcmV?d00001 diff --git a/extra/haxeci_ssh.enc b/extra/haxeci_ssh.enc new file mode 100644 index 0000000000000000000000000000000000000000..ccf5c25cf7e18018fe1cc71ae5a24fe8435a706c GIT binary patch literal 3264 zcmV;x3_tTzVQh3|WM5yZyiJy5m{W_Njdt=gSjV^byc;fgiMwcm+ts`iD*DkDA%u~a zP!P$jh^Yv~`Gm;s*Alh8x`&P$b8IV-%SwC|%Y}%m49-aATr&QWOOvpc8KU7N)l&Rx zc1x1f(FK4Z(MN~I>&bFkX5qVSJ-f)1JGf{H-t#@y8UHJzr<^yij(&O>*5aIKVh;2q zInB2umqpfbj z0w`i}e=)2b0~i-|D|g%p#7k>cIS{5cQ8t;$GPX!E)D;_mM2z9Dd(?DduVdDu0%e81$d0n86$FZ|_^ zsR0+i+DW^5eQ+D*_EGjgdnQ-US2Nf z>|4Fzt25>=t7buBN254&Y)lU0_TFF;Gk#ne`6zl;1ILFZktQr10n?gt-n*Qi zoZ-8Xl&r~ZRQm3EuG2``>0g-!`s9IC7fPg&1!s$6nV=HL5An#Eltz18gTLxuV~@C(+U(1t47XtRZ6EZWDkLm@9R>VgOuSh1vo?dz9XPy6ohbwVDjB5?AQyYRV4}6w zaqB-6mc)y;p7Z(z7LNuiu$E(*a)Fw*k!DK)h1lM`S%~1b(8sJt^S?1(UAl)FwJ_N& z4wXcr7^BEANOxG=Jwvp7J9<|JpBN@pTmQg9Irf{l37?C*GUPNhvEy(Bi3`g+I#~Hj zduk1bPZmyb;Qf!Kl}evvk2$yS;Rw7$xiV@QmvvBX*`<2$r#<+OA-#XHvOm{+qwB723Ueo{t2+~$y9M|wx;%yQUD>XGjw^-gS@iKFlg+6Zu z(ahoS02=Vy9a(#+jqU=&j|It&n6Cg1J+x)OCk3-pplliRP`b;rs!iL`Mb6pq6H-=4 z3+H_+W$&sLYl4o`1bJRg$~ALU6byopGWXpp%^w=szW$@f7vn$cJ6 z&0%44s2@Ts2s@vMTG0|>Fh{d`6PXY<}b9XuiDN$9uVC_CQhX5RkY4T`&b8TcU^bjm)}~ZYdcSMlj4}N<#~jJ zd4(x^v0T1d*ctvK@iBOaUI_1!6z*yWCJw)JP+~@FL})s0G@Qs`zB$)1X>vI*!!N&C zhs_hkjq);8!p(odL`qzUZK0-6qp^0|%KRuB@{Lv(s?*)v)j5{Ce*17(XKm=pO+o9i& z!o{D=Wod*g?yCWi8K3}b9XU1h^Ot$au!`%^#36jE9J|eZjBp~#cHQJ@xA!yKDQEKZ zuaWf@P0z*cZ)$MhpjZ&TUa8zOp3@n}c3n(U%e)~tK~&$Y=KFiRzeY=yCMs{0unM?k z5+ho%^TSJ*h^Bb76P4*)dq0yYF96^_%&N5H?_x(#)zQ{k3db|Tw0 zD!Ykci6c4r754NgC`0(t&MVU-4WRc^LtoGqxyp4|q#C(ezm`4=mF9J>Mi`ThanfiC zTqAO6a(R5L=`EHnPtS#IV9~7fFy+Aa)?-wg?d-Yytxafk%yui60OF|G!SI?3 z%6HvNHPp3fPeQ>hYQ<~- z*QqF+HHIV0V>_q8s8m#n7s{lvm=NKe^DiPGuE)EkB~Et!2FKn~c@QDm3QweQ`-SV| z1Ah)?8RiV6JM>RF!wIzhT#C-W3OAtFuFa`UH=2bmlTZe@0J~c(!-iVrS7JYbW<4-1 zh`fhOk+J{OWCCeoT#_sxNyer9^n+oQi+OsH8|%x+Dq|C^#qU90NHfxH|Hd^HxyffI z*BDn`%ibQP={O*~a~r^lhA6WPCUR1P({v&@S*;-S_Hv24uAqScUZ=@nf3*zwXj$JO zrM&&@(lm~a3|Z*_oES8KAQ@O#aIUTh214i5aAzC&UK2T2R_11EI|p_O5Z*|^NN6|N z49Sg;9uIDOb*y09vzhq11*6#2EJhWPtF@0UIVvFWGR$b z=SJ4wm^_H6M##!v5@nXcfU@&}qIhi1y1IHlgvO)SK;av{h~uf4Rp$x@{t2K_y>n51*y*U!zQK0xSD!I_(p@ol_blt`D@(GI1! zumPFk-R<1R{W2bfzCU3~nH4G>h=5?jc6J!feA9p)>2`&K;rjW_QC|a$)$i7RgmBIZ3t2Jg=Rnw2i=p|vcja`BhUoNS6=;QQarFG zy&n}~S|0S4$xzlO`J_u$6XvIb(0Yx8vc2DCqRQ&_n__ yS> /var/log/cwpump.log 2>&1' > /etc/cron.d/cwpump + 02-changeperm: + command: chmod 644 /etc/cron.d/cwpump + 03-changeperm: + command: chmod u+x /opt/cloudwatch/aws-scripts-mon/mon-put-instance-data.pl + +option_settings: + "aws:autoscaling:launchconfiguration" : + IamInstanceProfile : "aws-elasticbeanstalk-ec2-role" + "aws:elasticbeanstalk:customoption" : + CloudWatchMetrics : "--mem-util --mem-used --mem-avail --disk-space-util --disk-space-used --disk-space-avail --disk-path=/ --auto-scaling" \ No newline at end of file diff --git a/extra/haxelib_src/.ebextensions/docker_volumes.config b/extra/haxelib_src/.ebextensions/docker_volumes.config new file mode 100644 index 00000000..5640e53b --- /dev/null +++ b/extra/haxelib_src/.ebextensions/docker_volumes.config @@ -0,0 +1,7 @@ +commands: + 01-makefiles: + command: | + mkdir -p /media/docker_files + 02-maketmp: + command: | + mkdir -p /media/docker_tmp diff --git a/extra/haxelib_src/.ebextensions/nginx.config b/extra/haxelib_src/.ebextensions/nginx.config new file mode 100644 index 00000000..45a6a0d9 --- /dev/null +++ b/extra/haxelib_src/.ebextensions/nginx.config @@ -0,0 +1,7 @@ +files: + "/etc/nginx/conf.d/proxy.conf" : + mode: "000755" + owner: root + group: root + content: | + client_max_body_size 800M; \ No newline at end of file diff --git a/extra/haxelib_src/.travis.yml b/extra/haxelib_src/.travis.yml index da1248d0..90f70d6a 100644 --- a/extra/haxelib_src/.travis.yml +++ b/extra/haxelib_src/.travis.yml @@ -1,8 +1,115 @@ -language: haxe +env: + global: + # deploy_key_decrypt + - secure: "cWYcbB7z97sW4yZtz9qcYrEhFZktNjQMOraPm7Vy0FsCMqb4r314Fk8rJze+yDbOKGdsIz6VNHE8nlsQN3EgGiVFJnF8xv6GAlfHPuaVomP2vO7W0A+l7xVy2/326MQJP8JoMgdebDi71yxKeEhYA+mVliI9qql9yfD2YOBmilQ=" -haxe: - - development - - "3.1.3" +matrix: + include: + # haxe development + neko master + - os: linux + sudo: required + dist: trusty + env: + - TRAVIS_HAXE_VERSION=development + - DEPLOY=1 + before_install: + - sudo add-apt-repository ppa:haxe/snapshots -y + - sudo apt-get update + - sudo apt-get install haxe=1:3.3* neko-dev libapache2-mod-neko mysql-server mysql-client -y + - mkdir ~/haxelib && haxelib setup ~/haxelib + - sudo usermod -a -G travis www-data + # haxe 3.2.1 + neko 2.1.0 + - os: linux + language: haxe + haxe: 3.2.1 + sudo: required + dist: trusty + env: + - USE_DOCKER=1 + services: [docker] + before_install: + - sudo apt-get update + - sudo apt-get -o Dpkg::Options::=--force-confnew install docker-engine -y + - docker --version + # https://docs.travis-ci.com/user/docker/#Using-Docker-Compose + - sudo rm -f /usr/local/bin/docker-compose + - curl -L https://github.com/docker/compose/releases/download/1.6.2/docker-compose-`uname -s`-`uname -m` > docker-compose + - chmod +x docker-compose + - sudo mv docker-compose /usr/local/bin + # haxe 3.1.3 + neko 2.0.0 + - os: linux + language: haxe + haxe: 3.1.3 + sudo: required + dist: trusty + env: + - USE_DOCKER=1 + services: [docker] + before_install: + - sudo apt-get update + - sudo apt-get -o Dpkg::Options::=--force-confnew install docker-engine -y + - docker --version + # https://docs.travis-ci.com/user/docker/#Using-Docker-Compose + - sudo rm -f /usr/local/bin/docker-compose + - curl -L https://github.com/docker/compose/releases/download/1.6.2/docker-compose-`uname -s`-`uname -m` > docker-compose + - chmod +x docker-compose + - sudo mv docker-compose /usr/local/bin + # Mac + - os: osx + language: haxe + haxe: development + - os: osx + language: haxe + haxe: 3.2.1 + - os: osx + language: haxe + haxe: 3.1.3 + +install: + - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then + brew update; + fi + - npm -g install bower + - yes | haxelib install all + - yes | haxelib install tora + # We need https://github.com/ufront/ufront-uftasks/commit/1ef09322eb51cf5d16bc1f9abeecaeb30542b62f + - if [ "${TRAVIS_HAXE_VERSION}" = "development" ]; then + yes | haxelib git ufront-uftasks https://github.com/ufront/ufront-uftasks.git; + fi + # We need https://github.com/ufront/ufront-ufadmin/commit/4558fe0bb3534cda53396bc3b4b099a867f5b6a6 + - if [ "${TRAVIS_HAXE_VERSION}" = "development" ]; then + yes | haxelib git ufront-ufadmin https://github.com/ufront/ufront-ufadmin.git; + fi + # Make sure hscript is >= 2.0.5 + - yes | haxelib update hscript + # Make sure hscript is > 0.1.4 + - yes | haxelib update mcli + # copy aws.ndll to the right place + - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then + sudo cp $(haxelib config)/aws-sdk-neko/*/ndll/Mac64/aws.ndll ${NEKOPATH}/aws.ndll; + fi; + - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then + if [ "${TRAVIS_HAXE_VERSION}" = "development" ]; then + sudo cp $(haxelib config)/aws-sdk-neko/*/ndll/Linux64/aws.ndll /usr/lib/x86_64-linux-gnu/neko/aws.ndll; + elif [ "${TRAVIS_HAXE_VERSION}" = "3.2.1" ]; then + sudo cp $(haxelib config)/aws-sdk-neko/*/ndll/Linux64/aws.ndll ${NEKOPATH}/aws.ndll; + fi; + fi; + - haxelib list + - haxelib run tora > /dev/null 2>&1 & script: - - ./test.sh \ No newline at end of file + # run our CI script + - haxe ci.hxml + +deploy: + provider: elasticbeanstalk + access_key_id: $AWS_ACCESS_KEY + secret_access_key: $AWS_SECRET_KEY + region: $AWS_REGION + app: $EB_APP + env: ${TRAVIS_BRANCH}-lib-haxe-org + bucket_name: $EB_BUCKET + on: + all_branches: true + condition: $AWS_ACCESS_KEY && $DEPLOY && ($TRAVIS_BRANCH = master || $TRAVIS_BRANCH = development) diff --git a/extra/haxelib_src/.vscode/settings.json b/extra/haxelib_src/.vscode/settings.json new file mode 100644 index 00000000..fffce17a --- /dev/null +++ b/extra/haxelib_src/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "haxe.displayConfigurations": [ + ["client.hxml"], + ["server_each.hxml", "-neko", "repo.n"] + ] +} \ No newline at end of file diff --git a/extra/haxelib_src/.vscode/tasks.json b/extra/haxelib_src/.vscode/tasks.json new file mode 100644 index 00000000..6a789b94 --- /dev/null +++ b/extra/haxelib_src/.vscode/tasks.json @@ -0,0 +1,18 @@ +{ + "version": "0.1.0", + "command": "haxe", + "args": ["client.hxml"], + "problemMatcher": { + "owner": "haxe", + "pattern": { + "regexp": "^(.+):(\\d+): (?:lines \\d+-(\\d+)|character(?:s (\\d+)-| )(\\d+)) : (?:(Warning) : )?(.*)$", + "file": 1, + "line": 2, + "endLine": 3, + "column": 4, + "endColumn": 5, + "severity": 6, + "message": 7 + } + } +} diff --git a/extra/haxelib_src/CHANGES.md b/extra/haxelib_src/CHANGES.md new file mode 100644 index 00000000..5fc52354 --- /dev/null +++ b/extra/haxelib_src/CHANGES.md @@ -0,0 +1,15 @@ +## next version (2016-??-??) + + - New haxelib self-updating mechanism (#172, #293) + - Haxelib new version notification (#282) + - Partial download resume support (#133) + - Respect `-notimeout` for uploading and downloading files (#235) + - `haxelib run` now sets `HAXELIB_RUN_NAME` environment variable to the library name (#293) + - Fixed order of library versions in `haxelib list` (#83) + - Merged `upgrade` and `update` commands (#188) + - Deprecated now redundant commands: `local`, `selfupdate` (#288) + - Fixed suggested repository path on Linux (#242) + - Suggested repository path on OSX is now `/usr/local/lib/haxe/lib` (#250) + - `haxelib install .hxml` now checks hxml files recursively (#200) + - Git/Hg checkouts don't set dev mode unless subdir is specified now (#263) + - Tons of smaller fixes, cleanups and optimizations diff --git a/extra/haxelib_src/Dockerfile b/extra/haxelib_src/Dockerfile new file mode 100644 index 00000000..1d55f33a --- /dev/null +++ b/extra/haxelib_src/Dockerfile @@ -0,0 +1,74 @@ +# Build haxelib server as a Docker container. +# Note that it doesn't contain a MySQL database, +# which need to be launched seperately. See test/docker-compose.yml on how to launch one. + +FROM ubuntu:trusty + +# apt-get dependencies of bower +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y python-software-properties software-properties-common \ + && add-apt-repository ppa:haxe/snapshots -y \ + && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ + apache2 \ + neko-dev \ + haxe \ + npm \ + nodejs-legacy \ + git \ + libcurl4-gnutls-dev \ + && rm -r /var/lib/apt/lists/* + + +# apache httpd +RUN rm -rf /var/www/html \ + && mkdir -p /var/lock/apache2 /var/run/apache2 /var/log/apache2 /var/www/html \ + && chown -R www-data:www-data /var/lock/apache2 /var/run/apache2 /var/log/apache2 /var/www/html +RUN a2enmod rewrite +RUN a2enmod proxy +RUN a2enmod proxy_http +RUN mv /etc/apache2/apache2.conf /etc/apache2/apache2.conf.dist && rm /etc/apache2/conf-enabled/* /etc/apache2/sites-enabled/* +COPY apache2.conf /etc/apache2/apache2.conf +RUN { \ + echo 'LoadModule neko_module /usr/lib/x86_64-linux-gnu/neko/mod_neko2.ndll'; \ + echo 'LoadModule tora_module /usr/lib/x86_64-linux-gnu/neko/mod_tora2.ndll'; \ + echo 'AddHandler tora-handler .n'; \ + } > /etc/apache2/mods-enabled/tora.conf \ + && apachectl stop + +RUN npm -g install bower + + +# haxelib +ENV HAXELIB_PATH /haxelib +RUN mkdir "$HAXELIB_PATH" && haxelib setup "$HAXELIB_PATH" \ + && haxelib install tora 1.8.1 + +COPY server*.hxml /src/ +WORKDIR /src +RUN haxelib install all --always +RUN cp ${HAXELIB_PATH}/aws-sdk-neko/*/ndll/Linux64/aws.ndll /usr/lib/x86_64-linux-gnu/neko/aws.ndll; + +COPY www/bower.json /src/www/ +WORKDIR /src/www +RUN bower install --allow-root + +COPY www /src/www/ +COPY src/legacyhaxelib/.htaccess /src/www/legacy/ +COPY src/legacyhaxelib/haxelib.css /src/www/legacy/ +COPY src/legacyhaxelib/website.mtt /src/www/legacy/ +COPY src /src/src/ + +RUN rm -rf /var/www/html +RUN ln -s /src/www /var/www/html +RUN mkdir -p /var/www/html/files +RUN mkdir -p /var/www/html/tmp + +WORKDIR /src + +RUN haxe server_legacy.hxml +RUN haxe server_website.hxml +RUN haxe server_tasks.hxml +RUN haxe server_api.hxml + +EXPOSE 80 +VOLUME ["/var/www/html/files", "/var/www/html/tmp"] +CMD apachectl restart && haxelib run tora \ No newline at end of file diff --git a/extra/haxelib_src/Dockerrun.aws.json b/extra/haxelib_src/Dockerrun.aws.json new file mode 100644 index 00000000..874a7717 --- /dev/null +++ b/extra/haxelib_src/Dockerrun.aws.json @@ -0,0 +1,13 @@ +{ + "AWSEBDockerrunVersion": "1", + "Volumes": [ + { + "HostDirectory": "/media/docker_files", + "ContainerDirectory": "/var/www/html/files" + }, + { + "HostDirectory": "/media/docker_tmp", + "ContainerDirectory": "/var/www/html/tmp" + } + ] +} diff --git a/extra/haxelib_src/Package.hx b/extra/haxelib_src/Package.hx deleted file mode 100644 index e2839157..00000000 --- a/extra/haxelib_src/Package.hx +++ /dev/null @@ -1,63 +0,0 @@ -import Sys.*; -import sys.*; -import sys.io.*; -import haxe.io.*; - -class Package { - static function cp(srcFile:String, destFile:String):Void { - File.saveBytes(destFile, File.getBytes(srcFile)); - } - - static function zip(srcFolder:String, destFile:String):Void { - switch (Sys.systemName()) { - case "Linux", "Mac": - command("zip", ["-r", destFile, srcFolder]); - case "Windows": - command("7za", ["a", "-tzip", "-r", destFile, srcFolder]); - } - } - - /** - Make directory recursively. - It is needed for Haxe 3.1.3, which FileSystem.createDirectory is not recursive. - */ - static function mkdir(path:String):Void { - #if (haxe_ver < 3.2) - path = Path.normalize(path); - - if (FileSystem.exists(path)) { - return; - } - - var parent = path.substring(0, path.lastIndexOf("/")); - if (parent != "") - mkdir(parent); - #end - - FileSystem.createDirectory(path); - } - - static function main():Void { - mkdir("package/src/tools/haxelib"); - - for (file in [ - "Data.hx", - "Main.hx", - "Rebuild.hx", - "SemVer.hx", - "SiteApi.hx", - "ConvertXml.hx", - ]) { - cp('src/tools/haxelib/$file', 'package/src/tools/haxelib/$file'); - } - cp("haxelib.json", "package/haxelib.json"); - - setCwd("package"); - - var zipFile = "package.zip"; - if (FileSystem.exists(zipFile)) { - FileSystem.deleteFile(zipFile); - } - zip(".", zipFile); - } -} \ No newline at end of file diff --git a/extra/haxelib_src/README.md b/extra/haxelib_src/README.md index 2446612e..36acf8d8 100644 --- a/extra/haxelib_src/README.md +++ b/extra/haxelib_src/README.md @@ -1,50 +1,86 @@ -# Haxelib +[![TravisCI Build Status](https://travis-ci.org/HaxeFoundation/haxelib.svg?branch=development)](https://travis-ci.org/HaxeFoundation/haxelib) +[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/HaxeFoundation/haxelib?branch=development&svg=true)](https://ci.appveyor.com/project/HaxeFoundation/haxelib) -For more documentation, please refer to [haxe.org](http://haxe.org/haxelib) +# Haxelib: library manager for Haxe -[![TravisCI Build Status](https://travis-ci.org/HaxeFoundation/haxelib.svg?branch=master)](https://travis-ci.org/HaxeFoundation/haxelib) -[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/HaxeFoundation/haxelib?branch=master&svg=true)](https://ci.appveyor.com/project/HaxeFoundation/haxelib) +Haxelib is a library management tool shipped with the [Haxe Toolkit](http://haxe.org/). -## Per-project setup +It allows searching, installing, upgrading and removing libraries from the [haxelib repository](http://lib.haxe.org/) as well as submitting libraries to it. -Currently haxelib has two ways to have project local setups. +For more documentation, please refer to http://lib.haxe.org/documentation/ -1. Using `haxelib newrepo` -2. Using `haxelib install all` +## Development info -### Using haxelib newrepo +### Running the haxelib server for development -When using `haxelib newrepo` you can have a project-local haxelib repository. This feature is quite new and a little rough around the edges. +The server has to be compiled with Haxe 3.2.1+. It can be run in Apache using mod_neko / mod_tora. -Caveats: +Currently using [Docker](https://www.docker.com/) is the simpliest way to build and run the server. It doesn't require setting up Apache or MySQL since everything is included in the container. We would recommand to use the [Docker Platform](https://www.docker.com/products/docker) instead of the Docker Toolbox. -- if you mistakenly run a haxelib command in a subdirectory of your project, it will be executed on the global repo (to be fixed) -- there may be some issues with `haxelib run` and `haxelib selfupdate` (to be fixed) -- libraries get downloaded for each project -- it requires a recent Haxe version (after 3.1.3) to work properly with ndlls. +To start, run: -### Using haxelib install all +``` +docker-compose -f test/docker-compose.yml up -d +``` -Haxe allows you to define specific versions of the libraries you want to use with `-lib :`. If you make sure to use this in all your hxmls, then `haxelib install all --always` (the `--always` avoiding you being prompted for confirmation) will be able to ensure the libraries your project needs are available in the necessary versions. If in fact you run this in a checkout hook, your get to track your dependencies in your git repo (some other VCSs should allow for a similar setup), allowing you to have a well defined and replicable setup for any state (commit/branch/etc.). +The command above will copy the server source code and website resources into a container, compile it, and then start Apache to serve it. To view the website, visit `http://localhost:2000/` (or `http://$(docker-machine ip):2000/` if the Docker Toolbox is used). -Disadvantages: +Since the containers will expose port 2000 (web) and 3306 (MySQL), make sure there is no other local application listening to those ports. In case there is another MySQL instance listening to 3306, we will get an error similar to `Uncaught exception - mysql.c(509) : Failed to connect to mysql server`. -- the approach requires you to define all dependencies with specific versions and then running `haxelib install all` to grab them -- with this approach, any other project that does not have specific versions defined may be affected, as under some circumstances `haxelib install all` may set the global "current" version of the libraries (to be fixed) +To stop the server, run: +``` +docker-compose -f test/docker-compose.yml down +``` -Advantages: +If we modify any of the server source code or website resources, we need to rebuild the image and replace the running container by issuing the commands as follows: +``` +docker-compose -f test/docker-compose.yml build +docker-compose -f test/docker-compose.yml up -d +``` -- as pointed out above, this approach allows defining a *versionable* and *replicable* state. -- you don't have to download libraries for each project, which does make a difference for heavy weights like openfl and hxcpp +To iterate quickly during development, we can use `-f test/docker-compose-dev.yml` in place of `-f test/docker-compose.yml` when starting the container. `-f test/docker-compose-dev.yml` mounts the repo's `/www` folder to the container, such that there is no need to rebuild and replace the running containers. Instead, after modifying the server source code or html templates, run `haxe server.hxml` and the container should pick up the changes immediately. The downside of this is that we have to make sure we've installed the right haxelib dependencies. Also, Docker only allow mounting folders in certain locations (e.g. `/Users` on Mac), so it may not work if we cloned the repo to `/my_projects/haxelib`. -#### Sidestepping haxelib git issues +To run haxelib client with this local server, prepend the arguments, `-R $SERVER_URL`, to each of the haxelib commands, e.g.: +``` +neko bin/haxelib.n -R http://localhost:2000/ search foo +``` -Because you cannot specify git versions with `-lib` paremeters, we suggest using git submodules instead, as again they provide an adequate way of definining a *versionable* and *replicable* state. +To run integration tests with the local development server: +``` +# prepare the test files +haxe prepare_tests.hxml -### Combining both approaches +# run the tests +haxe integration_tests.hxml +``` +Note that the integration tests will reset the server database before and after each test. -You can of course combine both approaches, giving you the isolation provided by the first one, and the replicability provided by the second one. +### About this repo -### Future solutions +Build files: -A solution that combines the strengths of both approaches is in the making. Stay tuned. +* client.hxml: Build the current haxelib client. +* client_tests.hxml: Build and run the client tests. +* client_legacy.hxml: Build the haxelib client that works with Haxe 2.x. +* server.hxml: Build the new website, and the Haxe remoting API. +* server_tests.hxml: Build and run the new website tests. +* server_each.hxml: Libraries and configs used by server.hxml and server_tests.hxml. +* server_legacy.hxml: Build the legacy website. +* integration_tests.hxml: Build and run tests that test haxelib client and server together. +* package.hxml: Package the client as package.zip for submitting to the lib.haxe.org as [haxelib](http://lib.haxe.org/p/haxelib/). +* prepare_tests.hxml: Package the test libs. +* ci.hxml: Used by our CIs, TravisCI and AppVeyor. + +Folders: + +* /src/: Source code for the haxelib tool and the website, including legacy versions. +* /bin/: The compile target for building the haxelib client, legacy client, and others. +* /www/: The compile target (and supporting files) for the haxelib website (including legacy server) +* /test/: Source code and files for testings. + +Other files: + +* schema.json: JSON schema of haxelib.json. +* deploy.json: Deploy configuration used by `haxelib run ufront deploy` for pushing the haxelib website to lib.haxe.org. +* deploy_key.enc: Encrypted ssh private key for logging in to lib.haxe.org. Used by TravisCI. +* Dockerfile: Docker build file for building an image that runs the haxelib server. diff --git a/extra/haxelib_src/apache2.conf b/extra/haxelib_src/apache2.conf new file mode 100644 index 00000000..9d3c0e28 --- /dev/null +++ b/extra/haxelib_src/apache2.conf @@ -0,0 +1,64 @@ +# see http://sources.debian.net/src/apache2/2.4.10-1/debian/config-dir/apache2.conf + +Mutex file:/var/lock/apache2 default +PidFile /var/run/apache2/apache2.pid +Timeout 300 +KeepAlive On +MaxKeepAliveRequests 100 +KeepAliveTimeout 5 +User www-data +Group www-data +HostnameLookups Off +ErrorLog /proc/self/fd/2 +LogLevel warn + +IncludeOptional mods-enabled/*.load +IncludeOptional mods-enabled/*.conf + +# ports.conf +Listen 80 + + Listen 443 + + + Listen 443 + + + + Options FollowSymLinks + AllowOverride None + Require all denied + + + + AllowOverride All + Require all granted + + +DocumentRoot /var/www/html + +AccessFileName .htaccess + + Require all denied + + +LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined +LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %O" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +CustomLog /proc/self/fd/1 combined + + + SetHandler application/x-httpd-php + + +# Multiple DirectoryIndex directives within the same context will add +# to the list of resources to look for rather than replace +# https://httpd.apache.org/docs/current/mod/mod_dir.html#directoryindex +DirectoryIndex disabled +DirectoryIndex index.html + +IncludeOptional conf-enabled/*.conf +IncludeOptional sites-enabled/*.conf diff --git a/extra/haxelib_src/appveyor.yml b/extra/haxelib_src/appveyor.yml index b3c94e8f..4485444c 100644 --- a/extra/haxelib_src/appveyor.yml +++ b/extra/haxelib_src/appveyor.yml @@ -1,11 +1,19 @@ version: "{build}" +services: + - mysql + install: - - cinst 7zip.commandline -y - - cinst haxe -y + - npm -g install bower + - cinst haxe -y + - cinst nssm -y + - RefreshEnv + - haxelib setup haxelib_repo + - haxelib install all --always + - haxelib install tora + - haxelib list -build_script: - - haxe test.hxml +build: off test_script: - - neko bin/test.n + - haxe ci.hxml diff --git a/extra/haxelib_src/ci.hxml b/extra/haxelib_src/ci.hxml new file mode 100644 index 00000000..42c091d4 --- /dev/null +++ b/extra/haxelib_src/ci.hxml @@ -0,0 +1,2 @@ +-cp test +-x RunCi diff --git a/extra/haxelib_src/client.hxml b/extra/haxelib_src/client.hxml new file mode 100644 index 00000000..97b705ed --- /dev/null +++ b/extra/haxelib_src/client.hxml @@ -0,0 +1,3 @@ +-cp src +-neko run.n +-main haxelib.client.Main diff --git a/extra/haxelib_src/legacyhaxelib.hxml b/extra/haxelib_src/client_legacy.hxml similarity index 54% rename from extra/haxelib_src/legacyhaxelib.hxml rename to extra/haxelib_src/client_legacy.hxml index e4699a65..bfd5fd59 100644 --- a/extra/haxelib_src/legacyhaxelib.hxml +++ b/extra/haxelib_src/client_legacy.hxml @@ -1,3 +1,3 @@ -cp src -neko bin/legacyhaxelib.n --main tools.legacyhaxelib.Main \ No newline at end of file +-main legacyhaxelib.Main \ No newline at end of file diff --git a/extra/haxelib_src/test.hxml b/extra/haxelib_src/client_tests.hxml similarity index 67% rename from extra/haxelib_src/test.hxml rename to extra/haxelib_src/client_tests.hxml index 902314be..5f5d85c4 100644 --- a/extra/haxelib_src/test.hxml +++ b/extra/haxelib_src/client_tests.hxml @@ -1,10 +1,6 @@ --debug ---each - -haxelib.hxml ---next - -cp src -cp test --neko bin/test.n -main HaxelibTests +-debug +-neko bin/test.n +-cmd neko bin/test.n \ No newline at end of file diff --git a/extra/haxelib_src/deploy.json b/extra/haxelib_src/deploy.json new file mode 100644 index 00000000..d064590b --- /dev/null +++ b/extra/haxelib_src/deploy.json @@ -0,0 +1,42 @@ +{ + "files": [ + "api/", + "bower_components/", + "css/", + "documentation-files/", + "img/", + "view/", + "dbconfig.json", + "favicon.ico", + "index.n", + "tasks.n", + ".htaccess" + ], + "targets": [ + { + "name": "lib.haxe.org", + "gitRepo": "ssh://haxelib@lib.haxe.org/data/haxelib/haxelibwebsite.git", + "defines": ["deploy"], + "hxmls": ["server"], + "debug": false, + "servers": [{ + "name": "lib.haxe.org", + "user": "haxelib", + "host": "lib.haxe.org", + "port": 22, + "remoteDir": "/data/haxelib/www/" + }] + } + ], + "hooks": { + "beforeBuild": [], + "afterBuild": [], + "beforeCopy": [], + "afterCopy": [], + "beforePush": [], + "afterPush": [], + "beforePull": [], + "afterPull": ["touch index.n"], + "afterComplete": [] + } +} diff --git a/extra/haxelib_src/deploy_key.enc b/extra/haxelib_src/deploy_key.enc new file mode 100644 index 0000000000000000000000000000000000000000..bac650f1864fa0914904a07d46e1c2e6d0fefb23 GIT binary patch literal 3264 zcmV;x3_tTzVQh3|WM5x+C+zdl%VSh;_y?Y=^_>tKX;Rq~5HUProL!k&12x%&=*iUz zuTUflWu0Cj^p5oeD}u1Cd+H;Tmsc*Uj(=pRhtxc)4v^FOD_>Y*1@AAQi+=w)N$Ykt zvqCP){NEG4F62@|Dlc5SlWvu64X|HokIJ1#+|L>^E$c!{a|`A+TX_Gf9X&@v>y9KS zIP5>P;eA!;rD6^dA$tCvCrqgdQ&E4R4c^|JlyCK{r+ypzM}rCW!LYCqnTNha=Uus6 zTrz192-Q8r(IvX-9-#NV0?m>6ZYh^G7MIrW|1x^%hDa6o*vW*ly)OflV8w=C&$8Vq6PTA za%nY^;~jQrO2?n!!QSEHV`O|5V5=Y60Ca5?)5$9;3PJfg7ZiRs_?XmMd2aUq(~L?W zfQ%U>G81E)JFIUKrC&5`t1aQQFK=&qz<0-iq~ZQ;;w;I}7=5RoHlsPZxNhCb2%f0J(izz;Uo3Jq+L-Uu!YZ66TnPg7J%Yps;nMa@Q5!wI;#xJ|YDFtqGLcC1> z4*6d})opc*>}G3Yx3QH|^Shbj0bR}=;!>@YDVW^a5ur;~t$TCYwuoESPwJF)nayXg(6l$}OR=mes^Qd`*MozUe z9;;qL9C+35w}~%R`A@Z7O?n^Zn;)$im73ztaXkMS-_#;+Z0;M<9q*5-<4V;~cZkpp z7iP=WGQTW$Q5;a)zvdkCF{K6e!;e`N&OEJ43{9IwZdn@W9BN%6SEn(id@}nh^&B@h zyxlA#URfDHGwwr@%C-Q<*ppmGL4UHRQS0g*_yn6PkSh~9#fs3MfdMH+YP6C$m<$cb zfXI3fX>2}lY(Mv{hZ%5%3N#7K&`!u4W?QC%JH$23@3e1Lq|OX0zBTfd3tl#dX8&?LkACklrRN22@?{}rUhuPLGEm<$_|(AW#E{l# zb7U_^pwwc&ulIR@bTeyR_`jAy`f!%l>mfTtCz#gffubpPgQllwG^x-c*Ua)H#KD-q zXXQyFtQx)(I>CZ>ufG8O<};RL3JMs69wJP^^+OEeX9u~a;aU~!nkkx8k>sz$2zI1N zY_UmxeZ1}gtI2`tn$}3})S-071DLQygQtzOD&^`B1wazxz)Ce-`*HAQpIhX3doTVt|w8X1mqupwN~ z<8w@xV+#KDR6iTwZMEvzBhnA|3_gKY#j6{%5H@^NpYQ=FUS3q?%ov-NH)O0#>B+ukA~-zq_0U1qSDnY?sv-Hv}K!c$CK6y-}4UD&@0 z)=t^WSUGp#k(~Y4%HI{zFw`L?>Q=Hh3J#rQNfuR|FQdQ+3i@Nf+Mo@%AkZYsU|MsM zaS5e-!nn0e@wPdJe!oY*s^)W9e7Sp?>VC?;xu=G@u1 z`U7HDO+K>>;$(?2(iq^p?wU2hcsim}rix5VVjEp*@K?p#5Z%2Zt?NK7Ya$pP& zihUb2hMHHX3BhLSP;dLFZ#NuGBqh=M>4nG(bhG1~E`)C+EkIJR^w4seKFAZ!R1)Sc zc>(J969#A9YIFx#ZMQ3}X!$fqWXBd_Nw`Bz-rz$_{1E@}^_t|7I7IJ+^E`&)Kb$?+ z!Dst8GnUd_waNHkP7(+Vu<_o6inF9zO~WiGuKe{H8NEb`^u%vm%S|0Bleapasqt9E z(z1F)2TRSLRL5E0^3KaM>}_7R_;Rcg5T2zj8$HT<146NXjjF6kVe@PV@){<#?fh*cncXP(B%=YgFqYtDs}SJvCkA8kg0TL)j+%){15TL7|1rQRtG`2 z#J<+o1(#p0u*_2>%`zdDwS6<+W#xtXpG@%ZSwb|oJhJT<74pu?5Qu#PeLKQ@uV{{~ z&!kigHds#RB!Wmk5X!-Ks@^28XUb_<{$F(#pP{lCj0-ic_H)n4dvL4V0a`!ORzfv! zHeQ>D4|1rY*Nl@9e68PDsf_jHT%F-#hTO_%j&J35je?V7P{RF00QIuw38&j8)5i#% zScwUm)zS7-Qxzt^gw!7hRPV_wdvijOZ18L3sSDL?>S&w>p=s9>2nCw-xevtS_6{{; zkvgEIKegB2ZTGBaN*oc6KX*x6bXcQ6I8i#lzlmmMgeP1^FLlqTT=$r*7A=uEG$t=r zLje%~*WcFD`swsQ?%%Gtx71Kz1)4d$?#xAz5xm2_EJjAWK4f|wdYpWe6I>3xTc*=* zRe;u9C!j@$c+_q{th_SoQWPry`8V?&(_MD1U@i6n9*>^-Uu5VV ztg+7{*_fcv;L~y`Sp$ERu2`~Y7L{ZK5Q1aguBcDm@xQd1ZT$%o>AXe4Eg(NGC)qGbc>68X2Z@F5I%$oWSyLtq3G#ir?1wv;=rsA&pn{+vf; z&W-u ziB9!3_RchNCQV`jaVpq{2nu$s+V2L@y5YjSRpu$mA)}-;0Qo zJD+$o0id6m7*lJSARPcCC{%~=Camyo__>nF%H!b<%cm&pneYSkp84~SuF-#`F5$et z(Egz&EW6!+5_pfDeY_SaU5>Nb{yp?a_s}*V>tVq=*!#kihOJ!Jc2XeCBgROte|2iC zGNWZVE3};WlXrR8aIbkF67sY*yK5gQY5i2lu|RO*Xw3<$ck0ArFU4+auZJ*U%7LQY zWTCM!X-D-fC~@LYPbM+MhL6C-WZrwrD)c!?_6I1 literal 0 HcmV?d00001 diff --git a/extra/haxelib_src/haxelib.hxml b/extra/haxelib_src/haxelib.hxml deleted file mode 100644 index 07f5bf28..00000000 --- a/extra/haxelib_src/haxelib.hxml +++ /dev/null @@ -1,3 +0,0 @@ --cp src --neko bin/haxelib.n --main tools.haxelib.Main diff --git a/extra/haxelib_src/haxelib.hxproj b/extra/haxelib_src/haxelib.hxproj deleted file mode 100644 index 4e1f3beb..00000000 --- a/extra/haxelib_src/haxelib.hxproj +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - nekotools boot bin/haxelib.n - - - - - - \ No newline at end of file diff --git a/extra/haxelib_src/haxelib.json b/extra/haxelib_src/haxelib.json index db877601..e23f974b 100644 --- a/extra/haxelib_src/haxelib.json +++ b/extra/haxelib_src/haxelib.json @@ -1,11 +1,11 @@ { - "name": "haxelib_client", + "name": "haxelib", "url" : "http://haxe.org/haxelib", "license": "GPL", "tags": ["haxelib", "core"], "description": "The haxelib client", "classPath": "src", - "version": "3.2.0-rc.3", - "releasenote": "Correct behavior for locating base path", - "contributors": ["back2dos", "ncannasse", "jason", "Simn"] + "version": "3.3.0", + "releasenote": "Initial release for Haxe 3.3", + "contributors": ["back2dos", "ncannasse", "jason", "Simn", "nadako"] } diff --git a/extra/haxelib_src/haxelib.sh b/extra/haxelib_src/haxelib.sh deleted file mode 100755 index b4d08f41..00000000 --- a/extra/haxelib_src/haxelib.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -haxe haxelib.hxml -exec neko bin/haxelib "$@" diff --git a/extra/haxelib_src/haxelib_script.sh b/extra/haxelib_src/haxelib_script.sh deleted file mode 100755 index 16c52a56..00000000 --- a/extra/haxelib_src/haxelib_script.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -OLDCWD=`pwd` -cd src -exec haxe --run tools.haxelib.Main -cwd $OLDCWD $@ diff --git a/extra/haxelib_src/integration_tests.hxml b/extra/haxelib_src/integration_tests.hxml new file mode 100644 index 00000000..bddcaec6 --- /dev/null +++ b/extra/haxelib_src/integration_tests.hxml @@ -0,0 +1,5 @@ +-cp src +-cp test +-main IntegrationTests +-neko bin/integration_tests.n +-cmd neko bin/integration_tests.n \ No newline at end of file diff --git a/extra/haxelib_src/legacyhaxelib.sh b/extra/haxelib_src/legacyhaxelib.sh deleted file mode 100755 index c367c015..00000000 --- a/extra/haxelib_src/legacyhaxelib.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -haxe legacyhaxelib.hxml -exec neko bin/legacyhaxelib "$@" diff --git a/extra/haxelib_src/package.hxml b/extra/haxelib_src/package.hxml new file mode 100755 index 00000000..c5e4ebba --- /dev/null +++ b/extra/haxelib_src/package.hxml @@ -0,0 +1,2 @@ +-cp src +--run Package \ No newline at end of file diff --git a/extra/haxelib_src/package.sh b/extra/haxelib_src/package.sh deleted file mode 100755 index 49e2a240..00000000 --- a/extra/haxelib_src/package.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -haxe --run Package \ No newline at end of file diff --git a/extra/haxelib_src/prepare.hxml b/extra/haxelib_src/prepare.hxml deleted file mode 100644 index 3fcec8d3..00000000 --- a/extra/haxelib_src/prepare.hxml +++ /dev/null @@ -1,5 +0,0 @@ --cp testing --cp src --main PrepareServer --x bin/prepare --lib hx2compat \ No newline at end of file diff --git a/extra/haxelib_src/prepare_tests.hxml b/extra/haxelib_src/prepare_tests.hxml new file mode 100644 index 00000000..8b55e5b6 --- /dev/null +++ b/extra/haxelib_src/prepare_tests.hxml @@ -0,0 +1,2 @@ +-cp test +--run Prepare \ No newline at end of file diff --git a/extra/haxelib_src/run.bat b/extra/haxelib_src/run.bat deleted file mode 100644 index 335fe77b..00000000 --- a/extra/haxelib_src/run.bat +++ /dev/null @@ -1,3 +0,0 @@ -cd bin -haxelib -pause \ No newline at end of file diff --git a/extra/haxelib_src/run.n b/extra/haxelib_src/run.n new file mode 100644 index 0000000000000000000000000000000000000000..73edb5a9222484406115e5172b51342501e71126 GIT binary patch literal 203260 zcmb@v4}8?eb?E!kPp}AK)_Aekcx|uOYgq_cS_zpbSjK}eLIxQYWf2>)#w&KEU8F@? zDXWzL#ZgJ)Q0h2@l7v#?P(oZvxe1rJ4wuXGb!qDok|uuCb^VBMZZ03!b*XRak~B?e zuAAQPnfd)z!U4zcecs|d^Z(4unKS2{IWsFqS3J7*n8&i-Ew`+2@HO>CT)XWcA_Utlix_xgM9d)nnA1PX8 zBiosIUus*%z=8g>WiKvc(CZ8l?1xF%Ys;+i@-nN{J}eQhwLF!dUkvpO<;OCGVyMg| z*s?+)wcWB`lJ>1m;vei1vWG{r7FZtR`?!4vOJM&|IkOp=Mh_L!iA_u=@6QATJmh^+ zz*ku=`>!N6Zw6IHXMk>~1)5!+LBTHt1S$XzR#5sC0Y9mr@`E$U>z+yM`I+Q3RFX_p zlKe9P->W3=?(7tOH*^31{Dqy34j|=!s0bdaCtblI`I5*2GD=)W3 zioH;!KVQ7RNf;vAI zy_UUuHd9|Qhw2}l!#H*T$~{&gvpKVExZLMNy7QT>-9y90{-OK`6EmgV^w-mu>1CKx zGeEsr*785k0kL(H@bK!?V7fPDl{uk(ujFcev)2%{KP%w*n}kbD?n}h&p9xsw169&T z>`M|mB;d~kye8mBQg8`S*19HD?6b-=v~QS8*&TC1xGi>YG8`bu;{br?o0ShA`+2 zl>|UzOK_V=Wh%63P!1L)oFxd~XOEx=lPv3v$hk$L{^Qpo99;<9so={9sL6BK3m)Lsd}s0vm)q9H zFp-V+YcwM@e}1{&dMuf$A756VXsmyryY=4t9%`wJG}J#%wfQXi{4oFQ=kKP2MPb0F z!u0ZoVOmeKsy7!Oq?(fGfQ~MqMRjU$ShB0($?AI=?|97EaW_NMPPV!w2&Db8q0L|_KVPwvO*@+tCO>JGTT3p=`L;` z7Ccg%*@m_dQ6PyPDkHXNY@fb|@i$bl&gGUMn`TK%yN?{Z{9dxXI-@%~Ixx^Z%$9|a z8h3AIAcNexgF5ym0R;h10?O8*lI+@Q%_0&_SF@CZ0HmOFU+f=rhhIAEBbJ}L_1 zP|=AAhF?g{JLZGBVLsI>&5Y0i{dsqKBrpT)B~m`a`e;8wXzK{wG}s;US*}D4j2TZ2 zjApu^vG8bX~xjy=X`CrJ>ke)Ufvp_@RJXA~d}>LablF zHw64dz?}_%rC5XZIsj5`aI~1&#)ccnq((B(&!o+!Dix=CK0exC$k>~u;U@%q6+A5c zz);VY?yV`!>N;*3+9##XcLiJ)P~8alR3n5PYQgUN90rs9U6X7^nM!i*LI$=9fY6#< zS$>NZ%Zv=OmYI+UiqVmfHe@Mm5&gxY7a@JUk)h=`Sw*zz2;#b43mgn)7`CTxG`|H4 z;T9`d^BA&kS$%t|KKuB63mywSUP~Wk)*#xk%V`-(rH2YEE0Zp1M?nBhRu+rHp%r3C zhwiceav@7>TaDXj-)MjO!`QW-d4RD$CE)Xb@_ANj81>SVl0DHd1g{k9VbM%#km-Ne zvcLF%HN8B-p!&c&vb3e4VZqXx$Bc;H7!e^|&me1BWXwdC)fooTBxuTqK8&?b#*o@j4Yg8xpHWvNJESb2h(b;-N@2g zQjbcI+kYh#nhTo^6#Lnh#fH-GnBjw=v{)#q!uE&C@4kwP+v>M&-CD2fqE?Jn=>-qn z<=KsTqHuNqt745c*h~lxVe;< z79xfmVKa%s>C?%dDmPN-qS;m`RSdcNFl7JWBhcvJV*vj~z&AHeQq~wo_Fs@?-}N|P z`Qy~sNDSJK7PE^TV-bm~Q~jti_L`1kcy{-gO$YHyS*Zc!F`I8P13PqBaDVD?cE*<^ z_DunQBfV5ugQ+c|B=w$6((I3ujO(H#FH6ko z22^)b@F9t%yD2D2?DK%K)<+sGICj zJ=~SZjP#_2k^h;GkIIUMHo_L`^Lm$a*wMUh?~``RduexjsU4h?&J?aD{>O6+?P!k5 z|17ccEqXY4v14Xf;U#Q96-MNRmo8lzwij$+SiwB?egZ(aZcGa(3djq{3MdHJXs3p# z_gBNT$P_Ri{s3o-{XGHyQlPhLY6cH%g-uV}R*fNmdHju$4wfB=%2R5pTC|19WU7nb}5Pe=5nj+iCG(0c!w-f^}a9Qe+Vca2i5P66Z@YMd*Bm*%qM8^f`Gpl(DMX&djx2P zGF+~Aw0-*o#GYY2EQSQ6XqTjIMIwNzge4nRbN19GX!t28v_UHRyZqM4N~t2d0&_H@H9f+v zZPXYd83yYXJ;oWKG?Is=Cc<>!5&+{;Z$I1xbFEN+ehLD-4Wk(ZQwhnEhN)N-29TrS zjGhjy?`mIMuPHk-6R$kvNoF7_9;V^$d$W%^JsP zi5!;mU3Oq}q_2BW&cFE5@bAbuwLh%R5RK-C8h+7_Fk9L-tR;3I#rU z81PjA|4G1K9cGPg{~ECezsAZWzXqBc@N!;7XE$l+?4}Hz?SeGkCEz%Kliu>!^81@Y zgNUP0IujZ$4E3o^$qXSZv?$Z@h5Lfgyv+(@1w?NZJRvlPgMeymcQ z#|W81zjo~+`8hLXIPo#yM>C2BUV4rYR?~Y&eDEm;PN*rR7lw7S_B1 zp4ASXX;?LQL8e(+PR_zntWUYv?HMw;GZ_Ip#|fICoMbcG|15-l;hT{BZ2_0RNpkjc ztWLQQm);Fc?I)h2^i=_W4**+aynopKxzyyqqaCi|U( zSbt_~bac=R)6H;NL2A5X2E$-~9!_)OsoYS({;ww??rr~taojIp)qi1Fn*?kXuv_w8 zkl0@fcw3VHTY&cz;BEnn1Uw=j0btyzf#JRs(@19+p=}j<5SgR-0`AStd2Z!!IGOQ= z;4!^BnRyT`YTQn#ke+48;W^ioeO@|v_rC%@ahiebJx%PdB=+$CrB^5P*!G5eL+bI+ z(vba#WZBjyDgku@LLoRb6bb{wTBCl_u6qH&4{bjr8ly4N7+DCP_v-y8e9zGA-~Ml) zxy4$hodGgD8MmlhwmFm!6^BF)8lO%thDL)UUAngxID+Wqjuf{Q%loXZK3el%Dpbr2 zq69d?8>CL-Pq#=n&IXg+b zgjg(X85Reh5~fDgUoaFjc50-*$6iaq&I)+?FW6t-kg^#T^k&!27S5=dwy=@q7wi1q z1+(qHkg5-zrPj?>8=hTmZn!T(vxy5Fg+o`Sv6x@9841-uiANu97+FwhuRhCG`q#5C z<*nal=C*b3Y`gW_Al&+G`riL-O20{g{cV8o9^SpnQv4t108QUPq=>I+bU+-cMOlha zxw7g)^o@fdBxg{Zx@g*dPDSvO5nk*k+~=Xx7>1TCvJ7lHHr#6GX{4Oh0AFAnD(A3!2T;J5Vuvs&Es9k%r^m0~#cKryo zTU-?#dJL+|#lYjC$DG^E$B`)^J}gZrw5&AWk*)o5*C|IODXp)!=l&(6#3g5Tlzq?l zIcGuc4_kKY_ZcQz7xIk`3xgv?GtgnV$Y#B-xuiueV{t7T7?_-8Cy}@01T3#nx ze?CLQrHgMKB5=J_&_cop59!CPJ)iwMzr=!AD~x%NnJ+W$VEfIN;iH?Zb(k&EOq3GW zq!C%8PGcZSw(NABZU58D5U%;^89M8PcS^g1MBHiXfOYLN!Yh>O5nGcS21J6aMK%^Sllr;p7|SwHVbrO{e;BWkPTYen~pVhfm-&W*8roh>DAKC z`j(I!`Nw2=!mxW7^6P61Y=)ZDtoC6`_y84GTN&edm~6>XidF@(uN#vETXu3xDFjv+zL} z1$IjfXo-&n!N!oC;I5JVC;wgRr6vw%^M6Q#8Mp&_GwD&eE~>AGJ2Jw&_1vpMsCqU4 zx4VcC)L>yW&kCD68|TI*+0t;;JxzmiQ#0v_oU-4IP(%3LBU)b{q$X{jRAIBZ43xp@ z-nlszn*!6+022VX@0 zScYki4sR}`a7lQGY2DznKAI}zS(cX2a-)zqwKQ;QVRK?GI!1>^zO^5ffko(S74}Ie zOCJR+HWo%kENsPX;>gedolUpoT1Z=xTM_&sPt1vQ;iP!f>b}^AFHI|qe$fbdgvXSX zXB^l=E38#nsWa82!$Q1P1Bi%eDRo6Zr89lPb1B1h;Bl-CF2RlQgAO)i(uxQ{9?BND zU~o7S-ie6pj0_bvH;9-YX}CYq*no%^a>Ev(`L1ZiaS7`!kxFX*RQV`~R~y+DDR0t- zsaUtEfe|jTH6u$6y(>amCzMd?y!nyxE^`Svg(?nfMnYX^6NVuxSTZdpSvR!Au`-kl z$l2Z@m#+<*$q7r?tif{R=5j|&BX70MFv+Q`#Z=~-;kID;-Rl;ozmR?4hwRHI|CVjW z3A`6iJI=S&!YCQ>Ds{@8{79s4+n_FJ3)y@Bmip8G4*ADX2G2+2?~qpkYqh58l&$0* zDQdVQ{FTDgfLQ3l^7@caW4{SPd)-@rPYU?qTa0JA^%&y0#r}`C#FG7cdh}TJIrfy8 zhke^5MxFYe;bCzr^lc-e#R4v^X_6d~6pTTko`BueubRd|JD?+Vko8o9K@5&H$f3f-qz)giW&tdzze!x5jtns@Y4 zrH1<<2e83z{wGb!E<7ukgf^Bv^lZb&Lu#h=(M*~J2DwlkH~M%YO=||0RG?3q@A1dbnFtWwzD8L!t&P(1d^2mdthG1!Jv?Y$yp& zNHRsPL_&_?E|l8jiakxPO{O(E(ma$f_N=sZ8GUjGv$q%hGdwoea#6%44P)fvq+PFf z@%#3g+Kh`YQog};3)H!Oft2ReI<0k5lV|%$WZK*lyV;fF@12lAZSVLQbexW*gvhY} z<7bSU*JVVj{)Ol)YyG+vvCi1q_EoD_z}G9+u36C*TNPg+yhvPAy)fm>+bhqI@KI&3 zz@W1n14=`}`6-8AtqrH3mCaYed!LK-nrv-OWGqO8Eh#n2*ZqI!TN+*yy_f_Vc?ELM zIeU)$3*-^kMM(y+=Zyx1ktYxP+}p}s*(@=%-BS=EqNTDN8@uEZ(2gNFv~du~_w?0i z4;u5=$EC2`Ed6R#ak7OupR^gzqu%EwaVFyx(aPR)y;s^dZrA+Wnt||HuZr%@; ze1#o(m&3#2WS`3Yj!&KQzQ<}{3q|^&dQ0iVkh_+k)T{EZ{ z*ON~s#3B(4;@&~`HEi7YI1)A#TCSa6T=7Z5S-}uJmJV{fmJ7MYfGfq|0bT@#?6d#Q znaw|S;f-?<=RWeW+}ey2&bInC+utcG6DQfn#2$0BvnG{XSe4E&=5#I#HCH_!j`u%=K8wve>szE1QP;yY{-5PBJ%6St2b@=y#HfO8wdiPnmTsbHg|v zdpUyNE)rb}-zhxosM8wz)fxPfVOa&koaM^3h!{6Flv2V!DWxR9T>S`WF`eAE-vzl5Vo>#v96}+x<7t;S9^chg;XhoCv2!MrrEEg_Zm?L7W6I zo#POA&mbBcLb2rsy3`JTsRQkua+F@nJ(vzZ2x9%H->qIZ^k$&y|qwgrXrg; zu?u>g#bQr!pTaDYjU8)~BPqvG2JSNGB-#2h1H+Jw-8(#x+74CVT|H3P+5HU&w_*CC z3vZ)|$eK9}Tp|}kF|NzGtd+Sfg9frq^xPJfh>k9o3#<324MX~?NM=t6E8b~|yX_I| zhAEVQ!5vPrzaW)rbfq@=x z&b5V^(0fG^;@k)=UHNt=VfOQT4pUTRjUj(gL{*KOa2H18lMzoWsWUFEK3P@S?qW5T z+(Rx2%n`P9i9Ny;^)VLnRZms7S}AX8P4;woMw}X8AGlllYP8Nm8p%7b9TRgsE3nBW zliSFgyK!4!iEspDW+Rz_tmEXk#ohU(Rz)d=l2_sS6>&Hdap)klkFv7%Pkm+L&uZev za<;yjED2UFIGZhO@p#Y3`bqzcJ#Q`=VYc`Ni_66Xim`z9^0`=%s3FM|$2=BK-0^r8 zrHB_MQ;Htewvhb?QW7*4JFnUMxaV@8Du{o(z>}(c#D0zb?6(EneKX^|4Fk} zd*lwj7p)$X(-OCCqO$eIXL&TIhwyD|<$Q^sV;BP_bhRc~Dr#PuB4q08Ir{X2w+FEbSLQ)$a<2l&lkJm21l<`&*G>PHy&HJCu4tV z9(12;$>V7(k($RgZhWHQ@dZ7Dy;Y#pW_h`l#%CF{mbYx|EDYfl8w|CJehYj~Yx!^A z39ZY542$1?jB@o;*p7izzrMW8Y62C!hsA{3u^yo&ln{Mm9=|ibR@3R1Qo31D>pKf_K z=34fOo4vk+_%GH{`dcXYK{5}x87 zwxbJ}$QFPQPQMY=Pd~8>?B7{{sN*&1+IIWKT55f*7JPV^@@mQ{Io1rDOY|>DnipV*88E98qQ$cp&m^cM#W@9F}2u$rK+-EETmJ_nb>48 z@=<;;;}na}hkK^W^=#*Py!)2L3OTRNO3wd?-5z1d(KI{`_=5-{@|Fe`CM2M}0UB=x zuyvN@dkaJTy~vc+cs#dZ6E>I&JMF<55oyco(FPO|#>)urLZ-OJj4w?WP@%psG*qn5 zkBmfmxVE~V@jm0e{vd7IIk%m&CKie;_E==R_)s3%RDP$@QZ|QF+ z4p2qLC)m=sUFCj@LHMWODHX^_cw-|YDYezJ(__TRCncrv*}I?^dxQ)YNIL13ryS;Y zjZ-s3sKHy4HJm%;5&Nf&@TR>Gfjs$`4n@u&?fVw8W8PTEnrv;N8Nb zr0s)Etl3ck=bLD=;eKLo-(PAoxmQgaN!vFqqSEaGmJ3KNqMw-`0({~_jOe$Ujmd(d z`AIXypZu^^57MLAI`AWLjE8Q+cp@2`4B=PpD{)7N9zfet>aaO6nIasrB?FU6iGELGGE(nGeGbwcVrTKf5oTm7WX%xd!o47Uc4Nd2q&am!u2Qk!WWP+NQ(~@2 zV;PXPzWM!zR#9{KQwR0}fUN3v(f(!&F@bI;c7v0(cC^TqFL+J zpj>QgumH7_nTf2DoM|}68Kl12-i%c_vPvWvlhFx=D*Bh32XeUTo^EyP>ioLhTz4*K zdvE4V2DE4&SzqiQ7y;FCb1K@PZ>N?I^n)Uv;#c-59;@jE$qZt#3uSerdle6;x-~WR zOGQ{RhO0nsySt_9Wn7Zbahp78yh(;8Kc$Td)0l?(FDInfrabdvhnNSlPT8%KncL}8 zu0WiUa*J1|(C4G_98W|#KaX+VDASw%6*;9bC`&18B@fcqnBQZskUO|`dDsm>Aq4ll zJU=P7GSlIe_K`8FPx8{zz(xlAD zZHwQSu>Sh@Lh{=OpUn9TICAmt5UM{OZLVihU7}ES^n}T%+472r!@!kWHm?;}Ba0vhvA%L^7 zXvLoj;WaM$kwtg@@&p-c#G?bdt`;AbyszUSF$|`8f0na3%?}klmie<9G?KsX!9Z4X ztyF0ZW(u46TOzy@vDYp}e3$_yvr{3br1JXlXr>J7Ruv9`2`wzskCfx9mPT9 zMte95fm2r~rt(d0K5;k7Z$sQDZ&4tQ!SQjVuhX)iAHzEdeu<=C3F}%t8T{-{3pQxJ z6qg~m`7#D)WW)T5$;G4F&N97a4OTa$I}}5Qb5gnR7bJCm9^b^tNE2RmoAb9cgxTcf zI7>HTOf&ss5q>*@fYMq@{tk=tXIeyQ=|9s_`YS0+MGnl}a&WxK{d*Kr&G~&|tF`Rm z{Za{R$W|7DIB?zV=fBJzSB|RJ8ckfV-_I;Z}oqjRFn39k2M=1E6v;4$4 z!f%|bAkO_f#pzv)3F3F&!@DofQX#{o_LIUtbElLRhlWBp17NK$N>SJ?LaP?pRPt`r zJg_ePl1P5`Z(iFAcCKjfJm_a~qPFedzX}V|mzT)$FmFn|5rj|wHv7LxO`gy=e-k0b zd!UWIPdv7e-)V2`#T5~Gzhq5)jea-&guEJmqR_LT<~{WnEM2g)3MP=Z+Kq(wM|fxg zk?|}Fp*SJkAo0>`6h@+d)yg$gIh7mB=ZiSxhmwvc-ZfFpYr@r`64}TV@UV94oUZR z!gbWi&4=R+G47G+T}$Mbp7L8QGs2EgP3J?~URS+{oFxLGJ1r5MMm$_|-y@ zf!8e1t>o-3$CHLhYv-DkrLP9Gw))_xe@)hZ?m0zJ3kYt`J%|M#S|iW3n_D z)8v|UCKpJP4T}k^#@>K41&ZFCVbx2O5YrQGN|V zmi^ZeRScVJVlk%AHH$RUnN!RM8O0h*o9pAzOyF2&*RLg3-1SQ}4$Qq@TLXcA?b%N5 zBcqrxC9jFhlxnl{n&ngQY=584p$9C6?lqBM2VXN^BS&_M^?c0=S_VuS+SjimHu?2S zWxIij~S@HgLK8S45 z6PA7_T_W#~)c8=Ojx-gEpycnle#603PhqHmr z#RIRY_HQeug!X%pOn268Y@$n93&A zSZ-n>$X|7hMq|m2Xr7F`>d5Xp7LPT}nPCO?c&tP=xi^+frql5ReX1IMNtlerqG=UP zCxWM@TOF}jBArgCjgn&f2j>cz^=Y1Wa%?qk8DGNx=~6F1M%Ts9ZnRbfr2 zF%=IsPPd|Cv1BfpKAevp3-4#Rv9y{{v7|bnA{WZ6pXYPIQ~ZUhc;fZQ>S#LoT#mWr z!!@=QILe>Z$;FcCFD8jP=?fzrxO)mSOGo5z_Lr_ zmP*Ex{`1peoGj!V1`X`yUpd24GeS%%o`|c;dC=eTSjmo9Ji2dUg0+vY!cUg(rQn`2>p;4YROx-nx9U{6m7IV&1(irDCesmDYInL2SM9r1 z(+ReK%(D*<`j~VS&j-)jjFJ69Vqe0IsB^aEgU_PT1Z*?zy~Nmds`L>RUX+L`?`j{b zrNEp$5{p7`wkQOEG`UFMG|R_K;&By?=HmG*yP`vdH_-kKEw9wo&1mBh32ESHIar2yZOfa7i`O06=19#v0O~Xoy|vsjSL+^N^&d~ z3!W*nnpvs#v`Q#H5f!de1Wh52rGgjvp$81ymMo}wEJr$C%S4>ruy&(TEka$hIX=SP zVc*e8h1o(;=+u6UZS1>JVFl*!r_}c5js;#-{ta`aMqN_+KNwYPNY&mn02?QdD9@QW zGT?J_EMKq5sk}_}`1p8MHC>Q~mCq=(57Y_B`xYWdG49xlYM(mhT}i7=H(KM*F->n3 z*qb{mWEe?CvCr4YC^qrOZ1?7l1kTN{z;_hsc3w7#d|(JZo^z~bBeIaC_U-prftj6# zP_YSwB>Xv+j;oFX!3!q0uvft-kt86nnu9&DyvjwD@{9u(c828 z5CrgPP&nuWbvvNOIs{}bi-n{oC)lQfr$|skMTEcsHbgCdbu16_J*m8~Thp#`tN99l z(dNb6&y}YJPLNMb<@iCG6|B;dA)!3f@a;l+rd3B8;W-8^!s}(vHJ`GqaGOtdr;aZ1 zZDaoio(}F{->1`W#9}Aov6D@QrdvS@0x}K8nTR5MqHpJ-GWe@A<}el&?u3V%AP%}j zg&ScQR8zG2kjH9ao2qe@X6kYElx)QyGw8?%KiWFO%CUU@#WO75p-SeFFT{8IFL_Mv z&ve-mVAEnzvXM4g^i$U34D9JEOwu)*~FN%PR6~9 zTI!z5=kpV?u)m0RbQrO$MByWWReFMjNHZ#d5}sDcakOEQk(qCjhG}(7MdPPsUn*5y zm5gIe#ncgXFiY*UO8(+>7789w$9@U-cj+kM3Tqt!! z<4}V-qIQ zuvsFVz|u=%@z)w1|D_mB+SwW_XId?2kd`mDtZwNe?5nhzF7Q{3 zz{&EpXX#fWo~qhVh1J2r#aNkR>9o$@xmUfMOzP-a)!f!W)#ebIDGj;DRdZ1yX=b4g zs*@@kRfpL?7&=U@3X`*W*i;4CN!9%7QwS>E7wSTWSTUOwh|(mlcE%~#$C_b6@6L%e z8@$3o`luFYy~)a^n~(sxd@eT;Ks@_8^?KcO&TBQD;d{!97KN)-kj)>ZIXit~A_+59 zBCUL4LQXJ?4w!I41z%#_-t%cXG}}rbE@B6h0)s1^WG=^45)(oG*9m!1`Rz&5@PO(F zLQ`0CqG>T|F-;+h)UlVZ*xI{;J1QqzJVotJY71&G22aees&_E|s%n(H&ZQM5sEQYI z!3xZ})=Dd>yMtfoh@4GSKgaUWx`yO=7kfG>`tLw;B7C{R49B{`N`OjDya@2t@CGs$ z9H#ZIS)7IVz_kc!wjc1o6!^N18yKikEffcqsO)p9Js;lh4zoQMY@G?sX9xl%f-0vH zx!|4|R$sQotvtjbhEoi?DwfP5TsroS$0pQ)Xgb_SGanKj z(R?7EPsYX$`&sFL=nm!YLFpOo?>mHI@w5W8mTf|XQ$9C@EhZ)^@=_HFr%$V=A{lK2 ztH9=GTF}*SroRRxqJi{LA=qCdfBf0jB_}8m8!{Jxp?n%=aLW?a42raW@QW(wV5n<3 zWl&9`xpf2D3n2kZ#FFtNOq_M-@GTNU)8jxDkVKUU>U6LZTZ9)b8lKhAvjilGV@cty zw8{x6AOZyzRMR35@2wUo&kW_?J2ABvsQU|aB1q0*A2156Q>@NO5GLudIN;VwWDW}U z|L0J6?7AP_`;Sq-LZA-+MVq0OK$w_kQA|}5o{f(Mst`Zp%`&__@WEAhV+m~?dd^KP z7wp`6TKo zmJrQ`>H=GG;vmZ@v7d8-!lXvVkil`9vqHGaKaW+b-Vcr@QB6odZyiE+hH#PuJ5`G$ z7U{%UooM%y)2_J3BlOMT@6ajlM&Tw^UBSpP-H?4RqYXr~`xc28BCvyRRRDz(7{({z z?^2am=&F_?RZE$wtzrTaQY=EFvZyMkjBPj(OLVC5gc_eH%}8v5MDB2DTAsxiVSQ!R z1k-HlipLXyCADW<($(I!3;B^$%{v&|wwcx#VtN~fat9U`rZw7MMfPAnD^wdwmT0gm za0>C3Oa=!al{&%U0~ZS@@G}H)kjUm4OGb#vF}FRAVbgI$RkkHtSX%HDeT2a$B70al zUuQXoqL;@DY+hOkJ{8%Iy2fDh5eC~L&yPj3<0_s!F52Js@x^5pR?h+CO(RoynrSC; zx!^YbNH>G!Ul4IIkw_%OxOMyyo)I*Nim*R5e&snNA zG(7=5B9Ja{i29cx%O@;nO1u51q#A>ah#BQr_n%zS%#3^&WLCl7Xj9F^I3j(@;w-E7 z1}X^rfOeI9+kXfS;~?`KR-Bq(iV38)9J*@ZWN|;h7aVGruwd!ks=1X7Q56s^v&hNW z#FX~I+fv#|lVo$Rs=X{6l+HdU!jXTwl~0V3EOy|bY1UYxP>tSB%Z5y_6Wdwcc73Sr z}(v19~bg=nqbVQL>uqR1=UH?QnF_*yI$xH!Yw$B{-p`!J*^ zjo~E{3pl1b2Gu_Q#R_X@JR6hE@*{jWbQ_D+E}m&MFWOClLx2nQ>6cR%n>(X>IJj+t2siM+> zOLDx$5L5Z|>*-uNC#;nZU>)k*{6so%Viq{CM1(SV_1wWJ+SgISqK4HQ)Zr8(G&_!K zQ1``5$ie!NAw2b(dgpNLmBa9uB-QCxFg8te{1wJ}nLYKHP8KupMKKZJCWf0s3#b=! zu;VyclCxJ&Sgc@%3OFk$2*K#xL~ChE6M7!*n}*4Jc-TAtl)d` zqrm*X1!p64aOLRmu>Z4N>0B;ZT@_wgX1y+^`Z3>zG7QG1sw4(@meXKIJe%aqBFnrx zOTRzGWvO-stD?#AXmSE?d|t)Uh<@DB^2udm6W=XFNpF7z)2!xa8)L2ufPrgi~j?Wky4+F zoKzU@7^A5#fUgP8a(n`a_!7pGZ z*WOJvkHnN;qLn(@BGJjVEnnCVt**|SER~q95x%>TRvk@sB1)1nmD7pSc=!{i6KZeb zbnt>GUaSL;^_psF^;l!Ey~0mOq}n38#E)=12(<_Ti#S&?@7j=1Oa)LRs=cs}t=fKs z8YF#)3dp>Asan~r(c{&a7T%xg-7+$eiy@v$s5&-9jAj+%S zC(vE|;}9}2F_u+<9n&~O;t%sMqgWzwAkfAUPR@v=eK4P)=LB3G+$Q}nrDzNfzVhzC zi@S~g5!GrE`%tlpV*u9}b-_*W;Jp|Kxnp=#I({kc@NtSoMJ8J+ge2&ijvz7FoW9@d z6i2)|2s0(s*zS%oPDEn!7tMyF(zqTDIKcCf>QM8Ck)m-x38lR7Jd!m z)F%v5*$4UC3t?FVM!|R|3gKNk;Ufqx2~g6cC&;j{CB_agqo+{l$zav^L@s?ed>K!! zjM<2MH4)(`Fb2=0)r+W{^gF8k#b2sd^8We547Pb?nH8=>&#~hB=u4j*ma{7%PIe}-u*XP-meFDAT#_& zYb*}BrB5yCz#$A_?p)1kMf0r6glgLF<#13#?`)v<=0jYxqI^_z0+H1&&aa%@&&eXQ zMVTOy8;_!cw{}0f^h^Zu>F)3S4@t^8}GIPoj$7;53C%vv$)*i&k3KL9Y47*58>qW=D)(_N?kic;F$Z|bE2@*xKm>c zqn*oFYN zYz6O}IxEl^wpwb!9C3~%l5rJS8MgebVe2Us3UgXTiYGvmR3~eR`z(G@!`TH6=JSTP ztDwRcDlN~MnU?p*zfhf(R?9h@o=>zq(?nJ!MQryv)l#QwPgGioBgtyHQNSd~3t!=D zho%e-wyr%-Pe~T(SVzkhQ8=$pK!jt8c%&CN~OiisfSo_rL9Z1zk-wnu&B~V+|-}!e8rK`Wmyc%zz zM)1dnFz z{s^`K&7JeTl=81YM@H37o6@*qjYbu|> z(Yu7278@wM>n2@X`>3GvE#qYYKAUMsKSddAm=IGXQ-E{ ze3J8-+Hn^*syAD;m$((#t+0H!!xi_JR7s901jJ$7%_=;63#1drdZPK_%{*YZ83wEd z9?|eE4Xf);s=$vcDfhmc7xPXXshs2I0t-usIQrPn6ynWQ@Ml&<4uR(cIpL#zjwf6L zz!g#T7UIkg+2-OfeQg3q3I~g1j=_w3>yA}knJbSXf{9f3^4oWth1 z@=b38M=7zud2mlKEtno*xA;!zjaO6!Yi{PcjxwYZ{&_7+4hDzsw6cd`RAJ8}D%f|Y z<&&ct47)dcp2UVb7+oy(j^G=M?LICcyIFmgJt?2Jg72o`Em4XS+|9|#1y%~=(cOJQO0s;LL^XC2{t$yyk61LtsNf}dAImkD@ zTg48;Xl(pLNUnBf06U>ogrg3NW1!_S`KV-0AH;%n6Gt%Np^{7$mjbM3SW;7AFPR%tmTmuZxgQn2XziS?S9E=z8wZwv5+-!+7 zn*cT7EW|-Fa2`wS)g8k%yAR8Nj@~9XUqP<%9tN{Nt`1Hxr@cuoyMnC&Odf8t$!V8c zmjdj4{0+He6o&zOA%=+sz7DnXunKRw-Fo>&<=Jt&Sux7>79&*ZQULq>R!e>Njl@{s zA{T!1NQlM}+1lZ)nvj@$+I6Fobgy1Sv+))I%Z$!gfDSGnndD(VFj#Rbo(&|6RtV$A z$KyO=dX4s+b|+wd451G8%6#?-Vw5m=8L48SZ=)|7ad8DPv1hiGA5R2p>Tyt=9#_%Y zC7$7WYrJq8|5k|d8kojOon{dw z{LBoY5kLi6??on>n+XEnFyrx`!URTxT;^>F6pO2!d4o<+mcD{*YIzA_n9zUCFe)>0(o!v=Rpl0EuwzF zkJ9520^bJySGh%=K?!L|tql;l7?E|1CfCAr$tFAsG8iG33X;u)bM}pw*&*OhLHdA~G%^bkr@YlbZps=M8cX(PJj0KhuZXjHw^ToBm zPE_F+bn>g4^~yO!8DUI$>Bcw|syA^81-&>x zr5!<2BT>#tl@_kdxbj}1)j8?6i8F(O1AG=qfov4xC4Vfq=s-G(>B8yjIe8tL zm5Ypn;bN>%;2^*UtMDw19ZKIG2t?3Sz<4LW*scyjF`4 zNQof^iKcB-jkOFzP_R`m7DUyYjOsJ ztjTojb>BrUC1lQWaVs7GRegcfVLvcfl^3z)J3q~ecT7|ZiS>wy1j+M-xIZmOvp7#N zSd4TnIZUm0T&xD-zNcG&O>H*05b2CkiX1;59v z$ZR%L;Kmv(znh*8%)LP3ma4?9!P{Wn!0l%&>-9U8=dN=k?p{*+YTzC?AaF0)f%#8| z7c2?iCnYl_T_0>XvM_i*>F|d_q(3~5*aOwmUqueEGO}+yt2M0C5ZXxC^xz503PNu$ zq31FcB|OLFiiC5VaF@rVLr!>t7gtg~41Wx(RO1ZaTc+r01AWsV<#eCr}-DC|m(f2*D%;o}(uTpVsil8h%g1 z0S&({kZ0FUqoYnZ2lfj}yO0~1=SEgKRdzWcv@%r@T_$qTja+adkxOn)4TKT2Rl3{2 zQpPNgne`0lQ$lgT==2L376ob-Bo7`b?Szjd;t^X(M;7TCfn`sq+KZs5;pY6Dyo4j{ zgRT;`vVMeW#${G|9{mvp@OMk-!7r%O&kIz(0UZREYr3?|SXp7!Zu9~JO9ZO7d;+~I z&QrH`iI>1rr{N+E+caD)@GO1?i~DJT%Kyj-X#gSgtb}-E?3CB8o=eVzk2-}v)Dv2T z67*uH2&$bT{XLsZ!gGdtl73UeMklq2xk|1cN7JJxq`Qr}Go+0UpVjbPfoFBcPe@d) z3A^lh)L~P$xvq-QqeIqShx^R{12xV-UBoUsn+`DBbnOccHlec~&0*i>L` zSo5#a@=&km&&)!fV!d=4>?ZQ=)b&>3k8D&5OGC7~=M;TNh$BFU6|+ppwU$n=#5*PB zt+?JK8oN{VoD(i~!sn$?(>hI7uxomsr;H5GC4{sl z9O}VDF1iuX9=b^HD$nz}K65siCmaMUzsV5R5{!C>8D3>kP1zy0(it~`g44D4IIZ-$ zdd|2FxH2&M(9Z|M9suaqv)u*%e_k~#q{!iV9Mc`T@GHVI{p68=oXl}_mklG-U&pJoLK zSzld6hEH03^vA))a1A=evmY)ZfNOfftHqp`Jtt!MO%p8AxxvSt;c82!yMgInfKG%e_;@Su47r4!MiWM03!TPC zti$tom?)3%=GN46Lf+o$d>-CP7~naogi6aciBxl7*CpHNPcppSA=z-4O8ZH%@t_nj zy?&BYnd$`k4>1rT0olNWo=pr$Leba~Vr5DQp2atroM9fF1SLyexa%_SO}v`?sXU#8 z*KtyfX&CII4$SK%6s2QA(2TYbI5jGS->D%lrF2AjdnGi8lr{sK zuok@+nbI&qUx(C{kOxpY6e~^AVvR}2)OGkp4Og-blDoqx6_H9Bj_`i`43sI#G|Z$B zjKrm6i4*aUR5dN0Z4lHL1oCStgP^(-tpX~Ku$F|w@PLGMx;!`vvZgBxmJpoAAB;k2lN%%tzpVY9^$vXrIr0fzH31teO zklrsq3PRcl6awk~ycs4uZcyOC%=@gi8h}qE-@%bfQg|4UPaF-uEf0 zD$%=Fz`TbsN_dH}OW4O!Nhte6LeaYtZeo0dDk!GCAb91|&Ao!v^F@Ii|5s9j7*>}~ z`|f<6<219}1(zTUeyAfsHW!Jfy@Y|61S-#G&N1I7H8;0XpOiZ319~>9SY9f5Y59ko5z*D~8*7>J({$ZW3 zqiKnvsermR{>}(-aeEn!Cy6@WXPI)7CbH*QO_U9W7+MEua(L%KXkwnr5L&`2O{U=I zK)|_A(5d#%Uu&kK8}#I^xKj}wp>ss7=!i49-vLY0t6reqN)lEW&XE_WlFvFh+1(^%*zX&)^*k_X zLmQ*pnDV-wvF)|ZuUh86;MLC%cHbipSDP-%iUQabz{3*l(9twEU;5(_89N8+%waSV z?t+FAZg4{3R!Luh#uC;z={at`)Bd6po^!$zPPpF*cR1l07q5fwvXdTm!d~em&?Qhs zzQAdtMGn;b;ze`M&fi0obb`tyliK-Za(<=-n+%y5!gT_l)$pQ|w}&?5s=$14zwt^p zvXV>rDjyKy0CB39$tD24A<@b@FA!=0)BYuzSifw3(|ZUSydW_0gpOCx0V(B?2}`88 zO$Ux1t$fM5xLo9iz+QoH=OPm-|GQ0Gzk3^DiES{Bghy*k$j!P=_ql1O{8YrLA2uP^ z;JO}{(-KCweU>o56|>IY?}Xef>ok|jI;?Q;azU)q+z#uI8)6-D!>dDXb9HzHR+jN~ zI{kA+snf#nk}oErgxo>uaKBUUii3yyLdg$sd1vZla!GwIRb3$&?blNiW^=vZuJ*`f7>ULAk^_8y2<&+M&Mbcr7Ghc3xbeiiK9dfIpLoQ2n z$R&vmcRBRqQbeai&U{*(adWRB`H>BV9;&&|5CH4;1u5WqL5oPuN42`4jFm{57PnF1|erQ)ztz+EV8C{+hE0^xco-{FLBN{X&) z8E%tkV?vaSz&$LigmnVZNdm=}%P&Zt_W~&phyz_hDhQ;)SM;uI`F+L1K<^xQUr(=D zyj{*_WnYoFO3&2m(svlht6D#FY51gu&kHox;Ub;UD1u+KNR1o$ndB?aSHaTsjMe~c z8ve{keJ={h92GjB3C89O1M9#Z8 z=iEpM?;r3yXi|kBK)Y&` zc2)ZAO|J+m%7H;`~&a+UO4xsc<7&{4(6gVt&N)buSQN3l#ZGNb6lPF3EyH zO=OQ7sWMeKA9MZit{3R(gUclpGmbE_QK!zc7bN#-fh=1m4zQqP9C9P5YLjz<2*2#1 z?5LYH>_#@YkzH=2)s6JI5%!2dw8@REbR*l`$PPCm_P%t*L0{(dp^z-H@;%`tg0&~` z1r5*0umh5oiY9iV6k8;9)WHwacH#jRVKMcVXgJIwkb;b&Zg|>A$$mF>)~Aaw;9wt^ z0(N1=fuffQX?0naARu{H+}K%j!KotiAo@kfO{gNzNDz^;E1}%0Na&G6k)(&2Cn1y< z@^J4$nNZBcguW&wbTzTgQcUP*@`QdSCJSL=7l?_E-*d^0Ty!Is-N+R;a*Bv)cCHjV zQ;MA^#SWEXN8K2tRs63VAZ6tPdL}BYDMYRzq6&PtQLmnM+EY7x|0$WV3Trl|-bG!k z0_RM~y~RR`s~cn+QqAmJi0xEENa&CEYXsF_1-w-+F{fNr&eX*`qCu`s$^HtvX@L>E zVI!c!A>9K*II3lXv}?X#20LH$jSSL^^^mR*-erQ7rRsF>Wi$Tp@3HTtg)y~M_zOiu zwA^M$rl~`$(!6l3y;~csJSP&tx_yr146ps_kg~r^GI3@}rP*R^hiCnmIv-u6n%2*QR^mD&*L=d-XWBFqEXO{gn%AD7 ztZ9vEepEG!!@c$qow1@yHHqh+408`qI|FRXmZ&DVu~5%Fq?+ZvNHtAoI<*h-bdFou zr1BBrof$B=qESp*c`%jB<+xMly6l7hCqo6He83?e-=hqU+j_3*o&WeVJ@N^!xoBDb z+b;47Z+it`;U3`*|3epqSLl%ozH9zhy;O5|sYdk*@cbXRS6anLHU@0}hx` zGz>upjFI?$kszR;N5BM8qn>F3IS@<&PC)TdMWr=bYVEDJ_F8MLbz0j>E4@ieEw)%= zMT%D2s=cjRP^r<5idOC8s{G%#_CBx43=d2H|F1N2&e^ZE*IsMwwb$NzEh#ba9Krqg zxi1W=0Dz1;_h~uiI*FEXHZZY#6{%^dTnIsT{r`??!ayL;p9cXk5tZL7Uniaq{=y!u z_uo*?Z#*_~ISB7U;i(_u>7wQ684kcaH1U!Z<5J+oyIaODx*OhSV8;WcP?xx6Y6Z=1 zQztDHc?*~T&G$hb9ND%3Vg}V7-wwk5?u|zs(olp$dV}xj7{70Rn0i2eaqD2A*Z`=VjKUPT2XU^M!@mk0N?=SM*#Ypn>F|V(^Ck6KWLV7%$jRphlDEH~ZXfeL9Dkh5n5w|>C&@I( zHf4_E!?6=(*2$^yM*^z)>#sNG%ki?09HqBKBb93FTGo4Z)3%h z^s*}qM4m;M?`~s-_7uhv@Sm;{;dK^4uv!)|!k0X>rR4|icRP`BA>Bf!Qik&646n-w zULbDD<}aHAr?m!RY{1d;^7OJ5@@&(sd$-Zj-F{V@PU8;(CZMjx1SXYgK}emB_7z4e zpBF7M=s=$Sy-{uV90X_vB={p~5+MbTZXg%byt0*`PBB{2>6R-Ip{aX`vD|3UttdbM zwm7<7xo`zQXKV!4p`2MO=YMctyyBQT)(gkkEjr0@Y;AN0{9YTK#uDR7W0CrZ0F*4O zE9hR*p`X|j@s>?I$^)ZBz-_koLZ{gV{%czdm*FXKnjLsi9<+&S1O9>;V2;D9Tq+v~ zN(Y=NtPltEFij`I)A&&Wk##L>TW04}XkhqO7)#;U-AMp=h;$^rj}5|nS-{7-K^MhF zgWv5ss!w+v>azru4@F9y(W6EHd7!2bQ4u{YJ0vmxM&^Ut^ zA|E}u8C^n-nz-7~Q}K|`RE8x;Np)05@8$5&-Hk6RJ&*Yy7jOVFIZdtTT&}oB`o$5Q(=x|U)IiVbd<0E)FI=|#N~0U3 zfv6nv2e?NyG8)}N=G{QTBBNV414Qn+Jx4bAmPV7E@LbNn?cGg?Dc44)?F*NHau&6% znrlliH_c#Iw0E5YC*9LAx-ARQS28NX5u!-@GDJjJv4n#*A1<6b;4HNXqq{`oHt-EN z_1r--q6fMPDo1FGPP8q57s_8IG5kdeL9-;E4Nt!*LAWn`hE&Gj89L;a#Mn{+w^ZON z8$PZj{EO6~JbkMa6%9~6D;kiN+!(oVXx_b~-Clt~gO_Vi0^m^r1|?s6_q0}oGe95$ z;%NF6Kr=G9kn6z|nBfK+M9yA|8$s1NKDMRP@>O{YWEemOoQK?40h+yBc^Q`h;2Q^z zsrbe4ur0=-Qc$Ug9ehTN1IEu_ER}`8Dt*wmo!{OyExlMhpV!sCiZ7il%heDY^L2!J zWBwdq%9uYJ z76YHKEtQO^qDdH%z+K*{LQWW+3_Jm{l(^>lt!3e5E8Ei`UP)6VVl;@Ka-%~cR$$gz zcxmd27L1oXIeF-h*B9Ty2`eT6FhFn}ZEedXilhOAF!AX}PJqJ3oD~ddsS~{uG9t?x zE7Khem82sKG29U2H!oTSy#+}#5s+q4n*=y95GDPB3puH-5d1MzlLR8dr}PT)F+II2 z*o)9iZGo4GrhXt&D(o9Lp6+|wp;nN+Zv)d1vbZgGcGpEg;y`SOIH|X9sDC80m4c^qy4Lz8hrCLO#S9MQgLC0K~v$C@ljq5k& zRJj`47V20{MuQh30{km#73vih&~?dNZXj+5Gz6@Wz_xf~w>y?YFGiQ8UIAOOO4ob= zpmY<;akYp;iVsA4T|5(036y3b8ds`F)X6qfd^r?4tcsA6T7EmSLBe$y4NAx>jiy`D z8k9UzKPnjldIc8^>YK_u7a^da!Cv7BT%D}-pavzN5yDF33s?dw^ZAH9gRr|;078uy z28MFVuyWm^XmVNBAUY^iYslV|Qu!zq7;P*k4i~hXb7syxZ$76YHIwjZ9;e7QQi%vo zu#66}K^ddCUPpUDz?rT#J*c4Ib}AUtRv;oHMqj@g4RFSf8X*SU&|sR?T_tDHGRXiO zowpq81DV7MmU5LQ4m9;1>Pt$VXoW_9kE#i%+)3egrBjE3xM z1L5vFv>GoUn?ZThG>biTgS2^BTd5vEIY-P(kntkK@evC4GH?bm8l0#ml6W3idCKv| zOgGG%afYM*lKPQ)OdVQ9y!ht!<S!xqu|-fvC6NypQ-oGSznn;P)OJxfqo8S8^>d!*$lYkVaL#lc*3M{X zL>V9!0gVi-OoPaF-id5CQDMth9f*DwtO7EDpMzkdh#){lXo4)KTDDA4fW{~isE}OP z2GNG+b0CqI@IeqJq@r*uA$3H`s^Sh#m)RPRl2<>Aa)oHkUBrplDg=Gqs;D0$Qfm5) zMx)_;3Hqml*%@<46%zJ}1D8_KYY=>nQ3_SGKro;7XfHBOVi95j(%}Y!kp-cRbz<^@ z!a~&yQj9?dz0B=c`AghF)G6Ujp#4EX0SaJN>R7&{1*!*eLYa(Nm<+;^mGl{Nr(bZ6 zDcvKzEJ78_JE;o#rUk^W3C2fsW=>Qi>k&kgZG&i9hr<-(9AWWLDhIQl|v$4Fu2O1mA337(9zn&!@N`Yr?kLlQbj6|xh2aBz%0WmwC!}LV2X=YB4!rUbHsKxI=g8!!Lk6*i;hK_4aSDl1k_@jF}LxYY4e>n zAb2r-auwX!-UT~IXUkIjou>hqX3m>6%{YDL{Aotxbbzz66N0>3mVwBnq6{FSTssgX zK?$cxMgvGLOAE_U_Zu%Pwu} zYPzx$vk`Pb;Clw>fU;12s9dNguh1Y2H@Fc%(V$v!z!2EkvWhX*(jA6=7-cQrB&4GOwXSJ42nXcf$RO_Rf)xmM&d%M8UCN}Cr)(@* zhHs(|0~cVrmQI9P!Ac9=gBB0f2v`yM&;}Ak4#gYNEU}6QK$50rvAsX5Yg*ab*}h`-BBN<$Bb902=*ZlIWoS32Ty%pW%T@M# z7!g>c!o`Shx1w!PF3Ow?Ab-1kv5-A1nTS9QSXR&S0WShhZ@OhyyPM zo^H$>;Ar$1GZwM{n`bObqmSGKXz!k-qK`09%wEWWG_bcUKLmj;c9sK8M$1aDj$R0# z2Zc}~^1%ky4y~!B)+(%o0P8>jB@q@9 z!h$nlY6RGGrkyjBpul#BDD2&Od7GC4)XIA%jilgZJz|V-*rt^;nONOkyK^h27>x3H zT^`dbUSqqeQ%*-h+uI$xA8(_MH?gwmQ7lza`*(oPOLEwxh_-zX&ioW20?{OriM##GaX~VV95ri zy7q;#7}L_d0}vZzb4KK)x`6t?Eu6pvV(=<72;pQgJ}v@PUk+&q3S7C|IH$dPA;4_u zYFh@o78auvSgw4>qlONv1_B7;Kwq-!chO*vOoa;*=7irrNM$9-9Jv^r^&B*kCtN}xg zk%AI6y`>AQDv*ivN#58L=0IoI{ohVkW8A>n8ocVDR3R|C=uOxgm#n8xAuvRSRr$ z;77%3cV3iv5yk{&z+d!TlJF~AAM%1-0`S|aFYUqSb*S1Lwt&XkBK=e+WT{lR*^T7dE!tm;HD&(L-maYSocezu9&l=5naw^0+ zO*?j2=NdFac~JC<-08kS!S8L^-r6bksJ5Ud}( z&k7TcB@FZS>@zM*O`q8~-_h}5s+8unB<`jP-fmyX_Mz&?kK6tX%3e0+et~fpCWEFX zb2?R3*h&_zfQE-0f>D8H1>#bJ(Xq<{8WGJ(fy;o(z7L89D8w`Ywsfp$nloG13)b#x zpN=_;mKko<085t&N)1dk2xQ401v6`4>rxe@U236pg`fEb^#?s994T%gNqt^ctdgCK z3J(zMqVLQ|apr3BUT0n~f94#jo}%?(*OO}nOfV_6cHk34F=h{W(rXCcGZ!0tl|>{Z zFt&<|!jQA?h0#>%LGpEFs!;=CMC(TGv(52XAY+0*w3}(w!*ssO*ER+hg1R}-O zDGkNkCr7987fl&z?a0l1EDf<+1|3kx6F0c|Z8Z2IX!^sBb2%hI$_*VA6J|Aa9z$3G z(nIgt(;$YOb8-%M@6?)Bueo73OH-*_!PRUELJ13@#V|PNC#Bnqm}`>VMuu27urgF3 z*Chr!!?D9?N;|3iX^@q=L~vJA&`bt+mvw=9l6gsX${Un@pn;}XB~!GRff>iO#`zv$ z@}q^#m@^j!7t=IOH|I`2+i1{Gx~fLbGG6Ge!A0PQL~7RcDtR*jxldGRc)xk)N*LVZ0V|l^@3}L<&d5L z50UQ;i9j!jJPg!@Emh=2^m@Zqhbv&4#)x4cXW(rfskPv2Xi!-^w~53I<0HS=&C21I zhtl}(q*(*zX(;YbiaJTmc-qI~(;n$9^$(b=EW6BFv%y#xYr&EL{*!KPd(ja^tFWTF$3?I_%hK!-IR23#wycotjiebqI6Nx ztUSUi)MF-l1d~8V?WkGHes3n$F0OvMImE2M_Q1;})7i!rudh9J z{5rD=_);H24H%q$`$#j{VpjLmg~oimYuBy}Dj`Bk%$f zXqxzLa|rdlHT%v{>jCtDndr=%F?KxxPyBUF=!x}a5(U8xZtkp;Wh7IgM@rJ@`%e70 zIg}Bwvuvp@Z%dMdnvVNYY($@zBOPiCZ67eJ`t2c=M{0o6p)5bdbjOoDZSr1Hg4s!jGt4Q4FVgVIJr>Q#(iHeK9Uln&|U zt2BtfvJmFAWf-$0+E|NPoR5uYH3?z~qn7F(QVj^DYNLH5zsnc?HDkp>Pel_zWq3|D zgzJhjW6ga_5C8Tl;m6l?0WkHZt1!GLfeKqSR7fEv(|iv6(_zij>(NS?jDU*( zA3GDl!q7Ef!|EO%*9(>~`6;YbEArEsRZSBd;?iG@h5<}!wg1)mh3fABnI8J_5>dn^ zmG#@>F^UriG^7rMRT0Ej$V~iUWXqPmOzM9CFa@F~fU;}s;;dB)0M|O;X3d&Sc7!9> zW{nims!*g@)6+&;2YXaXBe5ckHkd*a>e{x{%cy@8{=Z9ciYKiConu?>U~BHF&k^gf zB1j!F3BtZb;K48_B=dWz5iXcv0CA*TE713^GQwmg?q@gcj>E*>EI zebk^az%KAJ2oBT>YAadm@B~O4i4A0Fs42PyH9ldYOQ4nUIM5vrd4&um7Hj(Rj|&7y z&baIi9aZPjkv&9UcSz|uLAalkG=vm_j-b$;@W>U|bvmN4uXvzF{fOk(Ge59T9LXPV z9wg3krbfzouZ46;W3eNEbn`Wv?G`cwWE((}IbG!3Mw^V;YlFzai@qtiE@Vx@>@ONf zoih?OLbEam03hUy8m5t&dVYnZ5Fyb>0x)YDvRX1q2`F1imrx*Wun%^|7qz~-H)IgD8+!ja}_xCgY z);GR8@a^8UH%{#v-w6p5_^h&a=J~cH@J$uJGS9a~+qV;#nTh$^*9*+lG_X3s#{oeW zdO7OZQp3PBR}K8&zpIK(-C=5}$$Iuk_(e2V)uY=nWTOn@0OKoW?c0%g#yVER_uIYq ztQj34O@8*cEiV#HfMfa18~F%i<3&J`X-F-9D{W=eBdfQ>-t$S{D~)jwwVk8|&<))|a+NxDRh`P@Nc?k-iF2M-@mgfr<9 zXxNJDJ$egcDvOLygUQwEg95V1ti04r41e;>Fh(oHQ;5Mhaq^^!?W7wy;Ll@Hh?({~4 z2u}RrjjjXwOcx2o`H`^rl#pTUEgni-Jfv{P+Q>nLgDv(j%n7$tH(6}fthOVuas_Ct zbgdP}GU;eD5nAx<$mVcHFVdjNMrAgx+3A~&t1*fcNm96f@eQ~Wi@9wA#w}|mKKS$e zTpR1MRp zD#}3>rUR7%r6*R#av@c&T9s3T3W1e_;f!Sig+W$I9!L|K?7$kkd_XmXK^Y;v z@vrhS)**wd;>3wDRsB`9fs|KaVXYY?>99bU1VR=lAt$V@D=w?U!oXpHBCtSF>cNk8 z?TUriLqFjXH>Dak#popY*`*`N&evRp4GU$=Gda8tfrT&V6}bPX$M2a!?q6+}Vm)p7 zEgosT!e(BDYLDYwNn#Gz6`XAsRIGd4Dvg+iJc)R&yu!zppjgF~5l328Z>(p(RqyQs zD^~?`zi~|4FZ(c&*J$ccKLq*aV;_31IW!f=6gY`0vAJ}x*bIR}-gjmWHQ@q?K@0j( z-hv)lcsN~@8h{AOl%=6NR$l8&;E+LsN{(|&l1bN*S0MSS-koh=h43OPDctI4w`_8q zYV|d@RV1mll*wT$?RAmyOWucam7TgIGX64*6(297wnY`D4bzTj4$71xb`cVT(mlc~ zOi8lFJ}PUMmSHhM^&WE4N3-~l^^2Z?_gcj2v-^d>60`EK#M%$1^sBZojYC`j&hbmQ zU?#LyIp8(3pWh?Am_mcf&kch{G@tTwSaQf?JAsEtf=}<&^RH5i__T&ob5=eYJ9a2a zIV`dD;&YE3RC&!i9;skeS9xoq?DS*aH7jp56D^nhWD2^L<;uB~cDE=Lu_^USA6chf zi$U$cISn(+fj27(1ybkWD;9SuhyJW=u(dzyu>W^mD-DQ}mjg`$Y_DB0khuPPf2&!& z!zwP@0m%8ew0FmjtV%u*4Jmf0UAlaBY@J!V@Ud$vX>CP*rzK^|9qQ@?JFHb`$g#UJ#s=_i1q;Hd+7ErL7{TBO4tdoC@#vR9+$b=Z^ST@ z_NdCQdRaM9&A6*4+&94G1bPCpn2V^1Y7prmjS(M6POzKC{nx=_~1BtW$>;A{qw3ZAcj=u2cC2K%wiF+^Gx*fPv2U0hONG)5^g=O7L9x|Cf)1-sy1Ouv^1gm^&p*e8vPerlm;B+pnmdHpi}#!{>pE8=<{|Mve+*H zD}vl*QVC@f%?F(FI<<=#uDY)AcWlx$YXpNuN`8|IVG?Q`!5>c}>sqmOI5aX$Q6RI8~P$-!ch?E<7fz)y2kM~jkbCt?sJ*ewvWo5|kRVJNh&*Dg&e zLf&eR!H4hn+C!3xpjo-w0^}uU_uA`vVRCR7?#$|ukJj@~@H6?ao_`FI?j@gJu?aJz z;suZwY0a#}VzXM$QbLwJWL(MXh=iKNJ6}qjB=e%$T}!;){BE+IAGNJB4b#*Hdo+~W zALiCpSG06&tP~2ZsxnrF?F@4Bx}Li7-EAlZMwsob$Lh$hZYymvbu&Z(7fk{V0Qm1* z0Ay_hu_=vuiCC`cnGCqbT(;uLL$LcKGm4mOI5T1K0P`*O_GGL-K1jaEHXsOC&oiU~ zrewI?SB5&jy5#;9~Ai=$q76_jVg}pO$W$QH&Qj}T3%}JzwCeh&V3{bRh#WGYF{zh zvet}FgS;AEebLqhMXvcjlX?VL1V|1cV5uM89-)zfo1Nxfw>V9;*zC194K23pZHvHD zxoWG$IvCcue!C32HNyw*BZyJ5tg6i#4#S$rTz8M54Y z6_P&G5VjAa4(p7ro0xsCExTr`9k#-$Z6E;T#k3>VbygVBfYtUcSW>hO2H>!LG1k#> z{TW6V+H}e_9~}AFr~kR2h>Pe+c^A>)yesBbEYNFU%g$mqyDgKt4^ZgEi@EeLw;>J( z)^*sKF8h~SvrE+0K@oaNE2FAR^UTMU*#54oHfy)Py>u6~E?UF|@v$+Z$K_r~*oCV#i$xN7<5NwbvY-Jp|fBMA=ZQds;+G137GD-C$}MDqu;|;sl0? zWEx?t$T=Dka5%qVYSfVRbFV82QIUEJ^o=AM*13=Cto#$Qq~~|Y;BDTx253i&5?r`~ z@e?y=CyM&EEMA-|CQhSti;m-mok1XK#2xuF+EjIpu> z|BA1mw>tLP=8lQ#u2S9><1~(uqyN$ns*Q82?Q<|ZKL~$e_NJ7%)Bxwb@x86*;pgJs)^8FAUMq!+L9i!rnV-Lzu-Gku7r>yK zS-$rb4XW9LzgW^LU(Jizj1^an?8uvJg)*5`Kg?*2Avvbua-N4eqBPK@tbN*E=N0Ql z{xL6L_^87U=zzW2?HhO|97+ND^SL`Sj*QOk#TuS?G9 zkspAe3Zj70)@NV{5H=>^*F4Np&+-Y&01xEhJLm{IDqr`C6VLwF$~Syzlqtu~I%0Bj zQBNRO52SyNBpSwjz5FtW`>P^@ViX;pL)cM zS@@{wxbkg(kNmnsYD?k6Ue^Yv((%=X^U9oKlt8@`G<2oEY)hT_>4| z&xF49aUWL7mHy9(UyLky93O`TJ}%z&)j#252nQ3nZp#^h-#pb4_JOox$G@rT!``~} zedsT_%|BIf(xH7Y2cV~>~k5kg@zO7Sb`JM@@l&r(#`h}4tWQlJ`?71V*Cl6OW}fQhc)0mT zuedpM_jJbJZhPb)4v$jTxqia2;9~uz^PKkc4WVYo-W@+UK+$Gx%>|#^ydcDpSI<0; z8*F3E)<-5nII!w8j1w-0kcxE^kI&sSG0;=6jzZ#3@Bh?DlAH7X^anR>5qesU<0*;- zbk6_T+S}g;3HeX`{)gY+0DCkF9ua`J*S;qo&G8@}$ZS>y6d89;d7 z%EajMryuWwK?6jm>F;nzWbe3HSmwtM{(IwSsI{U&t8-_+12w_^?AL%n)cux3?QwDA_c}do@iDEFKu-nl?PS6V=#kl z<+V66C>Hl#dn_Nl(dJ&7oVIg$GW8UCpA@4_{5YT;hs)x}`b1yplD#dBt`59hW{tJRSre>DR+)7aEUGQ4p)Wst z;a@>g`t5($+%^(#7pk=XeemHE@OG|xyMN8kCgW|kdb@k+*UIrW%{kD$#>R9fN!UL* zVf8zd_=jmrDs0GJ;>vTsGNcbvcA2W@m^WT}3#YU*R)u`Vb7t zQR<0fUX}d}*>2z+01G>#$(?HSoqZ;KLYoH@FrmWa;~Y+~Yh-Uq%Ef5n$5`eo+UBh{ zd6GN3y0s)L)?eXvsIffa@&7HL+<@@|s&-<`Jn*WeE|5Nu*!Z2#JPS%p^!>E|k@YeY zvkD}zw%wP7B|~4w&`0iFsVL@lHLWZAwxe3?*pYNfS)(xfphXhf&i>(n*a+7c zNm7?MdFz3XEr6;ESr(}Al<)PwhnZ_(yK99u-1>u-?$o=U*pb75h)KoQz8T(8 zM$^_OhFVWufcdEPk;gtx?5E1sO&$3!Rc0pM+g|cGG>|~oJ~{dl#MK%*LS3JaW@5u< z-+Z*sL#xaPcon1?oaZ6Y#wVWdyvRuG8ga;Y96!D7ywkYDp=jfe<3_)s$V4kN*jn@r z0wL{f9TND)f$jx4ogWNhidBK)9yX(|58%~aW_plq?*GJgL}~V z%r)=&dO&Ohs)YtA99CETQgtBV--pHedmnk~|58&!KXu?E|MsR}bgn1CMe?m&>M1KC zB;YTc4?#9Ly7qOwVy&mN0)2}BjGH9I+_S(rCsrajt&55LgvF>RwW}v#CLaIHrSJFA z7Ck8CxwBiJk(8VgAKK^sWBt@l*IuowJ9NyaP9D_!V9Rx6dS zvO+LDaqq>oFPe#!&F?;iV_Ce(hDKSzF}i}pbzit>gqe8m>{pLn?|eG{E7{3r;)d+_ z53$Nn?dWWef9B2KugCm}mdXddlSw^^3X$WI=l}AL1WRE<$tjR|v1uI7)2i*5?K+p4 zxa83fw?bqNBtF0Tywl8+c5c9O>YX;8VLIb~uX+;`XnYyQ`%Sa*8i>C`k1K8t)iWWE zkOtIwYj)PNASKXc*KL>rHCGo@>T-m$8R{-KJ_^>|SoR9*P7kUZ3Gr^PZWIjG&4RwV zagp*gOmOdyS$4>J+Or+aqyFsT*ZaqX%<#?Qigudg!aM7eOBX{$j|~Hj$T2m1hfrZQ&=9C-TNC1Ab0SZc=#3@2uJ z{5@hO?mqKNZ#9Ppc5by3_=tZ6U_@m|d)<2T)jk}&ZY3B#;psFfV|VmL4o8PUVOxHXF*tEUeB7cUZ?3*nT_EvneWcYifSlsl}3x| zu=^9`MY>e0E`oiyK#_5@mV5QE9BVlZ*;$Y)i9vOZ({;hv5v=S)R_3)39l8NPu$J6b zDwq%=bd4eFj}|zBjnw57uh`HU%>@qytEE?7->fea7g1al4fO0R7WIKB(4e_x*3o;{ zjtk&4>jVX$6!cf=K$zQS0S<6xV8Tm1k3+%nD}XbP;lL4tDcoJt<=6<6EK>_U7^%Ck z0~kv`M;mNaZ!7OukBqMh)~;3qSR{TCXZ_bZzxijY$A)fs)G*6H19Dq$pbd;{7}N z;-3y=Gvn6=-+7i{YM?M2AtJF9 zXpdExvC#p6LNHDk_1zdQdlVa~KLE52>&(0Y#B1iRjmH8Bj&A{d1po&?;@1TsSES+J z)(#f22CqRA!*b@FJH)ErM5XYis zB2v`+o8}^sg&o#Op9Ee^IffrJ>%TaE0Fax$_~HqDOJ@OfAk>ZasR|Y#4x2(Hu~Hnp z!1Kr)kct5+WcDZrGJuU^`$ICRpZ}XNTEmkmqzRn(j3h`DYrvzc^9=-Ml<4OE)-wE# zLPRHH6IS=v2Q$XP&O#U+NNgChaPxX29cirK!k3M#UfhTRPCGX_bmyNDxvQ!&;DH;U zYO5MEmb&qRuNc*`{W)VnEQp!`Ck4RvF5SFXOnaa(DPGCQ&b_0B$h<7)2J9OlA4lx^ z#jn8g>TXkVv%MUbr;E(QtEXO5j+xwy-xx#_jxxC{FANFVUlYjEYY)$5*0OX74K2Jr zg*)1u-l3JK7WqOMFjwH3#_}V~9!Hw}qV%g*i4Pa59Ou^WFK3LKjJG3kNX^PO|)U|xG3vVn{4d9G= zRbuP6&o>gk-Sr2|W}*i}Eg6o_m*50U@G~?9%zmmqs41Xr{R}A!`cN+r<^FRmKxJ@$ zq6G$5945@kRD&hTPXVD7j?S|Vfzu4NRb0K6t>}$mmn}dpMC=;Tx|53+Lh}vRMdVtk z@J`YAFPwmV#V&oCU0u)2m(ugel6Xa1!55v_Z;y_DA%I#OKx&iiTKAucSyrv}f<-F*8~MScTupCZQnLvz z3-=oMOlmwtYlhOjFhZCL!>%jzC3iu5NNPcRFjdh|E>fi2e-y%_uN+xF2bu!Nlqz=* z=$C>GYS1V{dd!@0$nznH6TanK!E4J{*91v$nI^&2_6R>C*5TR^HnDvtNaWb9A{}MM zr_TGWE$_YW+qXC4w+Gt(nwq9CJb|LI>0K8v6+1O0PK8)XopV%|n*} ztYc$C;3WYW;{O?F-#0AQSV{kKp>!x2_dou2ZDP*EYk#@MZj{V-6w1t0=#3t_A@rj2 zHrNxT7y=CD=VU47=VbYSg}vL8*btl#z&6E&@&5`|0%ZnMw?0~kgIdyC|M2)K(Ou1{ z!E1!AVr<<;1?W42?ZrxWOJ0%0cYk!RvBs{EvR@6BRf$S58ceiayQwmi!^ok-i*Y&L zsA+|Ro-=6RiGNLMgvp8L8k$2}?KRR+4tID})!0)d!`(qhybO~1_1&fVC5p!2J-f@F z!;L^ua@q?5B^4yNw2sOQOZCF%>xM2F5su^Z~e2a`2cQI9=>$$pZ)v;#d3vUJk_ znppDd=wm#DBC1W#|Nf;`2_MKZpBzYBf8)hlunNOE|CH4SHivLNbV%MpTt2$FWCcRh z;aY zQfE%1HtJaacu(NePqK!M4494Z2j^eLQd5WGePH5%;nzdU{Pb(~gl1f-pe|-AxUm8t z{4l&N!7%4C3$Z1r$ercg1m0iTW2Ov^4kM`Ve|^}z$D2d3;d(jQVYTP&Y1lq%z+4(( z&9dz5u#PB@FL&V%W!BXq9lhF*5hFbe3)rx0yRIky?A~;3W^cwaW5Bzohc*=TImBqZ zBlhR`eW2zy>uDs;n(+)?#NJ#+9enPe*7Wxc?3D9@+}`1u0A?}gu6RA=Y2Y2k`v{hL z^|Tvvl_Snw#wP||yS;qSW=GDh4xr=Kf|(fe*xbKzd&1pla1J;P-HP1=GyWaQ8yv=8 zW1o=}2X$D2j$JVm&Jkd04yi|8&4ImdvmJwXC7ipqu{n=vbiBRZir{>la<-Jk5$8~9 z11N|mB8!}D3)$RI#}9B)5Pm}NAMNh^j~4KQ(0;6>4sq(sjFzgp5_lS0V`s5Q#8u&v znz~R`T`{<%1bMLr?YFDkQ$3huk);$c(kE11m_{UC)uA=KF%&DV3&UUoUqu^RhXPjc zW-dqd9@GGq5ZKgDiUTVge5)%%ck2K8Giyt>CG{zQoUAKKMTtBtE!iPr zU^6-tK|iCR+v-YFui-p95P@Wra>h4STF>1hBVFEDzCDsS=FzhZ$k#j~ja%)H>^S&C zOd!EC0Sk(FyYxu6YT4eDd`#R4@IhTig<#VS>H}uJ zqZ1jouK4#0HK)PMqr0}brS*!_1IJB?7gX)sEdE(Y4m#1Kar&L3A5qIhO>t(w^Wp8mLLG4%^y3Zol}w8M>u^3_H>)?xaNvU%&UqT<%3E*6i8=v9VCuK)K||hg zKOp{@d&f`it8tI+L~)cR@6jD(-FC^l?_n!*qcrLQ74WvY1GyndyQM!qae-^C_fJPd%5-u zxPOQ|y#d7rH^znrxgzaeKvS zUua4I7$P5C0C4dwfFn8X|45*P-i0IZ4g#^gvFKfxkbUI%FLJV;tv)}R^Z85abAQg~ z;qdSV03OTv{J8r3%bd@Xu+!wAQOiWNXs8+*wcpC-357!Zq0CW#5eD!<_V57`dOfb6NW>@PZVmyx%o$-uIH3n za^@6h(Af!e)TDgNT8pTRY_#X`z1J@@3W_yrk_X9_LXfywfJ6^bRnVQ-KD(x;h;Er8 zAZ|9=XTuBZzXJrngm>YJ|Edt^P%XEBYB>Nd#1k0j&$$@n8f9iS5raoGpSPpO+K}|CQWrX62yXzbc*-r8F*6OqrJxV ztl;>2jr|R5sji*_eZql1lln2n*{6!_2K@B^*lYUN`w0GO7kuxOIByjCJpSZWTF`-l zS+3r-7#=P~fD6^iIr3inpgd);$>n$h&&sAp5Dyr~tM?WW)*Bucp58|+O!lzAF%Zoy znNJ`02I%R%hHI4&D^&mSi63rx`q{)69{aBLC8)ociT)pqcoVycp5oX z6HjcoDSM%5`w0<;U~oG(ld46N&J?M|{n(t@&=LJ|ki=~-lBoE?#|bDTzX<>hh2*z^ z4?Yp+POCvZK-YAXTlHRarAD-1U)|P$N$o18+OY*VgS!{?DpxYA?a^-DDu3PQ1YOOz znfwU#%`3SsmEeVwH(G+iU3pak+lvM=6gZbfk6wM?(2%T!T&huqeympY>;NK`pbv7K zUSO3R^_&MI-qp!^E~N0T$#Kiy`-88S89N%HmhQ@=u;F0$XxXqqOC%sP(11 zwK@f4$=7RRy{9fF_+%VhLEZqlK^a4LtFkQTgIbnjVOJnUPnUyWJsDoj;@b*9bMRZ= zJW3AH_S&Q9qs4F(x^3u}}0Gi#&ukhQ`3k=1Mc(0b7NzV(3hUF&}9Th@Knz1BU}-PT>!oz_>Z zFI%@;|6$!`-D<71Zn1i-&suA&8?Z*c*1E>J%35Vzj&qY4>$g^y)nP5g>e;pyS*_Nm zEGsn?NVS@+3#P|M>tyRh>-f|GP$5KhNtHwQ zOf}(;b!6&7{v2UVOkKc_pW>gL{PO|-G(kyEUC2Kd^Uvk{a}EEDE5@I>{PPz6SdrA* zd|r)pTWT}^{FZ+fVySGTY%Z)FvZJk{*mYvN~~;$g*rjDztNXWahylM>N|^6*F@PFPG%cqIt1>TMPW zg2SnsfHg=wk!2s|RVP!6jtKiFOzN?gPAsB>SxF}M?ge-PLLg=O`HCVaURU%+|p9j8W|rcPZ`Sen2y z5i_C^B?yKch-I zi~6Vn;fPpud`FNB8DAzh@RAl_*x6tkWv7hT1+6)U4keUO>c1dLwNE?r<%@iCc5`wI zXu>A_!l1VoV?Np)A&{DO4$NC91^TT zD0=iJ-f(~)^iXmya-(XvG@#e?8aFo&wyF^ur1GM2c+*67Y%A_fepHWX8u^Q3MPB}* z-PK+$7I5InW zB_0Y1T1+O^x8012gRML9LCN|3!E7}iuf4t-UaQH)AAnFySfqJIGa!!J{p`4pxA~6S zwGc7XhqT&2zt-@+P?d%?q*1KOtO(lLS_zS%w6*vfL16SaYAKUwzjEaX@cJD8OCT3% zf^|81I99s49Os_KKpnYs&-;nckWPa1oUDA6o-AAc(Y9Wm0Eo`)wGS*H+T=17FK>Nc zq_1uUp12%nedmGOBdd<=Lx7zs-2Cyu_UXNWZ4tnz>2+zkW`jUH5BIzZ0EYe?k1|KA zj+}(^IQTLVVl!HC8)kS!x#+127c85)5#7l`$5u`PZ-cav(+ya!D=F*Pd=j#b=h5)2 zHiamQnYfIk9fM=S-}?FAd(v+wAyN3>IsZ5k{JxWWU!vMF1|P&s@%Xf}VtOiWaRA8H zGaK6_oI{@YgO6}YJ(3~oWx473 zHiT>84zWAosIn`bICuh#D|!doS7Ku2=N{3neE=w^tlFY8N2kq;YFGccub$1IQU~}i ze&fjKo`6^0Sg|LLLk~D65(@0xUy-}ZqKyjrrrv{Qbk_qYCF)37zkQGr_nFxT>)=N|^;vvsgju@g zL9C46yUE4Sw4qJqiI@5rGW5;LSGM$-aRZa6XN}F5G1p=X)Z%Wg79kjEU!)1#ca`N_ zJcL@`G;3EM)N%NN(7;Z748~euU@OT970dMr0W{S9-H1N6Zt4=BWlYww=UfQPlmoC1q33*_4@m9 z@kDuC_TPCOudeRWG6iXSaqr^Q06e)G0Z5P50;>+&>n!Yu{8*7Vl@&jp+PMnOI!P=a z&Buen9tCDfHRWo%Mqaquc=m$+PC0kgs-KHtr<5kuA!6kzGetcgd0L&sXqi~Hbt<>J zkZQZB5q~O=jv%$mO|9^!@*p!(({Acef9g#tb%mQ+?oVB&QdjmaJ`qp3ch2;f;kLQP zt6l_PLED7`S#nF)QBb0;QXjo;vkn;rQpV6|pRI2rfX6OauQuCt;x{(B3BoU0a?ky~ zOe$eD6Y3xECs-R;dKXKdqcUw{rbwaECHLgkP`GMaB{7m|G+L;_$nGlKht@Jy9sJ7r zr7~}?U|(n5$)}uJSk;2o=4e~kR^dd?#l~t3`|3@$U4WI4`r#&fSndc}4M_OAKSAr3 zRt*w%`V&H0Q^!tfblWBy+Px`_=NSC01EE2TjE@QSOX<;=u%7%7tL4@9!7z3xWfliN zVekslR61nM4RWu_#d+7^UED2`BMfQ|jxpAh;xXlh0O#EDpG=g%Gl*9V^>p#!FrXFa zhK6Xc=t1wx6>nFlpP}mKFkC$}Qrlr*LJo+h2+*_W*^bD1glc+PeXUVBk5)fZ)K8uI zIY#{)tA37CKgX+|6V%U%>gS~1#XQ95A`sYvUReY0&|5)1(W85z=BoeL#kt73PhFH% z7rHQ6wFc$);8Xb&YsX_Ht%&qBI7hMdJaQb} zYbUVq#9|fhY<-nru~=4CR~D`-3FG4W50LYdLnJsoG8}msHU5luc6yPMn$w)2;O>BqJL8s3an9 zLFL50X`*x8Q_1yWzP<$Ou%uZAFB{J1nsljkRMLC*f#SyvvcLH9s^`|zo~`WH#8xJC zv1qNS(W;x6=$_HSKpA&@we3a6qAk7lqV7zcAPsuif-3%zjxPpi@`(+OK0JsjnH>f7rLtLIu0w z%`YPv6H3g-Z(uB$TOfk3MrvNpU5Esjy-&b2>GG||kVQPhjSYP)Cw25y-GPxsoDHEUW+g90EHN|$+30xUg|EM4ULgt`8I{vlqh;*~*NAPXZ>@V;0NW-w13 z2Z|aLcSn8YjW27F! zUuDyRIuk!Mh)M5wRO%joKL2UQ)U8N?@_nnBkQ3gF{~pP$$ZbJs={mYYs6fmxh(sdb z4jIaGGpz7sxD^@T)+|^0sHHq)t+onq!Vjl-x0h*R!Av;JQ#a+hySJfakAR3e-X~wnYg%_-4$NEHXk5BYs z(-oVQ4(0LzD`cDLq(D_91I9EQk40wNj#{8eG?gCiwruR0HgPN5Uw1efqQy zYIrMZEJ|ayLpWblvGkI!eWVP&JZIo@D#RrxW&%B#I>W^YH|O#_E=JGlDel?!TO%F`6b6Ca-w@fLS6fh%GYsS#C=Fy z{cQ7LbOsBnW7%Ez!~6vq45N-bqbZoHWR4YYq<$xR&}+a3sAytn$WzTlV)Am%g{MP^ z4~_n+6V+UqEL}po!9=HB+-AmQ-wFvlGD=)|f=5_F+o9=TV zjPuXPDz$mZYt-6COa}uC^IoU-x|P?d-!W8!^4syS(p08D+^mG$hdaRPQtozr>A^`K z^!e}KtNYkr;t%W;)YG9!;j51am#sdu23ZDX_40t+Oi(quJ;TviYmGwj(P75RJYzc7aNxoFS%{_I-DVc+Z@*~n%XhM^*@HVW4Nvw9y=Hh2$Zs9<12v8Usia+8= zgPgLTT;66BAK?exA7S#=qf*8Vedb@t{YV={C?Y6ZumEc@>YVPcWyBZ+9T= zsb?8!RSJVIXy*9QO|R@)4>eHQlQ^_YwZH(*64C()j+%=-NEDb!Wp6}1QYT!M@E50T zIY+2({&w8XX+6xlaY2l-<2jon{LC8hSyio8ns9Cp5zm7PRc$2csuq|ALsQ!$@Dj+X zIXx*mVOI4zjr;u0>?4xkmIYVT4xW9$u=?LsIGDlk^9vwf=*Tc4RICpH4hnR;efv^! zJ2Qd3@z2c>ILXJEr8(4*4*knMpJh5lFk3cQhJVhlS$o7=HGf}FydN3>#+-G7Qu8r$ zD&pE*=fn$(gxm$AIMPH(7}a}bz_6<@wfQq}^teEQQh^|=X&j>n4Be31?s{$T(DCp{ zuHpc!cnZvb4iZ}cE>M~=wN(+8QeJYSyy~I6^p79y7}WgW0~ZnHDHPO?-EDAq)ak3t z+giy`a#?4E8KzV{wm^24a7aspq%_xHp!e74YG#91MMs{{%PD=0@)t8IxmP{`{@p-M z_GC6;Pd;cv5MVFF&|+8oIJ({A-iX#ql51PCoNtM*{?-U2ZI7n7-AuRO`0=e%Tm1}A zI6yk}FP!zKF*272sAtz#M~)jbd}7qa;6k+uD zM}-tozoTXMu;(|8dj1K7H{l5;=Zz5z{O`fMFdGE9%^?>*??45D%}z^r$5#{>B!jiP z0B|ZQ9V`1>4ge#t_3i^gHJbCqmu{V$56GPSgX{FQiH>MpY=WzcDVMdFP;#`b-(wP& z5#l~IZ{G{2OpqDY@z?I4uZCJvkjtxEST^4a(YRp8yDy`mZ5Ed%MvN z-N_rpa4Swt-hdZs0(yy=bm<`wz~s|X`9s0KAC(-%hSC5;sk_WT(-iwkXTkA5SIYWy zHeYONEwwso-oVMMoYmG~sTIfdQlB{k0j}{+`?ZpJ^WsG}Oxl}zoKS3SsLu)HR+R4) z7ft55r?{wZo}t+RcIvDXsuWW_j#<}QNii<@P7Jv#C~TXmgRIz$;X%?e?6f=tN*O@l zprFg#U`Ri#eElI^x$O|l-aE+W?v8vr%~iSOKyJEbv9t^C_S;LKU3qST;_U&X_u3VD zq6NuTLhA}Cj;~%j!OY2uU{ks zB)2a;X8h7%hM;pI&+oko85|$Lq<czjCAj&J|G)Vy`hP_-uRHWqQaeGBP<0!OFF_ zJ)4Z>Co*GTwTzXPu#?z>N+@O=$r~}l^*`D$bF)z*DqXnq^CRXum@aqnVT{Mf9s;KES?K#~onPuV&-@#oKP{;O+X1x4sgav2q?i_DIb z205#QZ^}qQszfDpovh09UbMf~#Px4&`Mo%s#8)~IafGV|1Y9DXR$yw-Pw|yOaUH)r z_zu$j^|jxAp*a-4BA9>*)TR@1eEa=f*=C-YH{+|2%XOZ4C0@jNCiY>q^UNv++L0(s z`Zh`YszALP?D6rd178r%sV5j$-nGo3Dv%X}OsUFlP9ku7zDphIAb-9%YytE+gTgx? z$$Fw2f_;DjEF^lr- zwYO)~gVBHS`tcti;rc-dBg(!~*+VTaS*X1SZ7o|E_c1To1aUcU+lbe32mUUw*?*!~;tgWw5m&CLjaT zl;gaVHcHh|nqhR%Cr=Tn*0y%~F zZsLTaKSETc_-6wYxxr4vZwh=dW5ZzLC8Nm*U3vKPf6_S#>d*h>j#+fB;8V zvjsq!(c2m;khG}RzC=M=0MecST!fUjVLdk6J4nk2=?D+fwgTYPYzRQgyQ(f?ap|o( ze#<^KZpBpZ(EM<(`5Cc_)#%CR_OUXJ=c>AjXhmJQ6^Ra0L;=+?RX#*$tYwp322#6f zbL$BFOjB>o>J3+cnRe3VR{lU^=Fd^;C#8OBdbirG46KBm(82HxHDj_aEl3lvvJQcH zYb^)GAvw+Zhuw6?TYUf*W=#Zl`suG@^?i^RAe&;cM7XXjwY&m^y#RlNx3CNx14ft% z(uo$UZe~*FBGnoe9a2|el|{?(7ac!bN<{ZV$8W{NRE#dN>udLQXjl-I0(9Nwww8f9 zTm+W>(o27zeN6oGIn^SFKxLgr%-D(A6W?+0OK{CNwFt5(lbVIU7{$}HXeotgNyK^7 z&8w7*y!&xWjgne`Zhb7~aCm8Tg=<|=w9F;lSf~vRd?BZSJpr9b{Q`ni#&u$^J>4M^ zZfVAbYbjQyE;5W%tCmV?%P_|}*6wj^z;#1W@_Nl%0_hS+JwD@f~py70x zv)02*%oBwkX7&QzRwwiW97}KeL@;x+G0#FyzR3z&If3NxB<}qxqfS-T4FNM$Wd2{Z zn@P>VD_`Fd%NqqeI(J z6mwKbY72Bl)K-u4=dpbh3@xNam+%Djzz8GQqA=N(A$OuFqIv=*qMbB~hMc(PP zzh2Q&8PY*ZwYzKYN6-Fx)8O{l&ex%bt9lFd6HWS)_Nkv=JbWRXr=wp1Rm0!UV^#a7 z^e&zQcFNlaeU01~DmT%)n8D|Cf-eN@s$P3?PV7O?$OdCKR@_PjhcM{U_e8COVFPoF zz+7!>CEd-yHOA^qi^s`K=Ux=$teN+ss3fdLMY$J6VM%i@ib|$!%#?Fc)GM9m>ZX^N za|iWHQuPSjL0uvzl%n~rjC!T>Tp9He_ody5@!Nw!5W9-dyufJAe3fU-VvP_Ol^I!` z?#ftSbPDVmame_@Z=O7C!g&9Y>~&K|KDGe%;3jAn6XX9mxY0f7KB5Eo!h~UW){K8S zP!DLrwR>Af>>eIo&tE`u45&bLMBBr)UX-Nr@DdnnKTOG7A0#%|pFt3z+V~v-kO6>S zvD%}GNvR&4DE(B32P?*k_i<`~NX0qjwRJ<4iK4C~i|H_gnjod1uITl!d-?=d%u@gP zE)MVEXcl%~oE0}-c|PwlfnbBgVTBaCy|#$T4VL7&W{l^bKgDX+LVP{>a;jH7U1rePW$T_wh*e+&6Xb$@o{(->Oof-dn4wQj#8iTgnTjIRf=t2A{Jy~V01W31f?@v( z*3qtD^~=xKC_lwjJa+MA4%G9cmh6FVO0vh|Ig(ugj)kk3@dpY?_Ejzbx>6ph;vqh$ zQl*&pt@&7-gp~2EsMnr32p|873?s?TnSR!XefkIkt}d}j>~m+tHC%?L17u?fLy^{z|u-hKm(5G$YYd~jVGA5p^1xWuAcIQ8*=0hoUU;8lg0Rb)n}>( zA2-b1PafY*4ZTZ;%u+@JK)d~|i;cuDiY|N6Of>)er!O|srCS7fMWu&!;rs@(9&_jq zCN~#T<6_=m+U74^@=PC&bO|zi)vE&&PTs@cyJcIVDSH5Rsu2#$|5XCqod9~V9fy7Y<0^)3ZI*pvi4{4JxM64KFSfQ08AvQR``f=l z78yP|gk2ZlBu#tR)s%}#TpX*|^f>s3i%md!P6uzi^N3gargr;AL3$aQ@vDOd?dRr< zg6nteCjcSG?-=fWykE~y4Fee-#rQFDMAg zzbysSeJ+TI4YuXbj_>#)!ur5(k#Lw=1Hz%-TGe;b3%o^BF~R@6)o?~mJ;*%{mn0@l zC_cbUyn5XozX6Go43(Q^XlA?>F?L(&aBeY2vAC2Es%m}k!6PhH%lpsGJSb30#u`tp z$yd_hj6k!XSZNg_1p4p69T4o7Z^Pj&ISazl5T6PZ7)a)weSngbcq%TTgCt&+#!FF{ z%<;>7g8?2Ds&Rf%;V1)}C=cMC6aXCc&foN%sRQGW2g_ptqhvdPbO;Y+24taGw!uCy zzPUhwh?)3D&&DUJGyp!@Z& zPlN%k%pU1SVB(I0Z^s2xeRdK1Z7@8Ru}i>7U1|IY0QQ0jQm=oldHTy(YZcdDa`PQ9 zU&YGmzth|BXFQbGUvK{5H9VBm4_W;2bK&5iBb9{8|d%2E%Zx$`v%4c`6@^i?fq8B5=T=95+wN@g^5MA=8~m<{!U8SJx}68 zok=_-1=LK=shwAe!J*Qh4Oo+I4GI&akas;9q&ka}qpFCY0FEsL)iqMLKI!GiiG>GE zoZ?WujP!b*?aEGV&z=6i`NWN}Jx%{v!I?&U#PF7IYQ*69fx}M5mr!&y~@(<|WmvKp;6KV6y&WklfWw>yQO&5|6`8*IfH2n9ELD zu(?mQrdb!Bef$JOnGpOUAgZ=XqGeW?%C_oTGQk;;Q|oPa?mDGULFOVMsYIEB69h0r z)xK2nq#|mkKBvVJ2`**LC(H;!WcQKGUW>ltbqi;qa+ikH5Esa`}r z-8+O4jGA|c`B{&`;xW`rcADAu+6EE?Md3Ir;i}a$_~HOqqRFHVXLuY7Ht}9ix68_! zv^BZ;zY|Iy!LbXz+LH z@?0Ao#cTb^9vm-2;pjN^hM^Uh@fjz?Qv;Y;DNBlZAJf5EA$ZhSC_H;T$^TXNTT^8I zy0HYHI}3-!ChL(Ux{U+Q8Plicc#)Hw?0pS?`Zaq(GcI8Kj)aZu(VzY$v7TZTbL6s! z>8|_gNj$l8=BWRDe$1X`1MsEzApg%Zhi^;#e(Ed7h-JZd@c@@c<1Z`Th`)m0`Y%8I zN_Zf%!x{+-L?UtK6)y};%$j%i<1pfk`0^8dyqh8k$-B?lmUyzL_G6uZjT97IPpKJf zuonfSjO(nb@{UAiY&&#OEI1CoU~6CgTUwYwv_Yfao{j5$6O?l!Oh|3<*A&1>myKPY zIHRCM)+qB#?b7A5W9!V?UEyg5E(q0+eeInO!Jg0o-+bD^ z5PT1fdbdw+k>D;4gUtDCij_a~y+8!}ucgtol={5{015jZ7GV@cQH}~xQ9(}(!eMp8 zZbElub=4j_pp_hmEJV-`BWLcOCWPNO0%pFK@wh z8$D`Iba|E3bcQ)4bN+^6SSB?QVgAgZ`Ezvhq-YDh654wD*#mqn*ob8B~?{XFBMZprAS)*d;|Q4KLTPwqQm zp#99N4_j*7`wgSc_8H}+Sq}NXLTMTnVruN9+&YOd%E(nG$I5sD)r+d2E93GOP$_DC3X8pcf`;IS3Oi z5AidwPExdvo`JG4qe9t(;CcYfk(&&K&-$yPnsR)KaYCSyZ4H`-644ABCnmBxPVRr*n@HRgHJlHy(M`y1Q|MN8jc*Cv#{MQ zjdiqA40Lg#m}(>yMy#|zf^2NIZdK!p7z5rc?AvF=D$%+GD&M-*644B6T@%@D-GNd$ zcE=OtUqIbBit&VsrXLMcCbG*EvL#+2Cv{x6A}h*hH^ z7P+v90YISg)vlR{X4n8Qk=?e&0O0avtZM)M0Eo5-CAXmQz>l#=!4{Zc@f4zTMhr__ z(k6#uRmoH>=HhimzmL*j>{ov+NQNceE8Qm@Rq5@rMJYmOz1-p^f-i zJKOT=ZrO|-*lw$RrTXLV)`-}8j7*+I<+0ozb>_k^)IzI{a&U-X)xyxtmml@rVXHQW zv)-|o%YE0taxXWvW~pz~ZN9X`PT%@fe<&)$=JT_$%pvl z;|9CD_kfq^0$nneoTT`6|H@wzZ}u`h4>?r!UF1SQa5 z0ni(&7TR(mIv;mW!KjW!0E0_W-WE2g)z~NzV}f%5oHQ}gb>*qqtG0K?zA0)ruuv`c zt9{^-5qk_Z=}MoPga*WDSvBX)6_713lbx7_V_>VPQFg>?X8uMdbp+*$1lsBRyH<@% z0pliep{Tdo7Gf*n&SSlWgIVEDG(>K)|D(16?8(==emoK199-w z#R!)8Zz^m>@Z^GRhZlZ6is-BlHU#}a+%b+y|8*&lv`>vI;V~5cQd~p=3liCd<_`kks(jmyQ=s=?y zw#uv?0rNlHU2z%uamQd0qOry`#*&Qw^YO2`>bv8oRmaf8Ae9f?QF2uR3!?GJSV=f5 zOpGUDTjvGR@OrLweju$U44BoD5HqZSb%F7TcW~4K)B-G)RqI&Y9=N68 zSfDo4zjwdAt^634~ILo*YokpalsXR7F9#{)O&%w_HwZC|F`D1xaKEiiCNcRVyqk6e8YeKdoKE zy;O)0SsBSY$dglKmyA};91~5KKcrO_2RbAS1zgC9XjPRkHC2o%cVUJ>K99|Z#`blc zk_M6Tc?mvb&l3kQB94}@Z7q*=jf=k`BJ9Iwp!GTka(XhAO{tD8)<;5*YAIbBahidG zhpsuRhCQQKk0krpwS_whVjNp$+73GNtj16t9q4T97^=%Q^}3RYW7V%AZybZu6MN#` zmw%ymp|#pjsf$P3NP9Do)&^;OH_uy9g+bf)vjSHLGFUWuM>I2?|JF$5zsW_Dqi2M! zVh|_l2t71>d9ye^BB}2?{sMI`c12;}$jYER8zlsa(+WKBXo2tvOUtKbB}x1Dq3fkKGp=?Ig6Nm3XRBGzPs zOL=Z*BFe*yFskA}!Zp(rK}S*{OM2XQ?f}M{+cf;P{r?$1dtQ#UOv5Eo)2z072P$@=0!;I>xq;sFCKP-HR2 zrltMLw~f|BY#CbTU0=#M+p4dGw%XEO^V%~_?K-y|?rSftTXp5aSWD{)V+@I_*jE}! zTCFOJ-2^!R+k|hSER4X%6*B!QBb5b-7`l%ioZT4;@}fq+jzlE*Q$iQYR0fjt%R~t8 z!iaUXK~eMIUlfr`SNPOd(;Jl(rBA`*z!Mul?7JVakXowl*D=9-;tfB62d)gtz!r-1qu47Srd}@Ate`mskDfaxxApyjHFBiIf%gDsK{sAi{>g4FDp&g0xuoq3Sb6?-r zA!28I_)2S>@MHX*YG~Re+wziJt>~HUgJ-Yac6(uq0 zbtTkFPP>SGe)gmmCDA+|Qwc;OG+94EF=0z%Es@bTjTOC8KFnmM?>Mx2Pf4`0$$~2= zoM#G!)5qM>o-ch?l8R}mql@2)meeRD~%`z9As|`h**58+z@DZzv1k zj9cL-iANatH^Y9e#@RT+vNB|{HOm-Q5dOZMT{NPxOgX@d+av?*y93#EhI^2HpF*20 zObX&rZREH&ki%b~;1}+S_DNZ%rWHCY14(-5<@dO%tq=^TpVFMwI|`!iLS!gv$CUn6 zil@Bn(O1_@orS-m2_#uwJjtGo8#Hk7nGNkEv&MZMfA}@KJC3j767#JG48Fx${h*P= z%}m6a9Y}+Sv;HTLW>k4fN^T0==d$guSl`|AqIU>fpE^dbZyYu<*c5i719q#GT*Rn`XQW)r)onAm%&Qw`SXH$|U$=c! zX^DNX>dUp&B{X?+0JRj<#I*waP?v{bVoGocK-@CTtj_P^`s$xmE<6s`C{BGJCit>Q z^W@#i%`}%PZ*>|$FjVn&)t-FUr*}^TQKieUu808_v7Sb~u1#SKS`B)aLXN?gm?F-KtXXPH)xLYixdTuR_8&aij#$qd zNTQR{JuGB+e&-#3%WH=Us;<(eR@LIZ2&b}aHtR)$7)nH~Re>4y?T^7z-5&bDJOq@m zUNSMu1veOrQZkEXvtAD3jQphU-T=-kL7b+aeEdrQ=T#HOUq+cdb<&C)*R`O&H7_wP z-5iK*oF!-bCSJhuBrM3j`V@&+EV;OQUbKz!|KA=26v5$R0L;uoSHL?V#OeaOYKFb) z^>YX61Nzb0Z4Jv2#O4oZdUhy8YMevWW8>-w4M#_6hbBE8z_NZU0{4PMvnCRkk{;& z#~uiHrJMFa%wkbL9dTUP+RdU&HEv9raRf|d>CSV*&+o;*{g-~y4B{UwQ3~y=+025-x0xy?2-2iH z1|S6+Zo>6Y*qy)Muw`U2H&M(h3oDHwII^|KV8yHe*bcIj8f1q;gq(UyUHmR(ov)j? z?&~Kz%rm9p(b=6OsjvmyT}cxx-wSaGJ32$`E~ML1+k#dK7DY*ySN&Y;~_e zCr2ZR_IPS_8-1w7M{#>fJnyAELUDLg;S;LZyc{RSgzUOlL+f3WL;p;O*0Y}T8j;d$$bA6X{ngn+V#*ad-U4%+ehMIUtw)VYYD%q331nq{4S%o zBI3G?3S~;yV{p5M1L+Vaonn0lEpqW3&ljAsg;S%UOSJXPd*uuYHH}0NVIZ|TPV5jk zVZEFUrLk;lg<11XT8H|Vk&Z2!prQ3d+`1*Q`zxyr zG&R$U@@9)R)4j9$zT7%kR30`>_?n_vLznG;yM;aelgt$;+I&FDE80W6`IZaU05Q0Y zil@i}BM@k1JWYe2?sGTdVHyVbh4(^B@jy*k#9D(&iRWPu1p#7{2N7~g*BycTjLy#J zuJ5c=vod&Fs9IvVfoDC0aaA*zdE!u5u$1{!f8>iX5qo8WAz35StPjn0_0KV!#76A1 zwiGNcu}TwTg;WxP-=7+(SH^nsWgaLF;$;)vVLwc|U^nj6`AbcjQa!i&HVom~Vp6aA z{;{%e1#A-ksY+1Bq#r%8#vwL6v5v?h7m6XksVgLB_t6f*cdRreSu9)?S`Hiyb zjfAr5Qxn-ID!JqK2@1M2bWfg$x6!>dNElVSr%#S{NH94w=;?w8tiCe^+AnlBOG9O^ z+ybaJ*jcVMdEutwGb2e047xg*G?J>$*(V<|GFL2l5MzCAkP#LmpJFSQVS0jssMI}_ z^D)MHa1O;Ixr&W4`d%CqgW?E%y}^RCT73~n^N%NMgYnU=uTQ?j>PZ6t{>A&m5&P3= zjcbjBu__I0e`(~#5HJ?QCfMdleN*vD7W`t8EJxd-TXdw zVD1htTUb$i<`~r}fyF|!(%11N`5T2!+K7Fo6=iF)fi9O*wY#^zN&GFHt@YNDrOnY= zP}sL7#?%vj{8IoQ~5Yn$P8CU28NWQ1(w@0gSJF_ax#jxLDx!dX{vT$kII?mf8<28vq8 z`!uYIvoy$X)gk58cY z(bw~DGpnC)(iA-P>|Ok)r%|wjg^fZ!gvr=k!jmUng*aSM8JyeL56i0ueRngQi2B9T z6RQeNB6qP3^-z*#FZ1185%8h82>8&<;-e^@EcMC1XyZ;((xRDIjv=ai#w#Q;@Pioo zDDggH9{J9|V$I=8PrqdM@sIdhSv#V1csK9M86@~f;t?ohp#R+4UgAO*qq6W!ko$@- z1ARusN=2A%>XO~qqI-q#; zD@dyrNP87&re{&{XgFC|=_cMKuc0%LTs@G?C(DssBanPClCgzNo;S8!9y>tp4${E~ zly-z63uj|>|GkAuETi?gn73=?HH|N!s%tO7Xa)k}A#|Y(E5l0w+~A5|d3<_Kkw_IS zuYSnp&zt6bmL22bvUl<(i_hFRCT>#;=i2_^?3X2xEHC&tZFM?&OG_)m%*4&5VF*)e zk5VFCi-d@$hj^{LLL$T%Zp?wK_+1do)+@Y+&(RDVY;7cxH#II(_fH%O!T5{}#i|S9 zbHi~M!YNAbr|||mZ+>_u6~fBGTtT%=%rtqYwKQhM<%xuQTB+xn?YGv{SUVqf<53uM zM;hu-C7N5un62!Wou(c-u{H*f`uxxOm;3^mJT+7%V*!eHq&ibLQq?jFD~@%xY8xp+ zd8lI~73wm@`f0L+l2Yt8)u`q$t_xzld6K>;`UpgjYg~fhp>-uXD>${z|6fn7R!Y>s zT@S0Zu%Sfk+~q47%!hNXe)UgRmUKsqwP;sF`>hBWQ&J)$T39rLo~T86_x*MFu-sPQ z1s6H>Y>K|PXP}s1N#@uFTFlVAJ-OIT*slZqTW_8rAYBb@r)Lr z7`7?0fmR;Dp=lQcyW~TAb&Z~_pktHrqiL!6(YhjEwRHSSay|cq8K7KT7}5M?P-CG8 zs>F!T1mi6)>e7CGa41=PKgL^gp_^LujFf!i0D0U;lUP?_=lR&JkB#s;3roz=wnXmD<2 zRq)NK;9JuQzBNnyEv}2lVX^XeadWHrQRF_>z%7RGY+^id13!<4ovlY7^x;1chr>u@eF(1zHX! zRI`*}3Em09u!O~zL%C>Y$B}qM>n&{Kv;k~fb#I=jrLT=q!9tAXfZ(#Nwg!qg$qibe z{8gRU4OcDXVtkyDQ^-W$W*}(I^b@JPhj_UxE8D)T&!QD!0VbMeON>q)1~@U?p|^hV zQ`-{k{QVqQ?F{B|_O&tdr{B>3vndX+D$Cg3JQNcp^K{J|9XKD`&p{;Zds3YG4+Iv+ z@N7$k%HB3Qe8n9k968^VWNfTE82r1eiCc(evB}K+n{8A^7=y7P-(3(xFm|guT5}gQ_=U&zN-G%~wkMU&Pw?d7k>T=j z&tv&OJUO2OR0SR?4D^2kGKiyQJU&8C?$6>?ABcZzq>!O_2ak)YxRh>k};75oEWL%3Dv6zoq zg@x~oyQhuT6bGkrON*tDr~J9e>a|mBzB0jv8>2#oc16!0A+)RR_*gTu*J%$^Tj{*b zD5%Kvxoc+n+{IzzJ>qleHQ>MIeNy0>wO3*ZIAage?cK$E{n4J@`g3ft{TO1lpTnj10U{)k@tLB|^h)PFK77D_mMNOZ< zrr6f|rVM7DUzyGOh7Cx|RqD3jttco$A%aG!4n`s4{(%)PSdM$>m`{8(H%)qXWQ6r1c633f;MUGXJ zsCh8i`>kw21&f{d<7HK_yvQh6@^n={@4Glws~m5@>QmQfN)mk0Q7P?|i0~h(Rxkpz zlb=$gzoM=VB1v#lgE5$*D}-GAN*k;gks9qNpEnU;+ z;o&W%h!pXDh_EGg$eguP>M#gDfZABS4JwNN93v5psF)Tx`WPQoj=n}>AV)vrqsr0W zNc82{Lp3ePtn#840idwALtgmML**4d^dd^;-Tl7$rG$stRV~LP?Vl{rl`DD@vkYTa z>_hcYvUJ7DmVQTAH(FhKcIikNWm@`U7g;A9Wobj)NfYPrt=yHQ=T{(>LNwDl(JV=F zRah9125)d;Sc6Pltz!8+0Af8u8>6Mm9^8&qYpDAB{1%GxzLG+xYHljysU;qb@RO9n zs^5|{jFp2?f7f{}v%VgE!I z_N<%s=}7nri-3wagE_?{OWaR6P#vzMc_2yKX})`9cd-l3}6{I zZ9{Mec2g4ghc1jk^-bKgG5E%dGGvuRA%O^dK2vC{9{{;s*?mr8icKfXylt0wy4pfur5i4ROV_}ao zDL>hF^$rZ5;BGe_(e=mkY@~Mo`p>S1d#;Rkr?Z@T{dK>nouk8REc9cEyIq484BT~* z!YBS73ni2}zO6HjT1Bk0%-`86tbkHJ{A1i2W}=qc!=tgK0rJCxI968k-2t53AP&P{ z1aQs{;`EqvZJz+nIRTvb(H6*Xu9?AKxiT~KXMJl#V%$(K)H8gFx^p zix0Fws_qHy#LMlTj~rZL@?MnpPl!=@r^mX$B(Lgm;P|Gvg$x~|E;pAx8-((>fE3X> zN|=4a9N*~=oY@gkg0=-hqT1GlCTTg{!Rtjvy7uybS5jITZ|1}af(U(+p(4e(^S1Ui zq_*|q5mMJLd4p(&veMXbR@5j{+#=00lAt{&t5#NCCvxkmr<<_0ibw`@(foevcirZ1 zv+@lRp6Hc^`Yda7;JaTeh-TXs9jvbAf1vtu_Y)-f7!6ji94K+dN+$OUZyRHW1uuPW?~y_g2~{2vRuy0i6(hD zDx>*&^yQbwMu^B9V!p(gu_i}P3_oe$qkq;UlQvW*&$KNI@|!tC)JUPI38!Z053Z7- z9Q0aQmj)3JT_@nugijuysRgb}_ zV_jvC+!1YqOh@HOM~4fq%RI3%*1E?m zdyjE*GiZlWUgZTQN8HBwEL+hbpcI_2c=VJ5jAG4aKu_SM&fyjGQdb1bqRJxHtp+b4 zXJS2YDJEDCd772Z!6aSDzrYJ#PY<`9jEf1 zzw!)+gt!PBb#>1lPtWVgCdRux@x-(>C93CCi^}acT&{!rnrt;;6`pWR5xYECXsh3r zR;@%{h1ESHz86K;!3v!TL$}^NS_kJG6ju2jp%XGS1|HGKzTQomQq4c6LO4TX>tMktA9Xuwy-E1cW*5sYvXoENe zc_l%642C(#qgRYAKLauZ?olLmjt`w*m|HVq8DftvjzPwv7wW)HgHiQwoM=cj9#4bC zUy}jdPM{k%Da=`yVDwXQ%TF*224N7~Y4nRY*U4(Fow|*=)QPQeli;8$*m)l7(EsN7`hKC>|ETEpQ*52fhxMSDjkTlbsDoH25!$?uTRGs|23 zH6J{xbQvB`{}Q)T;9s4aHYLS+(4^%zE?ToI_-5W@kittDlFATQ$;|2V|K~gQ51C(m z>S6HyLq3kvXhX&STI65y{8OKfOhq80+>{+qHn9(+=rkq7h@mfh2q!*$WEp?soU&qA z0$I^bocoEGRSj{`q88LZcSeeP0uZo<_oAz;_`Db~iUb8XIeW{Ay4fC7M_t>^9HU(@ zoqg*TxKL*C;OfNd>UtfPO0RTNNFd6ggu3^c16PQSijGfu%coSrCOIMwtA{Gv>g#ag zT^01F@5rpC|D<&zC#AX@r>ybI$L*)e-3VU}a~h46vj{U8=acG98F;=oo~v0R0ADs@_{9Y3PkV{4n4qUM>5CwqM-q+qG)Yp5$jQtr>uW?mGXOT ztFuUhH`MU{i_T4&51SfAw0oHDn1|{31%bxxQ8EKCg$+S0G=Ul-9zfnA(Zhj@Dc!Nq z`fjQ$j8*fsUaYb8m{}hjs`zII;^3bqh6i{WYi4}B!i>-*L5kZ=LrBQCK~16ZbM3)6 zgu}skRi1A)tTx)hD7Kz3$j2|H!TE95v>$T$8`KWFJIrYC)8mq#` zjdxqHT0U(ykrtpqlX$$FTqw`*DN-!!HAZYJ}WN4 z{FK)cjESwrGX`tLqp<<8<_6McCPn|UOhoKbLN{KO3$Vu75U>a+5rk#K3$TVEfTdJL z&p^loo+QDzVbA@$aXr{M?0NlvXcB2yQ;auXoHY33-4v+9|Kscm2mJl?Z;^4u$|Cii zMhC&Sux}*w4w%>IS0dKu0lQ0M4H!|+oJo2~2Wr@z|DaTpb{%6ib?He{`4Hz8uU4?!qX>SnrpUdq)7xVG~00_I>Ld>10HVWsVk(~iE{_Id4*$y9-I z6R1EvFldWRej6t9?J+hpW@hdld=!FAYXUuFi28$G^&`l@4V`YMkpb$ zUI>q=qX|8N#jD%WKM-OR*YXy}x>(Pf)v#VLf3wNW3v*(FaL>Tjy%1LiN`YS1J{a@> zVu;IdBYPt0d#HRwtQSFTmotC!ix?){i^IRldI@RQrij=l*2`vTVux9gmWS0yzS0Jr z-hT4b2Y()!3Mt<(b+-(S0(m3dJrQH$m)+pw6fzxo6gXpHJY3vG^OekxtzUfww`|~M1M>^AA@fz-=&BCb+iIqY8_KAa{BMh(RLa!Xm}>!F8WuLKJ}h);sacFEWxan$2h% zNLU=i@K=hXL0o@;Ke3wwyeOEn04z(u#^UPNU(syCR2Y1hR)T>c?- zmV%32!aI}$lfgQ=VE2WHt-{AMd$%&b82cu~WvHgV02%XL->G_qyJa5RR7EHl*t=5m zt>vnkuA^_Va~(plqP{5uW2_JF7{aFFFa$2@CGS6~x?v%hlIEY{+A-I@eD3Lc=F>?m zur)!vY^IvK7)H@XYK9h(Jnx$??{Y?h21+HVrB6{n927f@yrbgpWNHh#v_GhP!hoI; zaj&vD3urL(I5(W)4#2X_P^AwTV*+s%y*~qg$zRH@%o{OlYpw&b1Gg-%^ai}ZTiMa zgX%{nP9>;*Y~~=q6DvulVVW){HUp}GjovFr6WEwduzRklYm$M82G}>L8?VNhOaSr z-C*KWf~xs4mS_RmQVgnJ9yQgCW)AYo3*83QuS}du@cOlxgH#)zUp331y2-?er~23< zg$<37)i!>-^5DUsy7{Q7nyx{jUDx+Tx&FEJO{J*%#sF*l{8m_U1Qiipb5A5F!?7%F z0pVQ{Yip(G`($D`{lIDf`r9P^Z;zI~wcX6Y@^1WRmxD&Dd}rds_h7BE8xKm0oRW?^ z%p9b;H}&d24XWRpIF+FKgPDU=2lU?8+@M-!;#7j_PBRCoKG(ANJA>+vCQbsXzJ3b? zsF89ES3C`>KUIpVZ?swEW)AXt+0XZ`GN|q{aVo*<&t?u%owR!Q?*`RhOdM;s`8%!@ z1Q$tJcd*156?@D)ET`ACX}EHN|FqVy*Tk`Y4g8MV&+Ic0pxmk*p{r+TPJF!sl|zJl zkr%e1wPF*XvOQ9;4$tTuS~|V)2pGx4GezZrXLa~ki~9=FK@_iEL24QH2+|+;9()AJ z&HR^_xsA$9BQgJ=P^&-YPt;} z93c%{j8fmeWg&xBg)|y$ypt9c;@KEolWeyZ2#STbm!qkjR4q8v)KNK}vra=Gz3^U~ zk~$?7(?|F}7R1h;c$@_Fynv;-qkg>ulFpVM531jbkFd2&H-m#m;Zu--m!8;@>}z&0 zNGh+lsu?yrU-o(KsFQ0jhKu-yIfyQkirgQ6u1==|)3zBq?g&^3JnM^NO~Pts-m3n) zKi;;>dr+Dt5KE(Sb;5{Kx2jd^{@sCrI5H3jkW-3(2diYtgmb`hsXq!Lik2s_z~cPCN_$k>E3=3tq~5UZ|^US;4sF}I8b z`IHmxZ6CKF)1yPqCgN>Y3xl_Wb;fzgL#DHo)zZwVbOmV%RK7>TQ&L^Hz6FX-Yv?+BKNZqW z#$~03F!(e(r6iW$MyLy-DU~iz$gq)c&5-Sjk?($Y6C6b6n33$;ij+ zKI`T(QWVX_HIy?F6y7kUvSrbiD5R`c-+rvCSC*@XOBZs4dQ0{z!J{U2(R`SuwIfKr z|DHOm8&arf>b>27iWbyC5lbxCf!^{8?a5e}7i_;Jeqj#0(5suMa$-_rcQ%+v*r1{d zb)MjI-^HL2vAPC+cMJUPZv38#x9rkFS8*lzB32J0Ln0>O$S0lnB5h^~@hRUj?VcQr z+5=xONZNXbCN>zE3<-=G$=@0qCz(Bs@)9lsQdmdI+_0x|G0(svC&i3dwzK8tO#Xq> zjhGH%8GzLF|G>8WB||HyrKXObT2P;%BW(hOrk7ERBPcY1^B}9YkvZ{fhm27Q4fc{U zu7HT*RzzM@i(3$}C^fbE znGLB|KYEg>Ye5Au%jzGFC3MEhtd_I{XxSRFTFNJIG=d>~&8=?GH5E}`OwLeEcW)CE zzGvp&zcFrC6eoONyyZ|1OjG=`&i8WrNhn9Z+^#Ks*?WBU#z8;`8ZG7Vx7vx8BhK#- zgIio${hap%+zYwVD4`8-j~|@fIbzQ{>;0b~-gM%-Bj4Pv%o^N^ir5l{mlj_<1it7R zWe}9+D(P8TaR&WdqHr};uBhS&-&co7unw;uZ5=*7sqweII$%>fVF+5msK$-c+wQ~F zhBgXMSRo7q>C2?{D2a zhSd<(6RvYU?>SlBz7H?hh0EAeQYJ^wPGCvx35RUl(ym&JP!{U`|Kp2$Dg)SjrCCPd zpsl~Y*#A7l$6Na+n@Z}PhJ|%X%9NCejTB?Lc_lZS>M!`DWb(HE9xvOrX{KKu+Nw;9 z$oMUsY(kUMYr6N_T_PMe${n__JFC@bxTpV{`;IiLE9xEDk&oZr^>@`feG~Lf7Tx7_ zC61=$;iaRiBnx|FbMmHx@=c zgw3f>?Q?#&+u8l`qT+-_*?U#jgn#BYOIBb|-uZTjM65SkHKrrmtO2>-55Y z@3|jIEYh(ReC>GB(=WlWwaOyajmAm^HO}>3^j+RWYp_ZDeEG&2?*NoIj3zBnyvwKV z5YUUI!xK4)mG0I(9*YNbQZ^XPTRXQ;&C0c`{lh5gJuSuK0(Rk_KXr-N(|_o}Cz14u z&yFq^&#K_Bt0B-)P~orN-nw&%LqfheBEGM(?ynxlM?le=2*a)HCS$=C`KQ#)U2XS# z_D3iwv)7GDSHk7I1ijQpT%)?p=qEg2mS{*H?fMOqvgA{&B0>J1x%>DHTuQD>z}y8# z$y_fCxxzqI{xix*rG%xZYC)`?sK&(Oi=Glsks* z5_;a{2?hw9fzjoaAH5xAo6U$d^w!jPWhhz!)5dyRIkk`-onTbRYF27g9Ee_c#8p#` zh;mcle17;V#AT~jn9>#jX{d3D87X3!C=n(xzTLQNzj(3~i-*L)d9;D?`=1l*_-M?) zP^VwGfirvml4T_hi-06H84;sfR#{5*8q1pv49Al4OJY^2eRBp@r-@A!IV@2^084KV zG2mqdn$J3O;7IIHZVw$T=y512DR%Db`#L}g`tX(3c;a}J7(kB&WJX8paU(@o=3f2u zvOe>1z!3~Vi)#UL_Y%crj=)&N`_(8`ucL8~FToqhZELd?#gNFb*+7vb*_t-n!Tlk= z$gOdP{G#^BGF)F0yl}(?{VtzO@7Zb|loo&Z4{X(Nc`iB9skP{!6L3EhO0@hT)9IA( zcB^#6u$FNR+7#yJ{R`(8z`(;%4TC^n(Pzgb#eq7D9T&xmeVHE<@cn_74yXFfb)=f7mqH==kecc@oy*bui17( zKDxO2NWM8{y(Y3)uj3E=dpe<(^Be}NfV2KS!Za8F9!~h#d+j~&@=4Eys|S?iI{g=| zpm)Aj5yUX7_j;ctagy0Q$fK*6XA&rV;k+dKz{S@b#)}5G*8W=DRBCDaQrUhZlj$=h zCM7E3`$*-JUSD%Fd=6|fC__-Dg;lcNrSKqZHdA9rqLh8qiv)m8Lqg+ zqq`vOtpMKer0CPuLL<>Ml#Y$wYQ1fIk67;nelIe92km=f5&vwlff2FZ4g7vD@caG1 z?| zk}0Xty1@@ipBmK@ABysx#U#Kz6x^%emccn+$kTFX2$cr^&Oi*8w^j}NC2m}XZ3^hp z#ev4Cfve2ck&|&^CnaR<16zCbgnu2e#h8SC;ny=nxjupZ_Mtk*{J*VdXniTZX1Z^D z)w!^FolpP2qIuNNT`KLOa%;kV^=Y48cUDHvnAlm9j2|V&hQuQ)7xb?Oyn|69%!vPW zbrf5^DX@f8Jp2<65@`nuR_I`>D*d>F`R~`}Xm%t=Hv%fN|G)~Vx}GiK+v17_lImFb z@e>giiW;X>5`CWxCDE0QzWFCLKcyd<2tn0Q&t4X4mrm|cD^}A;T0Ff=;~B9NCpPh? zx+LY|{N>{0o%0=HR{m0dhD*aO**SFECva8q7i5#DGk4f(i&kK}$>8ssl*T4-(<2(r zj~cNH`nN7Ep${z4Dh!zwr)gHSXRlZXg=RgIJ%lbDKK{&4N}Lx8h6>%Ce~r3C>`o8P zZdBrsbH%@s17QyICDwDr~LbdlvMupxSSllqw<@8(?T}^+3}kI{jg)=EkH<9H%+BZR*7u@ zD^n1w8#*#p{BYH>k_?+&B2Ys5X7gi*jt9yeYg*JOKsYDv6dFB`At##6>>&T{LhT-) z=BT}e*lm<+FLCu(Y9gqFHgI7_feYg-3_A;CR_aoJpL-QUb|_D>=GG=?8_>bC?WgV- zo@5V2S2~1%ZhzPI-4ARkI1VAGp08B`soY zMkRNNW+xRke<0I0*F4pMLz(iRAcl|<62u`TE+k7>mTU6*P_%CHNOc|KY$hc|k}wVsGLj8~w*O|O4@}`d5#i{r zKwh!M$36VWeWn3=>Dw+eahqm}n#CfA` z^Q8*BugQvkDR9nlAJc=p=--@qpxS{^3S3q7ya5VK-}+U51va1b<^bfL#N7Nx)lz~xKOfRjrHTs6R8e6GiV90mR9J!= zi}#nRY@+TmRn`3|mc)P5h>@TeF%lFbMuK9*NKgzD35sDNK{ZU?CQbemaTp0&fsCoG zKt^vyEe{fp|3sYeTdrNAL8u%GzM-i1UYCjQiceZ5fMQ!6v)f-3SrmpsHxkBGR! zp+Hefeu{`I9KfR)P1w>R!dRw2+S3$Ba~kltK#Ns6A{KN7a<#|D>#$&0{0DRKkr!7W zQ;g^P+6-#euj z%(u>C*C(&Wj~4jR!ntV76I?S|;zvv8n0ea@zJxUy%jZ>P=40xTK`4R)lJu z(d#1#wO{|*ZxUkIT?z5>n1pifz2}gGD4He27pEk&;nGn^v-yWapKLX|j{LCg=L=cB zjq+`0%bPROvuq+{KY7Mh2{Dk6g!m$fa#AA-Z_E0A-o81*k-U>+R!gF+dF`2|5)wSg zV`zThnX3H25vP<6e&7yHexP!plo)=Paa*e6`$;^ggD9}v+40ZY+e1M}6APtIY*Vct z)CpM5`PG?wW$8BjYVFX14&XTFoox}ETxMlEZ6AGWC4f#252+PC^O1nl=g}=c!s8yd zeS0$iS{H|*rUCSDXv_!D)0uYblMaAh4qxO1(A&vfzVdGXIS!*b1L)(l>iZYmXR`V_ zj3NS{pF`CKK!1mkQve+AJYIwPPm)8u1_=WkI`#q>=}Q5Cv9#9 z;ADr&4S>N8pVkF%ic_+Pw@1jzUI3>#i#8oR0N`||hco6^07IQ? zx3$NoB!{XQ5@ZVk$Z(_^V2`5hI>YF8M^y08$gCSB?c zx%|tBJ!@PWI0`yD*Vwodo23vg64z5qjN5vx+3aCNLolwmV=*!EoQEG>#gTZi^L3}I z*LivJkta1!?gPW0gNCWg9UX%4&t|uF^Dr(c#D>XaY_NR}2eo2-Onlw$%_2gQ)BN{S z(D6ym+*!8_^fHVMsmb_R6IK9Yoalc5<8?nzko|mCBx{)N=V8v7Gmr12`gtOdCp!$Z z4B&F7=a6?z=jK<2!o3^93m^oAcB`WKo#cgkW}F`83;8VO$&1;};@Ap2OJhMzZRmTz=MI%jbV-lXT|42R*RkaDwgH(nvlx&a}lG}&p+ zaW9;crrL5QTkc9A-lD{WD-;T}EVxz4f~0|b`1v-6QLq5`n3;~BGc_}}>lzix8qGv- zCSCM&XZny?-9^ztnzq_KXRDu-NE}`G?rtQe*!(J}Dwt{fD5yyyEg+IhFC2~|!mK;Q zHi+HRBD*FB)}3O1WRNHNtiQS~M`8<``83maX{KjMrsY>+5#1}WtoPl1f@Qt$!Oy!j zm3y6(R`=#0r|&ZPo+Mp8dl=z^4bDw>Oo213*os*&(Cn>W`Y?q)%h~ zPyA%dzw&JiuOugZP>;P?cSo}B(G7f$Q+8>W9;$C20u5g;J&d0ZX;$Yrr)9mg3n`B{ zt=_Ft8^EJZ(w3hx06gw+#{%F9r>OA+Or5MJont?~vuD;rk*tSxK@U64UY*+8>&XW` zeS~X*Tb$@g9$q6c#pYLC@?7WCHg%UF`8j9j$h{QIMNVweyi5Quh*cH9i_T?Nmy)U1 z93FiGc-`sxhmoJ+;u8 z)^N%fNO{|tkZ~Ospm!YZ`vEL+e#sb?gn*4%m+4wx=G=0zgCNslkzNd(cb%NBhqyMs zr`MhL9bQaC$`WVz-XFdN@PWf?G60q;ndMHgWqRFRt{2x8&i?Pufn!kCzZ?df2e8tq z{o>=4HmjUlC%nZ4eYI2N?6zEGWn%;IEuob2i*6bAb%nZ4U{0G@yqS|vff?s^JC40D*V&< zVchG%hQ9T1ZTzZJ>xnZDkhxE8YPAX^6{XKY#A)(~_3T%L@p(u^>p$1$Zx3T#2!?9b z^|}eZkWKJ$B&(}vf-FEAU>3~!Qr5f3`E}nks@YwgrE6~4sTyV@3h_0?SNOS6HARwB zbL>aZF0#IM__8;EO%7iM2e8>W=e_y60es`MeC{=_U|ZC}mi4`}|Bc1W^^^12IXyTs z%bhb%I-T0yE@#|@3#obi>`d!gPBra-6M5~ib^v~NXg~s>n&gl8=6`<8zTZ5AgYgLO z_4<2j)<#&P^a%LMnfUc3@Ts8Ui&qhxpB60O8thhAB=W!+i7jn@4Ge-m;|sZM`-;y! zF8+!~Sf2lGV-Mj_Ji>@Q(MBG^-|+~qG@0!~I2?~q>*ssCmavjwe+n5M)5A@*U1z<#jYIQ(zV!o$J*x@vd6U+|&l32!KyE6+1KwYl zj0_et@Y*-vW`ucf5pZ+DozB0@6Ia%;f>5wxi(b6g6Id3X4U8Wh1*IRf^%&wa0`U#K z@~kDmv0AZQ-ctu`6Xtboz^w_-sx^r6Lp5TXP&#QJf5)|2;j|6K8GK~~tBG|SX)@#y z;P!-hV;XP=!i@DPhL7~$QIbRW@;JN3$i*|KBQP!g<3SN&l7@5@>B3$OcI3zekSuoz zMPg72l!&lRGeZ}aOA~cjBr{z_hRUiYbqNuliX{c^i#ZRyd%>>(I$eEqQY%ZR$B*Cq z9H7(9qoZSP9g&?s3+}5MAk*C=qoZ#fnau0&<^;&}@W^DQRkl{MzV6p1K&PjVj=q(5 zM1Ec@c&~$^lf(Si44+d|{qD=(C+E!A6DX&juN)mN?1<$&Iq`|=z0}Zo<<5)yQ$fq= z4@&MB5-G=v6pJ6UbQ?f;`2OA-Fn}Gx$J{p@V%s`_@T>1`rZhZJ;BOs?b;=qg=9X&w= z{8jUBbChU~;2W}>MHI$Z1w5Sa!rOLX-X%Hh)22gxPjYHUe+Fr+48w2R&%c+hokp3I zOI$t>0{Cpga^*;JoF)^YW?1JiZNrOKVg*TZwhmp;0BPqkZP6zUxo`9>31=V~U&)Ye zv=M}R+;{E(q@PbXuk-oPd94cwzg_(jND^x#;TE?){4?NDgmW%C0~}iy5`J_2Crbcd zM0i>58#@6<3EzL*CFqDG=j-P6f8^hH2h2qoNzUV66ru5xoc^yY-^ah*+k68}7qyxD z0TfYm+Qkj9xw7&|Lt2ZhiwVJj%{>tKk$;z@>bru>r3!A@KPjDXfWxmi5X2q4CUo&B(p%!hw^+o2BNe`?`D0 z!i=g}bfZiVOvkO$cl_%u?k&}NHc=o2TEeN5)TlMsm_#;IeI^t3*M}v#^&vC9`f%KQ zGxxoX2IowC@-w>?5?k5)s`yQEiZ-9!oP%}lgP@g(eIY?`+0N9 zF@chto9-P2!?~bAS|l1MyzGbB)rraT0#LbU#1KUHfO)z(`H=hS<-A@jWa=3LNBa!&bkDyQvj{Km&j0N+kHd*V2h zZ50yU8Qt|AaSwbj0b35_$xYvmZ+G$A$_7KSm^SU>Mc~1j%QU`T!nERk*9f6i@2+<^ zO`Mk1^N$10v&7*uD{&3`;>usTh=yg&Rl{1(6a8YRI&_dE=ghX#p;THgFirL8i{d*? z$E|GUV`Gv~pfNufzfm;Om>UN6C#7HCi$e8GavEPfSjZZlvg0?SsC(j3h>0p!_J_s| zsw5$}QZUo_F;LPIjZWzuN93XnKVdQ=1HbC3y-e0GS|)VwR|q#+an`S7iep6KG7mEc z3fcSUq+^I#Bdu3rPl%@Nd z#^%u$=IHHroCE8OwUJrWn*SAHx#s(OSm#)I;^~+fAV~@~^Xtld?c-sSj|Ugg%|#l1 zZotT0b1zO|eVlV%`3MYcVgB2m%;lbM8{zc+bq)hACp_-EIR}aROXFjqi6=Q#r@c-= zx{KdpnbWDD{7ks%&(C(|_u1maM;n|HbQpK@lv+avomfxQj~wZ${X%kPKkY_RNIz}L z$`X_Kxqih^pxpl1LjtOQ_7Yb8!$R0BEH%&~_dnAy6E*pj*m9^^`v^b$%wLB{c~GLW z8BvYlH{T9j1e8feRYMQ4-#{jA1$C}o-4yG9#@R1$;ue&)S$AQqYor6Agq~`)`YR9T z_fVWsU1ogm;rtO^*zFs}a?%~dS9M5d{Ykj-iuW<`tiK4WHa$dGwJB@NnzIS~ZEEun z7d>2W_PLO^#@JS0&Ym`X3%;}xm^ShB0Qj5qf9^YCmH(rQ$$ViYJvq6seRxUVEEk8R zswCnC`sgqUjPIjeS=%9vtt#++aT@O3PEo1W_6o#?W|^h9ERz9)Wu9xJan86PhH+!1 zu!Mcvs$xMDCmt4GH&m*$(Q+!=F)yWK+My&7Ta`p~%cU`+>ZPiL*-HYIs^cDKWR?Cq z{rOxXBpJrxyN~}2!;6*f=Wvo{vwFpB9(r!r4v$SzQfxv?IQbGbZ4Dp0HIKk9^SkVl zw99Tz2C}MJ!5~FC|8r{Xtpf7)_#&M?X<#YA9-k<%Vv#`ov%2Ld0-Z59xaY6Ubh+mb z-5fJ_aLfPY!0kPRtP@>@9{;I&doF)iaSE3m+s!B8`tb~h;sQI%=BaG|rpI(O* z+iJzk^440C^WKhzjgi)xX?O2kOVzOh;p6SSP=>K1ocV!RvAW%wMlH*kobf9bBda5E z+Lw;NrYWFi7`2%){t2uMs@-gsuWQqZ1f)UE>P%SGtP5d(&6vrhKzc^a=u?9JU_cdc z)s>moH@%CiR5!vaGhVF$xI5vAdtZhb(dt3C@z!cM#P?uj z836YoJpGR>3@xiK;Ym*|qouJQVR;YG>Q9&#W7rxutRLAT(6@@qAA1bNJ`JtG-!^#` zt>I5_zY;gBrgx6`2Q+Q#c$WC)?c1q=3?Qty9Y|Pmt4C$hzzJR_C5Z^x;q0yX`7y_1 zj|J(@a!6Hm&bB?YF^SU)*J@vh^Pz076R@IvKJ^ll#cOnZ^>c$|# zGhULDPI}2$Co!#8pC;6JeFt8siBH`XO^$)W*dksXS%R+P$s{vmLN{m})?mWh-dTtd zZ=FJz!AJm~N?5hS5W;GpidG;ox6&*ptWJ}@J_K=ZoyN?+HM*RNvyW#vchqQk<*HUx z3e;#}M$PK!J~oC1*&w2ui!{R6IQ&>$vE|)#`W9H4tO$vy5p)LOzzA~I56z{VOT_B? zA6`q{NwG@en$>{H}BeFl#tr1_J{O zQyx_HyTAPm@Y#fK{2|6}KZh^_+WXh6gcYCxl(+Lfis)r!;@ zkBs}QhGA|Gqcie@nSB(U81pkMT7d32k8bE8NElg0BQiu&TK7+}G-}&XlJiW)8A1)B z11;0vTsRm@p`oKGp|+xK2U?Gmq#zyLi{r`IU7N(|)nvkV=R8Bh$7O`2`=fO^;hVRf zJP_$u5N4=(z*iF9`i0Q1rVv(x`6|MG8O;LS(#eZE8kkB~S*#J$ua4TRMS14MSbty@ zYy1x9uWNeuFb6)j>?cth=Cqkl&ulkA)3u2kR$ANXuVY$TSCds)qBV`MEEV>^S-tj> zixopo=jJMei|_AV^{dAP>FGATk%ao!e->sQwA;^XUZH%Xra8%Z>FI;m&p;{bRagApe6v{K zLMOc`3Okk2psLivb(%>tvB*z6 zUFxkYNgl8yIiG#hf~&?OOndQ)nY(p?%;1(zT4AM6y|pD)V5^9kZ~psT=!KrH%@`f{ z_B_A6{dbFH;at9Rs6c9yf=klVT)x1JO1FNIu}!-m zUa7_5+)Y|PXe01S@KrbXn}k(^yH$7Ffvw^;c+OkERV{>A8O+$eby^hxd8?5~uXr^g zinkgqBq4PMA9^}W^x$&zaMRgURl)Bt|93Y%{F(Z_n7@DfVsH~&qIegu%Q1gA$L+gw zt3}A;Sfp3XvCN}hN)nwlH$b_zQVPsA`8SW1zH%mM+;mdFs zoqOls+Brby10S8x)AKMoXO~y$8=$k)M<>)5B8*O_c|UfS>$jSZ&#t}&7ISMEiTzQy zm^$tX!dLBliu&;y!aFx~s0#Q)!g8A{Hj-h}`;sPYyLr=_#P#(4h`HOHvX4|hCfwnF zzToEh6T(U=eM;CrNl3t*B&6+55}gXEw5UlBXaQl|{8{C~<2-JNr@2|nlIEWJeu|bv z{HST#%okSDsFY8r?0?40e);z~6O{a0M>w(kvwA4qRR{qR)GT>YrLr<_J&KAq!~Sr~ zTRp&}NA8PIwC}z>o7Nr=ZG%8V(0bFG>f!7!%7OPKtEIYWBVm6xu^MjUv4&xdSMSda z++cpi%=bNdn5S2p2`5!KgX!N8&Rq194R{M-WtJLvIoHE~d^3kCzhC811NigPr^>yI zXiyfS8+0qFD3-So_Onbxmu1rMu`F*5V`SZ3bKEgTsqUALQo8(&FY10V@pP%*v7|HW zJj9u_gYbgJ18GS5o^XDHV_{c;mi+3&mOrygiFCs_dFhdvH2!<_cR87G$AG3DC&bg7 zl(EF-@6?0NXze6Sqp2>Hh;FH*;V%_czjN+3%z1x-NaVBUqAY&Z#r#OpZ3|lch+=*s zJf~z1+Q!;N_>3FRpi=NN;o8?6q805I!b{6maPnv1&ZNWVzX2aZIDL1wb%5&-zVV*7 zxhmHq{LP*pIa(VKexl2(gc}j&HBZ1I`g!Mq+rF8Pf`{w-X9~dma?IM=#=N62fH@pcLwQSPkT~okq2=irTz{e5h ztG9r&3I8zZg57{S5Pod=XB?oN2v=ErT@}Dx2oG-85LL9g5ng>?E_YNt2wMkvs%iBi zoHC<5c(!r~k6ybT3Ksf#>v0%nf#K3@#3zQorJQ*Pt0AEa4-n+p;xA3p9 z@|mV5bx!}fU44_;ZF}8iHoL_g<48pxPI+*PIMo?ik?HK6DB2o^b@gp zAs3lW*gONqH2+l8U-;&mAV*A_cxp7Dxz-la7<~z=(f9Cam~$eNKw@Dc2lI!On7aRP zW_XFq+l>9%E0K75{7qy@56|yGHQ;i>zaCnhr3)gWTPkUUm3s0c_p@>QOQLFlg1Wy! z@M~hk)1_X^l9H;m1SC$W2PAZ(ABj@90pMz~jQ0oGgVCc>kOuUG+i2H_ot zRzsdAIUf(6`L(|Qw=|aRa+`BA@@TX^xF8*|nBtsfw?8N#Pmqc9iUk=_JV7>-gp?o) z-9`{SD9HHCwklZfj&AYjgbK1SGLZ!z{vIGx;E@U69fi^1yX}h3ZOqRHp96Gn_vnTS z$S|_^Jo>{DDInE=sCH#TXd7We<<#r1`^6h7#M48ikOixC>JGwOrv$24p@b1!%?oDZ z0N^s`+P?$e!~|k#?%>cv22=LtmoM#y5q2kwQ6~Mn2+KoIswwkQqZTJ%#!-NQpnkC2u%^hZ`#rSfB;{Cl2+A0~VmG_ynn_Dn3crtfF@$rI==3w~EG*l!2gru-vdJ@_}$v?HLvr zxv518;JJhur~~i|grDCk+(rLMSm}1J5q>K3E3U$C5^i}>7YKT5Az{9P4)`6yuY6XQ zdiMK-tKXIe%ck`a;l}4z6~@+f`z@#o7+sH@&6Rr{zuoxHF3|6iobA&F)I{1QroFXf zX>-6^2rK{gZwV{?aywyVultVh`>D^A1OF$&GO~fSi?Gr`_Y%JUiZqVkBm@(2`0hO5 z6vCaq-#~e56TW=z>C~B96IQ0nY{Er5hGVE&?Fm1>^A7GYIud4-A;4V-?@hh>PrzLX z^96dq-3X8Gw-S1))r)Yn=^IctlAPYLCaAM@64QFtO{1QCD&e~Z?qFMrz~>WYs1?AY2!FrzJLXww+sEsK^AXB^=rqc&1wnoM}r_m7dz6@+g& z@6SGf@h%|nr&!$lUQPI-+Mk##%slK<|C*^EU|BJhdvv z<3hsEwJgSBYrRc)>4?un`>lHYT$b}L)ApR-XeZ!hgvS@{?8x@zJtO}8@#$Bg4p}Ss zt^E@Ru+Isbr5B9p0$o!JBF+&#OaH};efx|+#gm-h-&p~sa3x{?+b#I_&zc8CVd)Q? zDgJU{W_s82E;+!z*9<$4>g;c%p=SDi!fMwc#4-zWOC}#-v$k2}xEdrVXOx~Pm;neF z#dJo-;a@%w%fIqG3awC2`hxH|^6;8(?l2SWqifD`M9uvP?pNXp?u@S@I1jb?-&r-m ziPXYzyuB&s4DK1M)A6ltr4vWp zd8hWK9y1LJ?O=5jYB!$zU3vj0b!S z;XCG}VJ)+25mpy{>JV1rur6U&s}LiR-K&n=)FL7tuhyMSevIB1Un}f=J#x64z;l~m z=U5i2+Pn>6*}hgbVbxCU3Cng0o2z`s-D?-p)$P)e8CCr{5jN{5D&SY0#1o*pdZIS! zEgGF>Ah6u9xyiTeP_rBssA|@iu&UYdgk{abYQtCIz1onLuFXJZRJCykAE7qlO+C$d zSZxdhmg}nxV;8mi<~l5EJ|>x1cH;$*)wp)VuTnHfm}&gz63ICMOzLY+7JoS1_deHL zK;Bdr=@m|OPF45TQ~Rf0X~!w{BHjQ*BcDjBD$aqo_j0j+{P~P!f>~a*vYA(N>?Ua1 zHgP@P`D7q2Kr=`bOb#ri&TWVL3drMKq*uth%5bt^Gx_tkC2WKQwOglQn4?|MOK`kF_MES}Qe7Hagp3?GlLl8ZiM8Dehd2K(pF6*p_J6LooW(QxqL*{ds zS#1u^C9M23M-Z0VA6$C!-%2nVknaF`%|x22nKb9;flmBc3m*>jYInZCiHq&Tw+=m| z3qlF;c{tQ!B)L@rXB1&2aMZ5K+mNXK6wm$XJ(sZ|F%Z-bRx+#!`Su(NzmNs0?dL^= zmCsw0aJQv@a6se{zV6mxgfAw1Ut{P(RpQ zZYSl81ARTsE&gzNwm-!YkS8oedWFJ5Wza%!JPB1~1SiFy6ttU^eHfrK!J`vuI|?JS z>e26mWF~rKLWOAjLbG4fPj0)8?;^{XQ5g5Rifg%QQaBT7^MsG-6E|7v_lP@2Frz^;ln)g={Hs^iZka9V3 ztr214%7^8z0W0N>Fr#v4LB0nFhNh4SB~Gs*tZXf8L0tSqpilliLhJE4#X#$ke4zEN z2KkWI<1>t2>s=F$#5Wni?X~1kHQzr7o6Q#|HbujTmk;%{43nKcEPwN{R&mXTmg9SW zY!p5k$iIAIkbh;2lO!?rt|N1k78TMKa6RET!<;M$6x{#)hK!mxa|(D|SvIG#?9RWsj2n9Zywhj{K#{~+^58!@gYD#f=5L1+du zYo9=d-)B29&MFv}Iwb(l@mB^RNA^NIjVRhg1SKc2K%3kgRuPA9DSAyZGZcsKCxWwE z$eF5Q0bx}|w?NJp@q@g$Rm`~+xcUo&k>aK{bAR1vTrB~4!dj$PD6FLz5`_p-*Ks(+AiXmf*?<;x@IZGl1#U3At z^pNfrNWlTf2Ln){d&szI?RyEE^VTo++~yGMCK7u=EY(+{nyk6oVQx377UnB8VCX(F zp~T+(gq0Tg0O3luFdw7~v@od$TKGXwjMpdmK%v)mvjtAvy22+IJ){a7_8&=W}Q;9dyD;rlxt&Wn;ol+gLR(?-Jt45D-rr+BHH58VmduCWz+DMpzV!z91Hxb8 z0V0k&Ybkz7PwHiW;v|l5WpW14KknP!#B+1{LiX z0Rw8tQ`QI=S1<;NE1*P_6G0_zDEf?u8p*+9Tu@P#@MIOl6-Cel6cmtE5p%!ln(4Y# zHC0XclcR?>HC^9Vw{BHe^;B1Vx2WrGKD{euLg_l>7p_ykC|pHeqm&$<92Ub)IXP70 zvz#2>!Dq){BFR4uBjOx3L6J|i+`!y!hT)^O{5 z7=#zoFrRxd6hlnItQQzGe;GD@o<8kXjqjXn&ba%q@NF-CimQOZI1FAejRuN;K& z(lB2OOz}>LC}kRCvj>7WaJY973K4%1fROI%EdAm4n#$?EGAg?6k9-%upiA$!DKJgt=fVyRJtF z7V%^9gkt8x=;~+P##p0ZJ4=r#!@?j!TO(EmMVLU88deJC#{)0ryY!{t*~VYM4o+Aa zWk~zUZnlVV>Gk%`RD|LOrM>xfF@h*%^CiDf?T*!1_2x_G*rXJDC-Ie%u9GCCU?ItD zLtiPonFo!oi10|%6}3`i{Bb(gpS1pKGsnM|&xwUEzbSio(M7tG*ei&|LX&VWBOswI zmM(Vl3PQ1Pi)C6r>ko{TWV=|}@R+=LlTxsje&D72n7$Oe?(r9}pA+idmJKb;jtNIF zKoktu(s)CZ45fy*Wq%NacwyzY@FzE+>R7y{^b?jKWLF`4s9~W>h*!sc!b8#%;)T7R zu+&YcHi{s0+<4d&k;8Tfv(z$HN)(i{wBZ+7szP`cYZ*Gpp{37cX@gL71*t5H4INQ% zH};7YS|$o=FpEffpQQ~#(Q=XyyI1^#HQj`w$|_+|N5|V~%mQn%0(M69yr>M0!eF^w z3wwI#%r}S`FkzRCbSpatB`7J)eZL!*@*kkG^ zteu_^Th0B1bvG7<7chMSfe1r(niy(eM>0?CsEX! z8V6_8G)};%X&lf|)8kosOnF2{t(99u?Ql3mfPfv)WV1B{| zsR(h9&E#sxutmmPakLJn=}dehhL3{AEM06w!x2-Hs|myEw#fbxLvf%}ZS`(i8s|@w z>xLP!7vPAIX-3v*hHP(~V$R{Tu!#>Cp7bYK+OS0u;+(X})s$g%m#DVjaJh-sZE42% zirFG6hcohi!saOmr3wv>|I^E8HX+cNZAK6UEm+!ap(KO^f}gNudO`?N_z83A38AIo zCp;!SA@pASgst3!;!cu2j0vILlH4v)07)1%4N(>~4RIAU4Uv>2Z69=Hfza6T*PtSO z4PwHVnFUess+NWS00W$s}yU2uM7DrHgfZp&|u| zD?j0}=?S6OHicm;dfE-*D!rJWKj>YGb!9;&Nm1Bp%LmJ<2PWj> z^Bw`a$0GL=9R61uq7t+%rsCD6$XJ|O#Ckxo|a2lx|m-O;>P4Ui(!jY1A&7~=-FwY2yA3R z&q)JC^d%G8D-9G;uuSN=eyCidMF=l*4OU-8K9BL){VoX+CBxbp zQUtdn{UVle8($?wzZDS&>42R#-*FUXgLKVZ`7lh%(2X6DTUnDw)%YC4;Z^1T44jRrucpa$O zckfTDlgRb&{maM#=Hn#DSuJ(ayG@m<92VLU>J$A(PZ|b0HeW3omM;oB)e4q)Ph8v(! z9AxQ7(_? zOd|C!Q;OWrm3-3WdAUzAhdq-K_3&rH zi_J|DJt;M?|9G_RD0 z3!?^2=*Og3XTyR?JRQ{%v90poV|9yt&&K7OnawovYlG#?EKSTRB0D6R((r_=jjfZj z7k+L)1}hMwgs^AM0vW16EVtg}lZG!aiW#V4XkVvh+P%G>Y-L~uxiQZ-9p6#M1h;UX znNFB7>GmE5>Q*1B*`Bj@>!|Di#Xhs3P1U)&2BcDfSX_7Y#MjmunBTfF6FOI~&5n$+ z*D2Yuqm+cDoQWsBvc|w%uVTz5I&$gRT@1`<6=Tlk$1i%UqmBt~}Q~H|CWymwrt@bU0?Ef-&!*I***c+kmWA zAQsaO>07bgz^rm(>OXnPegpHaiZL6twBLL649p4zV|u#tl!kQ)GNLu}L2x^7RRfp) z$va$rbIX6xFV4)-QKn6lX&Yr)MVS^+rZUR3j56J#Ophp25oN|knZu$??J-BtKk857 z!-p=dPiSUccCWKaPgU>OX+XYrLSFB@e;sY?owdGEwN}(mPF$UD?%8R@1-01kC(H1? z?69uQt?8bJ-Td~=F&NAl@oZHxr`_YN( zx2>{>tu?u=M!yW-T{f^hUP57ACOFy$9Jgd%g$ht4~|WM2+y{X7#_4i9^HFX3gJ0&sIV*PORSYK0SmRruguc z&!bZ=DGT=v>%G^3AI$Me#Uy^w_>nsu_@O@hn)3#&%;Uv!Hn)ES$1C>7%RXV9$13IkLuM0=Z>o-sSP2IwETBnUs{ikhim;bg! zShcoqGfIg!1tj!eannLdiMJIcq0A{>d(;Z6_quw>ec>4CM4eZlmg*t^y&a3l_X^f5c6!srAK9V1IMh;XMfR?FcI-}$HH#g! z_~*wEGTv3k1`GO?i|lvUvTrS#{Z3o<9YwQGv}NB=H2a@z z**96USBV&h$y1)yiet*Vf;)- z96vV);sh!jW>pX}&`p6TUJ8Y!DhOhj=ZLqA>K;XeFNMQ21Hr!B6bS33P+-%!wrGI} zUv3UW5K}lzGZ0M7O_9B2 z@oNYWRlwcNu0?9$5&iZTw>%x+MQ|y?D7&oneZ#$&ar$c@1bpK7hHPgZ9S(Bh5h#k` z@fKCg&f932FPKcV*g`s1yfVRGkZ#+rG`Ls0FeQIsD!(Azl0$W)jk%t^a->8||7Gj- zEA3M%sP5y4;Ql<-1KNdY^1|k=eM&tUIKhZuXlc%jA}AH%4PSta+;2e<8>9R+RJ6f=j#fw7(H5jyl#px}!$Jj@D& zK6her4k40W6e9N=^aulmP`l?DZe+bi$l~)1j}ik`zNd4hSamORL3r!!1FC81SH0)r z7|y|C9C1}U5t`z0{_Ue(7k^2ipCHT6%RNB%l~X-n<_u0hxZ^)sQ}=#?f7`cDbJC*= zp5))oxpNC*Ayn~iUq1YGlB@`x;@>W>^Zr8m_HX>#Nj*-0+{x4Y+i&k*zn!XxhywK6 zKHhkWlcoGArZ+!lW{#CmJ9gkN;CRcl0ZHXNfjBG64Y)`nFjvbUNbDf!&k4*LK=s&x zzu1R|*l`{&P7m`694vkaFCRJv+KdOWUxxvMIf3Z_C<;69gE$`g51IjxEp`wL)CkNK zX^11|3B+-CaS)yR5wf(&3@T(OG&7)3>tlg#t-@kD0}{53M4Y_mri|hw7LP#g)yFd0 z%K|;vJd2PO;ATKFRjG^R-hz6ng8*`>3W4biD62Z~5L&h4<-!A$RtYa88HCURufT0Z z@$v^HWK13STYY#)rRMR81`0OqH%>SclCrjKO`XEFN*#65i^2jp8Jo5HICDJI1srV&tT%o}0BA8h#$)Ktp1G%K_< z9R@(BQXw!a0Le-R9y(JB-ZJ<@J<>q{@k*7z9DAW-=^%g{r%GUs{!r$05X{mD%=rtt zl@0<3St=HoK7^*F0}mZgCmxcZ4m_kiop`8xI`EHkyrmOCR@FfO#a6`tODBMMtApSP zjlk>#kYIHX%qUJEM|udo5`j>=iUpP4;+OzZno2E{Rboj2EloEC1UwZAr6))VD0sRl z-u6*IH#ARC5PYPKog5b| zL{NrQiIf{&5c}|$w+F9+x}mmgkoLi=7(VrLPceejPaVYw(mi#kOJO+#b(~GhbmBE-4zWaM F{}=9(); + + function add(path:String, ?target:String) { + if (!FileSystem.exists(path)) + throw 'Invalid path: $path'; + + if (target == null) + target = path; + + if (FileSystem.isDirectory(path)) { + for (item in FileSystem.readDirectory(path)) + add(path + "/" + item, target + "/" + item); + } else { + Sys.println("Adding " + target); + var bytes = File.getBytes(path); + var entry:Entry = { + fileName: target, + fileSize: bytes.length, + fileTime: FileSystem.stat(path).mtime, + compressed: false, + dataSize: 0, + data: bytes, + crc32: Crc32.make(bytes), + } + Tools.compress(entry, 9); + entries.add(entry); + } + } + + for (file in FileSystem.readDirectory("src/haxelib")) + if (file != "server") + add('src/haxelib/$file'); + + add("haxelib.json"); + add("run.n"); + add("README.md"); + + Sys.println("Saving to " + outPath); + var out = File.write(outPath, true); + var writer = new Writer(out); + writer.write(entries); + out.close(); + } + + @:access(haxelib.client.Main.VERSION) + static function checkVersion() { + var json:Infos = haxe.Json.parse(sys.io.File.getContent("haxelib.json")); + if (json.version != VERSION) { + Sys.println('Error: Version in haxelib.json (${json.version}) does not match version in haxelib.client.Main.VERSION field ($VERSION)'); + Sys.exit(1); + } + } +} diff --git a/extra/haxelib_src/src/tools/haxelib/Data.hx b/extra/haxelib_src/src/haxelib/Data.hx similarity index 66% rename from extra/haxelib_src/src/tools/haxelib/Data.hx rename to extra/haxelib_src/src/haxelib/Data.hx index f9b66db4..6becc1d8 100644 --- a/extra/haxelib_src/src/tools/haxelib/Data.hx +++ b/extra/haxelib_src/src/haxelib/Data.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-2016 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,13 +19,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package tools.haxelib; +package haxelib; import haxe.ds.Option; import haxe.zip.Reader; import haxe.zip.Entry; import haxe.Json; -import tools.haxelib.Validator; +import haxelib.Validator; using StringTools; @@ -39,6 +39,7 @@ typedef UserInfos = { typedef VersionInfos = { var date : String; var name : SemVer;//TODO: this should eventually be called `number` + var downloads : Int; var comments : String; } @@ -49,6 +50,7 @@ typedef ProjectInfos = { var owner : String; var license : String; var curversion : String; + var downloads : Int; var versions : Array; var tags : List; } @@ -58,12 +60,12 @@ abstract DependencyVersion(String) to String from SemVer { this = s; @:to function toValidatable():Validatable - return + return if (this == '') { validate: function () return None } else @:privateAccess new SemVer(this); static public function isValid(s:String) - return toValidatable(s).validate() == None; + return new DependencyVersion(s).toValidatable().validate() == None; static public var DEFAULT(default, null) = new DependencyVersion(''); } @@ -72,10 +74,46 @@ abstract Dependencies(Dynamic) from Dynamic { var fields = Reflect.fields(this); fields.sort(Reflect.compare); - return [for (f in fields) { - name: f, - version: (Reflect.field(this, f) : DependencyVersion), - }]; + + var result:Array = new Array(); + + for (f in fields) { + var value:String = Reflect.field(this, f); + + var isGit = value != null && (value + "").startsWith("git:"); + + if ( !isGit ) + { + result.push ({ + name: f, + type: (DependencyType.Haxelib : DependencyType), + version: (cast value : DependencyVersion), + url: (null : String), + subDir: (null : String), + branch: (null : String), + }); + } + else + { + value = value.substr(4); + var urlParts = value.split("#"); + var url = urlParts[0]; + var branch = urlParts.length > 1 ? urlParts[1] : null; + + result.push ({ + name: f, + type: (DependencyType.Git : DependencyType), + version: (DependencyVersion.DEFAULT : DependencyVersion), + url: (url : String), + subDir: (null : String), + branch: (branch : String), + }); + } + + + } + + return result; } public inline function iterator() return toArray().iterator(); @@ -97,6 +135,9 @@ typedef Dependency = { } typedef Infos = { + // IMPORTANT: if you change this or its fields types, + // make sure to update `schema.json` file accordingly, + // and make an update PR to https://github.com/SchemaStore/schemastore var name : ProjectName; @:optional var url : String; @:optional var description : String; @@ -129,12 +170,10 @@ abstract ProjectName(String) to String { @:to function toValidatable():Validatable return { validate: - function ():Option<{ error: String }> { + function ():Option { for (r in rules) if (!r.check(this)) - return Some( { - error: r.msg.replace('%VALUE', '`' + Json.stringify(this) + '`') - }); + return Some(r.msg.replace('%VALUE', '`' + Json.stringify(this) + '`')); return None; } } @@ -159,12 +198,12 @@ abstract ProjectName(String) to String { a; } - public function validate() + public function validate() return toValidatable().validate(); static public function ofString(s:String) return switch new ProjectName(s) { - case _.toValidatable().validate() => Some({ error: e }): throw e; + case _.toValidatable().validate() => Some(e): throw e; case v: v; } @@ -173,11 +212,10 @@ abstract ProjectName(String) to String { class Data { - public static var JSON = "haxelib.json"; - public static var XML = "haxelib.xml"; - public static var DOCXML = "haxedoc.xml"; - public static var REPOSITORY = "files/3.0"; - public static var alphanum = ~/^[A-Za-z0-9_.-]+$/; + public static var JSON(default, null) = "haxelib.json"; + public static var DOCXML(default, null) = "haxedoc.xml"; + public static var REPOSITORY(default, null) = "files/3.0"; + public static var alphanum(default, null) = ~/^[A-Za-z0-9_.-]+$/; public static function safe( name : String ) { @@ -193,18 +231,18 @@ class Data { public static function fileName( lib : String, ver : String ) { return safe(lib)+"-"+safe(ver)+".zip"; } - + static public function getLatest(info:ProjectInfos, ?preview:SemVer.Preview->Bool):Null { if (info.versions.length == 0) return null; if (preview == null) preview = function (p) return p == null; - + var versions = info.versions.copy(); versions.sort(function (a, b) return -SemVer.compare(a.name, b.name)); - - for (v in versions) + + for (v in versions) if (preview(v.name.preview)) return v.name; - + return versions[0].name; } @@ -217,44 +255,44 @@ class Data { var f = getJson(zip); return f.fileName.substr(0, f.fileName.length - JSON.length); } - + static function getJson(zip:List) return switch topmost(zip, fileNamed(JSON)) { case Some(f): f; default: throw 'No $JSON found'; } - + static function fileNamed(name:String) return function (f:Entry) return f.fileName.endsWith(name); - + static function topmost(zip:List, predicate:Entry->Bool):Option { var best:Entry = null, bestDepth = 0xFFFF; - - for (f in zip) + + for (f in zip) if (predicate(f)) { var depth = f.fileName.replace('\\', '/').split('/').length;//TODO: consider Path.normalize if ((depth == bestDepth && f.fileName < best.fileName) || depth < bestDepth) { best = f; bestDepth = depth; } - } - + } + return - if (best == null) + if (best == null) None; else Some(best); } - - public static function readDoc( zip : List ) : Null + + public static function readDoc( zip : List ) : Null return switch topmost(zip, fileNamed(DOCXML)) { case Some(f): Reader.unzip(f).toString(); case None: null; } - - public static function readInfos( zip : List, check : Bool ) : Infos + + public static function readInfos( zip : List, check : Bool ) : Infos return readData(Reader.unzip(getJson(zip)).toString(), check); public static function checkClassPath( zip : List, infos : Infos ) { @@ -270,56 +308,6 @@ class Data { } } - static function doCheck(doc:Infos) - //return Validator.validate(doc); - return //This is generated from the above macro, which seems not to run in --run mode - (function(v:tools.haxelib.Data.Infos) { - if (!Reflect.isObject(v)) throw "object expected"; - if (Reflect.hasField(v, "classPath") && v.classPath != null) (function(v:StdTypes.Null) if (!Std.is(v, String)) throw "String expected")(v.classPath); - if (!Reflect.hasField(v, "contributors")) throw ("missing field " + "contributors") else { - (function(v:Array) { - if (!Std.is(v, Array)) throw "Array expected"; - for (v in v) (function(v:String) if (!Std.is(v, String)) throw "String expected")(v); - })(v.contributors); - (function(v:Array) { - if (!(v.length > 0)) throw 'Specify at least one contributor'; - })(v.contributors); - }; - if (Reflect.hasField(v, "dependencies") && v.dependencies != null) (function(v:StdTypes.Null) { - if (!Reflect.isObject(v)) throw "object expected"; - for (f in Reflect.fields(v)) { - var v:tools.haxelib.Data.DependencyVersion = Reflect.field(v, f); - switch ((v : tools.haxelib.Validator.Validatable)).validate() { - case Some({ error : e }):{ - throw e; - }; - case None: - }; - }; - })(v.dependencies); - if (Reflect.hasField(v, "description") && v.description != null) (function(v:StdTypes.Null) if (!Std.is(v, String)) throw "String expected")(v.description); - if (!Reflect.hasField(v, "license")) throw ("missing field " + "license") else (function(v:tools.haxelib.Data.License) if (!Lambda.has([tools.haxelib.Data.License.Gpl, tools.haxelib.Data.License.Lgpl, tools.haxelib.Data.License.Mit, tools.haxelib.Data.License.Bsd, tools.haxelib.Data.License.Public, tools.haxelib.Data.License.Apache], v)) throw 'Invalid value ' + v + ' for ' + "License")(v.license); - if (Reflect.hasField(v, "main") && v.main != null) (function(v:StdTypes.Null) if (!Std.is(v, String)) throw "String expected")(v.main); - if (!Reflect.hasField(v, "name")) throw ("missing field " + "name") else (function(v:tools.haxelib.Data.ProjectName) switch ((v : tools.haxelib.Validator.Validatable)).validate() { - case Some({ error : e }):{ - throw e; - }; - case None: - })(v.name); - if (!Reflect.hasField(v, "releasenote")) throw ("missing field " + "releasenote") else (function(v:String) if (!Std.is(v, String)) throw "String expected")(v.releasenote); - if (Reflect.hasField(v, "tags") && v.tags != null) (function(v:StdTypes.Null>) { - if (!Std.is(v, Array)) throw "Array expected"; - for (v in v) (function(v:String) if (!Std.is(v, String)) throw "String expected")(v); - })(v.tags); - if (Reflect.hasField(v, "url") && v.url != null) (function(v:StdTypes.Null) if (!Std.is(v, String)) throw "String expected")(v.url); - if (!Reflect.hasField(v, "version")) throw ("missing field " + "version") else (function(v:tools.haxelib.SemVer) switch ((v : tools.haxelib.Validator.Validatable)).validate() { - case Some({ error : e }):{ - throw e; - }; - case None: - })(v.version); - })(doc); - public static function readData( jsondata: String, check : Bool ) : Infos { var doc:Infos = try Json.parse(jsondata) @@ -337,7 +325,7 @@ class Data { } if (check) - doCheck(doc); + Validator.validate(doc); else { if (!doc.version.valid) doc.version = SemVer.DEFAULT; @@ -361,6 +349,9 @@ class Data { if (doc.description == null) doc.description = ''; + if (doc.tags == null) + doc.tags = []; + if (doc.url == null) doc.url = ''; diff --git a/extra/haxelib_src/src/tools/haxelib/SemVer.hx b/extra/haxelib_src/src/haxelib/SemVer.hx similarity index 50% rename from extra/haxelib_src/src/tools/haxelib/SemVer.hx rename to extra/haxelib_src/src/haxelib/SemVer.hx index 80b76543..9a45cb15 100644 --- a/extra/haxelib_src/src/tools/haxelib/SemVer.hx +++ b/extra/haxelib_src/src/haxelib/SemVer.hx @@ -1,140 +1,177 @@ -package tools.haxelib; - -import haxe.ds.Option; - -using Std; - -enum Preview { - ALPHA; - BETA; - RC; -} - -abstract SemVer(String) to String { - - public var major(get, never):Int; - public var minor(get, never):Int; - public var patch(get, never):Int; - public var preview(get, never):Null; - public var previewNum(get, never):Null; - public var data(get, never):SemVerData; - public var valid(get, never):Bool; - - inline function new(s) this = s; - - static public function compare(a:SemVer, b:SemVer) { - function toArray(data:SemVerData) - return [ - data.major, - data.minor, - data.patch, - if (data.preview == null) 100 else data.preview.getIndex(), - if (data.previewNum == null) -1 else data.previewNum - ]; - - var a = toArray(a.data), - b = toArray(b.data); - - for (i in 0...a.length) - switch Reflect.compare(a[i], b[i]) { - case 0: - case v: return v; - } - - return 0; - } - @:to public function toValidatable():Validator.Validatable - return { - validate: - function ():Option<{ error: String }> - return - try { - get_data(); - None; - } - catch (e:Dynamic) - Some({ - error: Std.string(e) - }) - } - - inline function get_major() - return data.major; - - inline function get_minor() - return data.minor; - - inline function get_patch() - return data.patch; - - inline function get_preview() - return data.preview; - - inline function get_previewNum() - return data.previewNum; - - inline function get_valid() - return isValid(this); - - static var FORMAT = ~/^([0-9]+)\.([0-9]+)\.([0-9]+)(-(alpha|beta|rc)(\.([0-9]+))?)?$/; - - static var cache = new Map(); - - @:to function get_data():SemVerData { - if (!cache.exists(this)) - cache[this] = getData(); - return cache[this]; - } - - @:from static function fromData(data:SemVerData) - return - new SemVer( - data.major + '.' + data.minor + '.' + data.patch + - if (data.preview == null) '' - else '-' + data.preview.getName().toLowerCase() + - if (data.previewNum == null) ''; - else '.' + data.previewNum - ); - - function getData():SemVerData - return - if (valid) {//RAPTORS: This query will already cause the matching. - major: FORMAT.matched(1).parseInt(), - minor: FORMAT.matched(2).parseInt(), - patch: FORMAT.matched(3).parseInt(), - preview: - switch FORMAT.matched(5) { - case 'alpha': ALPHA; - case 'beta': BETA; - case 'rc': RC; - case v if (v == null): null; - case v: throw 'unrecognized preview tag $v'; - }, - previewNum: - switch FORMAT.matched(7) { - case null: null; - case v: v.parseInt(); - } - } - else - throw '$this is not a valid version string';//TODO: include some URL for reference - - static public function isValid(s:String) - return Std.is(s, String) && FORMAT.match(s.toLowerCase()); - - static public function ofString(s:String) { - var ret = new SemVer(s); - ret.getData(); - return ret; - } - - static public var DEFAULT(default, null) = new SemVer('0.0.0'); -} - -typedef SemVerData = { - major:Int, - minor:Int, - patch:Int, - preview:Null, - previewNum:Null, -} +/* + * Copyright (C)2005-2016 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 haxelib; + +import haxe.ds.Option; + +using Std; + +enum Preview { + ALPHA; + BETA; + RC; +} + +abstract SemVer(String) to String { + + public var major(get, never):Int; + public var minor(get, never):Int; + public var patch(get, never):Int; + public var preview(get, never):Null; + public var previewNum(get, never):Null; + public var data(get, never):SemVerData; + public var valid(get, never):Bool; + + inline function new(s) this = s; + + static public function compare(a:SemVer, b:SemVer) { + function toArray(data:SemVerData) + return [ + data.major, + data.minor, + data.patch, + if (data.preview == null) 100 else data.preview.getIndex(), + if (data.previewNum == null) -1 else data.previewNum + ]; + + var a = toArray(a.data), + b = toArray(b.data); + + for (i in 0...a.length) + switch Reflect.compare(a[i], b[i]) { + case 0: + case v: return v; + } + + return 0; + } + @:to public function toValidatable():Validator.Validatable + return { + validate: + function ():Option + return + try { + get_data(); + None; + } + catch (e:Dynamic) + Some(Std.string(e)) + } + + inline function get_major() + return data.major; + + inline function get_minor() + return data.minor; + + inline function get_patch() + return data.patch; + + inline function get_preview() + return data.preview; + + inline function get_previewNum() + return data.previewNum; + + inline function get_valid() + return isValid(this); + + @:op(a > b) static inline function gt(a:SemVer, b:SemVer) + return compare(a, b) == 1; + + @:op(a >= b) static inline function gteq(a:SemVer, b:SemVer) + return compare(a, b) != -1; + + @:op(a < b) static inline function lt(a:SemVer, b:SemVer) + return compare(a, b) == -1; + + @:op(a <= b) static inline function lteq(a:SemVer, b:SemVer) + return compare(a, b) != 1; + + @:op(a == b) static inline function eq(a:SemVer, b:SemVer) + return compare(a, b) == 0; + + @:op(a != b) static inline function neq(a:SemVer, b:SemVer) + return compare(a, b) != 0; + + static var FORMAT = ~/^(\d|[1-9]\d*)\.(\d|[1-9]\d*)\.(\d|[1-9]\d*)(-(alpha|beta|rc)(\.(\d|[1-9]\d*))?)?$/; + + static var cache = new Map(); + + @:to function get_data():SemVerData { + if (!cache.exists(this)) + cache[this] = getData(); + return cache[this]; + } + + @:from static function fromData(data:SemVerData) + return + new SemVer( + data.major + '.' + data.minor + '.' + data.patch + + if (data.preview == null) '' + else '-' + data.preview.getName().toLowerCase() + + if (data.previewNum == null) ''; + else '.' + data.previewNum + ); + + function getData():SemVerData + return + if (valid) {//RAPTORS: This query will already cause the matching. + major: FORMAT.matched(1).parseInt(), + minor: FORMAT.matched(2).parseInt(), + patch: FORMAT.matched(3).parseInt(), + preview: + switch FORMAT.matched(5) { + case 'alpha': ALPHA; + case 'beta': BETA; + case 'rc': RC; + case v if (v == null): null; + case v: throw 'unrecognized preview tag $v'; + }, + previewNum: + switch FORMAT.matched(7) { + case null: null; + case v: v.parseInt(); + } + } + else + throw '$this is not a valid version string';//TODO: include some URL for reference + + static public function isValid(s:String) + return Std.is(s, String) && FORMAT.match(s.toLowerCase()); + + static public function ofString(s:String) { + var ret = new SemVer(s); + ret.getData(); + return ret; + } + + static public var DEFAULT(default, null) = new SemVer('0.0.0'); +} + +typedef SemVerData = { + major:Int, + minor:Int, + patch:Int, + preview:Null, + previewNum:Null, +} diff --git a/extra/haxelib_src/src/tools/haxelib/SiteApi.hx b/extra/haxelib_src/src/haxelib/SiteApi.hx similarity index 90% rename from extra/haxelib_src/src/tools/haxelib/SiteApi.hx rename to extra/haxelib_src/src/haxelib/SiteApi.hx index 4e988580..2bb1f858 100644 --- a/extra/haxelib_src/src/tools/haxelib/SiteApi.hx +++ b/extra/haxelib_src/src/haxelib/SiteApi.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-2016 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,20 +19,21 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package tools.haxelib; +package haxelib; -import tools.haxelib.Data; +import haxelib.Data; interface SiteApi { public function search( word : String ) : List<{ id : Int, name : String }>; public function infos( project : String ) : ProjectInfos; + public function getLatestVersion( project : String ) : SemVer; public function user( name : String ) : UserInfos; - public function register( name : String, pass : String, mail : String, fullname : String ) : Bool; + public function register( name : String, pass : String, mail : String, fullname : String ) : Void; public function isNewUser( name : String ) : Bool; public function checkDeveloper( prj : String, user : String ) : Void; public function checkPassword( user : String, pass : String ) : Bool; public function getSubmitId() : String; - + public function processSubmit( id : String, user : String, pass : String ) : String; public function postInstall( project : String, version : String):Void; diff --git a/extra/haxelib_src/src/tools/haxelib/Validator.hx b/extra/haxelib_src/src/haxelib/Validator.hx similarity index 63% rename from extra/haxelib_src/src/tools/haxelib/Validator.hx rename to extra/haxelib_src/src/haxelib/Validator.hx index bec27b38..34c984f6 100644 --- a/extra/haxelib_src/src/tools/haxelib/Validator.hx +++ b/extra/haxelib_src/src/haxelib/Validator.hx @@ -1,4 +1,25 @@ -package tools.haxelib; +/* + * Copyright (C)2005-2016 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 haxelib; import haxe.ds.Option; @@ -11,7 +32,7 @@ using haxe.macro.Tools; #end typedef Validatable = { - function validate():Option<{ error: String }>; + function validate():Option; } class Validator { @@ -23,119 +44,119 @@ class Validator { this.pos = pos; IARG = macro @:pos(pos) $i{ARG}; } - + function doCheck(t:Type, e:Expr) { var ct = t.toComplexType(); return macro @:pos (function ($ARG : $ct) ${makeCheck(t)})($e); } - + function isAtom(s:String) return switch s { case 'String', 'Int', 'Bool', 'Float': true; default: false; } - + function enforce(type:String) - return + return macro @:pos(pos) if (!Std.is($i{ARG}, $i{type})) throw '$type expected'; - - function rename(e:Expr) + + function rename(e:Expr) return switch e { case macro $i{name} if (name == '_'): IARG; default: e.map(rename); } - - function makeCheck(t:Type):Expr + + function makeCheck(t:Type):Expr return switch Context.follow(t) { - case TAnonymous(_.get().fields => fields): - + case TAnonymous(_.get().fields => fields): + var block:Array = [ for (f in fields) if (f.kind.match(FVar(AccNormal, _))) { var name = f.name; var rec = doCheck(f.type, macro @:pos(pos) $IARG.$name); - + if (f.meta.has(':requires')) { var body = []; - for (m in f.meta.get()) + for (m in f.meta.get()) if (m.name == ':requires') - for (p in m.params) + for (p in m.params) switch p { case macro $msg => $p: body.push(rename( macro @:pos(pos) if (!$p) throw $msg )); - default: - Context.error('Should be "" =>" ', p.pos); + default: + Context.error('Should be "" =>" ', p.pos); } //{ //p = rename(p); //cond = macro @:pos(pos) $p && $cond; //} - + var t = f.type.toComplexType(); rec = macro @:pos(pos) { $rec; (function($ARG : $t) $b{body})($IARG.$name); } - } - + } + if (f.meta.has(':optional')) { rec = macro @:pos(pos) if (Reflect.hasField($IARG, $v{name}) && $IARG.$name != null) $rec; } else - rec = macro @:pos(pos) - if (!Reflect.hasField($IARG, $v{name})) + rec = macro @:pos(pos) + if (!Reflect.hasField($IARG, $v{name})) throw ("missing field " + $v{name}); - else + else $rec; - + rec; } ]; - + block.unshift( macro @:pos(pos) if (!Reflect.isObject($IARG)) throw 'object expected' ); - + macro @:pos(pos) $b{block}; - - case _.toString() => atom if (isAtom(atom)): - + + case _.toString() => atom if (isAtom(atom)): + enforce(atom); - + case TInst(_.get().module => 'Array', [p]): - + macro @:pos(pos) { ${enforce('Array')}; for ($IARG in $IARG) ${doCheck(p, IARG)}; } - + case TAbstract(_.get() => { from: [ { t: t, field: null } ] }, _): - + makeCheck(t); - + case TAbstract(_.get() => a, _) if (a.meta.has(':enum')): var name = a.module + '.' + a.name; var options:Array = [ - for (f in a.impl.get().statics.get()) + for (f in a.impl.get().statics.get()) if (f.kind.match(FVar(_, _))) macro @:pos(pos) $p{(name+'.'+f.name).split('.')} ]; - + macro if (!Lambda.has($a { options }, $IARG)) throw 'Invalid value ' + $IARG + ' for ' + $v { a.name }; - + case TAbstract(_.get() => a, _): - - macro @:pos(pos) switch ($IARG : tools.haxelib.Validator.Validatable).validate() { - case Some( { error: e } ): throw e; + + macro @:pos(pos) switch ($IARG : haxelib.Validator.Validatable).validate() { + case Some(e): throw e; case None: } - + case TDynamic(k): var checker = makeCheck(k); var ct = k.toComplexType(); @@ -146,11 +167,11 @@ class Validator { $checker; } } - case v: + case v: throw t.toString(); } - #end - macro static public function validate(e:Expr) - return + #end + macro static public function validate(e:Expr) + return new Validator(e.pos).doCheck(Context.typeof(e), e); } \ No newline at end of file diff --git a/extra/haxelib_src/src/haxelib/client/Cli.hx b/extra/haxelib_src/src/haxelib/client/Cli.hx new file mode 100644 index 00000000..b0c5fbea --- /dev/null +++ b/extra/haxelib_src/src/haxelib/client/Cli.hx @@ -0,0 +1,46 @@ +/* + * Copyright (C)2005-2016 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 haxelib.client; + +class Cli { + public static var defaultAnswer:Null; + + public static function ask(question:String):Bool { + if (defaultAnswer != null) + return defaultAnswer; + + while (true) { + Sys.print(question + " [y/n/a] ? "); + try { + switch (Sys.stdin().readLine()) { + case "n": return false; + case "y": return true; + case "a": return defaultAnswer = true; + } + } catch (e:haxe.io.Eof) { + Sys.println("n"); + return false; + } + } + return false; + } +} diff --git a/extra/haxelib_src/src/tools/haxelib/ConvertXml.hx b/extra/haxelib_src/src/haxelib/client/ConvertXml.hx similarity index 51% rename from extra/haxelib_src/src/tools/haxelib/ConvertXml.hx rename to extra/haxelib_src/src/haxelib/client/ConvertXml.hx index a4f97c5f..b7196033 100644 --- a/extra/haxelib_src/src/tools/haxelib/ConvertXml.hx +++ b/extra/haxelib_src/src/haxelib/client/ConvertXml.hx @@ -1,8 +1,29 @@ -package tools.haxelib; +/* + * Copyright (C)2005-2016 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 haxelib.client; + import haxe.Json; -class ConvertXml -{ +class ConvertXml { public static function convert(inXml:String) { // Set up the default JSON structure var json = { @@ -23,14 +44,11 @@ class ConvertXml json.name = project.get("name"); json.license = project.get("license"); json.url = project.get("url"); - for (node in project) - { - switch (node.nodeType) - { - case Xml.Element: - switch (node.nodeName) - { - case "tag": + for (node in project) { + switch (node.nodeType) { + case #if (haxe_ver >= 3.2) Element #else Xml.Element #end: + switch (node.nodeName) { + case "tag": json.tags.push(node.get("v")); case "user": json.contributors.push(node.get("name")); @@ -44,9 +62,9 @@ class ConvertXml var version = node.get("version"); if (version == null) version = ""; Reflect.setField(json.dependencies, name, version); - default: + default: } - default: + default: } } @@ -58,8 +76,7 @@ class ConvertXml sb.add("{\n"); var firstRun = true; - for (f in Reflect.fields(json)) - { + for (f in Reflect.fields(json)) { if (!firstRun) sb.add(",\n"); firstRun = false; @@ -67,7 +84,7 @@ class ConvertXml case "dependencies": var d = Reflect.field(json, f); prettyPrint(d, indent + " "); - default: + default: Json.stringify(Reflect.field(json, f)); } sb.add(indent+' "$f": $value'); @@ -76,4 +93,4 @@ class ConvertXml sb.add('\n$indent}'); return sb.toString(); } -} \ No newline at end of file +} diff --git a/extra/haxelib_src/src/haxelib/client/FsUtils.hx b/extra/haxelib_src/src/haxelib/client/FsUtils.hx new file mode 100644 index 00000000..74925836 --- /dev/null +++ b/extra/haxelib_src/src/haxelib/client/FsUtils.hx @@ -0,0 +1,131 @@ +/* + * Copyright (C)2005-2016 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 haxelib.client; + +import haxe.io.Path; +import sys.FileSystem; +using StringTools; + +class FsUtils { + static var IS_WINDOWS = (Sys.systemName() == "Windows"); + + //recursively follow symlink + public static function realPath(path:String):String { + var proc = new sys.io.Process('readlink', [path.endsWith("\n") ? path.substr(0, path.length-1) : path]); + var ret = switch (proc.stdout.readAll().toString()) { + case "": //it is not a symlink + path; + case targetPath: + if (targetPath.startsWith("/")) { + realPath(targetPath); + } else { + realPath(new Path(path).dir + "/" + targetPath); + } + } + proc.close(); + return ret; + } + + public static function isSamePath(a:String, b:String):Bool { + a = Path.normalize(a); + b = Path.normalize(b); + if (IS_WINDOWS) { // paths are case-insensitive on Windows + a = a.toLowerCase(); + b = b.toLowerCase(); + } + return a == b; + } + + public static function safeDir(dir:String, checkWritable = false):Bool { + if (FileSystem.exists(dir)) { + if (!FileSystem.isDirectory(dir)) + throw 'A file is preventing $dir to be created'; + if (checkWritable) { + var checkFile = dir+"/haxelib_writecheck.txt"; + try { + sys.io.File.saveContent(checkFile, "This is a temporary file created by Haxelib to check if directory is writable. You can safely delete it!"); + } catch (_:Dynamic) { + throw '$dir exists but is not writeable, chmod it'; + } + FileSystem.deleteFile(checkFile); + } + return false; + } else { + try { + FileSystem.createDirectory(dir); + return true; + } catch (_:Dynamic) { + throw 'You don\'t have enough user rights to create the directory $dir'; + } + } + } + + public static function deleteRec(dir:String):Bool { + if (!FileSystem.exists(dir)) + return false; + for (p in FileSystem.readDirectory(dir)) { + var path = Path.join([dir, p]); + + if (isBrokenSymlink(path)) { + safeDelete(path); + } else if (FileSystem.isDirectory(path)) { + if (!IS_WINDOWS) { + // try to delete it as a file first - in case of path + // being a symlink, it will success + if (!safeDelete(path)) + deleteRec(path); + } else { + deleteRec(path); + } + } else { + safeDelete(path); + } + } + FileSystem.deleteDirectory(dir); + return true; + } + + static function safeDelete(file:String):Bool { + try { + FileSystem.deleteFile(file); + return true; + } catch (e:Dynamic) { + if (IS_WINDOWS) { + try { + Sys.command("attrib", ["-R", file]); + FileSystem.deleteFile(file); + return true; + } catch (_:Dynamic) { + } + } + return false; + } + } + + static function isBrokenSymlink(path:String):Bool { + // TODO: figure out what this method actually does :) + var errors = 0; + try FileSystem.isDirectory(path) catch (error:String) if (error == "std@sys_file_type") errors++; + try FileSystem.fullPath(path) catch (error:String) if (error == "std@file_full_path") errors++; + return errors == 2; + } +} diff --git a/extra/haxelib_src/src/tools/haxelib/Main.hx b/extra/haxelib_src/src/haxelib/client/Main.hx similarity index 50% rename from extra/haxelib_src/src/tools/haxelib/Main.hx rename to extra/haxelib_src/src/haxelib/client/Main.hx index dc188155..9f9f34de 100644 --- a/extra/haxelib_src/src/tools/haxelib/Main.hx +++ b/extra/haxelib_src/src/haxelib/client/Main.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-2016 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package tools.haxelib; +package haxelib.client; import haxe.crypto.Md5; import haxe.*; @@ -30,41 +30,41 @@ import sys.io.File; import sys.FileSystem; import sys.io.*; import haxe.ds.Option; -import tools.haxelib.Vcs; +import haxelib.client.Cli.ask; +import haxelib.client.FsUtils.*; +import haxelib.client.Vcs; using StringTools; using Lambda; -using tools.haxelib.Data; - -enum Answer { - Yes; - No; -} +using haxelib.Data; private enum CommandCategory { Basic; Information; Development; Miscellaneous; + Deprecated(msg:String); } -class SiteProxy extends haxe.remoting.Proxy { +class SiteProxy extends haxe.remoting.Proxy { } -class Progress extends haxe.io.Output { +class ProgressOut extends haxe.io.Output { var o : haxe.io.Output; var cur : Int; - var max : Int; + var startSize : Int; + var max : Null; var start : Float; - public function new(o) { + public function new(o, currentSize) { this.o = o; - cur = 0; + startSize = currentSize; + cur = currentSize; start = Timer.stamp(); } - function bytes(n) { + function report(n) { cur += n; if( max == null ) Sys.print(cur+" bytes\r"); @@ -74,12 +74,12 @@ class Progress extends haxe.io.Output { public override function writeByte(c) { o.writeByte(c); - bytes(1); + report(1); } public override function writeBytes(s,p,l) { var r = o.writeBytes(s,p,l); - bytes(r); + report(r); return r; } @@ -87,14 +87,15 @@ class Progress extends haxe.io.Output { super.close(); o.close(); var time = Timer.stamp() - start; - var speed = (cur / time) / 1024; + var downloadedBytes = cur - startSize; + var speed = (downloadedBytes / time) / 1024; time = Std.int(time * 10) / 10; speed = Std.int(speed * 10) / 10; - Sys.print("Download complete : "+cur+" bytes in "+time+"s ("+speed+"KB/s)\n"); + Sys.print("Download complete : "+downloadedBytes+" bytes in "+time+"s ("+speed+"KB/s)\n"); } public override function prepare(m) { - max = m; + max = m + startSize; } } @@ -113,147 +114,27 @@ class ProgressIn extends haxe.io.Input { public override function readByte() { var c = i.readByte(); - doRead(1); + report(1); return c; } public override function readBytes(buf,pos,len) { var k = i.readBytes(buf,pos,len); - doRead(k); + report(k); return k; } - function doRead( nbytes : Int ) { + function report( nbytes : Int ) { pos += nbytes; Sys.print( Std.int((pos * 100.0) / tot) + "%\r" ); } } -enum CliError -{ - CwdUnavailable(pwd:String); - CantSetSwd_DirNotExist(dir:String); -} - -class Cli -{ - public var defaultAnswer(get, set):Answer; - private static var defaultAnswer_global:Answer; - - public var cwd(get_cwd, set_cwd):String; - private static var cwd_cache:String = null; - - - public function new() - defaultAnswer = null; - - - function get_cwd():String - { - var result:String = null; - - try - { - cwd_cache = Sys.getCwd(); - } - catch(error:String) - tryFixGetCwdError(error); - - return cwd_cache; - } - - function set_cwd(value:String):String - { - //TODO: For call `FileSystem.isDirectory(value)` we can get an exeption "std@sys_file_type": - if(value != null && cwd_cache != value && FileSystem.exists(value) && FileSystem.isDirectory(value)) - Sys.setCwd(cwd_cache = value); - else - throw CliError.CantSetSwd_DirNotExist(value); - return cwd_cache; - } - - - function tryFixGetCwdError(error:String) - { - switch(error) - { - case "std@get_cwd" | "std@file_path" | "std@file_full_path": - { - var pwd = Sys.getEnv("PWD"); - // This is a magic for issue #196: - // if we have $PWD then we can re-set it again. - // Works for case: `$ mkdir temp; cd temp; rm -r ../temp; mkdir ../temp; haxelib upgrade;` - if(pwd != null) - { - if(FileSystem.exists(pwd) && FileSystem.isDirectory(pwd)) - // Trying fix it: setting cwd to pwd - Sys.setCwd(cwd_cache = pwd); - else - // Can't fix it. - throw CliError.CwdUnavailable(pwd); - } - else throw CliError.CwdUnavailable(pwd); - } - default: throw error; - } - } - - - function get_defaultAnswer():Answer - { - return defaultAnswer_global; - } - - function set_defaultAnswer(value:Answer):Answer - { - defaultAnswer_global = value; - return defaultAnswer_global; - } - - - public function ask(question):Answer - { - if(defaultAnswer != null) - return defaultAnswer; - - while(true) - { - Sys.print(question + " [y/n/a] ? "); - try{ - switch(Sys.stdin().readLine()) - { - case "n": return No; - case "y": return Yes; - case "a": return defaultAnswer = Yes; - } - } - catch(e:haxe.io.Eof) - { - Sys.println("n"); - return No; - } - } - return null; - } - - public function command(cmd:String, args:Array) - { - var p = new sys.io.Process(cmd, args); - var code = p.exitCode(); - return {code:code, out:(code == 0 ? p.stdout.readAll().toString() : p.stderr.readAll().toString())}; - } - - public function print(str):Void - { - Sys.print(str + "\n"); - } -} - class Main { + static inline var HAXELIB_LIBNAME = "haxelib"; - static var VERSION = SemVer.ofString('3.2.0-rc.3'); - static var APIVERSION = SemVer.ofString('3.0.0'); + static var VERSION = SemVer.ofString('3.3.0'); static var REPNAME = "lib"; static var REPODIR = ".haxelib"; static var SERVER = { @@ -261,26 +142,29 @@ class Main { port : 80, dir : "", url : "index.n", - apiVersion : APIVERSION.major+"."+APIVERSION.minor, + apiVersion : "3.0", }; + static var IS_WINDOWS = (Sys.systemName() == "Windows"); - var cli:Cli; var argcur : Int; var args : Array; var commands : List<{ name : String, doc : String, f : Void -> Void, net : Bool, cat : CommandCategory }>; var siteUrl : String; var site : SiteProxy; + var isHaxelibRun : Bool; + var alreadyUpdatedVcsDependencies:Map = new Map(); - function new() - { - cli = new Cli(); + function new() { args = Sys.args(); + isHaxelibRun = (Sys.getEnv("HAXELIB_RUN_NAME") == HAXELIB_LIBNAME); + + if (isHaxelibRun) + Sys.setCwd(args.pop()); commands = new List(); addCommand("install", install, "install a given library, or all libraries from a hxml file", Basic); - addCommand("upgrade", upgrade, "upgrade all installed libraries", Basic); - addCommand("update", update, "update a single library", Basic); + addCommand("update", update, "update a single library (if given) or all installed libraries", Basic); addCommand("remove", remove, "remove a given library/version", Basic, false); addCommand("list", list, "list all installed libraries", Basic, false); addCommand("set", set, "set the current version for a library", Basic, false); @@ -295,24 +179,30 @@ class Main { addCommand("submit", submit, "submit or update a library package", Development); addCommand("register", register, "register a new user", Development); - addCommand("local", local, "install the specified package locally", Development, false); addCommand("dev", dev, "set the development directory for a given library", Development, false); //TODO: generate command about VCS by Vcs.getAll() - addCommand("git", function()doVcs(VcsID.Git), "use Git repository as library", Development); - addCommand("hg", function()doVcs(VcsID.Hg), "use Mercurial (hg) repository as library", Development); + addCommand("git", vcs.bind(VcsID.Git), "use Git repository as library", Development); + addCommand("hg", vcs.bind(VcsID.Hg), "use Mercurial (hg) repository as library", Development); addCommand("setup", setup, "set the haxelib repository path", Miscellaneous, false); - addCommand("newrepo", newRepo, "[EXPERIMENTAL] create a new local repository", Miscellaneous, false); + addCommand("newrepo", newRepo, "create a new local repository", Miscellaneous, false); addCommand("deleterepo", deleteRepo, "delete the local repository", Miscellaneous, false); - addCommand("selfupdate", updateSelf, "update haxelib itself", Miscellaneous); addCommand("convertxml", convertXml, "convert haxelib.xml file to haxelib.json", Miscellaneous); addCommand("run", run, "run the specified library with parameters", Miscellaneous, false); addCommand("proxy", proxy, "setup the Http proxy", Miscellaneous); + // deprecated commands + addCommand("local", local, "install the specified package locally", Deprecated("Use `haxelib install ` instead"), false); + addCommand("selfupdate", updateSelf, "update haxelib itself", Deprecated('Use `haxelib --global update $HAXELIB_LIBNAME` instead')); + initSite(); } - + function checkUpdate() { + var latest = try site.getLatestVersion(HAXELIB_LIBNAME) catch (_:Dynamic) null; + if (latest != null && latest > VERSION) + print('\nA new version ($latest) of haxelib is available.\nDo `haxelib --global update $HAXELIB_LIBNAME` to get the latest version.\n'); + } function initSite() { siteUrl = "http://" + SERVER.host + ":" + SERVER.port + "/" + SERVER.dir; @@ -337,9 +227,6 @@ class Main { return Sys.stdin().readLine(); } - inline function ask(question) - return cli.ask(question); - function paramOpt() { if( args.length > argcur ) return args[argcur++]; @@ -359,12 +246,13 @@ class Main { var maxLength = 0; for( c in commands ) { if (c.name.length > maxLength) maxLength = c.name.length; + if (c.cat.match(Deprecated(_))) continue; var i = c.cat.getIndex(); if (cats[i] == null) cats[i] = [c]; else cats[i].push(c); } - print("Haxe Library Manager " + VERSION + " - (c)2006-2015 Haxe Foundation"); + print("Haxe Library Manager " + VERSION + " - (c)2006-2016 Haxe Foundation"); print(" Usage: haxelib [command] [options]"); for (cat in cats) { @@ -380,28 +268,34 @@ class Main { } static var ABOUT_SETTINGS = { global : "force global repo if a local one exists", - debug : "run in debug mode", + debug : "run in debug mode, imply not --quiet", + quiet : "print less messages, imply not --debug", flat : "do not use --recursive cloning for git", always : "answer all questions with yes", - never : "answer all questions with no" + never : "answer all questions with no", + system : "run bundled haxelib version instead of latest update", } var settings: { debug : Bool, + quiet : Bool, flat : Bool, always : Bool, never : Bool, global : Bool, + system : Bool, }; function process() { argcur = 0; var rest = []; settings = { debug: false, + quiet: false, always: false, never: false, flat: false, global: false, + system: false, }; function parseSwitch(s:String) { @@ -417,7 +311,21 @@ class Main { while ( argcur < args.length) { var a = args[argcur++]; switch( a ) { - case '-cwd': cli.cwd = args[argcur++]; + case '-cwd': + var dir = args[argcur++]; + if (dir == null) { + print("Missing directory argument for -cwd"); + Sys.exit(1); + } + try { + Sys.setCwd(dir); + } catch (e:String) { + if (e == "std@set_cwd") { + print("Directory " + dir + " unavailable"); + Sys.exit(1); + } + neko.Lib.rethrow(e); + } case "-notimeout": haxe.remoting.HttpConnection.TIMEOUT = 0; case "-R": @@ -431,6 +339,12 @@ class Main { SERVER.dir = r.matched(4); if (SERVER.dir.length > 0 && !SERVER.dir.endsWith("/")) SERVER.dir += "/"; initSite(); + case "--debug": + settings.debug = true; + settings.quiet = false; + case "--quiet": + settings.debug = false; + settings.quiet = true; case parseSwitch(_) => Some(s) if (Reflect.hasField(settings, s)): //if (!Reflect.hasField(settings, s)) { //print('unknown switch $a'); @@ -445,14 +359,23 @@ class Main { } } - cli.defaultAnswer = + if (!isHaxelibRun && !settings.system) { + var rep = try getGlobalRepository() catch (_:Dynamic) null; + if (rep != null && FileSystem.exists(rep + HAXELIB_LIBNAME)) { + argcur = 0; // send all arguments + doRun(rep, HAXELIB_LIBNAME, null); + return; + } + } + + Cli.defaultAnswer = switch [settings.always, settings.never] { case [true, true]: print('--always and --never are mutually exclusive'); Sys.exit(1); null; - case [true, _]: Yes; - case [_, true]: No; + case [true, _]: true; + case [_, true]: false; default: null; } @@ -464,10 +387,19 @@ class Main { usage(); Sys.exit(1); } + if (cmd == "upgrade") cmd = "update"; // TODO: maybe we should have some alias system for( c in commands ) if( c.name == cmd ) { + switch (c.cat) { + case Deprecated(message): + Sys.println('Warning: Command `$cmd` is deprecated and will be removed in future. $message.'); + default: + } try { - if( c.net ) loadProxy(); + if( c.net ) { + loadProxy(); + checkUpdate(); + } c.f(); } catch( e : Dynamic ) { if( e == "std@host_resolve" ) { @@ -483,9 +415,13 @@ class Main { print("Http connection timeout. Try running haxelib -notimeout to disable timeout"); Sys.exit(1); } + if( e == "std@get_cwd" ) { + print("Error: Current working directory is unavailable"); + Sys.exit(1); + } if( settings.debug ) neko.Lib.rethrow(e); - print(Std.string(e)); + print("Error: " + Std.string(e)); Sys.exit(1); } return; @@ -495,6 +431,13 @@ class Main { Sys.exit(1); } + inline function createHttpRequest(url:String):Http { + var req = new Http(url); + if (haxe.remoting.HttpConnection.TIMEOUT == 0) + req.cnxTimeout = 0; + return req; + } + // ---- COMMANDS -------------------- function search() { @@ -552,40 +495,45 @@ class Main { return pass; } - function submit() { - var file = param("Package"), - data = null; - var zip = - if (FileSystem.isDirectory(file)) { - var ret = new List(), - out = new BytesOutput(); - function seek(dir:String) { - for (name in FileSystem.readDirectory(dir)) if (!name.startsWith('.')) { - var full = '$dir/$name'; - if (FileSystem.isDirectory(full)) seek(full); - else { - var blob = File.getBytes(full); - ret.push({ - fileName: full.substr(file.length+1), - fileSize : blob.length, - fileTime : FileSystem.stat(full).mtime, - compressed : false, - dataSize : blob.length, - data : blob, - crc32: null,//TODO: consider calculating this one - }); - } - } + function zipDirectory(root:String):List { + var ret = new List(); + function seek(dir:String) { + for (name in FileSystem.readDirectory(dir)) if (!name.startsWith('.')) { + var full = '$dir/$name'; + if (FileSystem.isDirectory(full)) seek(full); + else { + var blob = File.getBytes(full); + var entry:Entry = { + fileName: full.substr(root.length+1), + fileSize : blob.length, + fileTime : FileSystem.stat(full).mtime, + compressed : false, + dataSize : blob.length, + data : blob, + crc32: haxe.crypto.Crc32.make(blob), + }; + Tools.compress(entry, 9); + ret.push(entry); } - seek(file); - new Writer(out).write(ret); - data = out.getBytes(); - ret; - } - else { - data = File.getBytes(file); - Reader.readZip(File.read(file, true)); } + } + seek(root); + return ret; + } + + function submit() { + var file = param("Package"); + + var data, zip; + if (FileSystem.isDirectory(file)) { + zip = zipDirectory(file); + var out = new BytesOutput(); + new Writer(out).write(zip); + data = out.getBytes(); + } else { + data = File.getBytes(file); + zip = Reader.readZip(new haxe.io.BytesInput(data)); + } var infos = Data.readInfos(zip,true); Data.checkClassPath(zip, infos); @@ -596,7 +544,7 @@ class Main { do { print("Which of these users are you: " + infos.contributors); user = param("User"); - } while ( !Lambda.has(infos.contributors, user) ); + } while ( infos.contributors.indexOf(user) == -1 ); var password; if( site.isNewUser(user) ) { @@ -604,14 +552,7 @@ class Main { print("Please enter the following informations for registration"); password = doRegister(user); } else { - password = Md5.encode(param("Password",true)); - var attempts = 5; - while ( !site.checkPassword(user, password)) { - print ("Invalid password for " + user); - if (--attempts == 0) - throw 'Failed to input correct password'; - password = Md5.encode(param('Password ($attempts more attempt${attempts == 1 ? "" : "s"})', true)); - } + password = readPassword(user); } site.checkDeveloper(infos.name,user); @@ -635,15 +576,15 @@ class Main { var sinfos = try site.infos(infos.name) catch( _ : Dynamic ) null; if( sinfos != null ) for( v in sinfos.versions ) - if( v.name == infos.version && ask("You're about to overwrite existing version '"+v.name+"', please confirm") == No ) + if( v.name == infos.version && !ask("You're about to overwrite existing version '"+v.name+"', please confirm") ) throw "Aborted"; // query a submit id that will identify the file var id = site.getSubmitId(); // directly send the file data over Http - var h = new Http("http://"+SERVER.host+":"+SERVER.port+"/"+SERVER.url); - h.onError = function(e) { throw e; }; + var h = createHttpRequest("http://"+SERVER.host+":"+SERVER.port+"/"+SERVER.url); + h.onError = function(e) throw e; h.onData = print; h.fileTransfer("file",id,new ProgressIn(new haxe.io.BytesInput(data),data.length),data.length); print("Sending data.... "); @@ -651,33 +592,51 @@ class Main { // processing might take some time, make sure we wait print("Processing file.... "); - haxe.remoting.HttpConnection.TIMEOUT = 1000; + if (haxe.remoting.HttpConnection.TIMEOUT != 0) // don't ignore -notimeout + haxe.remoting.HttpConnection.TIMEOUT = 1000; // ask the server to register the sent file var msg = site.processSubmit(id,user,password); print(msg); } + function readPassword(user:String, prompt = "Password"):String { + var password = Md5.encode(param(prompt,true)); + var attempts = 5; + while (!site.checkPassword(user, password)) { + print('Invalid password for $user'); + if (--attempts == 0) + throw 'Failed to input correct password'; + password = Md5.encode(param('$prompt ($attempts more attempt${attempts == 1 ? "" : "s"})', true)); + } + return password; + } + function install() { + var rep = getRepository(); + var prj = param("Library name or hxml file:"); // No library given, install libraries listed in *.hxml in given directory - if( prj == "all") - { - installFromAllHxml(); + if( prj == "all") { + installFromAllHxml(rep); return; } if( sys.FileSystem.exists(prj) && !sys.FileSystem.isDirectory(prj) ) { // *.hxml provided, install all libraries/versions in this hxml file - if( prj.endsWith(".hxml") ) - { - installFromHxml(prj); + if( prj.endsWith(".hxml") ) { + installFromHxml(rep, prj); return; } // *.zip provided, install zip as haxe library - if( prj.endsWith(".zip") ) + if (prj.endsWith(".zip")) { + doInstallFile(rep, prj, true, true); + return; + } + + if ( prj.endsWith("haxelib.json") ) { - doInstallFile(prj,true,true); + installFromHaxelibJson( rep, prj); return; } } @@ -686,11 +645,10 @@ class Main { var inf = site.infos(prj); var reqversion = paramOpt(); var version = getVersion(inf, reqversion); - doInstall(inf.name,version,version == inf.getLatest()); + doInstall(rep,inf.name,version,version == inf.getLatest()); } - function getVersion( inf:ProjectInfos, ?reqversion:String ) - { + function getVersion( inf:ProjectInfos, ?reqversion:String ) { if( inf.versions.length == 0 ) throw "The library "+inf.name+" has not yet released a version"; var version = if( reqversion != null ) reqversion else inf.getLatest(); @@ -706,133 +664,189 @@ class Main { return version; } - function installFromHxml( path ) - { - var hxml = sys.io.File.getContent(path); - var lines = hxml.split("\n"); + function installFromHxml( rep:String, path:String ) { var targets = [ '-java ' => 'hxjava', '-cpp ' => 'hxcpp', '-cs ' => 'hxcs', ]; - var libsToInstall = new Map(); - for (l in lines) { - l = l.trim(); - for (target in targets.keys()) - if (l.startsWith(target)) { - var lib = targets[target]; - if (!libsToInstall.exists(lib)) - libsToInstall[lib] = { name: lib, version: null } - } - - if (l.startsWith("-lib")) - { - var key = l.substr(5); - var parts = key.split(":"); - var libName = parts[0].trim(); - var libVersion = if (parts.length > 1) parts[1].trim() else null; - - switch libsToInstall[key] { - case null, { version: null } : - libsToInstall.set(key, { name:libName, version:libVersion } ); - default: - } - } - } - installMany(libsToInstall); - } + var libsToInstall = new Map(); + + function processHxml(path) { + var hxml = sys.io.File.getContent(path); + var lines = hxml.split("\n"); + for (l in lines) { + l = l.trim(); + for (target in targets.keys()) + if (l.startsWith(target)) { + var lib = targets[target]; + if (!libsToInstall.exists(lib)) + libsToInstall[lib] = { name: lib, version: null, type:"haxelib", url: null, branch: null, subDir: null } + } - function installFromAllHxml() - { - var hxmlFiles = sys.FileSystem.readDirectory(cli.cwd).filter(function (f) return f.endsWith(".hxml")); - if (hxmlFiles.length > 0) - { - for (file in hxmlFiles) - { - if (file.endsWith(".hxml")) + if (l.startsWith("-lib")) { - print('Installing all libraries from $file:'); - installFromHxml(cli.cwd+file); + var key = l.substr(5).trim(); + var parts = ~/:/.split(key); + var libName = parts[0]; + var libVersion:String = null; + var branch:String = null; + var url:String = null; + var subDir:String = null; + var type:String; + + if ( parts.length > 1 ) + { + if ( parts[1].startsWith("git:") ) + { + + type = "git"; + var urlParts = parts[1].substr(4).split("#"); + url = urlParts[0]; + branch = urlParts.length > 1 ? urlParts[1] : null; + } + else + { + type = "haxelib"; + libVersion = parts[1]; + } + } + else + { + type = "haxelib"; + } + + switch libsToInstall[key] { + case null, { version: null } : + libsToInstall.set(key, { name:libName, version:libVersion, type: type, url: url, subDir: subDir, branch: branch } ); + default: + } } + + if (l.endsWith(".hxml")) + processHxml(l); } } - else - { - print ("No hxml files found in the current directory."); - } - } + processHxml(path); - function installMany( libs:Iterable<{name:String,version:String}>, ?setCurrent=true ) - { - if (Lambda.count(libs) == 0) return; + if (libsToInstall.empty()) + return; // Check the version numbers are all good // TODO: can we collapse this into a single API call? It's getting too slow otherwise. print("Loading info about the required libraries"); - for (l in libs) + for (l in libsToInstall) { + if ( l.type == "git" ) + { + // Do not check git repository infos + continue; + } var inf = site.infos(l.name); l.version = getVersion(inf, l.version); } // Print a list with all the info print("Haxelib is going to install these libraries:"); - for (l in libs) - { + for (l in libsToInstall) { var vString = (l.version == null) ? "" : " - " + l.version; print(" " + l.name + vString); } // Install if they confirm - if (ask("Continue?") != No) - { - for (l in libs) - { - doInstall(l.name, l.version, setCurrent); + if (ask("Continue?")) { + for (l in libsToInstall) { + if ( l.type == "haxelib" ) + doInstall(rep, l.name, l.version, true); + else if ( l.type == "git" ) + useVcs(VcsID.Git, function(vcs) doVcsInstall(rep, vcs, l.name, l.url, l.branch, l.subDir, l.version)); + else if ( l.type == "hg" ) + useVcs(VcsID.Hg, function(vcs) doVcsInstall(rep, vcs, l.name, l.url, l.branch, l.subDir, l.version)); } } } + + function installFromHaxelibJson( rep:String, path:String ) + { + doInstallDependencies(rep, Data.readData(File.getContent(path), false).dependencies); + } - function doInstall( project, version, setcurrent ) { - var rep = getRepository(); + function installFromAllHxml(rep:String) { + var cwd = Sys.getCwd(); + var hxmlFiles = sys.FileSystem.readDirectory(cwd).filter(function (f) return f.endsWith(".hxml")); + if (hxmlFiles.length > 0) { + for (file in hxmlFiles) { + print('Installing all libraries from $file:'); + installFromHxml(rep, cwd + file); + } + } else { + print("No hxml files found in the current directory."); + } + } + function doInstall( rep, project, version, setcurrent ) { // check if exists already if( FileSystem.exists(rep+Data.safe(project)+"/"+Data.safe(version)) ) { print("You already have "+project+" version "+version+" installed"); - setCurrent(project,version,true); + setCurrent(rep,project,version,true); return; } // download to temporary file var filename = Data.fileName(project,version); var filepath = rep+filename; - var out = try File.write(filepath,true) - catch (e:Dynamic) throw 'Failed to write to $filepath: $e'; + var out = try File.append(filepath,true) catch (e:Dynamic) throw 'Failed to write to $filepath: $e'; + out.seek(0, SeekEnd); + + var h = createHttpRequest(siteUrl+Data.REPOSITORY+"/"+filename); - var progress = new Progress(out); - var h = new Http(siteUrl+Data.REPOSITORY+"/"+filename); + var currentSize = out.tell(); + if (currentSize > 0) + h.addHeader("range", "bytes="+currentSize + "-"); + + var progress = new ProgressOut(out, currentSize); + + var has416Status = false; + h.onStatus = function(status) { + // 416 Requested Range Not Satisfiable, which means that we probably have a fully downloaded file already + if (status == 416) has416Status = true; + }; h.onError = function(e) { progress.close(); - FileSystem.deleteFile(filepath); - throw e; + + // if we reached onError, because of 416 status code, it's probably okay and we should try unzipping the file + if (!has416Status) { + FileSystem.deleteFile(filepath); + throw e; + } }; print("Downloading "+filename+"..."); h.customRequest(false,progress); - doInstallFile(filepath, setcurrent); + doInstallFile(rep,filepath, setcurrent); try { site.postInstall(project, version); } catch (e:Dynamic) {} } - function doInstallFile(filepath,setcurrent,?nodelete) { + function doInstallFile(rep,filepath,setcurrent,nodelete = false) { // read zip content var f = File.read(filepath,true); - var zip = Reader.readZip(f); + var zip = try { + Reader.readZip(f); + } catch (e:Dynamic) { + f.close(); + // file is corrupted, remove it + if (!nodelete) + FileSystem.deleteFile(filepath); + neko.Lib.rethrow(e); + throw e; + } f.close(); var infos = Data.readInfos(zip,false); + print('Installing ${infos.name}...'); // create directories - var pdir = getRepository() + Data.safe(infos.name); + var pdir = rep + Data.safe(infos.name); safeDir(pdir); pdir += "/"; var target = pdir + Data.safe(infos.version); @@ -843,30 +857,38 @@ class Main { var basepath = Data.locateBasePath(zip); // unzip content - for( zipfile in zip ) { + var entries = [for (entry in zip) if (entry.fileName.startsWith(basepath)) entry]; + var total = entries.length; + for (i in 0...total) { + var zipfile = entries[i]; var n = zipfile.fileName; - if( n.startsWith(basepath) ) { - // remove basepath - n = n.substr(basepath.length,n.length-basepath.length); - if( n.charAt(0) == "/" || n.charAt(0) == "\\" || n.split("..").length > 1 ) - throw "Invalid filename : "+n; - var dirs = ~/[\/\\]/g.split(n); - var path = ""; - var file = dirs.pop(); - for( d in dirs ) { - path += d; - safeDir(target+path); - path += "/"; - } - if( file == "" ) { - if( path != "" ) print(" Created "+path); - continue; // was just a directory - } - path += file; - print(" Install "+path); - var data = Reader.unzip(zipfile); - File.saveBytes(target+path,data); + // remove basepath + n = n.substr(basepath.length,n.length-basepath.length); + if( n.charAt(0) == "/" || n.charAt(0) == "\\" || n.split("..").length > 1 ) + throw "Invalid filename : "+n; + + if (!settings.debug) { + var percent = Std.int((i / total) * 100); + Sys.print('${i + 1}/$total ($percent%)\r'); + } + + var dirs = ~/[\/\\]/g.split(n); + var path = ""; + var file = dirs.pop(); + for( d in dirs ) { + path += d; + safeDir(target+path); + path += "/"; } + if( file == "" ) { + if( path != "" && settings.debug ) print(" Created "+path); + continue; // was just a directory + } + path += file; + if (settings.debug) + print(" Install "+path); + var data = Reader.unzip(zipfile); + File.saveBytes(target+path,data); } // set current version @@ -881,137 +903,144 @@ class Main { print("Done"); // process dependencies - doInstallDependencies(infos.dependencies); + doInstallDependencies(rep, infos.dependencies); return infos; } - function doInstallDependencies( dependencies:Array ) - { + function doInstallDependencies( rep:String, dependencies:Array ) { for( d in dependencies ) { + if( d.version == "" ) { + var pdir = rep + Data.safe(d.name); + var dev = try getDev(pdir) catch (_:Dynamic) null; + + if (dev != null) { // no version specified and dev set, no need to install dependency + continue; + } + } + + if( d.version == "" && d.type == DependencyType.Haxelib ) + d.version = site.getLatestVersion(d.name); print("Installing dependency "+d.name+" "+d.version); - if( d.version == "" ) - d.version = site.infos(d.name).getLatest(); switch d.type { case Haxelib: - doInstall(d.name, d.version, false); + doInstall(rep, d.name, d.version, false); case Git: - doVcs(VcsID.Git, d.name, d.url, d.branch, d.subDir, d.version); - //TODO: add mercurial-dependency type to schema.json (https://github.com/HaxeFoundation/haxelib/blob/master/schema.json#L38) + useVcs(VcsID.Git, function(vcs) doVcsInstall(rep, vcs, d.name, d.url, d.branch, d.subDir, d.version)); case Mercurial: - doVcs(VcsID.Hg, d.name, d.url, d.branch, d.subDir, d.version); + useVcs(VcsID.Hg, function(vcs) doVcsInstall(rep, vcs, d.name, d.url, d.branch, d.subDir, d.version)); } } } - function safeDir( dir ) { - if( FileSystem.exists(dir) ) { - if( !FileSystem.isDirectory(dir) ) - throw ("A file is preventing "+dir+" to be created"); - } - try { - FileSystem.createDirectory(dir); - } catch( e : Dynamic ) { - throw "You don't have enough user rights to create the directory "+dir; - } - return true; - } - - function safeDelete( file ) { - try { - FileSystem.deleteFile(file); - return true; - } catch (e:Dynamic) { - if( Sys.systemName() == "Windows") { - try { - Sys.command("attrib", ["-R", file]); - FileSystem.deleteFile(file); - return true; - } catch (e:Dynamic) { - } + function getConfigFile():String { + var home = null; + if (IS_WINDOWS) { + home = Sys.getEnv("USERPROFILE"); + if (home == null) { + var drive = Sys.getEnv("HOMEDRIVE"); + var path = Sys.getEnv("HOMEPATH"); + if (drive != null && path != null) + home = drive + path; } - return false; + if (home == null) + throw "Could not determine home path. Please ensure that USERPROFILE or HOMEDRIVE+HOMEPATH environment variables are set."; + } else { + home = Sys.getEnv("HOME"); + if (home == null) + throw "Could not determine home path. Please ensure that HOME environment variable is set."; } + return Path.addTrailingSlash(home) + ".haxelib"; } - function getRepository( ?setup : Bool ) { + function getGlobalRepositoryPath(create = false):String { + // first check the env var + var rep = Sys.getEnv("HAXELIB_PATH"); + if (rep != null) + return rep.trim(); + + // try to read from user config + rep = try File.getContent(getConfigFile()).trim() catch (_:Dynamic) null; + if (rep != null) + return rep; - if( !setup && !settings.global && FileSystem.exists(REPODIR) && FileSystem.isDirectory(REPODIR) ) { - var absolutePath = Path.join([cli.cwd, REPODIR]);//TODO: we actually might want to get the real path here - return Path.addTrailingSlash(absolutePath); + if (!IS_WINDOWS) { + // on unixes, try to read system-wide config + rep = try File.getContent("/etc/.haxelib").trim() catch (_:Dynamic) null; + if (rep == null) + throw "This is the first time you are runing haxelib. Please run `haxelib setup` first"; + } else { + // on windows, try to use haxe installation path + rep = getWindowsDefaultGlobalRepositoryPath(); + if (create) + try safeDir(rep) catch(e:Dynamic) throw 'Error accessing Haxelib repository: $e'; } - var win = Sys.systemName() == "Windows"; + return rep; + } + + // on windows we have default global haxelib path - where haxe is installed + function getWindowsDefaultGlobalRepositoryPath():String { var haxepath = Sys.getEnv("HAXEPATH"); - if( haxepath != null ) - haxepath = Path.addTrailingSlash( haxepath ); - var envPath = Sys.getEnv("HAXELIB_PATH"); - var config_file; - if( win ) - config_file = Sys.getEnv("HOMEDRIVE") + Sys.getEnv("HOMEPATH"); + if (haxepath == null) + throw "HAXEPATH environment variable not defined, please run haxesetup.exe first"; + return Path.addTrailingSlash(haxepath.trim()) + REPNAME; + } + + function getSuggestedGlobalRepositoryPath():String { + if (IS_WINDOWS) + return getWindowsDefaultGlobalRepositoryPath(); + + return if (FileSystem.exists("/usr/share/haxe")) // for Debian + '/usr/share/haxe/$REPNAME' + else if (Sys.systemName() == "Mac") // for newer OSX, where /usr/lib is not writable + '/usr/local/lib/haxe/$REPNAME' else - config_file = Sys.getEnv("HOME"); - config_file += "/.haxelib"; - var rep = if (envPath != null) - envPath - else try - File.getContent(config_file) - catch( e : Dynamic ) try - File.getContent("/etc/.haxelib") - catch( e : Dynamic ) { - if( setup ) { - (if (win) - haxepath; - else if (FileSystem.exists("/usr/share/haxe")) - "/usr/share/haxe"; - else - "/usr/lib/haxe")+REPNAME; - } else if( win ) { - // Windows have a default directory (no need for setup) - if( haxepath == null ) - throw "HAXEPATH environment variable not defined, please run haxesetup.exe first"; - var rep = haxepath+REPNAME; - try { - safeDir(rep); - } catch( e : String ) { - throw "Error accessing Haxelib repository: $e"; - } - return Path.addTrailingSlash( rep ); - } else - throw "This is the first time you are runing haxelib. Please run `haxelib setup` first"; - } - rep = rep.trim(); - if( setup ) { - if( args.length <= argcur ) { - print("Please enter haxelib repository path with write access"); - print("Hit enter for default (" + rep + ")"); - } - var line = param("Path"); - if( line != "" ) - rep = line; - if( !FileSystem.exists(rep) ) { - try { - FileSystem.createDirectory(rep); - } catch( e : Dynamic ) { - print("Failed to create directory '"+rep+"' ("+Std.string(e)+"), maybe you need appropriate user rights"); - print("Check also that the parent directory exists"); - Sys.exit(1); - } - } - rep = try FileSystem.fullPath(rep) catch( e : Dynamic ) rep; - File.saveContent(config_file, rep); - } else if( !FileSystem.exists(rep) ) { - throw "haxelib Repository "+rep+" does not exist. Please run `haxelib setup` again"; - } else if ( !FileSystem.isDirectory(rep) ) { - throw "haxelib Repository "+rep+" exists, but was a file, not a directory. Please remove it and run `haxelib setup` again."; - } - return rep+"/"; + '/usr/lib/haxe/$REPNAME'; // for other unixes + } + + function getRepository():String { + if (!settings.global && FileSystem.exists(REPODIR) && FileSystem.isDirectory(REPODIR)) + return Path.addTrailingSlash(FileSystem.fullPath(REPODIR)); + else + return getGlobalRepository(); + } + + function getGlobalRepository():String { + var rep = getGlobalRepositoryPath(true); + if (!FileSystem.exists(rep)) + throw "haxelib Repository " + rep + " does not exist. Please run `haxelib setup` again."; + else if (!FileSystem.isDirectory(rep)) + throw "haxelib Repository " + rep + " exists, but is a file, not a directory. Please remove it and run `haxelib setup` again."; + return Path.addTrailingSlash(rep); } function setup() { - var path = getRepository(true); - print("haxelib repository is now "+path); + var rep = try getGlobalRepositoryPath() catch (_:Dynamic) null; + if (rep == null) + rep = getSuggestedGlobalRepositoryPath(); + + var configFile = getConfigFile(); + + if (args.length <= argcur) { + print("Please enter haxelib repository path with write access"); + print("Hit enter for default (" + rep + ")"); + } + + var line = param("Path"); + if (line != "") + rep = line; + + rep = try FileSystem.fullPath(rep) catch (_:Dynamic) rep; + + if (isSamePath(rep, configFile)) + throw "Can't use "+rep+" because it is reserved for config file"; + + safeDir(rep); + File.saveContent(configFile, rep); + + print("haxelib repository is now " + rep); } function config() { @@ -1036,19 +1065,42 @@ class Main { for( p in folders ) { if( p.charAt(0) == "." ) continue; - var versions = new Array(); + var current = try getCurrent(rep + p) catch(e:Dynamic) continue; - var dev = try File.getContent(rep+p+"/.dev").trim() catch( e : Dynamic ) null; + var dev = try getDev(rep + p) catch( e : Dynamic ) null; + + var semvers = []; + var others = []; for( v in FileSystem.readDirectory(rep+p) ) { if( v.charAt(0) == "." ) continue; v = Data.unsafe(v); - if( dev == null && v == current ) - v = "["+v+"]"; - versions.push(v); + var semver = try SemVer.ofString(v) catch (_:Dynamic) null; + if (semver != null) + semvers.push(semver); + else + others.push(v); } - if( dev != null ) + + if (semvers.length > 0) + semvers.sort(SemVer.compare); + + var versions = []; + for (v in semvers) + versions.push((v : String)); + for (v in others) + versions.push(v); + + if (dev == null) { + for (i in 0...versions.length) { + var v = versions[i]; + if (v == current) + versions[i] = '[$v]'; + } + } else { versions.push("[dev:"+dev+"]"); + } + all.push(Data.unsafe(p) + ": "+versions.join(" ")); } all.sort(function(s1, s2) return Reflect.compare(s1.toLowerCase(), s2.toLowerCase())); @@ -1057,16 +1109,29 @@ class Main { } } - function upgrade() { - var state = { rep : getRepository(), prompt : true, updated : false }; + function update() { + var rep = getRepository(); + + var prj = paramOpt(); + if (prj != null) { + prj = projectNameToDir(rep, prj); // get project name in proper case + if (!updateByName(rep, prj)) + print(prj + " is up to date"); + return; + } + + var state = { rep : rep, prompt : true, updated : false }; for( p in FileSystem.readDirectory(state.rep) ) { if( p.charAt(0) == "." || !FileSystem.isDirectory(state.rep+"/"+p) ) continue; var p = Data.unsafe(p); print("Checking " + p); - try doUpdate(p, state) - catch (e:Dynamic) - if (e != VcsError.VcsUnavailable) neko.Lib.rethrow(e); + try { + doUpdate(p, state); + } catch (e:VcsError) { + if (!e.match(VcsUnavailable(_))) + neko.Lib.rethrow(e); + } } if( state.updated ) print("Done"); @@ -1074,193 +1139,66 @@ class Main { print("All libraries are up-to-date"); } - function doUpdate( p : String, state ) { - var rep = state.rep; - - //TODO: get content from `.current` and use vcs only if there "dev". - - var vcs:Vcs = Vcs.getVcsForDevLib(rep + "/" + p); - if(vcs != null) - { - if(!vcs.available) - throw VcsError.VcsUnavailable; - - var oldCwd = cli.cwd; - cli.cwd = (rep + "/" + p + "/" + vcs.directory); - var success = vcs.update(p, cast settings); + function projectNameToDir( rep:String, project:String ) { + var p = project.toLowerCase(); + var l = FileSystem.readDirectory(rep).filter(function (dir) return dir.toLowerCase() == p); - state.updated = success; - cli.cwd = oldCwd; - } - else - { - var inf = try site.infos(p) catch( e : Dynamic ) { Sys.println(e); return; }; - if( !FileSystem.exists(rep+Data.safe(p)+"/"+Data.safe(inf.getLatest())) ) { - if( state.prompt ) - switch ask("Update "+p+" to "+inf.getLatest()) { - case Yes: - case No: - return; - } - doInstall(p,inf.getLatest(),true); - state.updated = true; - } else - setCurrent(p, inf.getLatest(), true); + switch (l) { + case []: return project; + case [dir]: return Data.unsafe(dir); + case _: throw "Several name case for library " + project; } } - function updateByName(prj:String) { - var state = { rep : getRepository(), prompt : false, updated : false }; + + function updateByName(rep:String, prj:String) { + var state = { rep : rep, prompt : false, updated : false }; doUpdate(prj,state); return state.updated; } - function update() { - var prj = param('Library'); - if (!updateByName(prj)) - print(prj + " is up to date"); - } - - //recursively follow symlink - static function realPath(path:String):String { - return switch (new Process('readlink', [path.endsWith("\n") ? path.substr(0, path.length-1) : path]).stdout.readAll().toString()) { - case "": //it is not a symlink - path; - case targetPath: - if (targetPath.startsWith("/")) { - realPath(targetPath); - } else { - realPath(new Path(path).dir + "/" + targetPath); - } - } - } - - function rebuildSelf() { - var win = Sys.systemName() == "Windows"; - var haxepath = - if (win) Sys.getEnv("HAXEPATH"); - else new Path(realPath(new Process('which', ['haxelib']).stdout.readAll().toString())).dir + '/'; - cli.cwd = haxepath; - function tryBuild() { - var p = new Process('haxe', ['-neko', 'test.n', '-lib', 'haxelib_client', '-main', 'tools.haxelib.Main', '--no-output']); - return - if (p.exitCode() == 0) None; - else Some(p.stderr.readAll().toString()); - } + function doUpdate( p : String, state : { updated : Bool, rep : String, prompt : Bool } ) { + var pdir = state.rep + Data.safe(p); + var vcs = Vcs.getVcsForDevLib(pdir, settings); + if(vcs != null) { + if(!vcs.available) + throw VcsError.VcsUnavailable(vcs); - switch tryBuild() { - case None: + var oldCwd = Sys.getCwd(); + Sys.setCwd(pdir + "/" + vcs.directory); + var success = vcs.update(p); - if (haxepath == null) - throw (win ? 'HAXEPATH environment variable not defined' : 'unable to locate haxelib through `which haxelib`'); - else - haxepath = Path.addTrailingSlash(haxepath); + state.updated = success; + Sys.setCwd(oldCwd); + } else { + var latest = try site.getLatestVersion(p) catch( e : Dynamic ) { Sys.println(e); return; }; - if (win) { - Sys.command('start', ['haxe', '-lib', 'haxelib_client', '--run', 'tools.haxelib.Rebuild']); - print('rebuild launched'); - } - else { - var p = new Process('haxelib', ['path', 'haxelib_client']); - if (p.exitCode() == 0) { - var args = []; - var classPath = ""; - for (arg in p.stdout.readAll().toString().split('\n')) { - arg = arg.trim(); - if (arg.charAt(0) == '-') - args.push(arg); - else if (arg.length > 0) - classPath = arg; - }; - - var file = haxepath+'haxelib'; - try File.saveContent( - file, - '#!/bin/sh' - +'\n'+'OLDCWD=`pwd`' - +'\n'+'cd $classPath' - +'\n'+'exec haxe '+args.join(' ')+" --run tools.haxelib.Main -cwd $OLDCWD $@" - ) - catch (e:Dynamic) - throw 'Error writing file $file. Please ensure you have write permissions. \n ' + Std.string(e); - } - else throw p.stdout.readAll(); + if( !FileSystem.exists(pdir+"/"+Data.safe(latest)) ) { + if( state.prompt ) { + if (!ask("Update "+p+" to "+latest)) + return; } - case Some(error): - throw 'Error compiling haxelib client: $error'; - } - - } - - function updateSelf() { - settings.global = true; - if (updateByName('haxelib_client')) - print("Haxelib successfully updated."); - else - print("Haxelib was already up to date..."); - - rebuildSelf(); - } - - function deleteRec(dir) - { - if(!FileSystem.exists(dir)) return; - - for(p in FileSystem.readDirectory(dir)) - { - var path = Path.join([dir, p]); - - if(isBrokenSymlink(path)) - safeDelete(path); - else - if(FileSystem.isDirectory(path)) - { - // if isSymLink: - if(Sys.systemName() != "Windows" && path != FileSystem.fullPath(path)) - safeDelete(path); - else - deleteRec(path); - } - else - safeDelete(path); - } - FileSystem.deleteDirectory(dir); - } - - function isBrokenSymlink(path:String):Bool - { - var errors:Int = 0; - function isNeeded(error:String):Bool - { - return switch(error) - { - case "std@sys_file_type" | - "std@file_full_path": true; - default: false; - } + doInstall(state.rep, p, latest,true); + state.updated = true; + } else + setCurrent(state.rep, p, latest, true); } - - try{ FileSystem.isDirectory(path); } - catch(error:String) - if(isNeeded(error)) - errors++; - - try{ FileSystem.fullPath(path); } - catch(error:String) - if(isNeeded(error)) - errors++; - - return errors == 2; } function remove() { + var rep = getRepository(); var prj = param("Library"); var version = paramOpt(); - var rep = getRepository(); var pdir = rep + Data.safe(prj); if( version == null ) { if( !FileSystem.exists(pdir) ) throw "Library "+prj+" is not installed"; + + if (prj == HAXELIB_LIBNAME && isHaxelibRun) { + print('Error: Removing "$HAXELIB_LIBNAME" requires the --system flag'); + Sys.exit(1); + } + deleteRec(pdir); print("Library "+prj+" removed"); return; @@ -1270,46 +1208,49 @@ class Main { if( !FileSystem.exists(vdir) ) throw "Library "+prj+" does not have version "+version+" installed"; - var cur = getCurrent(pdir); + var cur = File.getContent(pdir + "/.current").trim(); // set version regardless of dev if( cur == version ) throw "Can't remove current version of library "+prj; + var dev = try getDev(pdir) catch (_:Dynamic) null; // dev is checked here + if( dev == vdir ) + throw "Can't remove dev version of library "+prj; deleteRec(vdir); print("Library "+prj+" version "+version+" removed"); } function set() { - var prj = param("Library"); - var version = param("Version"); - setCurrent(prj,version,false); + setCurrent(getRepository(), param("Library"), param("Version"), false); } - function setCurrent( prj : String, version : String, doAsk : Bool ) { - var pdir = getRepository() + Data.safe(prj); + function setCurrent( rep : String, prj : String, version : String, doAsk : Bool ) { + var pdir = rep + Data.safe(prj); var vdir = pdir + "/" + Data.safe(version); if( !FileSystem.exists(vdir) ){ print("Library "+prj+" version "+version+" is not installed"); - if(ask("Would you like to install it?") != No) - doInstall(prj, version, true); + if(ask("Would you like to install it?")) + doInstall(rep, prj, version, true); return; } - if( getCurrent(pdir) == version ) + if( File.getContent(pdir + "/.current").trim() == version ) return; - if( doAsk && ask("Set "+prj+" to version "+version) == No ) + if( doAsk && !ask("Set "+prj+" to version "+version) ) return; File.saveContent(pdir+"/.current",version); print("Library "+prj+" current version is now "+version); } - function checkRec( prj : String, version : String, l : List<{ project : String, version : String, info : Infos }> ) { - var pdir = getRepository() + Data.safe(prj); + function checkRec( rep : String, prj : String, version : String, l : List<{ project : String, version : String, dir : String, info : Infos }> ) { + var pdir = rep + Data.safe(prj); if( !FileSystem.exists(pdir) ) throw "Library "+prj+" is not installed : run 'haxelib install "+prj+"'"; var version = if( version != null ) version else getCurrent(pdir); - var vdir = pdir + "/" + Data.safe(version); - if( vdir.endsWith("dev") ) - vdir = getDev(pdir); + + var dev = try getDev(pdir) catch (_:Dynamic) null; + var vdir = if (dev != null) dev else pdir + "/" + Data.safe(version); + if( !FileSystem.exists(vdir) ) throw "Library "+prj+" version "+version+" is not installed"; + for( p in l ) if( p.project == prj ) { if( p.version == version ) @@ -1318,45 +1259,36 @@ class Main { } var json = try File.getContent(vdir+"/"+Data.JSON) catch( e : Dynamic ) null; var inf = Data.readData(json,false); - l.add({ project : prj, version : version, info: inf }); + l.add({ project : prj, version : version, dir : Path.addTrailingSlash(vdir), info: inf }); for( d in inf.dependencies ) if( !Lambda.exists(l, function(e) return e.project == d.name) ) - checkRec(d.name,if( d.version == "" ) null else d.version,l); + checkRec(rep,d.name,if( d.version == "" ) null else d.version,l); } function path() { + var rep = getRepository(); var list = new List(); while( argcur < args.length ) { var a = args[argcur++].split(":"); - checkRec(a[0],a[1],list); + checkRec(rep, a[0],a[1],list); } - var rep = getRepository(); for( d in list ) { - var pdir = Data.safe(d.project)+"/"+Data.safe(d.version)+"/"; - var dir = rep + pdir; - try { - dir = getDev(rep+Data.safe(d.project)); - dir = Path.addTrailingSlash(dir); - pdir = dir; - } catch( e : Dynamic ) {} - var ndir = dir + "ndll"; - if( FileSystem.exists(ndir) ) { - var sysdir = ndir+"/"+Sys.systemName(); - var is64 = neko.Lib.load("std", "sys_is64", 0)(); - if( is64 ) sysdir += "64"; - // if( !FileSystem.exists(sysdir) ) - // throw "Library "+d.project+" version "+d.version+" does not have a neko dll for your system"; - Sys.println("-L "+pdir+"ndll/"); - } + var ndir = d.dir + "ndll"; + if (FileSystem.exists(ndir)) + Sys.println('-L $ndir/'); + try { - var f = File.getContent(dir + "extraParams.hxml"); + var f = File.getContent(d.dir + "extraParams.hxml"); Sys.println(f.trim()); - } catch( e : Dynamic ) {} + } catch(_:Dynamic) {} + + var dir = d.dir; if (d.info.classPath != "") { var cp = d.info.classPath; - dir = Path.addTrailingSlash( dir + cp ); + dir = Path.addTrailingSlash( d.dir + cp ); } Sys.println(dir); + Sys.println("-D " + d.project + "="+d.info.version); } } @@ -1379,10 +1311,10 @@ class Main { while ( dir.endsWith("/") || dir.endsWith("\\") ) { dir = dir.substr(0,-1); } - dir = FileSystem.fullPath(dir); - if (!FileSystem.exists(dir)) + if (!FileSystem.exists(dir)) { print('Directory $dir does not exist'); - else + } else { + dir = FileSystem.fullPath(dir); try { File.saveContent(devfile, dir); print("Development directory set to "+dir); @@ -1390,105 +1322,106 @@ class Main { catch (e:Dynamic) { print('Could not write to $devfile'); } + } } } - function removeExistingDevLib(proj:String):Void - { + function removeExistingDevLib(proj:String):Void { //TODO: ask if existing repo have changes. // find existing repo: - var vcs:Vcs = Vcs.getVcsForDevLib(proj); + var vcs = Vcs.getVcsForDevLib(proj, settings); // remove existing repos: - while(vcs != null) - { + while(vcs != null) { deleteRec(proj + "/" + vcs.directory); - vcs = Vcs.getVcsForDevLib(proj); + vcs = Vcs.getVcsForDevLib(proj, settings); } } - function doVcs(id:VcsID, ?libName:String, ?url:String, ?branch:String, ?subDir:String, ?version:String) - { + inline function useVcs(id:VcsID, fn:Vcs->Void):Void { // Prepare check vcs.available: - var vcs = Vcs.get(id); + var vcs = Vcs.get(id, settings); if(vcs == null || !vcs.available) - return print('Could not use $id, please make sure it is installed and available in your PATH.'); - - // if called with known values: - if(libName != null && url != null) - doVcsInstall(vcs, libName, url, branch, subDir, version); - else - doVcsInstall(vcs, - param("Library name"), - param(vcs.name + " path"), - paramOpt(), - paramOpt(), - paramOpt() - ); + throw 'Could not use $id, please make sure it is installed and available in your PATH.'; + return fn(vcs); } - function doVcsInstall(vcs:Vcs, libName:String, url:String, ?branch:String, ?subDir:String, ?version:String) - { + function vcs(id:VcsID) { var rep = getRepository(); - var proj = rep + Data.safe(libName); - - // find & remove all existing repos: - removeExistingDevLib(proj); - // currently we already kill all dev-repos for all supported Vcs. + useVcs(id, function(vcs) doVcsInstall(rep, vcs, param("Library name"), param(vcs.name + " path"), paramOpt(), paramOpt(), paramOpt())); + } + function doVcsInstall(rep:String, vcs:Vcs, libName:String, url:String, branch:String, subDir:String, version:String) { + + var proj = rep + Data.safe(libName); var libPath = proj + "/" + vcs.directory; + + var jsonPath = libPath + "/haxelib.json"; + + if ( FileSystem.exists(proj + "/" + Data.safe(vcs.directory)) ) { + print("You already have "+libName+" version "+vcs.directory+" installed."); + + var wasUpdated = this.alreadyUpdatedVcsDependencies.exists(libName); + var currentBranch = if (wasUpdated) this.alreadyUpdatedVcsDependencies.get(libName) else null; + + if (branch != null && (!wasUpdated || (wasUpdated && currentBranch != branch)) + && ask("Overwrite branch: " + (currentBranch == null?"":"\"" + currentBranch + "\"") + " with \"" + branch + "\"")) + { + deleteRec(libPath); + this.alreadyUpdatedVcsDependencies.set(libName, branch); + } + else + { + if (!wasUpdated) + { + print("Updating " + libName+" version " + vcs.directory + " ..."); + this.alreadyUpdatedVcsDependencies.set(libName, branch); + updateByName(rep, libName); + setCurrent(rep, libName, vcs.directory, true); + + if(FileSystem.exists(jsonPath)) + doInstallDependencies(rep, Data.readData(File.getContent(jsonPath), false).dependencies); + } + return; + } + } - // prepare for new repo - if(FileSystem.exists(libPath)) + print("Installing " +libName + " from " +url + ( branch != null ? " branch: " + branch : "" )); + + try { + vcs.clone(libPath, url, branch, version); + } catch(error:VcsError) { deleteRec(libPath); - - - print("Installing " +libName + " from " +url); - - try - { - vcs.clone(libPath, url, branch, version, cast settings); - } - catch(error:VcsError) - { - var message = switch(error) - { - case VcsError.VcsUnavailable(vcs): + var message = switch(error) { + case VcsUnavailable(vcs): 'Could not use ${vcs.executable}, please make sure it is installed and available in your PATH.'; - case VcsError.CantCloneRepo(vcs, repo, stderr): + case CantCloneRepo(vcs, repo, stderr): 'Could not clone ${vcs.name} repository' + (stderr != null ? ":\n" + stderr : "."); - case VcsError.CantCheckoutBranch(vcs, branch, stderr): + case CantCheckoutBranch(vcs, branch, stderr): 'Could not checkout branch, tag or path "$branch": ' + stderr; - case VcsError.CantCheckoutVersion(vcs, version, stderr): + case CantCheckoutVersion(vcs, version, stderr): 'Could not checkout tag "$version": ' + stderr; - } - print(message); - deleteRec(libPath); + }; + throw message; } - // finish it! - var devPath = libPath + (subDir == null ? "" : "/" + subDir); - - cli.cwd = proj; - - File.saveContent(".dev", devPath); - - print('Library $libName set to use ${vcs.name}.'); - - if(branch != null) - print(' Branch/Tag/Rev: $branch'); - print(' Path: $devPath'); + if (subDir != null) { + libPath += "/" + subDir; + File.saveContent(proj + "/.dev", libPath); + print("Development directory set to "+libPath); + } else { + File.saveContent(proj + "/.current", vcs.directory); + print("Library "+libName+" current version is now "+vcs.directory); + } - cli.cwd = libPath; + this.alreadyUpdatedVcsDependencies.set(libName, branch); - if(FileSystem.exists("haxelib.json")) - doInstallDependencies( - Data.readData(File.getContent("haxelib.json"), false).dependencies - ); + if(FileSystem.exists(jsonPath)) + doInstallDependencies(rep, Data.readData(File.getContent(jsonPath), false).dependencies); } @@ -1496,60 +1429,56 @@ class Main { var rep = getRepository(); var project = param("Library"); var temp = project.split(":"); - project = temp[0]; + doRun(rep, temp[0], temp[1]); + } + + function doRun( rep:String, project:String, version:String ) { var pdir = rep + Data.safe(project); if( !FileSystem.exists(pdir) ) throw "Library "+project+" is not installed"; pdir += "/"; - var version = temp[1] != null ? temp[1] : getCurrent(pdir); + if (version == null) + version = getCurrent(pdir); var dev = try getDev(pdir) catch ( e : Dynamic ) null; var vdir = dev != null ? dev : pdir + Data.safe(version); - args.push(cli.cwd); - cli.cwd = vdir; + var infos = + try + Data.readData(File.getContent(vdir + '/haxelib.json'), false) + catch (e:Dynamic) + throw 'Error parsing haxelib.json for $project@$version: $e'; + + args.push(Sys.getCwd()); + Sys.setCwd(vdir); var callArgs = - switch try [Data.readData(File.getContent(vdir + '/haxelib.json'), false), null] catch (e:Dynamic) [null, e] { - case [null, e]: - throw 'Error parsing haxelib.json for $project@$version: $e'; - case [{ main: null }, _]: - if( !FileSystem.exists('$vdir/run.n') ) - throw 'Library $project version $version does not have a run script'; - ["neko", "run.n"]; - case [{ main: cls, dependencies: _.toArray() => deps }, _]: - deps = switch deps { case null: []; default: deps.copy(); }; - deps.push( { name: project, version: DependencyVersion.DEFAULT } ); - var args = []; - for (d in deps) { - args.push('-lib'); - args.push(d.name + if (d.version == '') '' else ':${d.version}'); - } - args.unshift('haxe'); - args.push('--run'); - args.push(cls); - args; - default: throw 'assert'; + if (infos.main == null) { + if( !FileSystem.exists('$vdir/run.n') ) + throw 'Library $project version $version does not have a run script'; + ["neko", vdir + "/run.n"]; + } else { + var deps = infos.dependencies.toArray(); + deps.push( { name: project, version: DependencyVersion.DEFAULT } ); + var args = []; + for (d in deps) { + args.push('-lib'); + args.push(d.name + if (d.version == '') '' else ':${d.version}'); + } + args.unshift('haxe'); + args.push('--run'); + args.push(infos.main); + args; } for (i in argcur...args.length) callArgs.push(args[i]); Sys.putEnv("HAXELIB_RUN", "1"); + Sys.putEnv("HAXELIB_RUN_NAME", project); var cmd = callArgs.shift(); Sys.exit(Sys.command(cmd, callArgs)); } - function local() { - var file = param("Package"); - if (doInstallFile(file, true, true).name == 'haxelib_client') - if (ask('You have updated haxelib. Do you wish to rebuild it?') != No) { - rebuildSelf(); - } - } - - inline function command(cmd:String, args:Array) - return cli.command(cmd, args); - function proxy() { var rep = getRepository(); var host = param("Proxy host"); @@ -1585,12 +1514,11 @@ class Main { } function convertXml() { - var cwd = cli.cwd; + var cwd = Sys.getCwd(); var xmlFile = cwd + "haxelib.xml"; var jsonFile = cwd + "haxelib.json"; - if (!FileSystem.exists(xmlFile)) - { + if (!FileSystem.exists(xmlFile)) { print('No `haxelib.xml` file was found in the current directory.'); Sys.exit(0); } @@ -1604,49 +1532,39 @@ class Main { } function newRepo() { - if( FileSystem.exists(REPODIR) ) { - if( !FileSystem.isDirectory(REPODIR) ) { - print('$REPODIR exists already but is not a directory, delete it first'); - Sys.exit(1); - } - try { - sys.io.File.saveContent(REPODIR+"/checkWrite.txt","CHECK WRITE"); - } catch( e : Dynamic ) { - print('$REPODIR exists but is not writeable, chmod it'); - Sys.exit(2); - } - FileSystem.deleteFile(REPODIR+"/checkWrite.txt"); - } else { - try { - FileSystem.createDirectory(REPODIR); - } catch( e : Dynamic ) { - print('Failed to create ./$REPODIR'); - Sys.exit(3); - } - } + var path = #if (haxe_ver >= 3.2) FileSystem.absolutePath(REPODIR) #else REPODIR #end; + var created = FsUtils.safeDir(path, true); + if (created) + print('Local repository created ($path)'); + else + print('Local repository already exists ($path)'); } function deleteRepo() { - if( !FileSystem.exists(REPODIR) ) - return; - function deleteRec(path) { - if( FileSystem.isDirectory(path) ) { - for( f in FileSystem.readDirectory(path) ) - deleteRec(Path.join([path, f])); - FileSystem.deleteDirectory(path); - } else - FileSystem.deleteFile(path); - } - deleteRec(REPODIR); + var path = #if (haxe_ver >= 3.2) FileSystem.absolutePath(REPODIR) #else REPODIR #end; + var deleted = FsUtils.deleteRec(path); + if (deleted) + print('Local repository deleted ($path)'); + else + print('No local repository found ($path)'); } // ---------------------------------- inline function print(str) - cli.print(str); + Sys.println(str); static function main() { new Main().process(); } + + // deprecated commands + function local() { + doInstallFile(getRepository(), param("Package"), true, true); + } + + function updateSelf() { + updateByName(getGlobalRepository(), HAXELIB_LIBNAME); + } } diff --git a/extra/haxelib_src/src/haxelib/client/Vcs.hx b/extra/haxelib_src/src/haxelib/client/Vcs.hx new file mode 100644 index 00000000..a24c1e3d --- /dev/null +++ b/extra/haxelib_src/src/haxelib/client/Vcs.hx @@ -0,0 +1,378 @@ +/* + * Copyright (C)2005-2016 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 haxelib.client; + +import sys.FileSystem; +using haxelib.client.Vcs; + +interface IVcs { + var name(default, null):String; + var directory(default, null):String; + var executable(default, null):String; + var available(get, null):Bool; + var settings(default, null):Settings; + + /** + Clone repo into `libPath`. + **/ + function clone(libPath:String, vcsPath:String, ?branch:String, ?version:String):Void; + + /** + Update to HEAD repo contains in CWD or CWD/`Vcs.directory`. + CWD must be like "...haxelib-repo/lib/git" for Git. + Returns `true` if update successful. + **/ + function update(libName:String):Bool; +} + + +@:enum abstract VcsID(String) to String { + var Hg = "hg"; + var Git = "git"; +} + +enum VcsError { + VcsUnavailable(vcs:Vcs); + CantCloneRepo(vcs:Vcs, repo:String, ?stderr:String); + CantCheckoutBranch(vcs:Vcs, branch:String, stderr:String); + CantCheckoutVersion(vcs:Vcs, version:String, stderr:String); +} + + +typedef Settings = { + @:optional var flat:Bool; + @:optional var debug:Bool; + @:optional var quiet:Bool; +} + + +class Vcs implements IVcs { + static var reg:Map; + + public var name(default, null):String; + public var directory(default, null):String; + public var executable(default, null):String; + public var settings(default, null):Settings; + + public var available(get, null):Bool; + + var availabilityChecked = false; + var executableSearched = false; + + public static function initialize(settings:Settings) { + if (reg == null) { + reg = [ + VcsID.Git => new Git(settings), + VcsID.Hg => new Mercurial(settings) + ]; + } else { + if (reg.get(VcsID.Git) == null) + reg.set(VcsID.Git, new Git(settings)); + if (reg.get(VcsID.Hg) == null) + reg.set(VcsID.Hg, new Mercurial(settings)); + } + } + + + function new(executable:String, directory:String, name:String, settings:Settings) { + this.name = name; + this.directory = directory; + this.executable = executable; + this.settings = { + flat: settings.flat != null ? settings.flat : false, + debug: settings.debug != null ? settings.debug : false, + quiet: settings.quiet != null ? settings.quiet : false + } + + if (settings.debug) { + this.settings.quiet = false; + } + } + + + public static function get(id:VcsID, settings:Settings):Null { + initialize(settings); + return reg.get(id); + } + + static function set(id:VcsID, vcs:Vcs, settings:Settings, ?rewrite:Bool):Void { + initialize(settings); + var existing = reg.get(id) != null; + if (!existing || rewrite) + reg.set(id, vcs); + } + + public static function getVcsForDevLib(libPath:String, settings:Settings):Null { + initialize(settings); + for (k in reg.keys()) { + if (FileSystem.exists(libPath + "/" + k) && FileSystem.isDirectory(libPath + "/" + k)) + return reg.get(k); + } + return null; + } + + function sure(commandResult:{code:Int, out:String}):Void { + switch (commandResult) { + case {code: 0}: //pass + case {code: code, out:out}: + if (!settings.debug) + Sys.stderr().writeString(out); + Sys.exit(code); + } + } + + function command(cmd:String, args:Array):{ + code: Int, + out: String + } { + var p = try { + new sys.io.Process(cmd, args); + } catch(e:Dynamic) { + return { + code: -1, + out: Std.string(e) + } + } + var out = p.stdout.readAll().toString(); + var err = p.stderr.readAll().toString(); + if (settings.debug && out != "") + Sys.println(out); + if (settings.debug && err != "") + Sys.stderr().writeString(err); + var code = p.exitCode(); + var ret = { + code: code, + out: code == 0 ? out : err + }; + p.close(); + return ret; + } + + function searchExecutable():Void { + executableSearched = true; + } + + function checkExecutable():Bool { + available = (executable != null) && try command(executable, []).code == 0 catch(_:Dynamic) false; + availabilityChecked = true; + + if (!available && !executableSearched) + searchExecutable(); + + return available; + } + + @:final function get_available():Bool { + if (!availabilityChecked) + checkExecutable(); + return available; + } + + public function clone(libPath:String, vcsPath:String, ?branch:String, ?version:String):Void { + throw "This method must be overriden."; + } + + public function update(libName:String):Bool { + throw "This method must be overriden."; + } +} + + +class Git extends Vcs { + + public function new(settings:Settings) + super("git", "git", "Git", settings); + + override function checkExecutable():Bool { + // with `help` cmd because without any cmd `git` can return exit-code = 1. + available = (executable != null) && try command(executable, ["help"]).code == 0 catch(_:Dynamic) false; + availabilityChecked = true; + + if (!available && !executableSearched) + searchExecutable(); + + return available; + } + + override function searchExecutable():Void { + super.searchExecutable(); + + if (available) + return; + + // if we have already msys git/cmd in our PATH + var match = ~/(.*)git([\\|\/])cmd$/; + for (path in Sys.getEnv("PATH").split(";")) { + if (match.match(path.toLowerCase())) { + var newPath = match.matched(1) + executable + match.matched(2) + "bin"; + Sys.putEnv("PATH", Sys.getEnv("PATH") + ";" + newPath); + } + } + + if (checkExecutable()) + return; + + // look at a few default paths + for (path in ["C:\\Program Files (x86)\\Git\\bin", "C:\\Progra~1\\Git\\bin"]) { + if (FileSystem.exists(path)) { + Sys.putEnv("PATH", Sys.getEnv("PATH") + ";" + path); + if (checkExecutable()) + return; + } + } + } + + override public function update(libName:String):Bool { + if ( + command(executable, ["diff", "--exit-code"]).code != 0 + || + command(executable, ["diff", "--cached", "--exit-code"]).code != 0 + ) { + if (Cli.ask("Reset changes to " + libName + " " + name + " repo so we can pull latest version?")) { + sure(command(executable, ["reset", "--hard"])); + } else { + if (!settings.quiet) + Sys.println(name + " repo left untouched"); + return false; + } + } + + var code = command(executable, ["pull"]).code; + // But if before we pulled specified branch/tag/rev => then possibly currently we haxe "HEAD detached at ..". + if (code != 0) { + // get parent-branch: + var branch = command(executable, ["show-branch"]).out; + var regx = ~/\[([^]]*)\]/; + if (regx.match(branch)) + branch = regx.matched(1); + + sure(command(executable, ["checkout", branch, "--force"])); + sure(command(executable, ["pull"])); + } + return true; + } + + override public function clone(libPath:String, url:String, ?branch:String, ?version:String):Void { + var oldCwd = Sys.getCwd(); + + var vcsArgs = ["clone", url, libPath]; + + if (settings == null || !settings.flat) + vcsArgs.push('--recursive'); + + //TODO: move to Vcs.run(vcsArgs) + //TODO: use settings.quiet + if (command(executable, vcsArgs).code != 0) + throw VcsError.CantCloneRepo(this, url/*, ret.out*/); + + + Sys.setCwd(libPath); + + if (version != null && version != "") { + var ret = command(executable, ["checkout", "tags/" + version]); + if (ret.code != 0) + throw VcsError.CantCheckoutVersion(this, version, ret.out); + } else if (branch != null) { + var ret = command(executable, ["checkout", branch]); + if (ret.code != 0) + throw VcsError.CantCheckoutBranch(this, branch, ret.out); + } + + // return prev. cwd: + Sys.setCwd(oldCwd); + } +} + + +class Mercurial extends Vcs { + + public function new(settings:Settings) + super("hg", "hg", "Mercurial", settings); + + override function searchExecutable():Void { + super.searchExecutable(); + + if (available) + return; + + // if we have already msys git/cmd in our PATH + var match = ~/(.*)hg([\\|\/])cmd$/; + for(path in Sys.getEnv("PATH").split(";")) { + if(match.match(path.toLowerCase())) { + var newPath = match.matched(1) + executable + match.matched(2) + "bin"; + Sys.putEnv("PATH", Sys.getEnv("PATH") + ";" + newPath); + } + } + checkExecutable(); + } + + override public function update(libName:String):Bool { + command(executable, ["pull"]); + var summary = command(executable, ["summary"]).out; + var diff = command(executable, ["diff", "-U", "2", "--git", "--subrepos"]); + var status = command(executable, ["status"]); + + // get new pulled changesets: + // (and search num of sets) + summary = summary.substr(0, summary.length - 1); + summary = summary.substr(summary.lastIndexOf("\n") + 1); + // we don't know any about locale then taking only Digit-exising:s + var changed = ~/(\d)/.match(summary); + if (changed && !settings.quiet) + // print new pulled changesets: + Sys.println(summary); + + + if (diff.code + status.code + diff.out.length + status.out.length != 0) { + if (!settings.quiet) + Sys.println(diff.out); + if (Cli.ask("Reset changes to " + libName + " " + name + " repo so we can update to latest version?")) { + sure(command(executable, ["update", "--clean"])); + } else { + changed = false; + if (!settings.quiet) + Sys.println(name + " repo left untouched"); + } + } else if (changed) { + sure(command(executable, ["update"])); + } + + return changed; + } + + override public function clone(libPath:String, url:String, ?branch:String, ?version:String):Void { + var vcsArgs = ["clone", url, libPath]; + + if (branch != null) { + vcsArgs.push("--branch"); + vcsArgs.push(branch); + } + + if (version != null) { + vcsArgs.push("--rev"); + vcsArgs.push(version); + } + + if (command(executable, vcsArgs).code != 0) + throw VcsError.CantCloneRepo(this, url/*, ret.out*/); + } +} diff --git a/extra/haxelib_src/src/haxelib/server/FileStorage.hx b/extra/haxelib_src/src/haxelib/server/FileStorage.hx new file mode 100644 index 00000000..97922d68 --- /dev/null +++ b/extra/haxelib_src/src/haxelib/server/FileStorage.hx @@ -0,0 +1,284 @@ +/* + * Copyright (C)2005-2016 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 haxelib.server; + +import sys.FileSystem; +import sys.io.*; +import haxe.io.Path; +import haxelib.server.Paths; +import neko.Web; +import aws.*; +import aws.s3.*; +import aws.s3.model.*; +import aws.transfer.*; +using Lambda; + +/** + `FileStorage` is an abstraction to a file system. + It maps relative paths to absolute paths, effectively hides the actual location of the storage. +*/ +class FileStorage { + /** + An static instance of `FileStorage` that everyone use. + One should not create their own instance of `FileStorage` except when testing. + + When both the enviroment variables, HAXELIB_S3BUCKET and AWS_DEFAULT_REGION, are set, + `instance` will be a `S3FileStorage`. Otherwise, it will be a `LocalFileStorage`. + */ + static public var instance(get, null):FileStorage; + static function get_instance() return instance != null ? instance : instance = { + var vars = [ + Sys.getEnv("HAXELIB_S3BUCKET"), + Sys.getEnv("AWS_DEFAULT_REGION") + ]; + switch (vars) { + case [bucket, region] if (vars.foreach(function(v) return v != null && v != "")): + Web.logMessage('using S3FileStorage with bucket $bucket in ${region}'); + new S3FileStorage(Paths.CWD, bucket, region); + case _: + Web.logMessage('using LocalFileStorage'); + new LocalFileStorage(Paths.CWD); + } + } + + /** + Request reading `file` in the function `f`. + `file` should be the relative path to the required file, e.g. `files/3.0/library.zip`. + If the file does not exist, an error will be thrown, and `f` will not be called. + If `file` exist, its abolute path will be given to `f` as input. + It only guarantees `file` exists and the abolute path to it is valid within the call of `f`. + */ + public function readFile(file:RelPath, f:AbsPath->T):T + return throw "should be implemented by subclass"; + + /** + Request writing `file` in the function `f`. + `file` should be a relative path to the required file, e.g. `files/3.0/library.zip`. + Any of the parent directories of `file` that doesn't exist will be created. + The mapped abolute path of `file` will be given to `f` as input. + The abolute path to `file` may and may not contain previously written file. + */ + public function writeFile(file:RelPath, f:AbsPath->T):T + return throw "should be implemented by subclass"; + + /** + Copy existing local `srcFile` to the storage as `dstFile`. + Existing `dstFile` will be overwritten. + If `move` is true, `srcFile` will be deleted, unless `dstFile` happens to located + at the same path of `srcFile`. + */ + public function importFile(srcFile:AbsPath, dstFile:RelPath, move:Bool):Void + throw "should be implemented by subclass"; + + /** + Delete `file` in the storage. + It will be a no-op if `file` does not exist. + */ + public function deleteFile(file:RelPath):Void + throw "should be implemented by subclass"; + + function assertAbsolute(path:String):Void { + #if (haxe_ver >= 3.2) // Path.isAbsolute is added in haxe 3.2 + if (!Path.isAbsolute(path)) + throw '$path is not absolute.'; + #end + } + + function assertRelative(path:String):Void { + #if (haxe_ver >= 3.2) // Path.isAbsolute is added in haxe 3.2 + if (Path.isAbsolute(path)) + throw '$path is not relative.'; + #end + } +} + +class LocalFileStorage extends FileStorage { + /** + The local directory of the file storage. + */ + public var path(default, null):AbsPath; + + /** + Create a `FileStorage` located at a local directory specified by an absolute `path`. + */ + public function new(path:AbsPath):Void { + assertAbsolute(path); + this.path = path; + } + + override public function readFile(file:RelPath, f:AbsPath->T):T { + assertRelative(file); + var file:AbsPath = Path.join([path, file]); + if (!FileSystem.exists(file)) + throw '$file does not exist.'; + return f(file); + } + + override public function writeFile(file:RelPath, f:AbsPath->T):T { + assertRelative(file); + var file:AbsPath = Path.join([path, file]); + FileSystem.createDirectory(Path.directory(file)); + return f(file); + } + + override public function importFile(srcFile:AbsPath, dstFile:RelPath, move:Bool):Void { + var localFile:AbsPath = Path.join([path, dstFile]); + if ( + FileSystem.exists(localFile) && + FileSystem.fullPath(localFile) == FileSystem.fullPath(srcFile) + ) { + // srcFile already located at dstFile + return; + } + FileSystem.createDirectory(Path.directory(localFile)); + File.copy(srcFile, localFile); + if (move) + FileSystem.deleteFile(srcFile); + } + + override public function deleteFile(file:RelPath):Void { + var localFile:AbsPath = Path.join([path, file]); + if (FileSystem.exists(localFile)) + FileSystem.deleteFile(localFile); + } +} + +class S3FileStorage extends FileStorage { + /** + The local directory for caching. + */ + public var localPath(default, null):AbsPath; + + /** + The S3 bucket name. + */ + public var bucketName(default, null):String; + + /** + The region where the S3 bucket is located. + e.g. 'us-east-1' + */ + public var bucketRegion(default, null):aws.Region; + + /** + The public endpoint of the S3 bucket. + e.g. 'http://${bucket}.s3-website-${region}.amazonaws.com/' + */ + public var bucketEndpoint(get, never):String; + function get_bucketEndpoint() + return 'http://${bucketName}.s3-website-${bucketRegion}.amazonaws.com/'; + + var s3Client(default, null):S3Client; + var transferClient(default, null):TransferClient; + + static var awsInited = false; + + public function new(localPath:AbsPath, bucketName:String, bucketRegion:String):Void { + assertAbsolute(localPath); + this.localPath = localPath; + this.bucketName = bucketName; + this.bucketRegion = bucketRegion; + + if (!awsInited) { + Aws.initAPI(); + awsInited = true; + } + + this.transferClient = new TransferClient(this.s3Client = new S3Client(bucketRegion)); + } + + override public function readFile(file:RelPath, f:AbsPath->T):T { + assertRelative(file); + var s3Path = Path.join(['s3://${bucketName}', file]); + var localFile:AbsPath = Path.join([localPath, file]); + if (!FileSystem.exists(localFile)) { + var request = transferClient.downloadFile(localFile, bucketName, file); + while (!request.isDone()) { + Sys.sleep(0.01); + } + switch (request.getFailure()) { + case null: + //pass + case failure: + throw 'failed to download ${s3Path} to ${localPath}\n${failure}'; + } + } + return f(localFile); + } + + function uploadToS3(localFile:AbsPath, file:RelPath, contentType = "application/octet-stream") { + var s3Path = Path.join(['s3://${bucketName}', file]); + var request = transferClient.uploadFile(localFile, bucketName, file, contentType); + while (!request.isDone()) { + Sys.sleep(0.01); + } + switch (request.getFailure()) { + case null: + //pass + case failure: + throw 'failed to upload ${localFile} to ${s3Path}\n${failure}'; + } + } + + override public function writeFile(file:RelPath, f:AbsPath->T):T { + assertRelative(file); + var localFile:AbsPath = Path.join([localPath, file]); + if (!FileSystem.exists(localFile)) + throw '$localFile does not exist'; + FileSystem.createDirectory(Path.directory(localFile)); + var r = f(localFile); + uploadToS3(localFile, file); + return r; + } + + override public function importFile(srcFile:AbsPath, dstFile:RelPath, move:Bool):Void { + var localFile:AbsPath = Path.join([localPath, dstFile]); + if ( + FileSystem.exists(localFile) && + FileSystem.fullPath(localFile) == FileSystem.fullPath(srcFile) + ) { + // srcFile already located at dstFile + uploadToS3(localFile, dstFile); + return; + } + FileSystem.createDirectory(Path.directory(localFile)); + File.copy(srcFile, localFile); + uploadToS3(localFile, dstFile); + if (move) + FileSystem.deleteFile(srcFile); + } + + override public function deleteFile(file:RelPath):Void { + var localFile:AbsPath = Path.join([localPath, file]); + if (FileSystem.exists(localFile)) + FileSystem.deleteFile(localFile); + + var del = new DeleteObjectRequest(); + del.setBucket(bucketName); + del.setKey(file); + try { + s3Client.deleteObject(del); + } catch (e:Dynamic) { + // maybe the object does not exist + } + } +} \ No newline at end of file diff --git a/extra/haxelib_src/src/haxelib/server/Paths.hx b/extra/haxelib_src/src/haxelib/server/Paths.hx new file mode 100644 index 00000000..ed8205a1 --- /dev/null +++ b/extra/haxelib_src/src/haxelib/server/Paths.hx @@ -0,0 +1,54 @@ +/* + * Copyright (C)2005-2016 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 haxelib.server; + +import neko.Web; +import haxe.io.*; + +/** + Absolute path. +*/ +typedef AbsPath = String; + +/** + Relative path. +*/ +typedef RelPath = String; + +class Paths { + static public var CWD(default, null):AbsPath = + #if haxelib_api + Path.normalize(Path.join([Web.getCwd(), "..", ".."])); + #elseif haxelib_legacy + Path.normalize(Path.join([Web.getCwd(), ".."])); + #else + Web.getCwd(); + #end + static public var DB_CONFIG_NAME(default, null):RelPath = "dbconfig.json"; + static public var DB_CONFIG(default, null):AbsPath = Path.join([CWD, DB_CONFIG_NAME]); + static public var DB_FILE_NAME(default, null):RelPath = "haxelib.db"; + static public var DB_FILE(default, null):AbsPath = Path.join([CWD, DB_FILE_NAME]); + + static public var TMP_DIR_NAME(default, null):RelPath = "tmp"; + static public var TMP_DIR(default, null):AbsPath = Path.join([CWD, TMP_DIR_NAME]); + static public var REP_DIR_NAME(default, null):RelPath = Data.REPOSITORY; +} \ No newline at end of file diff --git a/extra/haxelib_src/src/haxelib/server/Repo.hx b/extra/haxelib_src/src/haxelib/server/Repo.hx new file mode 100644 index 00000000..2bbf2fac --- /dev/null +++ b/extra/haxelib_src/src/haxelib/server/Repo.hx @@ -0,0 +1,368 @@ +/* + * Copyright (C)2005-2016 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 haxelib.server; + +import haxe.io.*; +import neko.Web; +import sys.io.*; +import sys.*; + +import haxelib.Data; +import haxelib.SemVer; +import haxelib.server.Paths.*; +import haxelib.server.SiteDb; +import haxelib.server.FileStorage; + +class Repo implements SiteApi { + + static function run() { + FileSystem.createDirectory(TMP_DIR); + + var ctx = new haxe.remoting.Context(); + ctx.addObject("api", new Repo()); + + if( haxe.remoting.HttpConnection.handleRequest(ctx) ) + return; + else + throw "Invalid remoting call"; + } + + public function new() {} + + public function search( word : String ) : List<{ id : Int, name : String }> { + return Project.containing(word); + } + + public function infos( project : String ) : ProjectInfos { + var p = Project.manager.select($name == project); + if( p == null ) + throw "No such Project : "+project; + var vl = Version.manager.search($project == p.id); + + var sumDownloads = function(version:Version, total:Int) return total += version.downloads; + var totalDownloads = Lambda.fold(vl, sumDownloads, 0); + + return { + name : p.name, + curversion : if( p.versionObj == null ) null else p.versionObj.toSemver(), + desc : p.description, + versions: + [for ( v in vl ) { + name : v.toSemver(), + comments : v.comments, + downloads : v.downloads, + date : v.date + }], + owner : p.ownerObj.name, + website : p.website, + license : p.license, + downloads : totalDownloads, + tags : Tag.manager.search($project == p.id).map(function(t) return t.tag), + }; + } + + public function getLatestVersion( project : String ) : SemVer { + var p = Project.manager.select($name == project); + if( p == null ) + throw "No such Project : "+project; + + var vl = Version.manager.unsafeObjects('SELECT * FROM Version WHERE project = ${p.id} ORDER BY major DESC, minor DESC, patch DESC, ifnull(preview, 100) DESC, previewNum DESC LIMIT 1', false); + return vl.first().toSemver(); + } + + public function user( name : String ) : UserInfos { + var u = User.manager.search($name == name).first(); + if( u == null ) + throw "No such user : "+name; + var pl = Project.manager.search($owner == u.id); + var projects = new Array(); + for( p in pl ) + projects.push(p.name); + return { + name : u.name, + fullname : u.fullname, + email : u.email, + projects : projects, + }; + } + + public function register( name : String, pass : String, mail : String, fullname : String ) : Void { + if( name.length < 3 ) + throw "User name must be at least 3 characters"; + if( !Data.alphanum.match(name) ) + throw "Invalid user name, please use alphanumeric characters"; + if( User.manager.count($name == name) > 0 ) + throw 'User name "$name" is already taken'; + var u = new User(); + u.name = name; + u.pass = pass; + u.email = mail; + u.fullname = fullname; + u.insert(); + } + + public function isNewUser( name : String ) : Bool { + return User.manager.select($name == name) == null; + } + + public function checkDeveloper( prj : String, user : String ) : Void { + var p = Project.manager.search({ name : prj }).first(); + if( p == null ) + return; + for( d in Developer.manager.search({ project : p.id }) ) + if( d.userObj.name == user ) + return; + throw "User '"+user+"' is not a developer of project '"+prj+"'"; + } + + public function checkPassword( user : String, pass : String ) : Bool { + var u = User.manager.search({ name : user }).first(); + return u != null && u.pass == pass; + } + + public function getSubmitId() : String { + return Std.string(Std.random(100000000)); + } + + public function processSubmit( id : String, user : String, pass : String ) : String { + var tmpFile = Path.join([TMP_DIR_NAME, Std.parseInt(id)+".tmp"]); + return FileStorage.instance.readFile( + tmpFile, + function(path):String { + var file = try sys.io.File.read(path,true) catch( e : Dynamic ) throw "Invalid file id #"+id; + var zip = try haxe.zip.Reader.readZip(file) catch( e : Dynamic ) { file.close(); neko.Lib.rethrow(e); }; + file.close(); + + var infos = Data.readInfos(zip,true); + var u = User.manager.search({ name : user }).first(); + if( u == null || u.pass != pass ) + throw "Invalid username or password"; + + var devs = infos.contributors.map(function(user) { + var u = User.manager.search({ name : user }).first(); + if( u == null ) + throw "Unknown user '"+user+"'"; + return u; + }); + + var tags = Lambda.array(infos.tags); + tags.sort(Reflect.compare); + + var p = Project.manager.search({ name : infos.name }).first(); + + // create project if needed + if( p == null ) { + p = new Project(); + p.name = infos.name; + p.description = infos.description; + p.website = infos.url; + p.license = infos.license; + p.ownerObj = u; + p.insert(); + for( u in devs ) { + var d = new Developer(); + d.userObj = u; + d.projectObj = p; + d.insert(); + } + for( tag in tags ) { + var t = new Tag(); + t.tag = tag; + t.projectObj = p; + t.insert(); + } + } + + // check submit rights + var pdevs = Developer.manager.search({ project : p.id }); + var isdev = false; + for( d in pdevs ) + if( d.userObj.id == u.id ) { + isdev = true; + break; + } + if( !isdev ) + throw "You are not a developer of this project"; + + var otags = Tag.manager.search({ project : p.id }); + var curtags = otags.map(function(t) return t.tag).join(":"); + + var devsChanged = (pdevs.length != devs.length); + if (!devsChanged) { // same length, check whether elements are the same + for (d in pdevs) { + var exists = Lambda.exists(devs, function(u) return u.id == d.userObj.id); + if (!exists) { + devsChanged = true; + break; + } + } + } + + // update public infos + if( devsChanged || infos.description != p.description || p.website != infos.url || p.license != infos.license || tags.join(":") != curtags ) { + if( u.id != p.ownerObj.id ) + throw "Only project owner can modify project infos"; + p.description = infos.description; + p.website = infos.url; + p.license = infos.license; + p.update(); + if( devsChanged ) { + for( d in pdevs ) + d.delete(); + for( u in devs ) { + var d = new Developer(); + d.userObj = u; + d.projectObj = p; + d.insert(); + } + } + if( tags.join(":") != curtags ) { + for( t in otags ) + t.delete(); + for( tag in tags ) { + var t = new Tag(); + t.tag = tag; + t.projectObj = p; + t.insert(); + } + } + } + + // look for current version + var current = null; + for( v in Version.manager.search({ project : p.id }) ) + if( v.name == infos.version ) { + current = v; + break; + } + + // update documentation + var doc = null; + var docXML = Data.readDoc(zip); + if( docXML != null ) { + try { + var p = new haxe.rtti.XmlParser(); + p.process(Xml.parse(docXML).firstElement(),null); + p.sort(); + var roots = new Array(); + for( x in p.root ) + switch( x ) { + case TPackage(name,_,_): + switch( name ) { + case "flash","sys","cs","java","haxe","js","neko","cpp","php","python": // don't include haXe core types + default: roots.push(x); + } + default: + // don't include haXe root types + } + var s = new haxe.Serializer(); + s.useEnumIndex = true; + s.useCache = true; + s.serialize(roots); + doc = s.toString(); + } catch ( e:Dynamic ) { + // If documentation can't be generated, ignore it. + } + } + + // update file + var fileName = Data.fileName(p.name, infos.version); + var storage = FileStorage.instance; + storage.importFile(path, Path.join([Paths.REP_DIR_NAME, fileName]), true); + storage.deleteFile(tmpFile); + + var semVer = SemVer.ofString(infos.version); + + // update existing version + if( current != null ) { + current.documentation = doc; + current.comments = infos.releasenote; + current.update(); + return "Version "+current.name+" (id#"+current.id+") updated"; + } + + // add new version + var v = new Version(); + v.projectObj = p; + v.major = semVer.major; + v.minor = semVer.minor; + v.patch = semVer.patch; + v.preview = semVer.preview; + v.previewNum = semVer.previewNum; + + v.comments = infos.releasenote; + v.downloads = 0; + v.date = Date.now().toString(); + v.documentation = doc; + v.insert(); + + // p.versionObj is the one shown on the website + if (p.versionObj == null || p.versionObj.toSemver() < v.toSemver()) { + p.versionObj = v; + } + + p.update(); + return "Version " + v.toSemver() + " (id#" + v.id + ") added"; + } + ); + } + + public function postInstall( project : String, version : String ) { + var p = Project.manager.select($name == project); + if( p == null ) + throw "No such Project : " + project; + + var version = SemVer.ofString(version); + // don't use macro select because of + // https://github.com/HaxeFoundation/haxe/issues/4931 + // and https://github.com/HaxeFoundation/haxe/issues/4932 + var v = Version.manager.dynamicSearch({ + project: p.id, + major: version.major, + minor: version.minor, + patch: version.patch, + preview: if (version.preview == null) null else version.preview.getIndex(), + previewNum: version.previewNum + }).first(); + + if( v == null ) + throw "No such Version : " + version; + v.downloads++; + v.update(); + p.downloads++; + p.update(); + } + + static function main() { + var error = null; + SiteDb.init(); + try { + run(); + } catch( e : Dynamic ) { + error = { e : e }; + } + SiteDb.cleanup(); + if( error != null ) + neko.Lib.rethrow(error.e); + } + +} diff --git a/extra/haxelib_src/src/tools/haxelib/SiteDb.hx b/extra/haxelib_src/src/haxelib/server/SiteDb.hx similarity index 77% rename from extra/haxelib_src/src/tools/haxelib/SiteDb.hx rename to extra/haxelib_src/src/haxelib/server/SiteDb.hx index 8123eeed..482a0e71 100644 --- a/extra/haxelib_src/src/tools/haxelib/SiteDb.hx +++ b/extra/haxelib_src/src/haxelib/server/SiteDb.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-2016 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,13 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package tools.haxelib; +package haxelib.server; import sys.db.*; import sys.db.Types; -import tools.haxelib.Paths.*; -using sys.io.File; -using sys.FileSystem; +import haxelib.server.Paths.*; class User extends Object { @@ -45,9 +43,9 @@ class Project extends Object { public var website : String; public var license : String; public var downloads : Int = 0; - @:relation(owner) public var owner : User; - @:relation(version) public var version : SNull; - + @:relation(owner) public var ownerObj : User; + @:relation(version) public var versionObj : SNull; + static public function containing( word:String ) : List<{ id: Int, name: String }> { var ret = new List(); word = '%$word%'; @@ -67,8 +65,8 @@ class Tag extends Object { public var id : SId; public var tag : String; - @:relation(project) public var project : Project; - + @:relation(project) public var projectObj : Project; + static public function topTags( n : Int ) : List<{ tag:String, count: Int }> { return cast Manager.cnx.request("SELECT tag, COUNT(*) as count FROM Tag GROUP BY tag ORDER BY count DESC LIMIT " + n).results(); } @@ -78,15 +76,15 @@ class Tag extends Object { class Version extends Object { public var id : SId; - @:relation(project) public var project : Project; + @:relation(project) public var projectObj : Project; public var major : Int; public var minor : Int; public var patch : Int; - @:nullable public var preview : SEnum; + public var preview : SNull>; public var previewNum : SNull; @:skip public var name(get, never):String; function get_name():String return toSemver(); - + public function toSemver():SemVer { return { major: this.major, @@ -100,9 +98,9 @@ class Version extends Object { public var comments : String; public var downloads : Int; public var documentation : SNull; - + static public function latest( n : Int ) { - return manager.search(true, { orderBy: -date, limit: n } ); + return manager.search(1 == 1, { orderBy: -date, limit: n } ); } static public function byProject( p : Project ) { @@ -113,26 +111,35 @@ class Version extends Object { @:id(user,project) class Developer extends Object { - - @:relation(user) public var user : User; - @:relation(project) public var project : Project; + + @:relation(user) public var userObj : User; + @:relation(project) public var projectObj : Project; } class SiteDb { static var db : Connection; //TODO: this whole configuration business is rather messy to say the least - + static public function init() { - db = - if (DB_CONFIG.exists()) - Mysql.connect(haxe.Json.parse(DB_CONFIG.getContent())); - else + db = + if (Sys.getEnv("HAXELIB_DB_HOST") != null) + Mysql.connect({ + "host": Sys.getEnv("HAXELIB_DB_HOST"), + "port": Std.parseInt(Sys.getEnv("HAXELIB_DB_PORT")), + "database": Sys.getEnv("HAXELIB_DB_NAME"), + "user": Sys.getEnv("HAXELIB_DB_USER"), + "pass": Sys.getEnv("HAXELIB_DB_PASS"), + "socket": null + }); + else if (sys.FileSystem.exists(DB_CONFIG)) + Mysql.connect(haxe.Json.parse(sys.io.File.getContent(DB_CONFIG))); + else Sqlite.open(DB_FILE); - + Manager.cnx = db; Manager.initialize(); - + var managers:Array> = [ User.manager, Project.manager, @@ -142,13 +149,11 @@ class SiteDb { ]; for (m in managers) if (!TableCreate.exists(m)) - TableCreate.create(m); + TableCreate.create(m); } + static public function cleanup() { db.close(); Manager.cleanup(); } - public static function create( db : sys.db.Connection ) { - //now based on TableCreate when establishing the connection - } } diff --git a/extra/haxelib_src/src/tools/legacyhaxelib/.htaccess b/extra/haxelib_src/src/legacyhaxelib/.htaccess similarity index 100% rename from extra/haxelib_src/src/tools/legacyhaxelib/.htaccess rename to extra/haxelib_src/src/legacyhaxelib/.htaccess diff --git a/extra/haxelib_src/src/tools/legacyhaxelib/Data.hx b/extra/haxelib_src/src/legacyhaxelib/Data.hx similarity index 99% rename from extra/haxelib_src/src/tools/legacyhaxelib/Data.hx rename to extra/haxelib_src/src/legacyhaxelib/Data.hx index 093ef0cc..e15a567b 100644 --- a/extra/haxelib_src/src/tools/legacyhaxelib/Data.hx +++ b/extra/haxelib_src/src/legacyhaxelib/Data.hx @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package tools.legacyhaxelib; +package legacyhaxelib; import haxe.zip.Reader; import haxe.zip.Entry; diff --git a/extra/haxelib_src/src/tools/legacyhaxelib/Main.hx b/extra/haxelib_src/src/legacyhaxelib/Main.hx similarity index 99% rename from extra/haxelib_src/src/tools/legacyhaxelib/Main.hx rename to extra/haxelib_src/src/legacyhaxelib/Main.hx index bdba8e1a..caeefc83 100644 --- a/extra/haxelib_src/src/tools/legacyhaxelib/Main.hx +++ b/extra/haxelib_src/src/legacyhaxelib/Main.hx @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package tools.legacyhaxelib; +package legacyhaxelib; import haxe.zip.Reader; enum Answer { @@ -28,7 +28,7 @@ enum Answer { Always; } -class SiteProxy extends haxe.remoting.Proxy { +class SiteProxy extends haxe.remoting.Proxy { } class Progress extends haxe.io.Output { diff --git a/extra/haxelib_src/src/tools/legacyhaxelib/Site.hx b/extra/haxelib_src/src/legacyhaxelib/Site.hx similarity index 87% rename from extra/haxelib_src/src/tools/legacyhaxelib/Site.hx rename to extra/haxelib_src/src/legacyhaxelib/Site.hx index b3f113a9..b8deded5 100644 --- a/extra/haxelib_src/src/tools/legacyhaxelib/Site.hx +++ b/extra/haxelib_src/src/legacyhaxelib/Site.hx @@ -19,11 +19,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package tools.legacyhaxelib; +package legacyhaxelib; #if haxelib_site -import tools.legacyhaxelib.SiteDb; +import legacyhaxelib.SiteDb; #end import haxe.rtti.CType; +import haxelib.server.FileStorage; +import haxe.io.Path; class Site { @@ -39,9 +41,14 @@ class Site { } static function initDatabase() { - db = neko.db.Sqlite.open(DB_FILE); - neko.db.Manager.cnx = db; - neko.db.Manager.initialize(); + var path = "legacy/haxelib.db"; + FileStorage.instance.readFile(path, function(file) { + if (Path.normalize(DB_FILE) != Path.normalize(file)) + throw '$file should be the same as $DB_FILE'; + db = neko.db.Sqlite.open(DB_FILE); + neko.db.Manager.cnx = db; + neko.db.Manager.initialize(); + }); } static function run() { @@ -150,26 +157,26 @@ class Site { return error("Project "+p.name+" version "+version+" has no documentation"); var root : TypeRoot = haxe.Unserializer.run(v.documentation); var buf = new StringBuf(); - var html = new tools.haxedoc.HtmlPrinter("/d/"+p.name+"/"+version+"/","",""); - html.output = function(str) buf.add(str); - var path = uri.join(".").toLowerCase().split("."); - if( path.length == 1 && path[0] == "" ) - path = []; - if( path.length == 0 ) { - ctx.index = true; - html.process(TPackage("root","root",root)); - } else { - var cl = html.find(root,path,0); - if( cl == null ) { - // we most likely clicked on a class which is part of the haxe core documentation - neko.Web.redirect("http://haxe.org/api/"+path.join("/")); - return false; - } - html.process(cl); - } - ctx.p = p; - ctx.v = v; - ctx.content = buf.toString(); +// var html = new tools.haxedoc.HtmlPrinter("/d/"+p.name+"/"+version+"/","",""); +// html.output = function(str) buf.add(str); +// var path = uri.join(".").toLowerCase().split("."); +// if( path.length == 1 && path[0] == "" ) +// path = []; +// if( path.length == 0 ) { +// ctx.index = true; +// html.process(TPackage("root","root",root)); +// } else { +// var cl = html.find(root,path,0); +// if( cl == null ) { +// // we most likely clicked on a class which is part of the haxe core documentation +// neko.Web.redirect("http://haxe.org/api/"+path.join("/")); +// return false; +// } +// html.process(cl); +// } +// ctx.p = p; +// ctx.v = v; +// ctx.content = buf.toString(); case "index": var vl = Version.manager.latest(10); for( v in vl ) { diff --git a/extra/haxelib_src/src/tools/legacyhaxelib/SiteApi.hx b/extra/haxelib_src/src/legacyhaxelib/SiteApi.hx similarity index 98% rename from extra/haxelib_src/src/tools/legacyhaxelib/SiteApi.hx rename to extra/haxelib_src/src/legacyhaxelib/SiteApi.hx index a6db5d1c..9c181f2f 100644 --- a/extra/haxelib_src/src/tools/legacyhaxelib/SiteApi.hx +++ b/extra/haxelib_src/src/legacyhaxelib/SiteApi.hx @@ -19,10 +19,10 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package tools.legacyhaxelib; -import tools.legacyhaxelib.Data; +package legacyhaxelib; +import legacyhaxelib.Data; #if haxelib_site -import tools.legacyhaxelib.SiteDb; +import legacyhaxelib.SiteDb; #end class SiteApi { @@ -245,7 +245,8 @@ class SiteApi { // update file var target = Site.REP_DIR+"/"+Data.fileName(p.name,infos.version); if( current != null ) sys.FileSystem.deleteFile(target); - sys.FileSystem.rename(path,target); + sys.io.File.copy(path,target); + sys.FileSystem.deleteFile(path); // update existing version if( current != null ) { diff --git a/extra/haxelib_src/src/tools/legacyhaxelib/SiteDb.hx b/extra/haxelib_src/src/legacyhaxelib/SiteDb.hx similarity index 99% rename from extra/haxelib_src/src/tools/legacyhaxelib/SiteDb.hx rename to extra/haxelib_src/src/legacyhaxelib/SiteDb.hx index fa772163..a0283b2d 100644 --- a/extra/haxelib_src/src/tools/legacyhaxelib/SiteDb.hx +++ b/extra/haxelib_src/src/legacyhaxelib/SiteDb.hx @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -package tools.legacyhaxelib; +package legacyhaxelib; class User extends neko.db.Object { diff --git a/extra/haxelib_src/src/tools/legacyhaxelib/haxelib.css b/extra/haxelib_src/src/legacyhaxelib/haxelib.css similarity index 100% rename from extra/haxelib_src/src/tools/legacyhaxelib/haxelib.css rename to extra/haxelib_src/src/legacyhaxelib/haxelib.css diff --git a/extra/haxelib_src/src/tools/legacyhaxelib/haxelib.hxml b/extra/haxelib_src/src/legacyhaxelib/haxelib.hxml similarity index 58% rename from extra/haxelib_src/src/tools/legacyhaxelib/haxelib.hxml rename to extra/haxelib_src/src/legacyhaxelib/haxelib.hxml index e98559c9..abad7f59 100644 --- a/extra/haxelib_src/src/tools/legacyhaxelib/haxelib.hxml +++ b/extra/haxelib_src/src/legacyhaxelib/haxelib.hxml @@ -1,3 +1,3 @@ --neko haxelib.n --main tools.legacyhaxelib.Main --cmd "nekotools boot haxelib.n" +-neko haxelib.n +-main legacyhaxelib.Main +-cmd "nekotools boot haxelib.n" diff --git a/extra/haxelib_src/src/legacyhaxelib/haxelib.sh b/extra/haxelib_src/src/legacyhaxelib/haxelib.sh new file mode 100644 index 00000000..cad281ca --- /dev/null +++ b/extra/haxelib_src/src/legacyhaxelib/haxelib.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exec haxe --run legacyhaxelib.Main "$@" diff --git a/extra/haxelib_src/src/legacyhaxelib/site.hxml b/extra/haxelib_src/src/legacyhaxelib/site.hxml new file mode 100644 index 00000000..ef1b1df6 --- /dev/null +++ b/extra/haxelib_src/src/legacyhaxelib/site.hxml @@ -0,0 +1,5 @@ +-neko index.n +-main legacyhaxelib.Site +-dce no +-D haxelib-site +-lib hx2compat \ No newline at end of file diff --git a/extra/haxelib_src/src/tools/legacyhaxelib/website.mtt b/extra/haxelib_src/src/legacyhaxelib/website.mtt similarity index 100% rename from extra/haxelib_src/src/tools/legacyhaxelib/website.mtt rename to extra/haxelib_src/src/legacyhaxelib/website.mtt diff --git a/extra/haxelib_src/src/tools/haxelib/Paths.hx b/extra/haxelib_src/src/tools/haxelib/Paths.hx deleted file mode 100644 index 1acf47df..00000000 --- a/extra/haxelib_src/src/tools/haxelib/Paths.hx +++ /dev/null @@ -1,19 +0,0 @@ -package tools.haxelib; - -class Paths { - static var RELATIVE_ROOT = - #if haxelib_api - '../../'; - #else - ''; - #end - //TODO: these should be inline or read-only or whatever - static public var CWD = neko.Web.getCwd() + RELATIVE_ROOT; - static public var DB_CONFIG = CWD + "dbconfig.json"; - static public var DB_FILE = CWD + "haxelib.db"; - - static public var TMP_DIR = CWD + "tmp"; - static public var TMPL_DIR = CWD + "tmpl/"; - static public var REP_DIR = CWD + Data.REPOSITORY; - -} \ No newline at end of file diff --git a/extra/haxelib_src/src/tools/haxelib/Rebuild.hx b/extra/haxelib_src/src/tools/haxelib/Rebuild.hx deleted file mode 100644 index 946fd5b4..00000000 --- a/extra/haxelib_src/src/tools/haxelib/Rebuild.hx +++ /dev/null @@ -1,46 +0,0 @@ -package tools.haxelib; - -import sys.FileSystem; -import sys.io.Process; - -class Rebuild { - static function run(cmd:String, ?msg:String = '', ?args:Array) { - if (args == null) args = []; - var p = new Process(cmd, args); - if (p.exitCode() != 0) - throw 'Error $msg:' + p.stderr.readAll().toString(); - } - static function main() - try { - Sys.sleep(.5);//wait for calling haxelib to exit - switch Sys.systemName() { - case 'Windows': - case os: throw 'Wrong OS. Expected Windows but detected $os'; - } - var haxepath = Sys.getEnv("HAXEPATH"); - var file = '$haxepath/haxelib.n'; - - run('haxe', 'rebuilding haxelib', [ - '-neko', file, - '-lib', 'haxelib_client', - '-main', 'tools.haxelib.Main', - ]); - run('nekotools', 'booting haxe', ['boot', file]); - FileSystem.deleteFile(file); - var oldMode = FileSystem.exists('update.hxml'); - if (oldMode) - FileSystem.deleteFile('update.hxml'); - - Sys.println('Update successful.'); - - if (!oldMode) { - Sys.println('Rebuild will exit in 5 seconds.'); - Sys.sleep(5.0); - } - } - catch (e:Dynamic) { - Sys.println(Std.string(e)); - Sys.println('Press any key to close'); - Sys.getChar(false); - } -} \ No newline at end of file diff --git a/extra/haxelib_src/src/tools/haxelib/Repo.hx b/extra/haxelib_src/src/tools/haxelib/Repo.hx deleted file mode 100644 index 4a31e389..00000000 --- a/extra/haxelib_src/src/tools/haxelib/Repo.hx +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (C)2005-2012 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 tools.haxelib; -import haxe.io.Bytes; -import tools.haxelib.Data; -import tools.haxelib.Paths.*; -import tools.haxelib.SiteDb; -import neko.Web; -import tools.haxelib.SemVer; - -class Repo implements SiteApi { - - static function run() { - if( !sys.FileSystem.exists(TMP_DIR) ) - sys.FileSystem.createDirectory(TMP_DIR); - if( !sys.FileSystem.exists(REP_DIR) ) - sys.FileSystem.createDirectory(REP_DIR); - - var ctx = new haxe.remoting.Context(); - ctx.addObject("api", new Repo()); - - if( haxe.remoting.HttpConnection.handleRequest(ctx) ) - return; - else - throw "Invalid remoting call"; - } - - public function new() {} - - public function search( word : String ) : List<{ id : Int, name : String }> { - return Project.containing(word); - } - - public function infos( project : String ) : ProjectInfos { - var p = Project.manager.select($name == project); - if( p == null ) - throw "No such Project : "+project; - var vl = Version.manager.search($project == p.id); - - return { - name : p.name, - curversion : if( p.version == null ) null else p.version.toSemver(), - desc : p.description, - versions: - [for ( v in vl ) { - name : v.toSemver(), - comments : v.comments, - date : v.date - }], - owner : p.owner.name, - website : p.website, - license : p.license, - tags : Tag.manager.search($project == p.id).map(function(t) return t.tag), - }; - } - - public function user( name : String ) : UserInfos { - var u = User.manager.search($name == name).first(); - if( u == null ) - throw "No such user : "+name; - var pl = Project.manager.search($owner == u.id); - var projects = new Array(); - for( p in pl ) - projects.push(p.name); - return { - name : u.name, - fullname : u.fullname, - email : u.email, - projects : projects, - }; - } - - public function register( name : String, pass : String, mail : String, fullname : String ) : Bool { - if( !Data.alphanum.match(name) ) - throw "Invalid user name, please use alphanumeric characters"; - if( name.length < 3 ) - throw "User name must be at least 3 characters"; - var u = new User(); - u.name = name; - u.pass = pass; - u.email = mail; - u.fullname = fullname; - u.insert(); - return null; - } - - public function isNewUser( name : String ) : Bool { - return User.manager.select($name == name) == null; - } - - public function checkDeveloper( prj : String, user : String ) : Void { - var p = Project.manager.search({ name : prj }).first(); - if( p == null ) - return; - for( d in Developer.manager.search({ project : p.id }) ) - if( d.user.name == user ) - return; - throw "User '"+user+"' is not a developer of project '"+prj+"'"; - } - - public function checkPassword( user : String, pass : String ) : Bool { - var u = User.manager.search({ name : user }).first(); - return u != null && u.pass == pass; - } - - public function getSubmitId() : String { - return Std.string(Std.random(100000000)); - } - - public function processSubmit( id : String, user : String, pass : String ) : String { - var path = TMP_DIR+"/"+Std.parseInt(id)+".tmp"; - - var file = try sys.io.File.read(path,true) catch( e : Dynamic ) throw "Invalid file id #"+id; - var zip = try haxe.zip.Reader.readZip(file) catch( e : Dynamic ) { file.close(); neko.Lib.rethrow(e); }; - file.close(); - - var infos = Data.readInfos(zip,true); - var u = User.manager.search({ name : user }).first(); - if( u == null || u.pass != pass ) - throw "Invalid username or password"; - - var devs = infos.contributors.map(function(user) { - var u = User.manager.search({ name : user }).first(); - if( u == null ) - throw "Unknown user '"+user+"'"; - return u; - }); - - var tags = Lambda.array(infos.tags); - tags.sort(Reflect.compare); - - var p = Project.manager.search({ name : infos.name }).first(); - - // create project if needed - if( p == null ) { - p = new Project(); - p.name = infos.name; - p.description = infos.description; - p.website = infos.url; - p.license = infos.license; - p.owner = u; - p.insert(); - for( u in devs ) { - var d = new Developer(); - d.user = u; - d.project = p; - d.insert(); - } - for( tag in tags ) { - var t = new Tag(); - t.tag = tag; - t.project = p; - t.insert(); - } - } - - // check submit rights - var pdevs = Developer.manager.search({ project : p.id }); - var isdev = false; - for( d in pdevs ) - if( d.user.id == u.id ) { - isdev = true; - break; - } - if( !isdev ) - throw "You are not a developer of this project"; - - var otags = Tag.manager.search({ project : p.id }); - var curtags = otags.map(function(t) return t.tag).join(":"); - - // update public infos - if( infos.description != p.description || p.website != infos.url || p.license != infos.license || pdevs.length != devs.length || tags.join(":") != curtags ) { - if( u.id != p.owner.id ) - throw "Only project owner can modify project infos"; - p.description = infos.description; - p.website = infos.url; - p.license = infos.license; - p.update(); - if( pdevs.length != devs.length ) { - for( d in pdevs ) - d.delete(); - for( u in devs ) { - var d = new Developer(); - d.user = u; - d.project = p; - d.insert(); - } - } - if( tags.join(":") != curtags ) { - for( t in otags ) - t.delete(); - for( tag in tags ) { - var t = new Tag(); - t.tag = tag; - t.project = p; - t.insert(); - } - } - } - - // look for current version - var current = null; - for( v in Version.manager.search({ project : p.id }) ) - if( v.name == infos.version ) { - current = v; - break; - } - - // update documentation - var doc = null; - var docXML = Data.readDoc(zip); - if( docXML != null ) { - try { - var p = new haxe.rtti.XmlParser(); - p.process(Xml.parse(docXML).firstElement(),null); - p.sort(); - var roots = new Array(); - for( x in p.root ) - switch( x ) { - case TPackage(name,_,_): - switch( name ) { - case "flash","flash8","sys","cs","java","flash9","haxe","js","neko","cpp","php","tools": // don't include haXe core types - default: roots.push(x); - } - default: - // don't include haXe root types - } - var s = new haxe.Serializer(); - s.useEnumIndex = true; - s.useCache = true; - s.serialize(roots); - doc = s.toString(); - } catch ( e:Dynamic ) { - // If documentation can't be generated, ignore it. - } - } - - // update file - var target = REP_DIR + "/" + Data.fileName(p.name, infos.version); - sys.FileSystem.rename(path,target); - var semVer = SemVer.ofString(infos.version); - - // update existing version - if( current != null ) { - current.documentation = doc; - current.comments = infos.releasenote; - current.update(); - return "Version "+current.name+" (id#"+current.id+") updated"; - } - - // add new version - var v = new Version(); - v.project = p; - v.major = semVer.major; - v.minor = semVer.minor; - v.patch = semVer.patch; - v.preview = semVer.preview; - v.previewNum = semVer.previewNum; - - v.comments = infos.releasenote; - v.downloads = 0; - v.date = Date.now().toString(); - v.documentation = doc; - v.insert(); - - p.version = v; - p.update(); - return "Version " + v.toSemver() + " (id#" + v.id + ") added"; - } - - public function postInstall( project : String, version : String ) { - var p = Project.manager.select($name == project); - if( p == null ) - throw "No such Project : " + project; - - var version = SemVer.ofString(version); - var v = Version.manager.select( - $project == p.id && - $major == version.major && - $minor == version.minor && - $patch == version.patch && - $preview == version.preview && - $previewNum == version.previewNum - ); - if( v == null ) - throw "No such Version : " + version; - v.downloads++; - v.update(); - p.downloads++; - p.update(); - } - - static function main() { - var error = null; - SiteDb.init(); - try { - run(); - } catch( e : Dynamic ) { - error = { e : e }; - } - SiteDb.cleanup(); - if( error != null ) - neko.Lib.rethrow(error.e); - } - -} \ No newline at end of file diff --git a/extra/haxelib_src/src/tools/haxelib/Site.hx b/extra/haxelib_src/src/tools/haxelib/Site.hx deleted file mode 100644 index 937823d5..00000000 --- a/extra/haxelib_src/src/tools/haxelib/Site.hx +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (C)2005-2012 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 tools.haxelib; - -import haxe.web.Dispatch; -import neko.Lib; -import neko.Web; -import sys.db.*; -import sys.io.File; -import tools.haxelib.SiteDb; -import haxe.rtti.CType; -import haxe.Json; -import tools.haxelib.Paths.*; - -using sys.io.File; -using sys.FileSystem; -using Lambda; - -class Site { - static function setup() {}//obsolete - - static function run() { - - if( !sys.FileSystem.exists(TMP_DIR) ) - sys.FileSystem.createDirectory(TMP_DIR); - if( !sys.FileSystem.exists(REP_DIR) ) - sys.FileSystem.createDirectory(REP_DIR); - - if( Sys.args()[0] == "setup" ) { - setup(); - Sys.print("Setup done\n"); - return; - } - var file = null; - var sid = null; - var bytes = 0; - - //RAPTORS: the whole handling for nekotools is seriously evil - if (Sys.executablePath().indexOf('nekotools') == -1) - Web.parseMultipart(function(p,filename) { - if( p == "file" ) { - sid = Std.parseInt(filename); - file = sys.io.File.write(TMP_DIR + "/" + sid + ".tmp", true); - } else - throw p+" not accepted"; - },function(data,pos,len) { - bytes += len; - file.writeFullBytes(data,pos,len); - }); - else { - var post = Web.getPostData(); - if (post != null) { - var index = post.indexOf('PK'); - if (index == -1) - throw 'Invalid Zip - or so I claim'; - - var start = post.substr(0, index); - var data = post.substr(index); - - sid = Std.parseInt(start.split('filename="').pop()); - file = sys.io.File.write(TMP_DIR + "/" + sid + ".tmp", true); - bytes = data.length;//thank got neko does not use utf8 - file.writeString(data); - } - } - - if( file != null ) { - file.close(); - Sys.print("File #"+sid+" accepted : "+bytes+" bytes written"); - return; - } - display(); - } - - static function getTemplate(name:String) { - var data = File.getContent(TMPL_DIR + name + '.mtt'); - return new Template(data); - } - static var macros = { - download : function( res:String->Dynamic, p, v ) { - return "/" + Data.REPOSITORY + "/" + Data.fileName(res(p).name, res(v).toSemver().toString()); - }, - }; - - static function display() { - - // required by all templates - haxe.Template.globals.menuTags = Tag.topTags(10); - - var uri = Web.getURI(); - if (uri == "/index.n") uri = "/"; - - try { - Dispatch.run(uri,Web.getParams(), Site); - } - catch (e:DispatchError) { - // TODO: maybe we could give a nicer error message - error('Page not found:' + uri); - } - - } - static function error(msg:String) { - render('error', { - error: StringTools.htmlEscape(msg), - legacyurl: "/legacy"+Web.getURI() - }); - } - // render content into layout template - static function render(page:String, context:Dynamic) { - var layout = getTemplate('layout'); - var content = getTemplate(page); - Sys.print(layout.execute({ - content: content.execute(context, macros), - site: neko.Web.getHostName() - })); - } - // index page - static function doDefault() { - var vl = Version.latest(10); - for( v in vl ) { - var p = v.project; // fetch - } - return render('index', { - versions: vl - }); - } - - // project page - static function doP(name:String) { - var p = Project.manager.select({ name : name }); - if( p == null ) - return error("Unknown project '"+name+"'"); - return render('project', { - p: p, - owner: p.owner, - version: p.version, - versions: Version.byProject(p), - tags: Tag.manager.search({ project : p.id }) - }); - } - - // user page - static function doU(name:String) { - var u = User.manager.select({ name : name }); - if( u == null ) - return error("Unknown user '"+name+"'"); - return render('user', { - u: u, - uprojects: Developer.manager.search({ user : u.id }).map(function(d:Developer) { return d.project; }) - }); - } - - // tag page - static function doT(tagName: String) { - render('tag', { - tag: StringTools.htmlEscape(tagName), - tprojects: Tag.manager.search({ tag : tagName }).map(function(t) return t.project) - }); - } - - // list of all projects page - static function doAll() { - render('list', { - projects: Project.allByName() - }); - } - - // documenation - static function doD(name:String, version:Null) { - return error('Library documenation display is currently not implemented'); - /* - // TODO: the current project does not allow uploads with documenation, this ported, but not tested - var ctx:Dynamic = {}; - var p = Project.manager.select({ name : name }); - if( p == null ) - return error("Unknown project '"+name+"'"); - var v; - if( version == null ) { - v = p.version; - version = v.name; - } else { - v = Version.manager.select( { project : p.id, name : version } ); - if( v == null ) return error("Unknown version '"+version+"'"); - } - if( v.documentation == null ) - return error("Project "+p.name+" version "+version+" has no documentation"); - var root : TypeRoot = haxe.Unserializer.run(v.documentation); - var buf = new StringBuf(); - var html = new tools.haxedoc.HtmlPrinter("/d/"+p.name+"/"+version+"/","",""); - html.output = function(str) buf.add(str); - var path = uri.join(".").toLowerCase().split("."); - if( path.length == 1 && path[0] == "" ) - path = []; - if( path.length == 0 ) { - ctx.index = true; - html.process(TPackage("root","root",root)); - } else { - var cl = html.find(root,path,0); - if( cl == null ) { - // we most likely clicked on a class which is part of the haxe core documentation - Web.redirect("http://haxe.org/api/"+path.join("/")); - return false; - } - html.process(cl); - } - ctx.p = p; - ctx.v = v; - ctx.content = buf.toString(); - return render('documentation', {}); - */ - } - - // search - static function doSearch() { - var v = Web.getParams().get("v"); - var p = Project.manager.select({ name : v }); - if( p != null ) { - return Web.redirect("/p/"+p.name); - } - if( Tag.manager.count({ tag : v }) > 0 ) { - return Web.redirect("/t/"+v); - } - return render('list', { - search: StringTools.htmlEscape(v), - projects: Project.containing(v).map(function(p) return Project.manager.get(p.id)) - }); - } - - // RSS feed - static function doRss() { - Web.setHeader("Content-Type", "text/xml; charset=UTF-8"); - Sys.println(''); - Sys.print(buildRss().toString()); - } - - static function buildRss() : Xml { - var createChild = function(root:Xml, name:String){ - var c = Xml.createElement(name); - root.addChild(c); - return c; - } - var createChildWithContent = function(root:Xml, name:String, content:String){ - var e = Xml.createElement(name); - var c = Xml.createPCData(if (content != null) content else ""); - e.addChild(c); - root.addChild(e); - return e; - } - var createChildWithCdata = function(root:Xml, name:String, content:String){ - var e = Xml.createElement(name); - var c = Xml.createCData(if (content != null) content else ""); - e.addChild(c); - root.addChild(e); - return e; - } - Sys.setTimeLocale("en_US.UTF8"); - var url = "http://"+Web.getClientHeader("Host"); - var rss = Xml.createElement("rss"); - var num = 50; - rss.set("version","2.0"); - var channel = createChild(rss, "channel"); - createChildWithContent(channel, "title", 'Latest haxelib releases (${neko.Web.getHostName()})'); - createChildWithContent(channel, "link", url); - createChildWithContent(channel, "description", 'The $num latest haxelib releases on ${neko.Web.getHostName()}'); - createChildWithContent(channel, "generator", "haxe"); - createChildWithContent(channel, "language", "en"); - for (v in Version.latest(num)){ - var project = v.project; - var item = createChild(channel, "item"); - createChildWithContent(item, "title", StringTools.htmlEscape(project.name + " " + v.toSemver())); - createChildWithContent(item, "link", url+"/p/"+project.name); - createChildWithContent(item, "guid", url+"/p/"+project.name+"?v="+v.id); - var date = DateTools.format(Date.fromString(v.date), "%a, %e %b %Y %H:%M:%S %z"); - createChildWithContent(item, "pubDate", date); - createChildWithContent(item, "author", project.owner.name); - createChildWithContent(item, "description", StringTools.htmlEscape(v.comments)); - } - return rss; - } - - static function main() { - var error = null; - SiteDb.init(); - try { - run(); - } catch( e : Dynamic ) { - error = { e : e }; - } - SiteDb.cleanup(); - if( error != null ) - Lib.rethrow(error.e); - } - -} diff --git a/extra/haxelib_src/src/tools/haxelib/Template.hx b/extra/haxelib_src/src/tools/haxelib/Template.hx deleted file mode 100644 index fd0f55a5..00000000 --- a/extra/haxelib_src/src/tools/haxelib/Template.hx +++ /dev/null @@ -1,72 +0,0 @@ -package tools.haxelib; - -import haxe.ds.Option; -import haxe.ds.StringMap; - -class Template extends haxe.Template { - static var fieldCache = new StringMap(); - static function fieldMap(type:Class) { - var name = Type.getClassName(type); - if (!fieldCache.exists(name)) { - fieldCache.set(name, [for (field in Type.getInstanceFields(type)) field => true]); - } - return fieldCache.get(name); - } - function tryField(o:Dynamic, field:String):Option { - return - switch Type.typeof(o) { - case TClass(c): - var fields = fieldMap(c); - if (fields.exists(field) || fields.exists('get_$field')) - Some(Reflect.getProperty(o, field)); - else { - None; - } - default: - if (Reflect.hasField(o, field)) Some(Reflect.field(o, field)); - else None; - } - } - function getField(o, field) - return - switch tryField(o, field) { - case Some(v): v; - case None: null; - } - - override private function makePath(e:Void -> Dynamic, l):Dynamic { - if (false) super.makePath(e, l);//to infer l - - var p = l.first(); - if( p == null || p.p != "." ) - return e; - l.pop(); - var field = l.pop(); - if( field == null || !field.s ) - throw field.p; - var f = field.p; - haxe.Template.expr_trim.match(f); - f = haxe.Template.expr_trim.matched(1); - return makePath(function() { return getField(e(), f); }, l); - } - override function resolve(field:String):Dynamic { - switch tryField(context, field) { - case Some(v): return v; - case None: - } - for (ctx in stack) - switch tryField(ctx, field) { - case Some(v): return v; - case None: - } - - if (field == "__current__" ) - return context; - - return - switch tryField(haxe.Template.globals, field) { - case Some(v): v; - case None: null; - } - } -} \ No newline at end of file diff --git a/extra/haxelib_src/src/tools/haxelib/Vcs.hx b/extra/haxelib_src/src/tools/haxelib/Vcs.hx deleted file mode 100644 index a8709e9a..00000000 --- a/extra/haxelib_src/src/tools/haxelib/Vcs.hx +++ /dev/null @@ -1,399 +0,0 @@ -package tools.haxelib; - -import tools.haxelib.Main; -import sys.FileSystem; - - - -interface IVcs -{ - public var name(default, null):String; - public var directory(default, null):String; - public var executable(default, null):String; - //TODO: public var internalDirectory(default, null):String; - - public var available(get_available, null):Bool; - - - - /** - Clone repo into CWD. - CWD must be like "...haxelib-repo/lib/git" for Git. - **/ - public function clone(libPath:String, vcsPath:String, ?branch:String, ?version:String, ?settings:Settings):Void; - - // check available updates for repo in CWD/{directory} - //TODO: public function updatable(libName:String):Void; - - /** - Update to HEAD repo contains in CWD or CWD/`Vcs.directory`. - CWD must be like "...haxelib-repo/lib/git" for Git. - Returns `true` if update successful. - **/ - public function update(libName:String, ?settings:Settings):Bool; - - // reset all changes in repo in CWD/{directory} - //TODO: public function reset(?cwd:String):Void; -} - - -@:enum abstract VcsID(String) to String -{ - var Hg = "hg"; - var Git = "git"; -} - -enum VcsError -{ - VcsUnavailable(vcs:Vcs); - CantCloneRepo(vcs:Vcs, repo:String, ?stderr:String); - CantCheckoutBranch(vcs:Vcs, branch:String, stderr:String); - CantCheckoutVersion(vcs:Vcs, version:String, stderr:String); -} - - -typedef Settings = -{ - var flat:Bool; - @:optional var quiet:Bool; - @:optional var debug:Bool; -}; - - -class Vcs implements IVcs -{ - private static var reg:Map; - - //----------- properties, fields ------------// - - public var name(default, null):String; - public var directory(default, null):String; - public var executable(default, null):String; - - public var available(get_available, null):Bool; - private var availabilityChecked:Bool = false; - private var executableSearched:Bool = false; - - private var cli(default, null):Cli; - - //--------------- constructor ---------------// - - public static function initialize() - { - if(reg == null) - reg = [VcsID.Git => new Git(), VcsID.Hg => new Mercurial()]; - else - { - if(reg.get(VcsID.Git) == null) - reg.set(VcsID.Git, new Git()); - if(reg.get(VcsID.Hg) == null) - reg.set(VcsID.Hg, new Mercurial()); - } - } - - - private function new(executable:String, directory:String, name:String) - { - this.name = name; - this.directory = directory; - this.executable = executable; - - cli = new Cli(); - } - - - //----------------- static ------------------// - - public static function get(id:VcsID):Null - { - initialize(); - return reg.get(id); - } - - private static function set(id:VcsID, vcs:Vcs, ?rewrite:Bool):Void - { - initialize(); - var existing = reg.get(id) != null; - if(!existing || (existing && rewrite)) - reg.set(id, vcs); - } - - public static function getVcsForDevLib(libPath:String):Null - { - initialize(); - for(k in reg.keys()) - { - if(FileSystem.exists(libPath + "/" + k) && FileSystem.isDirectory(libPath + "/" + k)) - return reg.get(k); - } - return null; - } - - - //--------------- initialize ----------------// - - private function searchExecutable():Void - { - executableSearched = true; - } - - private function checkExecutable():Bool - { - available = - executable != null && try - { - cli.command(executable, []).code == 0; - } - catch(e:Dynamic) false; - availabilityChecked = true; - - if(!available && !executableSearched) - searchExecutable(); - - return available; - } - - @:final function get_available():Bool - { - if(!availabilityChecked) - checkExecutable(); - return this.available; - } - - //----------------- ctrl -------------------// - - public function clone(libPath:String, vcsPath:String, ?branch:String, ?version:String, ?settings:Settings):Void - { - throw "This method must be overriden."; - } - - public function update(libName:String, ?settings:Settings):Bool - { - throw "This method must be overriden."; - return false; - } - - - public function toString():String - { - return Type.getClassName(Type.getClass(this)); - } -} - - -class Git extends Vcs -{ - public static function init() - { - Vcs.set(VcsID.Git, new Git()); - } - - public function new() - super("git", "git", "Git"); - - - override private function checkExecutable():Bool - { - available = - executable != null && try - { - // with `help` cmd because without any cmd `git` can return exit-code = 1. - cli.command(executable, ["help"]).code == 0; - } - catch(e:Dynamic) false; - availabilityChecked = true; - - if(!available && !executableSearched) - searchExecutable(); - - return available; - } - - override private function searchExecutable():Void - { - super.searchExecutable(); - - if(available) - return; - - // if we have already msys git/cmd in our PATH - var match = ~/(.*)git([\\|\/])cmd$/; - for(path in Sys.getEnv("PATH").split(";")) - { - if(match.match(path.toLowerCase())) - { - var newPath = match.matched(1) + executable + match.matched(2) + "bin"; - Sys.putEnv("PATH", Sys.getEnv("PATH") + ";" + newPath); - } - } - if(checkExecutable()) - return; - // look at a few default paths - for(path in ["C:\\Program Files (x86)\\Git\\bin", "C:\\Progra~1\\Git\\bin"]) - if(FileSystem.exists(path)) - { - Sys.putEnv("PATH", Sys.getEnv("PATH") + ";" + path); - if(checkExecutable()) - return; - } - } - - override public function update(libName:String, ?settings:Settings):Bool - { - var doPull = true; - - if(0 != Sys.command(executable, ["diff", "--exit-code"]) || 0 != Sys.command(executable, ["diff", "--cached", "--exit-code"])) - { - switch cli.ask("Reset changes to " + libName + " " + name + " repo so we can pull latest version?") - { - case Answer.Yes: - Sys.command(executable, ["reset", "--hard"]); - case Answer.No: - doPull = false; - cli.print(name + " repo left untouched"); - } - } - if(doPull) - { - var code = Sys.command(executable, ["pull"]); - // But if before we pulled specified branch/tag/rev => then possibly currently we haxe "HEAD detached at ..". - if(code != 0) - { - // get parent-branch: - var branch = cli.command(executable, ["show-branch"]).out; - var regx = ~/\[([^]]*)\]/; - if(regx.match(branch)) - branch = regx.matched(1); - - Sys.command(executable, ["checkout", branch, "--force"]); - Sys.command(executable, ["pull"]); - } - } - return doPull; - } - - override public function clone(libPath:String, url:String, ?branch:String, ?version:String, ?settings:Settings):Void - { - var vcsArgs = ["clone", url, libPath]; - - if(settings == null || !settings.flat) - vcsArgs.push('--recursive'); - - //TODO: move to Vcs.run(vcsArgs) - //TODO: use settings.quiet - if(Sys.command(executable, vcsArgs) != 0) - { - throw VcsError.CantCloneRepo(this, url/*, ret.out*/); - } - - - var cwd = cli.cwd; - cli.cwd = libPath; - - if(branch != null) - { - var ret = cli.command(executable, ["checkout", branch]); - if(ret.code != 0) - throw VcsError.CantCheckoutBranch(this, branch, ret.out); - } - - if(version != null) - { - var ret = cli.command(executable, ["checkout", "tags/" + version]); - if(ret.code != 0) - throw VcsError.CantCheckoutVersion(this, version, ret.out); - } - - // return prev. cwd: - cli.cwd = cwd; - } -} - - -class Mercurial extends Vcs -{ - public static function init() - { - Vcs.set(VcsID.Hg, new Mercurial()); - } - - public function new() - super("hg", "hg", "Mercurial"); - - override private function searchExecutable():Void - { - super.searchExecutable(); - - if(available) - return; - - // if we have already msys git/cmd in our PATH - var match = ~/(.*)hg([\\|\/])cmd$/; - for(path in Sys.getEnv("PATH").split(";")) - { - if(match.match(path.toLowerCase())) - { - var newPath = match.matched(1) + executable + match.matched(2) + "bin"; - Sys.putEnv("PATH", Sys.getEnv("PATH") + ";" + newPath); - } - } - checkExecutable(); - } - - override public function update(libName:String, ?settings:Settings):Bool - { - var changed = false; - cli.command(executable, ["pull"]); - var summary = cli.command(executable, ["summary"]).out; - var diff = cli.command(executable, ["diff", "-U", "2", "--git", "--subrepos"]); - var status = cli.command(executable, ["status"]); - - // get new pulled changesets: - // (and search num of sets) - summary = summary.substr(0, summary.length - 1); - summary = summary.substr(summary.lastIndexOf("\n") + 1); - // we don't know any about locale then taking only Digit-exising:s - changed = ~/(\d)/.match(summary); - if(changed) - // print new pulled changesets: - cli.print(summary); - - - if(diff.code + status.code + diff.out.length + status.out.length != 0) - { - cli.print(diff.out); - switch cli.ask("Reset changes to " + libName + " " + name + " repo so we can update to latest version?") - { - case Answer.Yes: - Sys.command(executable, ["update", "--clean"]); - case Answer.No: - changed = false; - cli.print(name + " repo left untouched"); - } - } - else if(changed) - Sys.command(executable, ["update"]); - - return changed; - } - - override public function clone(libPath:String, url:String, ?branch:String, ?version:String, ?settings:Settings):Void - { - var vcsArgs = ["clone", url, libPath]; - - if(branch != null) - { - vcsArgs.push("--branch"); - vcsArgs.push(branch); - } - - if(version != null) - { - vcsArgs.push("--rev"); - vcsArgs.push(version); - } - - if(Sys.command(executable, vcsArgs) != 0) - throw VcsError.CantCloneRepo(this, url/*, ret.out*/); - } -} \ No newline at end of file diff --git a/extra/haxelib_src/src/tools/haxelib/haxelib.css b/extra/haxelib_src/src/tools/haxelib/haxelib.css deleted file mode 100644 index 9902c093..00000000 --- a/extra/haxelib_src/src/tools/haxelib/haxelib.css +++ /dev/null @@ -1,216 +0,0 @@ - -/* structure */ - -body { - margin : 0; - padding : 0; - text-align: center; - font-family : "trebuchet ms",sans-serif; - font-size : 10.5pt; - background : #FFFFFF url("http://haxe.org/img/haxe/bg_main.gif") repeat-x; -} -.legacy-notice { - border : 1px solid #AAA; - padding: 10px; - margin: 10px; -} -.page { - margin: 10px auto 10px auto; - padding : 5px; - width : 750px; - background-color : #FFFFFF; - border : 1px solid #AAA; - -moz-border-radius : 10px; -} - -.menu { - text-align : left; - float : left; - width : 150px; -} - -.content { - text-align : left; - float : left; - width : 600px; -} - -.clear { - clear : both; -} - -/* style */ - -a, a:visited { - color : #C35700; - text-decoration : none; -} - -a:hover { - text-decoration : underline; -} - -h1 { - text-align : center; - margin-top : 20px; -} - -h1 a, h1 a:hover, h1 a:visited { - color : #C35700; - text-decoration : none; -} - -.content p { - text-align : justify; - margin : 0px; - padding : 0px 10px 0px 10px; -} - -.menu ul { - list-style : none; - margin : 5px; - padding : 0px; -} - -.versions .date, .versions .project, .versions .name { - display : inline; -} - -.versions ul, .projects ul { - list-style : circle; - margin : 25px; - padding : 0px; -} - -.date { - color : #555; - font-size : 12px; -} - -.versions .name { - font-weight : bold; -} - -.versions .download { - float : right; - margin-top : -22px; - margin-right : 30px; -} - -.download { - padding : 2px 4px 2px 4px; - background-color : #eee; - display : inline; -} - -.download a { - color : #555; - font-size : 12px; - text-decoration : none; -} - -.download a:visited { - color : #555; -} - -.versions .comments { - margin-right : 40px; - margin-left : 10px; - margin-bottom : 5px; - text-align : justify; -} - -.pinfos .description { - padding : 10px; -} - -.pinfos .download { - margin : 200px; -} - -.label { - color : #555; - width : 80px; - float : left; -} - -.tags a { - margin-right : 5px; -} - -form { - margin-left : 5px; - margin-top : 5px; -} - -input { - width : 80px; -} - -/* documentation */ - -.api .title { - font-size: 35; - font-weight: bold; - text-align: center; - background-color : #FFD473; - color : white; -} - -.api ul.entry { - list-style-type: disc; - margin-left : 30px; - padding-left : 0px; -} - -.api .package_content { - display : none; -} - -.api a { - text-decoration : none; -} - -.api a:hover { - text-decoration : underline; -} - -.api a.package { - color : black; -} - -.api .index { -} - -.api .kwd { - color : #09598A; - font-weight : bold; -} - -.api .classname { - font-size : 30; - font-weight : bold; -} - -.api .classdoc { - border : 1px dashed #666; - margin-left : 20px; - margin-right : 20px; - padding : 5 5 5 5; -} - -.api .importmod, .api .extends, .api .implements, .api .typedef, .api .platforms { - color : #777; -} - -.api dd { - margin-top : 10px; - font-size : 12pt; - color : #444; -} - -.api dt { - margin-left : 20px; - margin-bottom : 5px; - text-align : left; -} diff --git a/extra/haxelib_src/src/tools/haxelib/tmpl/documentation.mtt b/extra/haxelib_src/src/tools/haxelib/tmpl/documentation.mtt deleted file mode 100644 index 39f77984..00000000 --- a/extra/haxelib_src/src/tools/haxelib/tmpl/documentation.mtt +++ /dev/null @@ -1,14 +0,0 @@ -

::(p.name):: ::(v.name):: Documentation

- - - -
-::content:: -
\ No newline at end of file diff --git a/extra/haxelib_src/src/tools/haxelib/tmpl/error.mtt b/extra/haxelib_src/src/tools/haxelib/tmpl/error.mtt deleted file mode 100644 index b5df2f36..00000000 --- a/extra/haxelib_src/src/tools/haxelib/tmpl/error.mtt +++ /dev/null @@ -1,5 +0,0 @@ -
\ No newline at end of file diff --git a/extra/haxelib_src/src/tools/haxelib/tmpl/index.mtt b/extra/haxelib_src/src/tools/haxelib/tmpl/index.mtt deleted file mode 100644 index c6232308..00000000 --- a/extra/haxelib_src/src/tools/haxelib/tmpl/index.mtt +++ /dev/null @@ -1,24 +0,0 @@ -

Welcome

- -

- This website is listing all the libraries available through the haxelib Haxe package manager. - Please visit the haxelib page on Haxe website to learn more about haxelib. -

- -

Latest releases

- -
- -
- -

Browse Projects | RSS Feed

\ No newline at end of file diff --git a/extra/haxelib_src/src/tools/haxelib/tmpl/layout.mtt b/extra/haxelib_src/src/tools/haxelib/tmpl/layout.mtt deleted file mode 100644 index f530edda..00000000 --- a/extra/haxelib_src/src/tools/haxelib/tmpl/layout.mtt +++ /dev/null @@ -1,38 +0,0 @@ - - - -haxelib (::site::) - - - - - - -

haxelib (::site::)

- -
- - - - -
- ::content:: -
- -
- -
- - - diff --git a/extra/haxelib_src/src/tools/haxelib/tmpl/list.mtt b/extra/haxelib_src/src/tools/haxelib/tmpl/list.mtt deleted file mode 100644 index bdc7188f..00000000 --- a/extra/haxelib_src/src/tools/haxelib/tmpl/list.mtt +++ /dev/null @@ -1,12 +0,0 @@ -

::if search::Search Results for '::search::'::else::All Projects::end:::

- -
-
    -::foreach projects:: -
  • - ::name:: -
    ::description::
    -
  • -::end:: -
-
\ No newline at end of file diff --git a/extra/haxelib_src/src/tools/haxelib/tmpl/project.mtt b/extra/haxelib_src/src/tools/haxelib/tmpl/project.mtt deleted file mode 100644 index 71a230c7..00000000 --- a/extra/haxelib_src/src/tools/haxelib/tmpl/project.mtt +++ /dev/null @@ -1,27 +0,0 @@ -

::(p.name)::

- -
-
::(p.description)::
- ::if (tags.length != 0)::
Tags
::foreach tags::::tag::::end::
::end:: - -
Version
::(version.name)::
- -
License
::(p.license)::
- ::if (version.documentation)::::end:: - -
- -

History

- -
-
    - ::foreach versions:: -
  • -
    ::date::
    -
    ::name::
    - -
    ::comments::
    -
  • - ::end:: -
-
\ No newline at end of file diff --git a/extra/haxelib_src/src/tools/haxelib/tmpl/tag.mtt b/extra/haxelib_src/src/tools/haxelib/tmpl/tag.mtt deleted file mode 100644 index 476c0bd2..00000000 --- a/extra/haxelib_src/src/tools/haxelib/tmpl/tag.mtt +++ /dev/null @@ -1,16 +0,0 @@ -

Tag ::tag::

- -

- Here's the list of projects using this tag : -

- -
-
    -::foreach tprojects:: -
  • - ::name:: -
    ::description::
    -
  • -::end:: -
-
\ No newline at end of file diff --git a/extra/haxelib_src/src/tools/haxelib/tmpl/user.mtt b/extra/haxelib_src/src/tools/haxelib/tmpl/user.mtt deleted file mode 100644 index fe0cc640..00000000 --- a/extra/haxelib_src/src/tools/haxelib/tmpl/user.mtt +++ /dev/null @@ -1,16 +0,0 @@ -

::(u.name)::

- -
-
Name
::(u.fullname)::
- -
- -

Projects

- -
-
    -::foreach uprojects:: -
  • ::name::
  • -::end:: -
-
\ No newline at end of file diff --git a/extra/haxelib_src/src/tools/legacyhaxelib/haxelib.sh b/extra/haxelib_src/src/tools/legacyhaxelib/haxelib.sh deleted file mode 100644 index 4a0621d4..00000000 --- a/extra/haxelib_src/src/tools/legacyhaxelib/haxelib.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -exec haxe --run tools.legacyhaxelib.Main "$@" diff --git a/extra/haxelib_src/src/tools/legacyhaxelib/site.hxml b/extra/haxelib_src/src/tools/legacyhaxelib/site.hxml deleted file mode 100644 index e7b575f4..00000000 --- a/extra/haxelib_src/src/tools/legacyhaxelib/site.hxml +++ /dev/null @@ -1,5 +0,0 @@ --neko index.n --main tools.legacyhaxelib.Site --dce no --D haxelib-site --lib hx2compat \ No newline at end of file diff --git a/extra/haxelib_src/src/website/Server.hx b/extra/haxelib_src/src/website/Server.hx new file mode 100644 index 00000000..b02c9a31 --- /dev/null +++ b/extra/haxelib_src/src/website/Server.hx @@ -0,0 +1,88 @@ +package website; + +import website.controller.*; +import ufront.mailer.*; +import ufront.MVC; +import sys.*; +import sys.db.*; +import sys.io.*; +import haxe.io.*; + +import haxelib.server.*; +import haxelib.server.Paths.*; + +class Server { + static var ufApp:UfrontApplication; + + static function main() { + // this is a temporary fix from https://github.com/dpeek/haxe-markdown/pull/26 + @:privateAccess markdown.BlockParser.TableSyntax.TABLE_PATTERN = new EReg('^(.+?:?\\|:?)+(.+)$', ''); + + ufApp = new UfrontApplication({ + indexController: HomeController, + templatingEngines: [TemplatingEngines.erazor], + defaultLayout: "layout.html", + logFile: "logs/haxelib.log", + sessionImplementation: VoidSession, + authImplementation: NobodyAuthHandler, + contentDirectory: "../uf-content/", + requestMiddleware: [], + responseMiddleware: [], + }); + ufApp.injector.map( String, "documentationPath" ).toValue( neko.Web.getCwd()+"documentation-files/" ); + ufApp.injector.map( UFCacheConnectionSync ).toClass( DBCacheConnection ); + ufApp.injector.map( UFCacheConnection ).toClass( DBCacheConnection ); + + // var cacheMiddleware = new RequestCacheMiddleware(); + // ufApp.addRequestMiddleware( cacheMiddleware, true ).addResponseMiddleware( cacheMiddleware, true ); + + // If we're on neko, and using the module cache, next time jump straight to the main request. + #if (neko && !debug) + neko.Web.cacheModule(run); + #end + + // Execute the main request. + run(); + } + + static function run() { + var wasUpload = handleHaxelibUpload(); + if ( wasUpload==false ) { + SiteDb.init(); + + var cacheAPI = new ufront.cache.DBCache.DBCacheApi(); + cacheAPI.setup(); + + ufApp.executeRequest(); + SiteDb.cleanup(); + } + } + + static function handleHaxelibUpload():Bool { + var tmpFile = null; + var tmpFileName = null; + var tmpFilePath = null; + var sid = null; + var bytes = 0; + neko.Web.parseMultipart(function(p,fileName) { + if( p == "file" ) { + sid = Std.parseInt(fileName); + tmpFilePath = Path.join([TMP_DIR, tmpFileName = sid+".tmp"]); + FileSystem.createDirectory(Path.directory(tmpFilePath)); + tmpFile = sys.io.File.write(tmpFilePath, true); + } else + throw p+" not accepted"; + },function(data,pos,len) { + bytes += len; + tmpFile.writeFullBytes(data,pos,len); + }); + if( tmpFile != null ) { + tmpFile.close(); + FileStorage.instance + .importFile(tmpFilePath, Path.join([TMP_DIR_NAME, tmpFileName]), true); + neko.Lib.print("File #"+sid+" accepted : "+bytes+" bytes written"); + return true; + } + return false; + } +} diff --git a/extra/haxelib_src/src/website/Tasks.hx b/extra/haxelib_src/src/website/Tasks.hx new file mode 100644 index 00000000..2cb7fed7 --- /dev/null +++ b/extra/haxelib_src/src/website/Tasks.hx @@ -0,0 +1,58 @@ +package website; + +import haxelib.server.SiteDb; +import mcli.Dispatch; +import ufront.api.UFApi; +import ufront.tasks.UFTaskSet; +import ufront.auth.*; +import ufront.auth.tasks.EasyAuthTasks; +import ufront.auth.EasyAuth; +import ufront.web.session.*; +import website.tasks.*; +using ufront.core.InjectionTools; + +class Tasks extends UFTaskSet +{ + /** + The CLI runner. + **/ + static function main() { + // Only access the command line runner from the command line, not the web. + if ( !neko.Web.isModNeko ) { + + // This is an auth system that lets you do anything regardless of permissions, handy for CLI tools + var auth = new EasyAuthAdminMode(); + + var tasks = new Tasks(); + tasks.injector.map( UFHttpSession ).toValue( new VoidSession() ); + tasks.injector.map( UFAuthHandler ).toValue( auth ); + tasks.injector.map( EasyAuth ).toValue( auth ); + tasks.injector.map( String, "contentDirectory" ).toValue( "../uf-content" ); + tasks.useCLILogging( "log/twl-webapp.log" ); + + // Inject our APIs + for ( api in CompileTime.getAllClasses(UFApi) ) + tasks.injector.mapRuntimeTypeOf( api ); + + SiteDb.init(); + tasks.execute( Sys.args() ); + SiteDb.cleanup(); + } + } + + /** + Easyauth task set + @alias a + **/ + public function auth( d:Dispatch ) { + executeSubTasks( d, EasyAuthTasks ); + } + + /** + DBCache task set + @alias c + **/ + public function cache( d:Dispatch ) { + executeSubTasks( d, HaxelibCacheTasks ); + } +} diff --git a/extra/haxelib_src/src/website/api/DocumentationApi.hx b/extra/haxelib_src/src/website/api/DocumentationApi.hx new file mode 100644 index 00000000..862b359a --- /dev/null +++ b/extra/haxelib_src/src/website/api/DocumentationApi.hx @@ -0,0 +1,22 @@ +package website.api; + +import sys.FileSystem; +import ufront.web.HttpError; +import ufront.api.UFApi; +import sys.io.File; +using tink.CoreApi; + +class DocumentationApi extends UFApi { + @inject("documentationPath") public var docPath:String; + + public function getDocumentationHTML( page:String ):Outcome { + if ( page==null ) + page = "index"; + var markdownFile = docPath+page+'.md'; + var markdown = + try File.getContent( markdownFile ) + catch(e:Dynamic) return Failure( new Error(404,'Documentation page $page not found: $e') ); + var html = Markdown.markdownToHtml( markdown ); + return Success( html ); + } +} \ No newline at end of file diff --git a/extra/haxelib_src/src/website/api/ProjectApi.hx b/extra/haxelib_src/src/website/api/ProjectApi.hx new file mode 100644 index 00000000..095e78bc --- /dev/null +++ b/extra/haxelib_src/src/website/api/ProjectApi.hx @@ -0,0 +1,237 @@ +package website.api; + +import haxe.io.Bytes; +import haxe.zip.Entry; +import haxe.zip.Reader; +import haxelib.Data; +import haxelib.server.FileStorage; +import haxelib.server.Repo; +import haxelib.server.Paths.*; +import ufront.api.UFApi; +import ufront.cache.UFCache; +import ufront.web.HttpError; +import website.model.SiteDb; +import haxe.ds.Option; +import sys.*; +import sys.io.*; +using tink.CoreApi; +using StringTools; +using haxe.io.Path; + +class ProjectApi extends UFApi { + + public static var cacheNames = { + info: 'haxelib_zip_cache_info', + dirListing: 'haxelib_zip_cache_dir_list', + fileBytes: 'haxelib_zip_cache_file_content' + }; + + // TODO: inject the repo directory instead. + @inject("scriptDirectory") public var scriptDir:String; + @inject public var cacheCnx:UFCacheConnectionSync; + + /** Extensions that should be loaded as a text file. **/ + public static var textExtensions:Array = ["md","txt","hx","hxml","json","xml","htaccess"]; + public static var imgExtensions:Array = ["jpg","jpeg","gif","png"]; + + /** + Load the ProjectInfos for the given project. + This contains basic metadata and is loaded from the database (though it is set via a haxelib.json file during project upload). + **/ + public function projectInfo( projectName:String ):Outcome { + try { + var info = new Repo().infos(projectName); + return Success( info ); + } + catch ( e:Dynamic ) { + var error = + if ( Std.is(e,String) && StringTools.startsWith(e,"No such Project") ) HttpError.pageNotFound(); + else Error.withData('Failed to get info for project $projectName',e); + return Failure( error ); + } + } + + /** + Given a path, load either the file or the directory listing, and take a guess at the content type. + + This will use `this.cacheCnx` to cache results, to prevent us having to load the zip file each time. + **/ + public function getInfoForPath( projectName:String, version:String, path:String ):Outcome { + try { + var pathWithSlash = path.addTrailingSlash(); + var cache = cacheCnx.getNamespaceSync( cacheNames.info ); + var fileInfo = cache.getOrSetSync( '$projectName:$version:$pathWithSlash', function() { + var extension = path.extension(); + var zip = getZipEntries(projectName,version); + var fileInfo = null; + for ( entry in zip ) { + if ( entry.fileName==path ) { + // Exact match! It's a file, not a directory. Now, check the type and load it. + fileInfo = + if ( textExtensions.indexOf(extension)>-1 ) + Text( Reader.unzip(entry).toString(), extension ); + else if ( imgExtensions.indexOf(extension)>-1 ) + Image( Reader.unzip(entry), extension ); + else + Binary( entry.fileSize ); + break; + } + else if ( entry.fileName==pathWithSlash || pathWithSlash=="/" ) { + // It's a directory, so get the listing of files and sub directories. + var dirListing = getDirListing( zip, path ); + fileInfo = Directory( dirListing.dirs, dirListing.files ); + break; + } + } + if (fileInfo == null) { + // If it's still null, handle one more case: there's no zip entry for the requested directory, + // but there are entries for files in it. Get listing of that directory and if it's not empty, + // return it. + var dirListing = getDirListing( zip, path ); + if (dirListing.dirs.length > 0 || dirListing.files.length > 0) + fileInfo = Directory( dirListing.dirs, dirListing.files ); + } + return fileInfo; + }).sure(); + return + if ( fileInfo!=null ) Success( fileInfo ); + else Failure( HttpError.pageNotFound() ); + } + catch ( e:Dynamic ) return Failure( Error.withData('Failed to get file information for $path in $projectName ($version)',e) ); + } + + /** + Fetch a list of files in a directory in the zip file. + + This will use `this.cacheCnx` to cache results, to prevent us having to load the zip file each time. + + Returns a Success with two arrays, containing a) sub directories, and b) files. Names are relative to the dirPath, not absolute to the zip. + Returns a Failure with an error if one is encountered. + **/ + public function getDirListingFromZip( projectName:String, version:String, dirPath:String ):Outcome<{ dirs:Array, files:Array },Error> { + try { + var cache = cacheCnx.getNamespaceSync( cacheNames.dirListing ); + var listing = cache.getOrSetSync( '$projectName:$version:$dirPath', function() { + var zip = getZipEntries(projectName,version); + return getDirListing(zip,dirPath); + }).sure(); + return Success( listing ); + } + catch ( e:Dynamic ) return Failure( Error.withData('Failed to read directory $dirPath from $projectName ($version) zip',e) ); + } + + /** + Read text content from a file in a project's zip file. + Returns Success(Some(contents)) if the file was read successfully. + Returns Success(None) if the file was not found in the zip file. + Returns Failure if an error was encountered. + **/ + public function readContentFromZip( projectName:String, version:String, filename:String, ?caseSensitive:Bool=true ):Outcome,Error> { + // This is the same as readBytesFromZip, but we transform the result to turn Bytes into a String. + return readBytesFromZip( projectName, version, filename, caseSensitive ).map(function (outcome) return switch outcome { + case Some(bytes): Some( bytes.toString() ); + case None: None; + }); + } + + /** + Read the raw bytes from a file in a project's zip file. + Returns Success(Some(bytes)) if the file was read successfully. + Returns Success(None) if the file was not found in the zip file. + Returns Failure if an error was encountered. + **/ + public function readBytesFromZip( projectName:String, version:String, filename:String, ?caseSensitive:Bool=true ):Outcome,Error> { + try { + var cache = cacheCnx.getNamespaceSync( cacheNames.fileBytes ); + var bytes = cache.getOrSetSync( '$projectName:$version:$filename:$caseSensitive', function() { + var zip = getZipEntries( projectName, version ); + return getBytesFromFile( zip, filename, caseSensitive ); + }).sure(); + return + if ( bytes!=null ) Success( Some(bytes) ); + else Success( None ); + } + catch ( e:Dynamic ) return Failure( Error.withData('Failed to read $filename from $projectName ($version) zip: $e',e) ); + } + + /** + Get the path to the zip file (relative to the script directory). + **/ + public function getZipFilePath( project:String, version:String ):String { + return Path.join([REP_DIR_NAME, Data.fileName(project, version)]); + } + + // + // Private API + // + + /** Get a list of entries in a zip file. **/ + function getZipEntries( projectName:String, version:String ):List { + return FileStorage.instance.readFile( + getZipFilePath( projectName, version ), + function(path) { + var file = File.read(path, true); + var zip = try { + haxe.zip.Reader.readZip(file); + } catch( e : Dynamic ) { + file.close(); + neko.Lib.rethrow(e); + }; + file.close(); + return zip; + } + ); + } + + /** Attempt to extract the bytes of a file within a zip file. Will return null if the file was not found. **/ + function getBytesFromFile( zip:List, filename:String, caseSensitive:Bool ):Null { + var file = null; + for( f in zip ) { + var sameName = f.fileName==filename || (caseSensitive==false && f.fileName.toLowerCase()==filename.toLowerCase()); + if ( sameName ) + return Reader.unzip( f ); + } + return null; + } + + /** Get a directory listing from the zip entries. If the directory doesn't exist the file listings will just be empty. **/ + function getDirListing( zip:List, dirPath:String ):{ dirs:Array, files:Array } { + dirPath = dirPath.addTrailingSlash(); + var subdirectories = []; + var files = []; + for( f in zip ) { + var fileInsideDirectory = (f.fileName.startsWith(dirPath) && f.fileName.length>dirPath.length) || dirPath=="/"; + if ( fileInsideDirectory ) { + var remainingName = + if ( dirPath=="/" ) f.fileName; + else f.fileName.substr( dirPath.length ); + if ( remainingName.indexOf('/')==-1 ) { + // This is a file in this directory. Add it if we don't have it already. + if ( files.indexOf(remainingName)==-1 ) + files.push( remainingName ); + } + else { + // This is a file in a subdirectory. Add it if we don't have it already. + var subdirName = remainingName.substr( 0, remainingName.indexOf('/') ); + if ( subdirectories.indexOf(subdirName)==-1 ) + subdirectories.push( subdirName ); + } + } + } + return { dirs:subdirectories, files:files }; + } +} + +/** + A description of a file found in a Haxelib zip file. +**/ +enum FileInformation { + /** A text file, with it's String content and extension. **/ + Text( content:String, extension:String ); + /** A text file, with it's Bytes content and extension. **/ + Image( content:Bytes, extension:String ); + /** A binary file that we can't display, together with it's size. **/ + Binary( size:Int ); + /** A directory listing, with separate arrays for subdirs and files. **/ + Directory( subdirs:Array, files:Array ); +} diff --git a/extra/haxelib_src/src/website/api/ProjectListApi.hx b/extra/haxelib_src/src/website/api/ProjectListApi.hx new file mode 100644 index 00000000..a1d1ed6f --- /dev/null +++ b/extra/haxelib_src/src/website/api/ProjectListApi.hx @@ -0,0 +1,73 @@ +package website.api; + +import ufront.api.UFApi; +import website.model.SiteDb; +using tink.CoreApi; +using Lambda; +using CleverSort; + +class ProjectListApi extends UFApi { + public function all():Outcome,Error> { + try { + var all = Project.manager.search(1 == 1,{ orderBy: [-downloads,name] }); + return Success( all.array() ); + } + catch ( e:Dynamic ) return Failure( Error.withData("Failed to get list of all projects",e) ); + } + + public function byUser( username:String ):Outcome,Error> { + try { + var user = User.manager.select( $name==username ); + if ( user==null ) + return Failure( new Error(404,'User $username not found') ); + + var joins = Developer.manager.search( $user==user.id ); + // TODO: It would be better to do a single query on all IDs, rather than a single query for each project. + // Unfortunately, the current set up of the "Developer" model doesn't give us access to the ID. + var theirProjects = [ for (j in joins) j.projectObj ]; + return Success( theirProjects ); + } + catch ( e:Dynamic ) return Failure( Error.withData('Failed to get list of projects belong to $username',e) ); + } + + public function getTagList( num:Int ):Outcome,Error> { + try { + // TODO, see if we can return more useful info, maybe including the most popular projects in this tag etc. + return Success( Tag.topTags(num).array() ); + } + catch ( e:Dynamic ) return Failure( Error.withData('Failed to get list of tags',e) ); + } + + public function byTag( tag:String ):Outcome,Error> { + try { + var tagJoins = Tag.manager.search( $tag==tag ); + // TODO: It would be better to do a single query on all IDs, rather than a single query for each project. + // Unfortunately, the current set up of the "Tag" model doesn't give us access to the ID. + var projects = [for (t in tagJoins) t.projectObj]; + projects.cleverSort( -_.downloads ); + return Success( projects ); + } + catch ( e:Dynamic ) return Failure( Error.withData('Failed to get list of projects with tag $tag',e) ); + } + + public function search( word:String ):Outcome,Error> { + try { + // TODO: We should match other things too. Tags & users especially. Also release notes, docs, readmes. + word = '%$word%'; + var searchResults = Project.manager.search($name.like(word) || $description.like(word)); + return Success( searchResults.array() ); + } + catch ( e:Dynamic ) return Failure( Error.withData('Failed to search for projects with "$word" in the name or description',e) ); + } + + public function latest( n:Int ):Outcome,Error> { + try { + var latestVersions = Version.latest( n ); + var l = new List(); + // TODO: again, we are performing many queries here. Need to access project ID somehow. + var versionsAndProjects = [for (v in latestVersions) { v:v, p:v.projectObj }]; + return Success( versionsAndProjects ); + } + catch ( e:Dynamic ) return Failure( Error.withData('Failed to get most recent $n projects',e) ); + } +} \ No newline at end of file diff --git a/extra/haxelib_src/src/website/api/UserApi.hx b/extra/haxelib_src/src/website/api/UserApi.hx new file mode 100644 index 00000000..f156d510 --- /dev/null +++ b/extra/haxelib_src/src/website/api/UserApi.hx @@ -0,0 +1,69 @@ +package website.api; + +import haxe.crypto.Md5; +import website.model.SiteDb; +import ufront.web.HttpError; +import ufront.api.UFApi; +import haxe.Utf8; +using tink.CoreApi; +using CleverSort; +using Lambda; + +class UserApi extends UFApi { + @inject("documentationPath") public var docPath:String; + + /** + Given a username, return that user object and a + **/ + public function getUserProfile( username:String ):Outcome>,Error> { + try { + var user = User.manager.select( $name==username ); + if ( user==null ) + return Failure( HttpError.pageNotFound() ); + + var projectJoins = Developer.manager.search( $user==user.id ); + var projects = [for (j in projectJoins) j.projectObj]; + projects.cleverSort( -_.downloads ); + + return Success( new Pair(user,projects) ); + } + catch ( e:Dynamic ) return Failure( Error.withData('Failed to fetch user profile for $username', e) ); + } + + /** + **/ + public function getUserList():Outcome, totalDownloads:Int }>,Error> { + try { + // Fetch all the objects we are going to be using: + var allUsers = User.manager.all(); + var allProjects = Project.manager.all(); + var joins = Developer.manager.all(); + + // Collate them into a map, tally the downloads + var map = new Map(); + for ( u in allUsers ) { + var hash = Md5.encode( u.email ); + var obj = { user:u, emailHash:hash, projects:[], totalDownloads:0 }; + map.set( u.id, obj ); + } + for ( j in joins ) { + var obj = map[j.userObj.id]; + var project = j.projectObj; + if ( project==null ) throw 'How is it null? ${j}'; + obj.projects.push( project ); + obj.totalDownloads += project.downloads; + } + + // Sort the projects on each user, and then the users + var arr = []; + for ( obj in map ) { + obj.projects.cleverSort( -_.downloads, _.name ); + arr.push( obj ); + } + arr.cleverSort( -_.totalDownloads, _.user.fullname ); + + return Success( arr ); + } + catch ( e:Dynamic ) return Failure( Error.withData('Failed to get list of all users',e) ); + } +} diff --git a/extra/haxelib_src/src/website/controller/DocumentationController.hx b/extra/haxelib_src/src/website/controller/DocumentationController.hx new file mode 100644 index 00000000..3017caf2 --- /dev/null +++ b/extra/haxelib_src/src/website/controller/DocumentationController.hx @@ -0,0 +1,36 @@ +package website.controller; + +import ufront.web.Controller; +import ufront.web.result.*; +import website.api.DocumentationApi; +import ufront.core.OrderedStringMap; +using tink.CoreApi; + +@cacheRequest +class DocumentationController extends Controller { + + @inject public var api:DocumentationApi; + + @:route("/$page") + public function documentationPage( ?page:String ) { + var html = api.getDocumentationHTML( page ).sure(); + var documentationPages = getDocumentationPages(); + var docTitle = + if ( page==null ) documentationPages.get('/documentation/'); + else documentationPages.get('/documentation/$page/'); + return new ViewResult({ + title: '$docTitle - Haxelib Documentation', + content: html, + }); + } + + public static function getDocumentationPages():OrderedStringMap { + var pages = new OrderedStringMap(); + pages.set( "/documentation/", "Getting Started" ); + pages.set( "/documentation/using-haxelib/", "Using Haxelib" ); + pages.set( "/documentation/creating-a-haxelib-package/", "Creating a Haxelib" ); + // pages.set( "/documentation/faq/", "FAQ" ); + // pages.set( "/documentation/api/", "API" ); + return pages; + } +} diff --git a/extra/haxelib_src/src/website/controller/HomeController.hx b/extra/haxelib_src/src/website/controller/HomeController.hx new file mode 100644 index 00000000..19abf236 --- /dev/null +++ b/extra/haxelib_src/src/website/controller/HomeController.hx @@ -0,0 +1,193 @@ +package website.controller; + +import ufront.MVC; +import ufront.ufadmin.controller.*; +import website.api.*; +import website.model.SiteDb; +import haxelib.server.FileStorage; +import haxe.io.*; +using StringTools; +using tink.CoreApi; +using CleverSort; + +class HomeController extends Controller { + + @inject public var projectApi:ProjectApi; + @inject public var projectListApi:ProjectListApi; + + // Perform init() after dependency injection has occured. + @inject public function init( ctx:HttpContext ) { + // All MVC actions come through HomeController (our index controller) first, so this is a good place to set global template variables. + var r = ctx.request; + var url = 'http://'+r.hostName+r.uri; + if ( r.queryString!="" ) { + url += '?'+r.queryString; + } + ViewResult.globalValues.set( "useWrapper", true ); + ViewResult.globalValues.set( "pageUrl", url ); + ViewResult.globalValues.set( "currentPage", r.uri ); + ViewResult.globalValues.set( "todaysDate", Date.now() ); + ViewResult.globalValues.set( "documentationPages", DocumentationController.getDocumentationPages() ); + ViewResult.globalValues.set( "description", "Haxe is an open source toolkit based on a modern, high level, strictly typed programming language." ); + ViewResult.globalValues.set( "searchTerm", ctx.session.get('searchTerm') ); + } + + @:route("/") + public function homepage() { + var latestProjects = projectListApi.latest( 10 ).sure(); + var tags = projectListApi.getTagList( 10 ).sure(); + return new ViewResult({ + title: "Haxelib - the Haxe package manager", + description: "Haxelib is a tool that enables sharing libraries and code in the Haxe ecosystem.", + pageUrl: context.request.uri, + latestProjects: latestProjects, + tags: tags, + exampleCode: CompileTime.readFile( "website/homepage-example.txt" ), + useWrapper: false, + }); + } + + @:route("/p/*") + public var projectController:ProjectController; + + @:route("/u/*") + public var userController:UserController; + + @:route("/rss/") + public var rssController:RSSController; + + @:route("/documentation/*") + public var documentationController:DocumentationController; + + /** + `/files` is backed by a `FileStorage`. + In production, it should be routed by httpd to S3 using mod_proxy, thus + this function should never be called. + */ + @:route("/files/3.0/$fileName") + public function downloadFile( fileName:String ) { + return FileStorage.instance.readFile( + 'files/3.0/$fileName', + function(path) { + var r = new FilePathResult(path); + r.setContentTypeByFilename(Path.withoutDirectory(path)); + return r; + } + ); + } + + @cacheRequest + @:route("/t/") + public function tagList():ViewResult { + var tagList = projectListApi.getTagList( 50 ).sure(); + + // Build a tag cloud. + var least = null, + most = null, + minSize = 10, + maxSize = 140; + for (t in tagList) { + if ( least==null || t.countmost ) + most = t.count; + } + function fontSizeForCount( count:Int ) { + var countRange = most - least; + var sizeRange = maxSize-minSize; + var pos = (count - least) / countRange; + return minSize + pos*sizeRange; + } + var tagCloud = [for (t in tagList) { tag:t.tag, size:fontSizeForCount(t.count) }]; + tagCloud.cleverSort( _.tag ); + + return new ViewResult({ + title: 'Haxelib Tags', + description: 'The 50 most popular tags for projects on Haxelib, sorted by the number of projects', + tags: tagList, + tagCloud: tagCloud, + }); + } + + // TODO: get ufront-mvc to support `/t/$tagName` and `/t/$tagName.json` as different routes. + @cacheRequest + @:route("/t/$tagName") + public function tag( tagName:String ):ActionResult { + if ( tagName.endsWith(".json") ) { + return tagJson( tagName.substr(0,tagName.length-5) ); + } + else { + + var list = prepareProjectList( projectListApi.byTag( tagName ).sure() ); + return new ViewResult({ + title: 'Tag: $tagName', + icon: 'fa-tag', + description: 'A list of all projects on Haxelib with the tag "$tagName"', + projects: list, + }, "projectList.html"); + } + } + + @cacheRequest + @:route("/all") + public function all() { + var list = prepareProjectList( projectListApi.all().sure() ); + return new ViewResult({ + title: 'All Haxelibs', + icon: 'fa-star', + description: 'A list of every project uploaded on haxelib, sorted by popularity', + projects: list, + }, "projectList.html"); + } + + @:route("/search") + public function search( ?args:{ v:String } ) { + var result = new ViewResult(); + if ( args.v==null || args.v.length==0 ) { + result.setVars({ + title: 'Search Haxelib', + description: 'Search Haxelib project names and descriptions', + searchTerm: "", + projects: null + }); + } + else { + context.session.set( 'searchTerm', args.v ); + var list = prepareProjectList( projectListApi.search( args.v ).sure() ); + result.setVars({ + title: 'Search for "${args.v}"', + description: 'Haxelib projects that match the search word "${args.v}"', + projects: list, + searchTerm: args.v, + }); + } + return result; + } + + static function prepareProjectList( list:Array ):Array<{ name:String, author:String, description:String, version:String, downloads:Int }> { + return [for (p in list) if (p != null && p.ownerObj != null && p.versionObj != null) { + name: p.name, + author: p.ownerObj.name, + description: p.description, + version: p.versionObj.toSemver(), + downloads: p.downloads + }]; + } + + @:route("/search.json") + public function searchJson( args:{ v:String } ) + return new JsonResult( projectListApi.search(args.v).sure() ); + + @cacheRequest + @:route("/all.json") + public function allJson() + return new JsonResult( projectListApi.all().sure() ); + + @:route("/ufadmin/*") + public function ufadmin() { + return executeSubController( UFAdminHomeController ); + } + + public function tagJson( tagName:String ) + return new JsonResult( projectListApi.byTag(tagName).sure() ); +} diff --git a/extra/haxelib_src/src/website/controller/ProjectController.hx b/extra/haxelib_src/src/website/controller/ProjectController.hx new file mode 100644 index 00000000..8f7c7565 --- /dev/null +++ b/extra/haxelib_src/src/website/controller/ProjectController.hx @@ -0,0 +1,185 @@ +package website.controller; + +import haxelib.SemVer; +import ufront.MVC; +import website.api.ProjectApi; +import haxe.ds.Option; +import markdown.AST; +import Markdown; +using tink.CoreApi; +using haxe.io.Path; +using CleverSort; +using Lambda; +using DateTools; + +class ProjectController extends Controller { + + @inject public var projectApi:ProjectApi; + + @:route("/$projectName") + public function project( projectName:String ) { + var info = projectApi.projectInfo( projectName ).sure(); + return version( projectName ); + } + + @:route("/$projectName/versions/") + public function versionList( projectName:String ) { + var info = projectApi.projectInfo( projectName ).sure(); + info.versions.sort(function(v1, v2) return SemVer.compare(v2.name, v1.name)); + return new ViewResult({ + title: 'All versions of $projectName', + description: info.desc, + project: projectName, + allVersions: info.versions, + info: info, + }); + } + + @:route("/$projectName/$semver") + public function version( projectName:String, ?semver:String ) { + var info = projectApi.projectInfo( projectName ).sure(); + if ( semver==null ) + semver = info.curversion; + var currentVersion = info.versions.find( function(v) return v.name==semver ); + if ( currentVersion==null ) + throw HttpError.pageNotFound(); + + var downloadUrl = '/p/$projectName/$semver/download/'; + + var readmeHTML = switch projectApi.readContentFromZip( projectName, semver, "README.md" ) { + case Success(Some(readme)): markdownToHtml(readme, '/p/$projectName/$semver/raw-files/'); + case Success(None): ""; // No README. + case Failure(err): + ufError( err.message ); + ufError( err.toString() ); + ""; + } + + return new ViewResult({ + title: '$projectName ($semver)', + project: projectName, + description: '${currentVersion.comments} - ${info.desc}', + allVersions: info.versions, + version: semver, + versionDate: Date.fromString(currentVersion.date).format('%F'), + info: info, + downloadUrl: downloadUrl, + readme: readmeHTML, + }, "version.html"); + } + + function markdownToHtml(markdown:String, prefix:String) { + // this function is basically a copy of Markdown.markdownToHtml + // default md->html rendering function, but it adds a filter that + // fixes relative URLs in IMG tags + try { + var imgSrcfixer = new MarkdownImgRelativeSrcFixer(prefix); + var document = new Document(); + var lines = ~/(\r\n|\r)/g.replace(markdown, '\n').split("\n"); + document.parseRefLinks(lines); + var blocks = document.parseLines(lines); + for (block in blocks) block.accept(imgSrcfixer); // fix relative image links + return Markdown.renderHtml(blocks); + } catch (e:Dynamic) { + return '
$e
'; + } + } + + @:route("/$projectName/$semver/download/") + public function download( projectName:String, semver:String ) { + var zipFile = projectApi.getZipFilePath( projectName, semver ); + return new RedirectResult( "/" + zipFile, true ); + } + + @cacheRequest + @:route("/$projectName/$semver/doc/$typePath") + public function docs( projectName:String, semver:String, ?typePath:String ) { + return new ViewResult({ + title: 'View project $projectName docs for $typePath', + }); + } + + @cacheRequest + @:route("/$projectName/$semver/files/*") + public function file( projectName:String, semver:String, rest:Array ) { + var filePath = rest.join("/"); + var downloadLink = baseUri+'$projectName/$semver/raw-files/$filePath'; + var info = projectApi.projectInfo( projectName ).sure(); + var data:TemplateData = { + title: 'Viewing $filePath on $projectName:$semver', + project: projectName, + description: info.desc, + info: info, + version: semver, + fileParts: rest, + filePath: filePath, + downloadLink: downloadLink, + type: "download", + }; + + switch projectApi.getInfoForPath( projectName, semver, filePath ).sure() { + case Directory(dirs,files): + data["type"] = "directory"; + data["dirListing"] = dirs; + data["fileListing"] = files; + data["currentDir"] = baseUri+'$projectName/$semver/files/$filePath'.removeTrailingSlashes(); + case Text(str,ext): + if ( ["md","mdown","markdown"].indexOf(ext)>-1 ) { + str = Markdown.markdownToHtml( str ); + data["type"] = "markdown"; + } + else { + data["type"] = "text"; + } + data["fileContent"] = str; + data["extension"] = ext; + data["highlightLanguage"] = ext; + case Image(bytes,ext): + data["filename"] = rest[rest.length-1]; + data["type"] = "img"; + case Binary(size): + data["filename"] = rest[rest.length-1]; + var sizeInKb = Math.round(size/1024*10) / 10; + data["size"] = sizeInKb + "kb"; + } + + var vr = new ViewResult( data ); + vr.helpers["extensionAllowed"] = function(file:String) return ProjectApi.textExtensions.has(file.extension().toLowerCase()); + return vr; + } + + // TODO: write some tests... + @:route("/$projectName/$semver/raw-files/*") + public function downloadFile( projectName:String, semver:String, rest:Array ) { + var filename = rest[ rest.length-1 ]; + var filePath = rest.join("/"); + switch projectApi.readBytesFromZip( projectName, semver, filePath, true ).sure() { + case Some(bytes): + return new BytesResult( bytes, null, filename ); + case None: + throw HttpError.pageNotFound(); + } + } +} + +private class MarkdownImgRelativeSrcFixer implements NodeVisitor { + static var ABSOLUTE_URL_RE = ~/^(https?:\/)?\//; + + var prefix:String; + + public function new(prefix:String) { + this.prefix = prefix; + } + + public function visitElementBefore(element:ElementNode):Bool { + if (element.tag == "img") { + var url = element.attributes["src"]; + if (!ABSOLUTE_URL_RE.match(url)) + element.attributes["src"] = prefix + url; + } + return element.children != null; + } + + public function visitText(text:TextNode):Void {} + public function visitElementAfter(element:ElementNode):Void {} +} diff --git a/extra/haxelib_src/src/website/controller/RSSController.hx b/extra/haxelib_src/src/website/controller/RSSController.hx new file mode 100644 index 00000000..1f6cd8e1 --- /dev/null +++ b/extra/haxelib_src/src/website/controller/RSSController.hx @@ -0,0 +1,86 @@ +package website.controller; + +import haxelib.server.SiteDb; +import ufront.web.Controller; +import ufront.web.result.ContentResult; +import website.api.ProjectListApi; +using StringTools; +using DateTools; +using tink.CoreApi; + +class RSSController extends Controller { + + @inject public var projectListApi:ProjectListApi; + + @:route("/") + public function rss( ?args:{ number:Int } ) { + var number = (args.number!=null) ? args.number : 20; + var releases = projectListApi.latest( number ).sure(); + var rss = buildRss( releases ); + var content = ''+rss.toString(); + return new ContentResult( content, "text/xml" ); + } + + function buildRss( releases:Array<{v:Version, p:Project}> ):Xml { + // Helpers for building the XML + var createChild = function(root:Xml, name:String){ + var c = Xml.createElement( name ); + root.addChild( c ); + return c; + } + var createChildWithContent = function(root:Xml, name:String, content:String){ + var e = Xml.createElement( name ); + var c = Xml.createPCData( if (content != null) content else "" ); + e.addChild( c ); + root.addChild( e ); + return e; + } + var createChildWithCdata = function(root:Xml, name:String, content:String){ + var e = Xml.createElement( name ); + var c = Xml.createCData( if (content != null) content else "" ); + e.addChild( c ); + root.addChild( e ); + return e; + } + + // Set some variables we'll use. + Sys.setTimeLocale( "en_US.UTF8" ); + var hostName = context.request.hostName; + var url = "http://"+hostName; + var num = releases.length; + + // Create the RSS document and headers. + var rss = Xml.createElement( "rss" ); + rss.set( "version", "2.0" ); + rss.set( "xmlns:atom", "http://www.w3.org/2005/Atom" ); + rss.set( "xmlns:dc", "http://purl.org/dc/elements/1.1/" ); + var channel = createChild( rss, "channel" ); + var link = createChild( channel, "atom:link" ); + link.set( "href", 'http://$hostName/rss/' ); + link.set( "rel", "self" ); + link.set( "type", "application/rss+xml" ); + createChildWithContent( channel, "title", 'Latest Haxelib Releases ($hostName)' ); + createChildWithContent( channel, "link", url ); + createChildWithContent( channel, "description", 'The latest $num haxelib releases on $hostName' ); + createChildWithContent( channel, "generator", "haxe" ); + createChildWithContent( channel, "language", "en" ); + + // Create the various RSS entries. + for ( release in releases ) { + var version = release.v; + var project = release.p; + var item = createChild(channel, "item"); + var title = '${project.name} ${version.toSemver()}'; + var description = '

${version.comments.htmlEscape()}


${project.description.htmlEscape()}

'; + createChildWithContent( item, "title", title.htmlEscape() ); + createChildWithContent( item, "link", url+"/p/"+project.name ); + createChildWithContent( item, "guid", url+"/p/"+project.name+"?v="+version.id ); + var date = Date.fromString( version.date ).format( "%a, %e %b %Y %H:%M:%S %z" ); + createChildWithContent( item, "pubDate", date ); + createChildWithContent( item, "dc:creator", project.ownerObj.name ); + createChildWithContent( item, "description", description ); + } + + return rss; + } +} diff --git a/extra/haxelib_src/src/website/controller/UserController.hx b/extra/haxelib_src/src/website/controller/UserController.hx new file mode 100644 index 00000000..566b06d0 --- /dev/null +++ b/extra/haxelib_src/src/website/controller/UserController.hx @@ -0,0 +1,35 @@ +package website.controller; + +import haxe.crypto.Md5; +import ufront.web.Controller; +import ufront.web.result.*; +import website.api.UserApi; +using tink.CoreApi; + +@cacheRequest +class UserController extends Controller { + + @inject public var api:UserApi; + + @:route("/$username") + public function profile( username:String ) { + var data = api.getUserProfile( username ).sure(); + var user = data.a; + return new ViewResult({ + title: '$username (${user.fullname}) on Haxelib', + user: user, + projects: data.b, + emailHash: Md5.encode( user.email ), + }); + } + + @:route("/") + public function list() { + var userList = api.getUserList().sure(); + return new ViewResult({ + title: 'Haxelib Contributors', + list: userList + }); + } + // Future: edit your own profile. Especially password resets. +} diff --git a/extra/haxelib_src/src/website/homepage-example.txt b/extra/haxelib_src/src/website/homepage-example.txt new file mode 100644 index 00000000..57f9d010 --- /dev/null +++ b/extra/haxelib_src/src/website/homepage-example.txt @@ -0,0 +1,12 @@ +haxelib install actuate # Install `actuate` library +haxelib install actuate 1.8.1 # Install a specific version +haxe -lib actuate -main Test -js test.js # Use `actuate` library in your Haxe build + +haxelib list # List all of your installed libraries +haxelib list openfl # List your installed libraries that have "openfl" in the name + +haxelib install actuate.zip # Install a library from a zip file +haxelib install test.hxml # Install all the libs listed in a hxml +haxelib install all # Install all the libs in the hxml files in the current directory + +haxelib submit actuate.zip # Use Haxelib to share your library with others! diff --git a/extra/haxelib_src/src/website/model/SiteDb.hx b/extra/haxelib_src/src/website/model/SiteDb.hx new file mode 100644 index 00000000..0c6eea23 --- /dev/null +++ b/extra/haxelib_src/src/website/model/SiteDb.hx @@ -0,0 +1,7 @@ +package website.model; + +typedef Developer = haxelib.server.SiteDb.Developer; +typedef Project = haxelib.server.SiteDb.Project; +typedef Tag = haxelib.server.SiteDb.Tag; +typedef User = haxelib.server.SiteDb.User; +typedef Version = haxelib.server.SiteDb.Version; \ No newline at end of file diff --git a/extra/haxelib_src/src/website/tasks/HaxelibCacheTasks.hx b/extra/haxelib_src/src/website/tasks/HaxelibCacheTasks.hx new file mode 100644 index 00000000..dc0ee364 --- /dev/null +++ b/extra/haxelib_src/src/website/tasks/HaxelibCacheTasks.hx @@ -0,0 +1,29 @@ +package website.tasks; + +import ufront.tasks.UFTaskSet; +import ufront.cache.DBCache; +import ufront.cache.RequestCacheMiddleware; +import website.api.ProjectApi; + +class HaxelibCacheTasks extends UFTaskSet { + @:skip @inject public var api:DBCacheApi; + + /** Set up the cache table. **/ + public function setup():Void api.setup(); + + /** Clear every cached item. **/ + public function clearAll():Void api.clearAll(); + + /** Clear all cached pages. **/ + public function clearPageCache() api.clearNamespace( RequestCacheMiddleware.namespace ); + + /** Clear a projects zip file cache entries, and also the page caches for that project. **/ + public function clearZipCache( project:String, version:String ) { + var namespaces = ProjectApi.cacheNames; + var prefix = '$project:$version:%'; + api.clearItemLike( namespaces.info, prefix ); + api.clearItemLike( namespaces.dirListing, prefix ); + api.clearItemLike( namespaces.fileBytes, prefix ); + api.clearItemLike( RequestCacheMiddleware.namespace, '/p/$project/%' ); + } +} diff --git a/extra/haxelib_src/test.sh b/extra/haxelib_src/test.sh deleted file mode 100755 index 435329eb..00000000 --- a/extra/haxelib_src/test.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -haxe test.hxml -exec neko bin/test.n "$@" \ No newline at end of file diff --git a/extra/haxelib_src/test/HaxelibTests.hx b/extra/haxelib_src/test/HaxelibTests.hx index a08efa7a..51306f95 100644 --- a/extra/haxelib_src/test/HaxelibTests.hx +++ b/extra/haxelib_src/test/HaxelibTests.hx @@ -1,4 +1,4 @@ -import tools.haxelib.Vcs; +import haxelib.client.Vcs.VcsID; import haxe.unit.TestRunner; import sys.*; import sys.io.*; @@ -18,55 +18,42 @@ class HaxelibTests { Sys.exit(exitCode); } - static function prepare():Void { - runCommand("haxe", ["--run", "Package"]); - - /* - (re)package the dummy libraries - */ - for (item in FileSystem.readDirectory("test/libraries")) { - if ( - !item.startsWith("lib") || - item.endsWith(".zip") - ) - continue; - - var zipUri = 'test/libraries/${item}.zip'; - if (FileSystem.exists(zipUri)) { - FileSystem.deleteFile(zipUri); - } - Sys.setCwd('test/libraries/${item}'); - switch (Sys.systemName()) { - case "Linux", "Mac": - runCommand("zip", ["-r", '../${item}.zip', "."]); - case "Windows": - runCommand("7za", ["a", "-tzip", "-r", '../${item}.zip', "."]); - } - - Sys.setCwd('../../..'); + static function cmdSucceed(cmd:String, ?args:Array):Bool { + var p = try { + new Process(cmd, args); + } catch(e:Dynamic) { + return false; } + var exitCode = p.exitCode(); + p.close(); + return exitCode == 0; } static function main():Void { - prepare(); - var r = new TestRunner(); r.add(new TestSemVer()); r.add(new TestData()); - r.add(new TestRemoveSymlinks("symlinks")); - r.add(new TestRemoveSymlinks("symlinks-broken")); + r.add(new TestRemoveSymlinks()); + r.add(new TestRemoveSymlinksBroken()); - // Testing VCS on two identical repositories: - // Hg: https://bitbucket.org/fzzr/hx.signal - // Git: https://github.com/fzzr-/hx.signal.git + var isCI = Sys.getEnv("CI") != null; - // Hg impl. suports tags & revs. Here "78edb4b" is a first revision "initial import" at that repo: - r.add(new TestVcs(tools.haxelib.Vcs.VcsID.Hg, "Mercurial", "https://bitbucket.org/fzzr/hx.signal", "78edb4b")); - // Git impl. suports only tags. Here "0.9.2" is a first revision too ("initial import"): - r.add(new TestVcs(tools.haxelib.Vcs.VcsID.Git, "Git", "https://github.com/fzzr-/hx.signal.git", "0.9.2")); + if (isCI || cmdSucceed("hg", ["version"])) { + // Hg impl. suports tags & revs. Here "78edb4b" is a first revision "initial import" at that repo: + r.add(new TestHg()); + } else { + Sys.println("hg not found."); + } + if (isCI || cmdSucceed("git", ["version"])) { + // Git impl. suports only tags. Here "0.9.2" is a first revision too ("initial import"): + r.add(new TestGit()); + } else { + Sys.println("git not found."); + } r.add(new TestVcsNotFound()); - r.add(new TestCli()); + + r.add(new TestInstall()); var success = r.run(); Sys.exit(success ? 0 : 1); diff --git a/extra/haxelib_src/test/IntegrationTests.hx b/extra/haxelib_src/test/IntegrationTests.hx new file mode 100644 index 00000000..2fefdb2d --- /dev/null +++ b/extra/haxelib_src/test/IntegrationTests.hx @@ -0,0 +1,174 @@ +import haxe.unit.*; +import haxe.*; +import haxe.io.*; +import sys.*; +import sys.io.*; +import haxelib.*; +using StringTools; +using IntegrationTests; + +class IntegrationTests extends TestBase { + var haxelibBin:String = Path.join([Sys.getCwd(), "run.n"]); + public var server(default, null):String = switch (Sys.getEnv("HAXELIB_SERVER")) { + case null: + "localhost"; + case url: + url; + }; + public var serverPort(default, null) = switch (Sys.getEnv("HAXELIB_SERVER_PORT")) { + case null: + 2000; + case port: + Std.parseInt(port); + }; + public var serverUrl(get, null):String; + function get_serverUrl() return serverUrl != null ? serverUrl : serverUrl = 'http://${server}:${serverPort}/'; + + static var originalRepo(default, never) = { + var p = new Process("haxelib", ["config"]); + var repo = Path.normalize(p.stdout.readLine()); + p.close(); + repo; + }; + static public var repo(default, never) = "repo_integration_tests"; + static public var bar(default, never) = { + user: "Bar", + email: "bar@haxe.org", + fullname: "Bar", + pw: "barpassword", + }; + static public var foo(default, never) = { + user: "Foo", + email: "foo@haxe.org", + fullname: "Foo", + pw: "foopassword", + }; + public var clientVer(get, null):SemVer; + var clientVer_inited = false; + function get_clientVer() { + return if (clientVer_inited) + clientVer; + else { + clientVer = { + var r = haxelib(["version"]).result(); + if (r.code == 0) + SemVer.ofString(r.out.trim()); + else if (r.out.indexOf("3.1.0-rc.4") >= 0) + SemVer.ofString("3.1.0-rc.4"); + else + throw "unknown version"; + }; + clientVer_inited = true; + clientVer; + } + } + + function haxelib(args:Array, ?input:String):Process { + var p = #if system_haxelib + new Process("haxelib", ["-R", serverUrl].concat(args)); + #else + new Process("neko", [haxelibBin, "-R", serverUrl].concat(args)); + #end + + if (input != null) { + p.stdin.writeString(input); + p.stdin.close(); + } + + return p; + } + + function assertSuccess(r:{out:String, err:String, code:Int}, ?pos:haxe.PosInfos):Void { + if (r.code != 0) { + throw r; + } + assertEquals(0, r.code, pos); + } + + function assertNoError(f:Void->Void):Void { + f(); + assertTrue(true); + } + + var dbConfig:Dynamic = Json.parse(File.getContent("www/dbconfig.json")); + var dbCnx:sys.db.Connection; + function resetDB():Void { + var db = dbConfig.database; + dbCnx.request('DROP DATABASE IF EXISTS ${db};'); + dbCnx.request('CREATE DATABASE ${db};'); + + var filesPath = "www/files/3.0"; + for (item in FileSystem.readDirectory(filesPath)) { + if (item.endsWith(".zip")) { + FileSystem.deleteFile(Path.join([filesPath, item])); + } + } + var tmpPath = "tmp"; + for (item in FileSystem.readDirectory(filesPath)) { + if (item.endsWith(".tmp")) { + FileSystem.deleteFile(Path.join([tmpPath, item])); + } + } + } + + override function setup():Void { + super.setup(); + + dbCnx = sys.db.Mysql.connect({ + user: dbConfig.user, + pass: dbConfig.pass, + host: server, + port: dbConfig.port, + database: dbConfig.database, + }); + resetDB(); + + deleteDirectory(repo); + haxelibSetup(repo); + } + + override function tearDown():Void { + haxelibSetup(originalRepo); + deleteDirectory(repo); + + resetDB(); + dbCnx.close(); + + super.tearDown(); + } + + static public function result(p:Process):{out:String, err:String, code:Int} { + var out = p.stdout.readAll().toString(); + var err = p.stderr.readAll().toString(); + var code = p.exitCode(); + p.close(); + return {out:out, err:err, code:code}; + } + + static public function haxelibSetup(path:String):Void { + var p = new Process("haxelib", ["setup", path]); + if (p.exitCode() != 0) + throw "unable to set haxelib repo to " + path; + p.close(); + } + + static function main():Void { + var prevDir = Sys.getCwd(); + + var runner = new TestRunner(); + runner.add(new tests.integration.TestEmpty()); + runner.add(new tests.integration.TestSimple()); + runner.add(new tests.integration.TestUpgrade()); + runner.add(new tests.integration.TestUpdate()); + runner.add(new tests.integration.TestList()); + runner.add(new tests.integration.TestSet()); + runner.add(new tests.integration.TestInfo()); + runner.add(new tests.integration.TestUser()); + runner.add(new tests.integration.TestDev()); + var success = runner.run(); + + if (!success) { + Sys.exit(1); + } + } +} diff --git a/extra/haxelib_src/test/Prepare.hx b/extra/haxelib_src/test/Prepare.hx new file mode 100644 index 00000000..d17a4aad --- /dev/null +++ b/extra/haxelib_src/test/Prepare.hx @@ -0,0 +1,52 @@ +import sys.*; +import sys.io.*; +import haxe.io.*; +using StringTools; + +class Prepare { + static function zipDir(dir:String, outPath:String):Void { + var entries = new List(); + + function add(path:String, target:String) { + if (!FileSystem.exists(path)) + throw 'Invalid path: $path'; + + if (FileSystem.isDirectory(path)) { + for (item in FileSystem.readDirectory(path)) + add(path + "/" + item, target == "" ? item : target + "/" + item); + } else { + var bytes = File.getBytes(path); + var entry:haxe.zip.Entry = { + fileName: target, + fileSize: bytes.length, + fileTime: FileSystem.stat(path).mtime, + compressed: false, + dataSize: 0, + data: bytes, + crc32: haxe.crypto.Crc32.make(bytes), + } + haxe.zip.Tools.compress(entry, 9); + entries.add(entry); + } + } + add(dir, ""); + + var out = File.write(outPath, true); + var writer = new haxe.zip.Writer(out); + writer.write(entries); + out.close(); + } + + static function main():Void { + /* + (re)package the dummy libraries + */ + var libsPath = "test/libraries"; + for (item in FileSystem.readDirectory(libsPath)) { + var path = Path.join([libsPath, item]); + if (FileSystem.isDirectory(path)) { + zipDir(path, 'test/libraries/${item}.zip'); + } + } + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/RunCi.hx b/extra/haxelib_src/test/RunCi.hx new file mode 100644 index 00000000..5dfd1134 --- /dev/null +++ b/extra/haxelib_src/test/RunCi.hx @@ -0,0 +1,386 @@ +import Sys.*; +import haxe.*; +import haxe.io.*; +import sys.FileSystem.*; +import sys.io.File.*; + +class RunCi { + static function successMsg(msg:String):Void { + Sys.println('\x1b[32m' + msg + '\x1b[0m'); + } + static function failMsg(msg:String):Void { + Sys.println('\x1b[31m' + msg + '\x1b[0m'); + } + static function infoMsg(msg:String):Void { + Sys.println('\x1b[36m' + msg + '\x1b[0m'); + } + + /** + Run a command using `Sys.command()`. + If the command exits with non-zero code, exit the whole script with the same code. + + If `useRetry` is `true`, the command will be re-run if it exits with non-zero code (3 trials). + It is useful for running network-dependent commands. + */ + static function runCommand(cmd:String, ?args:Array, useRetry:Bool = false):Void { + var trials = useRetry ? 3 : 1; + var exitCode:Int = 1; + var cmdStr = cmd + (args != null ? ' $args' : ''); + + while (trials-->0) { + Sys.println("Command: " + cmdStr); + + var t = Timer.stamp(); + exitCode = Sys.command(cmd, args); + var dt = Math.round(Timer.stamp() - t); + + if (exitCode == 0) + successMsg('Command exited with $exitCode in ${dt}s: $cmdStr'); + else + failMsg('Command exited with $exitCode in ${dt}s: $cmdStr'); + + if (exitCode == 0) { + return; + } else if (trials > 0) { + Sys.println('Command will be re-run...'); + } + } + + Sys.exit(exitCode); + } + + static function download(url:String, saveAs:String):Void { + infoMsg('download $url as $saveAs'); + runCommand("curl", ["-fSLk", url, "-o", saveAs, "-A", "Mozilla/4.0"]); + } + + static function compileServer():Void { + runCommand("haxe", ["server.hxml"]); + } + + static function compileLegacyServer():Void { + runCommand("haxe", ["server_legacy.hxml"]); + } + + static function compileClient():Void { + runCommand("haxe", ["client.hxml"]); + } + + static function compileLegacyClient():Void { + runCommand("haxe", ["client_legacy.hxml"]); + } + + static function testClient():Void { + runCommand("haxe", ["client_tests.hxml"]); + } + + static function testServer():Void { + runCommand("haxe", ["server_tests.hxml"]); + } + + static function runWithLocalServer(test:Void->Void):Void { + var HAXELIB_SERVER = "localhost"; + var HAXELIB_SERVER_PORT = "2000"; + var ndllPath = getEnv("NEKOPATH"); + if (ndllPath == null) + if (exists("/usr/lib/x86_64-linux-gnu/neko")) + ndllPath = "/usr/lib/x86_64-linux-gnu/neko"; + else + ndllPath = "/usr/lib/neko"; + var DocumentRoot = Path.join([getCwd(), "www"]); + var dbConfigPath = Path.join(["www", "dbconfig.json"]); + var dbConfig = Json.parse(getContent(dbConfigPath)); + // update dbConfig.host to be "localhost" + saveContent(dbConfigPath, Json.stringify({ + user: dbConfig.user, + pass: dbConfig.pass, + host: "localhost", + database: dbConfig.database, + })); + function writeApacheConf(confPath:String):Void { + var hasModNeko = switch (systemName()) { + case "Windows": + false; + case _: + var p = new sys.io.Process("apachectl", ["-M"]); + var out = p.stdout.readAll().toString(); + var has = out.indexOf("neko_module") >= 0; + p.close(); + has; + } + + var confContent = +( + switch (systemName()) { + case "Windows": + "LoadModule rewrite_module modules/mod_rewrite.so\n" + + "LoadModule filter_module modules/mod_filter.so\n" + + "LoadModule deflate_module modules/mod_deflate.so\n"; + case "Mac": + "LoadModule rewrite_module libexec/mod_rewrite.so\n" + + "LoadModule deflate_module libexec/mod_deflate.so\n"; + case _: + ""; + } +) + +( + if (hasModNeko) + "" + else + 'LoadModule neko_module ${Path.join([ndllPath, "mod_neko2.ndll"])}\n' +) + +'LoadModule tora_module ${Path.join([ndllPath, "mod_tora2.ndll"])} +AddHandler tora-handler .n +Listen 2000 + + DocumentRoot "$DocumentRoot" + + + Options Indexes FollowSymLinks + AllowOverride All + Order allow,deny + Allow from all + Require all granted + +'; + var confOut = if (exists(confPath)) + append(confPath); + else + write(confPath); + confOut.writeString(confContent); + confOut.flush(); + confOut.close(); + } + function configDb():Void { + var isAppVeyor = getEnv("APPVEYOR") != null; + var user = if (isAppVeyor) + // https://www.appveyor.com/docs/services-databases#mysql + { user: "root", pass: "Password12!" }; + else + { user: "root", pass: "" }; + + var cnx = sys.db.Mysql.connect({ + user: user.user, + pass: user.pass, + host: "localhost", + port: 3306, + database: "", + }); + cnx.request('create user \'${dbConfig.user}\'@\'localhost\' identified by \'${dbConfig.pass}\';'); + cnx.request('create database ${dbConfig.database};'); + cnx.request('grant all on ${dbConfig.database}.* to \'${dbConfig.user}\'@\'localhost\';'); + cnx.close(); + } + + switch (systemName()) { + case "Windows": + configDb(); + + download("https://www.apachelounge.com/download/VC14/binaries/httpd-2.4.23-win32-VC14.zip", "bin/httpd.zip"); + runCommand("7z", ["x", "bin\\httpd.zip", "-obin\\httpd"]); + writeApacheConf("bin\\httpd\\Apache24\\conf\\httpd.conf"); + + var apachePath = "c:\\Apache24"; + rename("bin\\httpd\\Apache24", apachePath); + var serviceName = "HaxelibApache"; + var httpd = Path.join([apachePath, "bin", "httpd.exe"]); + runCommand(httpd, ["-k", "install", "-n", serviceName]); + runCommand(httpd, ["-n", serviceName, "-t"]); + runCommand(httpd, ["-k", "start", "-n", serviceName]); + + var toraPath = { + var p = new sys.io.Process("haxelib", ["path", "tora"]); + var path = p.stdout.readLine(); + p.close(); + path; + } + runCommand("nssm", ["install", "tora", Path.join([getEnv("NEKOPATH"), "neko.exe"]), Path.join([toraPath, "run.n"])]); + runCommand("nssm", ["start", "tora"]); + + Sys.sleep(2.5); + + try { + haxe.Http.requestUrl('http://${HAXELIB_SERVER}:${HAXELIB_SERVER_PORT}/'); + } catch (e:Dynamic) { + println("Cannot open webpage."); + println("===================="); + println("apache error log:"); + println(sys.io.File.getContent(Path.join([apachePath, "logs", "error.log"]))); + println("===================="); + println("apache config:"); + println(sys.io.File.getContent(Path.join([apachePath, "conf", "httpd.conf"]))); + println("===================="); + } + case "Mac": + runCommand("brew", ["install", "homebrew/apache/httpd24", "mysql"]); + + runCommand("mysql.server", ["start"]); + configDb(); + + runCommand("apachectl", ["start"]); + Sys.sleep(2.5); + writeApacheConf("/usr/local/etc/apache2/2.4/httpd.conf"); + Sys.sleep(2.5); + runCommand("apachectl", ["restart"]); + Sys.sleep(2.5); + + try { + haxe.Http.requestUrl('http://${HAXELIB_SERVER}:${HAXELIB_SERVER_PORT}/'); + } catch (e:Dynamic) { + println("Cannot open webpage."); + println("===================="); + println("apache error log:"); + println(sys.io.File.getContent("/usr/local/var/log/apache2/error_log")); + println("===================="); + println("apache config:"); + println(sys.io.File.getContent("/usr/local/etc/apache2/2.4/httpd.conf")); + println("===================="); + } + case "Linux": + configDb(); + + runCommand("sudo", ["apt-get", "install", "-y", "apache2"]); + + runCommand("sudo", ["a2enmod", "rewrite"]); + runCommand("sudo", ["a2enmod", "deflate"]); + + writeApacheConf("haxelib.conf"); + runCommand("sudo", ["ln", "-s", Path.join([Sys.getCwd(), "haxelib.conf"]), "/etc/apache2/conf-enabled/haxelib.conf"]); + + runCommand("sudo", ["service", "apache2", "restart"]); + Sys.sleep(2.5); + + try { + haxe.Http.requestUrl('http://${HAXELIB_SERVER}:${HAXELIB_SERVER_PORT}/'); + } catch (e:Dynamic) { + println("Cannot open webpage."); + println("===================="); + println("apachectl -V:"); + command("sudo", ["apachectl", "-V"]); + println("===================="); + println("apachectl -M:"); + command("sudo", ["apachectl", "-M"]); + println("===================="); + println("cat /var/log/apache2/error.log"); + command("sudo", ["cat", "/var/log/apache2/error.log"]); + println("===================="); + } + case name: + throw "System not supported: " + name; + } + + Sys.setCwd("www"); + runCommand("bower", ["install"]); + Sys.setCwd(".."); + + Sys.putEnv("HAXELIB_SERVER", HAXELIB_SERVER); + Sys.putEnv("HAXELIB_SERVER_PORT", HAXELIB_SERVER_PORT); + + test(); + + switch (systemName()) { + case "Mac": + runCommand("apachectl", ["stop"]); + runCommand("mysql.server", ["stop"]); + case _: + //pass + } + } + + static function runWithDockerServer(test:Void->Void):Void { + var server = switch (systemName()) { + case "Linux": + "localhost"; + case _: + var p = new sys.io.Process("docker-machine", ["ip"]); + var ip = p.stdout.readLine(); + p.close(); + ip; + } + var serverPort = 2000; + + runCommand("docker-compose", ["-f", "test/docker-compose.yml", "up", "-d"]); + + Sys.putEnv("HAXELIB_SERVER", server); + Sys.putEnv("HAXELIB_SERVER_PORT", Std.string(serverPort)); + infoMsg("waiting for server to start..."); + + var url = 'http://${server}:${serverPort}/'; + + var t = Timer.stamp(); + while (true) { + var isUp = try { + var response = haxe.Http.requestUrl(url); + !StringTools.startsWith(response, "Error"); + } catch (e:Dynamic) { + false; + } + + if (isUp) { + break; + } + + if (Timer.stamp() - t > 120) { + throw "server is not reachable..."; + } + + Sys.sleep(10.0); + // Sys.command("curl", ["-s", "-o", "/dev/null", "-w", "%{http_code}", url]); + } + infoMsg("server started"); + + test(); + + runCommand("docker-compose", ["-f", "test/docker-compose.yml", "down"]); + } + + static function integrationTests():Void { + function test():Void { + switch (Sys.getEnv("TRAVIS_HAXE_VERSION")) { + case null, "development": + runCommand("haxe", ["integration_tests.hxml"]); + case "3.1.3": + runCommand("haxe", ["integration_tests.hxml", "-D", "system_haxelib"]); + case _: + runCommand("haxe", ["integration_tests.hxml"]); + runCommand("haxe", ["integration_tests.hxml", "-D", "system_haxelib"]); + } + } + if (Sys.getEnv("CI") != null && Sys.getEnv("USE_DOCKER") == null) { + runWithLocalServer(test); + } else { + runWithDockerServer(test); + } + } + + static function main():Void { + // Note that package.zip output is also used by client tests, so it has to be run before that. + runCommand("haxe", ["package.hxml"]); + runCommand("haxe", ["prepare_tests.hxml"]); + + compileLegacyClient(); + compileLegacyServer(); + + // the server can only be compiled with haxe 3.2+ + // haxe 3.1.3 bundles haxelib client 3.1.0-rc.4, which is not upgradable to later haxelib + // so there is no need to test the client either + #if (haxe_ver >= 3.2) + compileClient(); + testClient(); + compileServer(); + testServer(); + #end + + // integration test + switch (systemName()) { + case "Windows", "Linux": + integrationTests(); + case "Mac": + #if (haxe_ver >= 3.2) + integrationTests(); + #end + case _: + throw "Unknown system"; + } + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/TestBase.hx b/extra/haxelib_src/test/TestBase.hx new file mode 100644 index 00000000..56674e45 --- /dev/null +++ b/extra/haxelib_src/test/TestBase.hx @@ -0,0 +1,33 @@ +import sys.*; +import sys.io.*; +import haxe.io.*; +import haxe.unit.*; + +class TestBase extends TestCase { + static var haxelibPath = FileSystem.fullPath("run.n"); + public function runHaxelib(args:Array) { + var p = new Process("neko", [haxelibPath].concat(args)); + var stdout = p.stdout.readAll().toString(); + var stderr = p.stderr.readAll().toString(); + var exitCode = p.exitCode(); + p.close(); + return { + stdout: stdout, + stderr: stderr, + exitCode: exitCode + } + } + + public function deleteDirectory(dir:String):Void { + if (!FileSystem.exists(dir)) return; + var exitCode = switch (Sys.systemName()) { + case "Windows": + Sys.command("rmdir", ["/S", "/Q", StringTools.replace(FileSystem.fullPath(dir), "/", "\\")]); + case _: + Sys.command("rm", ["-rf", dir]); + } + if (exitCode != 0) { + throw 'unable to delete $dir'; + } + } +} diff --git a/extra/haxelib_src/test/WebsiteTests.hx b/extra/haxelib_src/test/WebsiteTests.hx new file mode 100644 index 00000000..2e097daa --- /dev/null +++ b/extra/haxelib_src/test/WebsiteTests.hx @@ -0,0 +1,44 @@ +package; + +import website.api.ProjectListApi; +import ufront.app.UfrontApplication; +import ufront.mailer.*; +import ufront.auth.EasyAuth; +import ufront.view.TemplatingEngines; +import twl.webapp.*; +import twl.*; +import buddy.*; + +@:build(buddy.GenerateMain.withSuites([ + website.controller.DocumentationControllerTest, + website.controller.HomeControllerTest, + // website.controller.ProjectControllerTest, + website.controller.RSSControllerTest, + // website.controller.UserControllerTest, +])) +class WebsiteTests { + static var ufApp:UfrontApplication; + + public static function getTestApp():UfrontApplication { + if ( ufApp==null ) { + // Create a UfrontApplication suitable for unit testing. + ufApp = new UfrontApplication({ + indexController: website.controller.HomeController, + errorHandlers: [], + disableBrowserTrace: true, + contentDirectory: "../uf-content/", + templatingEngines: [TemplatingEngines.erazor], + viewPath: "www/view/", + defaultLayout: "layout.html", + }); + + // Different injections for our test suite. + ufApp.injector.map( UFMailer ).toSingleton( TestMailer ); + ufApp.injector.map( EasyAuth ).toValue( new EasyAuthAdminMode() ); + ufApp.injector.map( String, "documentationPath" ).toValue( "www/documentation-files/" ); + + haxelib.server.SiteDb.init(); + } + return ufApp; + } +} diff --git a/extra/haxelib_src/test/docker-compose-dev.yml b/extra/haxelib_src/test/docker-compose-dev.yml new file mode 100644 index 00000000..8edeae2c --- /dev/null +++ b/extra/haxelib_src/test/docker-compose-dev.yml @@ -0,0 +1,27 @@ +version: '2' +services: + web: + build: .. + ports: + - "2000:80" + environment: + - HAXELIB_DB_HOST=dbHost + - HAXELIB_DB_PORT=3306 + - HAXELIB_DB_USER=dbUser + - HAXELIB_DB_PASS=dbPass + - HAXELIB_DB_NAME=haxelib + volumes: + - ../www:/var/www/html + dbHost: + image: mariadb + ports: + - "3306:3306" + environment: + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=haxelib + - MYSQL_USER=dbUser + - MYSQL_PASSWORD=dbPass + volumes: + - database:/var/lib/mysql +volumes: + database: {} \ No newline at end of file diff --git a/extra/haxelib_src/test/docker-compose.yml b/extra/haxelib_src/test/docker-compose.yml new file mode 100644 index 00000000..f8bc5667 --- /dev/null +++ b/extra/haxelib_src/test/docker-compose.yml @@ -0,0 +1,25 @@ +version: '2' +services: + web: + build: .. + ports: + - "2000:80" + environment: + - HAXELIB_DB_HOST=dbHost + - HAXELIB_DB_PORT=3306 + - HAXELIB_DB_USER=dbUser + - HAXELIB_DB_PASS=dbPass + - HAXELIB_DB_NAME=haxelib + dbHost: + image: mariadb + ports: + - "3306:3306" + environment: + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=haxelib + - MYSQL_USER=dbUser + - MYSQL_PASSWORD=dbPass + volumes: + - database:/var/lib/mysql +volumes: + database: {} \ No newline at end of file diff --git a/extra/haxelib_src/test/libraries/UseCp/haxelib.json b/extra/haxelib_src/test/libraries/UseCp/haxelib.json new file mode 100644 index 00000000..cf0cf254 --- /dev/null +++ b/extra/haxelib_src/test/libraries/UseCp/haxelib.json @@ -0,0 +1,11 @@ +{ + "name": "UseCp", + "url" : "http://example.org", + "license": "GPL", + "tags": [], + "description": "This project use a deep class path.", + "version": "0.0.1", + "releasenote": "Initial release, everything is working correctly", + "classPath": "lib/src", + "contributors": ["Bar"] +} \ No newline at end of file diff --git a/extra/haxelib_src/testing/libraries/libBar/bar/Bar.hx b/extra/haxelib_src/test/libraries/UseCp/lib/src/bar/Bar.hx similarity index 100% rename from extra/haxelib_src/testing/libraries/libBar/bar/Bar.hx rename to extra/haxelib_src/test/libraries/UseCp/lib/src/bar/Bar.hx diff --git a/extra/haxelib_src/testing/libraries/libFoo/foo/Foo.hx b/extra/haxelib_src/test/libraries/UseGitDep/foo/Foo.hx similarity index 100% rename from extra/haxelib_src/testing/libraries/libFoo/foo/Foo.hx rename to extra/haxelib_src/test/libraries/UseGitDep/foo/Foo.hx diff --git a/extra/haxelib_src/test/libraries/UseGitDep/haxelib.json b/extra/haxelib_src/test/libraries/UseGitDep/haxelib.json new file mode 100644 index 00000000..0bbc31dd --- /dev/null +++ b/extra/haxelib_src/test/libraries/UseGitDep/haxelib.json @@ -0,0 +1,13 @@ +{ + "name": "Foo", + "url" : "http://example.org", + "license": "GPL", + "tags": ["foo", "test"], + "description": "This project is an example of an haxelib project", + "version": "0.1.0-alpha.0", + "releasenote": "Initial release, everything is working correctly", + "dependencies": { + "signal": "git:https://github.com/fzzr-/hx.signal.git" + }, + "contributors": ["Foo"] +} \ No newline at end of file diff --git a/extra/haxelib_src/test/libraries/UseGitDep/haxelib.xml b/extra/haxelib_src/test/libraries/UseGitDep/haxelib.xml new file mode 100644 index 00000000..38cf8a65 --- /dev/null +++ b/extra/haxelib_src/test/libraries/UseGitDep/haxelib.xml @@ -0,0 +1,7 @@ + + + + + This project is an example of an haxelib project + Initial release, everything is working correctly + \ No newline at end of file diff --git a/extra/haxelib_src/test/libraries/UseGitDep/tag_haxelib.json b/extra/haxelib_src/test/libraries/UseGitDep/tag_haxelib.json new file mode 100644 index 00000000..078f011b --- /dev/null +++ b/extra/haxelib_src/test/libraries/UseGitDep/tag_haxelib.json @@ -0,0 +1,13 @@ +{ + "name": "Foo", + "url" : "http://example.org", + "license": "GPL", + "tags": ["foo", "test"], + "description": "This project is an example of an haxelib project", + "version": "0.1.0-alpha.0", + "releasenote": "Initial release, everything is working correctly", + "dependencies": { + "signal": "git:https://github.com/fzzr-/hx.signal.git#0.9.2" + }, + "contributors": ["Foo"] +} \ No newline at end of file diff --git a/extra/haxelib_src/test/libraries/libBar/bar/Bar.hx b/extra/haxelib_src/test/libraries/libBar/bar/Bar.hx new file mode 100644 index 00000000..2936374c --- /dev/null +++ b/extra/haxelib_src/test/libraries/libBar/bar/Bar.hx @@ -0,0 +1,9 @@ +package bar; + +class Bar { + + static function new() { + trace("new Bar"); + } + +} \ No newline at end of file diff --git a/extra/haxelib_src/testing/libraries/libBar/haxelib.json b/extra/haxelib_src/test/libraries/libBar/haxelib.json similarity index 100% rename from extra/haxelib_src/testing/libraries/libBar/haxelib.json rename to extra/haxelib_src/test/libraries/libBar/haxelib.json diff --git a/extra/haxelib_src/testing/libraries/libBar/haxelib.xml b/extra/haxelib_src/test/libraries/libBar/haxelib.xml similarity index 100% rename from extra/haxelib_src/testing/libraries/libBar/haxelib.xml rename to extra/haxelib_src/test/libraries/libBar/haxelib.xml diff --git a/extra/haxelib_src/test/libraries/libBar2/bar/Bar.hx b/extra/haxelib_src/test/libraries/libBar2/bar/Bar.hx new file mode 100644 index 00000000..2936374c --- /dev/null +++ b/extra/haxelib_src/test/libraries/libBar2/bar/Bar.hx @@ -0,0 +1,9 @@ +package bar; + +class Bar { + + static function new() { + trace("new Bar"); + } + +} \ No newline at end of file diff --git a/extra/haxelib_src/test/libraries/libBar2/haxelib.json b/extra/haxelib_src/test/libraries/libBar2/haxelib.json new file mode 100644 index 00000000..56b00b50 --- /dev/null +++ b/extra/haxelib_src/test/libraries/libBar2/haxelib.json @@ -0,0 +1,10 @@ +{ + "name": "Bar", + "url" : "http://example.org", + "license": "MIT", + "tags": ["bar", "version2"], + "description": "This project is an example of an haxelib project", + "version": "2.0.0", + "releasenote": "Version 2.", + "contributors": ["Bar"] +} \ No newline at end of file diff --git a/extra/haxelib_src/test/libraries/libBar2/haxelib.xml b/extra/haxelib_src/test/libraries/libBar2/haxelib.xml new file mode 100644 index 00000000..476a4920 --- /dev/null +++ b/extra/haxelib_src/test/libraries/libBar2/haxelib.xml @@ -0,0 +1,7 @@ + + + + + This project is an example of an haxelib project + Initial release, everything is working correctly + \ No newline at end of file diff --git a/extra/haxelib_src/test/libraries/libFoo/foo/Foo.hx b/extra/haxelib_src/test/libraries/libFoo/foo/Foo.hx new file mode 100644 index 00000000..1ecc074b --- /dev/null +++ b/extra/haxelib_src/test/libraries/libFoo/foo/Foo.hx @@ -0,0 +1,9 @@ +package foo; + +class Foo { + + public function new() { + trace("new Foo"); + } + +} \ No newline at end of file diff --git a/extra/haxelib_src/testing/libraries/libFoo/haxelib.json b/extra/haxelib_src/test/libraries/libFoo/haxelib.json similarity index 95% rename from extra/haxelib_src/testing/libraries/libFoo/haxelib.json rename to extra/haxelib_src/test/libraries/libFoo/haxelib.json index 38f9bb07..359642ad 100644 --- a/extra/haxelib_src/testing/libraries/libFoo/haxelib.json +++ b/extra/haxelib_src/test/libraries/libFoo/haxelib.json @@ -7,7 +7,7 @@ "version": "0.1.0-alpha.0", "releasenote": "Initial release, everything is working correctly", "dependencies": { - "bar": "" + "Bar": "" }, "contributors": ["Foo"] } \ No newline at end of file diff --git a/extra/haxelib_src/testing/libraries/libFoo/haxelib.xml b/extra/haxelib_src/test/libraries/libFoo/haxelib.xml similarity index 100% rename from extra/haxelib_src/testing/libraries/libFoo/haxelib.xml rename to extra/haxelib_src/test/libraries/libFoo/haxelib.xml diff --git a/extra/haxelib_src/test/tests/TestCli.hx b/extra/haxelib_src/test/tests/TestCli.hx deleted file mode 100644 index 124c2de0..00000000 --- a/extra/haxelib_src/test/tests/TestCli.hx +++ /dev/null @@ -1,46 +0,0 @@ -package tests; - -import tools.haxelib.Main.Cli; -import tools.haxelib.Main.CliError; -import haxe.unit.TestCase; - -class TestCli extends TestCase -{ - //----------- properties, fields ------------// - - var cli:Cli; - - //--------------- constructor ---------------// - public function new() - { - super(); - } - - - //--------------- initialize ----------------// - - override public function setup():Void - { - cli = new Cli(); - } - - //----------------- tests -------------------// - - public function testSetWrongCwd():Void - { - var cwd = Sys.getCwd(); - - try - { - cli.cwd = "/this/path/dos/not/exists"; - assertTrue(false); - } - catch(error:CliError) - assertTrue(true); - - assertEquals(cwd, Sys.getCwd()); - } - - - //----------------- tools -------------------// -} diff --git a/extra/haxelib_src/test/tests/TestData.hx b/extra/haxelib_src/test/tests/TestData.hx index 435e1af3..82f2dac9 100644 --- a/extra/haxelib_src/test/tests/TestData.hx +++ b/extra/haxelib_src/test/tests/TestData.hx @@ -5,11 +5,11 @@ import haxe.Json; import haxe.io.*; import haxe.zip.*; import sys.io.*; -import tools.haxelib.Data; +import haxelib.Data; using StringTools; -class TestData extends haxe.unit.TestCase { - +class TestData extends TestBase { + public function testSafe() { assertEquals( "abc", checkSafe("abc") ); assertEquals( "bean,hx", checkSafe("bean.hx") ); @@ -27,13 +27,13 @@ class TestData extends haxe.unit.TestCase { Data.safe( str ); } catch (e:String) "invalid"; } - + public function testUnsafe() { assertEquals( "abc", Data.unsafe("abc") ); assertEquals( "1.2.3", Data.unsafe("1,2,3") ); assertEquals( "", Data.unsafe("") ); } - + public function testFileName() { assertEquals( "lib-1,2,3.zip", checkFileName("lib","1.2.3") ); assertEquals( "lib-1,2,3-rc,3.zip", checkFileName("lib","1.2.3-rc.3") ); @@ -47,26 +47,26 @@ class TestData extends haxe.unit.TestCase { Data.fileName( lib, ver ); } catch (e:String) "invalid"; } - + public function testLocateBasePath() { - var zip = Reader.readZip(new BytesInput(File.getBytes("package/package.zip"))); + var zip = Reader.readZip(new BytesInput(File.getBytes("package.zip"))); assertEquals( "", Data.locateBasePath(zip) ); var zip = Reader.readZip(new BytesInput(File.getBytes("test/libraries/libDeep.zip"))); assertEquals( "libDeep/", Data.locateBasePath(zip) ); } - + public function testReadDoc() { - var zip = Reader.readZip(new BytesInput(File.getBytes("package/package.zip"))); + var zip = Reader.readZip(new BytesInput(File.getBytes("package.zip"))); assertEquals( null, Data.readDoc(zip) ); //TODO } - + public function testReadInfos() { - var zip = Reader.readZip(new BytesInput(File.getBytes("package/package.zip"))); + var zip = Reader.readZip(new BytesInput(File.getBytes("package.zip"))); var info = Data.readInfos(zip, true); - assertEquals( "haxelib_client", info.name ); + assertEquals( "haxelib", info.name ); assertEquals( "GPL", info.license ); var zip = Reader.readZip(new BytesInput(File.getBytes("test/libraries/libDeep.zip"))); @@ -80,9 +80,9 @@ class TestData extends haxe.unit.TestCase { assertEquals( "N/A", info.releasenote ); assertEquals( "DeepAuthor, AnotherGuy", info.contributors.join(", ") ); } - + public function testCheckClassPath() { - var zip = Reader.readZip(new BytesInput(File.getBytes("package/package.zip"))); + var zip = Reader.readZip(new BytesInput(File.getBytes("package.zip"))); var info = Data.readInfos(zip, true); var ok:Dynamic = try { Data.checkClassPath(zip,info); @@ -91,7 +91,7 @@ class TestData extends haxe.unit.TestCase { e; } assertEquals( ok, true ); - + var zip = Reader.readZip(new BytesInput(File.getBytes("test/libraries/libDeep.zip"))); var info = Data.readInfos(zip, true); var ok:Dynamic = try { @@ -102,16 +102,16 @@ class TestData extends haxe.unit.TestCase { } assertEquals( ok, true ); } - + public function testReadDataWithCheck() { assertFalse( readDataOkay("bad json") ); - + assertTrue( readDataOkay(getJsonInfos()) ); - + // Names assertFalse( readDataOkay("{}") ); assertFalse( readDataOkay(getJsonInfos({ name: null })) ); - + assertFalse( readDataOkay(getJsonInfos({ name: '' })) ); assertFalse( readDataOkay(getJsonInfos({ name: 'haxe' })) ); assertFalse( readDataOkay(getJsonInfos({ name: 'haXe' })) ); @@ -157,7 +157,7 @@ class TestData extends haxe.unit.TestCase { // Dependencies (optional) assertTrue( readDataOkay(getJsonInfos({ dependencies: null })) ); assertTrue( readDataOkay(getJsonInfos({ dependencies: { somelib: "" } })) ); - + assertTrue( readDataOkay(getJsonInfos({ dependencies: { somelib:"1.3.0" } }) )); assertFalse( readDataOkay(getJsonInfos({ dependencies: { somelib: "nonsemver" }})) ); @@ -176,21 +176,21 @@ class TestData extends haxe.unit.TestCase { assertTrue( readDataOkay(getJsonInfos({ classPath: null })) ); assertFalse( readDataOkay(getJsonInfos({ classPath: ["src","othersrc"] })) ); } - + public function testReadDataWithoutCheck() { assertEquals( ProjectName.DEFAULT, Data.readData("bad json",false).name ); assertEquals( "0.0.0", Data.readData("bad json",false).version ); assertEquals( "mylib", Data.readData(getJsonInfos(),false).name ); assertEquals( "0.1.2", Data.readData(getJsonInfos(),false).version ); - + // Names assertEquals( ProjectName.DEFAULT, Data.readData("{}",false).name ); assertEquals( ProjectName.DEFAULT, Data.readData(getJsonInfos({ name: null }),false).name ); assertEquals( ProjectName.DEFAULT, Data.readData(getJsonInfos({ name: '' }),false).name ); assertEquals( "mylib", Data.readData(getJsonInfos({ name: 'mylib' }),false).name ); assertEquals( ProjectName.DEFAULT, Data.readData(getJsonInfos([ "name" ]), false).name ); // remove the field altogether - + /* // Description (optional) assertEquals( "Some Description", Data.readData(getJsonInfos({ description: 'Some Description' }),false).description ); @@ -226,7 +226,7 @@ class TestData extends haxe.unit.TestCase { assertEquals( 0, Data.readData(getJsonInfos({ tags: null }),false).tags.length ); assertEquals( 0, Data.readData(getJsonInfos({ tags: "mytag" }),false).tags.length ); */ - + // Dependencies (optional) assertEquals( 0, Data.readData(getJsonInfos({ dependencies: null }),false).dependencies.toArray().length ); assertEquals( "somelib", Data.readData(getJsonInfos({ dependencies: { somelib:"" } }),false).dependencies.toArray()[0].name ); @@ -235,7 +235,7 @@ class TestData extends haxe.unit.TestCase { assertEquals( "", Data.readData(getJsonInfos({ dependencies: { somelib:"nonsemver" } }),false).dependencies.toArray()[0].version ); assertEquals( "", Data.readData(getJsonInfos({ dependencies: { somelib:null } }),false).dependencies.toArray()[0].version ); assertEquals( "", Data.readData(getJsonInfos( { dependencies: { somelib:0 } } ), false).dependencies.toArray()[0].version ); - + /* // ReleaseNote assertEquals( "release", Data.readData(getJsonInfos({ releasenote: "release" }),false).releasenote ); @@ -249,10 +249,10 @@ class TestData extends haxe.unit.TestCase { } function readDataOkay( json ) { - try { - Data.readData( json,true ); - return true; - } + try { + Data.readData( json,true ); + return true; + } catch (e:String) { return false; } @@ -273,7 +273,7 @@ class TestData extends haxe.unit.TestCase { } } if (remove != null) { - for ( f in remove ) + for ( f in remove ) Reflect.deleteField( infos, f ); } return Json.stringify(infos); diff --git a/extra/haxelib_src/test/tests/TestGit.hx b/extra/haxelib_src/test/tests/TestGit.hx new file mode 100644 index 00000000..6cceea46 --- /dev/null +++ b/extra/haxelib_src/test/tests/TestGit.hx @@ -0,0 +1,9 @@ +package tests; + +import haxelib.client.Vcs; + +class TestGit extends TestVcs { + public function new():Void { + super(VcsID.Git, "Git", "https://github.com/fzzr-/hx.signal.git", "0.9.2"); + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/tests/TestHg.hx b/extra/haxelib_src/test/tests/TestHg.hx new file mode 100644 index 00000000..c4c8c2d0 --- /dev/null +++ b/extra/haxelib_src/test/tests/TestHg.hx @@ -0,0 +1,9 @@ +package tests; + +import haxelib.client.Vcs; + +class TestHg extends TestVcs { + public function new():Void { + super(VcsID.Hg, "Mercurial", "https://bitbucket.org/fzzr/hx.signal", "78edb4b"); + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/tests/TestInstall.hx b/extra/haxelib_src/test/tests/TestInstall.hx new file mode 100644 index 00000000..9cb6bdd7 --- /dev/null +++ b/extra/haxelib_src/test/tests/TestInstall.hx @@ -0,0 +1,101 @@ +package tests; + +import sys.io.*; +import sys.FileSystem; +import haxe.io.*; +import haxe.unit.TestCase; +import haxelib.Data; + + +class TestInstall extends TestBase +{ + + static inline var REPO = "haxelib-repo"; + static inline var PROJECT_FOLDER = "UseGitDep"; + static inline var REPO_ROOT = "test/libraries"; + static var CWD:String = null; + static var origRepo:String = null; + var repo:String = null; + + + //--------------- constructor ---------------// + + public function new() + { + super(); + this.repo = Path.join([Sys.getCwd(), "test", REPO]); + } + + + //--------------- initialize ----------------// + + override public function setup():Void + { + origRepo = ~/\r?\n/.split(runHaxelib(["config"]).stdout)[0]; + origRepo = Path.normalize(origRepo); + + if (runHaxelib(["setup", repo]).exitCode != 0) { + throw "haxelib setup failed"; + } + + CWD = Sys.getCwd(); + var dir = Path.join([CWD, REPO_ROOT, PROJECT_FOLDER]); + Sys.setCwd(dir); + } + + override public function tearDown():Void + { + // restore original CWD: + Sys.setCwd(CWD); + + if (runHaxelib(["setup", origRepo]).exitCode != 0) { + throw "haxelib setup failed"; + } + deleteDirectory(repo); + + } + + //----------------- tests -------------------// + + public function testInstallHaxelibParameter():Void + { + var r = runHaxelib(["install", "haxelib.json"]); + assertTrue(r.exitCode == 0); + + checkLibrary(getLibraryName()); + } + + public function testInstallHaxelibDependencyWithTag():Void + { + var r = runHaxelib(["install", "tag_haxelib.json"]); + assertTrue(r.exitCode == 0); + + var lib = getLibraryName(); + checkLibrary(lib); + + // if that repo "README.md" was added in tag/rev.: "0.9.3" + assertFalse(FileSystem.exists(Path.join([lib, "git", "README.md"]))); + } + + function getLibraryName():String + { + var haxelibFile = File.read("haxelib.json", false); + var details = Data.readData(haxelibFile.readAll().toString(), false ); + haxelibFile.close(); + return details.dependencies.toArray()[0].name; + } + + function checkLibrary(lib:String):Void + { + // Library folder exists + var libFolder = Path.join([repo, lib]); + assertTrue(FileSystem.exists(libFolder)); + assertTrue(FileSystem.isDirectory(libFolder)); + + // Library version is set to git + var current = File.read(Path.join([libFolder, ".current"]), false); + assertTrue(current.readAll().toString() == "git"); + current.close(); + } + +} \ No newline at end of file diff --git a/extra/haxelib_src/test/tests/TestRemoveSymlinks.hx b/extra/haxelib_src/test/tests/TestRemoveSymlinks.hx index 331c2c9c..6abe7b4b 100644 --- a/extra/haxelib_src/test/tests/TestRemoveSymlinks.hx +++ b/extra/haxelib_src/test/tests/TestRemoveSymlinks.hx @@ -1,50 +1,55 @@ package tests; import sys.FileSystem; +import sys.io.*; import haxe.io.Path; import haxe.unit.TestCase; -class TestRemoveSymlinks extends TestCase +class TestRemoveSymlinks extends TestBase { //----------- properties, fields ------------// static var REPO = "haxelib-repo"; - var lib:String = null; + var lib:String = "symlinks"; var repo:String = null; + var origRepo:String; //--------------- constructor ---------------// - public function new(lib:String) + public function new() { super(); - this.lib = lib; - this.repo = Path.join([Sys.getCwd(), "testing", REPO]); + this.repo = Path.join([Sys.getCwd(), "test", REPO]); } //--------------- initialize ----------------// override public function setup():Void { + origRepo = ~/\r?\n/.split(runHaxelib(["config"]).stdout)[0]; + origRepo = Path.normalize(origRepo); + var libzip = Path.join([Sys.getCwd(), "test", "libraries", lib + ".zip"]); - Sys.command("neko", ["./bin/haxelib.n", "setup", repo]); - Sys.command("neko", ["./bin/haxelib.n", "local", libzip]); + if (runHaxelib(["setup", repo]).exitCode != 0) { + throw "haxelib setup failed"; + } + if (runHaxelib(["local", libzip]).exitCode != 0) { + throw "haxelib local failed"; + } + } + + override public function tearDown():Void { + if (runHaxelib(["setup", origRepo]).exitCode != 0) { + throw "haxelib setup failed"; + } + deleteDirectory(repo); } //----------------- tests -------------------// public function testRemoveLibWithSymlinks():Void { - var code = Sys.command("neko", ["./bin/haxelib.n", "remove", lib]); + var code = runHaxelib(["remove", lib]).exitCode; assertEquals(code, 0); assertFalse(FileSystem.exists(Path.join([repo, lib]))); } - - - //----------------- tools -------------------// - - function command(cmd:String, args:Array) - { - var p = new sys.io.Process(cmd, args); - var code = p.exitCode(); - return {code:code, out:code == 0 ? p.stdout.readAll().toString() : p.stderr.readAll().toString()}; - } } diff --git a/extra/haxelib_src/test/tests/TestRemoveSymlinksBroken.hx b/extra/haxelib_src/test/tests/TestRemoveSymlinksBroken.hx new file mode 100644 index 00000000..7a351b77 --- /dev/null +++ b/extra/haxelib_src/test/tests/TestRemoveSymlinksBroken.hx @@ -0,0 +1,9 @@ +package tests; + +class TestRemoveSymlinksBroken extends TestRemoveSymlinks +{ + public function new():Void { + super(); + this.lib = "symlinks-broken"; + } +} diff --git a/extra/haxelib_src/test/tests/TestSemVer.hx b/extra/haxelib_src/test/tests/TestSemVer.hx index 8f837720..c538bb6b 100644 --- a/extra/haxelib_src/test/tests/TestSemVer.hx +++ b/extra/haxelib_src/test/tests/TestSemVer.hx @@ -1,8 +1,8 @@ package tests; -import tools.haxelib.SemVer; +import haxelib.SemVer; -class TestSemVer extends haxe.unit.TestCase { +class TestSemVer extends TestBase { static function make(major, minor, patch, ?preview, ?previewNum):SemVer { return { major : major, @@ -19,32 +19,32 @@ class TestSemVer extends haxe.unit.TestCase { assertEquals( "0.1.2-alpha", make(0,1,2,ALPHA) ); assertEquals( "0.1.2-beta", make(0,1,2,BETA) ); assertEquals( "0.1.2-rc", make(0,1,2,RC) ); - + // Release Tag Versions assertEquals( "0.1.2-alpha.0", make(0,1,2,ALPHA,0) ); assertEquals( "0.1.2-beta.0", make(0,1,2,BETA,0) ); assertEquals( "0.1.2-rc.0", make(0,1,2,RC,0) ); - + // Weird input assertEquals( "0.1.2", make(0,1,2,null,0) ); - + // Multiple characters assertEquals( "100.200.300-rc.400", make(100,200,300,RC,400) ); } - + public function testOfString() { // Normal assertEquals( "0.1.2", (SemVer.ofString("0.1.2").data : SemVer)); - assertEquals( "100.50.200", (SemVer.ofString("0100.050.0200").data : SemVer)); + assertEquals( "100.50.200", (SemVer.ofString("100.50.200").data : SemVer)); // Release tags assertEquals( "0.1.2-alpha", (SemVer.ofString("0.1.2-ALPHA").data : SemVer)); assertEquals( "0.1.2-alpha", (SemVer.ofString("0.1.2-alpha").data : SemVer)); assertEquals( "0.1.2-beta", (SemVer.ofString("0.1.2-beta").data : SemVer)); assertEquals( "0.1.2-rc", (SemVer.ofString("0.1.2-rc").data : SemVer)); - assertEquals( "0.1.2-rc.1", (SemVer.ofString("0.1.2-rc.01").data : SemVer)); + assertEquals( "0.1.2-rc.1", (SemVer.ofString("0.1.2-rc.1").data : SemVer)); } - + public function testOfStringInvalid() { assertEquals( "invalid", parseInvalid(null) ); assertEquals( "invalid", parseInvalid("") ); @@ -57,6 +57,8 @@ class TestSemVer extends haxe.unit.TestCase { assertEquals( "invalid", parseInvalid("1.2.3--rc.1") ); assertEquals( "invalid", parseInvalid("1.2.3-othertag") ); assertEquals( "invalid", parseInvalid("1.2.3-othertag.1") ); + assertEquals( "invalid", parseInvalid("10.050.02")); + assertEquals( "invalid", parseInvalid("10.50.2-rc.01")); } function parseInvalid( str:String ) { @@ -66,5 +68,5 @@ class TestSemVer extends haxe.unit.TestCase { "invalid"; } } - + } \ No newline at end of file diff --git a/extra/haxelib_src/test/tests/TestVcs.hx b/extra/haxelib_src/test/tests/TestVcs.hx index 031370aa..71200a0b 100644 --- a/extra/haxelib_src/test/tests/TestVcs.hx +++ b/extra/haxelib_src/test/tests/TestVcs.hx @@ -1,17 +1,18 @@ package tests; -import sys.io.File; +import sys.io.*; import sys.FileSystem; -import tools.haxelib.Vcs; +import haxe.io.*; import haxe.unit.TestCase; -import tools.haxelib.Main.Cli; -import tools.haxelib.Main.Answer; -class TestVcs extends TestCase +import haxelib.client.Cli; +import haxelib.client.Vcs; + +class TestVcs extends TestBase { //----------- properties, fields ------------// - static inline var REPO_ROOT = "testing/libraries"; + static inline var REPO_ROOT = "test/libraries"; static inline var REPO_DIR = "vcs"; static var CWD:String = null; @@ -40,10 +41,12 @@ class TestVcs extends TestCase override public function setup():Void { - Sys.setCwd(CWD + "/" + REPO_ROOT); + Sys.setCwd(Path.join([CWD, REPO_ROOT])); - if(!FileSystem.exists(REPO_DIR)) - FileSystem.createDirectory(REPO_DIR); + if(FileSystem.exists(REPO_DIR)) { + deleteDirectory(REPO_DIR); + } + FileSystem.createDirectory(REPO_DIR); Sys.setCwd(REPO_DIR); } @@ -52,6 +55,8 @@ class TestVcs extends TestCase { // restore original CWD: Sys.setCwd(CWD); + + deleteDirectory(Path.join([CWD, REPO_ROOT, REPO_DIR])); } //----------------- tests -------------------// @@ -59,8 +64,8 @@ class TestVcs extends TestCase public function testGetVcs():Void { - assertTrue(Vcs.get(id) != null); - assertTrue(Vcs.get(id).name == vcsName); + assertTrue(Vcs.get(id, {quiet: true}) != null); + assertTrue(Vcs.get(id, {quiet: true}).name == vcsName); } public function testAvailable():Void @@ -75,7 +80,7 @@ class TestVcs extends TestCase var vcs = getVcs(); testCloneSimple(); - assertEquals(vcs, Vcs.get(id)); + assertEquals(vcs, Vcs.get(id, {quiet: true})); } public function testCloneSimple():Void @@ -187,7 +192,7 @@ class TestVcs extends TestCase File.saveContent("file", "new file \"file\" with content"); //Hack: set the default answer: - new Cli().defaultAnswer = Answer.Yes; + Cli.defaultAnswer = true; // update to HEAD: // in this case `libName` can get any value: @@ -217,7 +222,7 @@ class TestVcs extends TestCase File.saveContent("file", "new file \"file\" with content"); //Hack: set the default answer: - new Cli().defaultAnswer = Answer.No; + Cli.defaultAnswer = false; // update to HEAD: // in this case `libName` can get any value: @@ -236,6 +241,6 @@ class TestVcs extends TestCase inline function getVcs():Vcs { - return Vcs.get(id); + return Vcs.get(id, {quiet: true}); } } diff --git a/extra/haxelib_src/test/tests/TestVcsNotFound.hx b/extra/haxelib_src/test/tests/TestVcsNotFound.hx index 0a259b41..946b2276 100644 --- a/extra/haxelib_src/test/tests/TestVcsNotFound.hx +++ b/extra/haxelib_src/test/tests/TestVcsNotFound.hx @@ -1,15 +1,15 @@ package tests; import sys.FileSystem; -import tools.haxelib.Vcs; -import haxe.unit.TestCase; +import haxe.io.*; +import haxelib.client.Vcs; -class TestVcsNotFound extends TestCase +class TestVcsNotFound extends TestBase { //----------- properties, fields ------------// - static inline var REPO_ROOT = "testing/libraries"; + static inline var REPO_ROOT = "test/libraries"; static inline var REPO_DIR = "vcs-no"; static var CWD:String = null; @@ -25,10 +25,12 @@ class TestVcsNotFound extends TestCase override public function setup():Void { - Sys.setCwd(CWD + "/" + REPO_ROOT); + Sys.setCwd(Path.join([CWD, REPO_ROOT])); - if(!FileSystem.exists(REPO_DIR)) - FileSystem.createDirectory(REPO_DIR); + if(FileSystem.exists(REPO_DIR)) { + deleteDirectory(REPO_DIR); + } + FileSystem.createDirectory(REPO_DIR); Sys.setCwd(REPO_DIR); } @@ -37,6 +39,8 @@ class TestVcsNotFound extends TestCase { // restore original CWD & PATH: Sys.setCwd(CWD); + + deleteDirectory(Path.join([CWD, REPO_ROOT, REPO_DIR])); } //----------------- tests -------------------// @@ -61,9 +65,8 @@ class TestVcsNotFound extends TestCase vcs.clone(vcs.directory, "https://bitbucket.org/fzzr/hx.signal"); assertFalse(true); } - catch(error:Dynamic) + catch(error:VcsError) { - assertTrue(Reflect.isEnumValue(error)); switch(error) { case VcsError.CantCloneRepo(_, repo, stderr): assertTrue(true); @@ -80,9 +83,8 @@ class TestVcsNotFound extends TestCase vcs.clone(vcs.directory, "https://github.com/fzzr-/hx.signal.git"); assertFalse(true); } - catch(error:Dynamic) + catch(error:VcsError) { - assertTrue(Reflect.isEnumValue(error)); switch(error) { case VcsError.CantCloneRepo(_, repo, stderr): assertTrue(true); @@ -96,12 +98,12 @@ class TestVcsNotFound extends TestCase inline function getHg():Vcs { - return new WrongHg(); + return new WrongHg({quiet: true}); } inline function getGit():Vcs { - return new WrongGit(); + return new WrongGit({quiet: true}); } } @@ -109,9 +111,9 @@ class TestVcsNotFound extends TestCase class WrongHg extends Mercurial { - public function new() + public function new(settings:Settings) { - super(); + super(settings); this.directory = "no-hg"; this.executable = "no-hg"; this.name = "Mercurial-not-found"; @@ -141,9 +143,9 @@ class WrongHg extends Mercurial class WrongGit extends Git { - public function new() + public function new(settings:Settings) { - super(); + super(settings); this.directory = "no-git"; this.executable = "no-git"; this.name = "Git-not-found"; diff --git a/extra/haxelib_src/test/tests/integration/TestDev.hx b/extra/haxelib_src/test/tests/integration/TestDev.hx new file mode 100644 index 00000000..57f3811f --- /dev/null +++ b/extra/haxelib_src/test/tests/integration/TestDev.hx @@ -0,0 +1,136 @@ +package tests.integration; + +import haxelib.*; +import IntegrationTests.*; +using IntegrationTests; +import haxe.io.*; + +class TestDev extends IntegrationTests { + function testDev():Void { + { + var r = haxelib(["dev", "Bar", "test/libraries/libBar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertTrue(r.out.indexOf("Bar") >= 0); + assertSuccess(r); + } + + { + var r = haxelib(["path", "Bar"]).result(); + var out = ~/\r?\n/g.split(r.out); + assertEquals( + Path.addTrailingSlash(Path.normalize(sys.FileSystem.fullPath("test/libraries/libBar"))), + Path.addTrailingSlash(Path.normalize(out[0])) + ); + if (clientVer > SemVer.ofString("3.1.0-rc.4")) + assertEquals("-D Bar=1.0.0", out[1]); + else + assertEquals("-D Bar", out[1]); + assertSuccess(r); + } + + { + var r = haxelib(["remove", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") == -1); + } + } + + function testWrongPath():Void { + { + var r = haxelib(["dev", "Bar", "test/libraries/libBar_not_exist"]).result(); + // assertTrue(r.code != 0); //TODO + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + if (clientVer > SemVer.ofString("3.1.0-rc.4")) + assertTrue(r.out.indexOf("Bar") == -1); + } + } + + function testNoHaxelibJson():Void { + { + var r = haxelib(["dev", "Bar", "bin"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") >= 0); + } + + { + var r = haxelib(["path", "Bar"]).result(); + var out = ~/\r?\n/g.split(r.out); + assertEquals( + Path.addTrailingSlash(Path.normalize(sys.FileSystem.fullPath("bin"))), + Path.addTrailingSlash(Path.normalize(out[0])) + ); + if (clientVer > SemVer.ofString("3.1.0-rc.4")) + assertEquals("-D Bar=0.0.0", out[1]); + else + assertEquals("-D Bar", out[1]); + assertSuccess(r); + } + + { + var r = haxelib(["remove", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") == -1); + } + } + + function testClassPath():Void { + { + var r = haxelib(["dev", "UseCp", "test/libraries/UseCp"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "UseCp"]).result(); + assertTrue(r.out.indexOf("UseCp") >= 0); + assertSuccess(r); + } + + { + var r = haxelib(["path", "UseCp"]).result(); + var out = ~/\r?\n/g.split(r.out); + assertEquals( + Path.addTrailingSlash(Path.normalize(sys.FileSystem.fullPath("test/libraries/UseCp/lib/src"))), + Path.addTrailingSlash(Path.normalize(out[0])) + ); + if (clientVer > SemVer.ofString("3.1.0-rc.4")) + assertEquals("-D UseCp=0.0.1", out[1]); + else + assertEquals("-D UseCp", out[1]); + assertSuccess(r); + } + + { + var r = haxelib(["remove", "UseCp"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "UseCp"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("UseCp") == -1); + } + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/tests/integration/TestEmpty.hx b/extra/haxelib_src/test/tests/integration/TestEmpty.hx new file mode 100644 index 00000000..8f75c2b9 --- /dev/null +++ b/extra/haxelib_src/test/tests/integration/TestEmpty.hx @@ -0,0 +1,78 @@ +package tests.integration; + +import haxe.*; +import haxe.io.*; +import haxelib.*; +import IntegrationTests.*; +using IntegrationTests; + +class TestEmpty extends IntegrationTests { + function testEmpty():Void { + // the initial local and remote repos are empty + + var installResult = haxelib(["install", "foo"]).result(); + assertTrue(installResult.code != 0); + + var upgradeResult = haxelib(["upgrade"]).result(); + assertSuccess(upgradeResult); + + var updateResult = haxelib(["update", "foo"]).result(); + // assertTrue(updateResult.code != 0); + + var removeResult = haxelib(["remove", "foo"]).result(); + assertTrue(removeResult.code != 0); + + var upgradeResult = haxelib(["list"]).result(); + assertSuccess(upgradeResult); + + var removeResult = haxelib(["set", "foo", "0.0"], "y\n").result(); + assertTrue(removeResult.code != 0); + + var searchResult = haxelib(["search", "foo"]).result(); + assertSuccess(searchResult); + assertTrue(searchResult.out.indexOf("0") >= 0); + + var infoResult = haxelib(["info", "foo"]).result(); + assertTrue(infoResult.code != 0); + + var userResult = haxelib(["user", "foo"]).result(); + assertTrue(userResult.code != 0); + + var configResult = haxelib(["config"]).result(); + assertSuccess(configResult); + + var pathResult = haxelib(["path", "foo"]).result(); + assertTrue(pathResult.code != 0); + + if (clientVer > SemVer.ofString("3.1.0-rc.4")) { + var versionResult = haxelib(["version"]).result(); + assertSuccess(versionResult); + + var helpResult = haxelib(["help"]).result(); + assertSuccess(helpResult); + } + } + + function testWebsite():Void { + // home page + assertNoError(function() Http.requestUrl(serverUrl)); + + // Haxelib Tags + assertNoError(function() Http.requestUrl(Path.join([serverUrl, "t"]))); + + // All Haxelibs + assertNoError(function() Http.requestUrl(Path.join([serverUrl, "all"]))); + + // Haxelib Contributors + assertNoError(function() Http.requestUrl(Path.join([serverUrl, "u"]))); + + // docs + assertNoError(function() Http.requestUrl(Path.join([serverUrl, "documentation"]))); + assertNoError(function() Http.requestUrl(Path.join([serverUrl, "documentation/using-haxelib"]))); + assertNoError(function() Http.requestUrl(Path.join([serverUrl, "documentation/creating-a-haxelib-package/"]))); + assertNoError(function() Http.requestUrl(Path.join([serverUrl, "documentation/creating-a-haxelib-package/"]))); + + // RSS feed + assertNoError(function() Http.requestUrl(Path.join([serverUrl, "rss"]))); + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/tests/integration/TestInfo.hx b/extra/haxelib_src/test/tests/integration/TestInfo.hx new file mode 100644 index 00000000..c70dcbc0 --- /dev/null +++ b/extra/haxelib_src/test/tests/integration/TestInfo.hx @@ -0,0 +1,66 @@ +package tests.integration; + +import IntegrationTests.*; +using IntegrationTests; + +class TestInfo extends IntegrationTests { + function test():Void { + { + var r = haxelib(["register", bar.user, bar.email, bar.fullname, bar.pw, bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["submit", "test/libraries/libBar.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["info", "Bar"]).result(); + assertSuccess(r); + + assertTrue(r.out.indexOf("Bar") >= 0); + + // license + assertTrue(r.out.indexOf("GPL") >= 0); + + // tags + assertTrue(r.out.indexOf("bar") >= 0); + assertTrue(r.out.indexOf("test") >= 0); + + // versions + assertTrue(r.out.indexOf("1.0.0") >= 0); + } + + { + var r = haxelib(["submit", "test/libraries/libBar2.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["info", "Bar"]).result(); + assertSuccess(r); + + assertTrue(r.out.indexOf("Bar") >= 0); + + // license + assertTrue(r.out.indexOf("MIT") >= 0); + + // tags + assertTrue(r.out.indexOf("bar") >= 0); + assertTrue(r.out.indexOf("test") == -1); + assertTrue(r.out.indexOf("version2") >= 0); + + // versions + assertTrue(r.out.indexOf("1.0.0") >= 0); + assertTrue(r.out.indexOf("2.0.0") >= 0); + } + } + + function testNotExist():Void { + { + var r = haxelib(["info", "Bar"]).result(); + assertTrue(r.code != 0); + } + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/tests/integration/TestList.hx b/extra/haxelib_src/test/tests/integration/TestList.hx new file mode 100644 index 00000000..4810042c --- /dev/null +++ b/extra/haxelib_src/test/tests/integration/TestList.hx @@ -0,0 +1,116 @@ +package tests.integration; + +import haxelib.*; +import IntegrationTests.*; +using IntegrationTests; + +class TestList extends IntegrationTests { + function test():Void { + { + var r = haxelib(["list"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["register", bar.user, bar.email, bar.fullname, bar.pw, bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["submit", "test/libraries/libBar.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["install", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") >= 0); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") >= 0); + assertTrue(r.out.indexOf("[1.0.0]") >= 0); + } + + { + var r = haxelib(["submit", "test/libraries/libBar2.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["update", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") >= 0); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") >= 0); + var pos1 = r.out.indexOf("1.0.0"); + var pos2 = r.out.indexOf("2.0.0"); + assertTrue(pos1 >= 0); + assertTrue(pos2 >= 0); + + if (SemVer.compare(clientVer, SemVer.ofString("3.3.0")) >= 0) { + assertTrue(pos2 >= pos1); + } + } + } + + /** + Make sure the version list is in ascending order, independent of the installation order. + **/ + function testInstallNewThenOld():Void { + { + var r = haxelib(["register", bar.user, bar.email, bar.fullname, bar.pw, bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["submit", "test/libraries/libBar.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["submit", "test/libraries/libBar2.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["install", "Bar", "2.0.0"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["install", "Bar", "1.0.0"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") >= 0); + var pos1 = r.out.indexOf("1.0.0"); + var pos2 = r.out.indexOf("2.0.0"); + assertTrue(pos1 >= 0); + assertTrue(pos2 >= 0); + + if (SemVer.compare(clientVer, SemVer.ofString("3.3.0")) >= 0) { + assertTrue(pos2 >= pos1); + } + } + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/tests/integration/TestSet.hx b/extra/haxelib_src/test/tests/integration/TestSet.hx new file mode 100644 index 00000000..b4336e8f --- /dev/null +++ b/extra/haxelib_src/test/tests/integration/TestSet.hx @@ -0,0 +1,77 @@ +package tests.integration; + +import IntegrationTests.*; +using IntegrationTests; +using StringTools; + +class TestSet extends IntegrationTests { + function test():Void { + { + var r = haxelib(["register", bar.user, bar.email, bar.fullname, bar.pw, bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["submit", "test/libraries/libBar.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["submit", "test/libraries/libBar2.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["search", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") >= 0); + } + + { + var r = haxelib(["install", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("[2.0.0]") >= 0); + } + + { + var r = haxelib(["install", "Bar", "1.0.0"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("[2.0.0]") >= 0); + assertTrue(r.out.indexOf("1.0.0") >= 0); + } + + { + var r = haxelib(["set", "Bar", "1.0.0"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("[1.0.0]") >= 0); + assertTrue(r.out.indexOf("2.0.0") >= 0); + } + + { + var r = haxelib(["set", "Bar", "2.0.0"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("1.0.0") >= 0); + assertTrue(r.out.indexOf("[2.0.0]") >= 0); + } + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/tests/integration/TestSimple.hx b/extra/haxelib_src/test/tests/integration/TestSimple.hx new file mode 100644 index 00000000..cfa7918c --- /dev/null +++ b/extra/haxelib_src/test/tests/integration/TestSimple.hx @@ -0,0 +1,91 @@ +package tests.integration; + +import IntegrationTests.*; +using IntegrationTests; + +class TestSimple extends IntegrationTests { + function testNormal():Void { + { + var r = haxelib(["register", bar.user, bar.email, bar.fullname, bar.pw, bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["submit", "test/libraries/libBar.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["search", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") >= 0); + } + + { + var r = haxelib(["register", foo.user, foo.email, foo.fullname, foo.pw, foo.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["submit", "test/libraries/libFoo.zip", foo.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["search", "Foo"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Foo") >= 0); + } + + { + var r = haxelib(["install", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["install", "Foo"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertTrue(r.out.indexOf("Bar") >= 0); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Foo"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Foo") >= 0); + } + + { + var r = haxelib(["list"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Foo") >= 0); + assertTrue(r.out.indexOf("Bar") >= 0); + } + + { + var r = haxelib(["remove", "Foo"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Foo"]).result(); + assertTrue(r.out.indexOf("Foo") < 0); + assertSuccess(r); + } + + { + var r = haxelib(["remove", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") < 0); + } + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/tests/integration/TestUpdate.hx b/extra/haxelib_src/test/tests/integration/TestUpdate.hx new file mode 100644 index 00000000..ad4463d5 --- /dev/null +++ b/extra/haxelib_src/test/tests/integration/TestUpdate.hx @@ -0,0 +1,69 @@ +package tests.integration; + +import IntegrationTests.*; +using IntegrationTests; +using StringTools; + +class TestUpdate extends IntegrationTests { + function test():Void { + { + var r = haxelib(["register", bar.user, bar.email, bar.fullname, bar.pw, bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["submit", "test/libraries/libBar.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["search", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") >= 0); + } + + { + var r = haxelib(["install", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["update", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("[1.0.0]") >= 0); + } + + { + var r = haxelib(["submit", "test/libraries/libBar2.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["update", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("[2.0.0]") >= 0); + assertTrue(r.out.indexOf("1.0.0") >= 0); + } + + { + var r = haxelib(["remove", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") < 0); + } + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/tests/integration/TestUpgrade.hx b/extra/haxelib_src/test/tests/integration/TestUpgrade.hx new file mode 100644 index 00000000..6226e111 --- /dev/null +++ b/extra/haxelib_src/test/tests/integration/TestUpgrade.hx @@ -0,0 +1,79 @@ +package tests.integration; + +import IntegrationTests.*; +using IntegrationTests; +using StringTools; + +class TestUpgrade extends IntegrationTests { + function test():Void { + { + var r = haxelib(["upgrade"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["register", bar.user, bar.email, bar.fullname, bar.pw, bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["submit", "test/libraries/libBar.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["search", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") >= 0); + } + + { + var r = haxelib(["install", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("[1.0.0]") >= 0); + } + + { + var r = haxelib(["upgrade"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["submit", "test/libraries/libBar2.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["upgrade"], "y\n").result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("[2.0.0]") >= 0); + assertTrue(r.out.indexOf("1.0.0") >= 0); + } + + { + var r = haxelib(["upgrade"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["remove", "Bar"]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["list", "Bar"]).result(); + assertSuccess(r); + assertTrue(r.out.indexOf("Bar") < 0); + } + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/tests/integration/TestUser.hx b/extra/haxelib_src/test/tests/integration/TestUser.hx new file mode 100644 index 00000000..7b0ebda5 --- /dev/null +++ b/extra/haxelib_src/test/tests/integration/TestUser.hx @@ -0,0 +1,49 @@ +package tests.integration; + +import IntegrationTests.*; +using IntegrationTests; + +class TestUser extends IntegrationTests { + function test():Void { + { + var r = haxelib(["register", bar.user, bar.email, bar.fullname, bar.pw, bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["user", "Bar"]).result(); + assertSuccess(r); + + assertTrue(r.out.indexOf("Bar") >= 0); + + assertTrue(r.out.indexOf(bar.email) >= 0); + assertTrue(r.out.indexOf(bar.fullname) >= 0); + assertTrue(r.out.indexOf(bar.pw) == -1); + } + + { + var r = haxelib(["submit", "test/libraries/UseCp.zip", bar.pw]).result(); + assertSuccess(r); + } + + { + var r = haxelib(["user", "Bar"]).result(); + assertSuccess(r); + + assertTrue(r.out.indexOf("Bar") >= 0); + + assertTrue(r.out.indexOf(bar.email) >= 0); + assertTrue(r.out.indexOf(bar.fullname) >= 0); + assertTrue(r.out.indexOf(bar.pw) == -1); + + assertTrue(r.out.indexOf("UseCp") >= 0); + } + } + + function testNotExist():Void { + { + var r = haxelib(["user", "Bar"]).result(); + assertTrue(r.code != 0); + } + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/website/controller/DocumentationControllerTest.hx b/extra/haxelib_src/test/website/controller/DocumentationControllerTest.hx new file mode 100644 index 00000000..9ef2a410 --- /dev/null +++ b/extra/haxelib_src/test/website/controller/DocumentationControllerTest.hx @@ -0,0 +1,48 @@ +package website.controller; + +import website.controller.*; +import ufront.web.result.ViewResult; +import website.Server; +using tink.CoreApi; + +// These imports are common for our various test-suite tools. +import buddy.*; +import mockatoo.Mockatoo.*; +import ufront.test.TestUtils.NaturalLanguageTests.*; +import utest.Assert; +using haxe.io.Path; +using buddy.Should; +using ufront.test.TestUtils; +using mockatoo.Mockatoo; + +class DocumentationControllerTest extends BuddySuite { + public function new() { + + var haxelibSite = WebsiteTests.getTestApp(); + + describe("When viewing documentation", { + it("Should load all pages without errors", function (done) { + var pages = DocumentationController.getDocumentationPages(); + var allResults = []; + for ( url in pages.keys() ) { + var title = pages.get( url ); + var page = + if ( url=="/documentation/" ) null + else url.substr( "/documentation/".length ).removeTrailingSlashes(); + var result = whenIVisit( url ) + .onTheApp( haxelibSite ) + .itShouldLoad( DocumentationController, "documentationPage", [page] ) + .itShouldReturn( ViewResult, function (result) { + Assert.same( TFromEngine("documentation/documentationPage"), result.templateSource ); + Assert.same( TFromEngine("layout.html"), result.layoutSource ); + (result.data['title']:String).should.be('$title - Haxelib Documentation'); + }); + allResults.push( result.result ); + } + + Future.ofMany( allResults ).handle( function() done() ); + }); + }); + + } +} diff --git a/extra/haxelib_src/test/website/controller/HomeControllerTest.hx b/extra/haxelib_src/test/website/controller/HomeControllerTest.hx new file mode 100644 index 00000000..3c9cf8f6 --- /dev/null +++ b/extra/haxelib_src/test/website/controller/HomeControllerTest.hx @@ -0,0 +1,137 @@ +package website.controller; + +import website.api.ProjectListApi; +import website.controller.*; +import ufront.web.result.*; +import ufront.web.result.ViewResult; +import website.Server; +using tink.CoreApi; +import haxelib.server.SiteDb; + +// These imports are common for our various test-suite tools. +import buddy.*; +import mockatoo.Mockatoo.*; +import ufront.test.TestUtils.NaturalLanguageTests.*; +import utest.Assert; +using buddy.Should; +using ufront.test.TestUtils; +using mockatoo.Mockatoo; + +class HomeControllerTest extends BuddySuite { + public function new() { + + var haxelibSite = WebsiteTests.getTestApp(); + var mockApi = mock( ProjectListApi ); + haxelibSite.injector.map( ProjectListApi ).toValue( mockApi ); + mockApi.all().returns( Success(new List()) ); + mockApi.byUser(cast anyString).returns( Success(new List()) ); + mockApi.byTag(cast anyString).returns( Success(new List()) ); + mockApi.search(cast anyString).returns( Success(new List()) ); + mockApi.latest(cast anyInt).returns( Success(new List()) ); + mockApi.getTagList(cast anyInt).returns( Success(new List()) ); + + describe("When I go to the homepage", { + it("Should show our homepage view", function (done) { + + + whenIVisit( "/" ) + .onTheApp( haxelibSite ) + .itShouldLoad( HomeController, "homepage", [] ) + .itShouldReturn( ViewResult, function (result) { + var title:String = result.data['title']; + (result.data['title']:String).should.be("Haxelib - the Haxe package manager"); + Assert.same( result.templateSource, TFromEngine("home/homepage") ); + Assert.same( result.layoutSource, TFromEngine("layout.html") ); + // TODO: check we have a list of popular projects + // TODO: check we have a list of recent projects + }) + .andFinishWith( done ); + }); + // TODO: it("Show me my projects if I am logged in"); + }); + + describe("When I load the tags page", { + it("Should show me a list of the most popular tags, sorted by popularity", function (done) { + whenIVisit( "/t/") + .onTheApp( haxelibSite ) + .itShouldLoad( HomeController, "tagList", [] ) + .itShouldReturn( ViewResult, function(result) { + Assert.same( result.templateSource, TFromEngine("home/tagList") ); + Assert.same( result.layoutSource, TFromEngine("layout.html") ); + // TODO: check that the tags are listed... + }) + .andFinishWith( done ); + }); + }); + + describe("When I load a tag page", { + it("Should show the list of projects with that tag", function (done) { + whenIVisit( "/t/games") + .onTheApp( haxelibSite ) + .itShouldLoad( HomeController, "tag", ["games"] ) + .itShouldReturn( ViewResult, function(result) { + Assert.same( result.templateSource, TFromEngine("home/projectList.html") ); + Assert.same( result.layoutSource, TFromEngine("layout.html") ); + // TODO: check that the matching projects are correct + }) + .andFinishWith( done ); + }); + }); + + describe("When I load the 'all projects' page", { + it("Should show them all", function (done) { + whenIVisit( "/all") + .onTheApp( haxelibSite ) + .itShouldLoad( HomeController, "all", [] ) + .itShouldReturn( ViewResult, function(result) { + Assert.same( result.templateSource, TFromEngine("home/projectList.html") ); + Assert.same( result.layoutSource, TFromEngine("layout.html") ); + // TODO: check that all projects are loaded + }) + .andFinishWith( done ); + }); + }); + + describe("When I search", { + // TODO: ask Nicolas, should we just use Google? +// it("Should show me the search form if there is no search term entered"); +// it("Should show projects matching the name"); +// it("Should show projects matching the description"); +// it("Redirect straight to the project page if there's only 1 search result"); + }); + + describe("When I want to access the data through a JSON API", { + it("Should give me search via JSON", function (done) { + whenIVisit( "/search.json" ) + .withTheQueryParams([ "v"=>"web" ]) + .onTheApp( haxelibSite ) + .itShouldLoad( HomeController, "searchJson", [{ v: "web" }] ) + .itShouldReturn( JsonResult, function (result) { + // TODO: check the data is good. + // TODO: check the JSON is valid. + }) + .andFinishWith( done ); + }); + it("Should give me tags via JSON", function (done) { + whenIVisit( "/t/games.json" ) + .onTheApp( haxelibSite ) + .itShouldLoad( HomeController, "tag", ["games.json"] ) + .itShouldReturn( JsonResult, function (result) { + // TODO: check the data is good. + // TODO: check the JSON is valid. + }) + .andFinishWith( done ); + }); + it("Should give me all via JSON", function (done) { + whenIVisit( "/all.json" ) + .onTheApp( haxelibSite ) + .itShouldLoad( HomeController, "allJson", [] ) + .itShouldReturn( JsonResult, function (result) { + // TODO: check the data is good. + // TODO: check the JSON is valid. + }) + .andFinishWith( done ); + }); + }); + } +} diff --git a/extra/haxelib_src/test/website/controller/ProjectControllerTest.hx b/extra/haxelib_src/test/website/controller/ProjectControllerTest.hx new file mode 100644 index 00000000..208199b3 --- /dev/null +++ b/extra/haxelib_src/test/website/controller/ProjectControllerTest.hx @@ -0,0 +1,158 @@ +package website.controller; + +import haxe.io.Bytes; +import website.api.ProjectApi; +import website.controller.*; +import ufront.web.result.*; +import ufront.web.result.ViewResult; +import website.Server; +import haxe.ds.Option; +using tink.CoreApi; + +// These imports are common for our various test-suite tools. +import buddy.*; +import mockatoo.Mockatoo.*; +import ufront.test.TestUtils.NaturalLanguageTests.*; +import utest.Assert; +using buddy.Should; +using ufront.test.TestUtils; +using mockatoo.Mockatoo; + +class ProjectControllerTest extends BuddySuite { + public function new() { + + var haxelibSite = WebsiteTests.getTestApp(); + var mockApi = mock( ProjectApi ); + haxelibSite.injector.map( ProjectApi ).toValue( mockApi ); + mockApi.projectInfo(cast anyString).returns( Success({ + name: "detox", + desc: "Detox Description", + website: "https://github.com/jasononeil/detox", + owner: "jason", + license: "MIT", + curversion: "1.0.0-rc.8", + versions: [{ date: "2010-01-01 34:56:12", name:"1.0.0-rc.8", downloads:150, comments:"Breaking changes everywhere." }], + tags: new List(), + }) ); + mockApi.readContentFromZip(cast anyString, cast anyString, cast anyString).returns( Success(Some("content")) ); + mockApi.readBytesFromZip(cast anyString, cast anyString, cast anyString).returns( Success(Some(Bytes.ofString(""))) ); + mockApi.getInfoForPath(cast anyString, cast anyString, cast anyString).returns( Success(Binary(12)) ); + + describe("When I view a project", { + it("Should show the project view for the latest version", function (done) { + whenIVisit( "/p/detox" ) + .onTheApp( haxelibSite ) + .itShouldLoad( ProjectController, "project", ["detox"] ) + .itShouldReturn( ViewResult, function (result) { + // TODO: Check we got the latest version. + // TODO: Check we got the correct project. + Assert.same( TFromEngine("project/version.html"), result.templateSource ); + Assert.same( TFromEngine("layout.html"), result.layoutSource ); + }) + .andFinishWith( done ); + }); + }); + + describe("When I view a project version", { + + var whenILoadAProjectVersion = whenIVisit( "/p/detox/1.0.0-rc.8/" ).onTheApp( haxelibSite ); + it("Should load the correct layout / view", function (done) { + whenILoadAProjectVersion + .itShouldLoad( ProjectController, "version", ["detox","1.0.0-rc.8"] ) + .itShouldReturn( ViewResult, function(result) { + Assert.same( TFromEngine("project/version.html"), result.templateSource ); + Assert.same( TFromEngine("layout.html"), result.layoutSource ); + }).andFinishWith( done ); + }); + it("Should show me the README for the current version", function (done) { + whenILoadAProjectVersion.itShouldReturn( ViewResult, function(result) { + // TODO: add appropriate tests here... + }).andFinishWith( done ); + }); + it("Should show me the file list for the current version", function (done) { + whenILoadAProjectVersion.itShouldReturn( ViewResult, function(result) { + // TODO: add appropriate tests here... + }).andFinishWith( done ); + }); + it("Should show me a list of all versions", function (done) { + whenILoadAProjectVersion.itShouldReturn( ViewResult, function(result) { + // TODO: add appropriate tests here... + }).andFinishWith( done ); + }); + it("Should show me the haxelibs this depends on", function (done) { + whenILoadAProjectVersion.itShouldReturn( ViewResult, function(result) { + // TODO: add appropriate tests here... + }).andFinishWith( done ); + }); + it("Should show me the haxelibs that depend on this", function (done) { + whenILoadAProjectVersion.itShouldReturn( ViewResult, function(result) { + // TODO: add appropriate tests here... + }).andFinishWith( done ); + }); + it("Should let me know if there is a more recent version", function (done) { + whenILoadAProjectVersion.itShouldReturn( ViewResult, function(result) { + // TODO: add appropriate tests here... + }).andFinishWith( done ); + }); + it("Should let me know if this version is not considered stable", function (done) { + whenILoadAProjectVersion.itShouldReturn( ViewResult, function(result) { + // TODO: add appropriate tests here... + }).andFinishWith( done ); + }); + }); + + describe("When I view a project's versions", { + it("Should show me a list of all the versions of that project, with the ability to show stable releases only.", function(done) { + whenIVisit( "/p/detox/versions" ) + .onTheApp( haxelibSite ) + .itShouldLoad( ProjectController, "versionList", ["detox"] ) + .itShouldReturn( ViewResult, function (result) { + // TODO: Check it shows the list of versions. + }) + .andFinishWith( done ); + }); + }); + + describe("When I view a project's files", { + it("Should show me that file's source code in line", function (done) { + whenIVisit( "/p/detox/1.0.0-rc.8/files/src/Detox.hx" ) + .onTheApp( haxelibSite ) + .itShouldLoad( ProjectController, "file", ["detox","1.0.0-rc.8",["src","Detox.hx"]] ) + .itShouldReturn( ViewResult, function (result) { + // TODO: Check it shows the source code for the file. + }) + .andFinishWith( done ); + }); + it("Should render markdown files as HTML", function (done) { + whenIVisit( "/p/detox/1.0.0-rc.8/files/README.md" ) + .onTheApp( haxelibSite ) + .itShouldLoad( ProjectController, "file", ["detox","1.0.0-rc.8",["README.md"]] ) + .itShouldReturn( ViewResult, function (result) { + // TODO: Check it shows the rendered markdown. + }) + .andFinishWith( done ); + }); + it("Should show binary files size and a link to download it", function (done) { + whenIVisit( "/p/hxssl/3.0.0-alpha/files/ndll/Linux64/hxssl.ndll" ) + .onTheApp( haxelibSite ) + .itShouldLoad( ProjectController, "file", ["hxssl","3.0.0-alpha",["ndll","Linux64","hxssl.ndll"]] ) + .itShouldReturn( ViewResult, function (result) { + // TODO: Check it shows the file name and download size. + }) + .andFinishWith( done ); + }); + }); + + describe("When I view a projects docs", { + it("Should show the correct documentation for this version", function(done) { + whenIVisit( "/p/detox/1.0.0-rc.8/doc/dtx.widget.Widget" ) + .onTheApp( haxelibSite ) + .itShouldLoad( ProjectController, "docs", ["detox","1.0.0-rc.8","dtx.widget.Widget"] ) + .itShouldReturn( ViewResult, function (result) { + // TODO: Check it loads the correct view, documentation is rendered, etc. + }) + .andFinishWith( done ); + }); + }); + } +} diff --git a/extra/haxelib_src/test/website/controller/RSSControllerTest.hx b/extra/haxelib_src/test/website/controller/RSSControllerTest.hx new file mode 100644 index 00000000..1a1a206a --- /dev/null +++ b/extra/haxelib_src/test/website/controller/RSSControllerTest.hx @@ -0,0 +1,46 @@ +package website.controller; + +import website.controller.*; +import ufront.web.result.*; +import website.Server; + +// These imports are common for our various test-suite tools. +import buddy.*; +import mockatoo.Mockatoo.*; +import ufront.test.TestUtils.NaturalLanguageTests.*; +import utest.Assert; +using buddy.Should; +using ufront.test.TestUtils; +using mockatoo.Mockatoo; + +class RSSControllerTest extends BuddySuite { + public function new() { + + var haxelibSite = WebsiteTests.getTestApp(); + + describe("When I try to view the RSS feed", { + it("Should give me some valid XML with the latest updates", function (done) { + whenIVisit( "/rss" ) + .onTheApp( haxelibSite ) + .itShouldLoad( RSSController, "rss", [{number:null}] ) + .itShouldReturn( ContentResult, function (result) { + result.contentType.should.be( "text/xml" ); + var rss = Xml.parse( result.content ); + }) + .andFinishWith( done ); + }); + it("Should let me set the number of entries to include", function (done) { + whenIVisit( "/rss" ) + .withTheQueryParams([ "number"=>"3" ]) + .onTheApp( haxelibSite ) + .itShouldLoad( RSSController, "rss", [{number:3}] ) + .itShouldReturn( ContentResult, function (result) { + result.contentType.should.be( "text/xml" ); + var rss = Xml.parse( result.content ); + // TODO: check that 3 results were loaded. + }) + .andFinishWith( done ); + }); + }); + } +} \ No newline at end of file diff --git a/extra/haxelib_src/test/website/controller/UserControllerTest.hx b/extra/haxelib_src/test/website/controller/UserControllerTest.hx new file mode 100644 index 00000000..3f0240df --- /dev/null +++ b/extra/haxelib_src/test/website/controller/UserControllerTest.hx @@ -0,0 +1,73 @@ +package website.controller; + +import haxe.crypto.Md5; +import haxelib.server.SiteDb; +import website.controller.*; +import website.api.UserApi; +import ufront.web.result.*; +import ufront.web.result.ViewResult; +import website.Server; +using tink.CoreApi; + +// These imports are common for our various test-suite tools. +import buddy.*; +import mockatoo.Mockatoo.*; +import ufront.test.TestUtils.NaturalLanguageTests.*; +import utest.Assert; +using buddy.Should; +using ufront.test.TestUtils; +using mockatoo.Mockatoo; + +class UserControllerTest extends BuddySuite { + public function new() { + + var haxelibSite = WebsiteTests.getTestApp(); + var mockApi = mock( UserApi ); + haxelibSite.injector.map( UserApi ).toValue( mockApi ); + + function mockUser(user,name,email) { + var u = new User(); + u.name = user; + u.fullname = name; + u.email = email; + var hash = Md5.encode( email ); + return { user:u, emailHash:hash, projects:[], totalDownloads:[] }; + } + var user1 = mockUser( "jason", "Jason O'Neil", "jason@example.org" ); + var user2 = mockUser( "ncanasse", "Nicolas Canasse", "nc@example.org" ); + var projects = []; + + mockApi.getUserProfile(cast anyString).returns( Success(new Pair(user1.user,[])) ); + mockApi.getUserList().returns( Success([user1, user2]) ); + + describe("When I look at the profile of a user", { + it("Should show me that users profile and their projects", function (done) { + whenIVisit( "/u/jason" ) + .onTheApp( haxelibSite ) + .itShouldLoad( UserController, "profile", ["jason"] ) + .itShouldReturn( ViewResult, function (result) { + var title:String = result.data['title']; + (result.data['title']:String).should.be("jason (Jason O'Neil) on Haxelib"); + Assert.same( result.templateSource, TFromEngine("user/profile") ); + Assert.same( result.layoutSource, TFromEngine("layout.html") ); + }) + .andFinishWith( done ); + }); + }); + + describe("When I want to see a list of users", { + it("Should show me that list, sorted by number of projects", function (done) { + whenIVisit( "/u" ) + .onTheApp( haxelibSite ) + .itShouldLoad( UserController, "list", [] ) + .itShouldReturn( ViewResult, function (result) { + var title:String = result.data['title']; + (result.data['title']:String).should.be("Haxelib Contributors"); + Assert.same( result.templateSource, TFromEngine("user/list") ); + Assert.same( result.layoutSource, TFromEngine("layout.html") ); + }) + .andFinishWith( done ); + }); + }); + } +} diff --git a/extra/haxelib_src/testing/PrepareServer.hx b/extra/haxelib_src/testing/PrepareServer.hx deleted file mode 100644 index 9163b6a3..00000000 --- a/extra/haxelib_src/testing/PrepareServer.hx +++ /dev/null @@ -1,131 +0,0 @@ -package; - -import haxe.crypto.Crc32; -import haxe.io.BytesInput; -import haxe.remoting.HttpConnection; -import haxe.zip.Entry; -import haxe.zip.Writer; -import sys.db.Sqlite; -import sys.FileSystem; -import sys.io.File; -import tools.haxelib.SiteDb; - -using StringTools; - -class SiteProxy extends haxe.remoting.Proxy { -} - -class PrepareServer { - - - static function deleteFolderContent(path:String) { - for (file in FileSystem.readDirectory(path)) { - var fullPath = path + '/' + file; - if (FileSystem.isDirectory(fullPath)) { - deleteFolderContent(fullPath); - FileSystem.deleteDirectory(fullPath); - } - else { - FileSystem.deleteFile(fullPath); - } - } - } - - static function getFileList(path:String):List { - var list = new List(); - for (file in FileSystem.readDirectory(path)) { - if (FileSystem.isDirectory(path + '/' + file)) { - for (sFile in getFileList(path + '/' + file)) { - list.add(file + '/' + sFile); - } - } - else { - list.add(file); - } - } - return list; - } - - static function packageLibrary(path:String) { - var files = getFileList(path); - var fileName = path + '.zip'; - if (FileSystem.exists(fileName)) - FileSystem.deleteFile(fileName); - var output = File.write(path + '.zip', true); - var writer = new Writer(output); - var entries = new List(); - for (file in files) { - var data = File.getBytes(path + '/' + file); - entries.add({ - fileTime: Date.now(), - compressed: false, - data: data, - crc32: Crc32.make(data), - dataSize: data.length, - fileName: file, - fileSize: 0 - }); - } - writer.write(entries); - output.flush(); - output.close(); - - } - - static function main() { - Sys.println("Cleaning up folders"); - var serverPath = Sys.getCwd() + 'server/'; - if (FileSystem.exists(serverPath + 'files') && FileSystem.isDirectory(serverPath + 'files')) - deleteFolderContent(serverPath + 'files'); - if (FileSystem.exists(serverPath + 'tmp') && FileSystem.isDirectory(serverPath + 'tmp')) - deleteFolderContent(serverPath + 'tmp'); - - Sys.println("Cleaning legacy DB"); - var sqlFile = serverPath + 'legacy/haxelib.db'; - var con = Sqlite.open(sqlFile); - tools.legacyhaxelib.SiteDb.create(con); - - Sys.println("Package testing libraries"); - var libraries = new List(); - var testFolder = Sys.getCwd() + 'testing/'; - for (file in FileSystem.readDirectory(testFolder + 'libraries')) { - if (FileSystem.isDirectory(testFolder + 'libraries/' + file) && file.startsWith('lib')) { - packageLibrary(testFolder + 'libraries/' + file); - Sys.println("Packaged libray: " + file.substr(3)); - libraries.push(file.substr(3)); - } - } - - Sys.println("Submitting test libraries"); - try { - var sites = [ - 'legacy' => 'http://localhost:2000/', - '2.0.0-rc' => 'http://localhost:2000/api/2.0.0-rc/', - ]; - for (siteName in sites.keys()) { - trace('Test $siteName on ' + sites.get(siteName)); - var site = new SiteProxy(HttpConnection.urlConnect(sites.get(siteName)).api); - for (library in libraries) { - Sys.println("Submitting library: " + library); - site.register(library, library, library+'@example.org', library + ' Developer'); - // TODO: This is not how haxelib usually behave, do we need dependencies checks and all the other stuff? - site.checkDeveloper(library, library); - var libraryFile = testFolder + 'libraries/lib' + library + '.zip'; - var data = File.getBytes(libraryFile); - var id = site.getSubmitId(); - var h = new haxe.Http('http://localhost:2000/'); - h.fileTransfert("file", id, new BytesInput(data), data.length); - h.request(true); - site.processSubmit(id, library, library); - //FileSystem.deleteFile(libraryFile); - } - } - } - catch (e:Dynamic) { - Sys.println("There was a problem submitting test libraries to the local haxelib server. Make sure it is running."); - Sys.println(e); - Sys.exit(1); - } - - } -} \ No newline at end of file diff --git a/extra/haxelib_src/testing/installSeveral.hxml b/extra/haxelib_src/testing/installSeveral.hxml deleted file mode 100644 index f3768e5d..00000000 --- a/extra/haxelib_src/testing/installSeveral.hxml +++ /dev/null @@ -1,3 +0,0 @@ --lib hxcpp --lib hxcs --lib hxjava diff --git a/extra/haxelib_src/src/tools/haxelib/.htaccess b/extra/haxelib_src/www/.htaccess similarity index 67% rename from extra/haxelib_src/src/tools/haxelib/.htaccess rename to extra/haxelib_src/www/.htaccess index e3aab222..b9b20dd8 100644 --- a/extra/haxelib_src/src/tools/haxelib/.htaccess +++ b/extra/haxelib_src/www/.htaccess @@ -4,6 +4,14 @@ DirectoryIndex index.n index.php index.html RewriteEngine On +# /files are stored in S3 + +RewriteBase / +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{ENV:HAXELIB_S3BUCKET} !^$ +RewriteCond %{ENV:AWS_DEFAULT_REGION} !^$ +RewriteRule "^files/(.*)$" "http://%{ENV:HAXELIB_S3BUCKET}.s3-%{ENV:AWS_DEFAULT_REGION}.amazonaws.com/files/$1" [P] + # Rewrite rules to send Haxe remoting calls on "/" to "haxelib1/". If it matches, that's [L], the last rule - go their immediately. RewriteBase / diff --git a/extra/haxelib_src/www/bower.json b/extra/haxelib_src/www/bower.json new file mode 100644 index 00000000..730bbc82 --- /dev/null +++ b/extra/haxelib_src/www/bower.json @@ -0,0 +1,23 @@ +{ + "name": "haxelib-server", + "homepage": "https://github.com/HaxeFoundation/haxelib", + "description": "Haxelib server", + "keywords": [ + "haxe", + "haxelib" + ], + "license": "MIT", + "private": true, + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "dependencies": { + "jquery": "^1.12.2", + "bootstrap": "^3.3.6", + "font-awesome": "^4.5.0" + } +} diff --git a/extra/haxelib_src/www/css/haxelib.css b/extra/haxelib_src/www/css/haxelib.css new file mode 100644 index 00000000..3cf8004a --- /dev/null +++ b/extra/haxelib_src/www/css/haxelib.css @@ -0,0 +1,164 @@ +html, body{ + height:100%; +} +body { + padding: 0; + margin:0; + min-height:100%; + font-size:16px; + font-family:"Open Sans", sans-serif; + color: #1e1e1e; + line-height: 1.5; +} +h1, h2, h3, h4, h5, h6 { + font-family: "Source Sans Pro", sans-serif; + font-weight: 600; + word-wrap: break-word; +} +h1 { + font-size: 36px; + color: #171717; +} +h1 small { + font-size: 14px; + color: #999; + font-weight: normal; +} +h2 { + font-size: 30px; +} +h3 { + font-size: 24px; +} +h4 { + font-size: 20px; +} +h5, h5 code { + font-size: 18px; +} +h6 { + font-size: 16px; +} +html pre, html pre code { + font-family: "Source Code Pro", "Courier New"; + font-size: 14px; + line-height: 20px; + white-space: pre; + overflow-x: auto; +} +pre, div.pre { + color: #333; + background-color: #f3f3f3; + border: 1px solid #bbb; + margin: 15px; + padding: 5px; + padding-left: 20px; +} + +code { + font-family: Monaco,Menlo,Consolas,"Courier New",monospace; + font-weight: normal; + color: #666; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; + white-space: nowrap; + border-radius: 3px; + padding: 2px 4px; + font-size: 13px; +} +code .identifier, code.type { + font-weight: bold; +} + +code a { text-decoration:none; } +code a:hover { text-decoration:underline; } + +.navbar { margin:0 0 20px 0; padding:0; color:#fff; } +.navbar .tagline { position:relative; top:11px; } +.navbar .brand { padding: 7px 20px 7px;} +.navbar .pull-right { position:relative; top:8px; } +.navbar .pull-right a {color: #F48821;} + +.dark { + background: rgb(20,20,25); + color: white; +} +.dark a { + color: white; +} +.dark a:hover { + color: rgb(200,200,200); +} +.dark blockquote { + border-left: 3px solid rgb(126,126,129); +} +.dark blockquote small { + color: white; + font-weight: bold; +} +.dark blockquote small:before { + display: none; +} + +footer{ + margin-top:40px; + font-size:12px; + padding: 10px; +} +.copyright { + padding: 6px; + overflow: hidden; + text-align:center; + margin: 40px 0; +} +.dark .copyright .hf-link { color:#F48821; } + +.legacy-notice { + border : 1px solid #AAA; + padding: 10px; + margin: 10px; +} + +li {line-height:1.5} + +.clear { + clear : both; +} + +.list-unstyled { + list-style:none; + margin-left:0; +} + +.menu ul i.fa { + color: rgb(200,200,200); + font-weight: normal; + font-size: 16px; +} +.menu .badge { + border:1px solid rgb(180,180,180); + background:transparent; + color: rgb(180,180,180); + font-weight: normal; +} + +.input-append .add-on, .input-prepend .add-on {background: #F48821;} +.well h1 {margin-top:0} +.well table, .well p.lead { margin-bottom: 0; } + +.avatar { + margin-right:40px; +} + +.navbar .nav>li:nth-child(2){ + margin-left:40px; +} +.navbar .nav>li>a { + color: #F48821; + text-shadow:none; +} +.navbar .nav>li>a:hover { + color: #F48821; + text-decoration:underline; + text-shadow:none; +} diff --git a/extra/haxelib_src/www/css/style.css b/extra/haxelib_src/www/css/style.css new file mode 100644 index 00000000..13d44178 --- /dev/null +++ b/extra/haxelib_src/www/css/style.css @@ -0,0 +1,741 @@ +/** + Sticky Footer +**/ +* { + margin: 0; +} +html, body { + height: 100%; +} +.page-wrap { + min-height: 100%; + margin-bottom: -36px; /* equal to footer height */ +} +.page-wrap:after { + content: ""; + display: block; +} +.site-footer, .page-wrap:after { + /* .push must be the same height as footer */ + min-height: 36px; +} +.site-footer .hf-link { + color: rgb(234,130,32) !important; +} + +/** + Responsive fixes +**/ +@media (min-width: 1200px) { + .hidden-desktop-large { + display: none !important; + } +} +@media (max-width: 1199px) { + .visible-desktop-large { + display: none !important; + } +} +@media (max-width: 767px) { + body { + padding-left: 0px !important; + padding-right: 0px !important; + } + .container { + padding-left: 20px; + padding-right: 20px; + width: auto; + margin: 0; + } + .section .row.component .title { + text-align: left !important; + } + .section .row.component .links { + margin-top: 20px; + } + .navbar-fixed-top, .navbar-fixed-bottom, .navbar-static-top { + margin: 0 0 20px 0 !important; + } + ul.logos { + margin-top: 20px; + } +} + +/** + Main styles +**/ +body { + font-family: "Open Sans", sans-serif; + font-weight: 400; + font-size: 16px; + color: #1e1e1e; +} +b, strong { + font-weight: 700; +} +a { + color: #3369bc; +} +a[href="#"] { + /** Non-existent link **/ + color: red; + cursor: default; + text-decoration: none; +} +body, body p, body td, body li { + line-height: 1.5; +} +body p, body li p, body td p { + margin-bottom: 12px; +} +body li { + margin-bottom: 2px; + padding-left: 10px; +} +body li ul { + margin-top: 2px; +} +body li p { + margin-bottom: 10px; +} +h1, h2, h3, h4, h5, h6 { + font-family: "Source Sans Pro", sans-serif; + font-weight: 600; +} +h3, h4, h5 { + margin-top: 25px; +} +h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { + color: inherit; + text-decoration: underline; +} +h1 { + font-size: 36px; + color: #171717; +} +h1 small { + display: block; + font-size: 50px; + color: #a1a1a1; + font-weight: 200; +} +h2 { + font-size: 30px; +} +h3 { + font-size: 24px; +} +h4 { + font-size: 20px; +} +h5, h5 code { + font-size: 18px; +} +h6 { + font-size: 16px; +} +a.anch { + position: relative; + top: -30px; +} +.section .container { + position: relative; + padding-top: 30px; + padding-bottom: 40px; +} +.section .container > :first-child { + margin-top: 0px; +} +.section .container > :last-child { + margin-bottom: 0px; +} +.section blockquote { + margin: 20px 20px 20px 20px; + padding: 0 20px; +} +.homepage .section blockquote { + padding: 10px 20px; +} +@media (min-width: 979px) { + .homepage .section blockquote { + margin: 100px 20px 100px 20px; + } +} +.section .row.component { + margin-bottom: 20px; +} +.section .row.component .title { + text-align: right; + font-weight: 400; +} + +.section.head .btn-haxe { + font-size: 26.5px; + border-radius: 9px; + position: relative; + bottom: 3px; + background: none; + box-shadow: none; + border: 2px solid rgb(234, 130, 32); + color: rgb(234, 130, 32); + width: 204px; + height: 54px; + line-height: 54px; + text-shadow: none; + padding-right: 33px; /* 12px default + some space for our caret */ +} +.section.head .btn-haxe:hover, .section.head .btn-haxe:active { + color: rgb(208, 116, 28); + border-color: rgb(208, 116, 28); + background: rgba(0,0,0,0.1); +} +.section.head .btn-haxe .fa { + position: absolute; + right: 15px; + top: 23px; + font-size: 16px; +} + + +.copyright { + text-align: center; +} +.site-footer, .site-footer .container { + font-size: 12px; + padding: 0; +} +.section.nav { + margin-bottom: 0; +} +.section.nav .container { + padding: 0; +} +.page-wrap .section:first-child .container { + padding-top: 80px; +} + +/** + Billboard / head on homepage +**/ +@media (max-width: 979px) { + .head .head-logo { + margin: 0 auto; + } + .head { + text-align: center; + } + .head .btn-toolbar .btn { + display: block; + margin: 10px auto 10px; + } + .head .btn-toolbar .logo { + display: block; + margin: 10px auto 30px; + } +} +@media (min-width: 768px) { +} +@media (min-width: 980px) { + .head .head-content .btn-toolbar .btn { + vertical-align: baseline; + } + .head .head-logo { + } + .head .head-content { + width: 50%; + margin: 0 auto 30px; + text-align:center; + } + .head .btn-toolbar { + width: 754px; /* 230px logo + 232px buttons*2 + 20px padding between each */ + position: relative; + margin: 0 auto; + } + .head .btn-toolbar .btn { + position: absolute; + top: 85px; + } + .head .btn-toolbar .download { + left: 0; + } + .head .btn-toolbar .learn-more { + right: 0; + } + .head .btn-toolbar .logo { + display: block; + margin: 0 auto; + } +} +@media (min-width: 1200px) { + .head .head-content { + position: relative; + } +} +.section.dark.head { + /* fallback */ + background-color: rgb(168,75,56); + background-repeat: no-repeat; + + /* Safari 4-5, Chrome 1-9 */ + background: -webkit-gradient(radial, 50% 80%, 0, center center, 100, from(rgb(183,77,49)), to(rgb(100,33,38))); + /* Safari 5.1+, Chrome 10+ */ + background: -webkit-radial-gradient(50% 80%, circle, rgb(183,77,49), rgb(100,33,38)); + /* Firefox 3.6+ */ + background: -moz-radial-gradient(50% 80%, circle, rgb(183,77,49), rgb(100,33,38)); + /* IE 10 */ + background: -ms-radial-gradient(50% 80%, circle, rgb(183,77,49), rgb(100,33,38)); +} +.head .head-logo { + display: block; + width: 230px; + max-width: 100%; +} +.head .head-content h1 { + font-weight: bold; + text-shadow: 0px 1px 0px rgb(88,27,32); + color: white; +} +.head .head-content .lead { +} +.sub-head .container { + padding-bottom: 30px; +} +@media (min-width: 979px) { + .homepage .section.sub-head blockquote { + margin: 120px 20px 60px 20px; + } +} +.target-logos { + width: 450px; + margin: 10px auto; + display: block; +} + + +.section p.tag-line { + margin-top: 20px; + font-weight: 200; + font-size: 18px; +} + + +/** + Prev / Next links +**/ +.prev-next-links { + clear: both; + text-align: center; +} +.prev-next-links.top { + border-bottom: #DDD solid 1px; + padding-bottom: 10px; + margin-bottom: 20px; +} +@media (min-width: 980px) { + .prev-next-links.top { + margin-top: -30px !important; + } +} +.prev-next-links.bottom { + border-top: #DDD solid 1px; + padding-top: 10px; + margin-top: 20px; +} +.prev-link { + float: left; +} +.prev-link:before { + content: "« "; +} +.next-link { + float: right; +} +.next-link:after { + content: " »"; +} + +/** + Code Highlighting +**/ + +html pre, html pre code { + font-family: "Source Code Pro", "Courier New"; + font-size: 14px; + line-height: 20px; + white-space: pre; + overflow-x: auto; +} +pre, div.pre { + color: #333; + background-color: #f3f3f3; + border: 1px solid #bbb; + margin: 15px; + padding: 5px; + padding-left: 20px; +} +pre .kwd, div.pre .kwd { + color: #008; +} +pre .val, div.pre .val { + color: #448; +} +pre .str, div.pre .str { + color: #800; +} +pre .cmt, div.pre .cmt { + color: #080; +} +/* Make sure keywords inside comments are not highlighted*/ +pre .cmt .kwd, pre .cmt .str, pre .cmt .val { + color: #080; +} + +/** + Icon headers +**/ +.header .fa { + font-size: 48px; + text-align: center; + display: block; + margin: 10px 0 30px; + color: rgb(200,200,200); + cursor: default; +} +.header a.fa { + text-decoration: none; + cursor: pointer; +} +.header a.fa:hover { + color: #3369BC; + text-decoration: none; +} + +/** + Manual / API nav +**/ +.tree-nav h5 { + color: rgb(130,130,130); + font-weight: 200; +} +.tree-nav ul { + list-style: none; + margin-left: 0; +} +.tree-nav li { + height: 24px; + overflow: hidden; +} +.tree-nav li i.fa { + height: 16px; + width: 16px; + margin-right:5px; + margin-bottom: 5px; + color: rgb(200,200,200); +} +.tree-nav li i.fa:hover { + color: rgb(150,150,150); +} +.tree-nav li > i.fa:before { + content: "\f016"; /* fa-file-o */ + cursor: pointer; +} +.tree-nav li.parent > i.fa:before { + content: "\f18e"; /* fa-arrow-circle-o-right */ + cursor: pointer; +} +.tree-nav li.parent.active { + height: auto; + overflow: auto; +} +.tree-nav li.parent.active > i.fa:before { + content: "\f01a"; /* fa-arrow-circle-o-down */ + cursor: pointer; +} +.tree-nav a.active { + font-weight: bold; +} +.tree-nav li ul { + margin-left: 10px; + display: none; +} +.tree-nav li.active > ul { + margin-left: 10px; + display: block; +} +.tree-nav li { + text-overflow: ellipsis; + white-space: nowrap; +} + +/** + Misc +**/ + +html code { + color: rgb(75,75,75) +} +.download-source { + margin-top: 16px; +} +.prev-next-links+p { + margin-top: 20px; +} +.nav-stacked > li { + overflow: hidden; +} +.nav-stacked li a i.fa { + color: rgb(200,200,200); + margin-right: 7px; +} +table.table.table-bordered.features, table.table.table-bordered.features td, table.table.table-bordered.features th { + /*border-color: rgb(40,40,40);*/ + /*background: rgb(30,30,30);*/ +} +.site-content ul ul, .site-content ul ol, .site-content ol ol, .site-content ol ul { + margin-bottom: 10px; +} +.tree-nav ul ul, .tree-nav ul ol, .tree-nav ol ol, .tree-nav ol ul { + margin-bottom: 0px; +} + +/** + Pull-out blockquotes +**/ +.site-content blockquote { + position: relative; + padding-left: 45px; + border-left: 0; +} +.site-content blockquote:before { + display: block; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + font-size: 30px; + width: 35px; + height: 100%; + position: absolute; + left: 0px; + top: 0; + bottom: 0; +} +blockquote.define:before { + border-right: 3px solid rgb(247, 148, 30); + content: "\f05a"; /*fa-info.circle*/ + color: rgb(247, 148, 30); +} +blockquote.trivia:before { + border-right: 3px solid rgb(190, 190, 190); + content: "\f02d"; /*fa-book*/ + color: rgb(190, 190, 190); +} + +/** + Search +**/ +.navbar-form .form-control { + height: auto; +} +.gsc-search-box input.gsc-search-button { + color: white; +} +.gsc-search-box input.gsc-search-button:hover { + background: rgb(244, 136, 33); +} +.gsc-search-box input.gsc-search-button { + border: 1px solid rgb(244, 136, 33); + background: rgb(244, 136, 33); + border-radius: 5px; + display: inline-block; + color: white; + padding: 6px 18px; + margin-top: 0px !important; + text-decoration: none; + text-shadow: none; + font-size: 8pt; +} +html td.gsc-search-button { + width: 50px; +} +html input.gsc-input, html input.gsc-input:focus { + font-size: inherit; + box-shadow: none; + transition: none; + position: relative; + top: -3px; +} +.gsc-input-box .gsib_b .gsst_b { + position: relative; + top: 2px; +} +html .gsc-search-box-tools .gsc-search-box .gsc-input { + padding-right: 0px; +} +html .gsc-search-box-tools .gsc-search-box .gsc-input .gsc-input-box { + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; + border: 1px solid rgb(244, 136, 33); + border-right: none; +} +html .gsc-search-box-tools .gsc-search-box td.gsc-search-button input.gsc-search-button, +html .gsc-search-box-tools .gsc-search-box td.gsc-search-button input.gsc-search-button:hover { + border-radius: 0px 5px 5px 0px; + border-left: none; + margin-left: 0; +} +html .cse input.gsc-search-button:hover, html input.gsc-search-button:hover { + border-color: rgb(244, 136, 33); +} +html .gsc-search-box .gsc-input > input:focus, html .gsc-input-box-focus { + box-shadow: none; +} +.navbar-inner .gsc-input-box { + width: 175px; +} +@media (max-width: 979px) { + html .nav-collapse .navbar-search { + float: left; + } +} +.dark { + background: rgb(20,20,25); + color: white; +} +.dark a { + color: white; +} +.dark a:hover { + color: rgb(200,200,200); +} +.dark blockquote { + border-left: 3px solid rgb(126,126,129); +} +.dark blockquote small { + color: white; + font-weight: bold; +} +.dark blockquote small:before { + display: none; +} + +/** Footer sitemap **/ +.copyright { + height: 26px; + padding: 6px; + overflow: hidden; +} + +.navbar .navbar-inner { + background: rgb(20,20,25); + border: none; +} +.navbar .navbar-inner .nav > li > a { + text-shadow: none; + color: white; +} +.navbar .navbar-inner .nav > li.dropdown.active > a, +.navbar .navbar-inner .nav > li.dropdown.open.active > a, +.navbar .navbar-inner .nav > li.dropdown.open > a, +.navbar .navbar-inner .nav > li.active > a { + color: rgb(244, 136, 33); + background-color: transparent; +} +.navbar-inner .dropdown-menu { + background-color: rgb(20,20,25); + margin-top: 5px; +} +.navbar .navbar-inner .nav > li > .dropdown-menu:after { + border-bottom-color: rgb(20,20,25); +} +.navbar-inner .dropdown-menu li a { + color: white; +} +.navbar-inner .dropdown-menu li.active a { + color: rgb(244, 136, 33); + background: transparent; +} +.navbar-inner .dropdown-menu li a:hover { + background: rgb(60,60,60); +} +.navbar .navbar-inner .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: white; + border-bottom-color: white; +} +.navbar .navbar-inner .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar .navbar-inner .nav li.dropdown.open > .dropdown-toggle .caret { + border-top-color: rgb(244, 136, 33); + border-bottom-color: rgb(244, 136, 33); +} +.navbar .brand { + font-weight: bold; + line-height: 16px; + padding-top: 9px; +} +.navbar .nav li { + margin-bottom: 0; + padding-left: 0; +} +@media (min-width: 1200px) { + .navbar .search-link-menu { display: none; } + .navbar .search { display: block; } +} +@media (max-width: 1199px) { + .navbar .search-link-menu { display: block; } + .navbar .search { display: none; } +} + +.user-profile img.avatar +{ + margin:0 30px 0 20px; +} + +i.fa { + color: #777; +} +h1 i.fa { + color: #f68712; +} +h2 i.fa, h3 i.fa, h4 i.fa, h5 i.fa { + color: #333; +} +.well .table { + margin-bottom: 0; +} +.btn-primary i.fa { + color: white; +} +/** File browser **/ +.panel-heading .breadcrumb { + margin: 0; + padding-left: 0; +} +.breadcrumb > li:first-child { + padding-left: 0; +} +pre.panel-body { + margin: 0; + border: none; + background: white; +} +/** Project lists. **/ +.project-list small { + font-weight: normal; +} +/** Homepage Banner **/ +.section.homepage-banner { + background: url('/img/homepage_banner.jpg'); + background-size: cover; + color: white; +} +.section.homepage-banner .jumbotron { + background: rgba(0,0,0,0.3); +} +.section.homepage-banner .jumbotron pre { + background: rgba(0,0,0,0.6); + margin: 0 0 20px 0; + padding: 10px; +} +.section.homepage-banner .jumbotron pre code { + color: white; +} diff --git a/extra/haxelib_src/src/tools/haxelib/dbconfig.json.example b/extra/haxelib_src/www/dbconfig.json similarity index 69% rename from extra/haxelib_src/src/tools/haxelib/dbconfig.json.example rename to extra/haxelib_src/www/dbconfig.json index baf97456..d008ca96 100644 --- a/extra/haxelib_src/src/tools/haxelib/dbconfig.json.example +++ b/extra/haxelib_src/www/dbconfig.json @@ -1,6 +1,6 @@ -{ - "user" : "dbUser", - "pass" : "dbPass", - "host" : "localhost", - "database" : "haxelib" +{ + "user" : "dbUser", + "pass" : "dbPass", + "host" : "dbHost", + "database" : "haxelib" } \ No newline at end of file diff --git a/extra/haxelib_src/www/documentation-files/api.md b/extra/haxelib_src/www/documentation-files/api.md new file mode 100644 index 00000000..2f77dfb0 --- /dev/null +++ b/extra/haxelib_src/www/documentation-files/api.md @@ -0,0 +1,5 @@ +# Accessing Haxelib info through the Remoting API +# Accessing Haxelib info through the JSON API + + +More information to go here... \ No newline at end of file diff --git a/extra/haxelib_src/www/documentation-files/creating-a-haxelib-package.md b/extra/haxelib_src/www/documentation-files/creating-a-haxelib-package.md new file mode 100644 index 00000000..5589f8af --- /dev/null +++ b/extra/haxelib_src/www/documentation-files/creating-a-haxelib-package.md @@ -0,0 +1,91 @@ +# Creating a haxelib package + +Each haxelib package is essentially a zip folder containing source code, supporting files, and a `haxelib.json` file. + +### haxelib.json + +Each Haxe library requires a `haxelib.json` file in which the following attributes are defined: + +* name: The name of the library. It must contain at least 3 characters among the following: `[A-Za-z0-9_-.]`. In particular, no spaces are allowed. +* url: The URL of the library, i.e. where more information can be found. +* license: The license under which the library is released. Can be `GPL`, `LGPL`, `BSD`, `Public` (for Public Domain), `MIT`, or `Apache`. +* tags: An array of tag-strings which are used on the repository website to sort libraries. +* description: The description of what the library is doing. +* version: The version string of the library. This is detailed in [Versioning](#versioning). +* classPath: The path string to the source files. +* releasenote: The release notes of the current version. +* contributors: An array of user names which identify contributors to the library that are allowed to upload to haxelib. +* dependencies: An object describing the dependencies of the library. This is detailed in [Dependencies](haxelib-json-dependencies.md). + +The following JSON is a simple example of a haxelib.json: + +```haxe +{ + "name": "useless_lib", + "url" : "https://github.com/jasononeil/useless/", + "license": "MIT", + "tags": ["cross", "useless"], + "description": "This library is useless in the same way on every platform.", + "version": "1.0.0", + "classPath": "src/", + "releasenote": "Initial release, everything is working correctly.", + "contributors": ["Juraj","Jason","Nicolas"], + "dependencies": { + "tink_macro": "", + "nme": "3.5.5" + } +} +``` + + + +### Versioning + +Haxelib uses a simplified version of [SemVer](http://semver.org/). The basic format is this: + +``` +major.minor.patch +``` + +These are the basic rules: + +* Major versions are incremented when you break backwards compatibility - so old code will not work with the new version of the library. +* Minor versions are incremented when new features are added. +* Patch versions are for small fixes that do not change the public API, so no existing code should break. +* When a minor version increments, the patch number is reset to 0. When a major version increments, both the minor and patch are reset to 0. + +Examples: + +* "0.0.1": A first release. Anything with a "0" for the major version is subject to change in the next release - no promises about API stability! +* "0.1.0": Added a new feature! Increment the minor version, reset the patch version +* "0.1.1": Realised the new feature was broken. Fixed it now, so increment the patch version +* "1.0.0": New major version, so increment the major version, reset the minor and patch versions. You promise your users not to break this API until you bump to 2.0.0 +* "1.0.1": A minor fix +* "1.1.0": A new feature +* "1.2.0": Another new feature +* "2.0.0": A new version, which might break compatibility with 1.0. Users are to upgrade cautiously. + +If this release is a preview (Alpha, Beta or Release Candidate), you can also include that, with an optional release number: + +``` +major.minor.patch-(alpha/beta/rc).release +``` + +Examples: + +* "1.0.0-alpha": The alpha of 1.0.0 - use with care, things are changing! +* "1.0.0-alpha.2": The 2nd alpha +* "1.0.0-beta": Beta - things are settling down, but still subject to change. +* "1.0.0-rc.1": The 1st release candidate for 1.0.0 - you shouldn't be adding any more features now +* "1.0.0-rc.2": The 2nd release candidate for 1.0.0 +* "1.0.0": The final release! + +### extraParams.hxml + +If you add a file named `extraParams.hxml` to your library root (at the same level as `haxelib.json`), these parameters will be automatically added to the compilation parameters when someone use your library with `-lib`. + +### Submission process + +* During development: Use `haxelib dev my_test_haxelib /path/to/my_test_haxelib/` to test the library. +* Ready to test: Zip the current directory, and use `haxelib install my_test_haxelib.zip` to try the final version. +- Submit: You can run `haxelib submit my_test_haxelib.zip` to submit the zip file to haxelib. Alternatively you can run `haxelib submit` without a zip file to have haxelib zip and submit the current directory. diff --git a/extra/haxelib_src/www/documentation-files/faq.md b/extra/haxelib_src/www/documentation-files/faq.md new file mode 100644 index 00000000..5be8f1bb --- /dev/null +++ b/extra/haxelib_src/www/documentation-files/faq.md @@ -0,0 +1,3 @@ +# FAQ + +More information to go here... diff --git a/extra/haxelib_src/www/documentation-files/index.md b/extra/haxelib_src/www/documentation-files/index.md new file mode 100644 index 00000000..6445b5b2 --- /dev/null +++ b/extra/haxelib_src/www/documentation-files/index.md @@ -0,0 +1,24 @@ +# Getting Started With Haxelib + +Haxelib is the library manager that comes with any Haxe distribution. Connected to a central repository, it allows submitting and retrieving libraries and has multiple features beyond that. Available libraries can be found at . + +A basic Haxe library is a collection of `.hx` files. That is, libraries are distributed by source code by default, making it easy to inspect and modify their behavior. Each library is identified by a unique name, which is utilized when telling the Haxe Compiler which libraries to use for a given compilation. + +### Using with Haxe + +Any installed Haxe library can be made available to the compiler through the `-lib ` argument. This is very similiar to the `-cp ` argument, but expects a library name instead of a directory path. These commands are explained thoroughly in [Compiler Usage](http://haxe.org/manual/compiler-usage.html). + +For our exemplary usage we chose a very simple Haxe library called "random". It provides a set of static convenience methods to achieve various random effects, such as picking a random element from an array. + +```haxe +class Main { + static public function main() { + var elt = Random.fromArray([1, 2, 3]); + trace(elt); + } +} +``` + +Compiling this without any `-lib` argument causes an error message along the lines of `Unknown identifier : Random`. This shows that installed Haxe libraries are not available to the compiler by default unless they are explicitly added. A working command line for above program is `haxe -lib random -main Main --interp`. + +If the compiler emits an error `Error: Library random is not installed : run 'haxelib install random'` the library has to be installed via the `haxelib` command first. As the error message suggests, this is achieved through `haxelib install random`. We will learn more about the `haxelib` command in [Using Haxelib](/documentation/using-haxelib/). diff --git a/extra/haxelib_src/www/documentation-files/installation.md b/extra/haxelib_src/www/documentation-files/installation.md new file mode 100644 index 00000000..88816f10 --- /dev/null +++ b/extra/haxelib_src/www/documentation-files/installation.md @@ -0,0 +1,4 @@ +# Installing and Upgrading Haxelib + + +More information to go here... \ No newline at end of file diff --git a/extra/haxelib_src/www/documentation-files/per-project-setup.md b/extra/haxelib_src/www/documentation-files/per-project-setup.md new file mode 100644 index 00000000..d8fcf99b --- /dev/null +++ b/extra/haxelib_src/www/documentation-files/per-project-setup.md @@ -0,0 +1,45 @@ +TODO: this needs editing and adding to the website + + + +## Per-project setup + +Currently haxelib has two ways to have project local setups. + +1. Using `haxelib newrepo` +2. Using `haxelib install all` + +### Using haxelib newrepo + +When using `haxelib newrepo` you can have a project-local haxelib repository. This feature is quite new and a little rough around the edges. + +Caveats: + +- libraries get downloaded for each project +- if you mistakenly run a haxelib command in a subdirectory of your project, it will be executed on the global repo ([to be fixed](https://github.com/HaxeFoundation/haxelib/issues/292)) + +### Using haxelib install all + +Haxe allows you to define specific versions of the libraries you want to use with `-lib :`. If you make sure to use this in all your hxmls, then `haxelib install all --always` (the `--always` avoiding you being prompted for confirmation) will be able to ensure the libraries your project needs are available in the necessary versions. If in fact you run this in a checkout hook, your get to track your dependencies in your git repo (some other VCSs should allow for a similar setup), allowing you to have a well defined and replicable setup for any state (commit/branch/etc.). + +Disadvantages: + +- the approach requires you to define all dependencies with specific versions and then running `haxelib install all` to grab them +- with this approach, any other project that does not have specific versions defined may be affected, as under some circumstances `haxelib install all` may set the global "current" version of the libraries (to be fixed) + +Advantages: + +- as pointed out above, this approach allows defining a *versionable* and *replicable* state. +- you don't have to download libraries for each project, which does make a difference for heavy weights like openfl and hxcpp + +#### Sidestepping haxelib git issues + +Because you cannot specify git versions with `-lib` paremeters, we suggest using git submodules instead, as again they provide an adequate way of definining a *versionable* and *replicable* state. + +### Combining both approaches + +You can of course combine both approaches, giving you the isolation provided by the first one, and the replicability provided by the second one. + +### Future solutions + +A solution that combines the strengths of both approaches is in the making. Stay tuned. diff --git a/extra/haxelib_src/www/documentation-files/tips-and-tricks.md b/extra/haxelib_src/www/documentation-files/tips-and-tricks.md new file mode 100644 index 00000000..351ef3f5 --- /dev/null +++ b/extra/haxelib_src/www/documentation-files/tips-and-tricks.md @@ -0,0 +1,3 @@ +# Tips and Tricks when using Haxelib + +More information to go here... diff --git a/extra/haxelib_src/www/documentation-files/using-haxelib.md b/extra/haxelib_src/www/documentation-files/using-haxelib.md new file mode 100644 index 00000000..4e7d02f4 --- /dev/null +++ b/extra/haxelib_src/www/documentation-files/using-haxelib.md @@ -0,0 +1,618 @@ +# Using Haxelib + +If the `haxelib` command is executed without any arguments, it prints an exhaustive list of all available arguments. Access the website to view all the libraries available. + +The following commands are available: + +
+
+

Basic

+ +
+ + + +
+

Development

+ +
+
+ + + + + + +## Basic + + + + + +#### `haxelib install` + + +``` +haxelib install [project-name] [version] +haxelib install actuate # Install latest version +haxelib install actuate 1.8.2 # Install specific version +``` + +> Install the given project. You can optionally specify a specific version to be installed. By default, latest released version will be installed. + +``` +haxelib install [library-file] +haxelib install actuate.zip # Install from zip file +``` + +> Install the project contained in the zip file. + +``` +haxelib install [hxml-file] +haxelib install build.hxml # Install all dependencies listed in hxml file +``` + +> Install all the dependencies from a hxml file. + +``` +haxelib install all # Install all dependencies in all hxml files +``` + +> Install all the dependencies from all hxml files in the current directory. + + + + + +#### `haxelib update` + +``` +haxelib update [project-name] +haxelib update minject +``` + +> Update a single library to the latest version. + +``` +haxelib update +``` + +> Update all the installed projects to their latest version. This command prompts a confirmation for each updating project. + + + + + +#### `haxelib remove` + +``` +haxelib remove [project-name] [version] +haxelib remove format # Remove all versions +haxelib remove format 3.1.2 # Remove the specified version +``` + +> Remove a complete project or only a specified version if specified. + + + + + +#### `haxelib list` + +``` +haxelib list [search] +haxelib list # List all installed projects +haxelib list ufront # List all projects with "ufront" in their name +``` + +> List all the installed projects and their versions. For each project, the version surrounded by brackets is the current one. + + + + + +#### `haxelib set` + +``` +haxelib set [project-name] [version] +haxelib set tink_core 1.0.0-rc.8 +``` + +> Change the current version for a given project. The version must be already installed. + + + + + +## Information + + + + + +#### `haxelib search` + +``` +haxelib search [word] +haxelib search tween +``` + +> Get a list of all haxelib projects with the specified word in the name or description. + + + + + +#### `haxelib info` + +``` +haxelib info [project-name] +haxelib info openfl +``` + +> Show information about this project, including the owner, license, description, website, tags, current version, and release notes for all versions. + + + + + +#### `haxelib user` + +``` +haxelib user [user-name] +haxelib user jason +``` + +> Show information on a given Haxelib user and their projects. + + + + + +#### `haxelib config` + +``` +haxelib config +``` + +> Print the Haxelib repository path. This is where each library will be installed to. You can modify the path using haxelib [setup](#setup). +> +> If you are in a local repository and want to print the global Haxelib repository path do haxelib [--global](#global) config. + + + + + +#### `haxelib path` + +``` +haxelib path [project-name[:version]...] +haxelib path hscript +haxelib path hscript:2.0.0 +haxelib path hscript erazor buddy +haxelib path hscript erazor buddy:1.0.0 +``` + +> Prints the path to one or more libraries, as well as any dependencies and compiler definitions required by those libraries. +> +> You can specify a version by appending `:version` to the library name. If no version is specified the set version is used. +> +> If a [development](#dev) version is set it'll be used even if a version is specified. +> +> This command is used by Haxe compiler to get required paths and flags for libraries. + + + + + +#### `haxelib version` + +``` +haxelib version +``` + +> Prints the version of Haxelib you are using. +> +> You can change the version of haxelib you are using with haxelib --global [set](#set) haxelib version + + + + + +#### `haxelib help` + +``` +haxelib help +``` + +> Print the list of available arguments. + + + + + +## Development + + + + + +#### `haxelib submit` + +``` +haxelib submit [project.zip] +haxelib submit detox.zip +haxelib sumbit +``` + +> Submits a zip package to Haxelib so other users can install it. +> +> Alternatively you can run `haxelib submit` without argument to have Haxelib zip and submit the current directory (excluding names starting with a dot). +> +> If the user name is unknown, you'll be first asked to register an account. +> If more the project has more than one developer, it will ask you which user you wish to submit as. +> If the user already exists, you will be prompted for your password. +> +> If you want to modify the project url or description, simply modify your `haxelib.json` (keeping version information unchanged) and submit it again. + + + + + +#### `haxelib register` + +``` +haxelib register [username] [email] [fullname] [password] [passwordconfirmation] +``` + +> Register a new developer account to be used when [submitting](#submit). +> +> Missing parameters will be asked interactively. + + + + + +#### `haxelib dev` + +``` +haxelib dev [project-name] [directory] +haxelib dev starling ../starling/ # Relative path to starling source. +haxelib dev starling /opt/starling/ # Absolute path to starling source. +haxelib dev starling # Cancel dev, use installed version. +``` + +> Set a development directory for the given project. +> This directory should either contain a `haxelib.json` or the source `*.hx` files. +> This command is useful when developing a library and testing changes on a project. +> +> If the directory is omitted the development version of the library will be deactivated. + + + + +#### `haxelib git` + +``` +haxelib git [project-name] [git-clone-path] [branch] +haxelib git minject https://github.com/massiveinteractive/minject.git # Use HTTP git path. +haxelib git minject git@github.com:massiveinteractive/minject.git # Use SSH git path. +haxelib git minject git@github.com:massiveinteractive/minject.git v2 # Checkout branch or tag `v2`. +``` + +> Use a git repository as library. +> +> This is useful for using a more up-to-date development version, a fork of the original project, or for having a private library that you do not wish to post to Haxelib. +> +> When you use `haxelib update` any libraries that are installed using GIT will automatically pull the latest version. + + + + + +#### `haxelib hg` + +``` +haxelib hg [project-name] [mercurial-clone-path] [branch] +``` + +> Use a mercurial repository as library. +> +> Usage is identical to haxelib [git](#git). + + + + + +## Miscellaneous + + + + + +#### `haxelib setup` + +``` +haxelib setup [path] +``` + +> Set the Haxelib repository path. To print current path use haxelib [config](#config). +> +> Missing parameter will be asked interactively. + + + + + +#### `haxelib newrepo` + +``` +haxelib newrepo +``` + +> Create a local repository in the current directory, to remove it use haxelib [deleterepo](#deleterepo). +> +> [Basic](#basic) commands will only use the libraries stored in the local repository when you are located in this directory. +> +> To access the global repository add the [--global](#global) flag. + + + + + +#### `haxelib deleterepo` + +``` +haxelib deleterepo +``` + +> Remove a local repository created with haxelib [newrepo](#newrepo) from the current directory. +> +> This will remove all libraries contained in it. + + + + + +#### `haxelib convertxml` + +``` +haxelib convertxml +``` + +> Convert the file `haxelib.xml` from the current directory in the Haxelib 2 xml specification into a file named `haxelib.json` which can be used by the current Haxelib. + + + + +#### `haxelib run` + +``` +haxelib run [project-name[:version]] [parameters] +haxelib run openfl +haxelib run openfl:2.6.0 +haxelib run openfl setup +haxelib run openfl create DisplayingABitmap +``` + +> Libraries with either a `run.n` helper or a main class defined in `haxelib.json`, can be executed using `haxelib run`. +> +> You can specify the version to run by appending `:version`, if the library has a [development](#dev) version set the version will be ignored. +> +> The library will receive the `HAXELIB_RUN` environment variable with value `"1"` and `HAXELIB_RUN_NAME` with the name of the library as value. + + + + +#### `haxelib proxy` + +``` +haxelib proxy [host port [username password]] +``` + +> Configure Haxelib to use a HTTP proxy. +> +> Missing parameters will be asked interactively. +> +> Rerun with an empty host to deactivate the current proxy. + + + + + +## Flags + + + +**Warning**: when using the [run](#run) command you need to specify the flags before `run`, +otherwise they'll be passed as arguments to the library. + + + + + +#### `haxelib --flat` + +``` +haxelib --flat +``` + +> Used by haxelib [git](#git), do not add the `--recursive` flag when cloning a git repository. + + + + + +#### `haxelib --always` + +``` +haxelib --always +``` + +> Answer all questions with yes, cannot be used at the same time as [--never](#never). + + + + + +#### `haxelib --system` + +``` +haxelib --system +``` + +> Use the version of Haxelib installed with Haxe in the system instead of the one currently [set](#set). +> +> Useful if your Haxelib update was broken. + + + + + +#### `haxelib --debug` + +``` +haxelib --debug +``` + +> Display debug information during the execution, cannot be used at the same time as [--quiet](#quiet). + + + + + +#### `haxelib --quiet` + +``` +haxelib --quiet +``` + +> Display less messages during the execution, cannot be used at the same time as [--debug](#debug). + + + + + +#### `haxelib --never` + +``` +haxelib --never +``` + +> Answer all questions with no, cannot be used at the same time as [--always](#always). + + + + + +#### `haxelib --global` + +``` +haxelib --global +``` + +> Force the usage of the global repository even if inside a local repository created with haxelib [newrepo](#newrepo). + + + + + +## Parameters + + + +**Warning**: when using the [run](#run) command you need to specify the parameters before `run`, +otherwise they'll be passed as arguments to the library. + + + + + +#### `haxelib -cwd` + +``` +haxelib -cwd [dir] +``` + +> Act like the Haxelib command was run from another repository. Affect all commands that use the "current directory". + + + + + +#### `haxelib -no-timeout` + +``` +haxelib -no-timeout +``` + +> Remove timeout when connecting to the Haxelib server, downloading or [submitting](#submit) a library. + + + + + +#### `haxelib -R` + +``` +haxelib -R [host:port[/dir]] +``` + +> Allow the usage of a custom Haxelib server instead of `lib.haxe.org`. diff --git a/extra/haxelib_src/www/favicon.ico b/extra/haxelib_src/www/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..9ae83d351afd49157fa6f577c99390d845dcfbb0 GIT binary patch literal 1150 zcmaKsJxc>Y5QZltc!dg)5Rs^7ayI@L8?n)UU<5IZbz)i@@dHKd6cH`7(=yuFs9XZQJS#)L2 z0@P#j=oh0s?m=_RJ^m@UJKvaFuN$GW;r=8*)|lRE){kE*nE57wi z?`GA;g*Cd5^mVH@ug>ZFe*EwQ`lI)qS)MU{8uZnP^3EgHhF&nnoWA0(cbkhN_!|Wn*Vos8{TEhUT@5e;_WJsIMMcG5%>DiS&dv_N`4@J0cnAQ-#>RjZ z00W5t&tJ^l-QC*ST1-p~00u^9XJ=AUl7oW-;2a+x2k__T=grN{+1c4XK0ZL~^z^i$ zp&>vEhr@4fZWb380S18T&!0cQ3IKpHF)?v=b_NIm0Q>vwY7D0baZ)n z31Fa5sELUQARIVaU0nqf0XzT+fB_63aA;@<$l~wse|mcA;^G1TmX?-)e)jkGPfkuA z92@|!<>h5S_4f8QP-JRq>d&7)^Yin8l7K8gED$&_FaV?gY+wLjpoW%~7NDe=nHfMG z5DO3j{R9kv5GbssrUpO)OyvVrlx>u0UKD0i;Dpm5S5dY16(DL5l{ixz|mhJU@&-OWCTb7_%}8-fE(P~+XIRO zJU|wp1|S>|J3KrLcz^+v1f&BDpd>&MAaibR4#5A_4(MucZwG9E1h4@u0P@C8;oo+g zIVj7kfJi{oV~E(NZ*h(@^-(Q(C`Psb3KZ{N;^GB(a8NE*Vwc715!9 zr-H4Ao|T_c6+VT_JH9H+P3>iXSt!a$F`>s`jn`w9GZ_~B!{0soaiV|O_c^R2aWa%}O3jUE)WO=pa zs~_Wz08z|ieY5A%$@FcBF9^!1a}m5ks@7gjn;67N>}S~Hrm`4sM5Hh`q7&5-N{|31 z6x1{ol7BnskoViZ0GqbLa#kW`Z)VCjt1MysKg|rT zi!?s##Ck>8c zpi|>$lGlw#@yMNi&V4`6OBGJ(H&7lqLlcTQ&1zWriG_fL>BnFcr~?;E93{M-xIozQ zO=EHQ#+?<}%@wbWWv23#!V70h9MOuUVaU>3kpTvYfc|LBw?&b*89~Gc9i&8tlT#kF ztpbZoAzkdB+UTy=tx%L3Z4)I{zY(Kb)eg{InobSJmNwPZt$14aS-uc4eKuY8h$dtfyxu^a%zA)>fYI&)@ZXky?^{5>xSC?;w4r&td6vBdi%vHm4=XJH!3yL3?Ep+T5aU_>i;yr_XGq zxZfCzUU@GvnoIk+_Nd`aky>S&H!b*{A%L>?*XPAgWL(Vf(k7qUS}>Zn=U(ZfcOc{B z3*tOHH@t5Ub5D~#N7!Fxx}P2)sy{vE_l(R7$aW&CX>c|&HY+7};vUIietK%}!phrCuh+;C@1usp;XLU<8Gq8P!rEI3ieg#W$!= zQcZr{hp>8sF?k&Yl0?B84OneiQxef-4TEFrq3O~JAZR}yEJHA|Xkqd49tR&8oq{zP zY@>J^HBV*(gJvJZc_0VFN7Sx?H7#75E3#?N8Z!C+_f53YU}pyggxx1?wQi5Yb-_`I`_V*SMx5+*P^b=ec5RON-k1cIlsBLk}(HiaJyab0`CI zo0{=1_LO$~oE2%Tl_}KURuX<`+mQN_sTdM&* zkFf!Xtl^e^gTy6ON=&gTn6)$JHQq2)33R@_!#9?BLNq-Wi{U|rVX7Vny$l6#+SZ@KvQt@VYb%<9JfapI^b9j=wa+Tqb4ei;8c5 z&1>Uz@lVFv6T4Z*YU$r4G`g=91lSeA<=GRZ!*KTWKDPR}NPUW%peCUj`Ix_LDq!8| zMH-V`Pv!a~QkTL||L@cqiTz)*G-0=ytr1KqTuFPan9y4gYD5>PleK`NZB$ev@W%t= zkp)_=lBUTLZJpAtZg;pjI;7r2y|26-N7&a(hX|`1YNM9N8{>8JAuv}hp1v`3JHT-=5lbXpbMq7X~2J5Kl zh7tyU`_AusMFZ{ej9D;Uyy;SQ!4nwgSnngsYBwdS&EO3NS*o04)*juAYl;57c2Ly0(DEZ8IY?zSph-kyxu+D`tt@oU{32J#I{vmy=#0ySPK zA+i(A3yl)qmTz*$dZi#y9FS;$;h%bY+;StNx{_R56Otq+?pGe^T^{5d7Gs&?`_r`8 zD&dzOA|j8@3A&FR5U3*eQNBf<4^4W_iS_()*8b4aaUzfk2 zzIcMWSEjm;EPZPk{j{1>oXd}pXAj!NaRm8{Sjz!D=~q3WJ@vmt6ND_?HI~|wUS1j5 z9!S1MKr7%nxoJ3k`GB^7yV~*{n~O~n6($~x5Bu{7s|JyXbAyKI4+tO(zZYMslK;Zc zzeHGVl{`iP@jfSKq>R;{+djJ9n%$%EL()Uw+sykjNQdflkJZSjqV_QDWivbZS~S{K zkE@T^Jcv)Dfm93!mf$XYnCT--_A$zo9MOkPB6&diM8MwOfV?+ApNv`moV@nqn>&lv zYbN1-M|jc~sG|yLN^1R2=`+1ih3jCshg`iP&mY$GMTcY^W^T`WOCX!{-KHmZ#GiRH zYl{|+KLn5!PCLtBy~9i}`#d^gCDDx$+GQb~uc;V#K3OgbbOG0j5{BRG-si%Bo{@lB zGIt+Ain8^C`!*S0d0OSWVO+Z89}}O8aFTZ>p&k}2gGCV zh#<$gswePFxWGT$4DC^8@84_e*^KT74?7n8!$8cg=sL$OlKr&HMh@Rr5%*Wr!xoOl zo7jItnj-xYgVTX)H1=A2bD(tleEH57#V{xAeW_ezISg5OC zg=k>hOLA^urTH_e6*vSYRqCm$J{xo}-x3@HH;bsHD1Z`Pzvsn}%cvfw%Q(}h`Dgtb z0_J^niUmoCM5$*f)6}}qi(u;cPgxfyeVaaVmOsG<)5`6tzU4wyhF;k|~|x>7-2hXpVBpc5k{L4M`Wbe6Q?tr^*B z`Y*>6*&R#~%JlBIitlZ^qGe3s21~h3U|&k%%jeMM;6!~UH|+0+<5V-_zDqZQN79?n?!Aj!Nj`YMO9?j>uqI9-Tex+nJD z%e0#Yca6(zqGUR|KITa?9x-#C0!JKJHO(+fy@1!B$%ZwJwncQW7vGYv?~!^`#L~Um zOL++>4qmqW`0Chc0T23G8|vO)tK=Z2`gvS4*qpqhIJCEv9i&&$09VO8YOz|oZ+ubd zNXVdLc&p=KsSgtmIPLN69P7xYkYQ1vJ?u1g)T!6Ru`k2wkdj*wDC)VryGu2=yb0?F z>q~~e>KZ0d_#7f3UgV%9MY1}vMgF{B8yfE{HL*pMyhYF)WDZ^^3vS8F zGlOhs%g_~pS3=WQ#494@jAXwOtr^Y|TnQ5zki>qRG)(oPY*f}U_=ip_{qB0!%w7~G zWE!P4p3khyW-JJnE>eECuYfI?^d366Shq!Wm#x&jAo>=HdCllE$>DPO0N;y#4G)D2y#B@5=N=+F%Xo2n{gKcPcK2!hP*^WSXl+ut; zyLvVoY>VL{H%Kd9^i~lsb8j4>$EllrparEOJNT?Ym>vJa$(P^tOG)5aVb_5w^*&M0 zYOJ`I`}9}UoSnYg#E(&yyK(tqr^@n}qU2H2DhkK-`2He% zgXr_4kpXoQHxAO9S`wEdmqGU4j=1JdG!OixdqB4PPP6RXA}>GM zumruUUH|ZG2$bBj)Qluj&uB=dRb)?^qomw?Z$X%#D+Q*O97eHrgVB2*mR$bFBU`*} zIem?dM)i}raTFDn@5^caxE^XFXVhBePmH9fqcTi`TLaXiueH=@06sl}>F%}h9H_e9 z>^O?LxM1EjX}NVppaO@NNQr=AtHcH-BU{yBT_vejJ#J)l^cl69Z7$sk`82Zyw7Wxt z=~J?hZm{f@W}|96FUJfy65Gk8?^{^yjhOahUMCNNpt5DJw}ZKH7b!bGiFY9y6OY&T z_N)?Jj(MuLTN36ZCJ6I5Xy7uVlrb$o*Z%=-)kPo9s?<^Yqz~!Z* z_mP8(unFq65XSi!$@YtieSQ!<7IEOaA9VkKI?lA`*(nURvfKL8cX}-+~uw9|_5)uC2`ZHcaeX7L8aG6Ghleg@F9aG%X$#g6^yP5apnB>YTz&EfS{q z9UVfSyEIczebC)qlVu5cOoMzS_jrC|)rQlAzK7sfiW0`M8mVIohazPE9Jzn*qPt%6 zZL8RELY@L09B83@Be;x5V-IHnn$}{RAT#<2JA%ttlk#^(%u}CGze|1JY5MPhbfnYG zIw%$XfBmA-<_pKLpGKwbRF$#P;@_)ech#>vj25sv25VM$ouo)?BXdRcO{)*OwTw)G zv43W~T6ekBMtUD%5Bm>`^Ltv!w4~65N!Ut5twl!Agrzyq4O2Fi3pUMtCU~>9gt_=h-f% z;1&OuSu?A_sJvIvQ+dZNo3?m1%b1+s&UAx?8sUHEe_sB7zkm4R%6)<@oYB_i5>3Ip zIA+?jVdX|zL{)?TGpx+=Ta>G80}0}Ax+722$XFNJsC1gcH56{8B)*)eU#r~HrC&}` z|EWW92&;6y;3}!L5zXa385@?-D%>dSvyK;?jqU2t_R3wvBW;$!j45uQ7tyEIQva;Db}r&bR3kqNSh)Q_$MJ#Uj3Gj1F;)sO|%6z#@<+ zi{pbYsYS#u`X$Nf($OS+lhw>xgjos1OnF^$-I$u;qhJswhH~p|ab*nO>zBrtb0ndn zxV0uh!LN`&xckTP+JW}gznSpU492)u+`f{9Yr)js`NmfYH#Wdtradc0TnKNz@Su!e zu$9}G_=ku;%4xk}eXl>)KgpuT>_<`Ud(A^a++K&pm3LbN;gI}ku@YVrA%FJBZ5$;m zobR8}OLtW4-i+qPPLS-(7<>M{)rhiPoi@?&vDeVq5%fmZk=mDdRV>Pb-l7pP1y6|J z8I>sF+TypKV=_^NwBU^>4JJq<*14GLfM2*XQzYdlqqjnE)gZsPW^E@mp&ww* zW9i>XL=uwLVZ9pO*8K>t>vdL~Ek_NUL$?LQi5sc#1Q-f6-ywKcIT8Kw?C(_3pbR`e|)%9S-({if|E+hR2W!&qfQ&UiF^I!|M#xhdWsenv^wpKCBiuxXbnp85`{i|;BM?Ba`lqTA zyRm=UWJl&E{8JzYDHFu>*Z10-?#A8D|5jW9Ho0*CAs0fAy~MqbwYuOq9jjt9*nuHI zbDwKvh)5Ir$r!fS5|;?Dt>V+@F*v8=TJJF)TdnC#Mk>+tGDGCw;A~^PC`gUt*<(|i zB{{g{`uFehu`$fm4)&k7`u{xIV)yvA(%5SxX9MS80p2EKnLtCZ>tlX>*Z6nd&6-Mv$5rHD*db;&IBK3KH&M<+ArlGXDRdX1VVO4)&R$f4NxXI>GBh zSv|h>5GDAI(4E`@F?EnW zS>#c&Gw6~_XL`qQG4bK`W*>hek4LX*efn6|_MY+rXkNyAuu?NxS%L7~9tD3cn7&p( zCtfqe6sjB&Q-Vs7BP5+%;#Gk};4xtwU!KY0XXbmkUy$kR9)!~?*v)qw00!+Yg^#H> zc#8*z6zZo>+(bud?K<*!QO4ehiTCK&PD4G&n)Tr9X_3r-we z?fI+}-G~Yn93gI6F{}Dw_SC*FLZ)5(85zp4%uubtD)J)UELLkvGk4#tw&Tussa)mTD$R2&O~{ zCI3>fr-!-b@EGRI%g0L8UU%%u_<;e9439JNV;4KSxd|78v+I+8^rmMf3f40Jb}wEszROD?xBZu>Ll3;sUIoNxDK3|j3*sam2tC@@e$ z^!;+AK>efeBJB%ALsQ{uFui)oDoq()2USi?n=6C3#eetz?wPswc={I<8x=(8lE4EIsUfyGNZ{|KYn1IR|=E==f z(;!A5(-2y^2xRFCSPqzHAZn5RCN_bp22T(KEtjA(rFZ%>a4@STrHZflxKoqe9Z4@^ zM*scx_y73?Q{vt6?~WEl?2q*;@8 z3M*&@%l)SQmXkcUm)d@GT2#JdzhfSAP9|n#C;$E8X|pwD!r#X?0P>0ZisQ~TNqupW z*lUY~+ikD`vQb?@SAWX#r*Y+;=_|oacL$2CL$^(mV}aKO77pg}O+-=T1oLBT5sL2i z42Qth2+0@C`c+*D0*5!qy26sis<9a7>LN2{z%Qj49t z=L@x`4$ALHb*3COHoT?5S_c(Hs}g!V>W^=6Q0}zaubkDn)(lTax0+!+%B}9Vqw6{H zvL|BRM`O<@;eVi1DzM!tXtBrA20Ce@^Jz|>%X-t`vi-%WweXCh_LhI#bUg2*pcP~R z*RuTUzBKLXO~~uMd&o$v3@d0shHfUjC6c539PE6rF&;Ufa(Rw@K1*m7?f5)t`MjH0 z)_V(cajV5Am>f!kWcI@5rE8t6$S>5M=k=aRZROH6fA^jJp~2NlR4;Q2>L$7F#RT#9 z>4@1RhWG`Khy>P2j1Yx^BBL{S`niMaxlSWV-JBU0-T9zZ%>7mR3l$~QV$({o0;jTI ze5=cN^!Bc2bT|BcojXp~K#2cM>OTe*cM{Kg-j*CkiW)EGQot^}s;cy8_1_@JA0Whq zlrNr+R;Efa+`6N)s5rH*|E)nYZ3uqkk2C(E7@A|3YI`ozP~9Lexx#*1(r8luq+YPk z{J}c$s` zPM35Fx(YWB3Z5IYnN+L_4|jaR(5iWJi2~l&xy}aU7kW?o-V*6Av2wyZTG!E2KSW2* zGRLQkQU;Oz##ie-Z4fI)WSRxn$(ZcD;TL+;^r=a4(G~H3ZhK$lSXZj?cvyY8%d9JM zzc3#pD^W_QnWy#rx#;c&N@sqHhrnHRmj#i;s%zLm6SE(n&BWpd&f7>XnjV}OlZntI70fq%8~9<7 zMYaw`E-rp49-oC1N_uZTo)Cu%RR2QWdHpzQIcNsoDp`3xfP+`gI?tVQZ4X={qU?(n zV>0ASES^Xuc;9JBji{)RnFL(Lez;8XbB1uWaMp@p?7xhXk6V#!6B@aP4Rz7-K%a>i z?fvf}va_DGUXlI#4--`A3qK7J?-HwnG7O~H2;zR~RLW)_^#La!=}+>KW#anZ{|^D3 B7G?kd literal 0 HcmV?d00001 diff --git a/extra/haxelib_src/www/img/glyphicons-halflings.png b/extra/haxelib_src/www/img/glyphicons-halflings.png new file mode 100644 index 0000000000000000000000000000000000000000..a9969993201f9cee63cf9f49217646347297b643 GIT binary patch literal 12799 zcma*OWmH^Ivn@*S;K3nSf_t!#;0f+&pm7Po8`nk}2q8f5;M%x$SdAkd9FAvlc$ zx660V9e3Ox@4WZ^?7jZ%QFGU-T~%||Ug4iK6bbQY@zBuF2$hxOw9wF=A)nUSxR_5@ zEX>HBryGrjyuOFFv$Y4<+|3H@gQfEqD<)+}a~mryD|1U9*I_FOG&F%+Ww{SJ-V2BR zjt<81Ek$}Yb*95D4RS0HCps|uLyovt;P05hchQb-u2bzLtmog&f2}1VlNhxXV);S9 zM2buBg~!q9PtF)&KGRgf3#z7B(hm5WlNClaCWFs!-P!4-u*u5+=+D|ZE9e`KvhTHT zJBnLwGM%!u&vlE%1ytJ=!xt~y_YkFLQb6bS!E+s8l7PiPGSt9xrmg?LV&&SL?J~cI zS(e9TF1?SGyh+M_p@o1dyWu7o7_6p;N6hO!;4~ z2B`I;y`;$ZdtBpvK5%oQ^p4eR2L)BH>B$FQeC*t)c`L71gXHPUa|vyu`Bnz)H$ZcXGve(}XvR!+*8a>BLV;+ryG1kt0=)ytl zNJxFUN{V7P?#|Cp85QTa@(*Q3%K-R(Pkv1N8YU*(d(Y}9?PQ(j;NzWoEVWRD-~H$=f>j9~PN^BM2okI(gY-&_&BCV6RP&I$FnSEM3d=0fCxbxA6~l>54-upTrw zYgX@%m>jsSGi`0cQt6b8cX~+02IghVlNblR7eI;0ps}mpWUcxty1yG56C5rh%ep(X z?)#2d?C<4t-KLc*EAn>>M8%HvC1TyBSoPNg(4id~H8JwO#I)Bf;N*y6ai6K9_bA`4 z_g9(-R;qyH&6I$`b42v|0V3Z8IXN*p*8g$gE98+JpXNY+jXxU0zsR^W$#V=KP z3AEFp@OL}WqwOfsV<)A^UTF4&HF1vQecz?LWE@p^Z2){=KEC_3Iopx_eS42>DeiDG zWMXGbYfG~W7C8s@@m<_?#Gqk;!&)_Key@^0xJxrJahv{B&{^!>TV7TEDZlP|$=ZCz zmX=ZWtt4QZKx**)lQQoW8y-XLiOQy#T`2t}p6l*S`68ojyH@UXJ-b~@tN`WpjF z%7%Yzv807gsO!v=!(2uR)16!&U5~VPrPHtGzUU?2w(b1Xchq}(5Ed^G|SD7IG+kvgyVksU) z(0R)SW1V(>&q2nM%Z!C9=;pTg!(8pPSc%H01urXmQI6Gi^dkYCYfu6b4^tW))b^U+ z$2K&iOgN_OU7n#GC2jgiXU{caO5hZt0(>k+c^(r><#m|#J^s?zA6pi;^#*rp&;aqL zRcZi0Q4HhVX3$ybclxo4FFJW*`IV`)Bj_L3rQe?5{wLJh168Ve1jZv+f1D}f0S$N= zm4i|9cEWz&C9~ZI3q*gwWH^<6sBWuphgy@S3Qy?MJiL>gwd|E<2h9-$3;gT9V~S6r z)cAcmE0KXOwDA5eJ02-75d~f?3;n7a9d_xPBJaO;Z)#@s7gk5$Qn(Fc^w@9c5W0zY z59is0?Mt^@Rolcn{4%)Ioat(kxQH6}hIykSA)zht=9F_W*D#<}N(k&&;k;&gKkWIL z0Of*sP=X(Uyu$Pw;?F@?j{}=>{aSHFcii#78FC^6JGrg-)!)MV4AKz>pXnhVgTgx8 z1&5Y=>|8RGA6++FrSy=__k_imx|z-EI@foKi>tK0Hq2LetjUotCgk2QFXaej!BWYL zJc{fv(&qA7UUJ|AXLc5z*_NW#yWzKtl(c8mEW{A>5Hj^gfZ^HC9lQNQ?RowXjmuCj4!!54Us1=hY z0{@-phvC}yls!PmA~_z>Y&n&IW9FQcj}9(OLO-t^NN$c0o}YksCUWt|DV(MJB%%Sr zdf}8!9ylU2TW!=T{?)g-ojAMKc>3pW;KiZ7f0;&g)k}K^#HBhE5ot)%oxq$*$W@b# zg4p<Ou`ME|Kd1WHK@8 zzLD+0(NHWa`B{em3Ye?@aVsEi>y#0XVZfaFuq#;X5C3{*ikRx7UY4FF{ZtNHNO?A_ z#Q?hwRv~D8fPEc%B5E-ZMI&TAmikl||EERumQCRh7p;)>fdZMxvKq;ky0}7IjhJph zW*uuu*(Y6)S;Od--8uR^R#sb$cmFCnPcj9PPCWhPN;n`i1Q#Qn>ii z{WR|0>8F`vf&#E(c2NsoH=I7Cd-FV|%(7a`i}gZw4N~QFFG2WtS^H%@c?%9UZ+kez z;PwGgg_r6V>Kn5n(nZ40P4qMyrCP3bDkJp@hp6&X3>gzC>=f@Hsen<%I~7W+x@}b> z0}Et*vx_50-q@PIV=(3&Tbm}}QRo*FP2@)A#XX-8jYspIhah`9ukPBr)$8>Tmtg&R z?JBoH17?+1@Y@r>anoKPQ}F8o9?vhcG79Cjv^V6ct709VOQwg{c0Q#rBSsSmK3Q;O zBpNihl3S0_IGVE)^`#94#j~$;7+u870yWiV$@={|GrBmuz4b)*bCOPkaN0{6$MvazOEBxFdKZDlbVvv{8_*kJ zfE6C`4&Kkz<5u%dEdStd85-5UHG5IOWbo8i9azgg#zw-(P1AA049hddAB*UdG3Vn0 zX`OgM+EM|<+KhJ<=k?z~WA5waVj?T9eBdfJGebVifBKS1u<$#vl^BvSg)xsnT5Aw_ZY#}v*LXO#htB>f}x3qDdDHoFeb zAq7;0CW;XJ`d&G*9V)@H&739DpfWYzdQt+Kx_E1K#Cg1EMtFa8eQRk_JuUdHD*2;W zR~XFnl!L2A?48O;_iqCVr1oxEXvOIiN_9CUVTZs3C~P+11}ebyTRLACiJuMIG#`xP zKlC|E(S@QvN+%pBc6vPiQS8KgQAUh75C0a2xcPQDD$}*bM&z~g8+=9ltmkT$;c;s z5_=8%i0H^fEAOQbHXf0;?DN5z-5+1 zDxj50yYkz4ox9p$HbZ|H?8ukAbLE^P$@h}L%i6QVcY>)i!w=hkv2zvrduut%!8>6b zcus3bh1w~L804EZ*s96?GB&F7c5?m?|t$-tp2rKMy>F*=4;w*jW}^;8v`st&8)c; z2Ct2{)?S(Z;@_mjAEjb8x=qAQvx=}S6l9?~H?PmP`-xu;ME*B8sm|!h@BX4>u(xg_ zIHmQzp4Tgf*J}Y=8STR5_s)GKcmgV!$JKTg@LO402{{Wrg>#D4-L%vjmtJ4r?p&$F!o-BOf7ej~ z6)BuK^^g1b#(E>$s`t3i13{6-mmSp7{;QkeG5v}GAN&lM2lQT$@(aQCcFP(%UyZbF z#$HLTqGT^@F#A29b0HqiJsRJAlh8kngU`BDI6 zJUE~&!cQ*&f95Ot$#mxU5+*^$qg_DWNdfu+1irglB7yDglzH()2!@#rpu)^3S8weW z_FE$=j^GTY*|5SH95O8o8W9FluYwB=2PwtbW|JG6kcV^dMVmX(wG+Otj;E$%gfu^K z!t~<3??8=()WQSycsBKy24>NjRtuZ>zxJIED;YXaUz$@0z4rl+TW zWxmvM$%4jYIpO>j5k1t1&}1VKM~s!eLsCVQ`TTjn3JRXZD~>GM z$-IT~(Y)flNqDkC%DfbxaV9?QuWCV&-U1yzrV@0jRhE;)ZO0=r-{s@W?HOFbRHDDV zq;eLo+wOW;nI|#mNf(J?RImB9{YSO2Y`9825Lz#u4(nk3)RGv3X8B(A$TsontJ8L! z9JP^eWxtKC?G8^xAZa1HECx*rp35s!^%;&@Jyk)NexVc)@U4$^X1Dag6`WKs|(HhZ#rzO2KEw3xh~-0<;|zcs0L>OcO#YYX{SN8m6`9pp+ zQG@q$I)T?aoe#AoR@%om_#z=c@ych!bj~lV13Qi-xg$i$hXEAB#l=t7QWENGbma4L zbBf*X*4oNYZUd_;1{Ln_ZeAwQv4z?n9$eoxJeI?lU9^!AB2Y~AwOSq67dT9ADZ)s@ zCRYS7W$Zpkdx$3T>7$I%3EI2ik~m!f7&$Djpt6kZqDWZJ-G{*_eXs*B8$1R4+I}Kf zqniwCI64r;>h2Lu{0c(#Atn)%E8&)=0S4BMhq9$`vu|Ct;^ur~gL`bD>J@l)P$q_A zO7b3HGOUG`vgH{}&&AgrFy%K^>? z>wf**coZ2vdSDcNYSm~dZ(vk6&m6bVKmVgrx-X<>{QzA!)2*L+HLTQz$e8UcB&Djq zl)-%s$ZtUN-R!4ZiG=L0#_P=BbUyH+YPmFl_ogkkQ$=s@T1v}rNnZ^eMaqJ|quc+6 z*ygceDOrldsL30w`H;rNu+IjlS+G~p&0SawXCA1+D zC%cZtjUkLNq%FadtHE?O(yQTP486A{1x<{krq#rpauNQaeyhM3*i0%tBpQHQo-u)x z{0{&KS`>}vf2_}b160XZO2$b)cyrHq7ZSeiSbRvaxnKUH{Q`-P(nL&^fcF2){vhN- zbX&WEjP7?b4A%0y6n_=m%l00uZ+}mCYO(!x?j$+O$*TqoD_Q5EoyDJ?w?^UIa491H zE}87(bR`X;@u#3Qy~9wWdWQIg1`cXrk$x9=ccR|RY1~%{fAJ@uq@J3e872x0v$hmv ze_KcL(wM|n0EOp;t{hKoohYyDmYO;!`7^Lx;0k=PWPGZpI>V5qYlzjSL_(%|mud50 z7#{p97s`U|Sn$WYF>-i{i4`kzlrV6a<}=72q2sAT7Zh{>P%*6B;Zl;~0xWymt10Mo zl5{bmR(wJefJpNGK=fSRP|mpCI-)Nf6?Pv==FcFmpSwF1%CTOucV{yqxSyx4Zws3O z8hr5Uyd%ezIO7?PnEO0T%af#KOiXD$e?V&OX-B|ZX-YsgSs%sv-6U+sLPuz{D4bq| zpd&|o5tNCmpT>(uIbRf?8c}d3IpOb3sn6>_dr*26R#ev<_~vi)wleW$PX|5)$_ z+_|=pi(0D(AB_sjQ;sQQSM&AWqzDO1@NHw;C9cPdXRKRI#@nUW)CgFxzQ1nyd!+h& zcjU!U=&u|>@}R(9D$%lu2TlV>@I2-n@fCr5PrZNVyKWR7hm zWjoy^p7v8m#$qN0K#8jT- zq`mSirDZDa1Jxm;Rg3rAPhC)LcI4@-RvKT+@9&KsR3b0_0zuM!Fg7u>oF>3bzOxZPU&$ab$Z9@ zY)f7pKh22I7ZykL{YsdjcqeN++=0a}elQM-4;Q)(`Ep3|VFHqnXOh14`!Bus& z9w%*EWK6AiAM{s$6~SEQS;A>ey$#`7)khZvamem{P?>k)5&7Sl&&NXKk}o!%vd;-! zpo2p-_h^b$DNBO>{h4JdGB=D>fvGIYN8v&XsfxU~VaefL?q} z3ekM?iOKkCzQHkBkhg=hD!@&(L}FcHKoa zbZ7)H1C|lHjwEb@tu=n^OvdHOo7o+W`0-y3KdP#bb~wM=Vr_gyoEq|#B?$&d$tals ziIs-&7isBpvS|CjC|7C&3I0SE?~`a%g~$PI%;au^cUp@ER3?mn-|vyu!$7MV6(uvt z+CcGuM(Ku2&G0tcRCo7#D$Dirfqef2qPOE5I)oCGzmR5G!o#Q~(k~)c=LpIfrhHQk zeAva6MilEifE7rgP1M7AyWmLOXK}i8?=z2;N=no)`IGm#y%aGE>-FN zyXCp0Sln{IsfOBuCdE*#@CQof%jzuU*jkR*Su3?5t}F(#g0BD0Zzu|1MDes8U7f9; z$JBg|mqTXt`muZ8=Z`3wx$uizZG_7>GI7tcfOHW`C2bKxNOR)XAwRkLOaHS4xwlH4 zDpU29#6wLXI;H?0Se`SRa&I_QmI{zo7p%uveBZ0KZKd9H6@U?YGArbfm)D*^5=&Rp z`k{35?Z5GbZnv>z@NmJ%+sx=1WanWg)8r}C_>EGR8mk(NR$pW<-l8OTU^_u3M@gwS z7}GGa1)`z5G|DZirw;FB@VhH7Dq*0qc=|9lLe{w2#`g+_nt>_%o<~9(VZe=zI*SSz4w43-_o>4E4`M@NPKTWZuQJs)?KXbWp1M zimd5F;?AP(LWcaI-^Sl{`~>tmxsQB9Y$Xi*{Zr#py_+I$vx7@NY`S?HFfS!hUiz$a z{>!&e1(16T!Om)m)&k1W#*d#GslD^4!TwiF2WjFBvi=Ms!ADT)ArEW6zfVuIXcXVk z>AHjPADW+mJzY`_Ieq(s?jbk4iD2Rb8*V3t6?I+E06(K8H!!xnDzO%GB;Z$N-{M|B zeT`jo%9)s%op*XZKDd6*)-^lWO{#RaIGFdBH+;XXjI(8RxpBc~azG1H^2v7c^bkFE zZCVPE+E*Q=FSe8Vm&6|^3ki{9~qafiMAf7i4APZg>b%&5>nT@pHH z%O*pOv(77?ZiT{W zBibx}Q12tRc7Py1NcZTp`Q4ey%T_nj@1WKg5Fz_Rjl4wlJQj)rtp8yL3r!Shy zvZvnmh!tH4T6Js-?vI0<-rzzl{mgT*S0d_7^AU_8gBg^03o-J=p(1o6kww2hx|!%T z-jqp}m^G*W?$!R#M%Ef?&2jYxmx+lXWZszpI4d$pUN`(S)|*c^CgdwY>Fa>> zgGBJhwe8y#Xd*q0=@SLEgPF>+Qe4?%E*v{a`||luZ~&dqMBrRfJ{SDMaJ!s_;cSJp zSqZHXIdc@@XteNySUZs^9SG7xK`8=NBNM)fRVOjw)D^)w%L2OPkTQ$Tel-J)GD3=YXy+F4in(ILy*A3m@3o73uv?JC}Q>f zrY&8SWmesiba0|3X-jmlMT3 z*ST|_U@O=i*sM_*48G)dgXqlwoFp5G6qSM3&%_f_*n!PiT>?cNI)fAUkA{qWnqdMi+aNK_yVQ&lx4UZknAc9FIzVk% zo6JmFH~c{_tK!gt4+o2>)zoP{sR}!!vfRjI=13!z5}ijMFQ4a4?QIg-BE4T6!#%?d&L;`j5=a`4is>U;%@Rd~ zXC~H7eGQhhYWhMPWf9znDbYIgwud(6$W3e>$W4$~d%qoJ z+JE`1g$qJ%>b|z*xCKenmpV$0pM=Gl-Y*LT8K+P)2X#;XYEFF4mRbc~jj?DM@(1e`nL=F4Syv)TKIePQUz)bZ?Bi3@G@HO$Aps1DvDGkYF50O$_welu^cL7;vPiMGho74$;4fDqKbE{U zd1h{;LfM#Fb|Z&uH~Rm_J)R~Vy4b;1?tW_A)Iz#S_=F|~pISaVkCnQ0&u%Yz%o#|! zS-TSg87LUfFSs{tTuM3$!06ZzH&MFtG)X-l7>3)V?Txuj2HyG*5u;EY2_5vU0ujA? zHXh5G%6e3y7v?AjhyX79pnRBVr}RmPmtrxoB7lkxEzChX^(vKd+sLh?SBic=Q)5nA zdz7Mw3_iA>;T^_Kl~?1|5t%GZ;ki_+i>Q~Q1EVdKZ)$Sh3LM@ea&D~{2HOG++7*wF zAC6jW4>fa~!Vp5+$Z{<)Qxb|{unMgCv2)@%3j=7)Zc%U<^i|SAF88s!A^+Xs!OASYT%7;Jx?olg_6NFP1475N z#0s<@E~FI}#LNQ{?B1;t+N$2k*`K$Hxb%#8tRQi*Z#No0J}Pl;HWb){l7{A8(pu#@ zfE-OTvEreoz1+p`9sUI%Y{e5L-oTP_^NkgpYhZjp&ykinnW;(fu1;ttpSsgYM8ABX4dHe_HxU+%M(D=~) zYM}XUJ5guZ;=_ZcOsC`_{CiU$zN3$+x&5C`vX-V3`8&RjlBs^rf00MNYZW+jCd~7N z%{jJuUUwY(M`8$`B>K&_48!Li682ZaRknMgQ3~dnlp8C?__!P2z@=Auv;T^$yrsNy zCARmaA@^Yo2sS%2$`031-+h9KMZsIHfB>s@}>Y(z988e!`%4=EDoAQ0kbk>+lCoK60Mx9P!~I zlq~wf7kcm_NFImt3ZYlE(b3O1K^QWiFb$V^a2Jlwvm(!XYx<`i@ZMS3UwFt{;x+-v zhx{m=m;4dgvkKp5{*lfSN3o^keSpp9{hlXj%=}e_7Ou{Yiw(J@NXuh*;pL6@$HsfB zh?v+r^cp@jQ4EspC#RqpwPY(}_SS$wZ{S959`C25777&sgtNh%XTCo9VHJC-G z;;wi9{-iv+ETiY;K9qvlEc04f;ZnUP>cUL_T*ms``EtGoP^B#Q>n2dSrbAg8a>*Lg zd0EJ^=tdW~7fbcLFsqryFEcy*-8!?;n%;F+8i{eZyCDaiYxghr z$8k>L|2&-!lhvuVdk!r-kpSFl`5F5d4DJr%M4-qOy3gdmQbqF1=aBtRM7)c_Ae?$b8 zQg4c8*KQ{XJmL)1c7#0Yn0#PTMEs4-IHPjkn0!=;JdhMXqzMLeh`yOylXROP- zl#z3+fwM9l3%VN(6R77ua*uI9%hO7l7{+Hcbr(peh;afUK?B4EC09J{-u{mv)+u#? zdKVBCPt`eU@IzL)OXA`Ebu`Xp?u0m%h&X41}FNfnJ*g1!1wcbbpo%F4x!-#R9ft!8{5`Ho}04?FI#Kg zL|k`tF1t_`ywdy8(wnTut>HND(qNnq%Sq=AvvZbXnLx|mJhi!*&lwG2g|edBdVgLy zjvVTKHAx(+&P;P#2Xobo7_RttUi)Nllc}}hX>|N?-u5g7VJ-NNdwYcaOG?NK=5)}` zMtOL;o|i0mSKm(UI_7BL_^6HnVOTkuPI6y@ZLR(H?c1cr-_ouSLp{5!bx^DiKd*Yb z{K78Ci&Twup zTKm)ioN|wcYy%Qnwb)IzbH>W!;Ah5Zdm_jRY`+VRJ2 zhkspZ9hbK3iQD91A$d!0*-1i#%x81|s+SPRmD}d~<1p6!A13(!vABP2kNgqEG z?AMgl^P+iRoIY(9@_I?n1829lGvAsRnHwS~|5vD2+Zi53j<5N4wNn0{q>>jF9*bI) zL$kMXM-awNOElF>{?Jr^tOz1glbwaD-M0OKOlTeW3C!1ZyxRbB>8JDof(O&R1bh%3x#>y2~<>OXO#IIedH0Q`(&&?eo-c~ z>*Ah#3~09unym~UC-UFqqI>{dmUD$Y4@evG#ORLI*{ZM)Jl=e1it!XzY($S3V zLG!Y6fCjE>x6r@5FG1n|8ompSZaJ>9)q6jqU;XxCQk9zV(?C9+i*>w z21+KYt1gXX&0`x3E)hS7I5}snbBzox9C@Xzcr|{B8Hw;SY1$}&BoYKXH^hpjW-RgJ z-Fb}tannKCv>y~^`r|(1Q9;+sZlYf3XPSX|^gR01UFtu$B*R;$sPZdIZShRr>|b@J z;#G{EdoY+O;REEjQ}X7_YzWLO+Ey3>a_KDe1CjSe| z6arqcEZ)CX!8r(si`dqbF$uu&pnf^Np{1f*TdJ`r2;@SaZ z#hb4xlaCA@Pwqj#LlUEe5L{I$k(Zj$d3(~)u(F%&xb8={N9hKxlZIO1ABsM{Mt|)2 zJ^t9Id;?%4PfR4&Ph9B9cFK~@tG3wlFW-0fXZS_L4U*EiAA%+`h%q2^6BCC;t0iO4V=s4Qug{M|iDV@s zC7|ef-dxiR7T&Mpre!%hiUhHM%3Qxi$Lzw6&(Tvlx9QA_7LhYq<(o~=Y>3ka-zrQa zhGpfFK@)#)rtfz61w35^sN1=IFw&Oc!Nah+8@qhJ0UEGr;JplaxOGI82OVqZHsqfX ze1}r{jy;G?&}Da}a7>SCDsFDuzuseeCKof|Dz2BPsP8? zY;a)Tkr2P~0^2BeO?wnzF_Ul-ekY=-w26VnU%U3f19Z-pj&2 z4J_a|o4Dci+MO)mPQIM>kdPG1xydiR9@#8m zh27D7GF{p|a{8({Q-Pr-;#jV{2zHR>lGoFtIfIpoMo?exuQyX_A;;l0AP4!)JEM$EwMInZkj+8*IHP4vKRd zKx_l-i*>A*C@{u%ct`y~s6MWAfO{@FPIX&sg8H{GMDc{4M3%$@c8&RAlw0-R<4DO3 trJqdc$mBpWeznn?E0M$F`|3v=`3%T2A17h;rxP7$%JLd=6(2u;`(N3pt&so# literal 0 HcmV?d00001 diff --git a/extra/haxelib_src/www/img/haxe-logo-horizontal-on-dark.png b/extra/haxelib_src/www/img/haxe-logo-horizontal-on-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..3a8cdade0a6795732162016c255089eb2204a291 GIT binary patch literal 1566 zcmV+(2I2XMP)x(`ho3 zJNNV9&P?yzxp$T%V~gz%4m00(&bjBC{O4@nM5T7s?!h9VLIMG4L=jamY@vFB)6;$2 zAtr8iD`Tdnrb8oL0!@gDNnDMlV?ojfYwGJa{kfu`&w1vIGWP`stg%pQ&Y_7(tu>kv z4^gT&Ct5}%Wzs1p73o+IYb@9(i9j^l-#TUtHf)czotcmG|HjZuOsug`&LI|25;`gg z+g6%JGg$Xf>b*t%IvHuV{?^S-aok8;RXyl)6+_iYW3dKe5hbpFQ*rf9dCP%ET)y=#dmT{Yuy+7^J)X4+a4xrpfR9{l4B#ao?C_<5H-Tiv4g)U(0Y{sI zz-K@QaJ9$SUi<^RU1r-^VW5esT8YV&j|kIhz#I;>0!l^FtxN<4#8jTkoFs`Up_rJ< zf!AEV^)7oIu+U+TQYe-Nwg8tqd^6a>9(VZ6jQ@34|0K3x0M7s$9Cc~nw#@qu;I4vC z;msIT7E1%eYU#|VXRSl1j7OXr6;MH6vjZt8@3URu*lYF57g22NbZQlZRyL_(z z7h!)XUUk)N0)Cu(i1UvIdi0XQ1D}UbS$qYPxI!smB;Hk2up6OoC) zpiCH(^}imuuY_2ufiEkJ@kwkEvwVxaXJxqw807ScZv<%ac~%5_sdMjlKVcs#+_8U6 z`3H;@c%NG54Q;=OX&w&to5P_NDiaFq8P+0(>Yv4|s+48GN{4*__?i3z#8rUbrTi4$ zGayExP-h((v6K;Lu-bLR90H_hk3u9p5*m_Ys-2a}m_-b6S1HCC^1n@$un)+8O)glfj1O-IZ@$`?%1BcVZ=QfH@f@}l7A5fXaQa<^6V|ZB_(400=V9%{8FOtoY9~R(yCKVW>QGy3zicKKmrm4 zI%he%%HbB^I+yP;>`V4jE`J2L$6?oE?|aTH#Q-qnuonUEmxv*WovH9D5ppY4b`co>>_4)Tcd_qH zXB`I6WQ_-Ed}`Zt#2m0DjO=mVS114#mPSbw%?-|$cJea~CxB0?KI1o#lRcb;OOHw-Ldx&6w!MOLtu^hjvPPbjeWEm6dZjCX+2 z>70$^XWjQ=-;136MkvfQB(a6L(&4Ma&N?{x4qK!w+kuN+V**?T^a0}gsc-6A{Tj%Wj*-y&ty8LBjs@CfS~W{b`~RLbVGJ(VIez}f$0}gB_bZvwG3zg5 zG<`IHn$n0Ry$y%{=wp|dbgK`h!;3paq*GEFE3P4~8lB>)u=SsRh;s#%+_qqkIUGu) zj|L#28xf+QhEY~eP9!(o%CJSF3nfhmF-hrBE3UDQ2kIAW|NZ>`U{ryB0ZEY!a!Q++ Q&Hw-a07*qoM6N<$f`$IY_5c6? literal 0 HcmV?d00001 diff --git a/extra/haxelib_src/www/img/haxe-logo-horizontal-on-dark.svg b/extra/haxelib_src/www/img/haxe-logo-horizontal-on-dark.svg new file mode 100644 index 00000000..c18ccdae --- /dev/null +++ b/extra/haxelib_src/www/img/haxe-logo-horizontal-on-dark.svg @@ -0,0 +1,154 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extra/haxelib_src/www/img/haxe-logo-horizontal.svg b/extra/haxelib_src/www/img/haxe-logo-horizontal.svg new file mode 100644 index 00000000..3c2ee83d --- /dev/null +++ b/extra/haxelib_src/www/img/haxe-logo-horizontal.svg @@ -0,0 +1,153 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extra/haxelib_src/www/img/haxe-logo-vertical.svg b/extra/haxelib_src/www/img/haxe-logo-vertical.svg new file mode 100644 index 00000000..e3351449 --- /dev/null +++ b/extra/haxelib_src/www/img/haxe-logo-vertical.svg @@ -0,0 +1,119 @@ + + + +image/svg+xml diff --git a/extra/haxelib_src/www/img/haxe-logo.png b/extra/haxelib_src/www/img/haxe-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c89a5e814d9c38546174ff949b3c3af3cba03306 GIT binary patch literal 5072 zcmXX~2~?747jAJT`L$AXG|Q=6z^IUjHmpohbAho^bHOc1LD90rwZzJ_+%gwJP^>h! zaw#{;N>bC(Slq%TOIs9|+{&d9)Bg9H8P8G9z4v*a=XvkF=i@uZAGft!`@fC0Qhd`cO_w4Ryas%1zR`= z+XqsE!@PogR)mFx8Ty^|XPovr=VKTcM9Z2yv~k4>wZE**O&!8{6WPZCwJj-@o~_4o zYxyYCtU=waZ7l`^k+X=`Zjp1tA7A(Ay)ac7lpWrvsDW32o%&r-<+N&D&(-~jzH85? zJ70FpL%3G#wa1@J$nKlLSbzlrhk-`8deKqg9|MhLs;D)Ey z?OdC-4lXz4jBZ!&@~6oNAH#_6GcN?gn7-%cx9;X+)pX3vODY#We6#Q=+ZDLH^g(In z-mfcbL}m^!qkU?cL2+?wemb}ZL|yvf1pryU1Q(;)xMm!F5q!^nwLf-e#?3uk3}yC=+&(f}9ZP zuuu;aCUSS_5Y@|*Cx|_2IG~xc6A)(;VtCPUApxEZ0!~s7I1XK-BE??)+vQq8OeUu( zSf=vokC2GyWc|TGi<0tzjN@vRJreDP1Gy5 zB0={!MGL=8pz_R5-;~V_9(#=jIT5 z;^U2Qo1${pX;zt8#UEI;mI*@xkY%p>+jFLyVpwrsI^Slr=@uAOs=Ut)RU)g|>9Q^D zJqd}NF%h9xt(rV@`GNeW$?+Y7*IN0Q2Q+xOTc#ZTuF*Uj59@Ms2;&a~?3Zc=3Zkw{ zG5hYEU7nI$hnJrt%i$l3CVIvm?z<`8GPl++bM1ODbxyO-Aj~%0rF`Memz$Trlw*ih zrwyHM`qfxQNkgZ{FawQ(&8m00vkbxn`!b4e7N4FuA5yWfG5qknMSQ48`gCsI5nKF& zf0N>o6eqdCnqQs9*vRRY-sAVVHsyWxnwy;0{X7>J{ywck7q2v2_~4uE7UDCGTNt%U z3105Y0$HI?cSdP&!hOlkWLp$Et&;Rq4v*BZ&vt?L+mZEY5y5ka@HkMtb_%L)Jp`)Y zqAn|H^Q){RyQfEq)9Uuw`0ZDr@Y^>Kx|2d=&gSWW`gKzwrrsWe+srdSXxUJSsdpm1 z<#Mf&`4&O4*N-teCSY9q(ujVkyohfTL`4@6uB)&H;leZsRqV65ym83J@2li+0?_5A zwC4e#s+d`X0`N>~7=fxr1W?tq&(_MKK-E3}Rg-MaLsjopi*Q1ddA3$O1u_{PGmn@B z%y`acC_Dg#Kv$-M)B~>88B}3%u7g4MlWc7g2enOZ3Sx{YxsvgEZwMVVJ4zfu6&T^- zS|HP(pzs-IjO0m$4qt08#N-r$5JNQp;f0P$%qOx)XuReD&Xrrr(rD@ZYe1l2=v3!& zM^DPVA@TqU0fm8{t7wj*k5UJkkxLQ;BDD&hD@Yt8Pu=dM?UiyvG$1mgk%0`F!Hb3Y zn%bGd0r~?RI`I~0>iW^%jEwQ4-^rre#rGu&`a^5eX3&QhzmE^@A27cD@=}Jv!vZ6F zyRKAT_w0x;t2%~>T`ZAR9JIIF_b42{I5#9FH%zSA5c5#B8{|SCdE+n64%L$h?xM}b zHFXje>-Nr*lFiJBN9>PLRvvA1!x9|AXDg9~dxQxrMLcO#b{7u?7vzn%sRh-ZHbdhW+su#Vx8B{{i^W z!-W7?hd&zZW2=xW|e4G4xq0N8F{w2lMmrj%y_VDY>D_&1d^;HqC$M*Rf58N5;-93K&W ztOg4eT1u^fQa0^Dp+9`4$%KLZe~gjE-@&MCd3Hkp=HU-xHjO)r8$e1D1OG3zq^U-B zth@_EargG%UF8)&$PFskKF7)=D3!kf-?s>*9yP`ArP_~ih#?WmRKgZ$SFv|Fh}cr? za*!fyaQ!b8iOuoaYdJ=;uG#g9RhffX^AORfQt7vM229Uw+r8%A_Ze5a;h%RR_molv zKtRdhF>ftX%LlE)=BzE|-p3*GSA2id+m>;n3;r36Jm82kquJP;H!;Nj$<#W7)+ykW zNlAU&G`j=VhK0{C_ev3s?xb_2)J(vYdy5rhB;P$oCIn#rEau(?T+_O@c*%mKr)-r= z*c^UlDp<&bt#-{WUxg$7FjQm7L+W$rpyr98=N~fKyWt%>k#C(C;Xo1_=N!}}-`zqc zY{&W+;~xRCID#_XpUL$`>wKUz^wZakkgQR;yB#F80urB{VkcUXj&}oR`ZCk z$D9>3DTcqEz9pTNyDf8Y&%@$1-eh7kO14IZ-(fuP6+#cPdELx~h_dRK=ZUa$j)!|9 zujZ-8R$>Yx%H`LR{9)%TpT*FSegvDm; z2tPSwT&l7Ze$xGyh>D!jdhu}5X)5qYsqMZkCtu5oONKRcRTwpLI-s!p>BhV;_xKX? z$Z!qg*Y*P+mZ#dU*Od>dBN%!JZAN#bB2RYck}(!gR1V>0C_Y=VF?fqqZ7bNLee3W4 zy>pl@a}(J!s-qkiIfLpJ=ZQALcZc-8&}FJKi(|&;o<@9ruI3z+pzF(m7bUN)^DC2z zsyT&qwG)rSHt&6Jh;J&YvWC@_M<~44>!drr;#AR|cnDu_@OZvFXWjX1itLe9Jl8D? z$^UgeAt2bs@5t0>`)||6)4uCkUmyByk}I4$eX~^>lu+`w4XiFTf>a0yo%#Hh2W4mKB)UrJ({OSKr-z*3*Ve`wbXrofBBkmerZ0~Dio@U+={r54oX zB)iY!q`02Ua*dfTGNA%;t7&VCTIob1G)lGmIc5A9ZHTqTq=M+zdhr=f$IkziGijJi z9U*FxC9zmG>vAzpr-QyutuhC#;|lda$;$!d2Uy!O%``i~`c(t35-yI5427pkZu6n+^(9gJ3=_K9R+bGI0m z^O`Q-Pjzx7j6yAN*_xgfWNAqwobtc6lR8Y+=!do-7HfgJQYMM1lg_Gj-a~uA0W?UX z!8^YZwB_zzre-Ar?X??9CW~143Xw)?s~jtzVVUpX1w9#tZ+UvVB2Z!B!N_oaK`Z4# z>5#%=M=TqMW2C~TM@iFe;!y12J~*-ua)qQK5dGP(&85B79PsUs4lM=_%SeY$Pmrda z#j;nkXNVlI&BqzYQ*67*>2cDCubAI7>mlTVVWVl@vYm*JecZP4%(K|l@8DD^M5<54 zAWXAi=+fRQPQO2_@}H(`C8od?M@hae;=UVN9qe7hpntOQdP?4V)i!QhTV`34GFhng z10vl@O#cV!EH=Zg?t@bY0BNB?A}j5qM8VR(OB3gd_ELqeANt4vb)`+B@R}|-BWmNv zcgAY0vD< zXnBJ|t!b;oU2SskTt^84`iiq7qElFD##L?-FKzcarV-AWH0Pt904{Je&ysd6{=Oi| zx*PzT0dOk-wxeuq!D~>RL>X?+2(EjG>5#bfm{`x(ky&cc1WXqKovqERTz z$^sqMh=+hnXP3ekXBB5&j;(YxUL!I7`}&c?YySS`^y25ikLoXJvXD8ETPZf9*b-j7 zt3R}0X3>tjgZJY@=J3~`Sf}2;j!5p)|U(8*!6_2QT16F z0YP6U>eQprjKIxa=^ZyG2J3tcSE8pDS^JKWpiVE(s<)@PH5=7OllAG^8;v?qU^nkv z(IrWGR!CVY7A!J-J zE-=1kRzT9v%@5c4YOeWK_r$>G5s@p!uoR<~=*#7$grvdfE)_+|l0)i@l}xU+xo|MH zB;D<}u)(}EOm>CC7#E6k$y5XH?0{%8)sS9`Ti?ht^Gw#y^_eGhwHOxpoXzbrnlTZf z=7*Yf$r=FIu24;Ke@mtb{$S`bUE<={O-e4bU{kc3ddLf0VB^kejFMWruFk=2M~@2? z%s)(tHerdQLV`t=RkKNg+FQHaqKnxPdNOCG%ab?_7(RvaTQzIzmbRopWvIC!sYVrvK?|KjUb>7 z6Mr56gS?SDiV*CgXOa>T;ut|5gw!SLdwY>Qjtf_u5O>~7q%Tg$g?s^z3)Ec>RI0v( zZ+);ZBY!Sm7)XBceoDxNnAJ{)Mw8!}FL{M{)XEpr2hJ{kmHbzs@uSJ}7EFHB)UTE1 Yo8POj>n2x$|GurTwy-rXBb + + +image/svg+xml diff --git a/extra/haxelib_src/www/img/homepage_banner.jpg b/extra/haxelib_src/www/img/homepage_banner.jpg new file mode 100644 index 0000000000000000000000000000000000000000..236f19ccda1691dfd76f4b92f5f00ac057732568 GIT binary patch literal 94785 zcmcG0d0dlM_V*J)fTk?5q*YdvqCo77Vu+Lgfsh~|!zOX6cB*38;*?eeL_yK8i^?YH zl${`(w6<00W~WwA6tFCbQibYNMFd1t5KwS^zc*-W`V_& zqigT$;Cw@-uJ$|-=cHjM?e&XaIz{E_V=Rht;4gNdRL{>BJ2=o(Gow6vM*3j}PpP+p zHpOlDa6@85IOqKYj$iOnpAR>Dw1MNeP`J>MztDl>uuUk8d|SYO+xgiwx`8|{Zj;NR zMIXg3Tpzyi{fLEO8$VpMZT+T2ix)a9qTD>TZCW4pK|~zq{fMXyABpVl{`-U-XG6Hi zZsn2yhk#Ae2>Axz#Fz+KV&ICf#1F!R;dUPGOt)<=+dka%VMN?|&bAMuKZyZ-+h&ue4YmJcI7id*KzA!vw+h~2m)CM-f^M`j!T`)rr~-)3vaS@hC! zy&_^Z#7BgC$87viJKm=CF|iRV5;kGLkmp0sV22O_YkcW_jPl<|F>?QsG2%H>4SoYZ^N=g|sUp0F56=NeqBbJHrtT*P(euK?^<1ZYp`8>hGx1Agp^7$^F zGH(}ApgW)M`~I@PcUG-gyT*BG9kpt&MX>z7VTLxWlnSqX){tzjx-&*E<+E`*e~CmdH(Dd%8*W@bXas2 zUYw>VrX)otkFCH{9de+kx$iaIOZGgFN@<9e3TEP95KJE6LSBbnIw_PyskxtffMQ@A z9ffQjo*2+5T`p6iRMqf2Jw1K#h+;BB6imv)n6lU9Q50K;oz7u!?6m{YCXMED%mw1; z0jU=U^AOM6);`lI7Hq=v8pLbOzGO|B^$BX>~u;+(R`U9DGJJ- zqK{t11Skeq%=Hby8U8~D+C)yv8NEG5c}+$v1;%@^K0Km=Wj7fv-U!w?0wL+iJId8 zMAY#7LKGop&h+}jm?*A)TQbdah716ZuI)y{lI4z1k1z3v7 zxk5FxbKiXhMWqQSU9e*{1MB{+ffKZBU~-D^EomfyXI|=NCgRbaYbd zA3FA6NKgZJ#lKOHJOzU)$nOl6aRNBMH`;+b1-SS{4`>;Rs&U#xUSPdEEada|PT()7 z1twt?GVaW5A!si(W(dZ8NpuKJULIF^0XHN{_8&%lsXu1Rz@_d>w{RMglBZCBdxBrO zZ4Q3MbZC^lOGS-H3xJUo?zL2G=6@#l085aY6-|F9k+>ev3_Tgn<=g)#*I-g9`bCP970q zG@LwVTylk`WiBv-_Tmo*@VSKOR@Ka1Ezu}h)N5n`HBMVaK8GjDQzL*oU;@Jii)Y?@ zaU^O&tG-{{`0ba?*3ptpJ0aX9lOq#G54lD?5ZqRrfY{XO|h*g&pbc6>HznQIN+kH;IB=5&HeHF$ntY z`5>R_`2(6KIpO8WYj_9BjBE6=%K|gQj&*CEGx?vfG1H3}fRSiGDKQ)&fPxS! zsF3o8Uv`{2D~2ARiOI?iqxlt@HEK9X$2x4DE(Q8%RiK!36eLN{?cAnN)i7Z6WJ?7h%Gzuz zqtx~U{|euSQ3ti`Kc)WzJcj?#6e`?;FE!Jk$`wTGL5Qomx97f6Fb}F8jLo5RwCn;O z&gAgUxbc(}MX*fFu1yZWzk<%qt`%MnePWktjnv~~54wDxkN46K2V(L9c~}WE`1v!v zuGQ+Rp@58e ze2|xZh-#d{9BhH)cR0MN?&!X71scH|%mV4FlX~oaXXaqwdl{VV*>Xl8_!+7NMxE?oI0H zmUa**Bn2(6Db-G@-s)myoC)3=iq?pMAKGYOUGJZu5a|~a7*L(CoGjQ31NfY;>Iv4kSGp2L#;l4O(B-oHalG2p$Wm^ny&q({`fRgpO@GRRhymQeaPa=+V7 zI{l%Mkbn@tg9SXY;9NcjMrj(B>heQd^`PVRO*sm}6KHUP38%Cs&_>+qI>4d|0|~oV zt*L^_(5|f#Yg5Aqqm1naOuEZRpO+eqIWuDweM}5s;Bl5>#+u3^&jw3v4J0}xu2zPY z`&iGHMr1hkLZWe$vWYe#tZ;^J$Wqj1TR@m=1aU4_MrFWfWCvRXnz(NmH#w(x3EIpl z*cr{^4TNGO3VIGur`Rdjz#v@FO4VkU1r#}i4$RDqUfF#o-er!nrGK8P?z`~{A}I)n z5Ca@l!Z@ji;#@3T%mpFDFPpNH-qsHOhr65!7-TGJ50 z;Tnh~%GwUL=5XjhEI(XP!{FU<%fxz96b4L~ljz!x5-4G-fHI?EfD6%4Nbe0^5;bD1 zmm7T3najtkz~N$ws^$>v8_)ujW)22SBM=Oh)}H4lXS1t$G@5|{%?~`TcJtW{hbx#y zOxIahmCEiRST85J#t+VfWzbI*^?%mBM2biYmX4+AYBe4i8~UQy$WV!ozcFuG`e$&9j)YcHEhR__uSD(+UGE({acx zof3hx2){rN85xX+=oYAgTG6Qxk6MeNGR1JxYjZ$PD2+-u5|sy(a1d!@fl2E)%Z&Cx;!oH2tDr4UtA0~Dzc?La(u6S;*6jew7t z`x#k5FI6_wt2OFgEQSivnOorDo2Ym`3{jphBaiZUjR^6J)_XXXk8_#|Q0!-*zzui- z{<~aJX}h9 zfm{PPko;_DG9H9YC0}Iqq%nPgwi;@ztCsMCJB*s(1Y0r%pIROU{=lst=vaMstvk)cBEs+Y)1x#i@ z)C;J>B`!MFqL+;TU|6K3Kf1zHla|iG0W9;P{fRQN zaA!g)kVZ=xkQ>yYundZ&nKaoA`it!uyns}g82~y^W@O=FA&|2vgPs0QXj+>#vm8qC z0sxo^>v=5x{hE?RW?QGW61*XqGlMp88Br;UbPf+rs$(CCz@eBAC^bh*oT3Sh%<*$H zMPVG(-_>ocK;IB#^$=Yn0r$U&CYWegu+2F1H&}$95v~9h7V4B_+6TJ|P=0WQ&u(#& z_Z}?~$h;vr!NJD*H@dpZ2q=X0pgq^W)K?ls#1@UjzlhrZzz&oky0%Ld>!$za3upia zW(GK}uNb@&rE#~XYA~9T-HVX5A+n>`$w;XQC=mqHg1FPCCVlW08p#6GvS2QN6!b-o&^023-;wutdT3uYRK2}rfO5JZC^_f*N@J_zFQ z9|=0^q+&Mx%+4K8mLE`%(HLYk%{!!>GN0HZRgu}{soh#dZm3kTs^J*?K~GTdqpZ3P zZgPt27A(hJ z*KM%VJzoVnmsb6mgrAyf#~D4$lwkGo7?;Byb_FCc<%(R|XxB0h4R0e5Cc=BXQi+%3)W9 z_W7Tb7R8jSYMkUv1@m;ZqCsRGEK6Qx(d%!!1H&-AHN3+>EW$TlckLc|FI?(kd$+p5 zpcnou&BW}go1LjH2Pz4A8fNqIh@3r~XbgEnlPLa(Wl&V5swTnW3|WadY7=H+S<1VcWfYjZL>%*kqvSZr0@K+qRSNDLv=Gd;88{F!hI z0X)1iV#b?V*~41|A#;#@E!uCnue@N`T1_lDEvR{B<-Z?;!HvYNCHf7G3!TNH9~*WL z<<3Nw@?PK=iU?~a`2ZDIY=>jzeLsK|TE{jf82i}R&hP{h3jr1`sd}9Qt)W*F_R;O6 z7m{KxXdMXRW&N?iwrW`z{D8b!3X~^@;aZ+L01q!DPopBrA&;b0N_bTf5Zm4GD!1k4 z?MxfevTxU{L5J`(j7Tu1s-esUM#$L-%VV=r=tu6jSKh?d37bV93|-@PbKSx zh8F8m6IQv!$Ww$U)Ah0~^s?y@JazBUVlY<+ahy!rE8_0672_52#w_>c>5%bgh_~ge zRt~SKvf+r@OlX-C$=oVxQB7DEgu;gXPZUG10VWYx29}Ev*ev#)c=rS&mWD}F(GHX# zPo)Wfw1P+XMAz_qDQ?yELicMyyzwAfYuj_L7_`-aKW}8!c_y0*ABYjMC#@U2a}$Qh z#?K$D8JQ%|uCB4Fb>m=f7`(R^vD5OZ#Wm}rGw*h`}Hv(0%brkE1KhxL;7SsFvq ztF=P_y$U1~W%Wbw*tx0s&2s2JKoC&VoQkYqzypG1A5OU=RB1;RhzuO#7P@}5`4lzkXtaY zg@llxRFs+5XF!7s30Fuv7G}#bciQS|&d~Ffh1NDr2CDvONWoorduC-?%0W6+xG_=M zDP~!ZhBmdbG*x1_)A~fe3*;c9g`R?M5L&w@!6YT=>WJq8i=nAL$xsvSe4u|KpLT)W~dyF7Y#}q6ZQnlRlRBpC!=B~ zq|cD$Sl~{Gw$#o=fbSMPtTrVA6(4yUIh^>>=dO*+a4jL3E}#L?KtSwfDzx z``r^#=W(=S-~jIg+6(-O6uwh*hGC(L6;s|jVX|sQGW0q#u}KxVue9|=2ZXL5=!|eM zaFd&=FYQhYn&sK3Xl1xo_};e;I}=`eHoEq#ya&pDk1PUdQ-koP<|#YbP-)P9$!`PI z5PE?vfa#%lC#gQaY)^>tq0hm`gpw5dPQuv`9iYRq{RO&lQ@dcTj|?v{b)FzjWEa~U z-iB-<+gud&!-Tag%af#fk+{+8phqB!l$UAKn2^hD)T$sYY~Wf87ZK$amlAG!TUEVh zRn&P8Yx0!gnwQ4V<>p0eQgz8SbQz8a0HONC;0`RM4ZC)-BSUU=j=KDCR*gvit6|#Z zp#)>w>|$;=0en^#0gtTKv)@A?CSyErYH+g-5_D`z-rGH5Sg0QgZ{w==p^LJQCKkw5 zifVqi0$E96%MwWwy%goS?$?z&iZ`v01t8tmuaaJ1%FOr=JA)! zWX$Ic{v@Fja4kvok*c@wWA(#Ar^MtbGu~NC(%@iOXcKsv(kTn%kO$g^9aS0JI?d(& z=*jZ)N2<;y1g%yXg!ad}S5}?bG2W9Hw79u9KnZ_X<0%%@$nSr$_8R~6);elUq3(CnRLw&0244YQ9g@?YRkmW`+`rt}Ze*F` z<5)T5nl~(;)(fhYkI!)-et2y%;%L4+^G270cD$K`93G+=5&@L)s?_nkW~;6}+9wt+ zmd{^f@EQoO>}`movC~+UL-NVrMpl$U7NE zkXz7S!B)KJ3Ooi=+QmXlYAAM{?3}z$c0>D|ce#$vdH!OE5;-$X&p00F3V#Hb^)H zZa-KN4bnR!5J;kjD2EaQ6;q+)J~Q6MGH@w}nwcmqAXS&)TG|;(bmh!WvArNMDB+Ha z8J}_+>~byNZ|QGk+@jK{m{<4J1Y4nMYMv}lZQc=kY_hYZG+n?9Hlifu(s6IlM}yRu zr-76MC@@{P0pcM}sand=mmX8kfTyV^EOQv-71A`_n)Xb`sDpL85$xb??4+aHr1kja zc(;K)l%D?_H}61rAPR~avj*t{3Wb(|p%3+?k-0euCJ7TArOXg8lxiR$w*x*zw2DPv zN~LiL&%*b6J_EfyWMhQg+dWM{QX%FdAID_vDImI7nRqt$Nqe@q)#Z_U!4f#U%*3G0 zw_Wm7Q<>jQnseI+HVdt*x{d9W_pQYIki0sZ0rs6(-sMSi%G|YFdcD}a@-`RxhiPan zy^0hVPX+AT^Pq{+wE7#Pk|Z9|)FH*ZhRCiQ0*7Kx(6bcUGm07A+jA$zZ7}v&>d9E3 zju4JAS$0QMCqa(&>^9>;)j+I^RTnhJPrMP4mpb)twI-0z8^(p_$wqS3JeEqz>Z)~0A934J=KUi6fH1QV!er+!TlMz>^TVAt5dM$Jyd<+}0hgB5i7PSxFnU76YW1Z?g-RCFnZCCiXlJbU= zJ5u!zKdcKYf|hEY_UUjipy72LWsN<2AZ$_4Fe;`%sj$@tkFdAux&n8=0X-wzc5BZl zWK$4%l$k6Z;E)?Ssp{<}8@g+F_i~YNT^$(ZnAJYK-N@X1x%z$yhwJItIGyffJa}jb z`NKha&vvFktk9B~w8(rjaPDSn6;28JyH$)ljWgv)(o~DXMTUv+Uhb^@DAFQI0Y0o>Fg7q) zU_pRD5fNhA)~o-hPDS@WvS)}%N>(@CafE=O&QO-7c{G&JBgn+9Nxd<)LNJ+M3FZ#NzvM;GjcZ%Q3IQui$u^R`}(&Brs)~6>2_!N@ecBd@&<8@zQhtW z2<_w6Hl48!2H{$s{S$8N?S)FXb#3jfgl~lOnJMaF<0=|^Wk;1Y?#ruwiPtlZvdIT~ z7*)9SZ|^+gC$X^CmxX2+dw1>Mo{QACiZNz01;;bnU)!lI6`DXQIgkS=g6rBN%Z;85z|mlDkk92 zh7W9`-Q>0pZFMcS*LNH!7S$b8v6@=@5=}N7$fIAi>`J&pQHGWQ)~5A6lL|v6J9FPX z>#81k|7O&}-Q@<&x*=*g2n4tkJC}AwnVw15H;0=SPA0%6R?HqJ&l{UPfE@$m!Svsx zj5CtK%%s)Dc5fBLx>!)E4F5UKsmFSTnFist$>W`n?$n~@zUYba1Lm%5R^N_O&52#r zNMhwT_HPw6yUd+4S$-hJ%!zWIE6}Lhx+ksnQ2M*atQ&f^VA)ki+ONjC)hYX99VDza z0*K7yrP=7D9zog!iLW8~)o}VT!_r3d5_1Dvswd2Op5sQ=*AMbzkypw*I3ypl4BFh? zh8!8abz5Kt(!1UAYOY_L3o9dN*1eAMla|?KUCYJ#%CWMp^=dkUzu9e2?RKU$5#E3~ zHL&Ak`Kb#?W%Ii03dhT1lbf3g;ER(f1wa2s&PhYa=Mc-qPUtWK{|Pgp8F5UQ@gjXy zuh?F{bhKC$E-XO;QA{ry-?KevnHaQZZ8!Fj5;sNpK(-LUD&Z6)akOutivuOo+U;n(Ik}DI_-1#elcI7 zRJECe>iH|D>(XG86>WZ$d%}QAN_pzJXv(m{xoJccK{YjBjdd?-pSI22e9K-JdAOkR z1Y>ych9rz24Op59tYJJU3cgX9(HsY{d?dPUkV7dTx|i!hQY-^+==pBJ{=`*h>+vI= zsc^HDqgDazJBis!%4G3Xk^XnX;_$wNPW{*s1?5(ET3F%rK&hw=^m(l;M_)CNDCQbb zCOo`%$TE;2imF!Yx4T7sb-xUI!&31?xpcrX(A&R|FPWJW7+%XuI^+_wVk0kVAg#Q7 z4?8czTU|?d1VBod}5|`l$nLoXL2_WQzYLZ?cVHKn!8-gmoC*aDK=T(kUR** zm-!v`AlsU!qjpcu4c4^xZFblqx>{#*qx}4ZU~#ZPjC(>mqVyKH4Q_*NF4ou2(U3!5 zJm?{g9-ZsfAIlGIf;rbt4#*;N(qWOjs(~2iypipGGW|AD-QixtVtZYowd2|7JBhig8zLYZ1^T-|qh-dK)e|V% z%5qc4q;s^bu|YYx*22Fs;Kj#>pR?^c;{TSu)^FK^-c z!Z)OnLM&WRmW2_xsae-t=ob)!(ozRm_pSC>8r#XvCHgUUglMIXvUa?YNAF3Zt2enP zj0YXq>RcY1Utnuk%uUhK4nu&y&=llAgHU6~C&PD(K$>-V7(TaUXVj)R7kEvG!nQhv zq*zPyhxmz11IZlyF#Qg}cH=tJP6Q(jzsgCm1tf=+#+yD>KWVH$>9k$m7^$r5j#la9 zP1h+W%de}bw#IvwxnIDIJv7%1_pE}xk8#)}v}`Zpi^J2Nb3AZ_rXYuqGGv3z9KvgJ zQ1JuO6^ndgZH=Qipe1n%{O9nF7IAOcGxYPO5hN9I1C$iX#Y%hCFjhwbAjYP>2tmqb?~BTnKY5)SL6u-e*3=Q<2;aj`BqhdhLYE>@w?>@2RO zza+M93o1_VPhqjm@p!mISmbQkInM!>*FZwb`Ce}H`oK(C<piO%&p}oeKFL4s@GFY=A+G+LCtWDqv*+($F0@a z13(qIvA*(NX_x1H<7&6e4mbE_l9XbX@>9PgGQ-5iKSxtnS{WB&dAO|utC>q6%8LT42K{Mbrw4QEG7Y@D40^c zz>Fr~2jT{$lL9jwO)%DeuUwiOw0^?GGj(9Dpbwt{q4)HXuYhbeA@tzmhC zYGyN?OeVv>h@sb6LqXP1G!;5J*IqNxwMHGW!S*Kxl;(hD)oNZKA`eJ7*w;_s#6VN*U3zvC6XSjTMR$EDKLUB zF~k0G8VCCV+VW=1X*jwLrE{z?>~E=5tQtK->)3qt$W|BjT>Co+2kCle4NJSQ7Ak9y)JR7U$sW31wOexYO7L7x=h<mQ`*-l&f~BpS5$b^50?Gmh_P}{i!Nb1g3J%*>mbn0+O9E+I{YPY=VLafk2gc4sBDvP5IO%Scso{(L!jY`NZ)zS>x9abi*heY}?1Y)X& zO6PF>6;e){VG%!+%u1(_!dzG#j5&KAM8-H9Cv zLkoLe`{*1Odi{|8`%01ugydN!-*L5YBH=?Y&9Klds?!BQ7?Mb8y&z=_ta@GPz493A zf|0U)#Bl9P(T;kPDY1-$s#eSh z-rcdAu1Xz*rx7T6V^f>me8Mhlp;$mpPPG$~aY3&Pi}VzTyaS_bvI>sebV*6ARFl*h zrDNt`RAE1ycs4k+hq9&*mKlVCTh@1v19=cI?A!)sA{Iss3M#j1h!e{*pc#bF84$N7 z!_w9mK2TMq%iFKRLjGYlHi$^Zm~zdVu+BrNA)-4g1uxY*89wb$VotxXP&mgaF`K2T zcGC-5J}e*!mD0c{>A9^)UsBQ`rHPqCrkJ-Ldy=TE>9I|xD8Y5yK7*+=J3Uo zJq!bUvkAIg;l1)rNshlttW5{Y;enxms>0A zW`;#c%CP%v1bgyZ8Hcp=h9IA zC}Fqx=e2UUGy}18$Z8J_ss0p86EpQhvCy(L-nEPd$LpFyV%Kudf_xO=Pg>_uluAX( zFuUfao=K}lL7csw3HM&pT~RvKG~kA`S&~dY#M(wnFKq0gYA4Q>u0kFspvXyX&OMAW zFMMQ(eG{l7a4%R!SBTgx!#7+-=di%nA*@>8@C<)tBiFz<^WX#mP*kAQ6#~yOR@unr zQf@w_lUDl(D|e%Y3ef=tmoTffcUUwZs2Y-!7{mt|#GEMQc%dtDhpc;Z-9`&_Az>g8 z>Y{ukN^_?WY}t!z^!Ctv<@kDxrD9WJpa>!dE&^+#V428lD~H43wYCcLSQ!CGWTP$> zlE&+)3n_MA-hJN+br-t)grLO@^_M5iUFKR2Z8ye1H0=8!`n9eKh4-T`4NXIR^YlP# zoGA0F5mX;_I;SAn#SGDIrej;X6txm+3%w?l91Nr@U}Do(OcIx@YJBy^m(JrtD41fR z*2E$3MN(~P?V0?%2i9*|SE&sx+act}$X_P+xs*2?rrLlDyMwh&D&{6PeQ6IiiJMxl zZbo*y47LM&q!@|g8HC=mgc|1dxhLG(Lp|X6oikL1#RLQnDEBCUfGYj56=J=%5G|t z@gZcb!bPd(sm-xXj+x+_B|t?*0t&svu!e?tX9-mHuGaegO17j z%W}?i&AL3nrZWV=hI8FAW6WR)j`btTz{abtdqV3SslM#oR)*6KY1H8fCG0V`aoo~y zuJ6O8`t-pHw>|>{RABH>-c}=sZfej2fsCwZhiONPc}LB0pM07E&xwTuG%@7}dng4v zLtzi&42?v=1!+fAX}L#!C(fRl?icwSR8i2rc>_?{^)?(vx@IiT%UD|YuG7Ux$g^@L=EEH@Jrj&5iieV$Rns*qRAVy@P z5xP_B6#$_$e7C|u&`jKx$cM}yM*Iiv%s=gny04<8;$ZBj$U#%8Bn}p4!PMPjeuzH-PTlfxQWamN!v5BF4rOWQc--h7e;~HP{Q|`eHMvtw5ii{qi7`^Ou+zHT?W1oXK*M?hQakCRj)em z1t}_x)R-)9utiGUP6{8XDS$He=@KM%1rwvZC($Gr%EDw8l5B^ECF2FqDip^>=!a}Y%HHE zrW7g#IGnd%si?;HRgfDA{Th>W&& z-4@Mvt4kXz;&333NC1$hY;$gRKMJFj)jZDtn3P~yxC_x=D&i{v`yp5<+$9ctWEzmb z^%FxLQczWuu}1=hrb=_Cp<)TR^+Qy;p08Y!+L_QfPn4+<$ndVo%j=G7i_5ip|{g9S?KiWG0JIi{#vUOXTfuWkk0#?c5|R!M6E?nOjuaJ?)kW zn2s>X^W)PjtW>piuLxGYOV=1g^dxkE< zV_`JBh!henL?NqIqa79Q!Br9udk5AXo-FgXHa)4WH6t4#a3*kIr&Ay_cuEh>0%Thi zqP!z9!&eQ`qG7PJs)j+Sz|vv}Ita~_pqG&jO9RslhX}|p(0#%ThYdI-TN_Mm}M;vvC} zA~n}QEsoHJGb|5<6O5}|6~9>OUhw&g_g$pZ{l0JtpcPC_B8^R0EO2n z!V!QbCb9~BrMH_1EL*LYY@DtywQVo+m3g{`}P)bHl=CJ`>x%s&Q4I}8sU@G8Eq@(pGp*W<-t zpk_(0Nu9ArUZaN!M>#kKf`Q=)=AfV=Ja0DS=q7(hdJoxEzo#;CcKD0M9K_ObE#HwwE0*cLqF0V5?`N19QdN(C5j=NRyz zp|TJSdJ=@7mSQ&)8D=U;0Xzt`G{3PgmNz8w3G+cp(GaS3W@!YKX!rrgskBJPpSmDb zICOEwo;Z5}K5BI-5=bNTcB9S>1|BaHJ5Ry%!V3V*JO~Il1PXxbYaqj4kNFFWqEk9F z9fmHQM&W-n{AHP0udz6~T!+PCQ_tYgH~Eg6*ftU={;CWK@@Wj6#~&>k|LKYAlIeNt zPWog#88?~ke|r4x*wBfzT%+4lYmmaYIK0ZE=26_5FYnDB&A)a+ziQo~ZM$x*S-ECn zSMJis^R{g)sq#LtX7u`7SB^aukyoC2XYXuDee{l(httB2r=Di+uerJ0n@Yq;VUbU5 zPb|N3W6`CnRi~a&YcGz?dAMk$_lawNzdgGA+B53Q4@OY0di=x0#3j!t;}aWG?J}Pp z|7FR&uReG>f9(}L|G5{RZoqHS==NP5Z(X|D^`ptHXO!T}Tcc4|^e3ND#VaSL9Pegc zdMd|IO}RTfESix+JXQul~eex9_cmf3q|Gn_W`_ zP~me`vu)!msf*@6+LP>^3pB>J9cP|@i+P~tr)fa`;OqHQ$Cgf&90~jP;wkc_S%C-iT|)QndkEM)L--S?tT5qtGWOBp8IN5_1>|?^QXR#8gIRR^5)LB}mR)sySH?$w zeMWubx7c&bRNDJr{w05M@s7IuWotQyzVhI>FZkVf3+-V-%h(% zc6YhOJl>lB`o|5I_x;^#TbzH*=wI)(C4VsYcFeMZD`UNG0m!4la-YnBRcVFu0f6D zhvtPrr$0};B(%6$DgNZ2vrl!rcXVpQ1&>SLED*KKOWWiEd<(%H@9^ck9 zL_U=FeQ+#p&EAVYy|=mR-goa-TsD2(+JBSqgBv%GZaQyws%lC+Zd`Kn$HJt?>mIn} zg0#_BJ~}>sY)8Zgvop&2pLD%nxw^mewIs*XsekhJ8ohdIFWW}xJ8pc*Y2&xAT=%%x zzwq>}sb78#()ai(`pTC_mbVY=dgGrab#~``H11gwMcV&XPpqB@I*?mscRn>ZMw#T5 zk__l!a=C|8ddqlc$o|?@v6IUYPTb@9tIf&i(er zkzFhA-XoL0cxbKFM!S&{8-EIWTETnu!r0xelZ&2I9DQ2vZtAE^cTPLsdq+>?FkF_>0PJ#zg&0v8Kr&q`h^wyiq0M{ z89{c)GCM1)G^=%i|1ZL-;QWgW!IOdfB4kDsN^lq zm7S#WW`%9E|F4~Y88@|sI;^j}@Qj*kJ^hS2)%Rs)-;U9+2f4RKOEd`+YZJqcocKp% zr=&9Y&_IGgK;`Namu#*y@5=4tPxs~SST{IoHE-?u|5)bQx^3!G?YgcWd)NGf3u{Vq z{NG9P47Xcgdgb==yL}!%UHfv+lTSXL+I92R-+BCPWv_pHH2Pu2LrmT+bI+W|F4j!< z?8@5Xx@o9M{-8G7$T7UX&wJ^*uUbwJ$~6zZ7dsU-d|}zrs71EFc9dY_DatV)I~?wn zI0&nPJLh!O?R&WDbgtPMlfDFN@9g-EJ~o9t2lr}not{zhmb-ns>KfPFy0)$N>00X_ zj?dn|d@c9Q$I`IYn77I2%-92N1sWTQCXGr9k213-B1~!@+WyVq*NY=PPaX$NPF#$c zwqB61e)R6N^z!{juNN=hX%i7{Wih=Yd*bhv?{rK=aKC5^e`ohk4ZDtBfBNfNm(=T$ zcSbC#DKYvm{+$g4wp#-i2W z^A^1o@y;{qm7^QKcsLZZL}Mz6?0nb8Zc)#XT^mjB4&OR(XWbh&-ut|-ZO=Ci7b=fd zT>F{%@2`Y{H`lG0@Ln!@+O+q|>0P^;-G6kPb?xZQsp6-BCrpn7|9h3D^0h~AUM~3O ziFK!*{NVF2@zqb=pX}bbX79PRCF85t_qE;{zW(^#_us#BacNKaz69aUJu^Ltp$ny5wTy z!@-#Tj4G?9iVJdwZr;A~ZPbw?tA)GUjvk2q zAz-WfXU7xUBb!g3Z}yk{-TCLi1;;#2*V_H($C0;3qkg>t9^&P^`^4mO?vCL{!vFJR}{Iu(;40WjIu5)`mz6!>Eiw?jccb};}^IUwTwR++HGHH z(`NExj3BK2!zHUSzrMKkz|e79`Io$Faf7gFS2acJ&zyMk`yY3&+1*mGi#FY|vty($ zqxkWKN3+}~N1llCKk*9hy|Hxt#rDtVueD`8Uh{hKt$W*N2gEOIo(TK=%XgE$0~=rfTu>_1iNQ1KboD>4mRNqa$RdAh(vSc7tb1(TwdoJ{ zKMMYSVg7sTKA-JQFozWC3?#rEEYoyy$a2lCRl!?(TZ5SF?Df?a;& zn*WX9pGOWY%X#nN-!6<AwCG{KA84vL3TnHuv^-Bz|ydbZ_O2+e4?wi`|dAHAnVIcF{~acP{KGp4c`0*mC{% zHYW>m!awcXsIGBZ>yjKU{KkLHtA<}pOxQIn%6Mm&+uzNyj^~^k*tBNWHP(^l5}}3Tm8We-ME7H`VS8+K)lJ`XS*x7}z8(5> zf$fEL##c*od^;M>W|~i|+v$Dor}sV^ug@wUoSQs<_Pyhe*0b+FjojT7=ac4jeYeo! z_D|X2)>lj3@a!4t?>Tbm4YM`h<{UY8yrAI3eyhUIVj@O|_Y|KQ8#uqOL~tZgT75^wFqG z{bx1#3BGk53yapZmCp8>S`p}+n&h;yG{7{`^vYU!yo=DqW^RT5M4xTe=MUdD{pW!r z1yPIpeJquKF$nqOpNXcupPc%1q2;mG{+5dOYorxHi@tvJc#ZjEzu8Txch^3n%vbu| z&tI6Wy#Mqs*S@zqd0=yM$=$Z}<=-xhez-3_CVJKFz3eY89DD2Zsy3kE-}|j{+BcT2 z%M9qskjnP0s5n3@S2lkArPS7_wDcJKUMp_D)!gNlG0UA@YPY4g z%r&Q{np%rX-8N6AYANtWg8>>*R=B^@tM(a zyKijFZ^bI6wu)XCE*^Y+or%LluTuSrwk0?S=1} z+V-{&9tr#Y4Ktr_KRo&M@>N+t&9@tjTYMIYKH8bK*RpN$ZNGwvjpj!_Jrl6kek4A& z*O{QPnXq=|iWSEa?Q9CHKg_E8oqVV=)dH7TuujqE&XT_Q&KmL#t zR`svbIR}+B8^8IXy)Z~{-R`x&u8eF6tNdm0g1B?$*)W3IY+;_@z2B%-p=Iy%}Z{*>AmulWaLup5e_}j0 zz2*BkEw|;nRMA%gZI1^zM(hwQyi`^^zN&sNzVJDBYj^ph`#JAlkQ_eVX%VF86VM9>6E^r?evO4!yvd=2M>k++Sb-{+qgwC=q1V7J+?4^$$<^-9r4|tuFO%r z6XUL`nqP43#w+tL7i|`@yNoaFDUd$VkLOdi)oc3mNa)+4yvaHE5R~EBfl# zf|gZnpBEGyBZSSmw=#LTyBWLA%&Fo)(VY*Dd@_G$Rzq09nxUOnHl}^gl{znyM))1A z`Dw)hLdV&XlWAXH+VuGf=UA`sJMpeoHuTyDzqB77C|G=B0uua|W&b*F_2KhuuZvX$ z#+~oJIRUp7eOfFnH@W5r#~|%@V#HNzIwv$7>QY&ZItl!bjPyB zzDM_MH!S`kG|pZ{>gM+{H3R{@7jKQG3Fvshu!dnKf4TGgSLR>(h-(C>l;eGAhLtA#2^a@4urT}n{g<}VYi}vsQxWjbOo0dVyEC#_2PS|APhkHr|=j zw@b5ag|~Z(Lj26ut}Q;(bA%gs+%G%V;+K}_hs*3Q{QK=o1+0T5>dzhb3v+T0^4h$v z{;h$3BkP^r5XOczIs0wiyn?^_v1q^T<^24Wk=gP6AW`eXl+u3%>hk_}?DNk~_LtZ} zarE3YK3nX`!mK7chxf~+y}tJdhSM+rkr zfub9k&(ys}aVqX1)jCA8&Igwk6}?YbXJ4nmkV)13i7dcUV~J`u4{NDW-{9+uidzws z`Bh-^hsA&@SXxaU#n{*>h4uSWPRpHgpH?(@=&zyTfe!h!{hs$9_9~DpLVaT9a6Jx#m9QTky7g7p z1b!_(eAgms1^=A0mPKB6qE#sHX9-v`I!Z5JbJ7LG8Z`t&rr6m$R*!StoN6%OMrgac zVD-Jhjm$ShYt6c<=KN^Z4wd2uGP!8RO$X6r?B7?>M7tlQO~V3*!Ezy@ut==w0_0I zXHrNd>VG7LSo{FiulDSF{YPaBV-o{$;fBikV*I#1F`aT`P};K-f8%(_VXm7-qc>Y_ z=I6<4nQc4}G{N+lK!a63K(ZXT!X^SbT(J1}$&b4V87m0H#TM}umL#c%K`!}7pH}x_ z6~>V2I~J<`p2bzOTB9mT6kK?9E(Q^+0sNa=_7dE>(4{xpO|Jco{>G@{YzZK*;lWu! zAo-yYq0sWvdmvWi?px$td|=Y|dN`qgvE0&-W#cQ$v!8Y9s=0-a9C)@u7U~XjYmCMT6T#uE?Z3$mEgbivwqb>}M5titx4GrNvm7IQ9P4Fs?dq zjx+r$eBHNL8Xd`^{l!9ph7Xw*v~|psi?qonu8#CuxC}}*J!07i>Wvg%*zVSak0>Gr z(Dx&5Rd%p%zZnKF-dPNMM3(&D2@Z4+>CT=HJqvbGiv#vXO9_A~=aUO6z^WbnoUU2? zdnGNYU&!D~u)N@2i07ng{Ye?OBXs(W(Q;{H4yJypl9*0zER2C146vy>hxuP{kujvW zt}`Y*P=EIAQ=>!sxlc(-WjbHR`2@MAbsSmf>~^IQ*^$p1zKkCq>WQa@Kx^XTBh!xX z2A_!b?MBQb+)DUF6@65-SCB3JIsx#Ank*lAQhgQ9Vv++IwcO@ zIBs{Ta?GPc`4+32v&-$tYPjfhbIArPaVYVOJU28ieU|jbc>Rcpb6A(p64oc`Mg8|m z<|Cp{dl|;;Yb{f8!ar9N|4-p=9@p07w?b{}hFbUmkqQk~Sbo`DCQkJ%_zPdwkA?>M zU`7WF;O9zvzQWu%?mL(}wPnmoa79g3upirQ?*xP8;1%UIVR1odz@wrl_ z2hjxfi0C_@;d8t4JO8QYAGjD92p7uIipwXmlcbwOZg(}Q`PwK^ijxs&6|S5 zL9z$U4P`Lbsb^>M!5m6tmgKU{Gm#N_9IBfZMxi?Z0+66qo%dpguqf)!$Seko3^!8k zaDf;y?8RA|`Vd{TU9vv`&=dS>VzWb`Y|wTjA7|dic3RP4ldvH3$UsK<{FqN=d>GY( zuEKMHjyf7=MNl>jbp7kU54`kYoA*3p4a0p4Xr;h^3UJ8G>5-GwXC#AB5eBAqbfzsq4TeC zTk&>aDvCnKP(O_cI;79c1VMz$=7_f0XSuG%A<{CrUGL}sinLT!#a$7}Z@Ua9jeJZ!nAM2&9;jCAomwVHDyHsK2!AchdMJMq+gxl60;ksuRbAHe#$ z^^t-AtUGBX;e`dTO^;7W3YX-ZY zp%|OEBFilL`s48BV^ok~;Vr0Ur0A>W$jUfKv4en0j_Wt;=_&aBXNXi5yv$``zbV=;lxuu6k2NafO1M-e3-prPD%| z!k=NS_w06l?X=ygyTxHy@8%g+#Kp0w=%2WE5T~q`vd_BN&0-kxV-7!DUPw>4;E~Xc zl5k+(E^|1Qg~t0-c8TN;l7%bWtd}(k_1*N{6s{FuJnHt&EpG6c+EnHuRBv{rFkjVo z>;lY-3jE8fnAz8VG(67jKPHZJYj5gVG_VB{ele?*K9*9P{V$%K&5?Czc6wP)he#mM z?%35KH}B9680?#UzjSq*JzpGKXIP^Wx+DLo2KyGn#_#>u z+35+GvIxPdPqk5)smWG{2R|y?3BV34np-PNYa3fP)Ffc^z!#8D`l81-$U@D5g*jh= zt6toSU8tX9h~u;Uf%$udSSZlCt@6+FHxKzo>t{^>{d#?ZGYvKzViGSvFMCHX=G?}{ z`ywL5A@N9cvi*A=1{-$&>@o5G0Ah5X*0<@ea0Q?!)@TtnvX)(js zBXOHSzNQ(Ohqdx@RkB7!@+wN4aiejGITiD;of->!rF-x-qqJeI#uL-GzQtx}9;+Oq zpEGMlAt4#RSQ`Sm&fx&x%HQrrAFZLbv0@=-psDtYzgNI@JK@SiJTS&W;GF|<_=*_} z?vKAVI)xS+QhRCc&^2^sUui+G21f zaT_Zv6u3|;SFH}SE`bgXK9qpsq8$+vtQWy_695^;G>mbAmv;+)PHr zRGCf(PqRs(>pT|FZqGMWQGKGp9rp}S;eg+@)ZWg;U|)h-cw6tB?bGPs9mawlD-;;` zvw8r%b4OW;Oj+V*>w>`KCL;#B?>pcvU;zO1QY5J-qsrmd06cG_ zCavhChKoh6w0zhzMjY5C4?-PIJ z$%-aOO%X3G0B-`V_i}E{u+2nCApMmpIt`tbMtDvghvw6EO_Ug9%6z$Xb~x|!u3K(v zKq8cH*;ak*Fye46w1b`VXkTt=X-2oc-bl)sv0`53SE0ar75xM;b)8SlA^__15+@T3 zk!h!dg#$=gX7JaYWRax3&5dkNKVYhnVY}U=nLpH6+Twl^@vkY?9IQ540ya+mbeq7Z zo`-(W!Zz^#*iNS3ZCm)5R2t9?Af)rX*w;EEx5IX+Gn|P5_UI>`sG=99Yq%KWlM*|a zM8-Y%FfsGoNUG)UmFvxQ9p5oK3+O}?;r->eMIQf`Ky>==6_lq*gnTd;C%Q$*x4@wO zkA-i|OrgN(0T*=|$`ZbDcz|NS%L;bQBbc&77jdgVPzlvn_1Y~70OEdB;yk=Xiqkq) z;@--S`bR$FksiNw>vtu_!@@b_X2$Ssc%q0BHM&JKWH8apA#5W2zKXc40PwHLudu#B z`uD#1M`3`7Oke@u8Zcc#wSxUw0Lm64k-{v6KlU{IfB)cfv||T$gF~j?|Gi>RE9;fa z!3>4wx&6K3oMbe zSyy*t;+j*#5!)LuJKfhAAa}!MXJ+k}%CR?xV&Tu4MFTiqZW*{aQl5|+u2`&pP|&UP z`qb`6T{=W-^q$-YM*(Bfk)DhS@tj;}H{)pgn<2nF-Ph^tT8SK9d$X^DfQ8k9AyT954wN{u*Gj-OsDSv9Lum3Nb1&g;3`)wYngcFJN)@bczRy{UFNyj zExGxPypBJ_BZlqw3iA=>>bO5quKd%8gPpTWC&$)qtlXmBRGyEW2>eh)iDxt})_VF- zf_qr`9(>+JJ*DnYwd{ZBT~(YWENLGnX&)z-JvuM_vFmeuB%ZPua&}*fcoY>iL0qdV zkR$kpD6<@JQqa~zeP-G=?LC1B_*prOq2c>yfJS;270nnAU*Y+Wb4RP3p5w9gJbou< z&-xzmG#s69M?7=NTGIhEd1yNqKzP3Rnql5JR{isM;ymVD{t@_pF;UYzU|gLD8}Dw> z%)|No=Xt=poI3M5e#upJOH4;xu$Q0#ey;=&>wkP(*x<8otznxQx?UTpNH&DQHYM-V zCr?_Q3@)^bKU-0a`?))~8;12dT+7>RJ*Jppmk-v+Vg|#UsFt)wl~ot2jxWG2dh_}d z(pE{nA#2~}y#;mG#?J`4i{dE@7@jEnZ^8kG;z`86LVY0#8KEC^i})y9znFilbA3a9 zNB_-~0$x1j-JP=Ci$g&1d&Jy@yU*GwZZw_ z^asZmmvSG04*b(sMS$<~ENx4F|AuSr1y{Jbps{*%!4FRAN)pY{JFab3T9RpY9+ z^Z%#Bwf|Q_9LV#%4y1=&13v%F4+CGhN=GYojTa($+Z1^>kltA{NIKdKa~+lO;(sY( zq#D<@Up-$SK7XYEY-V;ftfof-Kj9iy0lM8b0q52MmoZCG+|*G=8>6GM?KB3Dpv~7` z-lur+>h(5i%%F5dsC~xlkh*Gy9Z9H|s;ltDA0PHQIZ&GJI7dn5ZA<>xKAE@mHudXN zcTy8OYn8k;W7hg?*f7$0z2nr|>i3M48pn)e$*Jpu!&&Kz!;fz2xwDDL`2296?gB<- zx)<0=o_WK8!vGnfd+6(YIo%G@Dkm##q1f%}yPTX?I=mG8||E!eXI_ufDyl*AF?Mz2|MW_G z?}5FVSbalsx?!t9s8e0j@1S6tnc+}#1*$a7%TRYjGSup{|g*PkOg)R+t zm|S`KMq88rj4Q2qfRI>k@iUTZb}LG*Da#9XE~%o61I+_{XI z&XNCl%6--r6=^0B>lV#-++LhTV#ZHhADaI8;Na!uBx>v7|Urw}q-tDSoXKu~rP+do+xJI?- zh}z*pZA(ZOgvyEs}5`X(N2 zl)`%YvWrP*=L79`9%#+46bM1yYGHc1`3BW98?HAwZ>LAPj?R>YtlFEzOoZfZdi}c5 zcFv%x$a@#nm*gS+jZm3j2!9}Jn0G#7C^BgD;evy znY|o4#!NJ3O%1buuWZ|iD&MFMC6AmHa{6Gr=jDJAa+6b$xKvu%rfH#zc-MQMwK3it z{gwQDZ|VfQa*Ra;$IpJ&6~13lLEAz6!00KxLYnjD0&L~$H0HbVz}vyg?e$zEFls66 z=YA}sbXSi<#!G+l_?$)h_&uyaHk}*BE@v`mVrJvVv}c(B-GiMiM17`fZfAP=4p8cmgO@oGGG?9c7{U#USVWe zon1#JKdBo-YBn+{vaI$Z<7CXgC*ablI{Yb1a;vgA6x)T|nTU%U^(pQeY}8W#j7;q} zY}vepENXhnn2D_!Hxyga#^iZ+8@gK1#ah+|CV zZg+BCc}G=L|HH+I{S08GE)L?CrVDb~v`H-dm=yiA%m|FIJSA|1=}yF(+IZV%6(8fZ z&#AwkOQx$k##dI{SY%Y(o#il(17fq@VVaFOij1hGUBc$UFNH zW^x<$P}`h$(OPSg>Z!GrRjM$zW zHIp4ix(}w+ZZ)=XpS?u(+blbye!BX3xhbxlnl49=i`d3dMzd&!!e7jGz6P@_t4qq* zuv3HJ5Yx>jyI+&J?LwySuLH`&w0#QKt;eO<&Dc$PYmxr-cyh^;3Yob!&D^Rx*oU_I zo&L{U@2os(WqM9asN${5H3wWj+(ijB*SEu_Sf|ic<%iL^Ra#H?&-eK;HMTai9b0EQ z35wbZ!@~Emm?&NqFv|w1ZsN7wbF`jsj%b>uDX!X^C9eGC@Q>=WdR6nm=`r({!6nc4 z(w0A){$>=J?Yzv*NSS;VudB53@2h)}hG|ne6{J|;X%T10PJ6xv`9bRCmL4y-_yvhj z2pvv@%^31qf&yWMKH0PzqCRiA4M_jym|YBut5Lu$J?&!+b{Mx%X#ASLd^tzLVzvT3 zmodAIw`R42r>oOA^?oF;+1KMj8}EoO`IhxIHQp@1n8WtV{V97fm*ajOJxz?ZZ3SR9wFXolOI{V#%)AEoUi=58jUU!*hWtJ(p;28}jT0O?gq zGT9FcR#eRrDE|q>Gmz=Y*$cYJha>6^uHF;vbin)_Q6D>r+EBa}O*zdKjzrY_13jcA z9n`HTrss?98jmM7D8<2)RDfz2N^I@p4Ab4z&zSWwUnZchHZ0quWh0Zc(n>tZfU@wi zB6vJizZnsov74qa&uZ~?_lfpt()ZzPg+5i67I|$QvmXYK%j`5-+vkt{{?)g&yf6+E z1WucUlWmzKJrgoJMtD_fkLX*LbsJUIYVzG1a z`{hHa5df6St8&>QVGs5s(`DPIaou-R>GWRx{`4yyI{U&ZfQ;$Xw&3P|)-Y%b)E!gu z?%-EO`*g~&g}^U!v*`Vf6RAjJnsD1X>7Eu|FojJ>I|8OG0M`;!XDe zs!Xaq8^4){l{LXhOC1@esttSuP4UKnjxscPqTkOBT-J(c^6=q?7lCj0VRY6vKKOe==m0uA)s=Lblm*VtNi!5 zIufBc`d3k(wX;|ndVebN9aQY&28s2oYOf+uT}rI)b0tukBy@kTBqCE5U4B30O+UYP z_YfGahP-d7g~_Od2Wm!>r(|^*97zsEW&9?J&ZeKcAN=Mu9_Y`wt-ql6_sY=3Wh~ji zEIs{{(bdQ(lE=0EcoNfOkR~l}>=etl4BfW$CvaL#rf3l+s39zz{CrC-+2d_ntU>*X z$*Z)RF@iDtfm*R4kca6v7>hISc7e{H;!tW0he&9mg^1+&YK&Tpdtbx=l9}Bbo{4~F z8eL;qeW{(I#k=y3D719>bxZN{?~o(EO~iQPD&a>roORy0<1UAy1LUEmZL3 z7pL6RkJwDU4qFHm&yCm3RV$@^2`QZhSy~Ed*Bx0iWdQla%PzDr+GtR8jaEj1L!{D+ zboc$!p}o9>J?(3pXk8nv0;_MtsU{JA*c5{_6K165#dI#_4<2-RktO> zjC8bDu&+|nT}vqc=ZuDH4kQT#V}d7soy4XKmXI~D5Bf|#V^z&aQFw@Pj`5v4W^J&BPkC4e3tBE4Ii>kR-k9xdhu&A3>&`6 zNYB5J(JlG`of<{AjueXXr|ah)#p!bp4cvQzSxLaAu@bfl8S&@Mrq%}PTt8uVXwj3H zm3H&*w;z)dJJ<&^Olw7Gq3AJ2geCnaGSM_ZpEc%#1ef3Ck1ZRzIMt>3zYi zlEQOA1cb6cnFpM>NuLU`7>xyk9ABy~!y~Vf(Cr~847lUS%`(Ng7DA6nGqQ_i4aDg@ zo$BKjiq`c%yEp<8TqA(mUPF`%SNi zn)FO|C}YOPafp%+y#=fmQ`hM;NtV4Qji2!)Y-o>Kj5K_^D;B^*B=6-coJ|e% zG*gg0*5#d2#&eXz;^27+V~)^IuHRsBOhD8%W9tO3GkVRtx>LubXH>gNUuO%-y>Nf8 zs7V4!NRz~pLLUq2`-j1+Uk#tPCpQR|z9ll>M}SUAWZI`>5Se4@zPu&!e|U}w*CYw& z+4${ZF&l>jS%AY!?#7)hGMplcXCi>NpeRv2wYoEgi@jU&i8?eoWR2b*`JteOnH z>7G=>Xydk<;5Y!YnU8vbsO``Kh@1(Gm#(%NH53+ z8-8zh9dn)-XQ(cA>LdI2O825K*zAT59|&kdrk6_P>!mJK#Q9(}@6RJ9xCoX8MqBHc zdRDEz4i)c)z)qrFfpas0mCZ)9FW^Yik|Acegt1I!jP-dEdHUBx&w%Tb4Y0}$I4wUD zZS{MJ?;{l_>{DSU_BAv!$znnluveTUK<9EAql3C}Q?a5HG+%=?np6qTjl6Y+`bueI z?}EcMoFNZRAQh8eJ7WcjOti70b9XIZOa@aAdD@-9QBVs{mw3dQaQ+SvCcv4z34&Sp ziiqH1FUV*>R>C})2DhtoVjegN7M!p4nu&r{Ok?lzJA2xcg-g(|!qdYl_+P+^)uuJ_@f${S^y|Z7 zL(+oImse_QKzf_@6X{QLv{>KY`1!oz>BnOix^-AZ9NZ7?3#ORmnT@*H4jX!$I*te& z+^Aqgq9*ImYF*mO*qsy!{#I`xmkk9z*m3HO^zGNQU?h2luPAw(b_Ipa<(Ff%j-V`> zpt>3Ore5qIIjyFsrK$HwlFJ>NrO+g9o(VyVVb!-CEJQ6EQw)NG^RctXnxSW2nVdCK zY@UEn1DHGofkaZ64{l!4_&%4Om~~msE|GzOUX&qq)Nrn^&_-PWOh;}Z*uKIt9TQh%=y49moXU`BJ! z$V4z-?h)fspQVRTiIDKbr8nZ3=b?I;)xbmcm<{)u}!qlMM2@OW3?}6 zG=hDD-#dKNJ>(ukZwAwvLIt3P7>IpRD}544c|pADS00XwX8{ZEc!*j7gq#@tJ7#0B z%!@=nIIZk$br&6f$mfjwm!y&Ykuqc#7Aan~bS$-6%0(FGTb8D=!0Zl?Ic7pcYIq=n zztRmJV({3zUC>`l<)EmFHgtt#-mqv<~(R=KBQmF{_4ry6I*bY=ad;MWB^!!=<6V?aYaR@A+|X(K2UO7-!0RFVI5NmC4SjCH;-0 z0>#YrN2~##CODv(Ua|r(SE3yQ22GE5#wwS6+|;7~dxdXU2UI)L49+w3*VYZX0gsg+ z=x7bd(x>sR9QP)nF!^n`fKs8L<;U}SF;Nl!9q<3p{keK zPlmszT403nB*?o@<_OVQDD7xUEJe%>3=)x`T_S_%q|?m{v39i9U*mh-hUqw0E}#QL z@wLhV?84)6i~IpYf6}tvoQ=%nE-{$(!3(7?mx-lyF~D za;+cO_=cO1Ag-CZl@{Zwr;ux3juX0v;@sUb1a%Df6Pu|eIZgNzp>1uqX1t-WQpvbv zU+EC*((<$rk#K%#xfXL#$fdAy+^jW@czcel=g`7s0j4$iDuPr)B zN(d~*a*)$!D%AF*_9RurBEi$M;ZQ@#p;DD=&zQe&Mn$k5XMgt|5lF=0Nj|~_wzPjm z4by$K&NH;;eR}PZoWb*bZvH@g$rPSMTR^+edYc~XI80>#eWvaHuiil~$Q7DibU02_=FO_l0OhZz&)(qK# z$j6f|{$7T)en)My9^YJDAW4t%(GN(z+eLTb>kxdkF2#u+X`hoGJbVoLn0a_dvOMul zZOE4fisk-x>s!ew>e1ojVBGc8+sT=}P9FONLnEniw3C3AcD6r)PYV*hF>;!d&`Xny zD-n}Ycv{drnQ`o6qfC!3 zWGx|M=6i9Jfmxp5E-#X<{(zug_dD`m*vy!;Ie6%gsDU*w-p;O3pnZo-k#;ujdy|`I zK*a{hY|zLtv}ojmQ%U6?sK=L;|6XNlwP--m`yyiOr2Ff6m(yWF(I|vKid6q}CgOK_ z$+i1Xu%-*!4gS}(_KNK?>Aj;)qR|w`>Ll;jW2ZX*Ug;AR4HXvO)RONarOj}JFEkjR zC2w%;;A);0u8@uJ{lGt+9Mj9+7kx5jDtPaz$HHc0RRuJOE=*j!HLC&2k;xCI5XpL7 zIgoA(xCV%6dXviZQsMkP4Pq0mq#HxI)XWa%uCL*?VUo0FftJeOD;vUlZiS>Ld`}vo zyCPWk8<%X%@#QqvEZjyix2rkcc3piGyDgl2mOJcxvz~zndUShM@poksogS`Os`5P? zdd~l@m%=>^TwDMzPLnq|?Z5Wi73Q^WGNW_LJ{J0#ssbZEw1e{ET#t66*DvFG%GCCN z^1y~g%RXg3ToadqOL(rSI=^$){7Xjbt=F=*>8uJ_yYSgf=3m53i}duWywA)e;^Q2g z{q9aKM)8|?MKL=`0RpWRT*dDB{gSHhSdpMXFzeF_0*kFyB4UeM6PRtXL{; z0G(|QB7(WqK<2QCLFoRkNI`_*Q&^x4MuQrpx%pU)DIf;QufhgXqU~OnB*dD(Q+UIX zm$Mkuc`IaGw~!lZjP~fjutZKY#bu9dbx8WdfJQHC&KWyV&y20ffF$$*jNa0n z6kEheG{W_9jo8OOw!himL==2E_08FmbHK>WymxR=nIGA<8Y6ZO^@z4nI|X0%koktu zFP#oSYk#TNr>6hm#E(f%CAD2Dr>SI!+*^9Vf5;G2%+yN?YKH>u+_!SUQLjOwri+Bk z?O15vd8(DO3bu>dv>={R^gT;u#loxCHjT#H=`8x~GCoI4`!&`6eH%qGz&UMukb#j@ zBAI~_!Al=^6v~S*32DbwJmoWkf4{i;{6$^`$zy4{Yi8Ps1|v9HgY>(9Bv>8=n}In@ zGd+9A^$GTlJHk>y_Vqx%f>d`QQAmCwR1kHZpkCcZYl{l@oFB)6^qT1ae1TtJAR9v%OtF(UaVT`uMC zH+M+8=#W;85UHO;+G%F?qY=Fvu)&CIn>aj1)@8Z8d~h&$@QsFEk4O@VCOCmj{4P!X z3J780CyHieJ!OuzmQ)kVBBL}Fs+?Hq<&q0mg>e?vAK=1bLdq34=5E;?-ltk`Y)>?uNC=-FRl0ZZnu;9A%J#fJpd} zvEu5io4;`6f7p3Yo2)m-1oZSeM!lBSyMo;rVso0pbr=9|ZExE5h0FteS zYRxoqfjYXHSulPwoM)UG$Tmm`*>N5mtZjRL?S#~o_BGF2+ZUeqf#Ak(q{PRVPYbOr zp4APf0;CS5AXx@Q#~C`NF{T1#9SMtN##rVLRUBvsbSIgTuXS7eLg^%UH;C?I!PJ|% z8#j8+*`77hFRv>tY{os9dTYv9G9TkdK3e?ro{hH3+tz^FGXmgJi@v3653JLeDBiN8 zrIi*6%uSr3r+^doXaI~16elt4dY?>dv1)$gooFm%E+)gFw*WYSa2C`_xQ>Lww$+Ud zQrSxJF$a$5m-VeNoDIH`3f)+`cqTUbcsnjS=fq!l_Q-tJ(Rq$B8gJr4g6q6zzjC3G zmRVx=cv3HAl&e^?odJZkZ5X!bE=UIA$K_z=a7rI)5mbc+x$@tRVFc^i2JV}z_9h|YzD+u@fSk0saGPLdg9@?&S>ESC=;`G) z3Y8mmocNct^1+lM`K?jf$6N=m5N#_1Jnfl?KQ&qK5r!i@!E4qRr3Ul^5(4gqhtpXJ z;sdRntT)VfDhBwQ71=xZRml{aG)YR0zkmI}HfkE1z0F>rBjG3XIAb_4jkO`Y;rAgQ z{lyP>MrQn41P8NJt{a(+I&ASLKc5j;}@)o8PKw4RxCpTI9j>W~<~+RI=gp|)_&nzNgkF-H~qsv&^V zMJfRl{Wgj0Lu_wWYM}uyA0Lyi!YLD|J_iN&}b6^207gwO27*21^tBBjHJ;)2|XJ^Iqpsg*BRMp z8wR~UXYkRhxzjJ`Tavq{KC6Ez0{NC46`$ zKhgSI*A4DP3#ljU(4rOtt#h*v?PHb&iKq@XJ83Hj7aG+^dy7P`jW1vkLT|=X3Y#!& zVlK;MW2p}q0tE%7e{O%f9Q`G2FhPDtBLcAtfM|rVNF*r()ydui@g*o7abQc_T2aA8W@BG;;1W1&+Kv zn`>$Sr=U@h1B>&b#bLn&9HweHV&s{Xc1e28hRL+AXPC`|*fdqAV}DXYXMeWwU&SK)qv`CY^9Wom|E<={pd z%;8I^n<0sr(cc|&Vyxd3%8|Y3AMs1TxUSPFB)VuhJ;B9fBt$oS=u9y<$`ogP814Qp zi63n|3;jH^*7l9e#`PfH7H>DwK^G(2Bdr`Hk#$#4WQoH7!c3~RZYLTd`*9JBt07?q z-@oJUQ|nb@TNEvh^WRHK^`P`!5nAdd@v3>;I28Z0LPh-AgBaFvuDEyX4Fkk@wSfnD z_#nusM8uV1*q|QiXy@M4`zhQj1|xkubWTx;G>i4Q7CZg1`}$KWHl8PyU}5pV@5oHY zaYQEvG>mZ+o@)vgajHk$GDi$YS~l5TibgO2)lW!Jc4GQV7vxxL0u=AH@)mD?Cr%r))o6u%amsi&XJ7EE-R zE18PTvBvD#nrc&txR|vWYOT3_VCs`<_(gzKd#iBWvnDu|&O$j74e<{jTqMOOmYpQE z^T?t(d@RJchX|s=v>rdoSLs@GF^1(mnS9#okF1?aY|EZ(y6uYZdAyeLIUwYJ^=Tob z5p+v9i4HUD{E)9M?6Gs`8S%#a(Ix%|zGC%ah!}f(hGbQ|Li^jTTppb-)OYTMxcP}w zFKeP~eN)(Q2&x%|Z)M-p#ytmzTc3J-$y*o5;|c^P0Hd|_clYmgt>qW3_b7nZMVo&)Uv&8&V>&4i{cVPXi6dim5<{ znE^MAHtnPb?k4h0!&0o%UKINFw!D^PD7Gx0RVk%K1@bI{8f2+jl&p7~>!%aU4kWRt zq}*%PTg(qB?2y&H58zh3LoK=SwaYUa<5WP69&EQpH|Tr4`1#X$=x#0 zvFS_btj`FbXcUhv85=`D>^!Bn4Yxa^8)+TlndUx_s01b@DOe2p-jLU}MUV+~oDU6X zam169Y!_jHw<2&oK6bxZr;6T)738dy)gc_s^HsEy*)W z1BLf-Y0+uTDNojl2M7Bg#EGf6SOij$PVlzMfbA06xJ)}2 zvRrVb*Oh&St)!>3BX&KL)&TE`+IYpA7@E;GPKr+DQ0<^MAeXZzQuT?APyv%xK|Q1% z_o|+(y?`_2*LCQN92Sg&Q)yzR>Bmc#te#;MQD|{<4eIh_K3B0<J%T^g+clu46for*5q_+toI3m6<)y{ zDV;KH-b8!$-Nbd-Lf1ig19Z$?{>0tt$!UL&S!vPLz<&g_7k`d@f*=duA$O*l z+Kj_e`A-!htnd-B-{53AHYAsNL{ap@8pYHr`&SgI(L$!RyYgSl@9gdRU2b^23|B*X zQ0Zj_RnC`D*)!Xa(ZzVgDtW57V#mYX|1hw4+8rc5rknaW7RKIk^G?D+O+L)MZ&gze zEQkt%s$a*j6cv+Gz@1+=fgosPU$AuOE#Fof&LO&RNgY&%pSTVS|EC7)&!I!F(V}`I z{o)91+Puvlu^r3JH%@f@T=I?97oWd1FSw$2gf`v6tuq2wh>-htvjgJL$k5_ittmdz zc%8=Gg>^8+4guz8d5|DWJM0|I-&j#;OnHBtA)5b%!xLf-I@#t43~{@~@M{5~j&>RU zSwKe|s`WN8;K~IuLspYkSr;b?mn$N(K`l`+ld@*@QcAQXOXm1l+ZE#%T}i7S8{bh^ zpznK8xGNV|Hto~LpI^zZoiTS;fB8nKP}cfZaVS~kEBP64yNeD*%Yj^+bWaCaqx+NM zru-0E$CdSir)}Q-w$=+=0tJe+tOr9`G}n~q-tD1=)YP=kLBV>NL`1;yQ*(hcKBudx z%p?t53DOQ$o3gO2&#VgSDQ;cy4HNCgNh>O;;2T5f%&wG-w;%|u>eGSroEW(`q(1jiL zwCyLI>uVKkpGig$zvS%8&q3u)&V6*d`F#tTTNXlLT<>5oGb-!0VSF*!!Xrip(yNj8 z^}kJ{q1eyygQ@wtx$cRqKc!O1NyVPg{_%X|;6`2gp71KM1&n79@X0qe-{}D zeBradDQOO4+e<8T3Y8+`Z_~LtSvnJd9k1`&h7w{(*jGtgDsg56Pg`}Z zX$k2~>DwfGdwxKsC+=yWhN2#tK%6Bb9H?=W7uD9>vmd-@?*CZqlZXuFkUs!*u2%Zm1AoS{%VWgPC;qWi5CF)D?IFQ@X;G8-{80C2(G` z`TUKq%H)VX#wZ!~nu+dqEw%D$IzfGf3`>ofe2vC5&Mi9xZ zso2~cL~0Q*iHu3snXW|fyi`ykLaa|R^UxMA^xb~N!;lQ*2M^YS&?nMEp5OOaAj}rA z6;bI7Lq*q($Df)h*52OL<{El!eXIvcRd?YOGCUZF{WQ{aA*7(au))BY>eD%_n%ru$1jBjk{MAUqNu27PvouVLWF$XUNL>pxypit93{f6|1{FM+a6GUrfS=> zT_{`xJkiD(E=sbRTF`EtWHa84Vw{xR5Ggo%AnLjNC5`q|NQo)GmNRqRY!aVPrZB0D zz}a*6uSc_lZECdjf;ObT2+e`zM z(hhr+F{0^qEN3dp=WzaS1w|0Nk9Efpigej@(2%(%If#*$?E|=npzu5a(#JirhNVfsW)B;yqTuG{X#C3_l%wC-&W}uRFj~kGnx9)W>$15NwfsGv!ML|+{U$nU2?Dt>p`L!^*(@Nj9QwsL3U9lR+k*PrhqnlE zl;{P2xaT+#A>qvWyAZsmWb?Ld3m0tEEV}Z42>TAWD3b2mnz6xd6>M5XP>}}OgeZam z6FNh(2aK3Af(diLyy!R}K@^5jM2tigGiJ;vMo>X9qoQj7MORl)7gzV48gzHR@Be@A z&9Aq&r|Q226-@Ei><+S`T%d?Lz z*4IDXbdpyZF0`1iXCyw~)3v12<4`N1`9f*=CNDeAUJMD1iZ#jb4{EAj>?=dS(0oQVHGTmn&xq9-GR}i zS2lNYNwu|DbvVze)9(AykaP9N*!OFmS8uC#sx8xLQDEbh*KaiY_{OJ(U*f$ieR!jT z)0*zlh9{&p9@)1bw}1QFn|5y;7P6x1>4aoy@BA+HM+Bs0&Rw9n%Wzz7F@IleawIw1 zl1JONa)VX_HltVe1=WWsWbm-+sEwJ`ob31QRC&$sWmMu7GH5y z*H@2=jSsHeB3@zRQ)`s83!A)R(~VZ!{;V~m;Ly7rM~1hY9A54gXgT~?QoM)d{ju?< z{SLJeI~*|&6inAe{bK5V;dy@ZgEQ{3&*RScC_{&&h1N11Xcn8+&SKxzN$eb(vZ!wD z*1HvB_rF`%>HD3DM+-Y_?ypwXnf5KRv!-P%yV3bTC!6p24@2Hm_=NOne(>UoZ4Uw~ zXO$MMo9^Qs5plf9m9IOdg}e`$-{AbD@LuJfi-kv9*cexF>LA`bsK|HJ+7|UkG$sf2 zlH}7Uyic8>jUSeIcs3dJY(}puhK2I+(nY7Dol^J6>(&`O#gaw^m)o_J6PEAx$ZPAV zyR16a?S!Bi-YZS9XI#H;Ja;4YfoF+Z4;^=S%@NIvbJMP7o3=8$_txsML-&Bv)(I^p zY@Rr*d{)G(LS4&C>M>T2hn4?Dme2W%{MmMULP2(Os|(j-LJN-^iFdE($6c>|dGl{( z^?sQgGO7GQ)b-nwSGqEdJUZmYM{JJHj-PTk_Os}jACu(&VMx?8UES2GfR&R9CiXee z==ateqb)5OOg(*WdQ>~-f)1XpDNVW+9+yvB1UA3Y;$YFOjOojiue>fc44mEk!rhoh z4>>!b;=Xx|UGl&&m&Zr!uRO{f&9Z0O9Lhd1Y;@^~23P#gp0OL>ZT+q$<(s3M`<#zA zDT!%zeO~F|oL>I;6TE9@asF2C%&EP{ zFg38{$`&=UnZc>j(slFdM-@8mpAmD4={Ce?$AphTzs}9HsvVz_kA z>)bou@OH(FEvpuunvefz5onVX7JYWbt}PmO@5np6Ulop!O#p+{S*JPyCReBD1VW@Ph-1{z8MVneq%?`Yqd^n?>Y3M*0{RM+BbX5+I4Vln0#Jbxld{ zsY~nZoEziP_jAJ`ZjXW=9O>z`=k<(Edqd3*^z0E{XL-u=`E@_p%}C$E*c7EISH+nw zXg7L}Q{c`e8=ps&PH{6>e~-TsEB`J}-B;N1Y#gJy^IGrTvw6g-kAk14m;KZ_z55=q zyjsuI^4{tLZ8~IRWDa#WU8AYBc^#iq7mm7pNK_w|Vsu9I2d?-OfSuQ_|A z*ui8^XQ`mza75%r)4a={BSTuGL}X{HFXuCcvcM+W-d$ii4|lT;8BV_|d9rjZuhQ#E z?5{eXGIg6UvCSsSP_wH8&eZS>j&XA>_guB8!L#{|g0El1M^R@@>KQnF)mp`KZtH%HxXvF4ktId^}{ z`30BOdQ}7->om}GF?wDQgd$MloIUvJg_T5)uHd5&-~vSj60uK}L|f(PkppW;~y zrP;#NWuD3Br>|W-R zeiUR?-~0EB=LgfT<9nnVX$*dg*hlFeew6Qf*K538H`VQoTAy9}G@5NX{PNDl!Yl^| z#(vY|-p89yyOw7i>Ej_}T)ErzS;wBW4%{gF^VXVIrV6yc(Hb_FmZ`J=?L@+fGR>C&wyIMtOAk9BL}5?T(x?8TPTvt;VsuG*k7;d;JW* zH4=4K{M@>P48Ps-E7b@+#JTLam z9{w(Ri1m$@8vc@U%#G6Z_bzX0Q6u6n@}hBOV1;v;@9wg=1I@DwcDqmaXH#1-n)>*y zPUSKEBgTmcuu;|aq%I~sR1XZJI?61 z+dF=~&_-Xr?Orp_BN0BXe!+nk!<}6A*ta&nX_i0dp4T)tL7vevp#AB|)A3P-nd0Qp zF@dl8&vET@u1mwQ^H!uOzI5vGa?;T^-WH8&g)Ew22yCcy>lV{K(AlTAb-(7WuAvt3 zZud4WNV&mWz5-(C}# z8QWsq9aoE1DJ2)zDEr^(o89$d>BRb{b7N}zwhYg9^~t;ZqQqn5z*!5<58MBFT@ODt1oVBVobx57A*xf#iJiShMm<`+MfoOrRJgKHp=JG!ZKSR>*Z#fSdf6m{s;cQ$9v%*F?T znr%(+HjFaNjO*Kcf3NuQtEXNIn9}M~%krZw9`&5}Rjk@p@v)!O&}Y_-LYu9J)SGJG zC_h<(&tdzvH83&$OM~J8SD20un*Y(&CI6-DxjLF{ho1?(O+CG0x%Z>P|Fp5rZ&x}f zYxRzPlgc{9uev6st#wEm(;`}$S$chK;F@uKmA~!D+!T|W z>BFQZ9KHp+zti!#E;rlyRD&cbuO!T=^%vU-=dav1{Bg}NhfVVuf2w6U)pBpEprCOZdAHe**Sjq3y|dG-db$at_D43(U2}NVeQV#l z)}Hv}q)mHkUK-yn?1n=xb+&%fcBZ#mqXF}rQe5r7b{*R~WSaeAr?PJH#^;Z7%Pxjz ze(u*JBYaD4zd@($S0&V#Q|y0k<~8y3%TBhsnHL<^Tyeiuf4y_oW51J~dqg)2X_wP2 zwdso}tIf*N$q`FTx1H^N%yUA@5zB;@=boo;2$>vPFFtNXzH4}!F`uT-^v)dWR(p)K zxyiOoVRqIRdz_nQsycS!0PEuPKH^#1`*6C*0_+=@b8XekmVQTmCPA}$^#SXk2oig)yy;;{{Yo||Z!S(IFdVVT?C-u+9 z79CD!j(phf{_4E0`BhUiRnEiStzoVgeNDHxZF6De$nukqTYc@BIwflBU!Q|eQiE?jy!!p+Z}Ej|rkJ$x9k6Eq0|$q3es01MF=|a$hY|II;_t5> z7PRmL-)eW0V?jfAb>oI#KIhgyGJeg5T#r}ci@K5tMT z!D`1E*G6+fT9@=~>UTu)^M3KL!|DTmLjtqfrM8`L)y-0pAC|`Zo_+G?b!&Ew`M@Oc z?&Qav1a)3TPu~aemHkf53i#T7SLedY-V^mvtFQFPGkm(TNuMUoA8VKtR9e;O$cta& zRSCNxbB^|597gFtSs8%jwb)Lzl3$<%=8nb^2C*bKszX z)=j52zkOxi>T8$IZs=~`cYJy8=*G^inX5jY`wM?HZQ3il&aGb>dJJFl>*a`{IS*U* zUFSP-U1h@3sPwIa!mjT-c*Q2Z-<_y4HCpJVjgEg+9-B8~L-U^H5Af%sZwz;yzneet zFYb3P|P3M^-GNBpi75iXLs3I ze@VQa6N7uj$1T6*pl@|xcho)o{nEMhI&R2M477A}oOa&&nWuA53hP&26?>CE^ypyw zNwuGCuy{T#wZpXL*8I5W?G{(sbhyQDtreS}J=^nG-}32PPFBsOTvo{38oh#}is!c) z9o=jd|LN?(fTHouZ?0Om#yo29)*+5b?S~IuI&WBiY@7GJ8z(v!wg|p_>J`XdvL z>AE)5JwMs7*WHROe&vhoXKc=k@1a?F$$WCM>INQUvODyR8`q)R?3M-T+4c5cH63!U z$;VDvE${3qc=o(Y?hCWk7hmfmvR(X4-_JK6)+sD>_35Z)$uG_`PYdp6WPdJHR`$Pq z=-QPu>~Vykp6d1sT$?ih{5vy8I|PRb$2< z4Z4@reAu~RgSn$oBQ1R<_DjvzH}ex+3nT#xk}^j#Q!EAaMc z>+Wj;2Yk1=T)wm<>iO5hEew{qR@pO7$Nj!;{HK2A&y&g{mPS8c=JkHGPsh+M_J(jr zvo6wm=T0%>_{xH`O;bnBIh(W3DR7oUYy7{$TssGIyMZuYQuYj@FkeBp$sl49@Ni2Hq(d$1D>ZH}6~wlO=J_tRaoMs!g>3nEmjmt@8i<@1#k5k9R17INrhEy z`W<1JaY!=h$V%!1u)^EP3pWmYv+Y-zX8Oxk zuaMF83LO`wojqxL{ECh3tuN}3UMubPv>zg!Oo__X(Q@R9WEiOmCsUEX|cuU)L)w&^Z`Hwt$5-jLJ&R=u?uiyE~J&nlL6@xJx% z9m@UeFn8+K!1{fo2fn$HDQ)x*h|h7?dpp}$bnbrdo8gA-%|$&Az0d7wJ9(%>O2@qJ z!_M@&KbxPPvmm>P{>Y>a0f#2;Pp}yiU;BQ?kuk%XbmO`Y?B6cRx6aj85%|gU$j9F= zPxDL-8M?R6#pdHiHb2)X+v%OhtAdxgP1(@eCstX4NMRLwf$PG5(xgVvm^e zN!$D$*Irmyvh}`mT4`2b?uVJa&a1>@&ieI%6HHCBvRk>#CsQpyk#MG#*)!`JQJ%lP)V!R)PD zqecA6#CrX@Sa)ANYGdL?v!n6z1J+C#wRLB&IuBm_QSrcT^3-lM+Xp4zW12Z_%-s}n zdE=kfqgM~^C}$MT3NT3Lns`NDHF3Ol@1T|4J*Q(fm)$zmi?PUQdTwNlsYmYmD~C_z z-z*;T-EYeV~>lO0^`YfPfKE$x1pE;t?AXh_) z5Csr@^@jv0h)yN~2T>xH6OE`>0pSOfP9qvr65&Jx{_asD5|t>h5JG3Q5Qq`_VvJ`h z5R#!z&k=(L2PLLdGq^B7JC?v@HG_pZq+kI>Gtz@F7{Sx-vbdh$0d|N&l0@V5`bV1RbccSBdDnf@JGurT0(6UI3VBvL(1yMOHn;Y&jL~-3>B0a z5Hr3QKxtJBZ0D(Ipod5iWukmkG#G@dU${2>Jiq}^JZ({`QBa8}v4Las2*oNQ@(QLp zSWiUChY-5_XVSlMkV`;K4S2=qaK(w}il6a-l>kVgAd}AiJ%tO=*dz>s zwLoC$JXmQp48mw*u>T5{QB#Squ#|GciwgPI0f7*L5u%U`KON9(7+Az(?Y|-oz{g8r zgrWi|fqxE}5jbp83?c>gpopYOL}?hE2K(+`k;YZ%5Tq99HDan~vDSD2DBNdMjDf%e zf*6>?D<~8iz_>)xb3eI(i5hh@vigBz1o?R_pl2uz+C^GU1QdMGvIGtrWV%YP`3VKu zDnhvb3zSL{RFYC<ZLC+Vr!f2mM|81pyCzb^zeh0+=2Q!j z8dMu$Wg@6)u>=+2HMl#W4MdCx=vbUpgd)gvdG&#Q)02PR8V5y;;PxWOj1J8pqoX9E zqF!Nl69u3UkK-Q|)ldk~5+WFpp^FBkGhG6s&` z9H5TZh)T^*KGhd$`j$emG(h*$Oo84;7{EdiW(^=CqcLa|a682k;QTj~0-TLd$g4mi zqfs&g4k*1AQ|KaYSa3W7c!V$EDQ6NDs{ZC5t zx;nc?(kg(-DAgkB0>?lSP+B7D6sQ`?LC^`<<3yHpKsL@|`9FtDXx(whRFr^tHOdE< zU=ga%7}P`$1lqU2BwCaYh7*ROX~2s42MP;+A`?Ok&}e*%JDUNf$&3<*TH<99)o3aKTTH_Uz}FD?rlW-bH;Jg2Y8C$`_VZd4IGPS#Db=ux07}V; zL`Ay=2dvN$kRir+2KA~|^e+vmccCxP_$UE3vyTyd<2=HI}|lFBIth569qM?=I}q!C={%wr34?MSBsPw zk+hs~Be3WU(r>fPAzF!Mo&NzzR`Filn8o)%Bk@Gy)uNIP5{zq&3#pAbs=ZlWj7HIghW~`pAulTm6iVd53T1*naF}JZa6={#qOb0D^q7XxsU*Tl0_329 zk;urW`m9qBC32}GG$dsu1B%h&E0G3oi9sU@*o-Vu(j`bCqCI$ypj{0d(f+4bpn-}Q zkP*2!+#f`uphezqb;H}K)Q4TmswGcu}kL40k z5R{3wE3Q#@nLs1Ts+H;HLJ4#T_#bFI;#o;xX+|xq;3P<(cF`;n#2PRH$(*PqgyOJZ z%OL6h0;K>HqvWXbumTKu6_ztf5C9)Fp?Zx31P)>u4C+}?VEEkdu6lq{puplbAmO##Dc(w_$YSsQbU51Xfh4u$ECOek@mV5|vYZ$V5v-o)cj^j~)ONM+nqu zBp!9gt>$ki4cLl08LUKu%+TdB-50zO#~3E^Xa<6|p6)O$M9;pPzzTnNcAD2Mgklol(2D-!5KXD zSgQdb2rzH}w0Q+1s2BihIYvNg4Wrl4;GYN4tB64@Y1K5|IA}bh+$tJFwNxK6dQ#G% zKpYGa1+W4`bl2Yj8c`1$Wny%r8cGz5vrvsN>c1>uL{DfN5EZHe&lzl`>Ms2^l%T@a zkaP+Zy_&$!L^8FPx@|nLBb2ZL_}CqU`iX`V*dMdT7y^6IBuYY%y?W%QD3RxkBh+w_ zu#8?M@xTE?4f4VPz%mAn2&)ARB1I%pswJ?+&EW?)_roGR8e2n|V22Vl1C6|z(9TgY zs3}oP=rj=EWxAuWmT`o^gn%BP z(6N9bjE;qHh{XuKbr>-vEv1AJMu0ggMyEizA%Rh{@I<8cDrofygsT~f$w@SflQ3J2 zK$p{lA@CNBiWmhF!D>lRGdyIXOBFbX4xXs!6dcg130(+Qgb{w&{sYih4u)c)D4@rR z2+%?-D{55)YxP9ZbFhy3!&58JB!HrrJof_x42`TL!V=>Jx|$d`5ru~5T4dxXRYAij zAyXziN`R@KPzGbJY6Lwe36zYe1%F&{3@`;1wSwS2LokSKMPM>yYBkufgjb6OLcIkm zK_%(P4_4KHfU1@ZXABxz7wQZM5Rux&p~o04heHHDnja+)P*7wfqCl$U&^wGC_&9So zBaDvdIAa~vk`8uZBLfEn0Ek2?iLeZ)V&fPIi@eMT8VQFUl`=wMr$7h~V`WK)C4|9& z5h6>pnns>l4L}$y(If9qGJ3U0-)fAFN1@OR6jlks#(qX4p)`7EG{Oo*LKdPH!CX)= zdSp=%)S6ZVJ&YI)bx)up5>L>sL=U4tgOVWx-m1ZY(W((6@>t6<2-a#aWqffG0EwE> zu|`%LJp&55Xe%O24fhzNBOt~yI@DAF0wQt=Y6M7V6@smV7yOY$18`J~4#sjuR@7S~ z6jH-jj?ofuqi57w&oXpGB?=nK3VC%J+#I}YI}MCrmO-n- zWI`w`QPJ`NS*OAv4aO1*1uO6`c*Rk09MEFm2r{BclnMsz2Z20Cw6vy_66#JAqF#Ys zWoW!cRB9wGppX|(1ac^6y+*{8z%d532)lF&B*I!sMhS47(NPNerG!U3`i%pWq(?dm zQvE`qMFEMBMZxfxLg}e*gt~;g1QkUL@PQDl;?YHF$_+gRCIigdDL_?^DvZMrU7^@L^7@{CNCu!A2C^RH2#fz(cD}tw>5d~I4eFaXW zwZNefiJItShG#{t4m6BeU^U)SC_-~7C?Hbk)Ql3+V3$S$ zxPfIb0xJNhg;Haci4h9DL}jW7UVy^2l8Aa0RxvtGq&}+{B`#0`;LCI^Dyt<#3lmgy zmT=%tSs64U(iv37Ygq&iuSPs}qKJOr;f6-kgCXjxrojd^QZssv8i=+R)JQF%phhSO zDIf&bI`on(DY5&|Gb%<$7%dAo7`+17CE8RNK^QWsMILO?mI}rI<}}NH9x9?V5&(G} zCn;InqeQI=fQ(ixQZ(2FbJRE_A~QrrcF1RxviRRnGz*r%H1L-Mm55G2Qe(g2S`^@e z484p&CBX+;0$J3t5^Mp(f1~L^74lWI4M0Z8iUcO8(K#4F>q0Ei(V{@0Q7lRc`6{YW zNzea*MmWhp7%kKhLa+>5#foJgAfV@XLJbQ5HDg0_$bu?p-@WD11xMI5)Tdt;25GX3S=dNLe!y}oTvjU zkfd@5-5_A4LJCQ%G4e-hjR-zGhk8jmm8i$8OklE7Bhq^g!COX;FgnN}3y2XGT?cNG z4vGlaGFXUUKoL&TfgUHJ=x9H^47Wu>jBA0f21%5a(W@oOUn411i~+S~L6yKjt#joh`KrvloD!`v5q`?k`N_F2oVj0 z@F**)gE|6VL*R)LDp(QBK~l?NA){m^@DvcKqCQ|1auGG71STp@%S518hl7;}?Rj)5 zx)Il+R!s~l3A(67m{Ku%R1GBI4{8K~vZ$3sorWmkDpnaO=|F%5I66=wgaItVbP6C4 zB_Vo_b}zxX8cL=qc$K77i&~K30Lus~pGJ`iGT1|^DUTt(1PYJ%>9IYcF*Mlb>HX$i`QDM}AYQCV=%DzJ({MR=Cc0}8aE zLJf5c;xPg;5DOD{Fjt{QqK<TA+?aB!Lhu%fKA? zrsaqM-lE(9REQ7`lAwW>pv)1VfDeoki3q@vS5jgj)eZ@a68H*$7zxOd7P(}CFuj7| z(Yjc!qGrMzs*XmA)Fp+aRY(Tdq7Y%Mz=}$hsAP#!E$RuDh}3)}0*zm$V5v-C3ML|NkqsL&@fP; z5_wo>gn~=Rt7AoY2%o7%AgqxnJq4pvOL~szP#~7*0n3Rx4M>6p^#o`-REm1S@F<6d zC^e!1DKw%^M&n5oP|YA-$08lFO9%ifdPWy1umnyLfn^LZoRtIx8bd_W@@k_xl?2CN z1$qGf1BaIxXg7)_$PTeOmJpRl`DjF5Lkt>8;20gnK?NBqoI?r_Ac6|gMEH;D6OON|I6q-%u+sdO2sG%b~juipsHjg11lmU4_8$Z`~*)_T#qG0+4?lCeY-SP^9K7KPAbtp@5OrGoGn*ASja5NlA-)B^G%3x_EN7kUNAOf_2JW2-60Fgz=)T4#eB64Xtm?;4q9F!~_*D53} z6d{X7La_`gLI^{QwcuqS({wr(JP9Qa`J6;(=Q9Gl1s_&IE%dAiXS9SdP}?P(wQyBK zmuOKnR2i!vN<+KUKvhdRu)@Y+C8D5pha0H70g5080@WZX>7fon2!n+@wOZmi@TBR$ zPzTO3Lxpgn9$vu^PUJxb`%4W)61oLGD+y{R3K~hP0e?w=Ed;5dQPip#R8Y?nObHNz zyfO$&dIE2$nOd*~ZJ7Z#ol4ZP#HfydClu*q02&FP)&NwaScJMQi%KHu)C{y^Ul`O9 z`T?n7J_u{Egkb*?Jtu*r!N^L_VF@E(xdKc?WJ=!a9On3PMz(fe?6zFg=ZtsADX(PREJ=kH=xs2WImB z-v?$^N3@3jN<3Go1|FGN{lH8Gv9NPd^8?0-vzND1#i#Vo$|($Z`mcv7@!#7O&wt$d zvwP~;{>LATXL*UvnJ!}z7LPgVTyQD5 zLaa;(x9NJ;H=*?&{Bzs?I47;_x%TDoX9GXGEFC>B!u7(j8U90GnE5%fD zIHU>8({0RQs zJ0#OTW3gs*%>iSt3)j!~+|j0qr}wKJ$@z{6(Jzvgc4XWNzqbBbyK02EFQ}aD(|>~V z+qO<)V%DDWH%|{s8S9g=xURQrfq^9aMHHX;o?k!Oq(!wnd3>g8&d2C}3m2BUne{4n z{;fm5g0D5UWuA)M_9CyMN8~Q&6sMdJm$m#3Z{M;pX}bz4+F91J=?YiAb4yw-%U_-` zG^=~b6K|6z!Q;IzZde>P;CqKFCqtKWJ7@HES6u9t*ml(E6^U)@j#wAz^&zqs7jBn$ z;Mbeq8YQ$b;nKO*-|M&9UXU3(VA|1wDLq4%4S(A9D-(X#yy?vh-vpsiel{wTv^K}1 zZxX{OhYkt02|6E}e(ZcvZ46<5Ms;4Yc$G<>-?@S{$@8wX zPR>cZSv9;#%CM%9JN!Hpty?DC%vg5u(5j^uzYYD=&^g5|tlT3w>;o)K_FGxW?(?qL zagLFN3@_c7iKBg!`XsZQe}?a0B(BWrFH(23W@pbV&GyH(Ii-6OTBn)E`J$9N^zFI+ z%{&HKtvmKSb94j8p?~U&fh=5TM;R{4Zi+WA#mGJ8oHE zpOU;+<(jXzh8}Wv+8ehsIi-F$f=*X{HSbv>b#?jPa(#Q}1?8Hp*=ERgb$J`sJ{dh` zGw)2vzAveKqSd#}-)dJqck8(1TXfGUQ+`?e)_ixfWtLUW-)oJS;&gCQa^#SnQ^!u} zll<*_ZbaS*o46T=3skDIWmkH>A2N7t!r+?86)shG?;I~alWN;P;$^>bi$aTxr4Byf zd*3G%j_u|8^e@tpZ5sJ{>|T5>THfm+3!{Q#Uym@{pKyMMRk$wLw9c92dHepza6RQ* zwC{{vov#C)>`dP5yq=9dGadd6y6~)9S^q;P z+jP^fI-h$m%B4S7_-i+PpQv%m%QDAaE86$cQK-A4>Kv1~<>r=~x%(^-vd(`jIO&q)G>I?hlZQnpRG#irZ>N(c&50J z@bciy4}H)6(y#Fcleu5;R9$cLUSHN7{gSaQxSP8CQh@uF8JA94hTXg7@nvNv->(f~ z+FDjJq6bqey#KuZy|b84eWGSG>DnQ3;P>(Nr&m-hpLn>}TQaGAEZ_U;+jJHN7eg}f`NDPG z+tkQ)@>@_#`QoN_gN>t2-2tBzFT%1nM>zMfbPfxP6Do#>&KR5eqB46&NvZzr=B%D@y>h)zJ(IGqGd45)-Axip zS-va3T*8jj5y&uf7a%bRbyJL-#O)j|Ms$8Xz+*Mtf+URuO`OEZTsd{STVN9 z>fI$5eJk(iswC5Q-Q2$ocC5KOVjO$8f#15vC5O8|wFrxvYcjEQX{!0Qro$)JJk+c3 zqfg4{Rkm#$2M%30xm`EUqMX6U`xRf9-}6}|n>zIV?OYFi)PS5?r-|3OHdz%e6;DQ1 zj`gd$+&MNpC_tG$K|b2z%PDp1+x_iW>rzv@1_jn-kDK)A>RPKo+uieB6GLq7$F$Gc z@nuK%3$-3wntUKux%*Q3cd!5b)#^sy`&QYWz5DP%{SDV9PAJr#wJ}L_PAe>%y?E@l z7vE|pRyGkjgip5ns2}KmyvV(QBeR2#eeN1z=gb#f4&QV2K2v*&*@`8-!=48=vWXfs z?_;adh2m?c7ZC+@`&676ys#wNWA9&N-I+7)LqFN;Y{EKft|hw74y;&QJnU4%!raqG zKW+OpRNw#jax+cJZ+9{lPhoJwDhwPGP~pCxU{*_E{?1Ql5hIF{xeCy`|LBd|+H?yw#jr-t{TZ{aL)=+BS z)_u0<&C(NJ9TQrYcKh0>V(6ZMPHr|gmWYEp%at#kvgiEzIsJU@%kwSNN1FRRw|86^ z_p#JURopD3>mUbioba;A9KPPk1)an5*40&RU-h{5xEp+);Ru_q{>l zCpYKY{k2`9hV(dA8al44eU~l0KZodfo$HI6Q+#HTkB__SQj3nA%lrCKHTZ2qh3y)$ zqu!{iJ-a;~`L_6a>C``~E`%%VSaoa{{ad4{sUxl}>QcXFe?{w?fpr`Mt}R~h#-^_N z^`Q36h82BEoRU!%I`xa^+Y4O!&Z-;9RhLv}mpi(5^NMC4^xhcx7wPP4S@v*!15NKx z=SRZ~OT4@X|2l2kmZ5WN?K?i!BEo-=*#tHV&&qZ7R+Sz)6C6A)Kc)VK_D)Y*gqjg6 zyY&HKBRg ze5mzDVE*pbYwO?Hv253sm3tKN8n`kn{WdC4~d0Cf6 zxtX@esB+#jZ*SXW>b9DYv&rT?V=_liEuY=i>C6G!K@qjq#!dTtMZ$=Lwa! zA51ztq;>R!yxKeX;+`#w<_q_ew)XLz(7xRin^qHNsgJ1*R*`1sr=K67p7pv(PSPPa z*Kqft=80|loA(TAKc?rZ?9jHO&g{=~9CWwnblklpRg7haRXqkiaZN1TR25OjdRv|I zT_%6t7#8G^{}&l>VUzp%7bYLuJXmu6`{lU0<+?Y&<5qrp>$jFIzS<2wb716|s7-0l zI`w)U@%pn*;`6q_4)^=_b^0UmJ-2FXuJ?Se3+aRW&v~Y>c8``cO-g8;T&dlCK4qY3 z$@4J(cT;V;xz$ZCSsN30{@LJx&NoMFT-K)F&^JB(U*shg9XoJr zd*Q6*r%&Rk?tTF&9k$eIxM)GkCN@l(PA>usc$_lzP@|M*Za*qTGceW zx<+?q#hH_P_uW4BEi@&3koU~OMz2F1@XaH>)ADFlpb|q~70l~8H2J*gw_neMRh9LB z?H3#1`#QH&wY+mbw$}Bbw;sCWb{>xm%B(S66*&`uYBEfB9B3 zIedqWOKG$7bM{&ly$g8h5I)Q|{LJtU1*?X3ihDP3 z=i1WHgqNeT$3&Lz0;0a^N?mnDlm{O+g)Ee6qX%Ly7sKw=gsEJm4mp! zMFH2&&9K%TU2jsdZoTI$=UmIY4dMN6&iv4N&^w!Y+`!49wOVDQy&Tl-Qh3*Wub<#! zvu%$}z!R(w-AbuSwe4NOm(H{69O+k?GTZY^|n&(^=3<~oq43^uGeQg`n*$tEsHr*;g1z(e>08RQCcT5 zX>i1g=$3aJw1cvOOkNqf%9)>&Zq;PG>~<{vlegNtt*+ml?-?P@@RQujald@qQ?+;O zhb5lADwN8_H&unU1l%BtHt=-+FPl|?*yR&j*LXAw;H*nA98b@Bf z7}YtyeEEp{$0aW!UUZA_{~Y|VX;8c37nbAL#pQ3cEsiX`Tw1ZuuX5KL*R+~nHgDT( z?fT1&B0Jk{^SU-&bLV0u~w|ik(ZnMWJHPRf}K#5i5o8MxGt(Z2YRz#CW&t`Tn z7+t*c+xAs#x2wDLOJbc%3xajkSgs(z}fG0(J6P>>_DD>*EF+#1F`MUMV>xHehm)Y)Fx+Xa%>~3i1 zxa7)7?|O}yZBx-ah0Ax~7F|*u%)jE=R+*QaJw2dTIm-VSFJX_uWWBslc zN!pwZh8I=+MpvX2?Z5HCuieblRhG|c&Z_;w?DbnWG4Ayv{Q#tNfJh?LNgG$a@%T7rt-( zV}9piG?nOcMmO_^<@A0ufcQPO&oi>S;ecu0m*q5?Q%S}{h2>M zuVjk<=cpP-+I3$0n@zJ{a$6mnF@OGqJ{|rjt$K6w!6B#i$L48r^Lwt`YoT_$6g;U{ zjMec=m8}m=J!xlS zR@>F0V?i_LL&5on)nP7u>-Y`cu<}Fy8D{1MPwVNfmwtWC@)MI^M0}{z(d6?ykct6;;khY zk2h>v$FBC+@t(S`hFi(!EBd7`WC!CUq6PKZC1q#L z`RLqbZI8gc@2@pWEuJ{!Fmq5y3d`+Z#C6$yen{@)Kfjt~L2hVtB>DhK@!7mNNUrBZ_y z`x2B}0*&qz*$UfYKN;gv{C!8?pg{2@aSh2MzbAUR5!E<4In>Rj&Y{ZUklP73RP zTKp%8PZPP!xqQOQj2`zLExuseJ<0)bEwtY;&A%i8zN|i4Dov=>FEGqziakG`~ z%pzQPf{lR#>rXHjX;ZvHtT}+?fb($;Ts`16mEQT2Nw%#5ECsb z6uZP7OpwtAE3_sNF2~|sPVli67gxg&q)NFVw8IlJvkGNSAiNQADrTts%nh+&DqT$9 ziBq3ifo#~7*o&|NJS|>sGRqZZh&W>TK45&ob3E`jc!j&1mjQ1minH+@%y%%3S;2dg zHs5SVI(?$UcY--s+dr7kP&~v_H<~Id0{0aYjpnC1m-i!B?=Ulf{4jA#4Q68-JZ@ak zeXdoLUL}!4smAcZ1)h=VQlft&aEq7q&!R)9%lfo^>HDwhQ7x1hS4Ren1d&Xi)CTIXj02w zB5srBV8ZRW#PEr6iK-X(Cy_c}_PB9F;pJFi)Bm9)V?;CE?l{AdJcu) zt_q;%nVv{@*_&)T&@GJ39k}f;#8wL87q=Tu;vnJ8JB@~;6{xDwo+c*vi`khTV8a?> z?p%uQ%iiOnB7x5kZu=g7i@9El{yydXQ|O%zm(u$2>3s)8@pEirl2#=_)x;oYF#t0K z!E&3H%mx!CJKKsFDbFM^#nD zGQ^AT7++n>mo8ktKuYK`fmm@IVp%b5ZWV73Z0!9;tToXhI2en$W@Uy*H*prCBoR{- zOw>?HNFc%Q3A8@C>cP0!{zUqxua8CbtF^Kq;$*O|`xqvk0H<5`$jZLR=7J^1`_?KbqM?>3*q*u)x;kj*QiOVn? zM2uoysaq2>b4GIp&d_lN<)Wn&jMYtVjvxcUznCKQ9Lv%JyC19^9LJgLhG1@5#bwL; z5)hXG%u|WN%k{2d6n6ne33SkjgV6z=C{U-FL_$=;6LRpUF(Q!0z}embcX)@crGF%S zfe%UPK7lJ9gT*u+7@i?XbZ0Wyiln!pTH*y{nYf}enRkYE2vTcNvT(*$VB|v_%9|gE z#r;I?p_1xg@igx$l%D9=xOala+F7_9@hCKIHmJ$oYP`pU3f0O}yv|#jZfA*`(Hcl( z?FOB}D>FI2_l8b<4mZYstv?CuO6i!F@_;!R6=l; zGi)O+>Y%pB(ULc5M-fy+N`g@-mN2;O6A*_KKfh5|T^V`k{{Sd`BhYj`2UF<~j`|y! z!DVs&aBYOEyv1C{Fr$dcR)Qy(QWbp)8zP6i7J_8O&gF@nK`?Fr6@DRH-?SIFGkik| zjc}A}WNyNU+AH%K3<8&%n48>L^8Lv+_?r=R4{vp&!;7ZA`o z4B|GzXC$$?MoD+?7;AGop*u@t=2UZo%qUj7z$h@=Ay8OgkP=k|)Ha3L9zDn!m{WKr zS#=COpi?;J1TiXs+(lZzsdUEWxk822ZWJr5OHkP>Im}uvNwFmYxSq^v)ic;))Tw!? zT*pZB9}BzX5KXwO@^czA?q5rn*5&lMa{62ue{7PaL5?xUa9my@GJjI@pVU`H46fOQ z#hgx}O@C3B1Vq;0(-o4hw7;r`9RC15kMgJ5ne?AfnjRzfcMxgfRX{d_-%!p;nl9yb zgGQy4DsnW$hy|HTbpCchO_Y~p(hrvFpZMw zXLA55P)gI@Zt1dD3>OR>!LAq^Ig|;!-uRblW2mtOxVeoxjOa3Un3&c^ARBf5krCvp z5gm?~E??8Ra{k2WQld)fM4=@yo&?3><+YsnnqUGU?)HN6%A0Biz=jK!!cf)1*A&7l zU}kUmQ|g|Zm)8EnXl|W=n6>20PLZ)}!;D3h6%mmG(o^pjy8X$m^HVCM?q)Pe7Q%C~ac3A$KN)GE?zP_*RYI<(+|>y6A|G#Y^hk{ndS#umf4fCOHO z!cH$?hJGSwS46$aE?IUA<*4Zzu+uW)IpQb)KIev25nPN07mzODneP}!{f&e67cN}6 zaDJf(bWBQ>(Ntqh!ArPn4C7-i-CR}}8J*iKzF1z~#saF9VJ^qKTc`5~S&ky-iiAmH z)%w9yP34P9RCQHC7Q^BpK_B1`pnW^&eS4J2)O0uv1gYxgnyAx)j5Im(5~?z@5l&`V zQh?LE90(2w(88}F7Y~KRc1WcdWmB+9JK_LEhR*Q|Yz~GFOPSfIfZSPeaImuWGQ>sS zFu(hjFu`h!)@o!Pc{@eBX8!;Xu)p|$Shq|HtX)E7;t9P%){WE@K!)u%k(Z3hy~s{t zr*K1*hLp30?hYKwunm`y=2778^2J11?;a_B*nXK0MMRa*dQ@Zg1**6+Uzx6Jc#5@F zJi&T}_oz{&^DB*@_L(NU&Latq&t>})Vli8ax1fp4Kq!gk1$R3$AeMJN_PhX=u>faWQN$+K+_H*C~d2l;tQ(OU565BnA^A}qlS#knIUun zf@FsA09l#k0%!FA=M^y*NwPK;b2qbB4b)Yn#XLolGu|5wl9lBw05w^KA?7|%H(lX@ zq93@Eo6IyYR^3#0fSzz}>JFG=TW+AXUJDIw?ngFTH|i?w`-_A0PJ|(@l`2%ILY)KU z@irTB?$ zekDBwYIBfk1Mf1lJ(;vI-21`$M^azaxWo`mMP}fDRc-+p{J`VQL>3~US;rBnQN&qn zTj(%g#zbW>)PQ0zV0Yw~2=@6Rlubs00UP2S!W+|>dL91&QI?t!m;p7+0lBDPS&!}; z44Ux;?;!~(+`;0;Y?&S4Ygl=h0DdKEQD}49n3md(3kH)da@?xvxU{%l<1ic&%>uP` z8vGejvK`-SZzsUiMQeX}KSYG6dJ=OhryGPOY8}*NEpNO~IgM?pmE5@QBFmpM6=F4P z*NC`f#xWyM2)sVAxmHdRp=-hg#$1Gnu>4OFFR+giGi;)pXB!iY9}&!ks^8!pje52%|XY< z+$hc7%yX%@x_~qsGDD_mf;7L6`GRCup{R^1oMtLOg<*$&@`p#50AABOuf$nXaKNnG z#>6sN)6Bs^)H9JGLtItBirSbOrXAcw&Enw76$5pdh8J@nl@gh%m}r=lQB_TLxwr6# zp!A&|NY_IqOM?J6Oa#wp+i=++SOY8hm^LG;Zf4~$;07l`|T)A@P%Y!alxn#L=lCcq$ zF-*Rp0xJj}X3MzisEWIcKJd9t_Z0b@M2rbwxNvdau^UJZ*)T$Yd1es+;6-!@uGH9M zfOqaNcCEPDH=+L0t{*H^b)My>7K%>I*`@NRisVaM5d#!5x)FBC?*< z?JO4YF|aj}frw;*LMnD(X@r_*a4Bk;?FAUqlrC3^jY^{|3&O*BWG$}It)Jir(t59^ zrOWi{ToVv(8EJqPUzq6<{pH<=O(zmDfEY%DME<_Is5LzOAdX;Mz_$%Vy%?3EiANH3 zF$JuX!8}s@vW>Fz5gbJ^Pd=edN>4}p;@VGvKNDX7{+sbt_E^uB;w;o75IoiNgnX_rPsOqQvFvirCdstjKIaglx8uN z{KYr3=|XKI19VG%nx(gVUcw$)PI8)tybw!JCRC?~nOA4*mgG-B7J^|5ULppB z3@x?Q?q%RD9w3@VURAcuFe!9u^!rTdmzH9mf~I1xHbf}cRc0vL{@@E+s36#hd+jc^ z!vq^mV2%wp$qv!IOhH}8o46x*X&?o5m75=l$+|a~Bh0SSub9#f{7QvEg8+h4_vh0f z`YscQFl~!22``~B3WEl2DTkV4Rfh2hnjt)sFLUfFNWt#=F`UlqP6}d~R}mcjA%55J zCqZDkaWh#0lC$834L<3Q%se%njLgw@e4t7f7pA?Uo#&z}8Aw1|QITtwBQPOhCoqI+ zhlp&S%P~#(MDOwjXBXaoQ)sLZ*yeD4aVp-tdq+qN<8a_KNMH&Uu@(y6C4AW9-Y73x zxQ)JLe3MIOvjqro#7=2P5i44n)#7H2yfYiBmU)&`=C(_yW5G8b;bvGGr?gH8zR)36 z87>>fldjL-p1bIMF_$hG=s}J$gf6^8?2AE(PLG)ES$Vlc2H&uFg6`&i)M_a-K?TbA zh>m`MwR?X9Qq9dG6%amHB_nIw{h`J|%b9`&sE)Hoh^w~c`Wv{`NFmgVq>ub9KvhTD z84r9*N0A#xY3`h@A=o`kVaI4sXS670+(B2=*O&|&Jj^){coxZgTu?(tD+m5|m=?91 zKnJ`Pmi)#Qh0UcPT85>a{_1jjn*8%yo{%J@fck#-ZeJcEv6XacT=@=MZzFz5N$i7 zW9Wkjr=V6c%2(Dtt-+TsqVK5)N`Z67EU=h?E4HPIxXl-EYP*0o{{VksRc~<7xx)rd z@3=*XXG#w+DxXCq=9fp^5S1_ia)Ctf5|Io40Gz-S)0ZqkqUSAM(${@1Vayh<37T{v z!vnW?gO|e+(1IDC%*z40h9Z~P88NXv`2_$2LDw>XQZTu_x;U8uqmE`HDF`BjdrFln zqm9mP-xH0a%w>~9p=cZE)G-o(S>^^zenhc>-7p9EN>Hb{2|%t8H0$OnI5@lS4-uJk z_caEZj$x{WfOePOA+ie9IF6$f?L=1nVQdmnQlr!*N{JgrQoj7^L8v5Hly4mt4F|lV zLw%t`epeL>;R!JR0J!4;URUfW49oGDZpO3r_q=pOv@K#+!zhzyO-mA#3*?5Wt`qJK zs;CxLD4r5fp>jXw5K>M>y)1l+zVh$SsdN?QUgV~lBM$L0!E^Em6&}{m0Zq!d27o&r zffYM-s}U@AN7d!>mikz>AU7?OAXj74e{X2ItIHY8$+AwXIOPP|Vf zQ5VIsEt6c4%M^{=Bo};4iBQEJ7>G4zFzv+0Btl`-%Ukm>wd1iD!X+0U)U042t^)IN zmD17*e*UvX%a<3>LRG}6Q6p%l@CLdNgD`O@rv0E5e~FOS%&g^o?p2#%Gf4+0j?X_} z<_Eb2{0Nk%Z?&<~F*}U?OM%K{5uD&*79dh_x%+yEs1=n8Cx%xe;GdbeuIX$~1;x4i zL^qg#zjfHuGaxYEGPC_8ur_oS&`$7Xk%1H zgaDXJQ&$m6uX9mq;0>I@2xiwr%kX`CdXaESH50=s6uUHjVL7huSdIv{K8p>+n5Gk7 zC3lPK9pjZR`UJ8|<$`Tp>k~eMjG3KI^SBKF>=o!D?{N`-h)iIi!w{^ed16*dl`3G{ zJK6Ca)Dx5Pv5~DPye84zpaKtTm>Zi;LR^-4C3R5VA#EK+Ryv#?l&k&+l6lc!$?q#E zVhG}LMFV}4E6;Ot502z8R}(U_GY66g>N?CC)(VVr-xyh(Q6bEE0f~2Z$qe5gQ!+m@6sNPYf+D;GdaEZQiZ?z=LQBf#l``RdPC= zT{0%8DE(0J7B)(=n9*u@h5OJMjcU3sEEOIPLV=c`A4Q!*!vpOs!5F{yGX#$uL2~dg zeqPZXL*6PbKQ1Qu?F*dC^1}44T9^O>KvcK90m8_f-DhS{&`;D9!uRhtlTxKh=~AH< z1kBL#^d+NxaL3GEV>UgbB%|IG7|)!_7KrYv5W|ecoPX4;Z}l2)B(uZJuob@$ETWcH z#Pp9I$n{;#T~3 znHs0qx<)$>h;82<-)1?3GGz)Ux+QI>Ebif}JV7qycA1N9zhEVxxshJxFnML!$L0W7 zcw70E0uY2XOr4;_5V5-tcp_Nh0JWlPZXb1oEUWisVBQQ%7j|62^iSNmpp`D`YG_7d zaPh+j!(E+H-#z6=Hv9ChxIpL|BD6M6QC*ozui6O3UvmbmosB_gk9RMrkdtE>sZQB! zGsbz9<@jZ({6v)jv=a&yIZAk$o&NwZj^|}yB5<}0q1s?F05%SMtJYo=Dwi#pg z-RE+!hhVQx^*9?Pv=`E9QZzleg-!8Bs+bbn$DUx-kx`RN5!D%q@A?J8K2 zJr^(OTo^Lt#g_;mB&1V_y`sgB+TTlqh%pEygSZ0>((+&2#pU}Qr|X%n(=*4}E)wOD zN&=#$V23eQBHsR@Dg|Xld04{)uGk-$wQlun!&1r8p(r_E2Ns^th9N32Xo&?x?!Zxg z1_5JCs>HiU+N(_Cs)piDV)(D~EScXxU=w2zH;I-iZwH1tXTuD;PZb4*ediRBTK1Vl zDnM{r8_R9wioFF#Xr?u~)*GlbaKok!>AaGqO|G-jqd{v#)BF&l27%>^Dn;m+BL|Oi z=~Yv0GK>dc^jXrNs>#9mN^}mMNW*r_Z1;|EAYT}Gzq}6E!83b%;E1W2Bn`nTx0a@`h}_ZKb<9)SaK2M|}7G=9Fs+!Hd5LPN3pJC0`(vBapN z?1F)uL|fO>ML?{tPb&#jv+aQiraRVuFd%VxQUFljN{3SR(sLfcXpl+~32lt z3}>MV9Qce<;OO@b&^VFkt9c+GSEESZiBCuJl_l>$f1)EmJHUe}g(ZaNCTPd0c@twV zn1)`+w_Sbtlne69qkS-LTWt0s@dLXTE)Oho?12G-Xl;yIF)ZkOLCu}sj#!5J+QHBE z9*bMNz`^K4c6OFCCYWIu3We>;;1MJ#8iEbsjR?@Ws&BX88neo4Xl-1-J&*@eQI+GU;pDY-^%mJi-fK>n{zRLWy;7 zp}=>2Wq(~_gH2B}m30EbGi?0F>-d%=_5TwB~#VjfzdJSGt|SC~a; z%&_2l_?dQLaLSY=;wB)I2vQIr1T*{ zUc{_$yx}uS`xqfr<^w$z@6w<}1+5Uf*;l?8z!*4|qeB@*vf`g>h+Di9HQNSQ*q6BB zw1;4?MyC(u3Ue6RTM}7Z5+%a-!~%j#2wU8UKe}7p4#egcv6d-db}DAfcO?R0&RsFfY)i9JSuTJ8?^xxGBYE%$pW<3~1ae2=Sdt=y2+poS6v3Ie86JB650w~3sOU+C2 z_>~As=yWyj0}a%F35`X*^7t3pY$+nRDh`AP0aYue!JFW}n4ta<@ZC;2H?k1KsKBIN z1Y*t9aTBv-%y$;S)Kz?vxhr#=0005Nbx_KL;nIZBG%@d*tF9FVBlj3t>m0cZ|@ zYMMMlD680Iic)(CGin-N=$D;DG~zQ@v0nUNh~a2=*@A`FY^hPqG87LyL=5z)QGuT4 zWM<1hQwE-4g0%;hGuRZPa=$YuJi3)nU^<1*1QWy@Fnh{P?BqqJW88bj(E(8KKNEL) z#3Hp%;Vo7u{$=Gu_?854g`z}>U&`DWeMCZOAPPYyXBV{JpFc$03m*`sW*6CJxk`*B zLt*ALE172&%GnG84mP%P3u^pJIuClxtU!h*5`Z-d#i$s81V%~_j5isq60H9DfLFp~ zd`Xpx#O_O2Mlj6WNObp%i3S9JWU06{+&}=A5@NlXg!AW68qZfD1QXQ4CB`aCc|Gb6 zpasxMg+l@0hKPQL(c;XwFKhMaMj~utis<&1RDJn|)t!!F4TrS8a{J~ZUR{C^CSYk= z_sR5?7XGEWR%aCroRdmi00`L1^lSq5Bk0$bH816d*-HJ1Lr)a6H8_TtNQX5A1@OL* zD~2HDN|!7+W+P-1ABZ)HYYB;33ZCRtmxqY z{{Wf(^Oq@)1f*H}BKG%CJqYkh^k@eMv~JS(8et=W#Gn?=@Cib6u7YF`EESq6JWQ$I z?pBy;=fug85Sxh`LKTxMDS?QED@>#o&KOBVbyB)lP!^zhnp;weRhbUZ4M;2{ZMdfu zdu<2fceVfk0P!oW0H)YC&s-uPj>nkgm1Zu8F@55@I~jZc_GX1XVX=3X6`B#6_8CG{ zz8JKv4aG45fC`qf#&Skpf$Y1@Jq?b?;L3M~kVmN0yi?CqRxli5_k#Zbn7PDa>^w^r zSeA;)Lse(8N>CfVWf>5Wp<^ob6A?b8{{SO$nO`uV7df*#L`IUIO_q+y#8gkRLV~^t zu&=yUsQVZo0IAvx!BQ^7u^y`m(g#CzI7JftTOH;|UufM$2(=5#F=}@LR641b;yOpg z>N6qts)TAG*(0uVb;$tZM{c>~0A5B17PA3dj5+Y{iOWU7)z? zE;0a&1=;N=QY3UTb~5s3lcIvwrj7Vc5Fm~IW-6y0Q8P2;A9hioC_6#UNJXZY0|f%S z`%0hkgaCp)P%=hv1K+eY(z+xAu{RnZ!!9(OFfty~FJ~e%l0Xb=zEA+51F`Ah9Wh6| zQOvyrYLbG&L(ah;*v7|D+QnPfZ>Vs`rIQZHg{Y3~`Pe}WZW$U>Tx33U>^(!k2Z94@;$ zC~XPPTN6;ZV44NO*xTQ7(M4@7dKQ`A<)fI4SWq;7ZiME(&oYejyi^sc*J@w~Ti;rV za+1JKNq7tsf+>3lVmD|{%vangP7}e^K(-)iZV6cn3>ZOif=rR39$8msyn!e_AR$l0 z#Nhd0KV_3WNBqYOw_X^41dEW_XRCs{> zgl^(63yIz%vfZXdzq>6=Qo6Z&dF{z7qY*Aa#X$x?Ju9UMUmS?`-p^<~pmEwd8qV<2 z2=@8{8yR*#I6i(7Fywiajyf?cFk8IgA}9mPk{UILL1Jd%6{-YG%7g4L_)C`ta}?$= zg^2K9h)#Y9zx1ezb2f%QH=tM}OYII`S#bSDC@VAQ9`M#z_=3^=A%{xnN{xtj7}pY1 z5u}WU3;nQF1@;L-(cX6g+rOwydncxZXN2NdjIK>fI}?eF)7}UKY-LoaMFQLtRNPMh zmJjD+K0q;s2}HozOnP9(46MvHID13^8zn_ctBX)SxFc%gO9GaaJ7@;p(JM(w(Tr){ zAYxQv_>4&Sh|>=fA9e1+xSfTD@G-%kNNgelSLj4%8017~qbrp|hhsD>4p@hKn%3SU z%{-=ZpLRR2J&ZvH#o?^?@d2t13J&eLvMFQA`WXu7T^r+}W?-utVn&g_2_mwpG zAqIolhGDqPD1-}H-GtMy0%dCGA^vSc007W*LGcK!1n`{AVs&v{-(<2siBgJ<%T3*G zxrOfRzRU=yQp%MJ!+sz;S<3SbbV+1ng>YK{{?LvmXn0ex-_ZCD6*Wap&!7qbj>c2S z*h@YxYYeG${KPKE37Q9&aZi%51FvX3PmSb_t9!6-U4&r=`dMRa>w|NXx5Rb`KX60# zS!JpA1bc>QV&I1crO{X6A;_;tZ#8=LlT>8MGdTI(!UJnz*8-Qr+}DRG?YBDdtcq@PSc# zA}whk5a>{}x?`5x%BX+=3+>TD?WkiJfD#LX%pEEO%WwdUghqU!rGtZxr!WT?J3tNA zd-bTGT7*eJcjh4#idKSYmFy8(zU7yM9i>tQb$Wn-`k9rK#$`1ibk}F4bOOkiA}^gl z(+6lbO`g$17Ug#PK}B_`T@~nzEMD?j5+t-ek^vx(C#PD#G4nIAKd9()9@E4#75A1~ zCurujqZ?u2)#-&f9+fRkZ;0%QY+=-3>4V!$rY#y{viQuxJSPv##21U+VUEKn)s{JT z4iH;${$&{blbLb(6NXlrlPqJJ#j!C~xVelq*!mn1JVyTjGS1?~V9wAqC6u0wpst!MG>HGXe)jQ|xL~(ISYd zNELcurz4L>11#pPjlzjuYJv-HRf>mDj=Ha8zS?9=Ws>{|K%pMpR5yqvR$>McyKX9e zk9l1w%J}3(+23t2)*2j2jE8az#rI31y(n(Ob(ruH7v z`q|VF?a%^A!MxR zmx+Y45c4fTcmq^+A&PQfJIgK^5h0|O6S*zrKL#67$>fZ+d5v>}F_KZtNoilr3P&UC zvj|v1%>_=XP+w`E!RB%m4ZwSJoS2Hvnt+$3kHnclX^2B24q_s3oYcfLi^SI2=3cc> zGLy{DMN-IgsFxoIL;%!btQerTCJ?WAw6i-%sdUDw&%`*}yvIU)=v1qK=;~C}YQXOm zQ%Ql28NNiaGuxmFU{5~q0HRk??2mZS*23tBoNnj^IYDb&EBF4v6!4kD4CU* zxW#`4{kTm6#qg(@iC4UFD&b~WQ_S2IDZoA;V%QUjSb+3j68WqgR7-)VY9))7m|Ld5 zaW;kFj+EDVj0#LNi$6Hb6|`NUnEl`qrxK+~h9`O*YElKpwyw}0$8kK z-eNY#$qcV-Adn&GzgqY5yaQa`Bp<@SMc)ka983ZS|uHab~z1uM2cI9S3ImD3Jy99V37qPMhXxExJ>?}sC09U1{!I3pRrsB!?;W8wlQ*o_^a`^-i>3{tUn;yA_AFm}^jiL39tJt5JfaRuHd$akD4J)+TY z$%qoAKoM0GrIy9wEHF0&+;YS-(xQS3mrx4^(k)aY$yZX32c8*+VH=}Rl~LKsT|s!J zn0iog03VQtFunv$gb`f+Rw<`^Ou&LeW_N%HJW3@%`UkF}OJN{|Im>m$9Z^}{wEhFA|U=YNe$st<|0(y7d<+9pSc$!PH@7tUb-0pOKWd2=mQ?F6}wMuS4xzDP-_%J-6*3;9+#(n(&VgSj>it+ zUhN=m)wlwyj+Fu^EkYjAtHfDvd_?I4gTaTf9mkl$(i|KK@c@86iS;T}a1y0=lIp3a zygY$BLIm<~`bx5aX?|I=E3qr>Oc@w}d4OA|XiW<=(eDpY>0F_}%Lw6NRk!^^qtnC` zfSv9UlDiW4An(k|qwgpH9tf1J%T`+e{Ea}Akp|VNepKja)=kgzw^cnn7MCAG^!)i`a(Y zzVIERWXEZvIVGV163(>=Qo2)OBiKT)TNS2>tUaz)mGi_b3dyVHTZ~J$4y*+XO4Vh> zs8oCw`(c$I@e*^>6?0{0u^U7V>`{M~UxDmki(OP**|8WlA^`y^1h1@mE7C0KDlFj zYWJD~_#zm~mLhur4+FE77}Y{i!RRM z^qQHVp^J0mis-F&sgP0}R2u*+u4~ZN8H7eIX>zdQB{7K~;+>XT%w8bA1&`+wY${U4 z4`>iXyL&-Z)h;h#Uho=4tgwc2D$y3Lp#qA<(8m}}rSMH}={8TaXJtyLSfa8a3s-O@ zO0I@l2sVtwa5Vzl#MharLJq;XoOw~G2ZN~8qYNqPkV9k}jXkABXoaAtGsz0H{6H-E z7(Wce7Q99>oy?$H;FL}|^VF$clj)yAy3|Q*xXA&2Kbdlcb2eB`Mm>p;vEbZ5v%bnO z4+p0DIVu<^v%JEG{XJl*gUq!8<+ykRJE5!})UqB)8;$IN558q60VR8hA^o6#I03=a=$51n8bM) z9ipIvYSbYq_}B9-MEQ^ACvw`ZTw(MGCc{#NeE5q3&KTGOTjmh<}*a8Q6+x~ zNTB#aD%)T*APk{ACoo*aFqT0Td_=&VmYGP*U9^@e$}gOEVmlYH1Hhgrq?*u7V!;KT zhX!#0ec?%oS?DMwkPgGgX+&~MG}Iu`6@=dIB~lzHt?>X3)V+yYn>$NFCOT`OVqReM zxQC)tZ8E_ub`NPp`^IQM_JANt`iHA%&-M(xyMc}m_w*~(Q6m8H0zs_D@(~Fk78Beh zTs_WDrcNvDW+qAw>_t=aEmBvA#W!(?q8G6Y0Uq$6#1P?@C87^~{7XUH7eVnBEMof9 zBFSP99DspG_U0a7WelU+5a5@5lBu-)M&0S#a{$_&@`mLAMv18Pfm2P~B=qY-jY3R-;_Kz<;Mf!WM8nY&141b8DV zhTJ3(xIJqM?rx3L+e zMJ+6H#vV9yRI*zTg(8oYCj(&OH;ON`9z^JYXb&>rJR)3_J|Z@v`^%Q!w4+D6Ds24_ zV4&twkUYa{Keh_tiPD$it{mkb6|T1UO~LADEOJG;wR=Es^zSfw)liJVoH^XQo2;BUuy3;AbU3gYCOz`#7yWG6?mS| zU%cBG;waM?0fuaeDpn$LfmoV~8;@@0b}T=jLFAfnRQLmE?lUB%$Jat%RLK4%(a{LgVjtp?Fj7l=#trN zb_bU+JsuW0XWpeHCt?CVL4+^?DxUJ(x$eV)SqonbQq@^;h4fT91Y8kwL%XQyW7vW* zRobO$s+2Gn-!mu=H7L_X@XHke3K#7$#izQyB6%Z>IA*(kCRJ!B8;#udM0-Jopf!@1 z*W-#!>l{S_aT(1*TydHeTY)q8Ba>&U?y={fdfA-H@dZn}MZD zj;f}Jj-}1qTdYr*;Td-_>THz}8fOx*sa+nGDpaqqy`4_ARt)DR) zGu;)_6&bOX0hQ51Y}+%moT_}lIJMY<;J20#Z*}Gkx-J+Aa_mj@;u?*1MkQ;Bc1D;W zT+Tc7LbRAsJ|l3bjKMiP0TUs1TQM9!+oi*)=}Dz70d70MW@#LUKQf1QdE#&|`vzYS ziHR*{iY*ZtngJz@xvK~Qh52R8(D4#!zQh+zPcdL+Y}EOd0D*uY9JYCeY>Y?%f22xC zDF*t5Kwp1Oi1J#5nF~{@OQGys)C1xzC>*Uo&_m??%P{cr{$jVTRm+Pn(k2o{g)p0H zz2F=d5SXJHq6Jbw$Lay>&g9RM6@StwQsX`1c?_abVq;tPhAyfLx8gLLUM>J*_Y29O z=6vQ_x?-*tIpQZ9@e>|kZvkA~s?jVi((^=3EOcu#XcO6+PjT z5DcB^k5mZqOsw1jP^XyTOCB;t>rF&}Tt00_5gbNkx&HuiK2?YXrs0C&-Zg&&ErxuQy;P|Kk>l-5(c04mQziJ(`pn9YP8*vhZw33cUNd3nRbL60jP#s$8rwErcs{r`hl8AiHTUwW$~{N zIk+=yLBjh=0Qt#%*nzAskpZl&?+kMnv*raiUeK@)+-fB8yYbOcMO<9&V^HPa#1(d7 znJfBCj49#|1Ywqj4rUQ~<`=mX#!_9(DegcBTRgZRA^`=Zdy`a1SV4jA-bMUwKKgCx{**c$o>M%IcD(O8Pd?pxG(8Q86fPj-z0!9w68< zu>>HBa~zt&%tkRy#+1JCOTpNjeSE+a2v=&DF>7duMhJJ6DpW|f*g&%~rAHjVx?Ex{ z+HlMP`GK9-V>NeWD@gE1rZl@_R|7D6Y96DhDmAx>&Hf{}6&<$^ycX8%Kt;bUCN!3R z#SZiw9sPoI2{j#|Rl^;EPiupP`KqH@>Rb>AgXrcn+t9Gt=4JYLmQne8#CLs=@>kjy zW_Y=BT=!o0|+_uE_<8AuMv=qJwrKNn!moL%`Ezw#8-)QAV z0EDN6{{S+CVRjtClLr^Xp+v>;1r{|>r%+w!5LPgpQ#7R9u~~fim){cVU3iI`m!`n> znmdpQi(K*gN;W~8q~3dyi_crUuJ9& znq@SW@WWM!Tt)VNBTOp$Oh(7Fb}93yPFBT6%69E2MRN`nhnbhW>@L4kxJ5W+n^1d2 zG$SmjO$k`@GSqITGde3V?ow7_d5kY%CSo<>Qetr{w?#^o)g^kXY22#|5Nu_3l`FAw zmr>YAW}-Kmg>`nts0UXv+d(^_?!W~EJq3UJQ5q#z6Ag_p>MY6}%IJduVA0xak`bgs zEnEQuVSs@1w?o=5Yf;Xsr{#?i=U($a#*hG5EGCD5o~ zz9G$zW_dq$VijVdiSvlatNlvR1F-W8bs9i@K!7fxT>SEaq%p)vf#GYwAnLw`GWhz z-tF%iy2bX6y{EchF;1)T8`^##FAF=6EE|h%k|vz?fm8N~cO7pM!5w&e!i#eAS1*x7 ze&Dg1k0FNAb|5%1!z_Mc?ZkV?hL3f?y*Y+Gqm~GvTs(AQLe6mlb1Q+Fv;`DqYi44U zLbWR5N2NSU>YkS}M^zXW!-$a$uuMa@nu5D?G#+FsJ3y|7xry6dDqt>EV6_c!eGVuN zEYuQt>6pcX7jt04c}tAc5&p?`kndAB3k+WIncYAnFC9xJ%N%%!(7YLzuwyeghhX}4 zDF`sR*@ua3P4APxs(7XDD<5O_&FdF$JQ0;P~IVRpJS9+_a z88}~f0{KG#Z*?%5{Bbb*%Sx($aPEIn`wz^+Ie=CymszM;%keI^pAgCZBTJ9-DOyR! zDV0sr08CNhQOyu|TN>Opth2Df*izXUYplZdmGc5$GN{a;RUpNHCRuQ2SdZe5ir)2x zSl%7T7Zk6OE0PUIQN{a4sAl=?6517Nok~W@XEMo#cwn~!XA!Fg`#{s0^5$Q8RP7vh z6DJvgTPubox)ExO#)^5A)iS>@xa7AL9KtDz4)L)yiFJzTsEtbECL&6e6VSkm(2D7p zcL-&x{(q@nvE0~FuJ=N z1j!*aQjo4mDAFjQ$ouX45zqbHan5zrIC-dhLgjU(M@#GD*d(|R1>@7ShLX-`YZwMz z1X}IU74rqBQ4akgj$UPrI zGXlQX#B=`vdR+5e^@#?6{iLDk8%~9>bN_znXOc!pza|%UqrG4lrDW|1)T#%CZX6Qa z)C_Ly_Dw2GXV4?X)JG=7rT)S*9}QcW50HO4bxj_sbh&m)LDdyh3(b71sQ?DN>s10P zUx^r(jKRHoFU3LY;UNWy;FxF!svIx#6Z{e?^1+Wi=t)FXDTRU#h)=3O7CZ%>ElYQ|j;S&}?JmJ;Yi{rkkH&^g2~MM_pKn7f1mN zyp-i!VA6JajP;O})mY>Ditkwue(@e=P!%w9N2_Yas5HjzZ`{TF7E+Uc^fGFaB@{il z*V{igA0!~l*D>H?g4s_gh)u0$(-XCCHH`?>3Z3OI-zb*t&K0mt>C*q8Nm!O}= z<6uLE&k&!bF+RDvn=|TSW^31K`X>en2>FtIJPRgqy(I#{0rFA37PjeVXvFT72p-iu z=gN?kgPvjK7^k*HcSyCh9?eg^7S&gEkpYFW=)vtH!r-1z=WJVG+hlrWbwan3h>VOcbVzp6xj{$m7H%lX4z94s0kP5n&3i;c>N_wnb%)R$9A{ppoWfatHReKzJAFuniFuFn2-!gAm5%!V(4A^xuD&UDB3V(YN z_q7s6mR`k?Wgw!adwHY2b{)mQz@+|XPBIcyI}5ZU6Hu5WUWN#bI}j9n#$G3>If+n} z)L+;nA9(g~ur*jqV#_F;8{5@<(dOh-i{V{=mPKm(?FB}Z)VwMVuqjPU%4Wk2o_^{h zkZ66K^istiHH4519dg{0@=QNkA9dm+VCcvW5H>iZJLOjLt&I(_3CR<@^_8q8GTOTk z#8Kcj&k)y!>_!cs`;MG}CczPtjdzH8t6l1t>~m$JDw_OSrWrA%u7a zRo%s4d`O-rMYKw`InkQhTP@`2ALsuA6fQi3(n!@qF1y=F7W;a5`Cf?7Fb!dEd4>ut zM!juiSe%!Xjk5Gzlv4-6bRkN2L7^31e=J!8y0MQ+4tVW|<6I_LT7mb`#ENZk%Hb7C z=y|Xm8QWVxTjZ-tspk)KCzUI>^`$4-6dw-6T=mtMf&}gzok{`p6;1k&cmsnj!o!s~uijxKJoIdpx3TKrz^<>Zq4mY%2>93hpmBuZwSY?mmb{$TdC z;Em_E0~47)nF68>SGb=k{0aTz-C(@ji`PA-XM#(*P(PIWm{Lhs8K`8RLY;$Y)P@_) zIB7ThZnxZ|)%SwZ>IEDc@vID~XGY9yI}F)A@)7D)`D1jVd;|AtG?vC!cM_U8ami64qA*i&f&GWPs**td@0Bi*U(B((zmRzGA$hK*ZJTk5i`_O*aHc>tA!Wy$ z8G}ZT?XNr~_0mShuYgSw*AQj8R4FOLcH&-zNd#dG|E#xq0F}uH#T~0EF-^E*lHsWZ z3LX3kNtKR|&!Onjg15N@vSf_x#w`EQWXEMPv#t(p!^yQY=HS};Ow!q>`8qvMCU$x{5&LH> zUVqaL03UjSB`0zuoIpG{jq-n0F7b%k^~^p_c3+VaWN4xYS$4P%Q{el@rQG-eNN)0Klyf+P z;B_Ee-NMu$JPQA5u**XVjD%c;0fzoQeCqf?O*tjOReMdbRL%c z2t8d8T1v4!-lK)x>FLClPbXP@(WnwK^XqQ>1FJ73CM$B{p6UNBqReIO-N_|axEfLU z&FPFLDT@-x%H(Dn#tYkdIijy_Q^F8XO1YfFighS8OR?}w}7;i_UBbGVXDF;Rj}G#^ci zVUjT|_01j-=AxP5iRV0bVo581KO9}Fmi^Mm31o6IvX8bGu{U!)5m$xbGSpdV0e`W`a^fwfCI9Zl@?NLmvauR(rAw+e{{A_ST|8rhk33^w+jU`%ANQj(rD$bi&Zr8oW; z^g}88&>Dt{k+zfD=0AXxOn%JxF5=Q?+9zjeLqss(iU@0zKeMH^(&pMm)gQjwr%B~U zwbRx6p)}ITUb_f$$ml)Ul^@k4iD$}u3(w+q;)57gC%}=C`90mKWZZeGC`Mk6FT~dC zexI_0`REr8{R-+Zik&+0vuR?j)*=B{qV`QWiM)S-Z@q+jW9SkL+JRcre>riIuDeUx z{uF8)hViA5p{%Pqo$wWy=*80F2<%sV9Dsn{;F#Ek@lmEqJp-xAps&gxjC(6{^;7^! zcNh3BaTDKb*7t`&1vp=Wm^j?nsJ~5H!U<~b_|}M~i)^!HYZxbo#4;S3LMvhoIf&p1 zFsI)0{dxofB;EQ_h`7erf8$$|2n3z_HT160Q~d57SPnalkMakCuD4jCHMc6S**68 zmL%QjCSMk#$9*b@@$InWoT>KH!iQN~{+~mFZNLcDeZk#z8!snLO)5$ogkgv{W(kcn zno@*(HDS2}7R%CEK@vP#Psh9aWes=mw(;HmlRXLv&}Q%jePxW7!erwzq5HeP=}~#x zd@qGOnXtA1WC}Cq9m}cG3G8VQN{VXpwrhkP~y6kG>%=~ZiSWT{) zr4;TisJLR`Rzxn9Pa6r&`YI&yeiezeMgp+qA3NfIj+GE>!{9aj%z4?Tc92m}IByH& z33h`=u2D(pC0%7bAHnJ#EzUBCRNxE*cMM9L3O)5J&AJdPx zxtl`^gc_6$av<1?MN!fE!?JO2L8S87L)Uk}O%B%u$Q9)>zeSOj=NRS6{E;@d3ndC> zUzr;6Rpu%#JAjnsp+kez6$@7!N?tu_dbY#}bfWiTQWW%jRGWpXskCaK- zo5hJ-A0?daI8k9jy2wCFQ>TAB6;a)cj$m#l zR@n59o>Og8n&Mf<>ztama#4^gVabHk4or$5ww3BMxUoQ@MR?7foO`VXMjmT-fvW6M5~VRz@4uc)xQ*Q9J=!tQR|aZ;#fGMh!~xU=s^Mb2P6>6(joZyb_M z(L#*xc38=>WEs3H_Oc`4?H-|VcE|TTk8h%iU{^RN$iC_;9||6v>bsq+Z^*8ip%OB! zPL~hX8uU9D7j`vr_l6jcR=u|Z*5FJS@H59nk+bBe!;4>b?d#HOy={*lP>+l6?3swU z%DBfkJGE3$HP%8xAYrQa>b^8WvnN2e(9h)dX8=nV(E5HRRSfSl#-0ef+Ng?to~$n7 z3Q{cCCj)rL3CR6}(@rEh^?|5wbW_LhWunVqdsd5}+=usQ@;A`f$GcfiT>k@{>Hj3_ zn7_p$;0N@SGI9Ulk{?>3E-2g;51CknMU$;jV4^XeQ&NW**R)s`q_!MFI)Jp6q>U@? zi8-kQJOtHa-};=}$^vib58^!S6c}4@1W?%UZaZKs7K3XA7>4tB54@ZF?0P}->k!=} zwZ;D;jp*AJac&cd(Awy2#2vTrW_GRy`RXg`-tO)V-H<$tQJr&u%7#YlR6E(EHY1}T zjNxYvxZ}CKF4>sN?#6Z8Im)YxTAHT8&$3kdIP?QBgj?1%GZ+d|dRL-y(21Drt-H%A z2P3Xk5wSZ$Tw|mg1T5X1>7CUWPn$ov-xNQWj5xsU+BVX^#-bYTO4hsjsAziMh)*@k z!RyiL+R6m2%x$$cI}r9K=&^sLjx821SAfiAsFKyq+=$SCN;`R$>MDG!cSAbwL~7B3 zQ;n}e%_HWEQ!p;`&oZAzdbT|(+NXQ1F>@SSNt^QkH{f@&)5)VH474+*fdMo4Nl8>m zVa90_?!pq3xZZ#6jVMKjf(hpTM#RR801zf2M*lx=S!LUjtGm@>%e*lb!~=FC{h>y{ z0uOZ0F=`{S2f-Mu^a4Y8CF>b(VIrk;qF(#G!}4&3v+hj8t7nj6E!&%^dYQTrMKJv`Hk)Fa+*9_FK%7r`lLdU}^%-?a7F36D^J%q>!5@cI}%)qJ6Xs zS~#S3O5bzm|1${qdaVXCusTtJ`o?mBtd8+H_i z;cUj!_tm?7zOV}VbVzgY5g9ruo2~nvn``*PadzLkO7v)eEt04x%ITMpix$6}kT*kB zoZ`3hMDR7Yyp!CjSm*v4T)X6JC578PxRhl{vf&z@a*kiQqXUBw>;<7h@h^PknigGr z;=&Z*6w7Q@o)M|8LEkWjk^1^sML_CL1v}Pyy6BSkq!E`b2q^7@@6*BDN=BvPr9FhB z=PG#H+x6B_6A?_2QLox#L3?V{VIL1b2}_1X`rL;P3Q&5WW`r zY73`vRVqEnX(veMJWj9VbVoE5`v)CBrVNcz`}7|i9LMr+dx+~J<5v__1668@aQtY9h=8~*S+rpDl-5P=e^dY-^RN4V1-A&W2o2zEE_ zFp|?t2Saz6=D0LLlwa7GB6EE)!YbpW>&qAb{soEK9Ey6$=DasWX)aKk@^vs7mX1fR zL2ipg)mf!dOIUkmT81!fcvQ&uC|g>b?&GNjSr^mqZG;eean@aDi?GRtWY-!psEMI5 zZ8le4=X81n_c|>t7>17%c)+{Z#Q~Q_Wx^>nh#XwI1DQpZGU(@vJDtAR2QIbt3x}@e zDjwV+Oz5wKdUEKMNmwy}JJnv+SMMvLXIZj-YA3902ZUd%yyiJ1 z{$`J)UXim3ZEW8G(OXoHDG{|u?=#kTy@Yy^On!Y*qvk92 z%96HpVeDW!gh+YS7(KK_12RTsvSoIM$i0(Exri`aqj+5Nj^`C>7}v&L|LaaBIbUtT zk+j&FrRzS_+!zHE`yt}XDD_M!^AR~sJR&a4LC`!Bk$6Tnt&3vqNc@4U)SO_W_nIp$ zC86|XlN|MM*nAH(V00hDi1a7^#>%-l!RRK5OAL?RIg+XN1b1bjSj|9kF;d?d;aer{ zB1DeYh7`klmZgCE6faXU0=LO;Wb;6N%G_OmKlw9a8$xQax%n8}Qxz;)$w$ZJHqp*V zQyX{8ra{Wj81jM7xZ9oViPw>1l=*Bh$ismI-Sz5|*?S)*F2|^UI|h4kX+iX^q=YO7 zI5OcIN)$N=0}EBQ4X?=d$eih^Ph8JI(*C$fuY)5^#D!^^{0>UR+jXQ^pJH)uFODeW zKysK*6Ei|G=uwEb!BQH2Ln?}4%>vpOy^|$(559WhK!w&geVFU~G(s((>hjfHO1x+M zZ+D^QZ@{Ngg?q5JE6yIV`M3hgt90+yN$+|9C^9*7-aB<*@ie;sKqMYhsnV)g%#Mcw zi{A1IlN8dpVl$^waIYhpyGE#27{|nkc{C8pE^Vt$b`7$pYMgL+6+MRIUO05$&a!2f z$F4=;>rV1LO>`|gyrb;jbb8~OgKze8knb0BG)@Mv-QhogFFEmV9PPOy$J`$VF+S2G zZS?R*iBe#$SO{8*4QGfHTH069p=+lvweX2?p+cw3P((#sL}R5VDhM4G_IUQWDn&6B zew8>_x>CsC{FOTCE{>uLbIKbh3k8**4?E=OT;c`_@dt5Ifcux_`=c#C4 zrbGy`l$jTKr@bPq?upP9qM+-Carp=Y+lQi7SGejVCE*Wo(hdf}KLm1%gtM3+%%LKM<@=V)uh= zizFWm!tF1$`k{nt@Z8=am~;F5w|2ad8;0&4hn|2FsbG+$b^qlb?Vt#YmIKTO*G3e5 zuk+t1tB(EZl|98>XWUR_OUBD7?B3F9t3uM`ulQPcx5gIH*llzJ3*GXAtlR>sl2Di%MF12tIEzItSm>-JQ$u6oB zI~vX7gFa!nHZ#(A7llbv7(>w@$M}$7(L+6Bk8>3H<}FmDQ*no7_{yJ;QNQ{8q0;TZ z)EtGY@W+~jevyHQkyIVnrD2SmtvSShfnHyDF7oZ?@fdn%(lS0FE&i**1NC`ZQ7@j*F(*;Jhc7V8Y3l0(v$3 z`Fd?L&?K`H)(OM4Ct^A7lRB9}XQH)z;78Q$d_1NhJyt7|HFmr2O8HP&AyY?SR=fF? z^y2du{xd~xS=ZS4qfZA@Ys`p14*X5tL?@}|+d5(qQ88g;eVF`*1NKzd&PS~aSjv)L zdj6DC-2sVuQ5bkQQ4tdh42Rmv9%qtDV+IWE>IWpmIQf5*`BC-hlHaft76j}T-MgXiF>CKy@g*$0RY)&>|zUa zL_`xU3J6>t2q!+!n@0v>omBae;naj8>xl(iK=mS zBBs9ttL89(=o0Zw#Hi;`(ccBx}_$7tZpyY!#1Sn3S=t_G}b94@G&!8; z2se4BaP#}pZ{mmfi;^cl0nnMR)?;c1>(0nDiibSMIx8uNdg%!U$j3Mh3H?OZYfRP^ z7Tu{E41HQ6yr_+VXZUmv!>l?L!W#Ft88Ec? zhf%2cdvq($+_IBBt@zxV5l`y=m%k}^ryo`l5?WI}h_^VPL`s1}q8vvD7BxXWTK1O1 z>Y|O%sqCNs&t1&Ko3|!biaUgxs6_R|HBqaU@KH(DZVZn|3?~_nhK)g)Ybw;dDypJz zF^dEgV2@7F<0rMdNfQV{uCV@jkwC8w^2k-Q6jg**<7BiR!vNA#-3PUzi;a&`5u@b9 z=guE3q1L~Uk2tbWJkdgSZaRKklf76;gOKS8J9?8)sB68di%w_AiKw=F4>XjAjJaVL zD^tZKEV7nBc3<$Jx7ERjrJUSRaaVNf#lPRPA^x~^kKoS#0Sw>rI#5ggT@+J0q&j8v zZ1JA$Q#bjSvxDCuCPp(ei|UHW>eFKDJrg+%hsuQV2EE<@Pvg;DrN-G%D1O#^LUdr~ zIXWt+tuWNv5WG0ZXmi|zcRc7Dbl{!cCIu=&SF}gVSN9s+Ye~Kg!U#nzjTj6~+#saO z+SZ(Y+5G4Unf)fxT-NPmHZ3@UJN<(C4P%!$1jRAsqf0btx5OVWfp7i5Ep8EtIvxnD zH5KCc?JrXdt&Jxl2|U&_a)Q>& zdD*$C!19E1mCIDa1I{pF!ny-eJ)n5pQueUc?p;Em3N?}cyKEfthge$Jdc^p@$PB^ z9Q+4BQ6?TA;E$&weE?IQLARN?i?Tt20jCWm9^qt2Eb>Z%Y=DAm!@XVf+jB10q)=`* zFRcicYlK_W-EQ(RmA&-G*&G$(Sy-!NBX6`3+cPJ2{wa}B_H>+}6n5cskHr>2j2TBw_OnncO9@SI8_)+l~1`{LKmcQ3jmmX!CxYNbs?cR7XqTF0dj?;4&V**Ra7gMUi7oZCIK4&B)F|J85R1g znsm`)5-f~<208Gu5@clGXByrB+q-*^s67HO3FIXs^|$nkd~vO?@07hUx6F5(T*$<* zg~2$Sp1NM+v$Yo6B3nXcn=id^3&va>t}V=FReBV}q~h{r%y$$2-l%*c5K;op|EoPi zX(WEH6d0NNP^!9TUunD`<^o%fTYBJ22AL<{BEjWIzvb%)Qde&v;d5Gl?IrZ`3-Mry zEj__!<~DY>h@Egd2kbJM_hzwWqqcAe7itO2|Fvc}J|H6bv1&xr1V`#vJ1^YL210~) zMou_(CDoAOVT&GFvo6?n38nTXR{U1|hz-TIsJM-8`S7m9bH+?|x`^7dX}(hSU{*on zBKt}*(eZ#+Za`t?Y{XEG@h-t?8LiS5FW2gabCHw5Yx-`AB3TY&qVm8?dH(4LIXCzM z*j2IuGK{&SnLKWqJ(by_!lzg-C_6}-*^ld2A)pTs7}3)tLf<^sekdN}=`JPHAnR$h zQ!kQedD(b5Eg6`(`@&baXk(ms_Q-X6UdaM-a0RT!Ny*d)q)~EXTCg9Tyb*I8rczv0 zOpW*RN+Hn%;b?YyjWG#YP_6`iuOnBU1?aaU*fwH~_B*nYfgu>~A_$I=j3nb>wC(p( zQ}#FAW)!&8@?6eJLwIi^NnFmebL{QUwbEwo)J<0ZUkyx4E8Y^yy``3-m_kvWqbeab zzH@coo4u>3CknF%@#1i6sEDX@g>%%(`1D2`a5Bgja^&(~hF;+gRi&4`e5uy3HzQQ7KVmmic%lA9ncG#%MhxX_u8ztV*KfO{UOk&^OKBDj}kE3jjPnNIOCGEwGbOMBhB z{lf9NBTh^DJ0854T|P~&70@mkMGr4Srp4!+cu(}h9KWOM~B73o$*<>xHW-R zjqggFbkgWEHQ)|yHwsj~i%hhS%8L#2hnn)@MQq_=H7|hYny0M1AG-Jl6Oy?ONhFu3 zCz75+zhq4~sb7f2HzNyi|COqLd_Fzcmi7qfvDt?K?ezc2$|D#><89HMA2UU3#P>}{ z?tr&y&gaIU0=r%$UX2v~7nV7s?eY>R&EaDG)X>_j+8^?$+}=|yX@f=DSm$Jw)1jM~ zPZcMIp?DaxZV7D2X!C?)?GN|3mpqnHEV|Md!O^%m#_gRbzc$O|NKZQetY*QY>VVP?;R_6lOHW-`88p(4*#R4pdTn z#=-(cTVWXWpBi5$i|as<5^cjzaN_&c>R8Z#s*g`30ujuDXLOK`jdFsS&rHHXA`ugX zOyt_Bv~)fSYUMZ*rjNw^#?}mQpj)5zi90ID!Ho=QjFe$2W&2?#gn$2Fc0{k7p-d!$=`*ArJq^?zHMOc%J;F+^lYN%pGm5cRlLYqvD z&GMQ-5U1?6TkPM-K-ihcJ`^(-AA_-I`xLkt)#)YatbmZ!>H*byXi!TtlhJzN=Jk@=b{Qc_7Yh}`!OE6zDae>bD~5jGUc;4|_;O)h%8$=SDZS-aWpUL`KIjm>X>QFMc2 zT6?eu85ynZUSYFOp<1y>>qx5sS!e)?AXDs#TvW(JuSf>5fsFHliQj$cNq{-65D^2% zMNUuklNx5*y@LEPS6;X8k)({hcmR3yv7q{oHp{ z1lpfaz#0DXtaiv=sDe5_ddpy=T84%sff2TeM2(5e2Qzin4TuXe<(bORSwJXcL9?h@ z7Q#hw_K+m)^znvt)TbL{!y^f`+NS~p>=igBxsg3y^-)uRX*7?0Zpa0#&?#5oYaZWI zyvQ?QoR-Q1W!m)J6QMjJdX!L%(qP}f;tjW~`fIst4E()#$ENscdYfUczd`RL*SmeR z|9hH$573za!dsA-`y-mG%qzhu%3*6#vJL3{5c{_^Ca2{!nFN-rM~`o#x(Coo7Z;Kk z%TfNmkN*MoSPgJ{$j%rLO`%!(T{P7z*ZF3try$|;dZpwiw+LAvpGI6!aCY{YxZv1t zdP?_R`d!*W2lW>uZTFr#9MSKvMe~?v{pjZ|)w@A>xlqz#07~>T%UDe5J?;6pT|yvM zto41d#@0~g2Va2}!*H2y#SE`DYXZfHUvaX=T_ij{t^bSY3?GIIO~Lo_La07g>&XR8 zyx=I9!hZ$h2$&7_$r8Or8cdZ#cKp|#{bd^!jp>tx@bw$n8ze>qQLjgb+c{=Jb@X5Q z<2)6#_YNGJ!?T%duX|z&}A_i+wC(6c6?ZR)p~|`~jrV z{p&Gs&nftO#}~ya$)X3X1}b!bNKmd_;=6t($IWRuu@S*lp6qtOAZ)bK%GV$>kArLV zpXS6BaEG&IVi(d*7lHy?r>AUVEX|j5-WcFMJ}Sj?3>&P&vK^~$Gj*cLNt^n75kfYW zk6dhKUH8J3VM{il;xx%zJE47O#CUM`w#;2bKa~roSITcuvZ-|sYHv~M)`o9A;yb2q zD+%(%`pSoGV+6}NE|*R2pj&Bs5L^2bF%#TCz;U;gsqQOfi(8n~CBzIVbpU(NM9$Fu zO=VuB_q^X!GHGLjl-4@SMF9)MwK}clJLMt?30D!nluA?Lzb-x>guQod=6xZh#1p49 zIDCd;swB2c#AT}&WE`sTV3dtFrr%Fwu${xM_c@BY3+tjmhXYD)4LTP7SXqs3^lq?l zT78kCdnj#mQ_N8FaK+dMkuveZ>03u5h%ul<-zHgZN{TyPd=BmDk`uvU$dlazAESc1 zgszU()8HrBJ+{x6Xh<UF2hxip24G+45pu@L|?0dlJUn#N$Xi+du6Z(z3$$N8A@5 z;eRPdu+MLYMB$&t6I2ViaNnx;UQU_t^YMw-2gQuLk-YhazGjBR#-5|jQY9Nh->`1Z zJiYzVV*{%udU`0(s0hw}^4@@8tdm5X{KsvzTpHO?QBe1U?iKW?-PBL0HwN zVxwM4qr18;rYKB&1d(ap_ni0ZdYqZorMfi7xVEh6M<%!Vh=#0Sl+!|?uYlWs0NxQ* zA5 z{FK|$ZXH&`o#n<7kd2Rej60gfVJ6>Ea+Vm8eazz(u|5~e#JxCJ=!Uv$BP8qMqz2mD zeJ+@QU4WUgS)?4Wm-&)sN=mXaI8h7y7+anc)!nnFkEHGp7ooS|mP=5-)ZSrWj?!Dh zHP1YOf+B3JT9?kqdwj!_!N0eQQ3HB!c$Eq9%1ZRn#47%@?JX|$Xb$MMmK2SfK+_wE znmp7Z6`C$oso@5O&9P%5lAJ32tM1LFX1WfmJQ)pym1rxsc0BM&lwPVF6Ya&2-jc7z zSwa%^wJGOm11|KQ3XaDd$}n^hHpRJkP!trmpd8gw+G{0B`8dpZ>jl2b=7^D0p(uCv zS*`U&LlLL4wOC1_1~V(qi9cLVAnW&CY@;9_n<~aRH$vUU770gRH|4nOX;slQnmO@e z@+a@I-nT;gRJ$>Pf$t5;GhaNeg)|E5-j8gVV^?A9U26c#GzD!roNLs2)keYatoMxc zS}KrIh4vGQgNfLypLfqN{Blts{6pQ~0BC0uCo5AuFj*2>uOve4*jg-!V<#$RWmLQ* z)(*A+k=WR0BwR0g7X2WQGWKP~@wv2CCyuy_>UIfrgFYDYfE3i2u&tjJ-|dE{1XSzf z)d8jOYiJ^yLyzBCZk)Q-b@CK@Y-SWb8vQJfiFYuVtp*pow=> zl()lkSxX5bLjB2GY{jQy&h4^V_y2MJQEMvG<6`CcfhA7OJlh6ZY^+Nd4Q6)YPz-OQ zo|5&LA0uU|kyc>`jOO3sg|)%v>#*x%b$X8rjIf};LTY)e zhl-J4(}I(DTbM0|^PJ#Yjt8KgQ@XhMXxD zZ?@EqhI6MnquES2yV60yStqy2ea)pJZwv)~d&4t%?@?`e5vTXV%j#01#zQ*mME_oL zxxTw1m*dL$CPqGl(KpHdtoMuvV~_y2cw#M^qFspo;%XH`KZ!H1i8k4k`%$6f#SVS($ZSGlBP>VIfcA3Ck$KTNZnG_$TIT@jwO9sCJXQ!Q zJ;Y{w$C>oNrtM<-C%Z1@`O(@sU|!<4Z1&e9pbKvfLX(1KsaL(7LAd-TwnBIf7gv=j zQXo~NhjhSTPQk@wq5uEg%K!6lA0of_{t`^m6kn8j^O`z4n;Hb~7|B1?@5Z;XYA(fs zI0Jk-bh*@-b)PbKMCX28#N*`zQVf3d6!K%P#>=uMr*rvqo2SX9p;J7dZ=C=A>u!SFEdI6~op zJ~e?@(h~wXH6-h+1KcO;nUutud14PtB6bp5J5`fc7dt()5Is3nGCLt?))E~8 z3vm7|)_p&saKKqfL$`Yav!1_=0BhZ3xhOU=y|L<*9D_xed$)^hPtitGT*Ei2P#nMR zvI`!;pfk6*<5d$rz4Y&TQLVpv%cymrm-Z>qJX?%w1~dQQmHIZGO0h$ixY` zar_1?AO)64PP*ewPlg#ptSZDN)_C$wk1WbtWH&6PZXp)lFUUL0qcOg`XV0}p;PrEp zW8tfrc^}Ubk-GGR`Cs}md7=jQC5EV89&stYl3g%I|IwgyW6mxp8xpz9`(mTGA=z>b)myyh0T+<7uWHnx zOiMemaOibBu91(Z)i;{&OP_lrggN-kp0c$q2Y*a1nELESc7bEolIv(v%ZfHDzw2hC z=|(+wTG`5=ZoK?{7Pc|=HjW~--Bs#6Fz8W;YG3c*)xY7cfGc^4_c?CJ${?{riQ#E* z89#=ix~qp#Zp>LfL?DXCCDLs};*vmjFcroFyOAO?ioc-}Lrol_B+_o-#n+4k?`HPO z4MG*P_XcpV*&jC=$sHUTylag6Ql&<`%*&zO`(*+n#u&iu!zR_;bFrM;ZRY z^`DL`L(r1nM2vS1#fKMwZ%A(PE<<7~3uB%YsS~b#q_qooI??@VW~)Qr8PnL@Z->CI z$>j=ErFy}eJz_Xi-PLI|P=*C`uG(t-hQ}-Y3{UuFMIW4EZ+zf^FyE5whLpUfxf0Hq zp3O0fxg5mp0!lG5VZ{(Zjq^27b?Zt4euq3&< zeUeOQHX&)*rsUeDSnc^j;0l%obv}*fGZkU# z6dI*+IM7c`zqq~q+Y<(Hyjwer+T9+cD z5uTwcXkhX-`R5wHG47Oa(sNLT{BAFckv}Rc_sELCR93EojxD^{CRAyS@Fe5jY}$$F z;RTMAS?FK~iEi7IrdaS$+PxaZZnB=iZC4`xG+foW9#1#WM7jIY3y6O&fu-fV_Zu5F|XI3!poF!d@!_B>+=Jz-%nJp z@C%7hL(G0(D(bl@s{ArEtxZEd&ARHyJTROEHn-f@a`5+a->2OST!!!c_S!EjoR5ySn21`|r^HQNtIc`%NUr5wW40$3+jpV+yu^&g< z`8=z(uN#1vytGzrHgy3U0_meTkHbE+#4WqNrqWdm($j9!UZ)()1vVEhD>}ZvXS|>2rK+*V1LQtyYHrKjQB!ys(v|FHIPgqGy$04 z5zipWMu?`YOD}H2&+Ic~>jIYbsdU-+|7(2EnE%hmR$n}m!FaU?dQ!l&KL!AOD5!R!}R3j z%k?c7Hx7&hEv`|nyPvu7K=Ltl)n(d!%54L1yEx4WJ)Vr`oCM}))$t~h(dn}xx~i+9 xhqjBYjl7j!=4-;x^v6Cu$qBdB3M2>gA?Q!CFt%+}=TMxrucQ57*zA9+{{!**=8ymY literal 0 HcmV?d00001 diff --git a/extra/haxelib_src/www/img/logo_small.png b/extra/haxelib_src/www/img/logo_small.png new file mode 100644 index 0000000000000000000000000000000000000000..d37340a413301fbb0c205c79e330aa3095c56262 GIT binary patch literal 665 zcmV;K0%rY*P)@t=X$pV*6v`@m&uJE!ZOQ1gUUpT~@4kuAmv9WVfANUUc_ z!b?fQJ)F)Wyy?N`tsPD4Msg*rd9Q08O(ReNz#2j8aLoMek%3J7OO1I=z zbjWz|KMHVQw1-(nxAmAi zz=#9Jtr^|0!lvwt7O}1HoCdBrV9IL#2z~z#M9VNhyaC*Gz*+lKDJ^6dIsgN@gD#9a z46Nn{cDIf0g+ccm6L6Ns*r3@9pqnn!b(yn<%uulvDcR%gNFcVF-+2oIXzH-KL+g@h z!@Vc)5aV-nQZ1_L6O5adF=b6TZcV|O0=>6Iybj>5aOC|gV(ET#PCm9HD00000NkvXXu0mjf@OL4) literal 0 HcmV?d00001 diff --git a/extra/haxelib_src/www/robots.txt b/extra/haxelib_src/www/robots.txt new file mode 100644 index 00000000..27a4026c --- /dev/null +++ b/extra/haxelib_src/www/robots.txt @@ -0,0 +1,7 @@ +User-agent: * +Disallow: /api/ +Disallow: /bower_components/ +Disallow: /files/ +Disallow: /tmp/ +Disallow: /p/*/*/files/ +Disallow: /p/*/*/download/ diff --git a/extra/haxelib_src/www/view/documentation/documentationPage.html b/extra/haxelib_src/www/view/documentation/documentationPage.html new file mode 100644 index 00000000..05f6bb1a --- /dev/null +++ b/extra/haxelib_src/www/view/documentation/documentationPage.html @@ -0,0 +1,13 @@ +
+
+
Menu
+ +
+
+ @content +
+
diff --git a/extra/haxelib_src/www/view/home/homepage.html b/extra/haxelib_src/www/view/home/homepage.html new file mode 100644 index 00000000..0c00c4f3 --- /dev/null +++ b/extra/haxelib_src/www/view/home/homepage.html @@ -0,0 +1,58 @@ +
+
+
+

+ + Haxelib +

+

+ Haxelib is the easiest way to find libraries and code for your Haxe project - and the best place you can share your code with others in the Haxe ecosystem. + Haxelib is the package manager for the Haxe Toolkit. +

+
@exampleCode
+ +
+
+
+
+
+
+
+

Popular Tags

+ +
+ +
+

Recently Updated

+
+ @for( update in latestProjects ) { +

+ @update.p.name: @update.p.description +
@update.v.name: @update.v.comments +

+ } +
+
+
+
+
diff --git a/extra/haxelib_src/www/view/home/projectList.html b/extra/haxelib_src/www/view/home/projectList.html new file mode 100644 index 00000000..9121cbcd --- /dev/null +++ b/extra/haxelib_src/www/view/home/projectList.html @@ -0,0 +1,26 @@ +

@title

+

@description

+ + + + + + + + + + + + @for (p in projects) { + + + + + + + } + +
ProjectDescriptionVersionDownloads
+ @p.name +
@@@p.author +
@p.description@p.version@p.downloads
diff --git a/extra/haxelib_src/www/view/home/search.html b/extra/haxelib_src/www/view/home/search.html new file mode 100644 index 00000000..c7a5a78f --- /dev/null +++ b/extra/haxelib_src/www/view/home/search.html @@ -0,0 +1,48 @@ +

@title

+ +

@description

+ +
+
+ + + + +
+
+ +@if (projects!=null && projects.length>0) { + + + + + + + + + + + @for (p in projects) { + + + + + + + } + +
ProjectDescriptionVersionDownloads
+ @p.name +
(By @@@p.author) +
@p.description@p.version@p.downloads
+} +else if (projects!=null && projects.length==0) { +

No search results found.

+} + +

+ + Not found what you are looking for? + Search Haxelib for "@searchTerm" using Google instead. + +

diff --git a/extra/haxelib_src/www/view/home/tagList.html b/extra/haxelib_src/www/view/home/tagList.html new file mode 100644 index 00000000..94a06a4a --- /dev/null +++ b/extra/haxelib_src/www/view/home/tagList.html @@ -0,0 +1,30 @@ +

@title

+

@description

+ +
+
+ + + + + + + + + @for (t in tags) { + + + + + } + +
TagProjects
@t.tag@t.count
+
+
+
+ @for (t in tagCloud) { + @t.tag + } +
+
+
diff --git a/extra/haxelib_src/www/view/layout.html b/extra/haxelib_src/www/view/layout.html new file mode 100644 index 00000000..ac147492 --- /dev/null +++ b/extra/haxelib_src/www/view/layout.html @@ -0,0 +1,167 @@ + + + + + + + @title + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ @if( useWrapper ) { +
+
+ @viewContent +
+
+ } + else { + @viewContent + } +
+ + + + + + + + + + + diff --git a/extra/haxelib_src/www/view/project/docs.html b/extra/haxelib_src/www/view/project/docs.html new file mode 100644 index 00000000..5ac96fa3 --- /dev/null +++ b/extra/haxelib_src/www/view/project/docs.html @@ -0,0 +1,2 @@ +

Api Docs coming soon.

+

Hopefully using the New Dox Template.

\ No newline at end of file diff --git a/extra/haxelib_src/www/view/project/file.html b/extra/haxelib_src/www/view/project/file.html new file mode 100644 index 00000000..dff775a1 --- /dev/null +++ b/extra/haxelib_src/www/view/project/file.html @@ -0,0 +1,73 @@ +

@project @version

+

@info.desc

+ +
+
+
+ @if( type=="text" && extension=="hx" ) { View API Docs } + @if( type!="directory" ) { Download } +
+ + +
+ View Project +
+ +
+ @if ( type=="directory" ) { + + +
+ @for (dir in dirListing) { @dir/ } + @for (file in fileListing) { @file } +
+ } + else if ( type=="text" ) { + +
@fileContent
+ + + } + else if ( type=="markdown" ) { +
+ @fileContent +
+ } + else if ( type=="img" ) { + +
+ Viewing image @filename... sorry we don't have a better description +
+ } + else { + + + } +
diff --git a/extra/haxelib_src/www/view/project/version.html b/extra/haxelib_src/www/view/project/version.html new file mode 100644 index 00000000..323b994e --- /dev/null +++ b/extra/haxelib_src/www/view/project/version.html @@ -0,0 +1,96 @@ + + + + +
+
+ + +

@project @version

+

@info.desc

+

Released @versionDate.

+ + +

+
+

To install, run:

+
haxelib install @project @version
+

See using Haxelib in Haxelib documentation for more information.

+
+ + + + + +

+ @if( version!=info.curversion ) { +

This is not the latest stable version of @project. See version @info.curversion for the latest version.

+ } + +
+
+ + +
+ + + + + + + + + + + + + +
Maintainer@info.owner
Website@info.website
Current version@info.curversion
StatisticsInstalled @info.downloads times
License@info.license
Tags + @{var i = 0;} + @for( t in info.tags ) { + @{i++;} + @t@if( i +
+
+ +
+
+ +
+ +@if (readme!="") { +
+
+

README.md

+
+
+ @readme +
+
+} + + diff --git a/extra/haxelib_src/www/view/project/versionList.html b/extra/haxelib_src/www/view/project/versionList.html new file mode 100644 index 00000000..acb272f7 --- /dev/null +++ b/extra/haxelib_src/www/view/project/versionList.html @@ -0,0 +1,41 @@ +
+

@project All Versions

+

@info.desc

+ +

+

@info.website

+
+ + + + + + + + + + + + @for (v in allVersions) { + + + + + + + + + + + + + + } + +
VersionRelease NotesInstallDownloads
+ @v.name +
@v.date.substr(0,10) +
@v.commentshaxelib install @project @v.name@v.downloads
diff --git a/extra/haxelib_src/www/view/user/list.html b/extra/haxelib_src/www/view/user/list.html new file mode 100644 index 00000000..2d0cdf1e --- /dev/null +++ b/extra/haxelib_src/www/view/user/list.html @@ -0,0 +1,28 @@ +

@title

+ + + + + + + + + + @for (u in list) { + + + + + + + } + +
UserProjects
Avatar of @u.user.name@u.user.name@u.user.fullname +

+ @{i = 0;} + @for (p in u.projects) { + @{i++;} + @p.name@if(i +

\ No newline at end of file diff --git a/extra/haxelib_src/www/view/user/profile.html b/extra/haxelib_src/www/view/user/profile.html new file mode 100644 index 00000000..72ac08bb --- /dev/null +++ b/extra/haxelib_src/www/view/user/profile.html @@ -0,0 +1,33 @@ + + +

Projects

+ +
+
+ + + + + + + + @for( p in projects ) { + + + + + + } +
ProjectDownloads
@p.name@p.description@p.downloads
+
+
diff --git a/extra/images/Banner.bmp b/extra/images/Banner.bmp index e81d610c61a2a78760cb20521c69e7ae8ca90aca..f5b77517a95ee1fca20142df697d991314a7df7b 100644 GIT binary patch literal 25820 zcmeHQd2~}%8pl8UYtES?k}hfTlDwBfTPSM*#nEw;5eH>)aH)z2w8ae=WEqA{D0UE( zMX0n?6sCY>k&!8j3tNR28AXulQJ7J5KsH%Qlcq_NRPB5(H}}i!y~!g@GR_Hv^ZL&3 zefN9!y?1}_{_b~|7w#T>qM)7cUtic~!e1%;^@G0~+NHw2UAy&=e)F%$pU(h0y-t_d z;<^NGyph~~zuvtGxK#t>0htJ_ zR$|Fe6aqRSkY!@&Xt5BGZZ>nkN-b8Ci6kiqB*||PfJ`k26lw_zm`p7#B=5vNeoG+1 zVf;5GH~QmrSTt^MyI95f>ovwHRjxX zmcbv&1FGbE_FL|*G-l;$>6<|@J}}QTx!N@4fN5flX>7HrpxQj5#@KbZ)>-ji(*L`s zqxBHA6oEJiB~Cdhd(Y_0yvDU2skF&7-({KBC_mSrjIdjNzq7}0o+WpUTAI_lpK)lR z>BZCLc}~l$MtPD$ex^YgX;&VzS#xcs>}lX1L`yLor2wa#uxlTfauSD0Q9>!eu6?G4 zmZF3r2xDGJ3`YZsN5xP}FvAg5>ci$tIgIQrv1~qQSmrjab{pRE7&dtf8$HG~ZmFcn z^pex^mqzoj_YE0;Bsm)g&M;3rVVUgXZIq9EPbEghbl3&yh2QgBdHM~{YicJM4KDFMsUB}zcr82j9 zo(ndh(Ol$GhTD`!1sZ|Xk#_6gdMWGqp!cxrgAZDme+O!6Shvb8TbRU_T|0LIW2^=6 zqYppKo&tFFn{To{b#-;8PMu;cfPZ`2ZFm;E;9M#k!W%to$Pm#U%7VGY97Lz3)~{-n zuY%M=gGykNO5jT_^8(+d(&z*^d|wqW3p)l!bb-Me-{CjIZclRX8n%jIf1M!-0enctejpMLu3^5x4HFJ8RV`rnnhy05#f z#8w0n2^IFHVnU#EF<8 zEbHMsj~_e6S!PY2j{Y2n=g*zPBo?G4C1GsD+GB+&hv8_c7?-L`q4cTp;d;YTw*h*F zE8S`X2ofq#$6D0dILE0fDs&D<*v&c115-|PDHKlMb6Q%ydUasRDJyI7!i8)ZLrg;o z=AOImV(lPhkOWG*XZLQ_4mAe`OFQA{s4N%0@B-_=VW^Yrl2MLBZ1k`LZVsbsk6LQd z>&eXr0PWFhX{j2+MgKOKrp*NcjitUIhHC>ukqNbNwo`e+W*t_amg--t8}v@NdU*Q# z?;%FnT3HDjfNxKnV2c^+A!G$X2_|_x9#Ra@t3V?FLwyuD>Jx9EU&t_#;$B zV3OTHR^i2A^N%@>(OP}eYyUP+_eG&>5EF_(Vh0*ubeej-sQpYFhir+8nB@@qc&r1_ zK{zd0Wj?HQ`uXRd(Z71%KDf~5wY6w*Ih|5! zDi~QUC8fLQl~>S>fKw+=k|Yf+NHN7s+!R!hjtq%s^bKse!~fdM%AQE=~XDgnqwA zx5=Bl%}3*&=Cn1QkTkLc0*$cEfKG;8%A6AFrR3@%Cx9zTO4yR->LKL0p`wCyKnxvA z@rqEKP}$H2!1it1zWMrV*7C@M58{a&higIPiwXUS@o@+=?(ph>Mra$k+6X}mArSNvY9Q2tStBX+l0upv~%rI z%Xc1V43oD~4hfAQs()idH57qB<20u{&SAZ`Udk8)&vaES)gCY9v=lOgFGkOvIm4AG z^eQ2V)6y}cM{{nkE?x}dD=^AZf8`3B^!K;lhSS?LUJ7pqoC2E|plbE;XT?d6-JTAfdWK3`BY!-~e-&Tn?nK_@}XBIeVzX!_25G zcj@R4qtjCBfrDw)Ufssl9QtTX0vdNW8{Tk3heMw0RHIOlK*A(x5<86z`ZO@h12p0` zXVxs%ZSwQaV-f(IYGr+3={f5I7;8Ja&7D2_p9c@JZe&6V9iSb?)T+IEiKN4b9vZbl z(cHP1Rm_2{o@5!BmS)r(NqLuP41ql#fhqs+ro7`#*{aegm7K9mZLmJ&NY8hqk8vpD z9P-50wGo=cyavg~A(n2C&+u`HJ_WcYDy+|)!uaUEBMzKKv=mBXH7P57q`*Z>KvZco zix$zDwbVC6^IDj<9rQPbTfHfj-jprsmR#voE8#A0hpj*8#uw=gQfjw;Npm*qS2am5 zyI`%9^;t)Ho+JG!hce!w*3aoqd8{L`o+e@cuW4?-`;uyBNIBHf zQaX<>&OOPmALy{@a)%w4JM5}&zqjtDeRUo7oYPHOn5uLNwN^j5|B%%6`+t4-%1s|# z>G1xQq>9V>;)~`v7mPXTdek6V8hWihYH3*OOHoTHz)wfR`P@n4=SqIbWu>fyl9v?5 z6DWt*&s%%#Jt>{Hxb~jx`gtO|ojfaQDFSh=zNn?RI4Z(#NMrupQ(M;Rqn2`=eJBv| z$Do3IeUD!`A;7Pk5YT!2HjSW)f*HiZfeC#Yj^g5||I0U|=@E7IF;Ybd6+sYrq+NTBBrzYb6pg=D73TVRu7sAxzn0Q9 zCH?yJxw@#*#ZefJ2GP>!zQ+$}sj$!#S69dWw@vUzN)c!boQfZl(zq0-_)$v{1l2%N z;Fu&XM#Urz0GAl0&e|omxGsT&md5`p+}uoF!3eb!)s;#p2B?AYQu-@=zrb(qg*9;6 zrVsO}sA>eLfuYoJL^X8xUqdj(BvfetCt|R^G_Hl{8o2p{md3x9(zS^(*V1r)d@qNN xmqz)!`e98%wdn_=!U$0DbF_e#3cnns5vj6bNVFhAizFrHp5nhAs{d2Te*rR%cdq~d literal 26682 zcmeI4e{dA#8OP855S0P~S{0NeOzm{0)4%qQj`c6BGU|*t!&r-s9cy5AI>T6{t#vvm zU?PGrPMww?T}B2GG?Y$pIuuASFc29qVIx8S10k3gAV~A$ekVD&+kSSR{4j@Y~gN{5pn?U&pWGx0@RH4g3Z>27Uv-eL54r ziQmL;;xO^^3Rw6p{1$!-zh%i~*=k%!W34;}+N26znc7~pZ}0FMD40}uumG&s3K5seHg80;9} zF~H-{1|9=E26znc7~rv~G{9qk#{iE39s@iMy$(xuWNb9{Km0c3;4#5tg2x1p2_B~# zfX4)n2_6$XCU~5#0Ui@PCU{JMm|WE9E}YDyp-CkZhY22Dyzzs_1dj z;lc$mIy*bX2nK^K@Z1?t+ zS6=zXd-(9U;I-4zBS(%9@|iPdhC(5dZQ;U&>^}G0bCCAL6Hj2znlGtE(d+@x$=;?c0|uS%UrOqmS0s)*e257+ZE98z_qwEgBvn{l-zcv{dP&l2BzR zEma202v%k6-o0A_UsF>1NyxFs7W5Zi-Z!d?A9z80DWc%{VFUtvK zclq+=U0q$rj~{0niA2=3hP81WYbkm7K(<0oG7`?1F#}pY{P4pC3l?C^nKMUq*Oe<* z3S*Bv@C;IzsV^Snm&}v`hpLJD6ZrPfwA3rABD@6k%$YN63H+{IyCm=*fBZ4& z#57WNNy0C`{Ia{dTXtp3EK~?NaNvM=7$h;~&YeqTnuxQktn9>z6P)nm$&;Kxwc?^e z-Eb7u>r6|92gw{#i@;BtHjQ{+ym%2xu_;V4*`<(X!VGc>OSEFx6zUixp-$>oR#wtP zY_+A~{Q2{xm0XmqpMesAtI$$KAfcs@8*A6D-MDdMI2`6~dsS7{JMX;1vXHrp6c&V3 zShsE+6BJk?SD_2f`t|Ecr*r4dVN>?+-`~>GLR(eD&)k)cz=fpC$klxsi9jIW)k)>? z8fsq3A)-h)Mf!*?frl38LS{)Y%BfSQlmV+0T2X;&oQJI#!Z3%Vj=L4jadJXw#U+GB zM3qYez}HfT!@|0F^DU9MVN^?OLiMfTPun7&wndxH$Am_us6L0%6SHY4+9d~bX(_?u5J{*clsx(G z(bmcDCMFww_blxx{!_H%`AEs{BPB1`uW4n$%KDJ3)_GJ-;pQ5|QZU5BLcX)B>+J*a zpBk|#D|+nLN@x34Ptl@S@k`P9|FXrI3z3Sgt*w%Z!*POoeauVY5CVlmQBm};x-)*~ zzb{VuAkqJ-NK9VWH)V0WWM0JP^M%OI{v7$FF~s){ATy)jTu~dpceO*>s-7ut_Y^OT z70-*7yuho!Bh3Drt;Sr4QIw1Na;k=dLbVhEWh5k`NF34K8H$aqOJ3&CMdqYUiM!X> ze3GB{FN)M0?og%uLdTlg;Ez_tr~I|2=(SjX0uS(}2rPLqGJCl_w89~mlTi^2zMR6O zOG}k<=Fw8AL*%Ffhs2T@Ci+Hn-*0aH{yA&X`vZBXICLAE5>%MHrtkjMk?O|YH3#~B z{CdRZ4bldL_cCwkOqRYGVdY6@fkQ5ejKiVaVc>HNqY3Kuq@}_k5hXX6kyM7FH-rY` zQ1MxjxZCJ0S{Tp8Sf+n&1P+<;&{^m*B)`mT{5*8>P|51h4H*wJINTA81R~ZC|8pse zoGR+Xs7Op%-7B+}q0%@fJBK2tLr4CtteH(q-3xj7&`M^#TFS&y@^E8w3mlI7B-@af z&fz^m;K1awXwl%=IQ2JS@{nsu9*UOIiF_@EpsSnHs7WbWYUg3t8r71@KP2As4<`eK zz#-E(^(mV})*@~#_2)E_VOPx|LlXlO9M%QH-wCB|2wHblxKm4aBTF+^a;zAq1}SWZ)2K zoD(UT6*}JB#kJs&S(My3m3gUrCVyV)gt{lPL122Wk}2- zp>6{6iYkNQyuU}fyMtuAtS#K@!@NjG#KD5Jl*q``6b@xbB(wyWyJpL}A~&|C(x#?l zpmz-P5}1p|7ZK9n@l#z4hFrpXpJqhRl=nks(^8py(kz#j$|3R)Ic43AxWOUcr-4Im zqK%IxC%-qa(q|cwUqZcPuIx!$a6BLR?d$*JAwC@PbqwK9?w8V!{QISF5eUFTUY4^T z6gib45jmCR1!0E6x8jMr{@FjR$vKJfQs?$SBMT1a&dpRk+-!f7qdQ|l!=(j7c6=kr zd(|AukO+qiiEv1;xfgnCjm_Z|NT{1Yv7zxbd)@f!vM?tk!{Lx@XZ|FEp>Q~osLJ_S z^J=MD?0ZEO4{1Ok(KpG%W5F&ay#?V zYsH~x>4lDtF?FelRmn-~uZqT^rSamj*tC~yEtT=m*V3$=)6r5mq^RkrGV*Jw%u88! zi9+;3FKAs$4K?QX5rAEm%<@o&tP(3eF%pcNAmBYrNUvx z`tYmH&YPpwZQC3U3!@PNd0OlcXm4MO{c1s!=`J0FX_Kri5O4td^HSkxfW!QZd5;Q* z?lnGxA*0qy-SHb+t^PbLC>vD<_S0A%<7Vk6M>^rqU*mg;z>{}g>J?S-Kp^u{@(>Pr z9whfmS>v~Lb>9@Weo&uE<5043Xj7a_0!2<|ho3IDZvvs)42k~z(hMeDc{p@Abqgtj zp**+f4u;+c_XeWY_-YS_mB|T%j*Up@8!ib|T8i;vbm~)~^Ivt5>T=JUi_(4QL?Frd zKqGKBox>s0=;n~D5DuHVgFHXv*;8f`ilPpdjX4Q~!&hxNUAH4H9CA4~hdzygfLeQ^ zlft2rP-SFHPzf8$Z7MUN`TXQbQrx|@Hi;$*eCNyqvts7m-2sdeIc6qF%G|O{*pn`;w z739cqy0nxJ?NE4C9FE^T7>6RNvi#3jM!3hobek^=XZ>EAKP19hx|Rx!ND4Ttx8Vb&}WZPo@|gc!eRrz4ZI_n1C#X`ztEDnQg+p## zLL(faZ*a)8Wnun5# zaEPplobK+3-(HoRxGQ;UO=`^k)aW|vmV@@|)_QAtV`@`dq_eA=doA2Dlfq(ezzpGs z&+X^JGma%D);kSNYjkaDT=k{fHz)31-BY|QUb>Nva`_KtghO9Qb8v_|znl^|ijq@B zBQa*YvWKmKKL~{=Rd6zFQmB(ra5|0p|BTe#L|RdwsSF8Ef1%?j0)ZitF_O0hX(<6i z)`UhxRkD#Ar^J{@Baeg}T6nT=Qx=W#Q*J_sa6)N?;cmsrQF8hV z1o9&Q^dJEE--&{YY+5RPdWfl*k&Qy5@MCMAQ)HJz6cWi>uxAbxSU+t`)Nj|=L)q{%~aI{ z6;%`_kv@qr-#8Uo@VE_*$`7GHg8Vp%7}84pMhf2@l~!&;>ZqSI8IIFYHSPa;z7v(J p`x3cahm>DZLM5ciNr}4J;#WmA5kvVgRQ(J?)lqE~0N)4%{tq(+x?=zU diff --git a/extra/images/Wizard.bmp b/extra/images/Wizard.bmp index 8bbd1799c33f877dd50da82f3ec5269c00e05cf3..60fa52ac53a93dcb1f0e57473d755da4a28e5ba1 100644 GIT binary patch literal 154544 zcmeI5dz2hSy~pGI_nxcVJa&_vncbb;Wb+^iM0v<7KnNh< zg)1UlPy_)5@$%3s2?&Thiu=s)VF&3S6y4()6+dW zDbBFxH&xYL-QRE5=T}|RGg)@v=A-^;ocG@z^#2U{|2F!6>3hbFd(XJZ6pb5qF4d3! z=W+i3egXZNGI64NIR%^oO{qXfTbnp91npC%h!P%@CQlYsJSeudiYh};kZlSrEuyg@ zXqz-iv}umOaHgtC>SNHb7;OPe;l>Fi-Cw7GQ=s`20J;%y0-ywx;DHG{5={zL(G0I2 zv2DDoU+>tnNdzgBjhNg5l)x_pHs|izI0c*nV^IO18vzDB0>FU>m=+qalgsowbuR$n z8Uquy}fsX)i-~o_g2yCcTBN(xH2CAa3 zWPyzu$a)4n$Z2C5s-jVi9HDsk)KZVu)Ya0(=yhdYJ` zQ@H`uhAM#C5GZ2Hl@ne9FL>bQ;X#{R>=bB91@fJT178N#8LAq@5yKH0s&MXxfD>Dl zxOupngEy!OD8Ybke5?#&^T07Y%L~Kx8H~Hv$ZN9)J=&09y=!4a{vY zSYsQmJa&jGl%y3Hh^?wv`qPLRXZj5Xab7NP3OEItOaY)9L3^@=amf}9b|ji?7!IJN z1%44)f~s6_l)xPo$Xlu=yJ+3%I0c*nP@tnw5HZk=Alae{kYa5ZJ;U-6tUSaPr^#r?E70CS)+*0ecRV|0-)kjqCL)S43c z0kJ_Wr+`zS$rJ#?5n$l+z`zXyZBV6wl?B-nGLtQ*^ZkI~yeh4dc&A(& zy0P}fjcc-t)}4-1z$pL)fNliIR>*;O5Ze&MnwbNG$<|xaqOsL}EK(9qM+Fw>hM3Tq z2OQlff!!`}3OEItOaY*q2Ot0sFy-SUK?$&92o%TS&`-f!Ze;~niRUUA6REhksqscB>cREf1rvMZv7mFg+FkBKqF+nbjql6=cmjFbD06z-pz*E@m0;hmepve?a3~w%&+mIH(w`rWPO`LU- z)Y0u2-ejZIosLt0D*%Qgz`*ALCU}M*tz{Mf4HMUd6isXX9A`f`_*j9OW6P&~REfo` z8y{qF=3>O-tuo)vjWJ9f3803v>#k<6^+7G7R zvWj;atHeeG8&%Q9;0~ zp_11E-LP^@U!v~dodQk)g91~*a0GJl1_B^3z#MZw1sMw>*}$B)QFxd1%Lm=EcYcIc zB^LT{F`=_2h&Ik}0k|rsfKy;hD*%QgsBvZvw%9!1!Wk87u5LgjIFB|cu?etMYC$4m zLqn*l0!eHnR-{@UjOk0%9lTS(DPT|l=;lE@m;))%_xKiv^;R0|~P64ODm{wp~XQw#+sR$SW6wGCn!i7XPN-!-{*oj6{ zjZ|0kWAFq;Yb7?@Gw(EENwh2)>6p$CTm{k{pc}!MzC_)@I|ZBq1_i)y1O}Lc35x0# zY{{4E2>~n7UF+r&)W}vEKFc<$%0g8ebi*&h1>mZj0#1Q3t-!Q$SsXtY&I6#p5Y&(A zifoc~;9;$RO&iqwP)#Kg)W~rP%d$#S5cI1s+R^-x?~-*1Q7Q4B>E<|Q8Q=tC1&Ys{ z*eHp%$uWFPk4<;*P5~PQz;GVeOwmCJ8>)jyHjlm-SZCtAWTt9UBg6R)qe~3OY^nl{ zZ2}8o!xT7Zb0xSoP64ODSX5woceglf703yBid6sbUVELlVZ(*zpMTC-XVHs-b2n^Q z|H)5ss( z1-#Z!d2jRr25i5Agkb>X>7q+LKw-erRwos)4!uiN_w}-8DxEUCI31pL_OM zes({3?m6Ca<2mP0%P(Da8L#@mz4!8+P|1o9f0#F>lJ_rO{M3_AYO4-8=%CQ9{`R-O zX#fw1eq8!5fBB2H!Kj4~+;?B7uMFPKkPJr<59X2^8l(hhL%ijuPnvUl(FMR; z(&i+^(#4B;)%NY%7tfzRf6kmaGiK0>V){$F{nkx4@y5^pgiM&$%ec;6g$dQC_0~f~TK) ziVG#YrZ(CkNgyR$_XYlYJ7PSZe(I^Bqc2`^3GanUDB+3*)Zd>I%{&?9+i_-b7kweY?l{6MHG;JI-3-L;#1 z<;!2DM4+vD^NlxX4`6Q;!=HTo@$cSw=l8$&J$l`F3#O5khzj8 zuPKp!!PCqxC+aB5Ykmx7hEw~y?zls1#HfWw9e#MIJG%AbThZ|U>tFxM%c+Fsd%-<*YoGj4Yh2Lw=<_s6-P1y0V4oV5R2+y3sGI`HDydPZvT}l z>4o6sU;Tb(%!!(V z1$Xj4zyE!3E1}q~)2D0aW?SyQ`^Fn?_}aDC(n}l6>gl09XwWS|jXVeqO@Z_a?!Yeu zSzc^fuY+Qm~f-xQt>)?z}g*BgSBhcgoLHHbbA%tmd7+g z|NQ4a^9`wlE-Kz$lq4S4doEfOwa+Ff*IJ|1R$EA$heV+1&Aacu8){4+Y|-6us8GA= z9@^W_UU(t2Rq*Ydx8ELWFWyFZ-QV9&)BbmK|Iz&dE$Z$uZ=QCC^)95jtLOp@=YgWS zobqXKA*;X^6-3O#>8yYG(n~M?;ukb_X!=dTFMj@W?NW*G8t@ds5AVM}=m^D>so(g+ zA3}xaoOz}=!O-SZC`zK%ON0BNdvm^d6vK~RyLREcc~ncUB?}jdU{61oJ9FmJMT?59 zt<-z0sWrqjD6edi=!TU-fo%S2$F=rzJz8`MiY#J2uIaF~xDIVQI5>!pGqh()6YS6? z+P5@D@jGeQPt>^HZPqNb*$D%!*JLY~;>jnT;A(5VrcbD~%O=6iqdxIOzyJH@o5A)X zrd4rXNS{n$D-lF_z2VF=_uFTmkLn^aAetMB z>avZZO*F&N2Kb7_a2jRW6;WZLSQo`e3Z@tqo^b53w1ydai6`_z=SYR2 zX7rXe4>b$E{q`-l@J&8{$|=D%i0KZO8q?FNe3R85|2Ue7fIhJ1&1l+o{dLz-1G-KA z@uQFO1~w)1$Z@Ez4Bm>**Qg^ENECno2o%g^8xv9_WE9@zgwu*ztT8xWOF;kpaS-N0 zVO1hKHFr^(Jef8$v`Kb?N+>CvNnThW1K7la3@#+sg;T&Okc$HJfSl+Tfr7cL;!Hq^ zhUyY2CjLl9acU)`pJXrJ9Hiw{`INA8w-Ji#3=2$wbTF4o%XR7$a0+Cg0MKm+Vo@DP z;n-0nl4Cab(r{jGuBxILUPn;#!(b&gC#c#W{mB4gS_P8W@C%-1a3Q%aoB~dPToj;( zoJGGXkSG8FcmPVMAP#mE%;i?9L}E~pt+o&dA>fTsk}%+BDod>R%o|IaU;(!Y zCAnN$uG6Mhpl$k+((+47OD!TMH5At6W9PowW%1a8}duM+l^yHi96oG=dtO5!Q0Z5_=rcEoZ zIjMNtVDW2}_Am8!ZtN?cyuEAvw(i4wyASE@UftWZW?R=Mw{@)@{Z&5n<5kmYq%TDQJ*SEcRx!NTo>g*yfd-ySSp@A=-baYy-cBYi)z zcU0fYt6w3lY3HZBiTi21jbZvJX(d%8(YqphU z=|6_c=!_;#tY1f^W7c;(Tq%5|QoPB3-CQZ$TJ^msd?#@>_I1*DKjxk8Bdo@I`LNeY z3(uG`$$S2`UN0i{KA&$t_cxI)lfQJulDT?+J$8Bi9u)xB(c1`RrI|T+O%KQkp;RCT zevMRDNa^Vzugfo13Rg?7h2ufr|I;7u#Q7U4?O*Qi*tEmrJjnvi9~qDbjRoB(E3IGO{br?bLxrrY4(*`bh;ObGZ>DXuspoR@{aR|fJgWgqxU#{++Zw(^)RhPB(e57?T^xUN+h zJ8esA*H3+?Qo6HJxYp=3OsBx}eNgyL`MpH>UHE?T_Hx8{_r`cFb9Ktg%T87<3qA{f z3DlR;ta3+ne&y%is=uEYeM+gOokvr$?(N<$AFt^FIbk;f1#?*i6z~AtP=O9arBAM( z_HJcF$`0B(Y8)8v)p;HHzRAz;=te+4FZ>_hBsm^1*8;A+J~WcCXw@b2Af`bsCD(Q94U>b5m4_bTFF{Eqd|1{=bTs zvahNXZ?qoT+G`*<-ftT$-7w&f_Z?-ydFgxkW3QGL5Y;umn-My3?@nst>m676^Q-Fk zmG?)&U+~%P#!!u7Zn~eWh1a3OXqva4*Of~58-Bhvr);giQH25Dz592X*GbNcd0p53 zFO_zSobeX-JEMK$%Nb96EJIZ2hdBAr+zYloxI)B}!^N{CCb3dczz0+qDR-D>?`mbnJr&Grt?Tc0D zCF^aJti61#Ww^vL2Q^9*pJii>I}+XSG|TJC^LlG#+Hj@gp}<|X*0NLzNBS<-ZQ4(I zp|EIOap5tY$G%iP@f~lJ(Yj5Fd>+;JW2(uzdsRN;IvdBUUL$3vVyNX#$oE?+-eTQ% z2TRvg2-MvNZKVlPSFHK-s6N^>kjXkPujkCH&R12y2mllyFmOWy8NqNG*Y!x*HjaO@ zQv6oMTbll2f5%k=o#*sh=Xwi!p*L6?XTHl4yG|j%azvJKfy}PQb2Rb+Od9$x9?e;$M@b0X=*G|B2m9pv1 zOY2MOg&5IfG(Mk#-C2(AK(fxuYx;hZ7<;E{b&p0+_<wlc7h=s+N5gqfR)kQ?xT9^Vt3%qdM9Eyc|BN%g>m6{72S3tIylB@bkluz zou+CmS?AAiz#M^u15m&N&J8VgN}oEBZn&y1k+ScK^I3Li@M_;C7||iS#eH|`Gjk+s ze+Dkbb^GiMTA>7NHC56JE;u)Zmt@KC;(i}dUiVgN`YgL1Mr&Z6UhY1|d%z5LTf*z& zv^81kpK)L1N1lS+Dc@z+IHE(Nn_zx+s`uR@SqCO&ol7@oEWYRtKc0zTE*Q=ONfJ&8 zUJ{~BVa2}6>l7EpeWOdX1Zp$u4%!+Oi)9wFJC#LLU9v8emXi1i)Kb-uVqP0r#pTtM zaKB_p_Lo-q;U}whZ%^qiJH-(lv_8eD8j`iY3{C*gYfxuwcX8!@YG~K;_}PeAxBsC= z(5Y17;C**3ACbrh%tV@|zhY2lti0%Mw_U5>mr;Qn_*PVxjWtNo@u%ytXNBFhrtCV6 z=-_n%yK8~@$UE!KrCWey1eVeXzf@x=&jJ{SAeT$4xZnO&uWL!!Fgj|jJ7`%gv9LRF z?qjvIL%Hd{KqE6ZhIyDZ4?84vub{saoIxvmEcK zL$c@fmWFmUWg9-rCZqF3cW_(>?H=_5P`M1=xitI_0Och({&`syFaiJt2o%F*V@=6u zc&87)#1rF@-^*@5ql0!EMt2}ti%gx6&(P4Iv#f$UJjm|{wWoV=tedgFxQT5KUsG!*{o*E zfm0TOt17M!E8$o+l`sbzgeS%Q_aE`S?1s(JQ6n8UVpvrZ$@(KSsPn(4ZV;Do7+sG) zTm31OF*Krs*8jWz9WlV%zq9UKdM{3}K>{$G2We5A(?-GEhgEU^Ro?fq>CQ{!=*FCk z1_%n`kF zh8s!@xX@I|S*3wUv)3Nec0;9n{*F%iIy|Hsa{&$QD+f9+>YKA*wNTY?%BHF~e1_l# zzjD05c-N(eUYoFaxb5aj`NAFEuOEv;hDh+ zcMVPa(Qw;0J-f%==%$O)`?+lT8P&e>IXk+Jd#70bXrq~{7!H{8KqAFJ2~+_o_CeQ6 zuTOq(XwvtFCjDS&;zOR@onvcs(>)iBXfpZ~`jNE0@&@mRvdbTQhP>8*T8e3}kGCJW z6?C==q?HYF)s@z*E5A87>H9;IHV?JjGt?sN9z!sv5gj!8^uF?$-iv-rxY&6>gNWQ9 zhcWdxzixkJaN?c5(d4zT`$xkC-|j|-xiFe?v>4H3w0NDngMPfUyyp`QBC5%9 zgJc@2t>8s;&%M9S!R8n-xmdEo80$c<`^Ey9wqEH&qLcXqt?LjHb6TWq0rMcCo8bCgec3A&5tH zP7=m&!Jn=dU+WpFw7)zU26)JBe{?sH-BCF@TV~03s%D;yVK^f=!@tWusFzYU4edD#*9n~!%%!}s zq(ftFfuSVF%ZwJvJg+HP)17tbZi~6BhP-cgKBGIE$eY>;xL@cq<5KL~6Yrs_BfRz=Fstp( z+F(M{6HX0i5Ml1^E*%(b;%g4{e zKc*RCxCYC}jLJd>Fp_?qYyryxRnEsSbvZ{(xC5L(Prljac};8%EQ2uM&KE zCA^FKSEOwJxdkz<<7y~u;#=AHl|93&$=c=tGqZ{IwHV!4W~s-@n2qmedtdSrkDu)f z4Dacur@;eX-Lki=mX^})Hj%q8^S?G5`bv(CSv9tylzm2Dw|x98XNCjjJdl$>8(e7H z2!^M*3~ulKmZ8?WhgvreO?rU70Xj%i;;F}Or&srh+q*J$JaCsyUUM4r60Mjqa;~&8 zdxmG1tcAbd_gtpCvq|^USAB;jTyy{A#Ve=GTh?;ny=`9`X#c{F@@akDpWZ(8xb5`U z^S#EAJL=|vyX;)XbvBOExE9IU`|4KQ2h1#ou+HD{j}QOr)5GJhd$?tvj|I=PW%&W) zuX}L(BSS6U8*KafK>H>AWOUtq4=jx5;`Jgq%oipL?C?%r`^nn>>Q>wb%nV*f`@75Y z!|!`xc>MJb&su%7aG4Ww)?w>+x%t6=dG+1*{ruhWKOSoN?qJ(>1ML^@pvn2v69VHs zt+_fD##g*eUf0TJC~sk0@H($|?0KEmGC1>h!b3yjAM?iVE|DmRjT*JL@w}!7%$`lU z49@(epV|<7_WXUpe?9Mcy~}gM6RvrnW#yr9kGXZ9k5BlI`)Kp`JwIIa{T1?kIN-ZC z-mAWgdEKZ9nm3RsI~T9Pa6^y~?_kSryOq|ir_ZnBC2Nhp{`h@Hj$g7^`b!>pE?@iL ztRt$=03;*iu7@2dWtV2!F&r8u3gBtnE5DZZ zrS?jy&hhzFL=$n0?i9v>w&J`lI0fDW>f3-j~36-*=kV$^351 zdATrNnsG`kN7%^QmX2N@`PD7vFWn!F$iHm-23_!6{%~Es%-*{90TZtMVX!a6BYl_o zoqVVJIGWde$~dp{7sgA|bMSi6ym{gx!FZ1qSmK?=b>Z2-kD_S&9UkE?O|eGu89F2I zh<)S<;^31J+h(g>4?lhc)%|3FWAFlSUgUSWkGpHoyMOoR^P2qbr)(P6meN&EkTE=# zO<8iFwC?E1vA zuy_AX_i-WLKiAiF;`Y+4Q?oq&Ec4DFy(dOS+#kj9SBOl4x9+tn%Oel=)w=8; zp2wry5Bu)j$5lMvFWJ#~c3)}HdBHtr6Dx)T<~)!9iN%c?8MQNS9!qCUW9DEs*OKeS zDc}^yUI8nHGbWg}stx!cQgbjIr;}O`%L~~!`|HZ}=oD}YWTU_ya+sU2oK_p)9Xmvc z3nosip9R@mORg8EfKwoQ1@@R<{nv#6b3;%+$XM;UVL6YK)L;Ru%>KG^Jvs%P0@)~_ z7!H^l0?8=A0f7~S<>sz2nVU=m2yP0PgV|h5t{10(Qy_Z<;xU}TL2WMiY+?&*lZ<1{ zx|Nl51`DFAvcIlek4^!nKsE|2mIEJw!m_MNt%Nb$idxZI0p@%^HdSboEa06cEP>8A zQWOFUKUYr6>f$S9kx?=^YQ9UI_spA0#vkX!{i$ps#IGFu)<$81qI0dp%VDW+l zq9X$VYOGR#O@yYMdGi{T$L85wORg8EfKwoQ1r);pbDKcY7?emoXfkxCu8(Gi(Z*$e zUAZ2e0#1Q!6iCSMXk2J^SbyMafEK4y=n=;mk}VJ zHgOQneHQA8wZB&KwsvN{^{u8f1Uj6;$Jua^3$e8NgbRzNbexMgY*v4qimg|cVcvs-bs2V=~2-x(z{6S z;zJkdU8G0Vb(7vrdN=9aBy^L`&$K-0dD8Qw=Sk1!)hy=@8tS0Z4l3v%bKDh99rUMz z{&div4*C;!kN$MfpAP!dL4P{vPuykt(?Nea=uZdz>7YOHFz8PQ{pp}T9rUMz{zOCT zpg$e-r-S}<(4P+aL+|3AbaL*bKb`calm5gI(4S5^&`D#RRNP4=F)Uo{#OS0yo%E-Z z{=`txpHBMINq;)&Pbd9};iEsD^rw^lbkd(r`V&FgNq;)&PbdB9q(7bXCx$sjChAS} zUpN0qkD#YNUG%4m{&dlwF8UMGL4UgFPZyo&qQNdIk13*17a6+v&_#c`=ub=={pq4V zUG%4m{&dlwh{`Vd(?x%}=ua2@>7qX|y)jD>GEr}$|45H0r$62Fr83yN)Sy4z^rxHtbkmV;8jYt5m333Fn@rs#bkiSx_(wYZ>83y3^rxHt zkj%em#zZVd$V9#2zi6t_pFI7^)1N&3$2wc|~@Txagp@#eVY$?8B8g7QERxn`JK&ZQh)0yDfRrj?r%f`&6~e0Up2!|7gd?Iv~Y^129W zep_vr(oh<%$r)U`j!s(RrUTbC2E4-NmMrN}4Zd{yDJG{T!YPKya*CK+9y6?ob~YMN z!!()%zZgE5l%5opR?q#%zj(#lhVi<&YTRcT?5B#oF)R@jl)I3o|L5F zw!7lXDf%p~eW5m4P6@~@j~SNPZ>!}~8eGGfNN_E>3r?z#*h&Zlt{a?9({M8?3CN+_ z*KkWQeYOnFs*A^jgelUJciL3o<^X--QeTfodUO8g7Okhg(YJ0lB(uvTTOQa?0+C>4hXgOXRvNgKbOz;zutGU+zM6x%ndqT%TQd5VVng5RoQ-WnRttPZYSN7t@>(}C{V zV@``E-M-;#xTRzfbBii{!_?R}OqNr`-13-Vnf9eo%mSTC#@Y`y}lor!)TnVl@+Qg^Ye3*gj8czUIY~S#u z+fS)n%;nl9%VwA?Ta0a&%&6eD7->MD zLIh01TVod@MHrjtQqb@UXLTqZ5NIC+OvBA+BCTuHt_BTn9|sI04G2_-fJwI*ttyO7 zG_IiG70&8VJRs0M2$*!6(L`F;s$C5l-aZZ(Mj8;P5CQ+yj<7Kfr1f1Lf`(T(t3&aC zK>HvNG#sw$tJr?)LBrd}0mDcG0u>_QYk1gH0a9OAYnc)>yuw)>iU$PR2LaP?Gfcz7 zrV7)bmeOr)1r2W>2Mi+(2vmrGNw*n6!-3S~v@S-_@Cs*jC>{`K9|TOg%`go&qb@qu z&W#2QZyyH?BMk^th=57A87AFkw6mPnW$Z!2E1cD#ctD_i5HRWX4b$+jG0uFbrI-f| zZyyH?BMk^th=4EMmSP%iMlE%$o!bf;Ug4|`#RCHEgMh`@Cf#P3beqx6x?0Pz2Muo@ z2Mi+(2vmqbiiZ1QZkcN-Xl>Y5(C`XpbtoPXXdeVD#x}+F4a*ZWoQY9`H6>_x`#4}2 zX+WSt1blr?(QwOL108GUCW3}nIIBbPfI#~oV6tp6b`}k{%IpYph5(EeGVE9q?=Bkv(y|kyuw)>iU$PR2LaP?Gc3lo6yLBsCiq#TDdb^ZWdR{* zc>6eD7->MDLIkqtb4nf)^DNR7@<3J=5Q2tRIIBbPfIyodFg7-pqR$p%`*|$IG~6<0 z(WsDz36=uFrqFP>Zj)IZh8YlOD+El9eZ%zGzho(v$BYzd3YVB#SwPqn8cx&5cu?~8 z@$SHNn{bU9i))i*Gfb8(#e^hSeMlrcg;BY-$asKf$$I+piO& z3v?#{X{C>*EmCZ_HtF__6b-k`rs0;^ng|9nCkqHQ&~VM+;M%R^%jshYT&LsHyjOim zF*WuLU!PO*SZ2S8kivvX0ik9ZPB(&UH?Q-S+VjA5sfaa2eqTwDWw_=@(PxXX{XCXp z8g7~Wwn7S%#0R048cqk`x+&&r=wv`3AmAh53y6tuiedVkC68tH+X^W#;)76Q4W|!5 z#(mdl)s!ec3#)buvAcBXQjNw}67*SI`$BE9Y%z999?R@E5mEr(2ch;FPB&uDu0lY5 z#1TjQ^W^dQ&wu``v(9qeWq5e_D_{8v*Z1Flf1OV`<&^R9@o#_o+xzXeABhJXZ~*5c zk34c{Xvi&yO}3LxI*ANayU#xRaNc*{eLwrz&r%NtAE^QR=9_O$6ujn|Ym`Ba9(dq^ zl$t+({-cjRsun4wgGwgN>pZP!W@xSBa8{hbbiwRrO&4+~+=*=uabm zGz5Glkt{>Eug{i}qT!YY4aXk<3gkcasZVh}_Sj>Ei5eXl86krp4q`)QQoDyW`NRx^PP_y?t^(}%9Yl)7j* z1JRN#l*&G%mZDOw@y&03)2%9(%N=ykK_IF50My4EbBr?Jq)Mka;6vqyKJ+0{L=6g##OhwVI)iOXT6qC2Bb8sH6J&`dIgw1|(7~wNdbb3ofuyaIHEy zbBR2x_+S3=m%rp4U;N@1k2~%-E7NQ8GtA)O`Ot$EIzIb@?OicJO#qC`@( zG|(k#X8HK@pZ{#7&~U0%H^`5D%PqI8U%wuFhyyuXV{~+sf<9surqoNr8B10CT6_t^ zgkRGH8g2+f3hTAN=X~+S7n8z4Sq>DHt0$ar0xL2e2fxrwS$O%v7rxNj+iL|eSn*jt zAeR|J22B#2n%byppq47a*I|bp#x2iv*Ijq@)mLM5 zb#)=mT;<>@XP4_mix!aro1F1PxPI-m*97cWzxq{4x@H2i!Uvq&D9VauYT!^4oJsVH z6x47}zoP_%-DJ&gw*ga3y3O$Q$CqwPvB9QjIGOP{=^+SnU~`5w&XC1H3Wtaw(KH;y zs2PQq*TXeVdc_r2kpA+^FEc}6Sx(KRr=EJs?>s4IpMAC(rGDDdw8213SU#xAEmcx% z_NPDnDN&q{m8aBE!`1&vT$}Y8Y*|$y6sYasqgdc7WO48j`fym5NIP!2=_YZitGYdB z8P!KB;cDWZU47Ph?b@}69(pK^l2e&!j+wS#!2)Z-47jE?y2`}B@zrhh%|E~N(o1eb zEn}C#wE?JmE^q@q5CcZR&eBN=HrT?2G0r`gmBo1Ox#z@`SYYO?TD9t&bIze2+*~u~ z`s=SR1~qqKaIJ}?4p0QHxleank^Q^h{Z5=xInAlJO7YLnKmWYdP^|UFNjK>>!xc33 z(-b?!Ffmsi5I}o{0|r49J_y2~hr#iI4}5@|Tsxp!yo-9cravmq9v24ToTi5Wzv!Zi z*lH6U)Ja^e{`;LL<;*kBQq1#v5-?xthSBlDqD@iwtBY1NCDNJg{n< zfByNG#RoTNGA_LELLvvZIQ0mzg5Ah|sqPw1SF^Y_WA_hG71W>yk}Ste02aGvpMCbl z7hhzZWikj}&UiOmCxYJFZo5roVU`T=&PSzSGZXwqm7+aQ8YMGROOuUOIIvGU?X-34 z*12uXn>SBfOUB7|`|Y>88O$!$BI%;F+0Q9-7aKd^h-*jzI*{a{28mRq1GEX=V(KE< z#9+PVlA(&h1}2US{$!BHi4iK~Bb%iKTj$0Zq2T5k(I7vQgpD-}4hr&-t2`D_L+T9o zTy%gsIcSSKmtJ})8?#S8{WRyq!Fo;Ef=xFd<0jp{;R_M^3?NL`f?}>A1FsA`R~V84 zP2eWzKoV6HuwaG3h6y3DxhgEcbx%)^@|b}XbBTj`IKvmzV?ZCuAk0mTWuOma6Kk}~ z;?5e)b1~Y|?h1+6?44R$bLY;beih*oO}y`Y?<0kr{=q&E?E+oF*1^HYFiT1!Xt-n? zSQ6?aa^167wzIefD=_4I;)y5X%XY8?T zc0rJxz^b`ECb;%T=MG;qX*m}1pv5+_VaqlnT;tbV<$w`D#;-}YJTiD3cJRRm!x1%* z6OJGP3fL`CE1a!qA^}!ss-i*_fmR-kDJRo|8e#$`9%J2b!ws}Tqbvv1PZ2UuKL#~m zCk|TYU~N)`)@~!y?Mt_%_-Z5RW^|_E2(`F&4GkRW77oN4UXvBXx(LK&H8*+j^^^@i8$R8>x-mh&GU2Y|-TG zhg%TaDohxLKStt`eN0qUMjxyy47KPE*>FhUV*u96FvU(We6>Nt86#sc=|-_NMw4!C zoP`4hn1C=r5ofT)5W*Ndyyl>u6hoP5R0jJt;>!$I=S75@lE`fJ$e6Nqb<8cL3atqi z1&!2}l44>G%RZQXO50wWSUoaSdCEDF z-|axgJ``+SEoy)^UPHhzF_bXs<8H3w+^WiMT}`CWZI~EJGAe<+!m=sSZI^tJL2|`4h6ZKQO=vBy(Py{@4IU84l`w=e zH$(!NhZ+Ro9Hht~Xdf6Dz{ao?88o3%7^+7GJf<%JZf0z^o^U5se4AfSY{a5i|^ zCQUgko6C;Nno-~zZZ?-+s}rMG({3I$t=iOz29-{?&o$`Pm@jK?$&wz~rr0Tl)P~-o znPMDeV>nD>v`$1@)QutOMxTHE^w2Nn=dS$q;$J*G$j_C(S^SIngZyCp{NVw9Fm8FM zpP#PVdt_X7d(T~u_w(o(<>w3?EDD^#pPI!2>xC$g0THeUyO*%Zqf!(Xxl~Ba95nIF zD{F3EG;r1ZOF7H9<*7k_NRiR?z$-t0I>%3BJd@+6>%mul{cIFof<{3x2Noi8(G99X z3^5nrzI0nk<7l}0%$ZS0xFlKT)QVU{v?l-d^G0|6$=aQ-7@6^JLo-hsoOR;BtZxj= zIxapRKQQZ?MSl*xbYSknJ~mM~#EZ`6iLUFV*p?r|>QS{XzPjc+_vYUFliZBUhl~DP zF+AhS_=h|f5AXVep_ymrW}Z6u&Tsd*-ff|ppb#v+Yn!7rzTtAsKo}r{GNNIh6cLTS z0R@V;%aiMN{?E}JZ;5|?HoDXQi+R5wEAIzgJn);x`c}t>2r5Rs%c8EgswHhS42wjDKz#-SOs0-ftY;>DslsTs|`6+@YCg49@!2 zV2Z!*|HD;xcK7ibFpGkCCyW<&7$Q`Hk1d0%md8qA!1CGm<=*wxDxz z&&ka?Wg~tgq9sHp4D5MA9}5Q{h;Hq-FnqRIH2K}Fau+)2HpTXh2GMYvoF+{;HKSu_ zn$IFy^ITkm#`NCt?S8#(1KlFssF%OP`*mw~zH(&7c|$YL%+2~%Eb^YtAMhUow=d}9 zeKQ>*eaiD>_Ek^3+RZA23nO&=KF=AN;guAg*mmuuI?<;D9=vA;;F?N@nph-1Mlrj z&y8>K#Q4rra_#f}^JsePbakxr7Yxt*PR#pcT=#_^t-SS-HLyt&;~&S|t&jJ8|M!FM`hNdJ{A~Jc@v}==1@`R2`|xY->{!3FWD}5U$tEBd*V-Y+BU(el zA)13ZEZufB9HMb*(1^Gm&TqM}#3egB@8pDf7WbP+ce!c=H=lKE97R`~UlVW^>)D6) zv0gJelW`Cb*MMMt4LEQu*DzHqRZi=Y-+F5r9#g%6YdN)|vW>XT<=?V&{f`g&8Tpu~XHTyPkHVp?}A*O98xc0YDETu8`Qkbsh*NhJBV#wlJ zi#7TN8WGq1`Dn?Wm*Fnkr!qYy_UIW`O%knb?M+Pg>?1aCZ5lqMUqiQ?r7nJ5YNMt? zzJ^cD^>F?jPgi@%7SZO>?(+-LjhI*0yW@?W*@yLMy=Eq}WXrFo|j~E!lThW66#^dTOFw?{hy6Lz!={AGVQ4@gMf8P+-u7)c- zOK3P;TO5vtZ?z_l&ER@Czr~`8muyLQA{cXh*|)2;cC%Q2J-V~j&mKpyT(8NZ;jOWk zBCgp>(R!`>Yq*xOVSvWo17lGf9{cs?FRw5Ba5JNTmqB#GyDJIR5b(|@0vFf+^Is#b z+egD)u8nTiYvUT@uD-!H%eA#+|7u;Cn<^rD$~D^eYnSdyB6GMtY6I8bx;&c6%;%Ii z9DFz$VZAo#_KjizIWle31A8gFAF_|R_E7%s{!rGET_Mpf z-4(3eY=g_GcROPBvwx2K+TBZG>})c)`{6OwO}QV=3hsty8VFoNw77Qn!|`Z|Ie^@^ zrhhZJHcK|ovac)g&MPK5YcN*KuU)#!xDnfUu|DqNe&(>oD8IJ-aP&=pfQ%q={kqh6 zxQ_W*Fu!XDmL~ z3d}U&69Nua<|AdpUSUBKYLjl?@B?!4sOJ=C6u363r6n6f;TaG3`##zyG(E+3)l$40uH$Fc zCtVS}ovsmyYsTmYW)RIGq8q`f%hm*wBSyiIShC@o!+nY^mN^3vt{tt~L&cwEL$v$i zK{`#}{$}UQyab2E_p9*LU>xZ?DS^KzXmI5IL3Wz`nF!MF4`E6J-ShdcD-AVNLZ|o8({aFK6B82 zxMnQo*M1P5&~OW7D-qHAP|j;T&^-9$HBCf#P3V*5tAhC_FXh9h^AeGLapX?RJmqco9*i|c~18Ga4d;KO+NcI6Zv)7t3at5Zd|k8EnmJ|bpL40 z@br1(JN#^PSH4!C5&T+a!>=zLo_T(5pYsQnzcKL*(8PM(L|mJ6`-ZRKmV%i3ad^6h z6Ungo;Kt$0R;>6Ri`Q;@=lC|iAK&4I#-m$ApPQTc{oJfm2e1CGmxG2|Y{m-3QB1?( zS{kl69M`_Ae`t#**Kd2r_%?Sn9^FRtcO$O(4Gf<>FaB*#WDQuzW@dpNrwKQB@6Nmq(f0*xpOuuJ*8#ElQjqV%kE#^MaaD8r$Uxl>q zY5i}!vBKX=(SA7hm>PS^emIm_u$^Kw=3a^kxCP<9hARk%YjjUsvr@l%aQrPj`3a{M z*G6|8*Y1Kui|bPdc`f{x_eKG^{F)_+In3xRJc}OhwcLJqdJyjJrGP_%Yp}YaZ-{4_ z?^v{c+uJ9dx)JCuMs%#<{8AmBX&!J^v}&^qF>m3T3G8xh@1-R6%}m3=ttx6&Tif-F}Kmw;9rK`j3Vq;2e4*ngJ#>oaIbf2Qs`+-Gx*09x03UQ&Vvb z={2A`Bhj&j^9xvJ|4Sbc+TN%3y}o=UOA-^9nasO|a&0!oiR9 zH$@!oJ2k^$ToA3OjPaso_Jj*Gzyz+Btz0=$u{_gJ8RSJf`+`i z>U-u8eaSG&Jd>R2G_*lVDkE^RlBYpo%jm&;%rXsP(PhL^D5F^sz+-Y!1XB;OEz?0 zbL$c<+4`O)I>wL{p4o~9Ea1c8KHQuV@W$CokzYeJhXx`6Hw_opj2)saFuO`l9WT~z zf2Po#wZrVhPMVui#kIRUqGJt@mhAX9Ai?!Mr>A{SljRIRq~V|>xCC9PLR!cC8M&5I zi|f}{ul|Sr$zP)}kl%X#uH6+94c**j^P5QH@C>f^|4tNky5F_eotHMo@#}&bF0KcxecBmH2tIKE@PXea-!jyCHv$JOZM(ZwsI)$bFFC8U#wlO zH~b!?9KX7-bXSXLE!pR8ShB@6HyT>6iNk#j7uRka zF0Kp0s|nDs8lJ_kC%B$+8$3a1`p1lPSC?qXIKSd7Ub36ZuS->u@-*CjAL(0qs^Qc& z2c}%Rt4_4IJ}r8dO>CB(Yu$DkdZof%mHZ~%W~68fmnzcmp?q{_%?oBmR^>*DcW(-! zH(s){Yq%b6f}Xaa;4TH{R?u+ntnCG}%2~D=3evrah}M!FzkY^mi|fSwwYJXe{#xsG zGj6At3fVo^lKJ1vU6?dRYj9at;D3; zj1+CjqT&8t3Snx*b#!O#yWL-EbxLNX2y{++UZf1ExZz;o2kBUP`g8vxsXJYhEzZ+u)VZYGuVQ z6yG)eclWH{`VZ^(STKI!;^Du%vFi7)_V3$0`u8`E?C|4}UHDto-xKeH5%1ZZH$7*( zWbb)oax>f(>%@B92wWq%qT4h)ePdi)yL&0(n!Oa!Ee&Ue+cQlh4z4#_z46=NMp;Ql z%x~nv@H=n)R)1Lkj`{hwJ(hp>!nGIo4EHRLUf#BE;>>%!|DRtPd+Yr1EqPXc%jgbQ zjqLKnA?Tic7XDr_?`(`8KOnB%_fo_)V1fomtL}$0G}o^s<9hrN{XNa4Yu{&+MiwqjYoWpw+W zjO_C7LumV~vUz98K6S7?|DGnRl5w3_vY~tW;CSJ;!HYTdB)|CY-{Qabub<$zJK~og zh<@*)@k^ErEuH-Oq|2{w&t2Ak&Kp+wpH=d z8dPE()(~QkAK$ZR{6|ZM zm#mne*rhdktT@$S`HlLyuMO<;{Mg%E#?_W|9^TRUNAkpV+ul4H#q&Shn0KP|b8~yl z>DK`5Zi}&Vh-d&2I0DLWYa9(ne>7o=ZK}{!ZR#=v9@S|$h?TguhnsFd{@~o_cpqDo@uG{kWtWC+D-JV=`MKNWuoN?_l-0xg z>i51raNrAL8~OO;?21}h=@k+dUbb8O1L5tegF-k^gmL z^u}yK^@eEIsX@tb6W2{~wmxHsZViev1B7UC%?wwN1{Avg!UgoQ3cMHv1@U*eunaE0 zF0<5`ez=*fT@1How?*0RRV$^cXwH>xaUE&5_h&x9L=d^4)r)0|!_6=aFSe;dx2542 zdfkHI*h_|PK+f2qn|egIMdo_#5ZnmS1*2(iia};UO>vQ{09Yz2@YRH$LVhb{^<->a zjgr}KlyPxLx*4oCl$h{|@Ed##vF6fnSH=svw(s3?aJ<_b96AIYXMvf1w#?$x&Z;xZ z*^0PLXKCGUTFt>Sfvc<$zBxw|9SILXf4L-(;fp1_IGb|^D6~~C2 zD)ZqMbSuOz)-LI8POCv}W+WP9T)4`{yz+u3-DXUw;WX+#+>~oe%%M9)%xMCA018zX zZb&W$cox%MU2-$4xX@OG)S1yxDR)h=n#F0sZde{GE|zIj9_>rF-a>(8U=h*Ma6u>5 zirwaLwQ=Hbb=94#qFWAL(7WAeO+X1ZI}1<$Y#C&ztepjQ#QO@) zV?m-5T-Tjqgh+ib!!+ECVrm1|Zg?rW3yL{VfQ+;bgPMgHhQLe_VK+0S+t>{M!}7>*>#;^Py5Ue<>eu5oXLfbrt-LmqZr?BsFSapG>k0i~mXOr!Zc8x@H=_(i0+uYgnmrFFmC=nvDUp@E(J4nE?kew?>S-bkSBDFpi+My!dck_C zo0!siu}jtMK&UMsP+bHp#y06T!=&4cYH3uc2NF|2Xblao?nDi>1q1>D1rbQma9_+V zbBg|iOW<4~2tmUO&ef0@5C{nP2w045itQVgCuleTR;bTeiU$q%Cu&Fu2m}NQBH-(D ziiTU}EJ76W0C;&I1Pw1ZS3_bzARyo)V6tp6b`}k{%;jlRC+6Xn4W78WIBn0RbNY6Ka!Xi?QvJ8J5S4@-!-xf`}9l lf` diff --git a/gencpp.ml b/gencpp.ml deleted file mode 100644 index 6584a9c4..00000000 --- a/gencpp.ml +++ /dev/null @@ -1,5732 +0,0 @@ -(* - * Copyright (C)2005-2013 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. - *) - -open Ast -open Type -open Common - -let unsupported p = error "This expression cannot be generated to Cpp" p - -(* - Generators do not care about non-core-type abstracts, so let us follow them - away by default. -*) -let follow = Abstract.follow_with_abstracts - -(* - Code for generating source files. - It manages creating diretories, indents, blocks and only modifying files - when the content changes. -*) - -(* - A class_path is made from a package (array of strings) and a class name. - Join these together, inclding a separator. eg, "/" for includes : pack1/pack2/Name or "::" - for namespace "pack1::pack2::Name" -*) -let join_class_path path separator = - let result = match fst path, snd path with - | [], s -> s - | el, s -> String.concat separator el ^ separator ^ s in - if (String.contains result '+') then begin - let idx = String.index result '+' in - (String.sub result 0 idx) ^ (String.sub result (idx+1) ((String.length result) - idx -1 ) ) - end else - result;; - - -(* The internal classes are implemented by the core hxcpp system, so the cpp - classes should not be generated *) -let is_internal_class = function - | ([],"Int") | ([],"Void") | ([],"String") | ([], "Null") | ([], "Float") - | ([],"Array") | ([], "Class") | ([], "Enum") | ([], "Bool") - | ([], "Dynamic") | ([], "ArrayAccess") | (["cpp"], "FastIterator") - | (["cpp"],"Pointer") | (["cpp"],"ConstPointer") - | (["cpp"],"RawPointer") | (["cpp"],"RawConstPointer") - | (["cpp"],"Function") -> true - | ([],"Math") | (["haxe";"io"], "Unsigned_char__") -> true - | (["cpp"],"Int8") | (["cpp"],"UInt8") | (["cpp"],"Char") - | (["cpp"],"Int16") | (["cpp"],"UInt16") - | (["cpp"],"Int32") | (["cpp"],"UInt32") - | (["cpp"],"Int64") | (["cpp"],"UInt64") - | (["cpp"],"Float32") | (["cpp"],"Float64") -> true - | _ -> false;; - -let get_include_prefix common_ctx with_slash = - try - (Common.defined_value common_ctx Define.IncludePrefix) ^ (if with_slash then "/" else "") - with - Not_found -> "" -;; - - -let should_prefix_include = function - | x when is_internal_class x -> false - | ([],"hxMath") -> true - | _ -> false;; - -class source_writer common_ctx write_func close_func = - object(this) - val indent_str = "\t" - val mutable indent = "" - val mutable indents = [] - val mutable just_finished_block = false - method close = close_func(); () - method write x = write_func x; just_finished_block <- false - method indent_one = this#write indent_str - - method push_indent = indents <- indent_str::indents; indent <- String.concat "" indents - method pop_indent = match indents with - | h::tail -> indents <- tail; indent <- String.concat "" indents - | [] -> indent <- "/*?*/"; - method write_i x = this#write (indent ^ x) - method get_indent = indent - method begin_block = this#write ("{\n"); this#push_indent - method end_block = this#pop_indent; this#write_i "}\n"; just_finished_block <- true - method end_block_line = this#pop_indent; this#write_i "}"; just_finished_block <- true - method terminate_line = this#write (if just_finished_block then "" else ";\n") - - - method add_include class_path = - ( match class_path with - | (["@verbatim"],file) -> this#write ("#include \"" ^ file ^ "\"\n"); - | _ -> - let prefix = if should_prefix_include class_path then "" else get_include_prefix common_ctx true in - this#write ("#ifndef INCLUDED_" ^ (join_class_path class_path "_") ^ "\n"); - this#write ("#include <" ^ prefix ^ (join_class_path class_path "/") ^ ".h>\n"); - this#write ("#endif\n") - ) -end;; - -let file_source_writer common_ctx filename = - let out_file = open_out filename in - new source_writer common_ctx (output_string out_file) (fun ()-> close_out out_file);; - - -let read_whole_file chan = - Std.input_all chan;; - -(* The cached_source_writer will not write to the file if it has not changed, - thus allowing the makefile dependencies to work correctly *) -let cached_source_writer common_ctx filename = - try - let in_file = open_in filename in - let old_contents = read_whole_file in_file in - close_in in_file; - let buffer = Buffer.create 0 in - let add_buf str = Buffer.add_string buffer str in - let close = fun () -> - let contents = Buffer.contents buffer in - if (not (contents=old_contents) ) then begin - let out_file = open_out filename in - output_string out_file contents; - close_out out_file; - end; - in - new source_writer common_ctx (add_buf) (close); - with _ -> - file_source_writer common_ctx filename;; - -let make_class_directories = Common.mkdir_recursive;; - -let make_base_directory dir = - make_class_directories "" ( ( Str.split_delim (Str.regexp "[\\/]+") dir ) );; - -let new_source_file common_ctx base_dir sub_dir extension class_path = - let include_prefix = get_include_prefix common_ctx true in - let full_dir = - if (sub_dir="include") && (include_prefix<>"") then begin - let dir = match fst class_path with - | [] -> base_dir ^ "/include/" ^ (get_include_prefix common_ctx false) - | path -> base_dir ^ "/include/" ^ include_prefix ^ ( String.concat "/" path ) - in - make_base_directory dir; - dir - end else begin - make_class_directories base_dir ( sub_dir :: (fst class_path)); - base_dir ^ "/" ^ sub_dir ^ "/" ^ ( String.concat "/" (fst class_path) ) - end - in - cached_source_writer common_ctx (full_dir ^ "/" ^ ((snd class_path) ^ extension));; - - - -let source_file_extension common_ctx = - try - "." ^ (Common.defined_value common_ctx Define.FileExtension) - with - Not_found -> ".cpp" -;; - - -let new_cpp_file common_ctx base_dir = new_source_file common_ctx base_dir "src" (source_file_extension common_ctx);; - -let new_header_file common_ctx base_dir = - new_source_file common_ctx base_dir "include" ".h";; - - - -(* CPP code generation context *) - -type context = -{ - mutable ctx_common : Common.context; - mutable ctx_output : string -> unit; - mutable ctx_dbgout : string -> unit; - mutable ctx_writer : source_writer; - mutable ctx_calling : bool; - mutable ctx_assigning : bool; - mutable ctx_return_from_block : bool; - mutable ctx_tcall_expand_args : bool; - (* This is for returning from the child nodes of TMatch, TSwitch && TTry *) - mutable ctx_return_from_internal_node : bool; - mutable ctx_debug_level : int; - mutable ctx_real_this_ptr : bool; - mutable ctx_real_void : bool; - mutable ctx_dynamic_this_ptr : bool; - mutable ctx_dump_src_pos : unit -> unit; - mutable ctx_static_id_curr : int; - mutable ctx_static_id_used : int; - mutable ctx_static_id_depth : int; - mutable ctx_switch_id : int; - mutable ctx_class_name : string; - mutable ctx_class_super_name : string; - mutable ctx_local_function_args : (string,string) Hashtbl.t; - mutable ctx_local_return_block_args : (string,string) Hashtbl.t; - mutable ctx_class_member_types : (string,string) Hashtbl.t; - mutable ctx_file_info : (string,string) PMap.t ref; - mutable ctx_for_extern : bool; -} - -let new_context common_ctx writer debug file_info = -{ - ctx_common = common_ctx; - ctx_writer = writer; - ctx_output = (writer#write); - ctx_dbgout = if debug>1 then (writer#write) else (fun _ -> ()); - ctx_calling = false; - ctx_assigning = false; - ctx_debug_level = debug; - ctx_dump_src_pos = (fun() -> ()); - ctx_return_from_block = false; - ctx_tcall_expand_args = false; - ctx_return_from_internal_node = false; - ctx_real_this_ptr = true; - ctx_real_void = false; - ctx_dynamic_this_ptr = false; - ctx_static_id_curr = 0; - ctx_static_id_used = 0; - ctx_static_id_depth = 0; - ctx_switch_id = 0; - ctx_class_name = ""; - ctx_class_super_name = ""; - ctx_local_function_args = Hashtbl.create 0; - ctx_local_return_block_args = Hashtbl.create 0; - ctx_class_member_types = Hashtbl.create 0; - ctx_file_info = file_info; - ctx_for_extern = false; -} - -let new_extern_context common_ctx writer debug file_info = - let ctx = new_context common_ctx writer debug file_info in - ctx.ctx_for_extern <- true; - ctx -;; - - -(* The internal header files are also defined in the hx/Object.h file, so you do - #include them separately. However, Math classes has its - own header file (under the hxcpp tree) so these should be included *) -let include_class_header = function - | ([],"@Main") -> false - | ([],"Math") -> true - | path -> not ( is_internal_class path ) - - -let is_cpp_class = function - | ("cpp"::_ , _) -> true - | ( [] , "EReg" ) -> true - | ( ["haxe"] , "Log" ) -> true - | _ -> false;; - -let is_scalar typename = match typename with - | "int" | "unsigned int" | "signed int" - | "char" | "unsigned char" - | "short" | "unsigned short" - | "float" | "double" - | "bool" -> true - | _ -> false -;; - -let is_block exp = match exp.eexpr with | TBlock _ -> true | _ -> false ;; - -let to_block expression = - if is_block expression then expression else (mk_block expression);; - -(* todo - is this how it's done? *) -let hash_keys hash = - let key_list = ref [] in - Hashtbl.iter (fun key value -> key_list := key :: !key_list ) hash; - !key_list;; - -let pmap_keys pmap = - let key_list = ref [] in - PMap.iter (fun key _ -> key_list := key :: !key_list ) pmap; - !key_list;; - -let pmap_values pmap = - let value_list = ref [] in - PMap.iter (fun _ value -> value_list := value :: !value_list ) pmap; - !value_list;; - - - -(* The Hashtbl structure seems a little odd - but here is a helper function *) -let hash_iterate hash visitor = - let result = ref [] in - Hashtbl.iter (fun key value -> result := (visitor key value) :: !result ) hash; - !result - -(* Convert function names that can't be written in c++ ... *) -let keyword_remap name = - match name with - | "int" - | "auto" | "char" | "const" | "delete" | "double" | "Float" | "enum" - | "extern" | "float" | "friend" | "goto" | "long" | "operator" | "protected" - | "register" | "short" | "signed" | "sizeof" | "template" | "typedef" - | "union" | "unsigned" | "void" | "volatile" | "or" | "and" | "xor" | "or_eq" | "not" - | "and_eq" | "xor_eq" | "typeof" | "stdin" | "stdout" | "stderr" | "system" - | "BIG_ENDIAN" | "LITTLE_ENDIAN" | "assert" | "NULL" | "wchar_t" | "EOF" - | "bool" | "const_cast" | "dynamic_cast" | "explicit" | "export" | "mutable" | "namespace" - | "reinterpret_cast" | "static_cast" | "typeid" | "typename" | "virtual" - | "_Complex" | "INFINITY" | "NAN" - | "INT_MIN" | "INT_MAX" | "INT8_MIN" | "INT8_MAX" | "UINT8_MAX" | "INT16_MIN" - | "INT16_MAX" | "UINT16_MAX" | "INT32_MIN" | "INT32_MAX" | "UINT32_MAX" - | "struct" -> "_" ^ name - | "asm" -> "_asm_" - | x -> x -;; - -let remap_class_path class_path = - (List.map keyword_remap (fst class_path)) , (snd class_path) -;; - -let join_class_path_remap path separator = - match join_class_path (remap_class_path path) separator with - | "Class" -> "hx::Class" - | x -> x -;; - -let get_meta_string meta key = - let rec loop = function - | [] -> "" - | (k,[Ast.EConst (Ast.String name),_],_) :: _ when k=key-> name - | _ :: l -> loop l - in - loop meta -;; - - - -let get_meta_string_path meta key = - let rec loop = function - | [] -> "" - | (k,[Ast.EConst (Ast.String name),_], pos) :: _ when k=key-> - (try - if (String.sub name 0 2) = "./" then begin - let base = if (Filename.is_relative pos.pfile) then - Filename.concat (Sys.getcwd()) pos.pfile - else - pos.pfile - in - Gencommon.normalize (Filename.concat (Filename.dirname base) (String.sub name 2 ((String.length name) -2) )) - end else - name - with Invalid_argument _ -> name) - | _ :: l -> loop l - in - loop meta -;; - - -let get_meta_string_full_filename meta key = - let rec loop = function - | [] -> "" - | (k,_, pos) :: _ when k=key-> - if (Filename.is_relative pos.pfile) then - Gencommon.normalize (Filename.concat (Sys.getcwd()) pos.pfile) - else - pos.pfile - | _ :: l -> loop l - in - loop meta -;; - -let get_meta_string_full_dirname meta key = - let name = get_meta_string_full_filename meta key in - try - Gencommon.normalize (Filename.dirname name) - with Invalid_argument _ -> "" -;; - - -let get_field_access_meta field_access key = -match field_access with - | FInstance(_,_,class_field) - | FStatic(_,class_field) -> get_meta_string class_field.cf_meta key - | _ -> "" -;; - -let format_code code = - String.concat "\n" (ExtString.String.nsplit code "\r\n") - -let get_code meta key = - let code = get_meta_string meta key in - let magic_var = "${GENCPP_SOURCE_DIRECTORY}" in - let code = if ExtString.String.exists code magic_var then begin - let source_directory = get_meta_string_full_dirname meta key in - let _,code = ExtString.String.replace code magic_var source_directory in - code - end else - code - in - if (code<>"") then format_code code ^ "\n" else code -;; - -let has_meta_key meta key = - List.exists (fun m -> match m with | (k,_,_) when k=key-> true | _ -> false ) meta -;; - -let type_has_meta_key haxe_type key = - match follow haxe_type with - | TInst (klass,_) -> has_meta_key klass.cl_meta key - | TType (type_def,_) -> has_meta_key type_def.t_meta key - | TEnum (enum_def,_) -> has_meta_key enum_def.e_meta key - | _ -> false -;; - - -(* -let dump_meta meta = - List.iter (fun m -> match m with | (k,_,_) -> print_endline ((fst (MetaInfo.to_string k)) ^ "=" ^ (get_meta_string meta k) ) | _ -> () ) meta;; -*) - -let get_class_code class_def key = match class_def.cl_kind with - | KAbstractImpl abstract_def -> - let value = (get_code abstract_def.a_meta key) in - value - | _ -> get_code class_def.cl_meta key -;; - - -(* Add include to source code *) -let add_include writer class_path = - writer#add_include class_path;; - - -(* This gets the class include order correct. In the header files, we forward declare - the class types so the header file does not have any undefined variables. - In the cpp files, we include all the required header files, providing the actual - types for everything. This way there is no problem with circular class references. -*) -let gen_forward_decl writer class_path = - begin - let output = writer#write in - match class_path with - | (["@verbatim"],file) -> writer#write ("#include <" ^ file ^ ">\n"); - | _ -> - let name = fst (remap_class_path class_path) in - output ("HX_DECLARE_CLASS" ^ (string_of_int (List.length name ) ) ^ "("); - List.iter (fun package_part -> output (package_part ^ ",") ) name; - output ( (snd class_path) ^ ")\n") -end;; - -let real_interfaces = -List.filter (function (t,pl) -> - match t, pl with - | { cl_path = ["cpp";"rtti"],_ },[] -> false - | _ -> true -);; - -let rec is_function_expr expr = - match expr.eexpr with - | TParenthesis expr | TMeta(_,expr) -> is_function_expr expr - | TFunction _ -> true - | _ -> false;; - -let is_var_field field = - match field.cf_kind with - | Var _ -> true - | Method MethDynamic -> true - | _ -> false -;; - -let rec has_rtti_interface c interface = - List.exists (function (t,pl) -> - (snd t.cl_path) = interface && (match fst t.cl_path with | ["cpp";"rtti"] -> true | _ -> false ) - ) c.cl_implements || - (match c.cl_super with None -> false | Some (c,_) -> has_rtti_interface c interface);; - -let has_field_integer_lookup class_def = - has_rtti_interface class_def "FieldIntegerLookup";; - -let has_field_integer_numeric_lookup class_def = - has_rtti_interface class_def "FieldNumericIntegerLookup";; - -(* Output required code to place contents in required namespace *) -let gen_open_namespace output class_path = - List.iter (fun namespace -> output ("namespace " ^ namespace ^ "{\n")) (List.map keyword_remap (fst class_path));; - -let gen_close_namespace output class_path = - List.iter - (fun namespace -> output ( "}" ^ " // end namespace " ^ namespace ^"\n")) - (fst class_path);; - -(* The basic types can have default values and are passesby value *) -let is_numeric = function - | "Int" | "Bool" | "Float" | "::haxe::io::Unsigned_char__" | "unsigned char" -> true - | "::cpp::UInt8" | "::cpp::Int8" | "::cpp::Char" - | "::cpp::UInt16" | "::cpp::Int16" - | "::cpp::UInt32" | "::cpp::Int32" - | "::cpp::UInt64" | "::cpp::Int64" - | "::cpp::Float32" | "::cpp::Float64" - | "int" | "bool" | "double" | "float" -> true - | _ -> false - - -let rec remove_parens expression = - match expression.eexpr with - | TParenthesis e -> remove_parens e - | TMeta(_,e) -> remove_parens e - | _ -> expression -;; - - -(* -let rec remove_parens_cast expression = - match expression.eexpr with - | TParenthesis e -> remove_parens_cast e - | TMeta(_,e) -> remove_parens_cast e - | TCast ( e,None) -> remove_parens_cast e - | _ -> expression -;; -*) -let is_interface_type t = - match follow t with - | TInst (klass,params) -> klass.cl_interface - | _ -> false -;; - - -let is_cpp_function_instance haxe_type = - match follow haxe_type with - | TInst (klass,params) -> - (match klass.cl_path with - | ["cpp"] , "Function" -> true - | _ -> false ) - | _ -> false - ;; - - -let is_cpp_function_class haxe_type = - match follow haxe_type with - | TType (klass,params) -> - (match klass.t_path with - | ["cpp"] , "Function" -> true - | _ -> false ) - | _ -> false - ;; - -let is_fromStaticFunction_call func = - match (remove_parens func).eexpr with - | TField (_,FStatic ({cl_path=["cpp"],"Function"},{cf_name="fromStaticFunction"} ) ) -> true - | _ -> false -;; - -let is_addressOf_call func = - match (remove_parens func).eexpr with - | TField (_,FStatic ({cl_path=["cpp"],"Pointer"},{cf_name="addressOf"} ) ) -> true - | _ -> false -;; - -let is_lvalue var = - match (remove_parens var).eexpr with - | TLocal _ -> true - | TField (_,FStatic(_,field) ) | TField (_,FInstance(_,_,field) ) -> is_var_field field - | _ -> false -;; - - - -let is_pointer haxe_type includeRaw = - match follow haxe_type with - | TInst (klass,params) -> - (match klass.cl_path with - | ["cpp"] , "Pointer" - | ["cpp"] , "ConstPointer" - | ["cpp"] , "Function" -> true - | ["cpp"] , "RawPointer" when includeRaw -> true - | ["cpp"] , "RawConstPointer" when includeRaw -> true - | _ -> false ) - | TType (type_def,params) -> - (match type_def.t_path with - | ["cpp"] , "Pointer" - | ["cpp"] , "ConstPointer" - | ["cpp"] , "Function" -> true - | ["cpp"] , "RawPointer" when includeRaw -> true - | ["cpp"] , "RawConstPointer" when includeRaw -> true - | _ -> false ) - | _ -> false - ;; - -let is_dynamic_type_param class_kind = - match class_kind with - | KTypeParameter _ -> true - | _ -> false -;; - -(* Get a string to represent a type. - The "suffix" will be nothing or "_obj", depending if we want the name of the - pointer class or the pointee (_obj class *) -let rec class_string klass suffix params remap = - let type_string = type_string_remap remap in - let join_class_path_remap = if remap then join_class_path_remap else join_class_path in - (match klass.cl_path with - (* Array class *) - | ([],"Array") when is_dynamic_array_param (List.hd params) -> - "cpp::ArrayBase" ^ suffix (* "Dynamic" *) - | ([],"Array") -> (snd klass.cl_path) ^ suffix ^ "< " ^ (String.concat "," - (List.map array_element_type params) ) ^ " >" - (* FastIterator class *) - | (["cpp"],"FastIterator") -> "::cpp::FastIterator" ^ suffix ^ "< " ^ (String.concat "," - (List.map type_string params) ) ^ " >" - | (["cpp"],"Pointer") - | (["cpp"],"ConstPointer") -> - "::cpp::Pointer< " ^ (String.concat "," (List.map type_string params) ) ^ " >" - | (["cpp"],"RawPointer") -> - " " ^ (String.concat "," (List.map type_string params) ) ^ " * " - | (["cpp"],"RawConstPointer") -> - " const " ^ (String.concat "," (List.map type_string params) ) ^ " * " - | (["cpp"],"Function") -> - "::cpp::Function< " ^ (cpp_function_signature_params params) ^ " >" - | _ when is_dynamic_type_param klass.cl_kind -> "Dynamic" - | ([],"#Int") -> "/* # */int" - | (["haxe";"io"],"Unsigned_char__") -> "unsigned char" - | ([],"Class") -> "hx::Class" - | ([],"EnumValue") -> "Dynamic" - | ([],"Null") -> (match params with - | [t] -> - (match follow t with - | TAbstract ({ a_path = [],"Int" },_) - | TAbstract ({ a_path = [],"Float" },_) - | TAbstract ({ a_path = [],"Bool" },_) - | TInst ({ cl_path = [],"Int" },_) - | TInst ({ cl_path = [],"Float" },_) - | TEnum ({ e_path = [],"Bool" },_) -> "Dynamic" - | t when type_has_meta_key t Meta.NotNull -> "Dynamic" - | _ -> "/*NULL*/" ^ (type_string t) ) - | _ -> assert false); - (* Normal class *) - | path when klass.cl_extern && (not (is_internal_class path) )-> - (join_class_path_remap klass.cl_path "::") ^ suffix - | _ -> "::" ^ (join_class_path_remap klass.cl_path "::") ^ suffix - ) -and type_string_suff suffix haxe_type remap = - let type_string = type_string_remap remap in - let join_class_path_remap = if remap then join_class_path_remap else join_class_path in - (match haxe_type with - | TMono r -> (match !r with None -> "Dynamic" ^ suffix | Some t -> type_string_suff suffix t remap) - | TAbstract ({ a_path = ([],"Void") },[]) -> "Void" - | TAbstract ({ a_path = ([],"Bool") },[]) -> "bool" - | TAbstract ({ a_path = ([],"Float") },[]) -> "Float" - | TAbstract ({ a_path = ([],"Int") },[]) -> "int" - | TAbstract( { a_path = ([], "EnumValue") }, _ ) -> "Dynamic" - | TEnum (enum,params) -> "::" ^ (join_class_path_remap enum.e_path "::") ^ suffix - | TInst (klass,params) -> (class_string klass suffix params remap) - | TType (type_def,params) -> - (match type_def.t_path with - | [] , "Null" -> - (match params with - | [t] -> - (match follow t with - | TAbstract ({ a_path = [],"Int" },_) - | TAbstract ({ a_path = [],"Float" },_) - | TAbstract ({ a_path = [],"Bool" },_) - | TInst ({ cl_path = [],"Int" },_) - | TInst ({ cl_path = [],"Float" },_) - | TEnum ({ e_path = [],"Bool" },_) -> "Dynamic" ^ suffix - | t when type_has_meta_key t Meta.NotNull -> "Dynamic" ^ suffix - | _ -> type_string_suff suffix t remap) - | _ -> assert false); - | [] , "Array" -> - (match params with - | [t] when (type_string (follow t) ) = "Dynamic" -> "Dynamic" - | [t] -> "Array< " ^ (type_string (follow t) ) ^ " >" - | _ -> assert false) - | ["cpp"] , "FastIterator" -> - (match params with - | [t] -> "::cpp::FastIterator< " ^ (type_string (follow t) ) ^ " >" - | _ -> assert false) - | ["cpp"] , "Pointer" - | ["cpp"] , "ConstPointer" -> - (match params with - | [t] -> "::cpp::Pointer< " ^ (type_string (follow t) ) ^ " >" - | _ -> assert false) - | ["cpp"] , "RawPointer" -> - (match params with - | [t] -> " " ^ (type_string (follow t) ) ^ " *" - | _ -> assert false) - | ["cpp"] , "RawConstPointer" -> - (match params with - | [t] -> "const " ^ (type_string (follow t) ) ^ " *" - | _ -> assert false) - | ["cpp"] , "Function" -> - "::cpp::Function< " ^ (cpp_function_signature_params params ) ^ " >" - | _ -> type_string_suff suffix (apply_params type_def.t_params params type_def.t_type) remap - ) - | TFun (args,haxe_type) -> "Dynamic" ^ suffix - | TAnon a -> "Dynamic" - (* - (match !(a.a_status) with - | Statics c -> type_string_suff suffix (TInst (c,List.map snd c.cl_params)) - | EnumStatics e -> type_string_suff suffix (TEnum (e,List.map snd e.e_params)) - | _ -> "Dynamic" ^ suffix ) - *) - | TDynamic haxe_type -> "Dynamic" ^ suffix - | TLazy func -> type_string_suff suffix ((!func)()) remap - | TAbstract (abs,pl) when abs.a_impl <> None -> - type_string_suff suffix (Abstract.get_underlying_type abs pl) remap - | TAbstract (abs,pl) -> - "::" ^ (join_class_path_remap abs.a_path "::") ^ suffix - ) - -and type_string_remap remap haxe_type = - type_string_suff "" haxe_type remap - -and type_string haxe_type = - type_string_suff "" haxe_type true - -and array_element_type haxe_type = - match type_string haxe_type with - | x when cant_be_null haxe_type -> x - | x when is_interface_type (follow haxe_type) -> x - | "::String" -> "::String" - | _ -> "::Dynamic" - -and is_dynamic_array_param haxe_type = - if (type_string (follow haxe_type)) = "Dynamic" then true - else (match follow haxe_type with - | TInst (klass,params) -> - (match klass.cl_path with - | ([],"Array") | ([],"Class") | (["cpp"],"FastIterator") - | (["cpp"],"RawPointer") |(["cpp"],"ConstRawPointer") - | (["cpp"],"Pointer") |(["cpp"],"ConstPointer")|(["cpp"],"Function") -> false - | _ -> (match klass.cl_kind with KTypeParameter _ -> true | _ -> false) - ) - | _ -> false - ) -and cpp_function_signature tfun abi = - match follow tfun with - | TFun(args,ret) -> (type_string ret) ^ " " ^ abi ^ "( " ^ (gen_tfun_interface_arg_list args) ^ ")" - | _ -> "void *" - -and cpp_function_signature_params params = match params with - | [t; abi] -> (match follow abi with - | TInst (klass,_) -> cpp_function_signature t (get_meta_string klass.cl_meta Meta.Abi) - | _ -> print_endline (type_string abi); - assert false ) - | _ -> - print_endline ("Params:" ^ (String.concat "," (List.map type_string params) )); - assert false; - -and gen_interface_arg_type_name name opt typ = - let type_str = (type_string typ) in - (* type_str may have already converted Null to Dynamic because of NotNull tag ... *) - (if (opt && (cant_be_null typ) && type_str<>"Dynamic" ) then - "hx::Null< " ^ type_str ^ " > " - else - type_str ) - - - ^ " " ^ (keyword_remap name) -and gen_tfun_interface_arg_list args = - String.concat "," (List.map (fun (name,opt,typ) -> gen_interface_arg_type_name name opt typ) args) -and cant_be_null haxe_type = - is_numeric (type_string haxe_type) || (type_has_meta_key haxe_type Meta.NotNull ) -;; - -let is_object type_string = - not (is_numeric type_string || type_string="::String"); -;; - - - - - -let is_array haxe_type = - match follow haxe_type with - | TInst (klass,params) -> - (match klass.cl_path with - | [] , "Array" -> not (is_dynamic_array_param (List.hd params)) - | _ -> false ) - | TType (type_def,params) -> - (match type_def.t_path with - | [] , "Array" -> not (is_dynamic_array_param (List.hd params)) - | _ -> false ) - | _ -> false - ;; - -let is_array_or_dyn_array haxe_type = - match follow haxe_type with - | TInst (klass,params) -> - (match klass.cl_path with | [] , "Array" -> true | _ -> false ) - | TType (type_def,params) -> - (match type_def.t_path with | [] , "Array" -> true | _ -> false ) - | _ -> false - ;; - - - -let is_array_implementer haxe_type = - match follow haxe_type with - | TInst (klass,params) -> - (match klass.cl_array_access with - | Some _ -> true - | _ -> false ) - | _ -> false - ;; - - -let is_numeric_field field = - match field.cf_kind with - | Var _ -> is_numeric (type_string field.cf_type) - | _ -> false; -;; - - - -let is_static_access obj = - match (remove_parens obj).eexpr with - | TTypeExpr _ -> true - | _ -> false -;; - -let is_native_with_space func = - match (remove_parens func).eexpr with - | TField(obj,field) when is_static_access obj -> - String.contains (get_field_access_meta field Meta.Native) ' ' - | _ -> false -;; - - -let rec is_cpp_function_member func = - match (remove_parens func).eexpr with - | TField(obj,field) when is_cpp_function_instance obj.etype -> true - | TCall(obj,_) -> is_cpp_function_member obj - | _ -> false -;; - - - - -(* Get the type and output it to the stream *) -let gen_type ctx haxe_type = - ctx.ctx_output (type_string haxe_type) -;; - -let member_type ctx field_object member = - let name = (if (is_array field_object.etype) then "::Array" - else (type_string field_object.etype)) ^ "." ^ member in - try ( Hashtbl.find ctx.ctx_class_member_types name ) - with Not_found -> "?";; - -let is_interface obj = is_interface_type obj.etype;; - -let should_implement_field x = not (is_extern_field x);; - -let is_function_member expression = - match (follow expression.etype) with | TFun (_,_) -> true | _ -> false;; - -let is_internal_member member = - match member with - | "__Field" | "__IField" | "__Run" | "__Is" | "__GetClass" | "__GetType" | "__ToString" - | "__s" | "__GetPtr" | "__SetField" | "__length" | "__IsArray" | "__SetThis" | "__Internal" - | "__EnumParams" | "__Index" | "__Tag" | "__GetFields" | "toString" | "__HasField" - | "__GetRealObject" - -> true - | _ -> false;; - - -let is_extern_class class_def = - class_def.cl_extern || (has_meta_key class_def.cl_meta Meta.Extern) || - (match class_def.cl_kind with - | KAbstractImpl abstract_def -> (has_meta_key abstract_def.a_meta Meta.Extern) - | _ -> false ); -;; - - -let is_native_gen_class class_def = - (has_meta_key class_def.cl_meta Meta.NativeGen) || - (match class_def.cl_kind with - | KAbstractImpl abstract_def -> (has_meta_key abstract_def.a_meta Meta.NativeGen) - | _ -> false ); -;; - - -let is_extern_class_instance obj = - match follow obj.etype with - | TInst (klass,params) -> klass.cl_extern - | _ -> false -;; - - -let is_struct_access t = - match follow t with - | TInst (class_def,_) -> (has_meta_key class_def.cl_meta Meta.StructAccess) - | _ -> false -;; - - - -let rec is_dynamic_accessor name acc field class_def = - ( ( acc ^ "_" ^ field.cf_name) = name ) && - ( not (List.exists (fun f -> f.cf_name=name) class_def.cl_ordered_fields) ) - && (match class_def.cl_super with None -> true | Some (parent,_) -> is_dynamic_accessor name acc field parent ) -;; - - -let gen_arg_type_name name default_val arg_type prefix = - let remap_name = keyword_remap name in - let type_str = (type_string arg_type) in - match default_val with - | Some TNull -> (type_str,remap_name) - | Some constant when (cant_be_null arg_type) -> ("hx::Null< " ^ type_str ^ " > ",prefix ^ remap_name) - | Some constant -> (type_str,prefix ^ remap_name) - | _ -> (type_str,remap_name);; - -(* Generate prototype text, including allowing default values to be null *) -let gen_arg name default_val arg_type prefix = - let pair = gen_arg_type_name name default_val arg_type prefix in - (fst pair) ^ " " ^ (snd pair);; - -let rec gen_arg_list arg_list prefix = - String.concat "," (List.map (fun (v,o) -> (gen_arg v.v_name o v.v_type prefix) ) arg_list) - - -let rec gen_tfun_arg_list arg_list = - match arg_list with - | [] -> "" - | [(name,o,arg_type)] -> gen_arg name None arg_type "" - | (name,o,arg_type) :: remaining -> - (gen_arg name None arg_type "") ^ "," ^ (gen_tfun_arg_list remaining) - -(* Check to see if we are the first object in the parent tree to implement a dynamic interface *) -let implement_dynamic_here class_def = - let implements_dynamic c = match c.cl_dynamic with None -> false | _ -> true in - let rec super_implements_dynamic c = match c.cl_super with - | None -> false - | Some (csup, _) -> if (implements_dynamic csup) then true else - super_implements_dynamic csup; - in - ( (implements_dynamic class_def) && (not (super_implements_dynamic class_def) ) );; - - -let gen_hash32 seed str = - let h = ref (Int32.of_int seed) in - let cycle = Int32.of_int 223 in - for i = 0 to String.length str - 1 do - h := Int32.add (Int32.mul !h cycle) (Int32.of_int (int_of_char (String.unsafe_get str i))); - done; - !h -;; - -let gen_hash seed str = - Printf.sprintf "0x%08lx" (gen_hash32 seed str) -;; - -let gen_string_hash str = - let h = gen_hash32 0 str in - Printf.sprintf "\"\\x%02lx\",\"\\x%02lx\",\"\\x%02lx\",\"\\x%02lx\"" - (Int32.shift_right_logical (Int32.shift_left h 24) 24) - (Int32.shift_right_logical (Int32.shift_left h 16) 24) - (Int32.shift_right_logical (Int32.shift_left h 8) 24) - (Int32.shift_right_logical h 24) -;; - - - - -(* Make string printable for c++ code *) -(* Here we know there are no utf8 characters, so use the L"" notation to avoid conversion *) -let escape_stringw s l = - let b = Buffer.create 0 in - Buffer.add_char b 'L'; - Buffer.add_char b '"'; - let skip = ref 0 in - for i = 0 to String.length s - 1 do - if (!skip>0) then begin - skip := !skip -1; - l := !l-1; - end else - match Char.code (String.unsafe_get s i) with - | c when (c>127) -> - let encoded = ((c land 0x3F) lsl 6) lor ( Char.code ((String.unsafe_get s (i+1))) land 0x7F) in - skip := 1; - Buffer.add_string b (Printf.sprintf "\\x%X\"L\"" encoded) - | c when (c < 32) -> Buffer.add_string b (Printf.sprintf "\\x%X\"L\"" c) - | c -> Buffer.add_char b (Char.chr c) - done; - Buffer.add_char b '"'; - Buffer.contents b;; - -let special_to_hex s = - let l = String.length s in - let b = Buffer.create 0 in - for i = 0 to l - 1 do - match Char.code (String.unsafe_get s i) with - | c when (c>127) || (c<32) -> - Buffer.add_string b (Printf.sprintf "\\x%02x\"\"" c) - | c -> Buffer.add_char b (Char.chr c) - done; - Buffer.contents b;; - -let escape_extern s = - let l = String.length s in - let b = Buffer.create 0 in - for i = 0 to l - 1 do - match Char.code (String.unsafe_get s i) with - | c when (c>127) || (c<32) || (c=34) || (c=92) -> - Buffer.add_string b (Printf.sprintf "\\x%02x" c) - | c -> Buffer.add_char b (Char.chr c) - done; - Buffer.contents b;; - - - -let has_utf8_chars s = - let result = ref false in - for i = 0 to String.length s - 1 do - result := !result || ( Char.code (String.unsafe_get s i) > 127 ) - done; - !result;; - -let escape_command s = - let b = Buffer.create 0 in - String.iter (fun ch -> if (ch=='"' || ch=='\\' ) then Buffer.add_string b "\\"; Buffer.add_char b ch ) s; - Buffer.contents b;; - -let str s = - let rec split s plus = - let escaped = Ast.s_escape ~hex:false s in - let hexed = (special_to_hex escaped) in - if (String.length hexed <= 16000 ) then - plus ^ " HX_CSTRING(\"" ^ hexed ^ "\")" - else begin - let len = String.length s in - let half = len lsr 1 in - (split (String.sub s 0 half) plus ) ^ (split (String.sub s half (len-half)) "+" ) - end - in - let escaped = Ast.s_escape ~hex:false s in - let hexed = (special_to_hex escaped) in - if (String.length hexed <= 16000 ) then - "HX_HCSTRING(\"" ^ hexed ^ "\"," ^ (gen_string_hash s) ^ ")" - else - "(" ^ (split s "" ) ^ ")" -;; - -let const_char_star s = - let escaped = Ast.s_escape ~hex:false s in - "\"" ^ special_to_hex escaped ^ "\""; -;; - - - -(* When we are in a "real" object, we refer to ourselves as "this", but - if we are in a local class that is used to generate return values, - we use the fake "__this" pointer. - If we are in an "Anon" object, then the "this" refers to the anon object (eg List iterator) *) -let clear_real_this_ptr ctx dynamic_this = - let old_flag = ctx.ctx_real_this_ptr in - let old_dynamic = ctx.ctx_dynamic_this_ptr in - let old_void = ctx.ctx_real_void in - ctx.ctx_real_this_ptr <- false; - ctx.ctx_dynamic_this_ptr <- dynamic_this; - fun () -> ( - ctx.ctx_real_this_ptr <- old_flag; - ctx.ctx_dynamic_this_ptr <- old_dynamic; - ctx.ctx_real_void <- old_void; - ) -;; - - -(* Generate temp variable names *) -let next_anon_function_name ctx = - ctx.ctx_static_id_curr <- ctx.ctx_static_id_curr + 1; - "_Function_" ^ (string_of_int ctx.ctx_static_id_depth) ^"_"^ (string_of_int ctx.ctx_static_id_curr);; - -let use_anon_function_name ctx = - ctx.ctx_static_id_used <- ctx.ctx_static_id_used + 1; - "_Function_" ^ (string_of_int ctx.ctx_static_id_depth) ^"_"^ (string_of_int ctx.ctx_static_id_used);; - -let push_anon_names ctx = - let old_used = ctx.ctx_static_id_used in - let old_curr = ctx.ctx_static_id_curr in - let old_depth = ctx.ctx_static_id_depth in - ctx.ctx_static_id_used <- 0; - ctx.ctx_static_id_curr <- 0; - ctx.ctx_static_id_depth <- ctx.ctx_static_id_depth + 1; - ( function () -> ( - ctx.ctx_static_id_used <- old_used; - ctx.ctx_static_id_curr <- old_curr; - ctx.ctx_static_id_depth <- old_depth; ) ) -;; - -let get_switch_var ctx = - ctx.ctx_switch_id <- ctx.ctx_switch_id + 1; - "_switch_" ^ (string_of_int ctx.ctx_switch_id) - - -(* If you put on the "-debug" flag, you get extra comments in the source code *) -let debug_expression expression type_too = - "/* " ^ Type.s_expr_kind expression ^ (if (type_too) then " = " ^ (type_string expression.etype) else "") ^ " */";; - -(* This is like the Type.iter, but also keeps the "retval" flag up to date *) -let rec iter_retval f retval e = - match e.eexpr with - | TConst _ - | TLocal _ - | TBreak - | TContinue - | TTypeExpr _ -> - () - | TArray (e1,e2) - | TBinop (_,e1,e2) -> - f true e1; - f true e2; - | TWhile (e1,e2,_) -> - f true e1; - f false e2; - | TFor (_,e1,e2) -> - f true e1; - f false e2; - | TThrow e - | TField (e,_) - | TEnumParameter (e,_,_) - | TUnop (_,_,e) -> - f true e - | TParenthesis e | TMeta(_,e) -> - f retval e - | TBlock expr_list when retval -> - let rec return_last = function - | [] -> () - | expr :: [] -> f true expr - | expr :: exprs -> f false expr; return_last exprs in - return_last expr_list - | TArrayDecl el - | TNew (_,_,el) -> - List.iter (f true ) el - | TBlock el -> - List.iter (f false ) el - | TObjectDecl fl -> - List.iter (fun (_,e) -> f true e) fl - | TCall (e,el) -> - f true e; - List.iter (f true) el - | TVar (_,eo) -> - (match eo with None -> () | Some e -> f true e) - | TFunction fu -> - f false fu.tf_expr - | TIf (e,e1,e2) -> - f true e; - f retval e1; - (match e2 with None -> () | Some e -> f retval e) - | TSwitch (e,cases,def) -> - f true e; - List.iter (fun (el,e2) -> List.iter (f true) el; f retval e2) cases; - (match def with None -> () | Some e -> f retval e) -(* | TMatch (e,_,cases,def) -> - f true e; - List.iter (fun (_,_,e) -> f false e) cases; - (match def with None -> () | Some e -> f false e) *) - | TTry (e,catches) -> - f retval e; - List.iter (fun (_,e) -> f false e) catches - | TReturn eo -> - (match eo with None -> () | Some e -> f true e) - | TCast (e,None) -> - f retval e - | TCast (e,_) -> - f true e -;; - - -(* Convert an array to a comma separated list of values *) -let array_arg_list inList = - let i = ref (0-1) in - String.concat "," (List.map (fun _ -> incr i; "inArgs[" ^ (string_of_int !i) ^ "]" ) inList) - -let list_num l = string_of_int (List.length l);; - - -let only_int_cases cases = - match cases with - | [] -> false - | _ -> - not (List.exists (fun (cases,expression) -> - List.exists (fun case -> match case.eexpr with TConst (TInt _) -> false | _ -> true ) cases - ) cases );; - -(* See if there is a haxe break statement that will be swollowed by c++ break *) -exception BreakFound;; - -let contains_break expression = - try ( - let rec check_all expression = - Type.iter (fun expr -> match expr.eexpr with - | TBreak -> raise BreakFound - | TFor _ - | TFunction _ - | TWhile (_,_,_) -> () - | _ -> check_all expr; - ) expression in - check_all expression; - false; - ) with BreakFound -> true;; - - -(* Decide is we should look the field up by name *) -let dynamic_internal = function | "__Is" -> true | _ -> false - - -let rec is_null expr = - match expr.eexpr with - | TConst TNull -> true - | TParenthesis expr | TMeta (_,expr) -> is_null expr - | TCast (e,None) -> is_null e - | _ -> false -;; - - -let find_undeclared_variables_ctx ctx undeclared declarations this_suffix allow_this expression = - let output = ctx.ctx_output in - let rec find_undeclared_variables undeclared declarations this_suffix allow_this expression = - match expression.eexpr with - | TVar (tvar,optional_init) -> - Hashtbl.add declarations (keyword_remap tvar.v_name) (); - if (ctx.ctx_debug_level>1) then - output ("/* found var " ^ tvar.v_name ^ "*/ "); - (match optional_init with - | Some expression -> find_undeclared_variables undeclared declarations this_suffix allow_this expression - | _ -> ()) - | TFunction func -> List.iter ( fun (tvar, opt_val) -> - if (ctx.ctx_debug_level>1) then - output ("/* found arg " ^ tvar.v_name ^ " = " ^ (type_string tvar.v_type) ^ " */ "); - Hashtbl.add declarations (keyword_remap tvar.v_name) () ) func.tf_args; - find_undeclared_variables undeclared declarations this_suffix false func.tf_expr - | TTry (try_block,catches) -> - find_undeclared_variables undeclared declarations this_suffix allow_this try_block; - List.iter (fun (tvar,catch_expt) -> - let old_decs = Hashtbl.copy declarations in - Hashtbl.add declarations (keyword_remap tvar.v_name) (); - find_undeclared_variables undeclared declarations this_suffix allow_this catch_expt; - Hashtbl.clear declarations; - Hashtbl.iter ( Hashtbl.add declarations ) old_decs - ) catches; - | TLocal tvar -> - let name = keyword_remap tvar.v_name in - if not (Hashtbl.mem declarations name) then - Hashtbl.replace undeclared name (type_string expression.etype) -(* | TMatch (condition, enum, cases, default) -> - find_undeclared_variables undeclared declarations this_suffix allow_this condition; - List.iter (fun (case_ids,params,expression) -> - let old_decs = Hashtbl.copy declarations in - (match params with - | None -> () - | Some l -> List.iter (fun (opt_var) -> - match opt_var with | Some v -> Hashtbl.add declarations (keyword_remap v.v_name) () | _ -> () ) - l ); - find_undeclared_variables undeclared declarations this_suffix allow_this expression; - Hashtbl.clear declarations; - Hashtbl.iter ( Hashtbl.add declarations ) old_decs - ) cases; - (match default with | None -> () - | Some expr -> - find_undeclared_variables undeclared declarations this_suffix allow_this expr; - ); *) - | TFor (tvar, init, loop) -> - let old_decs = Hashtbl.copy declarations in - Hashtbl.add declarations (keyword_remap tvar.v_name) (); - find_undeclared_variables undeclared declarations this_suffix allow_this init; - find_undeclared_variables undeclared declarations this_suffix allow_this loop; - Hashtbl.clear declarations; - Hashtbl.iter ( Hashtbl.add declarations ) old_decs - | TConst TSuper - | TConst TThis -> - if ((not (Hashtbl.mem declarations "this")) && allow_this) then - Hashtbl.replace undeclared "this" (type_string_suff this_suffix expression.etype true) - | TBlock expr_list -> - let old_decs = Hashtbl.copy declarations in - List.iter (find_undeclared_variables undeclared declarations this_suffix allow_this ) expr_list; - (* what is the best way for this ? *) - Hashtbl.clear declarations; - Hashtbl.iter ( Hashtbl.add declarations ) old_decs - | _ -> Type.iter (find_undeclared_variables undeclared declarations this_suffix allow_this) expression - in - find_undeclared_variables undeclared declarations this_suffix allow_this expression -;; - - -let rec is_dynamic_in_cpp ctx expr = - let expr_type = type_string ( match follow expr.etype with TFun (args,ret) -> ret | _ -> expr.etype) in - ctx.ctx_dbgout ( "/* idic: " ^ expr_type ^ " */" ); - if ( expr_type="Dynamic" || expr_type="cpp::ArrayBase") then - true - else begin - let result = ( - match expr.eexpr with - | TEnumParameter( obj, _, index ) -> - true (* TODO? *) - | TField( obj, field ) -> - let name = field_name field in - ctx.ctx_dbgout ("/* ?tfield "^name^" */"); - if (is_dynamic_member_lookup_in_cpp ctx obj field) then - ( - ctx.ctx_dbgout "/* tf=dynobj */"; - true - ) - else if (is_dynamic_member_return_in_cpp ctx obj field) then - ( - ctx.ctx_dbgout "/* tf=dynret */"; - true - ) - else - ( - ctx.ctx_dbgout "/* tf=notdyn */"; - false - ) - | TConst TThis when ((not ctx.ctx_real_this_ptr) && ctx.ctx_dynamic_this_ptr) -> - ctx.ctx_dbgout ("/* dthis */"); true - | TArray (obj,index) -> let dyn = is_dynamic_in_cpp ctx obj in - ctx.ctx_dbgout ("/* aidr:" ^ (if dyn then "Dyn" else "Not") ^ " */"); - dyn; - | TTypeExpr _ -> false - | TCall(func,args) -> - (match follow func.etype with - | TFun (args,ret) -> ctx.ctx_dbgout ("/* ret = "^ (type_string ret) ^" */"); - is_dynamic_in_cpp ctx func - | _ -> ctx.ctx_dbgout "/* not TFun */"; true - ); - | TParenthesis(expr) | TMeta(_,expr) -> is_dynamic_in_cpp ctx expr - | TCast (e,None) -> (type_string expr.etype) = "Dynamic" - | TLocal { v_name = "__global__" } -> false - | TConst TNull -> true - | _ -> ctx.ctx_dbgout "/* other */"; false (* others ? *) ) - in - ctx.ctx_dbgout (if result then "/* Y */" else "/* N */" ); - result - end - -and is_dynamic_member_lookup_in_cpp ctx field_object field = - let member = field_name field in - ctx.ctx_dbgout ("/*mem."^member^".*/"); - if (is_internal_member member) then false else - if (is_pointer field_object.etype true) then false else - if (match field_object.eexpr with | TTypeExpr _ -> ctx.ctx_dbgout "/*!TTypeExpr*/"; true | _ -> false) then false else - if (is_dynamic_in_cpp ctx field_object) then true else - if (is_array field_object.etype) then false else ( - let tstr = type_string field_object.etype in - ctx.ctx_dbgout ("/* ts:"^tstr^"*/"); - match tstr with - (* Internal classes have no dynamic members *) - | "::String" | "Null" | "::hx::Class" | "::Enum" | "::Math" | "::ArrayAccess" -> ctx.ctx_dbgout ("/* ok:" ^ (type_string field_object.etype) ^ " */"); false - | "Dynamic" -> true - | name -> - let full_name = name ^ "." ^ member in - ctx.ctx_dbgout ("/* t:" ^ full_name ^ " */"); - try ( let mem_type = (Hashtbl.find ctx.ctx_class_member_types full_name) in - ctx.ctx_dbgout ("/* =" ^ mem_type ^ "*/"); - false ) - with Not_found -> not (is_extern_class_instance field_object) - ) -and is_dynamic_member_return_in_cpp ctx field_object field = - let member = field_name field in - if (is_array field_object.etype) then false else - if (is_pointer field_object.etype true) then false else - if (is_internal_member member) then false else - match field_object.eexpr with - | TTypeExpr t -> - let full_name = "::" ^ (join_class_path (t_path t) "::" ) ^ "." ^ member in - ctx.ctx_dbgout ("/*static:"^ full_name^"*/"); - ( try ( let mem_type = (Hashtbl.find ctx.ctx_class_member_types full_name) in mem_type="Dynamic"||mem_type="cpp::ArrayBase" ) - with Not_found -> true ) - | _ -> - let tstr = type_string field_object.etype in - (match tstr with - (* Internal classes have no dynamic members *) - | "::String" | "Null" | "::hx::Class" | "::Enum" | "::Math" | "::ArrayAccess" -> false - | "Dynamic" | "cpp::ArrayBase" -> ctx.ctx_dbgout "/*D*/"; true - | name -> - let full_name = name ^ "." ^ member in - ctx.ctx_dbgout ("/*R:"^full_name^"*/"); - try ( let mem_type = (Hashtbl.find ctx.ctx_class_member_types full_name) in mem_type="Dynamic"||mem_type="cpp::ArrayBase" ) - with Not_found -> true ) -;; - -let cast_if_required ctx expr to_type = - let expr_type = (type_string expr.etype) in - ctx.ctx_dbgout ( "/* cir: " ^ expr_type ^ " */" ); - if (is_dynamic_in_cpp ctx expr) then - ctx.ctx_output (".Cast< " ^ to_type ^ " >()" ) -;; - - -let is_matching_interface_type t0 t1 = - (match (follow t0),(follow t1) with - | TInst (k0,_), TInst(k1,_) -> k0==k1 - | _ -> false - ) -;; - - - -let default_value_string = function - | TInt i -> Printf.sprintf "%ld" i - | TFloat float_as_string -> "((Float)" ^ float_as_string ^ ")" - | TString s -> str s - | TBool b -> (if b then "true" else "false") - | TNull -> "null()" - | _ -> "/* Hmmm */" -;; - -let generate_default_values ctx args prefix = - List.iter ( fun (v,o) -> let type_str = type_string v.v_type in - let name = (keyword_remap v.v_name) in - match o with - | Some TNull -> () - | Some const -> - ctx.ctx_output (type_str ^ " " ^ name ^ " = " ^ prefix ^ name ^ ".Default(" ^ - (default_value_string const) ^ ");\n") - | _ -> () ) args;; - -let return_type_string t = - match t with - | TFun (_,ret) -> type_string ret - | _ -> "" -;; - - -let get_return_type field = - match follow field.cf_type with - | TFun (_,return_type) -> return_type - | _ -> raise Not_found -;; - - - -let has_default_values args = - List.exists ( fun (_,o) -> match o with - | Some TNull -> false - | Some _ -> true - | _ -> false ) args ;; - -exception PathFound of string;; - - -let strip_file ctx file = (match Common.defined ctx Common.Define.AbsolutePath with - | true -> file - | false -> let flen = String.length file in - (* Not quite right - should probably test is file exists *) - try - List.iter (fun path -> - let plen = String.length path in - if (flen>plen && path=(String.sub file 0 plen )) - then raise (PathFound (String.sub file plen (flen-plen)) ) ) - (ctx.class_path @ ctx.std_path); - file; - with PathFound tail -> - tail) -;; - -let hx_stack_push ctx output clazz func_name pos = - if ctx.ctx_debug_level > 0 then begin - let stripped_file = strip_file ctx.ctx_common pos.pfile in - let qfile = "\"" ^ (Ast.s_escape stripped_file) ^ "\"" in - ctx.ctx_file_info := PMap.add stripped_file pos.pfile !(ctx.ctx_file_info); - if (ctx.ctx_debug_level>0) then begin - let hash_class_func = gen_hash 0 (clazz^"."^func_name) in - let hash_file = gen_hash 0 stripped_file in - output ("HX_STACK_FRAME(\"" ^ clazz ^ "\",\"" ^ func_name ^ "\"," ^ hash_class_func ^ ",\"" ^ - clazz ^ "." ^ func_name ^ "\"," ^ qfile ^ "," ^ - (string_of_int (Lexer.get_error_line pos) ) ^ "," ^ hash_file ^ ")\n") - end - end -;; - - -(* - This is the big one. - Once you get inside a function, all code is generated (recursively) as a "expression". - "retval" is tracked to determine whether the value on an expression is actually used. - eg, if the result of a block (ie, the last expression in the list) is used, then - we have to do some funky stuff to generate a local function. - Some things that change less often are stored in the context and are extracted - at the top for simplicity. -*) - -let gen_expression_tree ctx retval expression_tree set_var tail_code = - let writer = ctx.ctx_writer in - let output_i = writer#write_i in - let output = ctx.ctx_output in - - let rec define_local_function_ctx func_name func_def = - let remap_this = function | "this" -> "__this" | other -> other in - let rec define_local_function func_name func_def = - let declarations = Hashtbl.create 0 in - let undeclared = Hashtbl.create 0 in - (* '__global__', '__cpp__' are always defined *) - Hashtbl.add declarations "__global__" (); - Hashtbl.add declarations "__cpp__" (); - Hashtbl.add declarations "__trace" (); - (* Add args as defined variables *) - List.iter ( fun (arg_var, opt_val) -> - if (ctx.ctx_debug_level>1) then - output ("/* found arg " ^ arg_var.v_name ^ " = " ^ (type_string arg_var.v_type) ^" */ "); - Hashtbl.add declarations (keyword_remap arg_var.v_name) () ) func_def.tf_args; - find_undeclared_variables_ctx ctx undeclared declarations "" true func_def.tf_expr; - - let has_this = Hashtbl.mem undeclared "this" in - if (has_this) then Hashtbl.remove undeclared "this"; - let typed_vars = hash_iterate undeclared (fun key value -> value ^ "," ^ (keyword_remap key) ) in - let func_name_sep = func_name ^ (if List.length typed_vars > 0 then "," else "") in - output_i ("HX_BEGIN_LOCAL_FUNC_S" ^ (list_num typed_vars) ^ "(" ^ - (if has_this then "hx::LocalThisFunc," else "hx::LocalFunc,") ^ func_name_sep ^ - (String.concat "," typed_vars) ^ ")\n" ); - output_i ("int __ArgCount() const { return " ^ (string_of_int (List.length func_def.tf_args)) ^"; }\n"); - - (* actual function, called "run" *) - let args_and_types = List.map - (fun (v,_) -> (type_string v.v_type) ^ " " ^ (keyword_remap v.v_name) ) func_def.tf_args in - let block = is_block func_def.tf_expr in - let func_type = type_string func_def.tf_type in - output_i (func_type ^ " run(" ^ (gen_arg_list func_def.tf_args "__o_") ^ ")"); - - let close_defaults = - if (has_default_values func_def.tf_args) then begin - writer#begin_block; - output_i ""; - generate_default_values ctx func_def.tf_args "__o_"; - output_i ""; - true; - end - else - false in - - - let pop_real_this_ptr = clear_real_this_ptr ctx true in - - writer#begin_block; - if (ctx.ctx_debug_level>0) then begin - hx_stack_push ctx output_i "*" func_name func_def.tf_expr.epos; - if (has_this && ctx.ctx_debug_level>0) then - output_i ("HX_STACK_THIS(__this.mPtr)\n"); - List.iter (fun (v,_) -> output_i ("HX_STACK_ARG(" ^ (keyword_remap v.v_name) ^ ",\"" ^ v.v_name ^"\")\n") ) - func_def.tf_args; - end; - - if (block) then begin - output_i ""; - gen_expression false func_def.tf_expr; - output_i "return null();\n"; - end else begin - (* Save old values, and equalize for new input ... *) - let pop_names = push_anon_names ctx in - - find_local_functions_and_return_blocks_ctx false func_def.tf_expr; - - (match func_def.tf_expr.eexpr with - | TReturn (Some return_expression) when (func_type<>"Void") -> - output_i "return "; - gen_expression true return_expression; - | TReturn (Some return_expression) -> - output_i ""; - gen_expression false return_expression; - | _ -> - output_i ""; - gen_expression false (to_block func_def.tf_expr); - ); - output ";\n"; - output_i "return null();\n"; - pop_names(); - end; - writer#end_block; - - if close_defaults then writer#end_block; - pop_real_this_ptr(); - - let return = if (type_string func_def.tf_type ) = "Void" then "(void)" else "return" in - output_i ("HX_END_LOCAL_FUNC" ^ (list_num args_and_types) ^ "(" ^ return ^ ")\n\n"); - - Hashtbl.replace ctx.ctx_local_function_args func_name - (if (ctx.ctx_real_this_ptr) then - String.concat "," (hash_keys undeclared) - else - String.concat "," (List.map remap_this (hash_keys undeclared)) ) - in - define_local_function func_name func_def - - and find_local_functions_and_return_blocks_ctx retval expression = - let rec find_local_functions_and_return_blocks retval expression = - match expression.eexpr with - | TBlock _ -> - if (retval) then begin - define_local_return_block_ctx expression (next_anon_function_name ctx) true; - end (* else we are done *) - | TTry (_, _) - | TSwitch (_, _, _) when retval -> - define_local_return_block_ctx expression (next_anon_function_name ctx) true; - | TObjectDecl ( ("fileName" , { eexpr = (TConst (TString file)) }) :: - ("lineNumber" , { eexpr = (TConst (TInt line)) }) :: - ("className" , { eexpr = (TConst (TString class_name)) }) :: - ("methodName", { eexpr = (TConst (TString meth)) }) :: [] ) -> () - | TObjectDecl decl_list -> - let name = next_anon_function_name ctx in - define_local_return_block_ctx expression name true; - | TFunction func -> - let func_name = next_anon_function_name ctx in - output "\n"; - define_local_function_ctx func_name func - | TField (obj,_) | TEnumParameter (obj,_,_) when (is_null obj) -> ( ) - | TArray (obj,_) when (is_null obj) -> ( ) - | TIf ( _ , _ , _ ) when retval -> (* ? operator style *) - iter_retval find_local_functions_and_return_blocks retval expression - | TSwitch (_, _, _) when retval -> ( ) - (* | TMatch ( cond , _, _, _) *) - | TWhile ( cond , _, _ ) - | TIf ( cond , _, _ ) - | TSwitch ( cond , _, _) -> iter_retval find_local_functions_and_return_blocks true cond - | _ -> iter_retval find_local_functions_and_return_blocks retval expression - in find_local_functions_and_return_blocks retval expression - - and define_local_return_block_ctx expression name retval = - let check_this = function | "this" when not ctx.ctx_real_this_ptr -> "__this" | x -> x in - let rec define_local_return_block expression = - let declarations = Hashtbl.create 0 in - let undeclared = Hashtbl.create 0 in - (* '__global__' is always defined *) - Hashtbl.add declarations "__global__" (); - Hashtbl.add declarations "__cpp__" (); - Hashtbl.add declarations "__trace" (); - find_undeclared_variables_ctx ctx undeclared declarations "_obj" true expression; - - let vars = (hash_keys undeclared) in - let args = String.concat "," (List.map check_this (hash_keys undeclared)) in - Hashtbl.replace ctx.ctx_local_return_block_args name args; - output_i ("struct " ^ name); - writer#begin_block; - let ret_type = if (not retval) then "Void" else - match expression.eexpr with - | TObjectDecl _ -> "Dynamic" - | _ -> type_string expression.etype in - (* TODO - analyse usage *) - let pass_by_value name = (String.length name >=5 ) && (String.sub name 0 5 = "_this") in - output_i ("inline static " ^ ret_type ^ " Block( "); - output (String.concat "," ( - (List.map - (fun var -> - let var_type = Hashtbl.find undeclared var in - (* Args passed into inline-block should be references, so they can be changed. - Fake 'this' pointers can't be changed, so needn't be references *) - match var with - | "this" -> "hx::ObjectPtr< " ^ var_type ^ " > __this" - | name when (pass_by_value name) -> var_type ^ " " ^ name - | name -> var_type ^ " &" ^name - ) vars) ) ); - output (")"); - let return_data = ret_type <> "Void" in - writer#begin_block; - hx_stack_push ctx output_i "*" "closure" expression.epos; - output_i ""; - - let pop_real_this_ptr = clear_real_this_ptr ctx false in - (match expression.eexpr with - | TObjectDecl decl_list -> - writer#begin_block; - output_i "hx::Anon __result = hx::Anon_obj::Create();\n"; - let pop_names = push_anon_names ctx in - List.iter (function (name,value) -> - find_local_functions_and_return_blocks_ctx true value; - output_i ( "__result->Add(" ^ (str name) ^ " , "); - gen_expression true value; - output (if is_function_expr value then ",true" else ",false" ); - output (");\n"); - ) decl_list; - pop_names(); - output_i "return __result;\n"; - writer#end_block; - | TBlock _ -> - ctx.ctx_return_from_block <- return_data; - ctx.ctx_return_from_internal_node <- false; - gen_expression false expression; - | TCall(func,args) -> - writer#begin_block; - let pop_names = push_anon_names ctx in - find_local_functions_and_return_blocks_ctx true func; - List.iter (find_local_functions_and_return_blocks_ctx true) args; - ctx.ctx_tcall_expand_args <- true; - gen_expression return_data expression; - output ";\n"; - pop_names(); - writer#end_block; - | _ -> - ctx.ctx_return_from_block <- false; - ctx.ctx_return_from_internal_node <- return_data; - gen_expression false (to_block expression); - ); - output_i "return null();\n"; - writer#end_block; - pop_real_this_ptr(); - writer#end_block_line; - output ";\n"; - in - define_local_return_block expression - - - and gen_expression retval expression = - let calling = ctx.ctx_calling in - ctx.ctx_calling <- false; - let assigning = ctx.ctx_assigning in - ctx.ctx_assigning <- false; - let return_from_block = ctx.ctx_return_from_block in - ctx.ctx_return_from_block <- false; - let tcall_expand_args = ctx.ctx_tcall_expand_args in - ctx.ctx_tcall_expand_args <- false; - let return_from_internal_node = ctx.ctx_return_from_internal_node in - ctx.ctx_return_from_internal_node <- false; - let dump_src_pos = ctx.ctx_dump_src_pos in - ctx.ctx_dump_src_pos <- (fun() -> ()); - - (* Annotate source code with debug - can get a bit verbose. Mainly for debugging code gen, - rather than the run time *) - if (ctx.ctx_debug_level>1) then begin - (*if calling then output "/* Call */";*) - (*if ctx.ctx_real_this_ptr then output "/* this */" else output "/* FAKE __this */";*) - output (debug_expression expression (ctx.ctx_debug_level>1) ); - end; - - (* Write comma separated list of variables - useful for function args. *) - let rec gen_expression_list expressions = - (match expressions with - | [] -> () - | [single] -> gen_expression true single - | first :: remaining -> - gen_expression true first; - output ","; - gen_expression_list remaining - ) in - - let rec gen_bin_op_string expr1 op expr2 = - let cast = (match op with - | ">>" | "<<" | "&" | "|" | "^" -> "int(" - | "&&" | "||" -> "bool(" - | "/" -> "Float(" - | _ -> "") in - if (op <> "=") then output "("; - if ( cast <> "") then output cast; - gen_expression true expr1; - if ( cast <> "") then output ")"; - - output (" " ^ op ^ " "); - - if ( cast <> "") then output cast; - gen_expression true expr2; - if ( cast <> "") then output ")"; - if (op <> "=") then output ")"; - in - let rec is_const_string_term expr = - match expr.eexpr with - | TConst( TString _ ) -> true - | TBinop (OpAdd,e1,e2) -> (is_const_string_term e1) && (is_const_string_term e2 ) - | _ -> false - in - let rec combine_string_terms expr = - match expr.eexpr with - | TConst( TString s ) -> s - | TBinop (OpAdd,e1,e2) -> (combine_string_terms e1) ^ (combine_string_terms e2 ) - | _ -> "" - in - let rec gen_bin_op op expr1 expr2 = - match op with - | Ast.OpAdd when (is_const_string_term expr1) && (is_const_string_term expr2) -> - output (str ((combine_string_terms expr1) ^ (combine_string_terms expr2)) ) - | Ast.OpAssign -> ctx.ctx_assigning <- true; - gen_bin_op_string expr1 "=" expr2 - | Ast.OpUShr -> - output "hx::UShr("; - gen_expression true expr1; - output ","; - gen_expression true expr2; - output ")"; - | Ast.OpMod -> - output "hx::Mod("; - gen_expression true expr1; - output ","; - gen_expression true expr2; - output ")"; - - | Ast.OpAssignOp bin_op -> - output (match bin_op with - | Ast.OpAdd -> "hx::AddEq(" - | Ast.OpMult -> "hx::MultEq(" - | Ast.OpDiv -> "hx::DivEq(" - | Ast.OpSub -> "hx::SubEq(" - | Ast.OpAnd -> "hx::AndEq(" - | Ast.OpOr -> "hx::OrEq(" - | Ast.OpXor -> "hx::XorEq(" - | Ast.OpShl -> "hx::ShlEq(" - | Ast.OpShr -> "hx::ShrEq(" - | Ast.OpUShr -> "hx::UShrEq(" - | Ast.OpMod -> "hx::ModEq(" - | _ -> error "Unknown OpAssignOp" expression.epos ); - ctx.ctx_assigning <- true; - gen_expression true expr1; - output ","; - gen_expression true expr2; - output ")" - | Ast.OpNotEq -> gen_bin_op_string expr1 "!=" expr2 - | Ast.OpEq -> gen_bin_op_string expr1 "==" expr2 - | _ -> gen_bin_op_string expr1 (Ast.s_binop op) expr2 - in - - let gen_array_cast cast_name real_type call = - output (cast_name ^ "< " ^ real_type ^ " >" ^ call) - in - let rec check_array_element_cast array_type cast_name call = - match follow array_type with - | TInst (klass,[element]) -> - ( match type_string element with - | _ when is_struct_access element -> () - | x when cant_be_null element -> () - | _ when is_interface_type element -> () - | "::String" | "Dynamic" -> () - | real_type -> gen_array_cast cast_name real_type call - ) - | TAbstract (abs,pl) when abs.a_impl <> None -> - check_array_element_cast (Abstract.get_underlying_type abs pl) cast_name call - | _ -> () - in - let rec check_array_cast array_type = - match follow array_type with - | x when is_interface_type x -> () - | TInst (klass,[element]) -> - let name = type_string element in - if ( is_object name && not (is_interface_type element) ) then - gen_array_cast ".StaticCast" "Array" "()" - else - gen_array_cast ".StaticCast" (type_string array_type) "()" - | TAbstract (abs,pl) when abs.a_impl <> None -> - check_array_cast (Abstract.get_underlying_type abs pl) - | _ -> () - in - - let rec gen_tfield field_object field = - let member = (field_name field) in - let remap_name = keyword_remap member in - let already_dynamic = ref false in - (match field_object.eexpr with - (* static access ... *) - | TTypeExpr type_def -> - (match get_field_access_meta field Meta.Native with - | "" -> - let class_name = "::" ^ (join_class_path_remap (t_path type_def) "::" ) in - if (class_name="::String") then - output ("::String::" ^ remap_name) - else - output (class_name ^ "_obj::" ^ remap_name); - | native -> output native - ) - (* Special internal access *) - | TLocal { v_name = "__global__" } -> - output ("::" ^ member ) - | TConst TSuper -> output (if ctx.ctx_real_this_ptr then "this" else "__this"); - output ("->super::" ^ remap_name) - | TConst TThis when ctx.ctx_real_this_ptr -> output ( "this->" ^ remap_name ) - | TConst TNull -> output "null()" - | _ -> - gen_expression true field_object; - ctx.ctx_dbgout "/* TField */"; - (* toString is the only internal member that can be set... *) - let settingInternal = assigning && member="toString" in - let isString = (type_string field_object.etype)="::String" in - if (is_struct_access field_object.etype) then - output ( "." ^ member ) - else if (is_internal_member member && not settingInternal) then begin - output ( (if isString then "." else "->") ^ member ); - end else if (settingInternal || is_dynamic_member_lookup_in_cpp ctx field_object field) then begin - if assigning then - output ( "->__FieldRef(" ^ (str member) ^ ")" ) - else - output ( "->__Field(" ^ (str member) ^ ", hx::paccDynamic )" ); - already_dynamic := true; - end else begin - if (isString) then - output ( "." ^ remap_name ) - else begin - cast_if_required ctx field_object (type_string field_object.etype); - let remap_name = if (type_string field_object.etype)="cpp::ArrayBase" then - match remap_name with - | "length" -> remap_name - | _ -> "__" ^ remap_name - else - remap_name - in - output ( "->" ^ remap_name ); - if (calling && (is_array field_object.etype) && remap_name="iterator" ) then - check_array_element_cast field_object.etype "Fast" ""; - - already_dynamic := (match field with - | FInstance(_,_,var) when is_var_field var -> true - | _ -> false); - end; - end; - ); - if ( (not !already_dynamic) && (not calling) && (not assigning) && (is_function_member expression) ) then - output "_dyn()"; - in - let gen_local_block_call () = - let func_name = use_anon_function_name ctx in ( - try - output ( func_name ^ "::Block(" ^ - (Hashtbl.find ctx.ctx_local_return_block_args func_name) ^ ")" ) - with Not_found -> - (*error ("Block function " ^ func_name ^ " not found" ) expression.epos;*) - output ("/* Block function " ^ func_name ^ " not found */" ); - ) - in - - match expression.eexpr with - | TConst TNull when not retval -> - output "Dynamic()"; - | TCall (func, arg_list) when (match func.eexpr with - | TLocal { v_name = "__cpp__" } -> true - | _ -> false) -> - ( match arg_list with - | [{ eexpr = TConst (TString code) }] -> output (format_code code); - | ({ eexpr = TConst (TString code) } as ecode) :: tl -> - Codegen.interpolate_code ctx.ctx_common (format_code code) tl output (gen_expression true) ecode.epos - | _ -> error "__cpp__'s first argument must be a string" func.epos; - ) - | TCall (func, arg_list) when tcall_expand_args-> - let arg_string = ref "" in - let idx = ref 0 in - List.iter (fun arg -> - let a_name = "__a" ^ string_of_int(!idx) in - arg_string := !arg_string ^ (if !arg_string<>"" then "," else "") ^ a_name; - idx := !idx + 1; - output_i ( (type_string arg.etype) ^ " " ^ a_name ^ " = "); - gen_expression true arg; - output ";\n"; - ) arg_list; - output_i (if retval then "return " else ""); - ctx.ctx_calling <- true; - gen_expression true func; - output ("(" ^ !arg_string ^ ");\n"); - | TCall (func, arg_list) when is_fromStaticFunction_call func -> - (match arg_list with - | [ {eexpr = TField( _, FStatic(klass,field)) } ] -> - let signature = cpp_function_signature field.cf_type "" in - let name = keyword_remap field.cf_name in - let void_cast = has_meta_key field.cf_meta Meta.Void in - output ("::cpp::Function< " ^ signature ^">("); - if (void_cast) then output "hx::AnyCast("; - output ("&::" ^(join_class_path klass.cl_path "::")^ "_obj::" ^ name ); - if (void_cast) then output ")"; - output (" )"); - | _ -> error "fromStaticFunction must take a static function" expression.epos; - ) - - | TCall (func, [arg]) when is_addressOf_call func && not (is_lvalue arg) -> - error "addressOf must take a local or member variable" expression.epos; - - | TCall (func, arg_list) -> - let rec is_variable e = match e.eexpr with - | TField _ | TEnumParameter _ -> false - | TLocal { v_name = "__global__" } -> false - | TParenthesis p | TMeta(_,p) -> is_variable p - | _ -> true - in - let expr_type = type_string expression.etype in - let rec is_fixed_override e = (not (is_scalar expr_type)) && match e.eexpr with - | TField(obj,FInstance(_,_,field) ) -> - let cpp_type = member_type ctx obj field.cf_name in - (not (is_scalar cpp_type)) && ( - let fixed = (cpp_type<>"?") && (expr_type<>"Dynamic") && (cpp_type<>"Dynamic") && - (cpp_type<>expr_type) && (expr_type<>"Void") && (cpp_type<>"cpp::ArrayBase") in - if (fixed && (ctx.ctx_debug_level>1) ) then begin - output ("/* " ^ (cpp_type) ^ " != " ^ expr_type ^ " -> cast */"); - end; - fixed - ) - | TParenthesis p | TMeta(_,p) -> is_fixed_override p - | _ -> false - in - let check_extern_pointer_cast e = match (remove_parens e).eexpr with - | TField (_,FInstance(class_def,_,_) ) - | TField (_,FStatic(class_def,_) ) - when class_def.cl_extern -> - (try - let return_type = expression.etype in - (is_pointer return_type false) && - ( output ( (type_string return_type) ^ "(" ); true; ) - with Not_found -> false ) - | _ -> false - in - let is_super = (match func.eexpr with | TConst TSuper -> true | _ -> false ) in - if (ctx.ctx_debug_level>1) then output ("/* TCALL ret=" ^ expr_type ^ "*/"); - let cast_result = (not is_super) && (is_fixed_override func) in - if (cast_result) then output ("hx::TCast< " ^ expr_type ^ " >::cast("); - let cast_result = cast_result || check_extern_pointer_cast func in - - (* If a static function has @:native('new abc') - c++ new has lower precedence than in haxe so ( ) must be used *) - let paren_result = - if is_native_with_space func then - ( output "("; true ) - else - false - in - ctx.ctx_calling <- true; - gen_expression true func; - - output "("; - gen_expression_list arg_list; - output ")"; - if paren_result then - output ")"; - - if (cast_result) then output (")"); - if ( (is_variable func) && (not (is_cpp_function_member func) ) && - (expr_type<>"Dynamic" && expr_type<>"cpp::ArrayBase" ) && (not is_super) ) then - ctx.ctx_output (".Cast< " ^ expr_type ^ " >()" ); - - let rec cast_array_output func = - match func.eexpr with - | TField(obj,field) when is_array obj.etype -> - (match field_name field with - | "pop" | "shift" | "__unsafe_get" | "__unsafe_set" -> check_array_element_cast obj.etype ".StaticCast" "()" - | "map" -> check_array_cast expression.etype - | _ -> () - ) - | TParenthesis p | TMeta(_,p) -> cast_array_output p - | _ -> () - in - cast_array_output func; - - | TBlock expr_list -> - if (retval) then - gen_local_block_call() - else begin - writer#begin_block; - dump_src_pos(); - (* Save old values, and equalize for new input ... *) - let pop_names = push_anon_names ctx in - let remaining = ref (List.length expr_list) in - List.iter (fun expression -> - let want_value = (return_from_block && !remaining = 1) in - find_local_functions_and_return_blocks_ctx want_value expression; - if (ctx.ctx_debug_level>0) then - output_i ("HX_STACK_LINE(" ^ (string_of_int (Lexer.get_error_line expression.epos)) ^ ")\n" ); - output_i ""; - ctx.ctx_return_from_internal_node <- return_from_internal_node; - if (want_value) then output "return "; - gen_expression want_value expression; - decr remaining; - writer#terminate_line - ) expr_list; - writer#end_block; - pop_names() - end - | TTypeExpr type_expr -> - let klass = "::" ^ (join_class_path_remap (t_path type_expr) "::" ) in - let klass1 = if klass="::Array" then "Array" else klass in - output ("hx::ClassOf< " ^ klass1 ^ " >()") - | TReturn _ when retval -> - unsupported expression.epos - | TReturn optional_expr -> - output ""; - ( match optional_expr with - | Some return_expression when ( (type_string expression.etype)="Void") -> - output "return null("; - gen_expression true return_expression; - output ")"; - | Some return_expression -> - output "return "; - gen_expression true return_expression - | _ -> output (if ctx.ctx_real_void then "return" else "return null()") - ) - - | TConst const -> - (match const with - | TInt i when ctx.ctx_for_extern -> output (Printf.sprintf "%ld" i) - | TInt i -> output (Printf.sprintf "(int)%ld" i) - | TFloat float_as_string -> output ("((Float)" ^ float_as_string ^")") - | TString s when ctx.ctx_for_extern -> output ("\"" ^ (escape_extern s) ^ "\"") - | TString s -> output (str s) - | TBool b -> output (if b then "true" else "false") - (*| TNull -> output ("((" ^ (type_string expression.etype) ^ ")null())")*) - | TNull -> output (if ctx.ctx_for_extern then "null" else "null()") - | TThis -> output (if ctx.ctx_real_this_ptr then "hx::ObjectPtr(this)" else "__this") - | TSuper when calling -> - output (if ctx.ctx_real_this_ptr then - "super::__construct" - else - ("__this->" ^ ctx.ctx_class_super_name ^ "::__construct") ) - | TSuper -> output ("hx::ObjectPtr(" ^ (if ctx.ctx_real_this_ptr then "this" else "__this.mPtr") ^ ")") - ) - - - | TLocal v -> output (keyword_remap v.v_name); - | TArray (array_expr,_) when (is_null array_expr) -> output "Dynamic()" - | TArray (array_expr,index) -> - let dynamic = is_dynamic_in_cpp ctx array_expr || (type_string array_expr.etype) = "cpp::ArrayBase" in - if ( assigning && (not dynamic) ) then begin - if (is_array_implementer array_expr.etype) then begin - output "hx::__ArrayImplRef("; - gen_expression true array_expr; - output ","; - gen_expression true index; - output ")"; - end else begin - gen_expression true array_expr; - output "["; - gen_expression true index; - output "]"; - end - end else if (assigning) then begin - (* output (" /*" ^ (type_string array_expr.etype) ^ " */ "); *) - output "hx::IndexRef(("; - gen_expression true array_expr; - output ").mPtr,"; - gen_expression true index; - output ")"; - end else if ( dynamic ) then begin - gen_expression true array_expr; - output "->__GetItem("; - gen_expression true index; - output ")"; - end else begin - gen_expression true array_expr; - output "->__get("; - gen_expression true index; - output ")"; - if not (is_pointer array_expr.etype true) then - check_array_element_cast array_expr.etype ".StaticCast" "()"; - end - (* Get precidence matching haxe ? *) - | TBinop (op,expr1,expr2) -> gen_bin_op op expr1 expr2 - | TField (expr,_) | TEnumParameter (expr,_,_) when (is_null expr) -> - output "hx::Throw(HX_CSTRING(\"Invalid field access on null object\"))" - | TEnumParameter (expr,ef,i) -> - let enum = match follow ef.ef_type with - | TEnum(en,_) | TFun(_,TEnum(en,_)) -> en - | _ -> assert false - in - output ( "(::" ^ (join_class_path_remap enum.e_path "::") ^ "("); - gen_expression true expr; - output ( "))->__Param(" ^ (string_of_int i) ^ ")") - | TField (field_object,field) -> - gen_tfield field_object field - - | TParenthesis expr when not retval -> - gen_expression retval expr; - | TParenthesis expr -> output "("; gen_expression retval expr; output ")" - | TMeta (_,expr) -> gen_expression retval expr; - | TObjectDecl ( - ("fileName" , { eexpr = (TConst (TString file)) }) :: - ("lineNumber" , { eexpr = (TConst (TInt line)) }) :: - ("className" , { eexpr = (TConst (TString class_name)) }) :: - ("methodName", { eexpr = (TConst (TString meth)) }) :: [] ) -> - output ("hx::SourceInfo(" ^ (str file) ^ "," ^ (Printf.sprintf "%ld" line) ^ "," ^ - (str class_name) ^ "," ^ (str meth) ^ ")" ) - | TObjectDecl decl_list -> gen_local_block_call() - | TArrayDecl decl_list -> - (* gen_type output expression.etype; *) - let tstr = (type_string_suff "_obj" expression.etype true) in - if tstr="Dynamic" then - output "Dynamic( Array_obj::__new()" - else - output ( (type_string_suff "_obj" expression.etype true) ^ "::__new()"); - List.iter ( fun elem -> output ".Add("; - gen_expression true elem; - output ")" ) decl_list; - if tstr="Dynamic" then output ")"; - | TNew (klass,params,expressions) -> - let is_param_array = match klass.cl_path with - | ([],"Array") when is_dynamic_array_param (List.hd params) -> true | _ -> false - in - if is_param_array then - output "Dynamic( Array_obj::__new() )" - else begin - if (klass.cl_path = ([],"String")) then - output "::String(" - else - output ( ( class_string klass "_obj" params true) ^ "::__new(" ); - gen_expression_list expressions; - output ")" - end - | TUnop (Ast.NegBits,Ast.Prefix,expr) -> - output "~(int)("; - gen_expression true expr; - output ")" - | TUnop (op,Ast.Prefix,expr) -> - ctx.ctx_assigning <- (match op with Ast.Increment | Ast.Decrement -> true | _ ->false); - output (Ast.s_unop op); - output "("; - gen_expression true expr; - output ")" - | TUnop (op,Ast.Postfix,expr) -> - ctx.ctx_assigning <- true; - output "("; - gen_expression true expr; - output ")"; - output (Ast.s_unop op) - | TFunction func -> - let func_name = use_anon_function_name ctx in - ( - try - output ( " Dynamic(new " ^ func_name ^ "(" ^ - (Hashtbl.find ctx.ctx_local_function_args func_name) ^ "))" ) - with Not_found -> - (*error ("function " ^ func_name ^ " not found.") expression.epos; *) - output ("function " ^ func_name ^ " not found."); - ) - - | TVar (tvar,optional_init) -> - let count = ref 1 in (* TODO: this section can be simplified *) - if (retval && !count==1) then - (match optional_init with - | None -> output "null()" - | Some expression -> gen_expression true expression ) - else begin - let type_name = (type_string tvar.v_type) in - output (if type_name="Void" then "Dynamic" else type_name ); - let name = (keyword_remap tvar.v_name) in - output (" " ^ name ); - (match optional_init with - | None -> () - | Some expression -> output " = "; gen_expression true expression); - count := !count -1; - if (ctx.ctx_debug_level>0) then - output (";\t\tHX_STACK_VAR(" ^name ^",\""^ tvar.v_name ^"\")"); - if (!count > 0) then begin output ";\n"; output_i "" end - end - | TFor (tvar, init, loop) -> - output ("for(::cpp::FastIterator_obj< " ^ (type_string tvar.v_type) ^ - " > *__it = ::cpp::CreateFastIterator< "^(type_string tvar.v_type) ^ " >("); - gen_expression true init; - output ("); __it->hasNext(); )"); - ctx.ctx_writer#begin_block; - output_i ( (type_string tvar.v_type) ^ " " ^ (keyword_remap tvar.v_name) ^ " = __it->next();\n" ); - output_i ""; - gen_expression false loop; - output ";\n"; - ctx.ctx_writer#end_block; - | TIf (condition, if_expr, optional_else_expr) -> - (match optional_else_expr with - | Some else_expr -> - if (retval) then begin - output "( ("; - gen_expression true condition; - output ") ? "; - let type_str = match (type_string expression.etype) with - | "Void" -> "Dynamic" - | other -> other - in - output (type_str ^ "("); - gen_expression true if_expr; - output ") : "; - - output (type_str ^ "("); - gen_expression true else_expr; - output ") )"; - end else begin - output "if ("; - gen_expression true condition; - output ")"; - gen_expression false (to_block if_expr); - output_i "else"; - gen_expression false (to_block else_expr); - end - | _ -> output "if ("; - gen_expression true condition; - output ")"; - gen_expression false (to_block if_expr); - ) - | TWhile (condition, repeat, Ast.NormalWhile ) -> - output "while("; - gen_expression true condition; - output ")"; - gen_expression false (to_block repeat) - | TWhile (condition, repeat, Ast.DoWhile ) -> - output "do"; - gen_expression false (to_block repeat); - output "while("; - gen_expression true condition; - output ")" - - (* These have already been defined in find_local_return_blocks ... *) - | TTry (_,_) - | TSwitch (_,_,_) when (retval && (not return_from_internal_node) ) -> - gen_local_block_call() - | TSwitch (condition,cases,optional_default) -> - let switch_on_int_constants = (only_int_cases cases) && (not (contains_break expression)) in - if (switch_on_int_constants) then begin - output "switch( (int)"; - gen_expression true condition; - output ")"; - ctx.ctx_writer#begin_block; - List.iter (fun (cases_list,expression) -> - output_i ""; - List.iter (fun value -> output "case "; - gen_expression true value; - output ": " ) cases_list; - ctx.ctx_return_from_block <- return_from_internal_node; - gen_expression false (to_block expression); - output_i ";break;\n"; - ) cases; - (match optional_default with | None -> () - | Some default -> - output_i "default: "; - ctx.ctx_return_from_block <- return_from_internal_node; - gen_expression false (to_block default); - ); - ctx.ctx_writer#end_block; - end else begin - let tmp_name = get_switch_var ctx in - output ( (type_string condition.etype) ^ " " ^ tmp_name ^ " = " ); - gen_expression true condition; - output ";\n"; - let else_str = ref "" in - if (List.length cases > 0) then - List.iter (fun (cases,expression) -> - output_i ( !else_str ^ "if ( "); - else_str := "else "; - let or_str = ref "" in - List.iter (fun value -> - output (!or_str ^ " ( " ^ tmp_name ^ "=="); - gen_expression true value; - output ")"; - or_str := " || "; - ) cases; - output (")"); - ctx.ctx_return_from_block <- return_from_internal_node; - gen_expression false (to_block expression); - ) cases; - (match optional_default with | None -> () - | Some default -> - output_i ( !else_str ^ " "); - ctx.ctx_return_from_block <- return_from_internal_node; - gen_expression false (to_block default); - output ";\n"; - ); - end - | TTry (expression, catch_list) -> - output "try\n"; - output_i "{\n"; - let counter = ref 0 in - List.iter (fun (v, e) -> - let type_name = type_string v.v_type in - output_i ("HX_STACK_CATCHABLE(" ^ type_name ^ ", " ^ string_of_int !counter ^ ");\n"); - counter := !counter + 1;) - catch_list; - output_i(""); - (* Move this "inside" the try call ... *) - ctx.ctx_return_from_block <-return_from_internal_node; - gen_expression false (to_block expression); - output_i "}\n"; - if (List.length catch_list > 0 ) then begin - output_i "catch(Dynamic __e)"; - ctx.ctx_writer#begin_block; - let seen_dynamic = ref false in - let else_str = ref "" in - List.iter (fun (v,expression) -> - let type_name = type_string v.v_type in - if (type_name="Dynamic") then begin - seen_dynamic := true; - output_i !else_str; - end else - output_i (!else_str ^ "if (__e.IsClass< " ^ type_name ^ " >() )"); - ctx.ctx_writer#begin_block; - output_i "HX_STACK_BEGIN_CATCH\n"; - output_i (type_name ^ " " ^ v.v_name ^ " = __e;"); - (* Move this "inside" the catch call too ... *) - ctx.ctx_return_from_block <-return_from_internal_node; - gen_expression false (to_block expression); - ctx.ctx_writer#end_block; - else_str := "else "; - ) catch_list; - if (not !seen_dynamic) then begin - output_i "else {\n"; - output_i " HX_STACK_DO_THROW(__e);\n"; - output_i "}\n"; - end; - ctx.ctx_writer#end_block; - end; - | TBreak -> output "break" - | TContinue -> output "continue" - | TThrow expression -> - output "HX_STACK_DO_THROW("; - gen_expression true expression; - output ")"; - | TCast (cast,None) when (not retval) || (type_string expression.etype) = "Void" -> - gen_expression retval cast; - | TCast (cast,None) -> - let ret_type = type_string expression.etype in - let from_type = if is_dynamic_in_cpp ctx cast then "Dynamic" else type_string cast.etype in - if (from_type = ret_type) then begin - gen_expression true cast - end else begin - output ("((" ^ ret_type ^ ")("); - gen_expression true cast; - output "))"; - end; - | TCast (e1,Some t) -> - let class_name = (join_class_path_remap (t_path t) "::" ) in - if (class_name="Array") then - output ("hx::TCastToArray(" ) - else - output ("hx::TCast< ::" ^ class_name ^ " >::cast(" ); - gen_expression true e1; - output ")"; - in - - if (set_var<>"") then begin - find_local_functions_and_return_blocks_ctx true expression_tree; - output set_var; - end; - gen_expression retval expression_tree; - output tail_code -;; - - - -(* -let is_dynamic_haxe_method f = - match follow f.cf_type with - | TFun _ when f.cf_expr = None -> true - | _ -> - (match f.cf_expr with - | Some { eexpr = TFunction fd } when f.cf_set = MethodAccess true -> true - | Some { eexpr = TFunction fd } when f.cf_set = NormalAccess -> true - | _ -> false);; -*) - -let is_dynamic_haxe_method f = - (match f.cf_expr, f.cf_kind with - | Some { eexpr = TFunction _ }, (Var _ | Method MethDynamic) -> true - | _ -> false);; - - -let is_data_member field = - match field.cf_expr with - | Some { eexpr = TFunction function_def } -> is_dynamic_haxe_method field - | _ -> true;; - - -let is_override class_def field = - List.exists (fun f -> f.cf_name = field) class_def.cl_overrides -;; - -let rec all_virtual_functions clazz = - (List.fold_left (fun result elem -> match follow elem.cf_type, elem.cf_kind with - | _, Method MethDynamic -> result - | TFun (args,return_type), Method _ when not (is_override clazz elem.cf_name ) -> (elem,args,return_type) :: result - | _,_ -> result ) [] clazz.cl_ordered_fields) - @ (match clazz.cl_super with - | Some def -> all_virtual_functions (fst def) - | _ -> [] ) -;; - -let reflective class_def field = not ( - (Meta.has Meta.NativeGen class_def.cl_meta) || - (Meta.has Meta.Unreflective class_def.cl_meta) || - (Meta.has Meta.Unreflective field.cf_meta) || - (match field.cf_type with - | TInst (klass,_) -> Meta.has Meta.Unreflective klass.cl_meta - | _ -> false - ) -) -;; - - - - - -let field_arg_count field = - match follow field.cf_type, field.cf_kind with - | _, Method MethDynamic -> -1 - | TFun (args,return_type), Method _ -> List.length args - | _,_ -> -1 -;; - - - (* external mem Dynamic & *) - -let gen_field ctx class_def class_name ptr_name dot_name is_static is_interface field = - let output = ctx.ctx_output in - ctx.ctx_real_this_ptr <- not is_static; - let remap_name = keyword_remap field.cf_name in - let decl = get_meta_string field.cf_meta Meta.Decl in - let has_decl = decl <> "" in - let nativeGen = has_meta_key class_def.cl_meta Meta.NativeGen in - if (is_interface) then begin - (* Just the dynamic glue - not even that ... *) - () - end else (match field.cf_expr with - (* Function field *) - | Some { eexpr = TFunction function_def } -> - let return_type = (type_string function_def.tf_type) in - let nargs = string_of_int (List.length function_def.tf_args) in - let is_void = (type_string function_def.tf_type ) = "Void" in - let ret = if is_void then "(void)" else "return " in - let output_i = ctx.ctx_writer#write_i in - let orig_debug = ctx.ctx_debug_level in - let dump_src = if ((Meta.has Meta.NoStack field.cf_meta)||(Meta.has Meta.NoDebug field.cf_meta) || orig_debug<1 || nativeGen) then begin - ctx.ctx_debug_level <- 0; - (fun()->()) - end else begin - (fun() -> - hx_stack_push ctx output_i dot_name field.cf_name function_def.tf_expr.epos; - if (not is_static) then output_i ("HX_STACK_THIS(this)\n"); - List.iter (fun (v,_) -> output_i ("HX_STACK_ARG(" ^ (keyword_remap v.v_name) ^ ",\"" ^ v.v_name ^"\")\n") ) - function_def.tf_args ) - end in - - if (not (is_dynamic_haxe_method field)) then begin - (* The actual function definition *) - let real_void = is_void && (has_meta_key field.cf_meta Meta.Void) in - let fake_void = is_void && not real_void in - output (if real_void then "void" else return_type ); - output (" " ^ class_name ^ "::" ^ remap_name ^ "( " ); - output (gen_arg_list function_def.tf_args "__o_"); - output ")"; - ctx.ctx_real_this_ptr <- true; - ctx.ctx_real_void <- real_void; - ctx.ctx_dynamic_this_ptr <- false; - let code = (get_code field.cf_meta Meta.FunctionCode) in - let tail_code = (get_code field.cf_meta Meta.FunctionTailCode) in - if (has_default_values function_def.tf_args) then begin - ctx.ctx_writer#begin_block; - generate_default_values ctx function_def.tf_args "__o_"; - dump_src(); - output code; - gen_expression_tree ctx false function_def.tf_expr "" tail_code; - if (fake_void) then output "return null();\n"; - ctx.ctx_writer#end_block; - end else begin - let add_block = is_void || (code <> "") || (tail_code <> "") in - if (add_block) then ctx.ctx_writer#begin_block; - ctx.ctx_dump_src_pos <- dump_src; - output code; - gen_expression_tree ctx false (to_block function_def.tf_expr) "" tail_code; - if (add_block) then begin - if (fake_void) then output "return null();\n"; - ctx.ctx_writer#end_block; - end; - end; - - output "\n\n"; - let nonVirtual = has_meta_key field.cf_meta Meta.NonVirtual in - let doDynamic = (nonVirtual || not (is_override class_def field.cf_name ) ) && (reflective class_def field ) in - (* generate dynamic version too ... *) - if ( doDynamic ) then begin - if (is_static) then output "STATIC_"; - output ("HX_DEFINE_DYNAMIC_FUNC" ^ nargs ^ "(" ^ class_name ^ "," ^ - remap_name ^ "," ^ ret ^ ")\n\n"); - end; - - end else begin - ctx.ctx_real_this_ptr <- false; - ctx.ctx_dynamic_this_ptr <- false; - let func_name = "__default_" ^ (remap_name) in - output ("HX_BEGIN_DEFAULT_FUNC(" ^ func_name ^ "," ^ class_name ^ ")\n"); - output return_type; - output (" run(" ^ (gen_arg_list function_def.tf_args "__o_") ^ ")"); - ctx.ctx_dump_src_pos <- dump_src; - if (is_void) then begin - ctx.ctx_writer#begin_block; - generate_default_values ctx function_def.tf_args "__o_"; - gen_expression_tree ctx false function_def.tf_expr "" ""; - output "return null();\n"; - ctx.ctx_writer#end_block; - end else if (has_default_values function_def.tf_args) then begin - ctx.ctx_writer#begin_block; - generate_default_values ctx function_def.tf_args "__o_"; - gen_expression_tree ctx false function_def.tf_expr "" ""; - ctx.ctx_writer#end_block; - end else - gen_expression_tree ctx false (to_block function_def.tf_expr) "" ""; - - output ("HX_END_LOCAL_FUNC" ^ nargs ^ "(" ^ ret ^ ")\n"); - output ("HX_END_DEFAULT_FUNC\n\n"); - - if (is_static) then - output ( "Dynamic " ^ class_name ^ "::" ^ remap_name ^ ";\n\n"); - end; - ctx.ctx_debug_level <- orig_debug - - (* Data field *) - | _ when has_decl -> - if is_static then begin - output ( class_name ^ "::" ^ remap_name ^ "_decl "); - output ( " " ^ class_name ^ "::" ^ remap_name ^ ";\n\n"); - end - | _ -> - if is_static && (not (is_extern_field field)) then begin - gen_type ctx field.cf_type; - output ( " " ^ class_name ^ "::" ^ remap_name ^ ";\n\n"); - end - ) - ;; - - - - - -let gen_field_init ctx field = - let output = ctx.ctx_output in - let remap_name = keyword_remap field.cf_name in - (match field.cf_expr with - (* Function field *) - | Some { eexpr = TFunction function_def } -> - - if (is_dynamic_haxe_method field) then begin - let func_name = "__default_" ^ (remap_name) in - output ( "\t" ^ remap_name ^ " = new " ^ func_name ^ ";\n\n" ); - end - - (* Data field *) - | _ -> (match field.cf_expr with - | Some expr -> - let var_name = ( match remap_name with - | "__meta__" -> "\t__mClass->__meta__=" - | "__rtti" -> "\t__mClass->__rtti__=" - | _ -> "\t" ^ remap_name ^ "= ") in - gen_expression_tree ctx true expr var_name ";\n"; - | _ -> ( ) - ); - ) - ;; - - - -let has_field_init field = - match field.cf_expr with - (* Function field *) - | Some { eexpr = TFunction function_def } -> is_dynamic_haxe_method field - (* Data field *) - | Some _ -> true - | _ -> false -;; - - -let gen_member_def ctx class_def is_static is_interface field = - let output = ctx.ctx_output in - let remap_name = keyword_remap field.cf_name in - let nativeGen = has_meta_key class_def.cl_meta Meta.NativeGen in - - if (is_interface) then begin - match follow field.cf_type, field.cf_kind with - | _, Method MethDynamic -> () - | TFun (args,return_type), Method _ -> - output ( (if (not is_static) then " virtual " else " " ) ^ type_string return_type); - output (" " ^ remap_name ^ "( " ); - output (gen_tfun_interface_arg_list args); - output (if (not is_static) then ")=0;\n" else ");\n"); - if reflective class_def field then begin - output ("virtual Dynamic " ^ remap_name ^ "_dyn()=0;\n" ); - end - | _ -> ( ) - end else begin - let decl = get_meta_string field.cf_meta Meta.Decl in - let has_decl = decl <> "" in - if (has_decl) then - output ( " typedef " ^ decl ^ ";\n" ); - output (if is_static then "\t\tstatic " else "\t\t"); - (match field.cf_expr with - | Some { eexpr = TFunction function_def } -> - let nonVirtual = has_meta_key field.cf_meta Meta.NonVirtual in - let doDynamic = (nonVirtual || not (is_override class_def field.cf_name ) ) && (reflective class_def field ) in - if ( is_dynamic_haxe_method field ) then begin - if ( doDynamic ) then begin - output ("Dynamic " ^ remap_name ^ ";\n"); - output (if is_static then "\t\tstatic " else "\t\t"); - output ("inline Dynamic &" ^ remap_name ^ "_dyn() " ^ "{return " ^ remap_name^ "; }\n") - end - end else begin - let return_type = (type_string function_def.tf_type) in - - if ( not is_static && not nonVirtual ) then output "virtual "; - output (if return_type="Void" && (has_meta_key field.cf_meta Meta.Void) then "void" else return_type ); - - output (" " ^ remap_name ^ "( " ); - output (gen_arg_list function_def.tf_args "" ); - output ");\n"; - if ( doDynamic ) then begin - output (if is_static then "\t\tstatic " else "\t\t"); - output ("Dynamic " ^ remap_name ^ "_dyn();\n" ) - end; - end; - output "\n"; - | _ when has_decl -> - output ( remap_name ^ "_decl " ^ remap_name ^ ";\n" ); - (* Variable access *) - | _ -> - (* Variable access *) - gen_type ctx field.cf_type; - output (" " ^ remap_name ^ ";\n" ); - - (* Add a "dyn" function for variable to unify variable/function access *) - (match follow field.cf_type with - | _ when nativeGen -> () - | TFun (_,_) -> - output (if is_static then "\t\tstatic " else "\t\t"); - gen_type ctx field.cf_type; - output (" &" ^ remap_name ^ "_dyn() { return " ^ remap_name ^ ";}\n" ) - | _ -> (match field.cf_kind with - | Var { v_read = AccCall } when (not is_static) && (is_dynamic_accessor ("get_" ^ field.cf_name) "get" field class_def) -> - output ("\t\tDynamic get_" ^ field.cf_name ^ ";\n" ) - | _ -> () - ); - (match field.cf_kind with - | Var { v_write = AccCall } when (not is_static) && (is_dynamic_accessor ("set_" ^ field.cf_name) "set" field class_def) -> - output ("\t\tDynamic set_" ^ field.cf_name ^ ";\n" ) - | _ -> () - ) - ) - ); - end - ;; - -let path_of_string path = - ["@verbatim"], path -;; - - -(* - Get a list of all classes referred to by the class/enum definition - These are used for "#include"ing the appropriate header files, - or for building the dependencies in the Build.xml file -*) -let find_referenced_types ctx obj super_deps constructor_deps header_only for_depends include_super_args = - let types = ref PMap.empty in - let rec add_type in_path = - if ( not (PMap.mem in_path !types)) then begin - types := (PMap.add in_path () !types); - try - List.iter add_type (Hashtbl.find super_deps in_path); - with Not_found -> () - end - in - let add_extern_class klass = - let include_file = get_meta_string_path klass.cl_meta (if for_depends then Meta.Depend else Meta.Include) in - if (include_file<>"") then - add_type ( path_of_string include_file ) - else if (not for_depends) && (has_meta_key klass.cl_meta Meta.Include) then - add_type klass.cl_path - in - let add_native_gen_class klass = - let include_file = get_meta_string_path klass.cl_meta (if for_depends then Meta.Depend else Meta.Include) in - if (include_file<>"") then - add_type ( path_of_string include_file ) - else if for_depends then - add_type klass.cl_path - else - add_type ( path_of_string ( (join_class_path klass.cl_path "/") ^ ".h") ) - in - let visited = ref [] in - let rec visit_type in_type = - if not (List.exists (fun t2 -> Type.fast_eq in_type t2) !visited) then begin - visited := in_type :: !visited; - begin match follow in_type with - | TMono r -> (match !r with None -> () | Some t -> visit_type t) - | TEnum (enum,params) -> add_type enum.e_path - (* If a class has a template parameter, then we treat it as dynamic - except - for the Array, Class, FastIterator or Pointer classes, for which we do a fully typed object *) - | TInst (klass,params) -> - (match klass.cl_path with - | ([],"Array") | ([],"Class") | (["cpp"],"FastIterator") - | (["cpp"],"Pointer") | (["cpp"],"ConstPointer") | (["cpp"],"Function") - | (["cpp"],"RawPointer") | (["cpp"],"RawConstPointer") -> List.iter visit_type params - | _ when is_native_gen_class klass -> add_native_gen_class klass - | _ when is_extern_class klass -> add_extern_class klass - | _ -> (match klass.cl_kind with KTypeParameter _ -> () | _ -> add_type klass.cl_path); - ) - | TFun (args,haxe_type) -> visit_type haxe_type; - List.iter (fun (_,_,t) -> visit_type t; ) args; - | _ -> () - end; - visited := List.tl !visited; - end - in - let rec visit_params expression = - begin - let rec visit_expression = fun expression -> - (* Expand out TTypeExpr (ie, the name of a class, as used for static access etc ... *) - (match expression.eexpr with - | TTypeExpr type_def -> ( match type_def with - | TClassDecl class_def when is_native_gen_class class_def -> add_native_gen_class class_def - | TClassDecl class_def when is_extern_class class_def -> add_extern_class class_def - | _ -> add_type (t_path type_def) - ) - - (* Must visit the types, Type.iter will visit the expressions ... *) - | TTry (e,catches) -> - List.iter (fun (v,_) -> visit_type v.v_type) catches - (* Must visit the enum param types, Type.iter will visit the rest ... *) -(* | TMatch (_,enum,cases,_) -> - add_type (fst enum).e_path; - List.iter (fun (case_ids,params,expression) -> - (match params with - | None -> () - | Some l -> List.iter (function None -> () | Some v -> visit_type v.v_type) l ) ) cases; *) - (* Must visit type too, Type.iter will visit the expressions ... *) - | TNew (klass,params,_) -> begin - visit_type (TInst (klass,params)); - try - let construct_type = Hashtbl.find constructor_deps klass.cl_path in - visit_type construct_type.cf_type - with Not_found -> (); - end - (* Must visit type too, Type.iter will visit the expressions ... *) - | TVar (v,_) -> - visit_type v.v_type - (* Must visit enum type too, Type.iter will visit the expressions ... *) - | TEnumParameter (_,ef,_) -> visit_type (follow ef.ef_type) - (* Must visit args too, Type.iter will visit the expressions ... *) - | TFunction func_def -> - List.iter (fun (v,_) -> visit_type v.v_type) func_def.tf_args; - | TConst TSuper -> - (match follow expression.etype with - | TInst (klass,params) -> - (try let construct_type = Hashtbl.find constructor_deps klass.cl_path in - visit_type construct_type.cf_type - with Not_found -> () ) - | _ -> print_endline ("TSuper : Odd etype ?" ^ ( (type_string expression.etype)) ) - ) - | _ -> () - ); - Type.iter visit_expression expression; - visit_type (follow expression.etype) - in - visit_expression expression - end - in - let visit_field field = - (* Add the type of the expression ... *) - visit_type field.cf_type; - if (not header_only) then - (match field.cf_expr with - | Some expression -> visit_params expression | _ -> ()); - in - let visit_class class_def = - let fields = List.append class_def.cl_ordered_fields class_def.cl_ordered_statics in - let fields_and_constructor = List.append fields - (match class_def.cl_constructor with | Some expr -> [expr] | _ -> [] ) in - List.iter visit_field fields_and_constructor; - if (include_super_args) then - List.iter visit_field (List.map (fun (a,_,_) -> a ) (all_virtual_functions class_def )); - - (* Add super & interfaces *) - if is_native_gen_class class_def then - add_native_gen_class class_def - else - add_type class_def.cl_path; - in - let visit_enum enum_def = - add_type enum_def.e_path; - PMap.iter (fun _ constructor -> - (match constructor.ef_type with - | TFun (args,_) -> - List.iter (fun (_,_,t) -> visit_type t; ) args; - | _ -> () ); - ) enum_def.e_constrs; - if (not header_only) then begin - let meta = Codegen.build_metadata ctx (TEnumDecl enum_def) in - match meta with Some expr -> visit_params expr | _ -> (); - end; - in - let inc_cmp i1 i2 = - String.compare (join_class_path i1 ".") (join_class_path i2 ".") - in - - (* Body of main function *) - (match obj with - | TClassDecl class_def -> visit_class class_def; - (match class_def.cl_init with Some expression -> visit_params expression | _ -> ()) - | TEnumDecl enum_def -> visit_enum enum_def - | TTypeDecl _ | TAbstractDecl _ -> (* These are expanded *) ()); - - List.sort inc_cmp (List.filter (fun path -> (include_class_header path) ) (pmap_keys !types)) - ;; - - -let generate_main_header output_main = - output_main "#include \n\n"; - output_main "#include \n\n"; - output_main "extern \"C\" void __hxcpp_main();\n\n"; - output_main "extern \"C\" void __hxcpp_lib_main();\n\n" -;; - -let generate_main_footer1 output_main = - output_main "void __hxcpp_main() {\n";; - -let generate_main_footer2 output_main = - output_main " }\n\n"; - output_main "void __hxcpp_lib_main() {\n"; - output_main " HX_TOP_OF_STACK\n"; - output_main " hx::Boot();\n"; - output_main " __boot_all();\n"; - output_main " __hxcpp_main();\n"; - output_main " }\n" -;; - - -let generate_main common_ctx member_types super_deps class_def file_info = - (* main routine should be a single static function *) - let main_expression = - (match class_def.cl_ordered_statics with - | [{ cf_expr = Some expression }] -> expression; - | _ -> assert false ) in - ignore(find_referenced_types common_ctx (TClassDecl class_def) super_deps (Hashtbl.create 0) false false false); - let depend_referenced = find_referenced_types common_ctx (TClassDecl class_def) super_deps (Hashtbl.create 0) false true false in - let generate_startup filename is_main = - (*make_class_directories base_dir ( "src" :: []);*) - let cpp_file = new_cpp_file common_ctx common_ctx.file ([],filename) in - let output_main = (cpp_file#write) in - - generate_main_header output_main; - - List.iter ( add_include cpp_file ) depend_referenced; - output_main "\n\n"; - - if is_main then output_main "\n#include \n\n"; - - generate_main_footer1 output_main; - gen_expression_tree (new_context common_ctx cpp_file 1 file_info) false main_expression "" ";\n"; - generate_main_footer2 output_main; - cpp_file#close; - in - generate_startup "__main__" true; - generate_startup "__lib__" false - ;; - -let generate_dummy_main common_ctx = - let generate_startup filename is_main = - let main_file = new_cpp_file common_ctx common_ctx.file ([],filename) in - let output_main = (main_file#write) in - generate_main_header output_main; - if is_main then output_main "\n#include \n\n"; - generate_main_footer1 output_main; - generate_main_footer2 output_main; - main_file#close; - in - generate_startup "__main__" true; - generate_startup "__lib__" false - ;; - -let generate_boot common_ctx boot_enums boot_classes nonboot_classes init_classes = - (* Write boot class too ... *) - let base_dir = common_ctx.file in - let boot_file = new_cpp_file common_ctx base_dir ([],"__boot__") in - let output_boot = (boot_file#write) in - output_boot "#include \n\n"; - List.iter ( fun class_path -> boot_file#add_include class_path ) - (boot_enums @ boot_classes @ nonboot_classes); - - output_boot "\nvoid __files__boot();\n"; - output_boot "\nvoid __boot_all()\n{\n"; - output_boot "__files__boot();\n"; - output_boot "hx::RegisterResources( hx::GetResources() );\n"; - List.iter ( fun class_path -> - output_boot ("::" ^ ( join_class_path_remap class_path "::" ) ^ "_obj::__register();\n") ) - (boot_enums @ boot_classes @ nonboot_classes); - - let dump_boot = - List.iter ( fun class_path -> - output_boot ("::" ^ ( join_class_path_remap class_path "::" ) ^ "_obj::__boot();\n") ) in - - dump_boot boot_enums; - - List.iter ( fun class_path -> - output_boot ("::" ^ ( join_class_path_remap class_path "::" ) ^ "_obj::__init__();\n") ) (List.rev init_classes); - - dump_boot (List.filter (fun path -> is_cpp_class path ) (List.rev boot_classes)); - dump_boot (List.filter (fun path -> not (is_cpp_class path) ) (List.rev boot_classes)); - - output_boot "}\n\n"; - boot_file#close;; - - -let generate_files common_ctx file_info = - (* Write __files__ class too ... *) - let base_dir = common_ctx.file in - let files_file = new_cpp_file common_ctx base_dir ([],"__files__") in - let output_files = (files_file#write) in - let types = common_ctx.types in - output_files "#include \n\n"; - output_files "namespace hx {\n"; - output_files "const char *__hxcpp_all_files[] = {\n"; - output_files "#ifdef HXCPP_DEBUGGER\n"; - List.iter ( fun file -> output_files ((const_char_star file)^",\n" ) ) - ( List.sort String.compare ( pmap_keys !file_info) ); - output_files "#endif\n"; - output_files " 0 };\n"; - output_files "\n"; - - output_files "const char *__hxcpp_all_files_fullpath[] = {\n"; - output_files "#ifdef HXCPP_DEBUGGER\n"; - List.iter ( fun file -> output_files ((const_char_star ( - Common.get_full_path (try Common.find_file common_ctx file with Not_found -> file) - ))^",\n" ) ) - ( List.sort String.compare ( pmap_keys !file_info) ); - output_files "#endif\n"; - output_files " 0 };\n"; - output_files "\n"; - - - output_files "const char *__hxcpp_all_classes[] = {\n"; - output_files "#ifdef HXCPP_DEBUGGER\n"; - List.iter ( fun object_def -> - (match object_def with - | TClassDecl class_def when is_extern_class class_def -> ( ) - | TClassDecl class_def when class_def.cl_interface -> ( ) - | TClassDecl class_def -> - output_files ((const_char_star (join_class_path class_def.cl_path "." )) ^ ",\n") - | _ -> ( ) - ) - ) types; - output_files "#endif\n"; - output_files " 0 };\n"; - - output_files "} // namespace hx\n"; - output_files "void __files__boot() { __hxcpp_set_debugger_info(hx::__hxcpp_all_classes, hx::__hxcpp_all_files_fullpath); }\n"; - - files_file#close;; - - -let begin_header_file output_h def_string = - output_h ("#ifndef INCLUDED_" ^ def_string ^ "\n"); - output_h ("#define INCLUDED_" ^ def_string ^ "\n\n"); - output_h "#ifndef HXCPP_H\n"; - output_h "#include \n"; - output_h "#endif\n\n";; - -let end_header_file output_h def_string = - output_h ("\n#endif /* INCLUDED_" ^ def_string ^ " */ \n");; - -let new_placed_cpp_file common_ctx class_path = - let base_dir = common_ctx.file in - - if (Common.defined common_ctx Define.Vcproj ) then begin - make_class_directories base_dir ("src"::[]); - cached_source_writer common_ctx - ( base_dir ^ "/src/" ^ ( String.concat "-" (fst class_path) ) ^ "-" ^ - (snd class_path) ^ (source_file_extension common_ctx) ) - end else - new_cpp_file common_ctx common_ctx.file class_path;; - - - -let generate_enum_files common_ctx enum_def super_deps meta file_info = - let class_path = enum_def.e_path in - let just_class_name = (snd class_path) in - let class_name = just_class_name ^ "_obj" in - let remap_class_name = ("::" ^ (join_class_path_remap class_path "::") ) in - (*let cpp_file = new_cpp_file common_ctx.file class_path in*) - let cpp_file = new_placed_cpp_file common_ctx class_path in - let output_cpp = (cpp_file#write) in - let debug = if (has_meta_key enum_def.e_meta Meta.NoDebug) || ( Common.defined common_ctx Define.NoDebug) - then 0 else 1 in - - let ctx = new_context common_ctx cpp_file debug file_info in - - if (debug>1) then - print_endline ("Found enum definition:" ^ (join_class_path class_path "::" )); - - output_cpp "#include \n\n"; - - let referenced = find_referenced_types common_ctx (TEnumDecl enum_def) super_deps (Hashtbl.create 0) false false false in - List.iter (add_include cpp_file) referenced; - - gen_open_namespace output_cpp class_path; - output_cpp "\n"; - - PMap.iter (fun _ constructor -> - let name = keyword_remap constructor.ef_name in - match constructor.ef_type with - | TFun (args,_) -> - output_cpp (remap_class_name ^ " " ^ class_name ^ "::" ^ name ^ "(" ^ - (gen_tfun_arg_list args) ^")\n"); - output_cpp ("\t{ return hx::CreateEnum< " ^ class_name ^ " >(" ^ (str name) ^ "," ^ - (string_of_int constructor.ef_index) ^ ",hx::DynamicArray(0," ^ - (string_of_int (List.length args)) ^ ")" ); - List.iter (fun (arg,_,_) -> output_cpp (".Add(" ^ (keyword_remap arg) ^ ")")) args; - output_cpp "); }\n\n" - - | _ -> - output_cpp ( remap_class_name ^ " " ^ class_name ^ "::" ^ name ^ ";\n\n" ) - ) enum_def.e_constrs; - - - - - output_cpp ("HX_DEFINE_CREATE_ENUM(" ^ class_name ^ ")\n\n"); - output_cpp ("int " ^ class_name ^ "::__FindIndex(::String inName)\n{\n"); - PMap.iter (fun _ constructor -> - let name = constructor.ef_name in - let idx = string_of_int constructor.ef_index in - output_cpp ("\tif (inName==" ^ (str name) ^ ") return " ^ idx ^ ";\n") ) enum_def.e_constrs; - output_cpp ("\treturn super::__FindIndex(inName);\n"); - output_cpp ("}\n\n"); - - let constructor_arg_count constructor = - (match constructor.ef_type with | TFun(args,_) -> List.length args | _ -> 0 ) - in - - - (* Dynamic versions of constructors *) - let dump_dynamic_constructor _ constr = - let count = constructor_arg_count constr in - if (count>0) then begin - let nargs = string_of_int count in - output_cpp ("STATIC_HX_DEFINE_DYNAMIC_FUNC" ^ nargs ^ "(" ^ class_name ^ "," ^ - (keyword_remap constr.ef_name) ^ ",return)\n\n"); - end - in - PMap.iter dump_dynamic_constructor enum_def.e_constrs; - - - output_cpp ("int " ^ class_name ^ "::__FindArgCount(::String inName)\n{\n"); - PMap.iter (fun _ constructor -> - let name = constructor.ef_name in - let count = string_of_int (constructor_arg_count constructor) in - output_cpp ("\tif (inName==" ^ (str name) ^ ") return " ^ count ^ ";\n") ) enum_def.e_constrs; - output_cpp ("\treturn super::__FindArgCount(inName);\n"); - output_cpp ("}\n\n"); - - (* Dynamic "Get" Field function - string version *) - output_cpp ("Dynamic " ^ class_name ^ "::__Field(const ::String &inName,hx::PropertyAccess inCallProp)\n{\n"); - let dump_constructor_test _ constr = - output_cpp ("\tif (inName==" ^ (str constr.ef_name) ^ ") return " ^ - (keyword_remap constr.ef_name) ); - if ( (constructor_arg_count constr) > 0 ) then output_cpp "_dyn()"; - output_cpp (";\n") - in - PMap.iter dump_constructor_test enum_def.e_constrs; - output_cpp ("\treturn super::__Field(inName,inCallProp);\n}\n\n"); - - output_cpp "static ::String sStaticFields[] = {\n"; - let sorted = - List.sort (fun f1 f2 -> (PMap.find f1 enum_def.e_constrs ).ef_index - - (PMap.find f2 enum_def.e_constrs ).ef_index ) - (pmap_keys enum_def.e_constrs) in - - List.iter (fun name -> output_cpp ("\t" ^ (str name) ^ ",\n") ) sorted; - - output_cpp "\t::String(null()) };\n\n"; - - (* ENUM - Mark static as used by GC *) - output_cpp "static void sMarkStatics(HX_MARK_PARAMS) {\n"; - PMap.iter (fun _ constructor -> - let name = keyword_remap constructor.ef_name in - match constructor.ef_type with - | TFun (_,_) -> () - | _ -> output_cpp ("\tHX_MARK_MEMBER_NAME(" ^ class_name ^ "::" ^ name ^ ",\"" ^ name ^ "\");\n") ) - enum_def.e_constrs; - output_cpp "};\n\n"; - - (* ENUM - Visit static as used by GC *) - output_cpp "#ifdef HXCPP_VISIT_ALLOCS\n"; - output_cpp "static void sVisitStatic(HX_VISIT_PARAMS) {\n"; - output_cpp ("\tHX_VISIT_MEMBER_NAME(" ^ class_name ^ "::__mClass,\"__mClass\");\n"); - PMap.iter (fun _ constructor -> - let name = keyword_remap constructor.ef_name in - match constructor.ef_type with - | TFun (_,_) -> () - | _ -> output_cpp ("\tHX_VISIT_MEMBER_NAME(" ^ class_name ^ "::" ^ name ^ ",\"" ^ name ^ "\");\n") ) - enum_def.e_constrs; - output_cpp "};\n"; - output_cpp "#endif\n\n"; - - output_cpp "static ::String sMemberFields[] = { ::String(null()) };\n"; - - output_cpp ("hx::Class " ^ class_name ^ "::__mClass;\n\n"); - - output_cpp ("Dynamic __Create_" ^ class_name ^ "() { return new " ^ class_name ^ "; }\n\n"); - - output_cpp ("void " ^ class_name ^ "::__register()\n{\n"); - let text_name = str (join_class_path class_path ".") in - output_cpp ("\nhx::Static(__mClass) = hx::RegisterClass(" ^ text_name ^ - ", hx::TCanCast< " ^ class_name ^ " >,sStaticFields,sMemberFields,\n"); - output_cpp ("\t&__Create_" ^ class_name ^ ", &__Create,\n"); - output_cpp ("\t&super::__SGetClass(), &Create" ^ class_name ^ ", sMarkStatics\n"); - output_cpp("#ifdef HXCPP_VISIT_ALLOCS\n , sVisitStatic\n#endif\n"); - output_cpp ("#ifdef HXCPP_SCRIPTABLE\n , 0\n#endif\n"); - output_cpp (");\n}\n\n"); - - output_cpp ("void " ^ class_name ^ "::__boot()\n{\n"); - (match meta with - | Some expr -> - let ctx = new_context common_ctx cpp_file 1 file_info in - gen_expression_tree ctx true expr "__mClass->__meta__ = " ";\n"; - | _ -> () ); - PMap.iter (fun _ constructor -> - let name = constructor.ef_name in - match constructor.ef_type with - | TFun (_,_) -> () - | _ -> - output_cpp ( "hx::Static(" ^ (keyword_remap name) ^ ") = hx::CreateEnum< " ^ class_name ^ " >(" ^ (str name) ^ "," ^ - (string_of_int constructor.ef_index) ^ ");\n" ) - ) enum_def.e_constrs; - output_cpp ("}\n\n"); - - - - - output_cpp "\n"; - gen_close_namespace output_cpp class_path; - cpp_file#close; - - let h_file = new_header_file common_ctx common_ctx.file class_path in - let super = "hx::EnumBase_obj" in - let output_h = (h_file#write) in - let def_string = join_class_path class_path "_" in - ctx.ctx_output <- output_h; - - begin_header_file output_h def_string; - - List.iter (gen_forward_decl h_file ) referenced; - - gen_open_namespace output_h class_path; - - output_h "\n\n"; - output_h ("class " ^ class_name ^ " : public " ^ super ^ "\n"); - output_h ("{\n\ttypedef " ^ super ^ " super;\n"); - output_h ("\t\ttypedef " ^ class_name ^ " OBJ_;\n"); - output_h "\n\tpublic:\n"; - output_h ("\t\t" ^ class_name ^ "() {};\n"); - output_h ("\t\tHX_DO_ENUM_RTTI;\n"); - output_h ("\t\tstatic void __boot();\n"); - output_h ("\t\tstatic void __register();\n"); - output_h ("\t\t::String GetEnumName( ) const { return " ^ - (str (join_class_path class_path ".")) ^ "; }\n" ); - output_h ("\t\t::String __ToString() const { return " ^ - (str (just_class_name ^ ".") )^ " + tag; }\n\n"); - - - PMap.iter (fun _ constructor -> - let name = keyword_remap constructor.ef_name in - output_h ( "\t\tstatic " ^ remap_class_name ^ " " ^ name ); - match constructor.ef_type with - | TFun (args,_) -> - output_h ( "(" ^ (gen_tfun_arg_list args) ^");\n"); - output_h ( "\t\tstatic Dynamic " ^ name ^ "_dyn();\n"); - | _ -> - output_h ";\n"; - output_h ( "\t\tstatic inline " ^ remap_class_name ^ " " ^ name ^ - "_dyn() { return " ^name ^ "; }\n" ); - ) enum_def.e_constrs; - - output_h "};\n\n"; - - gen_close_namespace output_h class_path; - - end_header_file output_h def_string; - h_file#close; - let depend_referenced = find_referenced_types common_ctx (TEnumDecl enum_def) super_deps (Hashtbl.create 0) false true false in - depend_referenced;; - - -let list_iteri func in_list = - let idx = ref 0 in - List.iter (fun elem -> func !idx elem; idx := !idx + 1 ) in_list -;; - -let has_new_gc_references class_def = - match class_def.cl_dynamic with - | Some _ -> true - | _ -> ( - let is_gc_reference field = - (should_implement_field field) && (is_data_member field) && - match type_string field.cf_type with - | "bool" | "int" | "Float" -> false - | _ -> true - in - List.exists is_gc_reference class_def.cl_ordered_fields - ) -;; - - -let rec has_gc_references class_def = - ( match class_def.cl_super with - | Some def when has_gc_references (fst def) -> true - | _ -> false ) - || has_new_gc_references class_def -;; - -let rec find_next_super_iteration class_def = - match class_def.cl_super with - | Some (klass,params) when has_new_gc_references klass -> class_string klass "_obj" params true - | Some (klass,_) -> find_next_super_iteration klass - | _ -> ""; -;; - -let has_init_field class_def = - match class_def.cl_init with - | Some _ -> true - | _ -> false;; - - -let is_abstract_impl class_def = match class_def.cl_kind with - | KAbstractImpl _ -> true - | _ -> false -;; - -let variable_field field = - (match field.cf_expr with - | Some { eexpr = TFunction function_def } -> is_dynamic_haxe_method field - | _ -> true) -;; - -let is_readable class_def field = - (match field.cf_kind with - | Var { v_read = AccNever } when (is_extern_field field) -> false - | Var { v_read = AccInline } -> false - | Var _ when is_abstract_impl class_def -> false - | _ -> true) -;; - -let is_writable class_def field = - (match field.cf_kind with - | Var { v_write = AccNever } when (is_extern_field field) -> false - | Var { v_read = AccInline } -> false - | Var _ when is_abstract_impl class_def -> false - | _ -> true) -;; - - -let statics_except_meta class_def = (List.filter (fun static -> static.cf_name <> "__meta__" && static.cf_name <> "__rtti") class_def.cl_ordered_statics);; - -let has_set_member_field class_def = - implement_dynamic_here class_def || ( - let reflect_fields = List.filter (reflective class_def) (class_def.cl_ordered_fields) in - let reflect_writable = List.filter (is_writable class_def) reflect_fields in - List.exists variable_field reflect_writable - ) -;; - - -let has_set_static_field class_def = - let reflect_fields = List.filter (reflective class_def) (statics_except_meta class_def) in - let reflect_writable = List.filter (is_writable class_def) reflect_fields in - List.exists variable_field reflect_writable -;; - - -let has_get_fields class_def = - implement_dynamic_here class_def || ( - let is_data_field field = (match follow field.cf_type with | TFun _ -> false | _ -> true) in - List.exists is_data_field class_def.cl_ordered_fields - ) -;; - -let has_get_member_field class_def = - implement_dynamic_here class_def || ( - let reflect_fields = List.filter (reflective class_def) (class_def.cl_ordered_fields) in - List.exists (is_readable class_def) reflect_fields - ) -;; - - -let has_get_static_field class_def = - let reflect_fields = List.filter (reflective class_def) (statics_except_meta class_def) in - List.exists (is_readable class_def) reflect_fields -;; - - - - - - - -let has_boot_field class_def = - List.exists has_field_init (List.filter should_implement_field class_def.cl_ordered_statics); -;; - - -let is_macro meta = - Meta.has Meta.Macro meta -;; - - -let access_str a = match a with - | AccNormal -> "AccNormal" - | AccNo -> "AccNo" - | AccNever -> "AccNever" - | AccResolve -> "AccResolve" - | AccCall -> "AccCall" - | AccInline -> "AccInline" - | AccRequire(_,_) -> "AccRequire" ;; - -let generate_class_files common_ctx member_types super_deps constructor_deps class_def file_info inScriptable = - let class_path = class_def.cl_path in - let nativeGen = has_meta_key class_def.cl_meta Meta.NativeGen in - let class_name = (snd class_path) ^ (if nativeGen then "" else "_obj") in - let dot_name = join_class_path class_path "." in - let smart_class_name = (snd class_path) in - (*let cpp_file = new_cpp_file common_ctx.file class_path in*) - let cpp_file = new_placed_cpp_file common_ctx class_path in - let output_cpp = (cpp_file#write) in - let debug = if (has_meta_key class_def.cl_meta Meta.NoDebug) || ( Common.defined common_ctx Define.NoDebug) - then 0 else 1 in - let scriptable = inScriptable && not class_def.cl_private in - let ctx = new_context common_ctx cpp_file debug file_info in - - - ctx.ctx_class_name <- "::" ^ (join_class_path class_def.cl_path "::"); - ctx.ctx_class_super_name <- (match class_def.cl_super with - | Some (klass, params) -> class_string klass "_obj" params true - | _ -> ""); - ctx.ctx_class_member_types <- member_types; - if (debug>1) then print_endline ("Found class definition:" ^ ctx.ctx_class_name); - - let ptr_name = "hx::ObjectPtr< " ^ class_name ^ " >" in - let constructor_arg_var_list = - match class_def.cl_constructor with - | Some definition -> - (match definition.cf_expr with - | Some { eexpr = TFunction function_def } -> - List.map (fun (v,o) -> (v.v_name, gen_arg_type_name v.v_name o v.v_type "__o_")) - function_def.tf_args; - | _ -> - (match follow definition.cf_type with - | TFun (args,_) -> List.map (fun (a,_,t) -> (a, (type_string t, a)) ) args - | _ -> []) - ) - | _ -> [] in - let constructor_type_var_list = - List.map snd constructor_arg_var_list in - let constructor_var_list = List.map snd constructor_type_var_list in - let constructor_type_args = String.concat "," - (List.map (fun (t,a) -> t ^ " " ^ a) constructor_type_var_list) in - let constructor_args = String.concat "," constructor_var_list in - - let implement_dynamic = implement_dynamic_here class_def in - - output_cpp "#include \n\n"; - - let force_field = scriptable && (has_get_member_field class_def) in - let field_integer_dynamic = force_field || (has_field_integer_lookup class_def) in - let field_integer_numeric = force_field || (has_field_integer_numeric_lookup class_def) in - - let all_referenced = find_referenced_types ctx.ctx_common (TClassDecl class_def) super_deps constructor_deps false false scriptable in - List.iter ( add_include cpp_file ) all_referenced; - - - (* All interfaces (and sub-interfaces) implemented *) - let implemented_hash = Hashtbl.create 0 in - List.iter (fun imp -> - let rec descend_interface interface = - let imp_path = (fst interface).cl_path in - let interface_name = "::" ^ (join_class_path_remap imp_path "::" ) in - if ( not (Hashtbl.mem implemented_hash interface_name) ) then begin - Hashtbl.add implemented_hash interface_name (); - List.iter descend_interface (fst interface).cl_implements; - end; - match (fst interface).cl_super with - | Some (interface,params) -> descend_interface (interface,params) - | _ -> () - in descend_interface imp - ) (real_interfaces class_def.cl_implements); - let implemented = hash_keys implemented_hash in - - if (scriptable) then - output_cpp "#include \n"; - - output_cpp ( get_class_code class_def Meta.CppFileCode ); - let inc = get_meta_string_path class_def.cl_meta Meta.CppInclude in - if (inc<>"") then - output_cpp ("#include \"" ^ inc ^ "\"\n"); - - gen_open_namespace output_cpp class_path; - output_cpp "\n"; - - output_cpp ( get_class_code class_def Meta.CppNamespaceCode ); - - if (not class_def.cl_interface) && not nativeGen then begin - output_cpp ("Void " ^ class_name ^ "::__construct(" ^ constructor_type_args ^ ")\n{\n"); - (match class_def.cl_constructor with - | Some definition -> - (match definition.cf_expr with - | Some { eexpr = TFunction function_def } -> - if has_meta_key definition.cf_meta Meta.NoDebug then ctx.ctx_debug_level <- 0; - if ctx.ctx_debug_level >0 then begin - hx_stack_push ctx output_cpp dot_name "new" function_def.tf_expr.epos; - output_cpp "HX_STACK_THIS(this)\n"; - List.iter (fun (a,(t,o)) -> output_cpp ("HX_STACK_ARG(" ^ (keyword_remap o) ^ ",\"" ^ a ^"\")\n") ) constructor_arg_var_list; - end; - - if (has_default_values function_def.tf_args) then begin - generate_default_values ctx function_def.tf_args "__o_"; - end; - gen_expression_tree ctx false (to_block function_def.tf_expr) "" ";\n"; - ctx.ctx_debug_level <- debug; - | _ -> () - ) - | _ -> ()); - output_cpp "\treturn null();\n"; - output_cpp "}\n\n"; - - (* Destructor goes in the cpp file so we can "see" the full definition of the member vars *) - output_cpp ( "//" ^ class_name ^ "::~" ^ class_name ^ "() { }\n\n"); - output_cpp ("Dynamic " ^ class_name ^ "::__CreateEmpty() { return new " ^ class_name ^ "; }\n"); - - output_cpp (ptr_name ^ " " ^ class_name ^ "::__new(" ^constructor_type_args ^")\n"); - - let create_result () = - output_cpp ("{ " ^ ptr_name ^ " _result_ = new " ^ class_name ^ "();\n"); - in - create_result (); - output_cpp ("\t_result_->__construct(" ^ constructor_args ^ ");\n"); - output_cpp ("\treturn _result_;}\n\n"); - - output_cpp ("Dynamic " ^ class_name ^ "::__Create(hx::DynamicArray inArgs)\n"); - create_result (); - output_cpp ("\t_result_->__construct(" ^ (array_arg_list constructor_var_list) ^ ");\n"); - output_cpp ("\treturn _result_;}\n\n"); - if ( (List.length implemented) > 0 ) then begin - output_cpp ("hx::Object *" ^ class_name ^ "::__ToInterface(const hx::type_info &inType) {\n"); - List.iter (fun interface_name -> - output_cpp ("\tif (inType==typeid( " ^ interface_name ^ "_obj)) " ^ - "return operator " ^ interface_name ^ "_obj *();\n"); - ) implemented; - output_cpp ("\treturn super::__ToInterface(inType);\n}\n\n"); - - - List.iter (fun interface_name -> - output_cpp (class_name ^ "::operator " ^ interface_name ^ "_obj *()\n\t" ^ - "{ return new " ^ interface_name ^ "_delegate_< " ^ class_name ^" >(this); }\n" ); - ) implemented; - end; - - end; - - (match class_def.cl_init with - | Some expression -> - output_cpp ("void " ^ class_name^ "::__init__() {\n"); - hx_stack_push ctx output_cpp dot_name "__init__" expression.epos; - gen_expression_tree (new_context common_ctx cpp_file debug file_info) false (to_block expression) "" ""; - output_cpp "}\n\n"; - | _ -> ()); - - let statics_except_meta = statics_except_meta class_def in - let implemented_fields = List.filter should_implement_field statics_except_meta in - let dump_field_name = (fun field -> output_cpp ("\t" ^ (str field.cf_name) ^ ",\n")) in - let implemented_instance_fields = List.filter should_implement_field class_def.cl_ordered_fields in - - List.iter - (gen_field ctx class_def class_name smart_class_name dot_name false class_def.cl_interface) - class_def.cl_ordered_fields; - List.iter - (gen_field ctx class_def class_name smart_class_name dot_name true class_def.cl_interface) statics_except_meta; - output_cpp "\n"; - - let override_iteration = (not nativeGen) && (has_new_gc_references class_def) in - - (* Initialise non-static variables *) - if ( (not class_def.cl_interface) && (not nativeGen) ) then begin - output_cpp (class_name ^ "::" ^ class_name ^ "()\n{\n"); - if (implement_dynamic) then - output_cpp "\tHX_INIT_IMPLEMENT_DYNAMIC;\n"; - List.iter - (fun field -> let remap_name = keyword_remap field.cf_name in - match field.cf_expr with - | Some { eexpr = TFunction function_def } -> - if (is_dynamic_haxe_method field) then - output_cpp ("\t" ^ remap_name ^ " = new __default_" ^ remap_name ^ "(this);\n") - | _ -> () - ) - class_def.cl_ordered_fields; - output_cpp "}\n\n"; - - - let dump_field_iterator macro field = - if (is_data_member field) then begin - let remap_name = keyword_remap field.cf_name in - output_cpp ("\t" ^ macro ^ "(" ^ remap_name ^ ",\"" ^ field.cf_name^ "\");\n"); - - (match field.cf_kind with Var { v_read = AccCall } when (is_dynamic_accessor ("get_" ^ field.cf_name) "get" field class_def) -> - let name = "get_" ^ field.cf_name in - output_cpp ("\t" ^ macro ^ "(" ^ name ^ "," ^ "\"" ^ name ^ "\");\n" ) | _ -> ()); - (match field.cf_kind with Var { v_write = AccCall } when (is_dynamic_accessor ("set_" ^ field.cf_name) "set" field class_def) -> - let name = "set_" ^ field.cf_name in - output_cpp ("\t" ^ macro ^ "(" ^ name ^ "," ^ "\"" ^ name ^ "\");\n" ) | _ -> ()); - end - in - - - if (override_iteration) then begin - let super_needs_iteration = find_next_super_iteration class_def in - (* MARK function - explicitly mark all child pointers *) - output_cpp ("void " ^ class_name ^ "::__Mark(HX_MARK_PARAMS)\n{\n"); - output_cpp ("\tHX_MARK_BEGIN_CLASS(" ^ smart_class_name ^ ");\n"); - if (implement_dynamic) then - output_cpp "\tHX_MARK_DYNAMIC;\n"; - List.iter (dump_field_iterator "HX_MARK_MEMBER_NAME") implemented_instance_fields; - (match super_needs_iteration with - | "" -> () - | super -> output_cpp ("\t" ^ super^"::__Mark(HX_MARK_ARG);\n" ) ); - output_cpp "\tHX_MARK_END_CLASS();\n"; - output_cpp "}\n\n"; - - (* Visit function - explicitly visit all child pointers *) - output_cpp ("void " ^ class_name ^ "::__Visit(HX_VISIT_PARAMS)\n{\n"); - if (implement_dynamic) then - output_cpp "\tHX_VISIT_DYNAMIC;\n"; - List.iter (dump_field_iterator "HX_VISIT_MEMBER_NAME") implemented_instance_fields; - (match super_needs_iteration with - | "" -> () - | super -> output_cpp ("\t" ^ super ^ "::__Visit(HX_VISIT_ARG);\n") ); - output_cpp "}\n\n"; - end; - - - let reflect_member_fields = List.filter (reflective class_def) class_def.cl_ordered_fields in - let reflect_member_readable = List.filter (is_readable class_def) reflect_member_fields in - let reflect_member_writable = List.filter (is_writable class_def) reflect_member_fields in - let reflect_write_member_variables = List.filter variable_field reflect_member_writable in - - let reflect_static_fields = List.filter (reflective class_def) (statics_except_meta) in - let reflect_static_readable = List.filter (is_readable class_def) reflect_static_fields in - let reflect_static_writable = List.filter (is_writable class_def) reflect_static_fields in - let reflect_write_static_variables = List.filter variable_field reflect_static_writable in - - let dump_quick_field_test fields = - if ( (List.length fields) > 0) then begin - let len = function (_,l,_) -> l in - let sfields = List.sort (fun f1 f2 -> (len f1)-(len f2)) fields in - let len_case = ref (-1) in - output_cpp "\tswitch(inName.length) {\n"; - List.iter (fun (field,l,result) -> - if (l <> !len_case) then begin - if (!len_case>=0) then output_cpp "\t\tbreak;\n"; - output_cpp ("\tcase " ^ (string_of_int l) ^ ":\n"); - len_case := l; - end; - output_cpp ("\t\tif (HX_FIELD_EQ(inName,\"" ^ (Ast.s_escape field) ^ "\") ) { " ^ result ^ " }\n"); - ) sfields; - output_cpp "\t}\n"; - end; - in - - let checkPropCall field = if ( (has_meta_key class_def.cl_meta Meta.NativeProperty) || - (has_meta_key field.cf_meta Meta.NativeProperty) || - (Common.defined common_ctx Define.ForceNativeProperty) ) - then - "inCallProp != hx::paccNever" - else - "inCallProp == hx::paccAlways" - in - - - - if (has_get_member_field class_def) then begin - (* Dynamic "Get" Field function - string version *) - output_cpp ("Dynamic " ^ class_name ^ "::__Field(const ::String &inName,hx::PropertyAccess inCallProp)\n{\n"); - let get_field_dat = List.map (fun f -> - (f.cf_name, String.length f.cf_name, - (match f.cf_kind with - | Var { v_read = AccCall } when is_extern_field f -> "if (" ^ (checkPropCall f) ^ ") return " ^(keyword_remap ("get_" ^ f.cf_name)) ^ "()" - | Var { v_read = AccCall } -> "return " ^ (checkPropCall f) ^ " ? " ^ (keyword_remap ("get_" ^ f.cf_name)) ^ "() : " ^ - ((keyword_remap f.cf_name) ^ if (variable_field f) then "" else "_dyn()") - | _ -> "return " ^ ((keyword_remap f.cf_name) ^ if (variable_field f) then "" else "_dyn()") - ) ^ ";" - ) ) - in - dump_quick_field_test (get_field_dat reflect_member_readable); - if (implement_dynamic) then - output_cpp "\tHX_CHECK_DYNAMIC_GET_FIELD(inName);\n"; - output_cpp ("\treturn super::__Field(inName,inCallProp);\n}\n\n"); - - (* Dynamic "Get" Field function - int version *) - if ( field_integer_numeric || field_integer_dynamic) then begin - let dump_static_ids = (fun field -> - let remap_name = keyword_remap field.cf_name in - output_cpp ("static int __id_" ^ remap_name ^ " = __hxcpp_field_to_id(\"" ^ - (field.cf_name) ^ "\");\n"); - ) in - List.iter dump_static_ids reflect_member_readable; - output_cpp "\n\n"; - - - let output_ifield return_type function_name all_fields = - output_cpp (return_type ^" " ^ class_name ^ "::" ^ function_name ^ "(int inFieldID)\n{\n"); - let dump_field_test = (fun f -> - let remap_name = keyword_remap f.cf_name in - output_cpp ("\tif (inFieldID==__id_" ^ remap_name ^ ") return " ^ - ( if (return_type="Float") then "hx::ToDouble( " else "" ) ^ - (match f.cf_kind with - | Var { v_read = AccCall } -> (keyword_remap ("get_" ^ f.cf_name)) ^ "()" - | _ -> (remap_name ^ if ( variable_field f) then "" else "_dyn()") - ) ^ ( if (return_type="Float") then " ) " else "" ) ^ ";\n"); - ) in - List.iter dump_field_test (List.filter (fun f -> all_fields || (is_numeric_field f)) reflect_member_readable); - if (implement_dynamic) then - output_cpp "\tHX_CHECK_DYNAMIC_GET_INT_FIELD(inFieldID);\n"; - output_cpp ("\treturn super::" ^ function_name ^ "(inFieldID);\n}\n\n"); - in - - if (field_integer_dynamic) then output_ifield "Dynamic" "__IField" true; - if (field_integer_numeric) then output_ifield "double" "__INumField" false; - end; - end; - - if (has_get_static_field class_def) then begin - output_cpp ("bool " ^ class_name ^ "::__GetStatic(const ::String &inName, Dynamic &outValue, hx::PropertyAccess inCallProp)\n{\n"); - let get_field_dat = List.map (fun f -> - (f.cf_name, String.length f.cf_name, - (match f.cf_kind with - | Var { v_read = AccCall } when is_extern_field f -> "if (" ^ (checkPropCall f) ^ ") { outValue = " ^(keyword_remap ("get_" ^ f.cf_name)) ^ "(); return true; }" - | Var { v_read = AccCall } -> "outValue = " ^ (checkPropCall f) ^ " ? " ^ (keyword_remap ("get_" ^ f.cf_name)) ^ "() : " ^ - ((keyword_remap f.cf_name) ^ if (variable_field f) then "" else "_dyn()") ^ "; return true;"; - | _ -> "outValue = " ^ ((keyword_remap f.cf_name) ^ (if (variable_field f) then "" else "_dyn()") ^ "; return true; ") - ) - ) ) - in - dump_quick_field_test (get_field_dat reflect_static_readable); - output_cpp ("\treturn false;\n}\n\n"); - end; - - (* Dynamic "Set" Field function *) - if (has_set_member_field class_def) then begin - - output_cpp ("Dynamic " ^ class_name ^ "::__SetField(const ::String &inName,const Dynamic &inValue,hx::PropertyAccess inCallProp)\n{\n"); - - let set_field_dat = List.map (fun f -> - let default_action = - (keyword_remap f.cf_name) ^ "=inValue.Cast< " ^ (type_string f.cf_type) ^ " >();" ^ - " return inValue;" in - (f.cf_name, String.length f.cf_name, - (match f.cf_kind with - | Var { v_write = AccCall } -> "if (" ^ (checkPropCall f) ^ ") return " ^ (keyword_remap ("set_" ^ f.cf_name)) ^ "(inValue);" - ^ ( if is_extern_field f then "" else default_action ) - | _ -> default_action - ) - ) - ) in - - dump_quick_field_test (set_field_dat reflect_write_member_variables); - if (implement_dynamic) then begin - output_cpp ("\ttry { return super::__SetField(inName,inValue,inCallProp); }\n"); - output_cpp ("\tcatch(Dynamic e) { HX_DYNAMIC_SET_FIELD(inName,inValue); }\n"); - output_cpp "\treturn inValue;\n}\n\n"; - end else - output_cpp ("\treturn super::__SetField(inName,inValue,inCallProp);\n}\n\n"); - end; - - if (has_set_static_field class_def) then begin - - output_cpp ("bool " ^ class_name ^ "::__SetStatic(const ::String &inName,Dynamic &ioValue,hx::PropertyAccess inCallProp)\n{\n"); - - let set_field_dat = List.map (fun f -> - let default_action = - (keyword_remap f.cf_name) ^ "=ioValue.Cast< " ^ (type_string f.cf_type) ^ " >(); return true;" in - (f.cf_name, String.length f.cf_name, - (match f.cf_kind with - | Var { v_write = AccCall } -> "if (" ^ (checkPropCall f) ^ ") ioValue = " ^ (keyword_remap ("set_" ^ f.cf_name)) ^ "(ioValue);" - ^ ( if is_extern_field f then "" else " else " ^ default_action ) - | _ -> default_action - ) - ) - ) in - - dump_quick_field_test (set_field_dat reflect_write_static_variables); - output_cpp ("\treturn false;\n}\n\n"); - end; - - - - - (* For getting a list of data members (eg, for serialization) *) - if (has_get_fields class_def) then begin - let append_field = - (fun field -> output_cpp ("\toutFields->push(" ^( str field.cf_name )^ ");\n")) in - let is_data_field field = (match follow field.cf_type with | TFun _ -> false | _ -> true) in - - output_cpp ("void " ^ class_name ^ "::__GetFields(Array< ::String> &outFields)\n{\n"); - List.iter append_field (List.filter is_data_field class_def.cl_ordered_fields); - if (implement_dynamic) then - output_cpp "\tHX_APPEND_DYNAMIC_FIELDS(outFields);\n"; - output_cpp "\tsuper::__GetFields(outFields);\n"; - output_cpp "};\n\n"; - end; - - let storage field = match type_string field.cf_type with - | "bool" -> "hx::fsBool" - | "int" -> "hx::fsInt" - | "Float" -> "hx::fsFloat" - | "::String" -> "hx::fsString" - | str -> "hx::fsObject" ^ " /*" ^ str ^ "*/ " - in - let dump_member_storage = (fun field -> - output_cpp ("\t{" ^ (storage field) ^ ",(int)offsetof(" ^ class_name ^"," ^ (keyword_remap field.cf_name) ^")," ^ - (str field.cf_name) ^ "},\n") - ) - in - let dump_static_storage = (fun field -> - output_cpp ("\t{" ^ (storage field) ^ ",(void *) &" ^ class_name ^"::" ^ (keyword_remap field.cf_name) ^"," ^ - (str field.cf_name) ^ "},\n") - ) - in - - output_cpp "#if HXCPP_SCRIPTABLE\n"; - - let stored_fields = List.filter is_data_member implemented_instance_fields in - if ( (List.length stored_fields) > 0) then begin - output_cpp "static hx::StorageInfo sMemberStorageInfo[] = {\n"; - List.iter dump_member_storage stored_fields; - output_cpp "\t{ hx::fsUnknown, 0, null()}\n};\n"; - end else - output_cpp "static hx::StorageInfo *sMemberStorageInfo = 0;\n"; - - let stored_statics = List.filter is_data_member implemented_fields in - if ( (List.length stored_statics) > 0) then begin - output_cpp "static hx::StaticInfo sStaticStorageInfo[] = {\n"; - List.iter dump_static_storage stored_statics; - output_cpp "\t{ hx::fsUnknown, 0, null()}\n};\n"; - end else - output_cpp "static hx::StaticInfo *sStaticStorageInfo = 0;\n"; - - output_cpp "#endif\n\n"; - end; (* cl_interface *) - - let reflective_members = List.filter (reflective class_def) implemented_instance_fields in - let sMemberFields = if List.length reflective_members>0 then begin - output_cpp "static ::String sMemberFields[] = {\n"; - List.iter dump_field_name reflective_members; - output_cpp "\t::String(null()) };\n\n"; - "sMemberFields" - end else - "0 /* sMemberFields */"; - in - - if (not nativeGen) then begin - (* Mark static variables as used *) - output_cpp "static void sMarkStatics(HX_MARK_PARAMS) {\n"; - output_cpp ("\tHX_MARK_MEMBER_NAME(" ^ class_name ^ "::__mClass,\"__mClass\");\n"); - List.iter (fun field -> - if (is_data_member field) then - output_cpp ("\tHX_MARK_MEMBER_NAME(" ^ class_name ^ "::" ^ (keyword_remap field.cf_name) ^ ",\"" ^ field.cf_name ^ "\");\n") ) - implemented_fields; - output_cpp "};\n\n"; - - (* Visit static variables *) - output_cpp "#ifdef HXCPP_VISIT_ALLOCS\n"; - output_cpp "static void sVisitStatics(HX_VISIT_PARAMS) {\n"; - output_cpp ("\tHX_VISIT_MEMBER_NAME(" ^ class_name ^ "::__mClass,\"__mClass\");\n"); - List.iter (fun field -> - if (is_data_member field) then - output_cpp ("\tHX_VISIT_MEMBER_NAME(" ^ class_name ^ "::" ^ (keyword_remap field.cf_name) ^ ",\"" ^ field.cf_name ^ "\");\n") ) - implemented_fields; - output_cpp "};\n\n"; - output_cpp "#endif\n\n"; - end; - - let script_type t optional = if optional then "Object" else - match type_string t with - | "bool" -> "Int" - | "int" -> "Int" - | "Float" -> "Float" - | "::String" -> "String" - | "Null" -> "Void" - | "Void" -> "Void" - | _ -> "Object" - in - let script_signature t optional = match script_type t optional with - | "Bool" -> "b" - | "Int" -> "i" - | "Float" -> "f" - | "String" -> "s" - | "Void" -> "v" - | _ -> "o" - in - let script_size_type t optional = match script_type t optional with - | "Object" -> "void *" - | x -> x - in - - let generate_script_function isStatic field scriptName callName = - match follow field.cf_type with - | TFun (args,return_type) -> - output_cpp ("\nstatic void " ^ scriptName ^ "(hx::CppiaCtx *ctx) {\n"); - let ret = script_signature return_type false in - if (ret<>"v") then output_cpp ("ctx->return" ^ (script_type return_type false) ^ "("); - if isStatic then - output_cpp (class_name ^ "::" ^ callName ^ "(") - else - output_cpp ("((" ^ class_name ^ "*)ctx->getThis())->" ^ callName ^ "("); - - let (signature,_,_) = List.fold_left (fun (signature,sep,size) (_,opt,t) -> - output_cpp (sep ^ "ctx->get" ^ (script_type t opt) ^ "(" ^ size ^ ")"); - (signature ^ (script_signature t opt ), ",", (size^"+sizeof(" ^ (script_size_type t opt) ^ ")") ) ) (ret,"","sizeof(void*)") args - in - - output_cpp ")"; - if (ret<>"v") then output_cpp (")"); - output_cpp (";\n}\n"); - signature; - | _ -> "" - in - - - if (scriptable && not nativeGen) then begin - let dump_script_field idx (field,f_args,return_t) = - let args = if (class_def.cl_interface) then - gen_tfun_interface_arg_list f_args - else - gen_tfun_arg_list f_args in - let names = List.map (fun (n,_,_) -> keyword_remap n) f_args in - let return_type = type_string return_t in - let ret = if (return_type="Void") then " " else "return " in - let name = keyword_remap field.cf_name in - let vtable = "__scriptVTable[" ^ (string_of_int (idx+1) ) ^ "] " in - let args_varray = (List.fold_left (fun l n -> l ^ ".Add(" ^ n ^ ")") "Array()" names) in - output_cpp (" " ^ return_type ^ " " ^ name ^ "( " ^ args ^ " ) { "); - output_cpp ("\n\tif (" ^ vtable ^ ") {\n" ); - output_cpp ("\t\thx::CppiaCtx *__ctx = hx::CppiaCtx::getCurrent();\n" ); - output_cpp ("\t\thx::AutoStack __as(__ctx);\n" ); - output_cpp ("\t\t__ctx->pushObject(" ^ (if class_def.cl_interface then "mDelegate.mPtr" else "this" ) ^");\n" ); - List.iter (fun (name,opt, t ) -> - output_cpp ("\t\t__ctx->push" ^ (script_type t opt) ^ "(" ^ (keyword_remap name) ^ ");\n" ); - ) f_args; - output_cpp ("\t\t" ^ ret ^ "__ctx->run" ^ (script_type return_t false) ^ "(" ^ vtable ^ ");\n" ); - output_cpp ("\t} else " ^ ret ); - - if (class_def.cl_interface) then begin - output_cpp (" mDelegate->__Field(HX_CSTRING(\"" ^ field.cf_name ^ "\"), hx::paccNever)"); - if (List.length names <= 5) then - output_cpp ("->__run(" ^ (String.concat "," names) ^ ");") - else - output_cpp ("->__Run(" ^ args_varray ^ ");"); - end else - output_cpp (class_name ^ "::" ^ name ^ "(" ^ (String.concat "," names)^ ");"); - output_cpp ("return null(); }\n"); - if (class_def.cl_interface) then begin - output_cpp (" Dynamic " ^ name ^ "_dyn() { return mDelegate->__Field(HX_CSTRING(\"" ^ field.cf_name ^ "\"), hx::paccNever); }\n\n"); - - end - in - - let not_toString = fun (field,args,_) -> field.cf_name<>"toString" || class_def.cl_interface in - let functions = List.filter not_toString (all_virtual_functions class_def) in - let new_sctipt_functions = List.filter (fun (f,_,_) -> not (is_override class_def f.cf_name) ) functions in - let sctipt_name = class_name ^ "__scriptable" in - output_cpp ("class " ^ sctipt_name ^ " : public " ^ class_name ^ " {\n" ); - output_cpp (" typedef "^sctipt_name ^" __ME;\n"); - output_cpp (" typedef "^class_name ^" super;\n"); - let has_funky_toString = List.exists (fun f -> f.cf_name="toString") class_def.cl_ordered_statics || - List.exists (fun f -> f.cf_name="toString" && field_arg_count f <> 0) class_def.cl_ordered_fields in - let super_string = if has_funky_toString then class_name ^ "::super" else class_name in - output_cpp (" typedef "^ super_string ^" __superString;\n"); - if (class_def.cl_interface) then - output_cpp (" HX_DEFINE_SCRIPTABLE_INTERFACE\n") - else begin - output_cpp (" HX_DEFINE_SCRIPTABLE(HX_ARR_LIST" ^ (string_of_int (List.length constructor_var_list) ) ^ ")\n"); - if (not implement_dynamic) then - output_cpp "\tHX_DEFINE_SCRIPTABLE_DYNAMIC;\n"; - end; - - list_iteri dump_script_field functions; - output_cpp ("};\n\n"); - - if (List.length new_sctipt_functions) > 0 then begin - let sigs = Hashtbl.create 0 in - List.iter (fun (f,_,_) -> - let s = generate_script_function false f ("__s_" ^f.cf_name) (keyword_remap f.cf_name) in - Hashtbl.add sigs f.cf_name s - ) new_sctipt_functions; - - output_cpp "static hx::ScriptNamedFunction __scriptableFunctions[] = {\n"; - List.iter (fun (f,_,_) -> - let s = try Hashtbl.find sigs f.cf_name with Not_found -> "v" in - output_cpp (" hx::ScriptNamedFunction(\"" ^ f.cf_name ^ "\",__s_" ^ f.cf_name ^ ",\"" ^ s ^ "\"),\n" ) ) new_sctipt_functions; - output_cpp " hx::ScriptNamedFunction(0,0,0) };\n"; - end else - output_cpp "static hx::ScriptNamedFunction *__scriptableFunctions = 0;\n"; - end; - - - - let class_name_text = join_class_path class_path "." in - - (* Initialise static in boot function ... *) - if (not class_def.cl_interface && not nativeGen) then begin - (* Remap the specialised "extern" classes back to the generic names *) - output_cpp ("hx::Class " ^ class_name ^ "::__mClass;\n\n"); - if (scriptable) then begin - (match class_def.cl_constructor with - | Some field -> - let signature = generate_script_function false field "__script_construct_func" "__construct" in - output_cpp ("hx::ScriptFunction " ^ class_name ^ "::__script_construct(__script_construct_func,\"" ^ signature ^ "\");\n"); - | _ -> - output_cpp ("hx::ScriptFunction " ^ class_name ^ "::__script_construct(0,0);\n"); - ); - end; - - let reflective_statics = List.filter (reflective class_def) implemented_fields in - let sStaticFields = if List.length reflective_statics > 0 then begin - output_cpp "static ::String sStaticFields[] = {\n"; - List.iter dump_field_name reflective_statics; - output_cpp "\t::String(null()) };\n\n"; - "sStaticFields"; - end else - "0 /* sStaticFields */" - in - - output_cpp ("void " ^ class_name ^ "::__register()\n{\n"); - output_cpp ("\thx::Static(__mClass) = new hx::Class_obj();\n"); - output_cpp ("\t__mClass->mName = " ^ (str class_name_text) ^ ";\n"); - output_cpp ("\t__mClass->mSuper = &super::__SGetClass();\n"); - output_cpp ("\t__mClass->mConstructEmpty = &__CreateEmpty;\n"); - output_cpp ("\t__mClass->mConstructArgs = &__Create;\n"); - output_cpp ("\t__mClass->mGetStaticField = &" ^ ( - if (has_get_static_field class_def) then class_name ^ "::__GetStatic;\n" else "hx::Class_obj::GetNoStaticField;\n" )); - output_cpp ("\t__mClass->mSetStaticField = &" ^ ( - if (has_set_static_field class_def) then class_name ^ "::__SetStatic;\n" else "hx::Class_obj::SetNoStaticField;\n" )); - output_cpp ("\t__mClass->mMarkFunc = sMarkStatics;\n"); - output_cpp ("\t__mClass->mStatics = hx::Class_obj::dupFunctions(" ^ sStaticFields ^ ");\n"); - output_cpp ("\t__mClass->mMembers = hx::Class_obj::dupFunctions(" ^ sMemberFields ^ ");\n"); - output_cpp ("\t__mClass->mCanCast = hx::TCanCast< " ^ class_name ^ " >;\n"); - output_cpp ("#ifdef HXCPP_VISIT_ALLOCS\n\t__mClass->mVisitFunc = sVisitStatics;\n#endif\n"); - output_cpp ("#ifdef HXCPP_SCRIPTABLE\n\t__mClass->mMemberStorageInfo = sMemberStorageInfo;\n#endif\n"); - output_cpp ("#ifdef HXCPP_SCRIPTABLE\n\t__mClass->mStaticStorageInfo = sStaticStorageInfo;\n#endif\n"); - output_cpp ("\thx::RegisterClass(__mClass->mName, __mClass);\n"); - if (scriptable) then - output_cpp (" HX_SCRIPTABLE_REGISTER_CLASS(\""^class_name_text^"\"," ^ class_name ^ ");\n"); - output_cpp ("}\n\n"); - - end else if not nativeGen then begin - output_cpp ("hx::Class " ^ class_name ^ "::__mClass;\n\n"); - - output_cpp ("void " ^ class_name ^ "::__register()\n{\n"); - - output_cpp ("\thx::Static(__mClass) = new hx::Class_obj();\n"); - output_cpp ("\t__mClass->mName = " ^ (str class_name_text) ^ ";\n"); - output_cpp ("\t__mClass->mSuper = &super::__SGetClass();\n"); - output_cpp ("\t__mClass->mMarkFunc = sMarkStatics;\n"); - (*output_cpp ("\t__mClass->mStatics = hx::Class_obj::dupFunctions(" ^ sStaticFields ^ ");\n");*) - output_cpp ("\t__mClass->mMembers = hx::Class_obj::dupFunctions(" ^ sMemberFields ^ ");\n"); - output_cpp ("\t__mClass->mCanCast = hx::TCanCast< " ^ class_name ^ " >;\n"); - output_cpp ("#ifdef HXCPP_VISIT_ALLOCS\n\t__mClass->mVisitFunc = sVisitStatics;\n#endif\n"); - output_cpp ("\thx::RegisterClass(__mClass->mName, __mClass);\n"); - if (scriptable) then - output_cpp (" HX_SCRIPTABLE_REGISTER_INTERFACE(\""^class_name_text^"\"," ^ class_name ^ ");\n"); - output_cpp ("}\n\n"); - end; - - if (has_boot_field class_def) then begin - output_cpp ("void " ^ class_name ^ "::__boot()\n{\n"); - List.iter (gen_field_init ctx ) (List.filter should_implement_field class_def.cl_ordered_statics); - output_cpp ("}\n\n"); - end; - - - gen_close_namespace output_cpp class_path; - - cpp_file#close; - - - let h_file = new_header_file common_ctx common_ctx.file class_path in - let super = match class_def.cl_super with - | Some (klass,params) -> (class_string klass "_obj" params true) - | _ when nativeGen -> "" - | _ -> if (class_def.cl_interface) then "hx::Interface" else "hx::Object" - in - let output_h = (h_file#write) in - let def_string = join_class_path class_path "_" in - ctx.ctx_output <- output_h; - - begin_header_file output_h def_string; - - (* Include the real header file for the super class *) - (match class_def.cl_super with - | Some super -> - let super_path = (fst super).cl_path in - h_file#add_include super_path - | _ -> () ); - - (* And any interfaces ... *) - List.iter (fun imp-> h_file#add_include (fst imp).cl_path) - (real_interfaces class_def.cl_implements); - - (* Only need to foreward-declare classes that are mentioned in the header file - (ie, not the implementation) *) - let referenced = find_referenced_types ctx.ctx_common (TClassDecl class_def) super_deps (Hashtbl.create 0) true false scriptable in - List.iter ( gen_forward_decl h_file ) referenced; - - output_h ( get_class_code class_def Meta.HeaderCode ); - let inc = get_meta_string_path class_def.cl_meta Meta.HeaderInclude in - if (inc<>"") then - output_h ("#include \"" ^ inc ^ "\"\n"); - - gen_open_namespace output_h class_path; - output_h "\n\n"; - output_h ( get_class_code class_def Meta.HeaderNamespaceCode ); - - let extern_class = Common.defined common_ctx Define.DllExport in - let attribs = "HXCPP_" ^ (if extern_class then "EXTERN_" else "") ^ "CLASS_ATTRIBUTES " in - - if (super="") then begin - output_h ("class " ^ attribs ^ " " ^ class_name); - output_h "{\n\tpublic:\n"; - end else begin - output_h ("class " ^ attribs ^ " " ^ class_name ^ " : public " ^ super ); - output_h "{\n\tpublic:\n"; - output_h ("\t\ttypedef " ^ super ^ " super;\n"); - output_h ("\t\ttypedef " ^ class_name ^ " OBJ_;\n"); - end; - - if (not class_def.cl_interface && not nativeGen) then begin - output_h ("\t\t" ^ class_name ^ "();\n"); - output_h ("\t\tVoid __construct(" ^ constructor_type_args ^ ");\n"); - output_h "\n\tpublic:\n"; - let new_arg = if (has_gc_references class_def) then "true" else "false" in - output_h ("\t\tinline void *operator new( size_t inSize, bool inContainer=" ^ new_arg - ^",const char *inName=" ^ (const_char_star class_name_text )^ ")\n" ); - output_h ("\t\t\t{ return hx::Object::operator new(inSize,inContainer,inName); }\n" ); - output_h ("\t\tstatic " ^ptr_name^ " __new(" ^constructor_type_args ^");\n"); - output_h ("\t\tstatic Dynamic __CreateEmpty();\n"); - output_h ("\t\tstatic Dynamic __Create(hx::DynamicArray inArgs);\n"); - if (scriptable) then - output_h ("\t\tstatic hx::ScriptFunction __script_construct;\n"); - output_h ("\t\t//~" ^ class_name ^ "();\n\n"); - output_h ("\t\tHX_DO_RTTI_ALL;\n"); - if (has_get_member_field class_def) then - output_h ("\t\tDynamic __Field(const ::String &inString, hx::PropertyAccess inCallProp);\n"); - if (has_get_static_field class_def) then - output_h ("\t\tstatic bool __GetStatic(const ::String &inString, Dynamic &outValue, hx::PropertyAccess inCallProp);\n"); - if (has_set_member_field class_def) then - output_h ("\t\tDynamic __SetField(const ::String &inString,const Dynamic &inValue, hx::PropertyAccess inCallProp);\n"); - if (has_set_static_field class_def) then - output_h ("\t\tstatic bool __SetStatic(const ::String &inString, Dynamic &ioValue, hx::PropertyAccess inCallProp);\n"); - if (has_get_fields class_def) then - output_h ("\t\tvoid __GetFields(Array< ::String> &outFields);\n"); - - if (field_integer_dynamic) then output_h "\t\tDynamic __IField(int inFieldID);\n"; - if (field_integer_numeric) then output_h "\t\tdouble __INumField(int inFieldID);\n"; - if (implement_dynamic) then - output_h ("\t\tHX_DECLARE_IMPLEMENT_DYNAMIC;\n"); - output_h ("\t\tstatic void __register();\n"); - if (override_iteration) then begin - output_h ("\t\tvoid __Mark(HX_MARK_PARAMS);\n"); - output_h ("\t\tvoid __Visit(HX_VISIT_PARAMS);\n"); - end; - - if ( (List.length implemented) > 0 ) then begin - output_h "\t\thx::Object *__ToInterface(const hx::type_info &inType);\n"; - - List.iter (fun interface_name -> - output_h ("\t\toperator " ^ interface_name ^ "_obj *();\n") - ) implemented; - end; - - if (has_init_field class_def) then - output_h "\t\tstatic void __init__();\n\n"; - output_h ("\t\t::String __ToString() const { return " ^ (str smart_class_name) ^ "; }\n\n"); - end else if not nativeGen then begin - output_h ("\t\tHX_DO_INTERFACE_RTTI;\n"); - end; - if (has_boot_field class_def) then - output_h ("\t\tstatic void __boot();\n"); - - - (match class_def.cl_array_access with - | Some t -> output_h ("\t\ttypedef " ^ (type_string t) ^ " __array_access;\n") - | _ -> ()); - - - List.iter (gen_member_def ctx class_def true class_def.cl_interface) (List.filter should_implement_field class_def.cl_ordered_statics); - - if class_def.cl_interface then begin - let dumped = ref PMap.empty in - let rec dump_def interface = - List.iter (fun field -> try ignore (PMap.find field.cf_name !dumped) with Not_found -> - begin - dumped := PMap.add field.cf_name true !dumped; - gen_member_def ctx interface false true field - end - ) interface.cl_ordered_fields; - List.iter (fun impl -> dump_def (fst impl)) (real_interfaces interface.cl_implements); - in - (* Dump this class, not its super, but also its implements *) - dump_def class_def; - List.iter (fun impl -> dump_def (fst impl)) (real_interfaces class_def.cl_implements); - end else begin - List.iter (gen_member_def ctx class_def false false) (List.filter should_implement_field class_def.cl_ordered_fields); - end; - - - output_h ( get_class_code class_def Meta.HeaderClassCode ); - output_h "};\n\n"; - - if (class_def.cl_interface && not nativeGen) then begin - output_h ("\n\n"); - output_h ("template\n"); - output_h ("class " ^ smart_class_name ^ "_delegate_ : public " ^ class_name^"\n"); - output_h "{\n\tprotected:\n"; - output_h ("\t\tIMPL *mDelegate;\n"); - output_h "\tpublic:\n"; - output_h ("\t\t" ^ smart_class_name ^ "_delegate_(IMPL *inDelegate) : mDelegate(inDelegate) {}\n"); - output_h ("\t\thx::Object *__GetRealObject() { return mDelegate; }\n"); - output_h ("\t\tvoid __Visit(HX_VISIT_PARAMS) { HX_VISIT_OBJECT(mDelegate); }\n"); - - let dumped = ref PMap.empty in - let rec dump_delegate interface = - List.iter (fun field -> try ignore (PMap.find field.cf_name !dumped) with Not_found -> - begin - dumped := PMap.add field.cf_name true !dumped; - match follow field.cf_type, field.cf_kind with - | _, Method MethDynamic -> () - | TFun (args,return_type), Method _ -> - let remap_name = keyword_remap field.cf_name in - output_h ( " " ^ (type_string return_type) ^ " " ^ remap_name ^ "( " ); - output_h (gen_tfun_interface_arg_list args); - output_h (") { return mDelegate->" ^ remap_name^ "("); - output_h (String.concat "," (List.map (fun (name,opt,typ) -> (keyword_remap name)) args)); - output_h ");}\n"; - if reflective interface field then - output_h (" Dynamic " ^ remap_name ^ "_dyn() { return mDelegate->" ^ remap_name ^ "_dyn();}\n"); - | _ -> () - end - ) interface.cl_ordered_fields; - - match interface.cl_super with | Some super -> dump_delegate (fst super) | _ -> (); - List.iter (fun impl -> dump_delegate (fst impl)) (real_interfaces interface.cl_implements); - in - dump_delegate class_def; - List.iter (fun impl -> dump_delegate (fst impl)) (real_interfaces class_def.cl_implements); - output_h "};\n\n"; - end; - - - gen_close_namespace output_h class_path; - - end_header_file output_h def_string; - h_file#close; - let depend_referenced = find_referenced_types ctx.ctx_common (TClassDecl class_def) super_deps constructor_deps false true false in - depend_referenced;; - - -let write_resources common_ctx = - - let idx = ref 0 in - - Hashtbl.iter (fun _ data -> - let id = "__res_" ^ (string_of_int !idx) in - let resource_file = new_cpp_file common_ctx common_ctx.file (["resources"],id) in - resource_file#write "namespace hx {\n"; - resource_file#write_i ("unsigned char " ^ id ^ "[] = {\n"); - resource_file#write_i "0xff, 0xff, 0xff, 0xff,\n"; - for i = 0 to String.length data - 1 do - let code = Char.code (String.unsafe_get data i) in - resource_file#write (Printf.sprintf "%d," code); - if ( (i mod 10) = 9) then resource_file#write "\n"; - done; - resource_file#write ("0x00 };\n"); - incr idx; - resource_file#write ("}\n"); - resource_file#close; - ) common_ctx.resources; - - - let resource_file = new_cpp_file common_ctx common_ctx.file ([],"__resources__") in - resource_file#write "#include \n\n"; - resource_file#write "namespace hx { \n\n"; - - idx := 0; - Hashtbl.iter (fun _ data -> - let id = "__res_" ^ (string_of_int !idx) in - resource_file#write_i ("extern unsigned char " ^ id ^ "[];\n"); - incr idx; - ) common_ctx.resources; - - resource_file#write "}\n\n"; - - idx := 0; - resource_file#write "hx::Resource __Resources[] ="; - resource_file#begin_block; - Hashtbl.iter (fun name data -> - let id = "__res_" ^ (string_of_int !idx) in - resource_file#write_i - ("{ " ^ (str name) ^ "," ^ (string_of_int (String.length data)) ^ "," ^ - "hx::" ^ id ^ " + 4 },\n"); - incr idx; - ) common_ctx.resources; - - resource_file#write_i "{::String(null()),0,0}"; - resource_file#end_block_line; - resource_file#write ";\n\n"; - resource_file#write "namespace hx { Resource *GetResources() { return __Resources; } } \n\n"; - resource_file#close;; - - - -let write_build_data common_ctx filename classes main_deps boot_deps build_extra extern_src exe_name = - let buildfile = open_out filename in - let include_prefix = get_include_prefix common_ctx true in - let add_class_to_buildfile class_path deps = - let cpp = (join_class_path class_path "/") ^ (source_file_extension common_ctx) in - output_string buildfile ( " \n" ); - let project_deps = List.filter (fun path -> not (is_internal_class path) ) deps in - List.iter (fun path-> output_string buildfile (" file - | _ -> "include/" ^ include_prefix ^ (join_class_path path "/") ^ ".h" ) - ^ "\"/>\n") ) project_deps; - output_string buildfile ( " \n" ) - in - let add_classdef_to_buildfile (class_path, deps, _) = add_class_to_buildfile class_path deps in - - output_string buildfile "\n"; - output_string buildfile ("\n"); - output_string buildfile "\n"; - output_string buildfile "\n"; - List.iter add_classdef_to_buildfile classes; - add_class_to_buildfile ( [] , "__boot__") boot_deps; - add_class_to_buildfile ( [] , "__files__") []; - add_class_to_buildfile ( [] , "__resources__") []; - output_string buildfile "\n"; - output_string buildfile "\n"; - output_string buildfile "\n"; - add_class_to_buildfile ( [] , "__lib__") main_deps; - output_string buildfile "\n"; - output_string buildfile "\n"; - output_string buildfile "\n"; - add_class_to_buildfile ( [] , "__main__") main_deps; - output_string buildfile "\n"; - output_string buildfile "\n"; - let idx = ref 0 in - Hashtbl.iter (fun _ data -> - let id = "__res_" ^ (string_of_int !idx) in - output_string buildfile ("\n"); - incr idx; - ) common_ctx.resources; - output_string buildfile "\n"; - output_string buildfile "\n"; - List.iter (fun src -> output_string buildfile ("\n") ) extern_src; - output_string buildfile "\n"; - output_string buildfile ("\n"); - output_string buildfile "\n"; - output_string buildfile build_extra; - output_string buildfile "\n"; - close_out buildfile;; - -let write_build_options common_ctx filename defines = - let writer = cached_source_writer common_ctx filename in - PMap.iter ( fun name value -> match name with - | "true" | "sys" | "dce" | "cpp" | "debug" -> () - | _ -> writer#write (name ^ "="^(escape_command value)^ "\n" ) ) defines; - let cmd = Unix.open_process_in "haxelib path hxcpp" in - writer#write ("hxcpp=" ^ (Pervasives.input_line cmd)); - Pervasives.ignore (Unix.close_process_in cmd); - writer#close;; - -let create_member_types common_ctx = - let result = Hashtbl.create 0 in - let add_member class_name interface member = - match follow member.cf_type, member.cf_kind with - | _, Var _ when interface -> () - | _, Method MethDynamic when interface -> () - | TFun (_,ret), _ -> - (*print_endline (class_name ^ "." ^ member.cf_name ^ "=" ^ (type_string ret) );*) - Hashtbl.add result (class_name ^ "." ^ member.cf_name) (type_string ret) - | _,_ when not interface -> - Hashtbl.add result (class_name ^ "." ^ member.cf_name) (type_string member.cf_type) - | _ -> () - in - List.iter (fun object_def -> - (match object_def with - | TClassDecl class_def -> - let class_name = "::" ^ (join_class_path class_def.cl_path "::") in - let rec add_all_fields class_def = - if class_def.cl_interface then - List.iter (fun impl -> add_all_fields (fst impl) ) class_def.cl_implements; - (match class_def.cl_super with Some super -> add_all_fields (fst super) | _->();); - List.iter (add_member class_name class_def.cl_interface) class_def.cl_ordered_fields; - List.iter (add_member class_name class_def.cl_interface) class_def.cl_ordered_statics - in - add_all_fields class_def - | _ -> ( ) - ) ) common_ctx.types; - result;; - -(* Builds inheritance tree, so header files can include parents defs. *) -let create_super_dependencies common_ctx = - let result = Hashtbl.create 0 in - List.iter (fun object_def -> - (match object_def with - | TClassDecl class_def when not class_def.cl_extern -> - let deps = ref [] in - (match class_def.cl_super with Some super -> - if not (fst super).cl_extern then - deps := ((fst super).cl_path) :: !deps - | _ ->() ); - List.iter (fun imp -> if not (fst imp).cl_extern then deps := (fst imp).cl_path :: !deps) (real_interfaces class_def.cl_implements); - Hashtbl.add result class_def.cl_path !deps; - | TEnumDecl enum_def when not enum_def.e_extern -> - Hashtbl.add result enum_def.e_path []; - | _ -> () ); - ) common_ctx.types; - result;; - -let create_constructor_dependencies common_ctx = - let result = Hashtbl.create 0 in - List.iter (fun object_def -> - (match object_def with - | TClassDecl class_def when not class_def.cl_extern -> - (match class_def.cl_constructor with - | Some func_def -> Hashtbl.add result class_def.cl_path func_def - | _ -> () ) - | _ -> () ); - ) common_ctx.types; - result;; - -(* - - Exports can now be done with macros and a class list - -let rec s_type t = - let result = - match t with - | TMono r -> (match !r with | None -> "Dynamic" | Some t -> s_type t) - | TEnum (e,tl) -> Ast.s_type_path e.e_path ^ s_type_params tl - | TInst (c,tl) -> Ast.s_type_path c.cl_path ^ s_type_params tl - | TType (t,tl) -> Ast.s_type_path t.t_path ^ s_type_params tl - | TAbstract (abs,pl) when abs.a_impl <> None -> - s_type (Abstract.get_underlying_type abs pl); - | TAbstract (a,tl) -> Ast.s_type_path a.a_path ^ s_type_params tl - | TFun ([],t) -> "Void -> " ^ s_fun t false - | TFun (l,t) -> - String.concat " -> " (List.map (fun (s,b,t) -> - (if b then "?" else "") ^ (""(*if s = "" then "" else s ^ " : "*)) ^ s_fun t true - ) l) ^ " -> " ^ s_fun t false - | TAnon a -> - let fl = PMap.fold (fun f acc -> ((if Meta.has Meta.Optional f.cf_meta then " ?" else " ") ^ f.cf_name ^ " : " ^ s_type f.cf_type) :: acc) a.a_fields [] in - "{" ^ (if not (is_closed a) then "+" else "") ^ String.concat "," fl ^ " }" - | TDynamic t2 -> "Dynamic" ^ s_type_params (if t == t2 then [] else [t2]) - | TLazy f -> s_type (!f()) - in - if result="Array" then "haxe.io.BytesData" else result - -and s_fun t void = - match follow t with - | TFun _ -> "(" ^ s_type t ^ ")" - | TAbstract ({ a_path = ([],"Void") },[]) when void -> "(" ^ s_type t ^ ")" - | TMono r -> (match !r with | None -> s_type t | Some t -> s_fun t void) - | TLazy f -> s_fun (!f()) void - | _ -> (s_type t) - -and s_type_params = function - | [] -> "" - | l -> "< " ^ String.concat ", " (List.map s_type l) ^ " >" - -;; - - -let gen_extern_class common_ctx class_def file_info = - let file = new_source_file common_ctx common_ctx.file "extern" ".hx" class_def.cl_path in - let path = class_def.cl_path in - - let rec remove_all_prefix class_def field t = - let path = class_def.cl_path in - let filterPath = fst path @ [snd path] in - let rec remove_prefix t = match t with - | TInst ({cl_path=[f],suffix } as cval ,tl) when f=field -> - TInst ( { cval with cl_path = ([],suffix) }, List.map remove_prefix tl) - | TInst ({cl_path=cpath,suffix } as cval ,tl) when cpath=filterPath -> - TInst ( { cval with cl_path = ([],suffix) }, List.map remove_prefix tl) - | TInst (cval,tl) -> TInst ( cval, List.map remove_prefix tl) - (*| TInst ({cl_path=prefix} as cval ,tl) -> - TInst ( { cval with cl_path = ([],snd cval.cl_path) }, List.map (remove_prefix field) tl)*) - | t -> Type.map remove_prefix t - in - let t = remove_prefix t in - let superred = (match class_def.cl_super with - | Some (super,_) -> remove_all_prefix super field t - | _ -> t ) - in - List.fold_left ( fun t (impl,_) -> remove_all_prefix impl field t ) superred class_def.cl_implements; - (* - remove_prefix t - *) - in - - - let params = function [] -> "" | l -> "< " ^ (String.concat "," (List.map (fun (n,t) -> n) l) ^ " >") in - let output = file#write in - - let print_field stat f = - let s_type t = s_type (remove_all_prefix class_def f.cf_name t) in - let args = function TFun (args,_) -> - String.concat "," (List.map (fun (name,opt,t) -> (if opt then "?" else "") ^ name ^":"^ (s_type t)) args) | _ -> "" in - let ret = function TFun (_,ret) -> s_type ret | _ -> "Dynamic" in - let override = if (is_override class_def f.cf_name ) then "override " else "" in - - output ("\t" ^ (if stat then "static " else "") ^ (if f.cf_public then "public " else "") ); - let s_access mode op name = match mode with - | AccNormal -> "default" - | AccNo -> "null" - | AccNever -> "never" - | AccResolve -> "resolve" - | AccCall -> op ^ "_" ^ name - | AccInline -> "default" - | AccRequire (n,_) -> "require " ^ n - in - (match f.cf_kind, f.cf_name with - | Var { v_read = AccInline; v_write = AccNever },_ -> - (match f.cf_expr with Some expr -> - output ("inline var " ^ f.cf_name ^ ":" ^ (s_type f.cf_type) ^ "=" ); - let ctx = (new_extern_context common_ctx file 1 file_info) in - gen_expression ctx true expr; - | _ -> () ) - | Var { v_read = AccNormal; v_write = AccNormal },_ -> output ("var " ^ f.cf_name ^ ":" ^ (s_type f.cf_type)) - | Var v,_ -> output ("var " ^ f.cf_name ^ "(" ^ (s_access v.v_read "get" f.cf_name) ^ "," ^ (s_access v.v_write "set" f.cf_name) ^ "):" ^ (s_type f.cf_type)) - | Method _, "new" -> output ("function new(" ^ (args f.cf_type) ^ "):Void") - | Method MethDynamic, _ -> output ("dynamic function " ^ f.cf_name ^ (params f.cf_params) ^ "(" ^ (args f.cf_type) ^ "):" ^ (ret f.cf_type) ) - | Method _, _ -> output (override ^ "function " ^ f.cf_name ^ (params f.cf_params) ^ "(" ^ (args f.cf_type) ^ "):" ^ (ret f.cf_type) ) - ); - output ";\n\n"; - in - - let s_type t = s_type (remove_all_prefix class_def "*" t) in - let c = class_def in - output ( "package " ^ (String.concat "." (fst path)) ^ ";\n" ); - output ( "@:include extern " ^ (if c.cl_private then "private " else "") ^ (if c.cl_interface then "interface" else "class") - ^ " " ^ (snd path) ^ (params c.cl_params) ); - (match c.cl_super with None -> () | Some (c,pl) -> output (" extends " ^ (s_type (TInst (c,pl))))); - List.iter (fun (c,pl) -> output ( " implements " ^ (s_type (TInst (c,pl))))) (real_interfaces c.cl_implements); - (match c.cl_dynamic with None -> () | Some t -> output (" implements Dynamic< " ^ (s_type t) ^ " >")); - (match c.cl_array_access with None -> () | Some t -> output (" implements ArrayAccess< " ^ (s_type t) ^ " >")); - output "{\n"; - (match c.cl_constructor with - | None -> () - | Some f -> print_field false f); - let is_public f = f.cf_public in - List.iter (print_field false) (List.filter is_public c.cl_ordered_fields); - List.iter (print_field true) (List.filter is_public c.cl_ordered_statics); - output "}"; - output "\n"; - file#close -;; - - - - -let gen_extern_enum common_ctx enum_def file_info = - let path = enum_def.e_path in - let file = new_source_file common_ctx common_ctx.file "extern" ".hx" path in - let output = file#write in - - let params = function [] -> "" | l -> "< " ^ (String.concat "," (List.map (fun (n,t) -> n) l) ^ " >") in - output ( "package " ^ (String.concat "." (fst path)) ^ ";\n" ); - output ( "@:include extern " ^ (if enum_def.e_private then "private " else "") - ^ " enum " ^ (snd path) ^ (params enum_def.e_params) ); - output " {\n"; - let sorted_items = List.sort (fun f1 f2 -> (f1.ef_index - f2.ef_index ) ) (pmap_values enum_def.e_constrs) in - List.iter (fun constructor -> - let name = keyword_remap constructor.ef_name in - match constructor.ef_type with - | TFun (args,_) -> - output ( name ^ "(" ); - output ( String.concat "," (List.map (fun (arg,_,t) -> arg ^ ":" ^ (s_type t) ) args) ); - output ");\n\n"; - | _ -> output ( name ^ ";\n\n" ) - ) sorted_items; - - output "}\n"; - file#close -;; -*) - -let is_this expression = - match (remove_parens expression).eexpr with - | TConst TThis -> true - | _ -> false -;; - -let is_super expression = - match (remove_parens expression).eexpr with - | TConst TSuper -> true - | _ -> false -;; - - -let is_assign_op op = - match op with - | OpAssign - | OpAssignOp _ -> true - | _ -> false -;; - -let rec script_type_string haxe_type = - match haxe_type with - | TType ({ t_path = ([],"Null") },[t]) -> - (match follow t with - | TAbstract ({ a_path = [],"Int" },_) - | TAbstract ({ a_path = [],"Float" },_) - | TAbstract ({ a_path = [],"Bool" },_) - | TInst ({ cl_path = [],"Int" },_) - | TInst ({ cl_path = [],"Float" },_) - | TEnum ({ e_path = [],"Bool" },_) -> "Dynamic" - | _ -> script_type_string t) - | TInst ({cl_path=[],"Null"},[t]) -> - (match follow t with - | TAbstract ({ a_path = [],"Int" },_) - | TAbstract ({ a_path = [],"Float" },_) - | TAbstract ({ a_path = [],"Bool" },_) - | TInst ({ cl_path = [],"Int" },_) - | TInst ({ cl_path = [],"Float" },_) - | TEnum ({ e_path = [],"Bool" },_) -> "Dynamic" - | _ -> script_type_string t ) - | _ -> - match follow haxe_type with - | TType ({t_path = [],"Array"},params) -> "Array" - | TInst ({cl_path=[],"Array"},params) -> - (match params with - | [t] -> - (match type_string_suff "" t false with - | "int" -> "Array.int" - | "Float" -> "Array.Float" - | "bool" -> "Array.bool" - | "::String" -> "Array.String" - | "unsigned char" -> "Array.unsigned char" - | "Dynamic" -> "Array.Any" - | _ -> "Array.Object" - ) - | _ -> "Array.Object" - ) - | TAbstract (abs,pl) when abs.a_impl <> None -> - script_type_string (Abstract.get_underlying_type abs pl); - | _ -> - type_string_suff "" haxe_type false -;; - -type array_of = - | ArrayInterface of int - | ArrayData of string - | ArrayObject - | ArrayAny - | ArrayNone -;; - -let is_template_type t = - false -;; - -let rec is_dynamic_in_cppia ctx expr = - match expr.eexpr with - | TCast(_,None) -> true - | _ -> is_dynamic_in_cpp ctx expr -;; - -type cppia_op = - | IaFunction - | IaVar - | IaToInterface - | IaToDynArray - | IaToDataArray - | IaToInterfaceArray - | IaFun - | IaCast - | IaBlock - | IaBreak - | IaContinue - | IaIsNull - | IaNotNull - | IaSet - | IaCall - | IaCallGlobal - | IaCallStatic - | IaCallMember - | IaCallSuper - | IaCallThis - | IaCallSuperNew - | IaCreateEnum - | IaADef - | IaIf - | IaIfElse - | IaFStatic - | IaFName - | IaFThisInst - | IaFLink - | IaFThisName - | IaFEnum - | IaThrow - | IaArrayI - | IaPlusPlus - | IaPlusPlusPost - | IaMinusMinus - | IaMinusMinusPost - | IaNeg - | IaBitNot - | IaLogicNot - | IaTVars - | IaVarDecl - | IaVarDeclI - | IaNew - | IaReturn - | IaRetVal - | IaPosInfo - | IaObjDef - | IaClassOf - | IaWhile - | IaFor - | IaEnumI - | IaSwitch - | IaTry - | IaImplDynamic - | IaConstInt - | IaConstFloat - | IaConstString - | IaConstFalse - | IaConstTrue - | IaConstNull - | IaConsThis - | IaConstSuper - | IaCastInt - | IaCastBool - | IaInterface - | IaClass - | IaAccessNormal - | IaAccessNot - | IaAccessResolve - | IaAccessCall - | IaEnum - | IaInline - | IaMain - | IaNoMain - | IaResources - | IaReso - | IaNoCast - | IaAccessCallNative - - | IaBinOp of Ast.binop -;; - -let cppia_op_info = function - | IaFunction -> ("FUNCTION", 1) - | IaVar -> ("VAR", 2) - | IaToInterface -> ("TOINTERFACE", 3) - | IaToDynArray -> ("TODYNARRAY", 4) - | IaToDataArray -> ("TODATAARRAY", 5) - | IaToInterfaceArray -> ("TOINTERFACEARRAY", 6) - | IaFun -> ("FUN", 7) - | IaCast -> ("CAST", 8) - | IaBlock -> ("BLOCK", 9) - | IaBreak -> ("BREAK", 10) - | IaContinue -> ("CONTINUE", 11) - | IaIsNull -> ("ISNULL", 12) - | IaNotNull -> ("NOTNULL", 13) - | IaSet -> ("SET", 14) - | IaCall -> ("CALL", 15) - | IaCallGlobal -> ("CALLGLOBAL", 16) - | IaCallStatic -> ("CALLSTATIC", 17) - | IaCallMember -> ("CALLMEMBER", 18) - | IaCallSuper -> ("CALLSUPER", 19) - | IaCallThis -> ("CALLTHIS", 20) - | IaCallSuperNew -> ("CALLSUPERNEW", 21) - | IaCreateEnum -> ("CREATEENUM", 22) - | IaADef -> ("ADEF", 23) - | IaIf -> ("IF", 24) - | IaIfElse -> ("IFELSE", 25) - | IaFName -> ("FNAME", 27) - | IaFStatic -> ("FSTATIC", 28) - | IaFThisInst -> ("FTHISINST", 29) - | IaFLink -> ("FLINK", 30) - | IaFThisName -> ("FTHISNAME", 31) - | IaFEnum -> ("FENUM", 32) - | IaThrow -> ("THROW", 33) - | IaArrayI -> ("ARRAYI", 34) - | IaPlusPlus -> ("++", 35) - | IaPlusPlusPost -> ("+++", 36) - | IaMinusMinus -> ("--", 37) - | IaMinusMinusPost -> ("---", 38) - | IaNeg -> ("NEG", 39) - | IaBitNot -> ("~", 40) - | IaLogicNot -> ("!", 41) - | IaTVars -> ("TVARS", 42) - | IaVarDecl -> ("VARDECL", 43) - | IaVarDeclI -> ("VARDECLI", 44) - | IaNew -> ("NEW", 45) - | IaReturn -> ("RETURN", 46) - | IaRetVal -> ("RETVAL", 47) - | IaPosInfo -> ("POSINFO", 48) - | IaObjDef -> ("OBJDEF", 49) - | IaClassOf -> ("CLASSOF", 50) - | IaWhile -> ("WHILE", 51) - | IaFor -> ("FOR", 52) - | IaEnumI -> ("ENUMI", 53) - | IaSwitch -> ("SWITCH", 54) - | IaTry -> ("TRY", 55) - | IaImplDynamic -> ("IMPLDYNAMIC", 56) - | IaConstInt -> ("i", 57) - | IaConstFloat -> ("f", 58) - | IaConstString -> ("s", 59) - | IaConstFalse -> ("false", 60) - | IaConstTrue -> ("true", 61) - | IaConstNull -> ("NULL", 62) - | IaConsThis -> ("THIS", 63) - | IaConstSuper -> ("SUPER", 64) - | IaCastInt -> ("CASTINT", 65) - | IaCastBool -> ("CASTBOOL", 66) - | IaInterface -> ("INTERFACE", 67) - | IaClass -> ("CLASS", 68) - | IaAccessNormal -> ("N", 69) - | IaAccessNot -> ("n", 70) - | IaAccessResolve -> ("R", 71) - | IaAccessCall -> ("C", 72) - | IaEnum -> ("ENUM", 73) - | IaInline -> ("INLINE", 74) - | IaMain -> ("MAIN", 75) - | IaNoMain -> ("NOMAIN", 76) - | IaResources -> ("RESOURCES", 77) - | IaReso -> ("RESO", 78) - | IaNoCast -> ("NOCAST", 79) - | IaAccessCallNative -> ("V", 80) - - | IaBinOp OpAdd -> ("+", 101) - | IaBinOp OpMult -> ("*", 102) - | IaBinOp OpDiv -> ("/", 103) - | IaBinOp OpSub -> ("-", 104) - | IaBinOp OpAssign -> ("=", 105) - | IaBinOp OpEq -> ("==", 106) - | IaBinOp OpNotEq -> ("!=", 107) - | IaBinOp OpGte -> (">=", 108) - | IaBinOp OpLte -> ("<=", 109) - | IaBinOp OpGt -> (">", 110) - | IaBinOp OpLt -> ("<", 111) - | IaBinOp OpAnd -> ("&", 112) - | IaBinOp OpOr -> ("|", 113) - | IaBinOp OpXor -> ("^", 114) - | IaBinOp OpBoolAnd -> ("&&", 115) - | IaBinOp OpBoolOr -> ("||", 116) - | IaBinOp OpShr -> (">>", 117) - | IaBinOp OpUShr -> (">>>", 118) - | IaBinOp OpShl -> ("<<", 119) - | IaBinOp OpMod -> ("%", 120) - | IaBinOp OpInterval -> ("...", 121) - | IaBinOp OpArrow -> ("=>", 122) - | IaBinOp OpAssignOp OpAdd -> ("+=", 201) - | IaBinOp OpAssignOp OpMult -> ("*=", 202) - | IaBinOp OpAssignOp OpDiv -> ("/=", 203) - | IaBinOp OpAssignOp OpSub -> ("-=", 204) - - - | IaBinOp OpAssignOp OpAnd -> ("&=", 212) - | IaBinOp OpAssignOp OpOr -> ("|=", 213) - | IaBinOp OpAssignOp OpXor -> ("^=", 214) - | IaBinOp OpAssignOp OpBoolAnd -> ("&&=", 215) - | IaBinOp OpAssignOp OpBoolOr -> ("||=", 216) - | IaBinOp OpAssignOp OpShr -> (">>=", 217) - | IaBinOp OpAssignOp OpUShr -> (">>>=", 218) - | IaBinOp OpAssignOp OpShl -> ("<<=", 219) - | IaBinOp OpAssignOp OpMod -> ("%=", 220) - - | IaBinOp OpAssignOp OpInterval - | IaBinOp OpAssignOp OpAssign - | IaBinOp OpAssignOp OpEq - | IaBinOp OpAssignOp OpNotEq - | IaBinOp OpAssignOp OpGte - | IaBinOp OpAssignOp OpLte - | IaBinOp OpAssignOp OpGt - | IaBinOp OpAssignOp OpLt - | IaBinOp OpAssignOp OpAssignOp _ - | IaBinOp OpAssignOp OpArrow -> assert false -;; - -class script_writer common_ctx ctx filename asciiOut = - object(this) - val debug = asciiOut - val indent_str = if asciiOut then "\t" else "" - val mutable indent = "" - val mutable indents = [] - val mutable just_finished_block = false - val mutable classCount = 0 - val mutable return_type = TMono(ref None) - val buffer = Buffer.create 0 - val identTable = Hashtbl.create 0 - val fileTable = Hashtbl.create 0 - val identBuffer = Buffer.create 0 - - method stringId name = - try ( Hashtbl.find identTable name ) - with Not_found -> begin - let size = Hashtbl.length identTable in - Hashtbl.add identTable name size; - Buffer.add_string identBuffer ((string_of_int (String.length name)) ^ " " ^ name ^ "\n"); - size; - end - method incClasses = classCount <- classCount +1 - - method stringText name = (string_of_int (this#stringId name)) ^ " " - val typeTable = Hashtbl.create 0 - val typeBuffer = Buffer.create 0 - method typeId name = - let name = if name="::hx::Class" then "::Class" else name in - try ( Hashtbl.find typeTable name ) - with Not_found -> begin - let size = Hashtbl.length typeTable in - Hashtbl.add typeTable name size; - Buffer.add_string typeBuffer ((string_of_int (String.length name)) ^ " " ^ name ^ "\n"); - size; - end - method write str = if asciiOut then - Buffer.add_string buffer str - else begin - let push i = Buffer.add_char buffer (Char.chr i) in - let pushI32 i = push (Int32.to_int (Int32.logand i (Int32.of_int 255))) in - List.iter (fun i -> - if ((Int32.compare i Int32.zero) >= 0) && ((Int32.compare i (Int32.of_int 254)) < 0) then - pushI32 i - else if ((Int32.compare i Int32.zero) >= 0) && ((Int32.compare i (Int32.of_int 65536)) < 0) then begin - push 254; - pushI32 i; - pushI32 (Int32.shift_right i 8); - end else begin - push 255; - pushI32 i; - pushI32 (Int32.shift_right i 8); - pushI32 (Int32.shift_right i 16); - pushI32 (Int32.shift_right i 24); - end - ) (List.map Int32.of_string (Str.split (Str.regexp "[\n\t ]+") str) ); - end; - just_finished_block <- false - method typeTextString typeName = (string_of_int (this#typeId typeName)) ^ " " - method typeText typeT = (string_of_int (this#typeId (script_type_string typeT))) ^ " " - method writeType typeT = this#write (this#typeText typeT) - method boolText value = if value then "1" else "0" - method writeBool value = this#write (if value then "1 " else "0 ") - method staticText value = if value then "1" else "0" - method writeData str = Buffer.add_string buffer str; - method wint ival = this#write ((string_of_int ival)^" ") - method ident name = this#wint (this#stringId name) - method instText clazz = match clazz.cl_path with - | ([],"Array") -> string_of_int (this#typeId "Array< ::Dynamic >") ^ " " - | _ -> this#typeText (TInst(clazz,[])) - method instName clazz = this#write (this#instText clazz) - method enumText e = this#typeText (TEnum(e,[])) - method enumName e = this#write (this#enumText e) - method close = - let out_file = open_out_bin filename in - output_string out_file (if asciiOut then "CPPIA\n" else "CPPIB\n"); - let idents = Buffer.contents identBuffer in - output_string out_file ((string_of_int (Hashtbl.length identTable)) ^ "\n"); - output_string out_file idents; - let types = Buffer.contents typeBuffer in - output_string out_file ((string_of_int (Hashtbl.length typeTable)) ^ "\n"); - output_string out_file types; - output_string out_file ( (string_of_int classCount) ^ "\n" ); - let contents = Buffer.contents buffer in - output_string out_file contents; - close_out out_file - method fileId file = - try ( Hashtbl.find fileTable file ) - with Not_found -> begin - let stripped_file = strip_file common_ctx file in - let result = this#stringId stripped_file in - Hashtbl.add fileTable file result; - result; - end - method constText c = match c with - | TInt i -> (this#op IaConstInt) ^ (Printf.sprintf "%ld " i) - | TFloat f -> (this#op IaConstFloat) ^ (this#stringText f) - | TString s -> (this#op IaConstString) ^ (this#stringText s) - | TBool true -> (this#op IaConstTrue) - | TBool false -> (this#op IaConstFalse) - | TNull -> (this#op IaConstNull) - | TThis -> (this#op IaConsThis) - | TSuper -> (this#op IaConstSuper) - - method get_array_type t = - match follow t with - | TInst ({cl_path=[],"Array"},[param]) -> - let typeName = type_string_suff "" param false in - (match typeName with - | "::String" -> ArrayData "String" - | "int" | "Float" | "bool" | "String" | "unsigned char" -> - ArrayData typeName - | "cpp::ArrayBase" | "Dynamic" -> ArrayAny - | _ when is_interface_type param -> ArrayInterface (this#typeId (script_type_string param)) - | _ -> ArrayObject - ) - | TAbstract (abs,pl) when abs.a_impl <> None -> - this#get_array_type (Abstract.get_underlying_type abs pl); - | _ -> ArrayNone; - - method pushReturn inType = - let oldReturnType = return_type in - return_type <- inType; - fun () -> return_type <- oldReturnType; - method fileText file = string_of_int (this#fileId file) - method indent_one = this#write indent_str - method push_indent = indents <- indent_str::indents; indent <- String.concat "" indents - method pop_indent = match indents with - | h::tail -> indents <- tail; indent <- String.concat "" indents - | [] -> indent <- "/*?*/"; - method write_i x = this#write (indent ^ x) - method get_indent = indent - method begin_expr = this#push_indent - method end_expr = if not just_finished_block then this#write "\n"; this#pop_indent; just_finished_block <- true - method op x = match cppia_op_info x with - | (name,index) -> (if debug then name else string_of_int index) ^ " " - method writeOp o = this#write (this#op o) - method writeOpLine o = this#write ((this#op o) ^ "\n") - method voidFunc isStatic isDynamic funcName fieldExpression = - this#write ( (this#op IaFunction) ^ (this#staticText isStatic) ^ " " ^(this#boolText isDynamic) ^ " " ^(this#stringText funcName) ^ " "); - this#write ((this#typeTextString "Void") ^ "0\n"); - this#gen_expression fieldExpression - method func isStatic isDynamic funcName ret args isInterface fieldExpression = - this#write ( (this#op IaFunction) ^ (this#staticText isStatic) ^ " " ^(this#boolText isDynamic) ^ " " ^(this#stringText funcName) ^ " "); - this#write ((this#typeText ret) ^ (string_of_int (List.length args)) ^ " "); - List.iter (fun (name,opt,typ) -> this#write ( (this#stringText name) ^ (this#boolText opt) ^ " " ^ (this#typeText typ) ^ " " )) args; - this#write "\n"; - if (not isInterface) then begin - match fieldExpression with - | Some ({ eexpr = TFunction function_def } as e) -> this#gen_expression e - | _ -> print_endline ("Missing function body for " ^ funcName ); - end - method var readAcc writeAcc isExtern isStatic name varType varExpr = - this#write ( (this#op IaVar) ^ (this#staticText isStatic) ^ " " ^ (this#op readAcc) ^ (this#op writeAcc) ^ - (this#boolText isExtern) ^ " " ^ (this#stringText name)^ (this#typeText varType) ^ - (match varExpr with Some _ -> "1\n" | _ -> "0\n" ) ); - match varExpr with - | Some expression -> this#gen_expression expression - | _ -> () - method implDynamic = this#writeOpLine IaImplDynamic; - method writeVar v = - this#ident v.v_name; - this#wint v.v_id; - this#writeBool v.v_capture; - this#writeType v.v_type; - method writeList prefix len = this#write (prefix ^" " ^ (string_of_int (len)) ^ "\n"); - method writePos expr = if debug then - this#write ( (this#fileText expr.epos.pfile) ^ "\t" ^ (string_of_int (Lexer.get_error_line expr.epos) ) ^ indent); - method checkCast toType expr forceCast fromGenExpression= - let write_cast text = - if (not fromGenExpression) then - this#writePos expr; - this#write (text ^"\n" ); - this#begin_expr; - this#gen_expression expr; - this#end_expr; - true; - in - let was_cast = - if (is_interface_type toType) then begin - if (is_dynamic_in_cppia ctx expr) then begin - write_cast ( (this#op IaToInterface) ^ (this#typeText toType) ^ " " ^ (this#typeTextString "Dynamic") ) - end else if (not (is_matching_interface_type toType expr.etype)) then begin - write_cast ( (this#op IaToInterface) ^ (this#typeText toType) ^ " " ^ (this#typeText expr.etype) ) - end else - false - end else begin - let get_array_expr_type expr = - if is_dynamic_in_cppia ctx expr then - ArrayNone - else - this#get_array_type expr.etype - in - match (this#get_array_type toType), (get_array_expr_type expr) with - | ArrayAny, _ -> false - | ArrayObject, ArrayData _ -> write_cast (this#op IaToDynArray) - | ArrayData t, ArrayNone - | ArrayData t, ArrayObject - | ArrayData t, ArrayAny -> write_cast ((this#op IaToDataArray) ^ (this#typeTextString ("Array." ^ t))) - | ArrayInterface t, ArrayNone - | ArrayInterface t, ArrayAny -> write_cast ((this#op IaToInterfaceArray) ^ (string_of_int t)) - | _,_ -> (* a0,a1 -> - let arrayString a = - match a with - | ArrayNone -> "ArrayNone" - | ArrayAny -> "ArrayAny" - | ArrayObject -> "ArrayObject" - | ArrayData _ -> "ArrayData" - | ArrayInterface _ -> "ArrayInterface" - in - this#write ("NOCAST " ^ (arrayString a0) ^ "=" ^ (arrayString a1)); *) - false - end - in - - if (not was_cast) then begin - if (forceCast) then begin - let op =match (type_string expr.etype) with - | "int" -> IaCastInt - | "bool" -> IaCastBool - | _ when is_interface_type toType -> IaNoCast - | _ -> IaCast - in - this#writeOpLine op; - end; - this#gen_expression expr; - end - method gen_expression expr = - let expression = remove_parens expr in - this#begin_expr; - (*this#write ( (this#fileText expression.epos.pfile) ^ "\t" ^ (string_of_int (Lexer.get_error_line expression.epos) ) ^ indent);*) - this#writePos expression; - (match expression.eexpr with - | TFunction function_def -> this#write ( (this#op IaFun) ^ (this#typeText function_def.tf_type) ^ (string_of_int (List.length function_def.tf_args)) ^ "\n" ); - List.iter (fun(arg,init) -> - this#write (indent ^ indent_str ); - this#writeVar arg; - match init with - | Some const -> this#write ("1 " ^ (this#constText const) ^ "\n") - | _ -> this#write "0\n"; - ) function_def.tf_args; - let pop = this#pushReturn function_def.tf_type in - this#gen_expression function_def.tf_expr; - pop (); - | TBlock expr_list -> this#writeList (this#op IaBlock) (List.length expr_list); - List.iter this#gen_expression expr_list; - | TConst const -> this#write (this#constText const) - | TBreak -> this#writeOp IaBreak - | TContinue -> this#writeOp IaContinue - - | TBinop (op,e1,e2) when op=OpAssign -> - this#writeOpLine IaSet; - this#gen_expression e1; - this#checkCast e1.etype e2 false false; - | TBinop (OpEq ,e1, { eexpr = TConst TNull } ) -> this#writeOpLine IaIsNull; - this#gen_expression e1; - | TBinop (OpNotEq ,e1, { eexpr = TConst TNull }) -> this#writeOpLine IaNotNull; - this#gen_expression e1; - | TBinop (OpEq , { eexpr = TConst TNull }, e1) -> this#writeOpLine IaIsNull; - this#gen_expression e1; - | TBinop (OpNotEq, { eexpr = TConst TNull }, e1) -> this#writeOpLine IaNotNull; - this#gen_expression e1; - | TBinop (op,e1,e2) -> this#writeOpLine (IaBinOp op); - this#gen_expression e1; - this#gen_expression e2; - | TThrow e -> this#writeOpLine IaThrow; - this#gen_expression e; - | TArrayDecl expr_list -> - this#write ( (this#op IaADef) ^ (this#typeText expression.etype) ^ " " ^(string_of_int (List.length expr_list))^"\n"); - List.iter this#gen_expression expr_list; - | TIf (e,e1,e2) -> - (match e2 with - | None -> - this#writeOpLine IaIf; - this#gen_expression e; - this#gen_expression e1; - | Some elze -> - this#writeOpLine IaIfElse; - this#gen_expression e; - this#gen_expression e1; - this#gen_expression elze; ) - | TCall (func, arg_list) -> - let argN = (string_of_int (List.length arg_list)) ^ " " in - let is_real_function field = - match field.cf_kind with - | Method MethNormal | Method MethInline-> true - | _ -> false; - in - let gen_call () = - (match (remove_parens func).eexpr with - | TField ( { eexpr = TLocal { v_name = "__global__" }}, field ) -> - this#write ( (this#op IaCallGlobal) ^ (this#stringText (field_name field)) ^ argN ^ "\n"); - | TField (obj,FStatic (class_def,field) ) when is_real_function field -> - this#write ( (this#op IaCallStatic) ^ (this#instText class_def) ^ " " ^ (this#stringText field.cf_name) ^ - argN ^ "\n"); - | TField (obj,FInstance (_,_,field) ) when (is_this obj) && (is_real_function field) -> - this#write ( (this#op IaCallThis) ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^ - argN ^ "\n"); - | TField (obj,FInstance (_,_,field) ) when is_super obj -> - this#write ( (this#op IaCallSuper) ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^ - argN ^ "\n"); - | TField (obj,FInstance (_,_,field) ) when is_real_function field -> - this#write ( (this#op IaCallMember) ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^ - argN ^ "\n"); - this#gen_expression obj; - | TField (obj,FDynamic (name) ) when (is_internal_member name || (type_string obj.etype = "::String" && name="cca") ) -> - this#write ( (this#op IaCallMember) ^ (this#typeText obj.etype) ^ " " ^ (this#stringText name) ^ - argN ^ "\n"); - this#gen_expression obj; - | TConst TSuper -> this#write ((this#op IaCallSuperNew) ^ (this#typeText func.etype) ^ " " ^ argN ^ "\n"); - | TField (_,FEnum (enum,field)) -> this#write ((this#op IaCreateEnum) ^ (this#enumText enum) ^ " " ^ (this#stringText field.ef_name) ^ argN ^ "\n"); - | _ -> this#write ( (this#op IaCall) ^ argN ^ "\n"); - this#gen_expression func; - ); - let matched_args = match func.etype with - | TFun (args,_) -> - ( try ( - List.iter2 (fun (_,_,protoT) arg -> this#checkCast protoT arg false false) args arg_list; - true; ) - with Invalid_argument _ -> (*print_endline "Bad count?";*) false ) - | _ -> false - in - if not matched_args then - List.iter this#gen_expression arg_list; - in - (match (remove_parens func).eexpr with - | TField(obj,field) when is_array_or_dyn_array obj.etype && (field_name field)="map" -> - (match this#get_array_type expression.etype with - | ArrayData t -> - this#write ( (this#op IaToDataArray) ^ (this#typeTextString ("Array." ^ t)) ^ "\n"); - this#begin_expr; - this#writePos func; - gen_call(); - this#end_expr; - | ArrayInterface t -> - this#write ( (this#op IaToInterfaceArray) ^ (string_of_int t) ^ "\n"); - this#begin_expr; - this#writePos func; - gen_call(); - this#end_expr; - | _ -> gen_call(); - ) - | _ -> gen_call(); - ); - | TField (obj, acc) -> - let typeText = this#typeText obj.etype in - (match acc with - | FDynamic name -> this#write ( (this#op IaFName) ^ typeText ^ " " ^ (this#stringText name) ^ "\n"); - this#gen_expression obj; - | FStatic (class_def,field) -> this#write ( (this#op IaFStatic) ^ (this#instText class_def) ^ " " ^ (this#stringText field.cf_name) ); - | FInstance (_,_,field) when is_this obj -> this#write ( (this#op IaFThisInst) ^ typeText ^ " " ^ (this#stringText field.cf_name) ); - | FInstance (_,_,field) -> this#write ( (this#op IaFLink) ^ typeText ^ " " ^ (this#stringText field.cf_name) ^ "\n"); - this#gen_expression obj; - - | FClosure (_,field) when is_this obj -> this#write ( (this#op IaFThisName) ^typeText ^ " " ^ (this#stringText field.cf_name) ^ "\n") - | FAnon (field) when is_this obj -> this#write ( (this#op IaFThisName) ^typeText ^ " " ^ (this#stringText field.cf_name) ^ "\n") - - | FClosure (_,field) - | FAnon (field) -> this#write ( (this#op IaFName) ^typeText ^ " " ^ (this#stringText field.cf_name) ^ "\n"); - this#gen_expression obj; - - | FEnum (enum,field) -> this#write ( (this#op IaFEnum) ^ (this#enumText enum) ^ " " ^ (this#stringText field.ef_name) ); - ) - | TArray (e1, e2) -> this#write ((this#op IaArrayI) ^ (this#typeText e1.etype) ^ "\n"); - this#gen_expression e1; - this#gen_expression e2; - | TUnop (op, flag, e) -> - this#writeOpLine (match op,flag with - | Increment, Prefix -> IaPlusPlus - | Increment, _ -> IaPlusPlusPost - | Decrement, Prefix -> IaMinusMinus - | Decrement, _ -> IaMinusMinusPost - | Not, _ -> IaLogicNot - | Neg, _ -> IaNeg - | NegBits, _ -> IaBitNot ); - this#gen_expression e; - (* TODO - lval op-assign local/member/array *) - | TLocal var -> this#write ((this#op IaVar) ^ (string_of_int var.v_id) ); - - | TVar (tvar,optional_init) -> - this#write ( (this#op IaTVars) ^ (string_of_int (1)) ^ "\n"); - this#write ("\t\t" ^ indent); - (match optional_init with - | None -> this#writeOp IaVarDecl; - this#writeVar tvar; - | Some init ->this#writeOp IaVarDeclI; - let init = remove_parens init in - this#writeVar tvar; - this#write (" " ^ (this#typeText init.etype)); - this#write "\n"; - this#checkCast tvar.v_type init false false); - | TNew (clazz,params,arg_list) -> - this#write ((this#op IaNew) ^ (this#typeText (TInst(clazz,params))) ^ (string_of_int (List.length arg_list)) ^ "\n"); - let rec matched_args clazz = match clazz.cl_constructor, clazz.cl_super with - | None, Some super -> matched_args (fst super) - | None, _ -> false - | Some ctr, _ -> - (match ctr.cf_type with - | TFun(args,_) -> - ( try ( - List.iter2 (fun (_,_,protoT) arg -> this#checkCast protoT arg false false) args arg_list; - true; ) - with Invalid_argument _ -> (*print_endline "Bad count?";*) false ) - | _ -> false - ) - in - if not (matched_args clazz) then - List.iter this#gen_expression arg_list; - - | TReturn optval -> (match optval with - | None -> this#writeOpLine IaReturn; - | Some value -> this#write ( (this#op IaRetVal) ^ (this#typeText value.etype) ^ "\n"); - this#checkCast return_type value false false; - ) - | TObjectDecl ( - ("fileName" , { eexpr = (TConst (TString file)) }) :: - ("lineNumber" , { eexpr = (TConst (TInt line)) }) :: - ("className" , { eexpr = (TConst (TString class_name)) }) :: - ("methodName", { eexpr = (TConst (TString meth)) }) :: [] ) -> - this#write ( (this#op IaPosInfo) ^ (this#stringText file) ^ (Printf.sprintf "%ld" line) ^ " " ^ - (this#stringText class_name) ^ " " ^ (this#stringText meth)) - - | TObjectDecl values ->this#write ( (this#op IaObjDef) ^ (string_of_int (List.length values))); - this#write " "; - List.iter (fun (name,_) -> this#write (this#stringText name) ) values; - this#write "\n"; - List.iter (fun (_,e) -> this#gen_expression e ) values; - | TTypeExpr type_expr -> - let klass = "::" ^ (join_class_path (t_path type_expr) "::" ) in - this#write ((this#op IaClassOf) ^ (string_of_int (this#typeId klass))) - | TWhile (e1,e2,flag) -> this#write ( (this#op IaWhile) ^ (if flag=NormalWhile then "1" else "0" ) ^ "\n"); - this#gen_expression e1; - this#gen_expression e2; - | TFor (tvar,init,loop) -> this#writeOp IaFor; - this#writeVar tvar; - this#write "\n"; - this#gen_expression init; - this#gen_expression loop; - | TEnumParameter (expr,ef,i) -> - let enum = match follow ef.ef_type with - | TEnum(en,_) | TFun(_,TEnum(en,_)) -> en - | _ -> assert false - in - this#write ( (this#op IaEnumI) ^ (this#typeText (TEnum(enum,[])) ) ^ (string_of_int i) ^ "\n"); - this#gen_expression expr; - | TSwitch (condition,cases,optional_default) -> - this#write ( (this#op IaSwitch) ^ (string_of_int (List.length cases)) ^ " " ^ - (match optional_default with None -> "0" | Some _ -> "1") ^ "\n"); - this#gen_expression condition; - List.iter (fun (cases_list,expression) -> - this#writeList ("\t\t\t"^indent) (List.length cases_list); - List.iter (fun value -> this#gen_expression value ) cases_list; - this#gen_expression expression; - ) cases; - (match optional_default with None -> () | Some expr -> this#gen_expression expr); - | TTry (e,catches) -> - this#writeList (this#op IaTry) (List.length catches); - this#gen_expression e; - List.iter ( fun (tvar,catch_expr) -> - this#write ("\t\t\t"^indent); - this#writeVar tvar; - this#write "\n"; - this#gen_expression catch_expr; - ) catches; - | TCast (cast,None) -> this#checkCast expression.etype cast true true; - | TCast (cast,Some _) -> this#checkCast expression.etype cast true true; - | TParenthesis _ -> error "Unexpected parens" expression.epos - | TMeta(_,_) -> error "Unexpected meta" expression.epos - ); - this#end_expr; -end;; - -let generate_script_class common_ctx script class_def = - script#incClasses; - script#writeOp (if class_def.cl_interface then IaInterface else IaClass ); - script#instName class_def; - (match class_def.cl_super with - | None -> script#ident "" - | Some (c,_) -> script#instName c); - script#wint (List.length class_def.cl_implements); - List.iter (fun(c,_) -> script#instName c) class_def.cl_implements; - script#write "\n"; - (* Looks like some map impl classes have their bodies discarded - not sure best way to filter *) - let non_dodgy_function field = - class_def.cl_interface || - match field.cf_kind, field.cf_expr with - | Var _, _ -> true - | Method MethDynamic, _ -> true - | Method _, Some _ -> true - | _ -> false - in - let ordered_statics = List.filter non_dodgy_function class_def.cl_ordered_statics in - let ordered_fields = List.filter non_dodgy_function class_def.cl_ordered_fields in - script#write ((string_of_int ( (List.length ordered_fields) + - (List.length ordered_statics) + - (match class_def.cl_constructor with Some _ -> 1 | _ -> 0 ) + - (if (implement_dynamic_here class_def) then 1 else 0) + - (match class_def.cl_init with Some _ -> 1 | _ -> 0 ) ) ) - ^ "\n"); - - let generate_field isStatic field = - match field.cf_kind, follow field.cf_type with - | Var { v_read = AccInline; v_write = AccNever },_ -> - script#writeOpLine IaInline; - | Var v,_ -> - let mode_code mode = match mode with - | AccNormal -> IaAccessNormal - | AccNo -> IaAccessNot - | AccNever -> IaAccessNot - | AccResolve -> IaAccessResolve - | AccCall -> if ( (has_meta_key class_def.cl_meta Meta.NativeProperty) || - (has_meta_key field.cf_meta Meta.NativeProperty) || - (Common.defined common_ctx Define.ForceNativeProperty) ) - then IaAccessCallNative else IaAccessCall; - | AccInline -> IaAccessNormal - | AccRequire (_,_) -> IaAccessNormal - in - let isExtern = is_extern_field field in - script#var (mode_code v.v_read) (mode_code v.v_write) isExtern isStatic field.cf_name field.cf_type field.cf_expr - | Method MethDynamic, TFun(args,ret) -> - script#func isStatic true field.cf_name ret args class_def.cl_interface field.cf_expr - | Method _, TFun(args,ret) when field.cf_name="new" -> - script#func true false "new" (TInst(class_def,[])) args false field.cf_expr - | Method _, TFun (args,ret) -> - script#func isStatic false field.cf_name ret args class_def.cl_interface field.cf_expr - | Method _, _ -> print_endline ("Unknown method type " ^ (join_class_path class_def.cl_path "." ) - ^ "." ^field.cf_name ) - in - (match class_def.cl_constructor with - | Some field -> generate_field true field - | _ -> () ); - (match class_def.cl_init with - | Some expression -> script#voidFunc true false "__init__" expression - | _ -> () ); - - List.iter (generate_field false) ordered_fields; - List.iter (generate_field true) ordered_statics; - if (implement_dynamic_here class_def) then - script#implDynamic; - script#write "\n"; -;; - -let generate_script_enum common_ctx script enum_def meta = - script#incClasses; - let sorted_items = List.sort (fun f1 f2 -> (f1.ef_index - f2.ef_index ) ) (pmap_values enum_def.e_constrs) in - script#writeList ((script#op IaEnum) ^ (script#enumText enum_def)) (List.length sorted_items); - - List.iter (fun constructor -> - let name = script#stringText constructor.ef_name in - match constructor.ef_type with - | TFun (args,_) -> - script#write ( name ^ " " ^ (string_of_int (List.length args)) ); - List.iter (fun (arg,_,t) -> script#write ( " " ^ (script#stringText arg) ^ " " ^ (script#typeText t) ) ) args; - script#write "\n"; - | _ -> script#write ( name ^ " 0\n" ) - ) sorted_items; - - match meta with - | Some expr -> script#write "1\n"; - script#gen_expression expr - | _ -> script#write "0\n"; - script#write "\n" -;; - - -let generate_cppia common_ctx = - let debug = 1 in - let null_file = new source_writer common_ctx ignore (fun () -> () ) in - let ctx = new_context common_ctx null_file debug (ref PMap.empty) in - ctx.ctx_class_member_types <- create_member_types common_ctx; - let script = new script_writer common_ctx ctx common_ctx.file common_ctx.debug in - ignore (script#stringId ""); - ignore (script#typeId ""); - - List.iter (fun object_def -> - (match object_def with - | TClassDecl class_def when class_def.cl_extern -> - () (*if (gen_externs) then gen_extern_class common_ctx class_def;*) - | TClassDecl class_def -> - let is_internal = is_internal_class class_def.cl_path in - if (is_internal || (is_macro class_def.cl_meta)) then - ( if (debug>1) then print_endline (" internal class " ^ (join_class_path class_def.cl_path ".") )) - else begin - ctx.ctx_class_name <- "::" ^ (join_class_path class_def.cl_path "::"); - generate_script_class common_ctx script class_def - end - | TEnumDecl enum_def when enum_def.e_extern -> () - | TEnumDecl enum_def -> - let is_internal = is_internal_class enum_def.e_path in - if (is_internal) then - (if (debug>1) then print_endline (" internal enum " ^ (join_class_path enum_def.e_path ".") )) - else begin - let meta = Codegen.build_metadata common_ctx object_def in - if (enum_def.e_extern) then - (if (debug>1) then print_endline ("external enum " ^ (join_class_path enum_def.e_path ".") )); - ctx.ctx_class_name <- "*"; - generate_script_enum common_ctx script enum_def meta - end - | TTypeDecl _ | TAbstractDecl _ -> (* already done *) () - ); - ) common_ctx.types; - - (match common_ctx.main with - | None -> script#writeOpLine IaNoMain; - | Some e -> script#writeOpLine IaMain; - script#gen_expression e - ); - - script#write ( (script#op IaResources) ^ (string_of_int (Hashtbl.length common_ctx.resources)) ^ "\n"); - Hashtbl.iter (fun name data -> - script#write ((script#op IaReso) ^ (script#stringText name) ^ (string_of_int (String.length data)) ^ "\n"); - ) common_ctx.resources; - Hashtbl.iter (fun _ data -> script#writeData data) common_ctx.resources; - - script#close -;; - - -(* - The common_ctx contains the haxe AST in the "types" field and the resources -*) -let generate_source common_ctx = - make_base_directory common_ctx.file; - - let debug = 1 in - let exe_classes = ref [] in - let boot_classes = ref [] in - let boot_enums = ref [] in - let nonboot_classes = ref [] in - let init_classes = ref [] in - let file_info = ref PMap.empty in - let class_text path = join_class_path path "::" in - let member_types = create_member_types common_ctx in - let super_deps = create_super_dependencies common_ctx in - let constructor_deps = create_constructor_dependencies common_ctx in - let main_deps = ref [] in - let extern_src = ref [] in - let build_xml = ref "" in - let scriptable = (Common.defined common_ctx Define.Scriptable) in - - List.iter (fun object_def -> - (match object_def with - | TClassDecl class_def when is_extern_class class_def -> - build_xml := !build_xml ^ (get_class_code class_def Meta.BuildXml); - let source = get_meta_string_path class_def.cl_meta Meta.SourceFile in - if (source<>"") then - extern_src := source :: !extern_src; - | TClassDecl class_def -> - let name = class_text class_def.cl_path in - let is_internal = is_internal_class class_def.cl_path in - if (is_internal || (is_macro class_def.cl_meta)) then - ( if (debug>1) then print_endline (" internal class " ^ name )) - else begin - build_xml := !build_xml ^ (get_class_code class_def Meta.BuildXml); - if (has_init_field class_def) then - init_classes := class_def.cl_path :: !init_classes; - if (has_boot_field class_def) then - boot_classes := class_def.cl_path :: !boot_classes - else if not (has_meta_key class_def.cl_meta Meta.NativeGen) then - nonboot_classes := class_def.cl_path :: !nonboot_classes; - let deps = generate_class_files common_ctx - member_types super_deps constructor_deps class_def file_info scriptable in - exe_classes := (class_def.cl_path, deps, object_def) :: !exe_classes; - end - | TEnumDecl enum_def when enum_def.e_extern -> () - | TEnumDecl enum_def -> - let name = class_text enum_def.e_path in - let is_internal = is_internal_class enum_def.e_path in - if (is_internal) then - (if (debug>1) then print_endline (" internal enum " ^ name )) - else begin - let meta = Codegen.build_metadata common_ctx object_def in - if (enum_def.e_extern) then - (if (debug>1) then print_endline ("external enum " ^ name )); - boot_enums := enum_def.e_path :: !boot_enums; - let deps = generate_enum_files common_ctx enum_def super_deps meta file_info in - exe_classes := (enum_def.e_path, deps, object_def) :: !exe_classes; - end - | TTypeDecl _ | TAbstractDecl _ -> (* already done *) () - ); - ) common_ctx.types; - - - (match common_ctx.main with - | None -> generate_dummy_main common_ctx - | Some e -> - let main_field = { cf_name = "__main__"; cf_type = t_dynamic; cf_expr = Some e; cf_pos = e.epos; cf_public = true; cf_meta = []; cf_overloads = []; cf_doc = None; cf_kind = Var { v_read = AccNormal; v_write = AccNormal; }; cf_params = [] } in - let class_def = { null_class with cl_path = ([],"@Main"); cl_ordered_statics = [main_field] } in - main_deps := find_referenced_types common_ctx (TClassDecl class_def) super_deps constructor_deps false true false; - generate_main common_ctx member_types super_deps class_def file_info - ); - - generate_boot common_ctx !boot_enums !boot_classes !nonboot_classes !init_classes; - - generate_files common_ctx file_info; - - write_resources common_ctx; - - (* Output class info if requested *) - if (scriptable || (Common.defined common_ctx Define.DllExport) ) then begin - let filename = - try - let value = Common.defined_value common_ctx Define.DllExport in - if value="1" then raise Not_found; - value - with Not_found -> "export_classes.info" - in - if (filename <> "") then begin - let escape s = - let b = Buffer.create 0 in - for i = 0 to String.length s - 1 do - let c = String.unsafe_get s i in - match c with - | '\\' -> Buffer.add_char b c; Buffer.add_char b c; - | ' ' -> Buffer.add_char b '\\'; Buffer.add_char b 's'; - | '\n' -> Buffer.add_char b '\\'; Buffer.add_char b 'n'; - | _ -> Buffer.add_char b c; - done; - Buffer.contents b; - in - - let exeClasses = open_out filename in - let out = output_string exeClasses in - let outline str = output_string exeClasses (str ^ "\n") in - let spath path = (join_class_path path ".") in - let rec stype = function - | TMono r -> (match !r with None -> "Dynamic" | Some t -> stype t) - | TAbstract ({ a_path = ([],"Void") },[]) -> "void" - | TAbstract ({ a_path = ([],"Bool") },[]) -> "bool" - | TAbstract ({ a_path = ([],"Float") },[]) -> "float" - | TAbstract ({ a_path = ([],"Int") },[]) -> "int" - | TAbstract( { a_path = ([], "EnumValue") }, _ ) -> "Dynamic" - | TEnum (enum,params) -> spath enum.e_path - | TInst (klass,params) -> - (match klass.cl_path, params with - (* Array class *) - (*| ([],"Array") when is_dynamic_array_param (List.hd params) -> "Dynamic" *) - | _,_ when is_dynamic_type_param klass.cl_kind -> "Dynamic" - | ([],"Array"), [t] -> "Array<" ^ (stype t) ^ ">" - | (["haxe";"io"],"Unsigned_char__"),_ -> "uint8" - | ([],"EnumValue"),_ -> "Dynamic" - | ([],"Null"),[t] when cant_be_null t -> "Null<" ^ (stype t) ^ ">" - | ([],"Null"),[t] -> (stype t) - | _ -> spath klass.cl_path - ) - | TType (type_def,params) -> - (match type_def.t_path, params with - | ([],"Null"),[t] when cant_be_null t -> "Null<" ^ (stype t) ^ ">" - | ([],"Array"), [t] -> "Array< " ^ (stype (follow t) ) ^ " >" - | _,_ -> stype (apply_params type_def.t_params params type_def.t_type) - ) - | TLazy func -> stype ((!func)()) - | TAbstract (abs,pl) when abs.a_impl <> None -> - stype (Abstract.get_underlying_type abs pl) - | TAbstract (abs,_) -> spath abs.a_path - | TFun (args,ret) -> "fun<" ^ (List.fold_left (fun s (_,opt,t) -> s ^ (if opt then "?" else "") ^ (stype t) ^ ",") "" args) ^ (stype ret) ^ ">" - | _ -> "Dynamic" - in - List.iter (fun (name,_,def) -> - match def with - | TClassDecl class_def -> - outline ((if class_def.cl_interface then "interface " else "class ") ^ (spath name) ); - (match class_def.cl_super with - | Some (super,_) -> outline ("super " ^ (spath super.cl_path) ) - | _ -> () ); - List.iter ( fun(c,_) -> out ("implements " ^ (spath c.cl_path) ^ "\n") ) class_def.cl_implements; - (match class_def.cl_dynamic with None -> () | Some t -> outline ("implementsdynamic " ^ (stype t))); - (match class_def.cl_array_access with None -> () | Some t -> outline ("arrayaccess " ^ (stype t))); - - let args = function - | TFun (args,_) -> - List.iter (fun (name,opt,t) -> - outline ("arg " ^ name ^ (if opt then " ? " else " : ") ^ (stype t) ) - ) args; - | _ -> () in - let ret = function TFun (_,ret) -> stype ret | _ -> "Dynamic" in - - let print_field stat f = - let pub = if f.cf_public then "pub " else "priv " in - let stat = pub ^ ( if stat then "s " else "m " ) in - (match f.cf_kind, f.cf_name with - | Var { v_read = AccInline; v_write = AccNever },_ -> - outline ("inlinevar " ^ f.cf_name ^ " " ^ (stype f.cf_type) ) - | Var { v_read = AccNormal; v_write = AccNormal },_ -> - outline ("var " ^ stat ^ f.cf_name ^ " " ^ (stype f.cf_type) ) - | Var v,_ -> - let saccess = function | AccNormal -> "v" | AccNo -> "0" | AccNever -> "!" - | AccResolve -> "r" | AccCall -> "c" | AccInline -> "i" | AccRequire (_,_) -> "v" in - outline ("property " ^ stat ^ (saccess v.v_read) ^ " " ^ (saccess v.v_write) - ^ " " ^ f.cf_name ^ " " ^ (stype f.cf_type) ) - | Method _, "new" -> - outline ("function " ^ stat ^ "new " ^ (ret f.cf_type) ); - args f.cf_type - | Method MethDynamic, _ -> - outline ("dynamicfunction " ^ stat ^ f.cf_name ^ " " ^ (ret f.cf_type) ); - args f.cf_type - | Method _, _ -> - outline ("function " ^ stat ^ f.cf_name ^ " " ^ (ret f.cf_type) ); - args f.cf_type - ) in - (match class_def.cl_constructor with | None -> () | Some f -> print_field false f); - List.iter (print_field false) class_def.cl_ordered_fields; - List.iter (print_field true) class_def.cl_ordered_statics; - | TEnumDecl enum_def -> - out ("enum " ^ (spath name) ^ "\n"); - let sorted_items = List.sort (fun f1 f2 -> (f1.ef_index - f2.ef_index ) ) (pmap_values enum_def.e_constrs) in - List.iter (fun constructor -> - outline ("constructor " ^ constructor.ef_name); - match constructor.ef_type with - | TFun (args,_) -> List.iter (fun (arg,_,t) -> outline ("eparam " ^ arg ^ " " ^ (stype t) ) ) args; - | _ -> () - ) sorted_items; - | _ -> () - ) !exe_classes; - - (* Output file info too *) - List.iter ( fun file -> - let full_path = Common.get_full_path (try Common.find_file common_ctx file with Not_found -> file) in - out ("file " ^ (escape file) ^ " " ^ (escape full_path) ^"\n") ) - ( List.sort String.compare ( pmap_keys !file_info) ); - close_out exeClasses; - end; - end; - - let output_name = match common_ctx.main_class with - | Some path -> (snd path) - | _ -> "output" in - - write_build_data common_ctx (common_ctx.file ^ "/Build.xml") !exe_classes !main_deps (!boot_enums@ !boot_classes) !build_xml !extern_src output_name; - let cmd_defines = ref "" in - PMap.iter ( fun name value -> match name with - | "true" | "sys" | "dce" | "cpp" | "debug" -> () - | _ -> cmd_defines := !cmd_defines ^ " -D" ^ name ^ "=\"" ^ (escape_command value) ^ "\"" ) common_ctx.defines; - write_build_options common_ctx (common_ctx.file ^ "/Options.txt") common_ctx.defines; - if ( not (Common.defined common_ctx Define.NoCompilation) ) then begin - let old_dir = Sys.getcwd() in - Sys.chdir common_ctx.file; - let cmd = ref "haxelib run hxcpp Build.xml haxe" in - if (common_ctx.debug) then cmd := !cmd ^ " -Ddebug"; - cmd := !cmd ^ !cmd_defines; - cmd := List.fold_left (fun cmd path -> cmd ^ " -I\"" ^ (escape_command path) ^ "\"" ) !cmd common_ctx.class_path; - print_endline !cmd; - if common_ctx.run_command !cmd <> 0 then failwith "Build failed"; - Sys.chdir old_dir; - end - ;; - -let generate common_ctx = - if (Common.defined common_ctx Define.Cppia) then - generate_cppia common_ctx - else - generate_source common_ctx -;; - - diff --git a/haxe.hxproj b/haxe.hxproj index 27bf5b53..b29fe73b 100644 --- a/haxe.hxproj +++ b/haxe.hxproj @@ -15,7 +15,7 @@ - + @@ -150,15 +150,285 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - make -j4 MSVC=1 FD_OUTPUT=1 -f Makefile.win kill haxe + make -j4 FD_OUTPUT=1 -f Makefile.win kill haxe diff --git a/libs/.editorconfig b/libs/.editorconfig new file mode 100755 index 00000000..703bf30a --- /dev/null +++ b/libs/.editorconfig @@ -0,0 +1,11 @@ +# http://editorconfig.org + +[*.c] +charset = utf-8 +indent_style = tab +indent_size = 4 +end_of_line = lf +indent_brace_style = K&R +insert_final_newline = true +trim_trailing_whitespace = true +max_line_length = 100 diff --git a/libs/.travis.yml b/libs/.travis.yml new file mode 100644 index 00000000..b71ffd8e --- /dev/null +++ b/libs/.travis.yml @@ -0,0 +1,23 @@ +language: generic + +os: + - linux + - osx + +dist: trusty +sudo: required + +install: + # Install dependencies + - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then + sudo add-apt-repository ppa:haxe/ocaml -y; + sudo apt-get update -qq; + sudo apt-get install ocaml camlp4 zlib1g-dev -qqy; + fi + - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then + travis_retry brew update; + travis_retry brew install ocaml camlp4; + fi + +script: + - make diff --git a/libs/Makefile b/libs/Makefile index d0e8b2f0..913d020f 100644 --- a/libs/Makefile +++ b/libs/Makefile @@ -1,7 +1,7 @@ OCAMLOPT = ocamlopt OCAMLC = ocamlc TARGET_FLAG = all -LIBS=extlib extc neko javalib ilib ziplib swflib xml-light ttflib objsize +LIBS=extlib extc neko javalib ilib ziplib swflib xml-light ttflib objsize pcre all: $(LIBS) $(LIBS): @@ -13,9 +13,12 @@ clean: make -C neko clean make -C ziplib clean make -C javalib clean + make -C ilib clean make -C swflib clean make -C xml-light clean make -C ttflib clean + make -C objsize clean + make -C pcre clean .PHONY: all clean $(LIBS) diff --git a/libs/README.md b/libs/README.md new file mode 100644 index 00000000..2298a441 --- /dev/null +++ b/libs/README.md @@ -0,0 +1,5 @@ +# ocamllibs + +[![TravisCI Build Status](https://travis-ci.org/HaxeFoundation/ocamllibs.svg?branch=master)](https://travis-ci.org/HaxeFoundation/ocamllibs) + +Various OCaml libraries. diff --git a/libs/extc/LICENSE b/libs/extc/LICENSE index 5b6e7c66..ecbc0593 100644 --- a/libs/extc/LICENSE +++ b/libs/extc/LICENSE @@ -1,12 +1,12 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to +the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not @@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - - GNU GENERAL PUBLIC LICENSE + + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions: License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) - + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in @@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - + 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is @@ -225,7 +225,7 @@ impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - + 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License @@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -303,10 +303,9 @@ the "copyright" line and a pointer to where the full notice is found. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. @@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names: This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. \ No newline at end of file diff --git a/libs/extc/Makefile b/libs/extc/Makefile index 2fd95ed1..101efd30 100644 --- a/libs/extc/Makefile +++ b/libs/extc/Makefile @@ -1,4 +1,4 @@ -CFLAGS = -I zlib +ALL_CFLAGS = $(CFLAGS) LIBS = -I ../extlib OCAMLOPT=ocamlopt OCAMLC=ocamlc @@ -17,13 +17,13 @@ extc.cmxa: extc.ml process.ml extc_stubs.o process_stubs.o $(OCAMLOPT) -a -o extc.cmxa $(LIBS) extc.ml process.ml extc_stubs.o: extc_stubs.c - $(OCAMLC) $(CFLAGS) extc_stubs.c + $(OCAMLC) $(ALL_CFLAGS) extc_stubs.c process_stubs.o: process_stubs.c - $(OCAMLC) $(CFLAGS) process_stubs.c + $(OCAMLC) $(ALL_CFLAGS) process_stubs.c clean: - rm -f extc.cma extc.cmi extc.cmx extc.cmxa extc.o extc.obj extc.lib extc_stubs.obj extc_stubs.o process.cmx process.obj process.cmi process_stubs.obj process_stubs.o + rm -f extc.cma extc.cmi extc.cmx extc.cmxa extc.o extc.obj extc.lib extc_stubs.obj extc_stubs.o process.cmx process.obj process.cmi process.o process_stubs.obj process_stubs.o rm -f extc.a libextc.a libextc.lib extc.cmo process.cmo test: native diff --git a/libs/extc/extc.ml b/libs/extc/extc.ml index c7e29ea5..be7a6057 100644 --- a/libs/extc/extc.ml +++ b/libs/extc/extc.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type zstream @@ -74,6 +74,8 @@ external dlcaml_callback : int -> value = "sys_dlcaml_callback" external dlint32 : int32 -> value = "sys_dlint32" external getch : bool -> int = "sys_getch" +external filetime : string -> float = "sys_filetime" + (* support for backward compatibility *) let zlib_deflate_init lvl = zlib_deflate_init2 lvl 15 let zlib_inflate_init() = zlib_inflate_init2 15 diff --git a/libs/extc/extc_stubs.c b/libs/extc/extc_stubs.c index 012fe1b2..64428837 100644 --- a/libs/extc/extc_stubs.c +++ b/libs/extc/extc_stubs.c @@ -1,6 +1,6 @@ /* * Extc : C common OCaml bindings - * Copyright (c)2004 Nicolas Cannasse + * Copyright (c)2004-2017 Nicolas Cannasse * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,11 +14,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#include #include #include +#include #include #include #include @@ -34,6 +36,7 @@ # include # include # include +# include # include #endif #ifdef __APPLE__ @@ -51,68 +54,270 @@ # define CLK_TCK 100 #endif +/** + * Converts an OCaml value to a C pointer for a z_stream. + * + * @param v {value} An OCaml value + * @return {z_streamp} A pointer for a z_stream + */ +#define ZStreamP_val(v) (*((z_streamp *) Data_custom_val(v))) -#define zval(z) ((z_streamp)(z)) - -value zlib_new_stream() { - value z = alloc((sizeof(z_stream) + sizeof(value) - 1) / sizeof(value),Abstract_tag); - z_stream *s = zval(z); - s->zalloc = NULL; - s->zfree = NULL; - s->opaque = NULL; - s->next_in = NULL; - s->next_out = NULL; - return z; +/** + * Converts an OCaml `Extc.zflush` value to an allowed flush value for _zlib_. + * + * It may raise the following OCaml exception: + * - Failure: Unknown zflush value. + * + * Make sure to update this function when refactoring OCaml's `Extc.zflush` type. The integer value + * of OCaml's `Extc.zflush` is the 0-based index of the position of the constructor in the type + * definition. + * + * See: + * https://github.com/HaxeFoundation/haxe-debian/blob/31cb4aaab9f6770d058883a1c5b97e36c8ec5d71/libs/extc/extc.ml#L22 + * https://github.com/madler/zlib/blob/cacf7f1d4e3d44d871b605da3b647f07d718623f/zlib.h#L168 + * + * @param zflush_val {value} OCaml `Extc.zflush` + * @return {int} C int representing an allowed flush value for _zlib_ + */ +int Zflush_val(value zflush_val) { + switch (Int_val(zflush_val)) { + case 0: return Z_NO_FLUSH; + case 1: return Z_PARTIAL_FLUSH; + case 2: return Z_SYNC_FLUSH; + case 3: return Z_FULL_FLUSH; + case 4: return Z_FINISH; + // TODO: support Z_BLOCK and Z_TREE + // TODO: append the received value + default: failwith("Error in `Zflush_val` (extc_stubs.c): Unknown zflush value"); + } + assert(0); } -CAMLprim value zlib_deflate_init2(value lvl,value wbits) { - value z = zlib_new_stream(); - if( deflateInit2(zval(z),Int_val(lvl),Z_DEFLATED,Int_val(wbits),8,Z_DEFAULT_STRATEGY) != Z_OK ) - failwith("zlib_deflate_init"); - return z; +/** + * Converts an allowed flush value for _zlib_ to an OCaml `Extc.zflush` value. + * + * Make sure to update this function when refactoring OCaml's `Extc.zflush` type. The integer value + * of OCaml's `Extc.zflush` is the 0-based index of the position of the constructor in the type + * definition. + * + * See: + * https://github.com/madler/zlib/blob/cacf7f1d4e3d44d871b605da3b647f07d718623f/zlib.h#L168 + * https://github.com/HaxeFoundation/haxe-debian/blob/31cb4aaab9f6770d058883a1c5b97e36c8ec5d71/libs/extc/extc.ml#L22 + * + * @param {int} C int representing an allowed flush value for _zlib_ + * @return {value} OCaml `Extc.zflush` + */ +value val_Zflush(int zflush) { + switch (zflush) { + case Z_NO_FLUSH: return Val_int(0); + case Z_PARTIAL_FLUSH: return Val_int(1); + case Z_SYNC_FLUSH: return Val_int(2); + case Z_FULL_FLUSH: return Val_int(3); + case Z_FINISH: return Val_int(4); + // TODO: support Z_BLOCK and Z_TREE + } + assert(0); } -CAMLprim value zlib_deflate( value zv, value src, value spos, value slen, value dst, value dpos, value dlen, value flush ) { - z_streamp z = zval(zv); - value res; - int r; +/** + * Free the memory of the pointer contained in the supplied OCaml value `caml_z_stream_pointer`. + * + * @param z_streamp_val {value} An OCaml value containing a z_stream pointer to the memory to free. + */ +void zlib_free_stream(value z_streamp_val) { + caml_stat_free(ZStreamP_val(z_streamp_val)); + ZStreamP_val(z_streamp_val) = NULL; +} - z->next_in = (Bytef*)(String_val(src) + Int_val(spos)); - z->next_out = (Bytef*)(String_val(dst) + Int_val(dpos)); - z->avail_in = Int_val(slen); - z->avail_out = Int_val(dlen); - if( (r = deflate(z,Int_val(flush))) < 0 ) - failwith("zlib_deflate"); +/** + * Define the custom operations for a z_stream. This ensures that the memory owned + * by the z_stream pointer is freed. + * + * See: + * https://github.com/ocaml/ocaml/blob/70d880a41a82aae1ebd428fd38100e8467f8535a/byterun/caml/custom.h#L25 + */ +static struct custom_operations zlib_stream_ops = { + // identifier + "z_stream_ops", + // finalize + &zlib_free_stream, + // compare + NULL, + // hash + NULL, + // serialize + NULL, + // compare_ext + NULL +}; + +/** + * Create an OCaml value containing a new z_stream pointer. + * + * This function may raise the following OCaml exception: + * - Out_of_memory exception + * + * @return {value} An OCaml value containing a new z_stream pointer. + */ +value zlib_new_stream() { + value z_streamp_val = caml_alloc_custom(&zlib_stream_ops, sizeof(z_streamp), 0, 1); + ZStreamP_val(z_streamp_val) = caml_stat_alloc(sizeof(z_stream)); + ZStreamP_val(z_streamp_val)->zalloc = NULL; + ZStreamP_val(z_streamp_val)->zfree = NULL; + ZStreamP_val(z_streamp_val)->opaque = NULL; + ZStreamP_val(z_streamp_val)->next_in = NULL; + ZStreamP_val(z_streamp_val)->next_out = NULL; + return z_streamp_val; +} + +/** + * OCaml binding for _zlib_'s `deflateInit2` function. + * + * This creates a new stream and initializes it for deflate. + * + * This function may raise the following OCaml exceptions: + * - Out_of_memory exception + * - Failure exception: Invalid parameters + * - Failure exception: Invalid version + * - Failure exception: Unknown zlib return code + * + * See: + * https://github.com/madler/zlib/blob/cacf7f1d4e3d44d871b605da3b647f07d718623f/zlib.h#L538 + * + * @param levelVal {value} OCaml `int`: the compression level, must be in the range 0..9. + * 0 gives no compression at all, 1 the best speed, 9 the best compression. + * @param windowBitsVal {value} OCaml `int`: base two logarithm of the window size (size of the + * history buffer) used by _zlib_. It should be in the range 9..15 for this version of _zlib_. + * It can also be in the range -15..-8 (the absolute value is used) for raw deflate. + * Finally, it can be greater than 15 for gzip encoding. See _zlib_'s documentation for + * `deflateInit2` for the exact documentation. + * @return {value} An OCaml value representing the new stream, initialized for deflate. + */ +CAMLprim value zlib_deflate_init2(value level_val, value window_bits_val) { + int level = Int_val(level_val); + int window_bits = Int_val(window_bits_val); + value z_streamp_val = zlib_new_stream(); + z_streamp stream = ZStreamP_val(z_streamp_val); + + int deflate_init2_result = deflateInit2( + stream, + level, + Z_DEFLATED, // method + window_bits, + 8, // memLevel + Z_DEFAULT_STRATEGY // strategy + ); + + if (deflate_init2_result == Z_OK) { + return z_streamp_val; + } - z->next_in = NULL; - z->next_out = NULL; + switch (deflate_init2_result) { + case Z_MEM_ERROR: + caml_raise_out_of_memory(); + break; + case Z_STREAM_ERROR: + // TODO: use stream->msg to get _zlib_'s text message + failwith("Error in `zlib_deflate_init2` (extc_stubs.c): call to `deflateInit2` failed: Z_STREAM_ERROR"); + break; + case Z_VERSION_ERROR: + // TODO: use stream->msg to get _zlib_'s text message + failwith("Error in `zlib_deflate_init2` (extc_stubs.c): call to `deflateInit2` failed: Z_VERSION_ERROR"); + break; + default: + failwith("Error in `zlib_deflate_init2` (extc_stubs.c): unknown return code from `deflateInit2`"); + } + assert(0); +} - res = alloc_small(3, 0); - Field(res, 0) = Val_bool(r == Z_STREAM_END); - Field(res, 1) = Val_int(Int_val(slen) - z->avail_in); - Field(res, 2) = Val_int(Int_val(dlen) - z->avail_out); - return res; +/** + * OCaml binding for _zlib_'s `deflate` function. + * + * Compresses as much data as possible, and stops when the input buffer becomes empty or the output + * buffer becomes full. + * + * This function may raise the following OCaml exceptions: + * - Out_of_memory exception + * - Failure exception: Invalid parameters + * - Failure exception: Invalid version + * - Failure exception: Unknown zlib return code + * + * See: + * https://github.com/madler/zlib/blob/cacf7f1d4e3d44d871b605da3b647f07d718623f/zlib.h#L250 + * + * @param stream_val {value} OCaml `Extc.zstream`: value containing a z_stream pointer to a deflate + * stream. + * @param src {value} OCaml `bytes`: Source buffer + * @param spos {value} OCaml `int`: Index of the inclusive start offset of the source. + * @param slen {value} OCaml `int`: Length of the data to read from the source buffer, from spos. + * @param dst {value} OCaml `bytes`: Source buffer + * @param dpos {value} OCaml `int`: Index of the inclusive start offset of the source. + * @param dlen {value} OCaml `int`: Length of the data to read from the source buffer, from spos. + * @param flush_val {value} OCaml `Extc.zflush`: Controls the flush logic. See _zlib_'s + * documentation. + * @return {value} OCaml `Extc.reslut`. + */ +CAMLprim value zlib_deflate(value stream_val, value src, value spos, value slen, value dst, value dpos, value dlen, value flush_val) { + z_streamp stream = ZStreamP_val(stream_val); + int flush = Zflush_val(flush_val); + + stream->next_in = (Bytef*)(String_val(src) + Int_val(spos)); + stream->next_out = (Bytef*)(String_val(dst) + Int_val(dpos)); + stream->avail_in = Int_val(slen); + stream->avail_out = Int_val(dlen); + + int deflate_result = deflate(stream, flush); + + if (deflate_result == Z_OK || deflate_result == Z_STREAM_END) { + stream->next_in = NULL; + stream->next_out = NULL; + value zresult = alloc_small(3, 0); + // z_finish + Field(zresult, 0) = Val_bool(deflate_result == Z_STREAM_END); + // z_read + Field(zresult, 1) = Val_int(Int_val(slen) - stream->avail_in); + // z_wrote + Field(zresult, 2) = Val_int(Int_val(dlen) - stream->avail_out); + + return zresult; + } + switch (deflate_result) { + case Z_MEM_ERROR: + caml_raise_out_of_memory(); + break; + case Z_STREAM_ERROR: + // TODO: use stream->msg to get _zlib_'s text message + failwith("Error in `zlib_deflate` (extc_stubs.c): call to `deflate` failed: Z_STREAM_ERROR"); + break; + case Z_BUF_ERROR: + // TODO: use stream->msg to get _zlib_'s text message + failwith("Error in `zlib_deflate` (extc_stubs.c): call to `deflate` failed: Z_BUF_ERROR"); + break; + default: + failwith("Error in `zlib_deflate` (extc_stubs.c): unknown return code from `deflate`"); + } + assert(0); } -CAMLprim value zlib_deflate_bytecode(value * arg, int nargs) { - return zlib_deflate(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],arg[7]); +CAMLprim value zlib_deflate_bytecode(value *arg, int nargs) { + return zlib_deflate(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], arg[7]); } CAMLprim value zlib_deflate_end(value zv) { - if( deflateEnd(zval(zv)) != 0 ) + if( deflateEnd(ZStreamP_val(zv)) != 0 ) failwith("zlib_deflate_end"); return Val_unit; } CAMLprim value zlib_inflate_init(value wbits) { value z = zlib_new_stream(); - if( inflateInit2(zval(z),Int_val(wbits)) != Z_OK ) + if( inflateInit2(ZStreamP_val(z),Int_val(wbits)) != Z_OK ) failwith("zlib_inflate_init"); return z; } CAMLprim value zlib_inflate( value zv, value src, value spos, value slen, value dst, value dpos, value dlen, value flush ) { - z_streamp z = zval(zv); + z_streamp z = ZStreamP_val(zv); value res; int r; @@ -138,13 +343,13 @@ CAMLprim value zlib_inflate_bytecode(value * arg, int nargs) { } CAMLprim value zlib_inflate_end(value zv) { - if( inflateEnd(zval(zv)) != 0 ) + if( inflateEnd(ZStreamP_val(zv)) != 0 ) failwith("zlib_inflate_end"); return Val_unit; } CAMLprim value zlib_deflate_bound(value zv,value len) { - return Val_int(deflateBound(zval(zv),Int_val(len))); + return Val_int(deflateBound(ZStreamP_val(zv),Int_val(len))); } CAMLprim value executable_path(value u) { @@ -305,6 +510,27 @@ CAMLprim value sys_getch( value b ) { # endif } +CAMLprim value sys_filetime( value file ) { +# ifdef _WIN32 + FILETIME fp; + ULARGE_INTEGER ui; + HANDLE h = CreateFile(String_val(file),FILE_READ_ATTRIBUTES,FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL); + if( h == INVALID_HANDLE_VALUE || !GetFileTime(h,NULL,NULL,&fp) ) { + CloseHandle(h); + return caml_copy_double(0.); + } + CloseHandle(h); + ui.LowPart = fp.dwLowDateTime; + ui.HighPart = fp.dwHighDateTime; + return caml_copy_double( ((double)ui.QuadPart) / 10000000.0 - EPOCH_DIFF ); +# else + struct stat sbuf; + if( stat(String_val(file),&sbuf) < 0 ) + return caml_copy_double(0.); + return caml_copy_double( sbuf.st_mtime ); +# endif +} + // --------------- Support for NekoVM Bridge CAMLprim value sys_dlopen( value lib ) { diff --git a/libs/extc/process.ml b/libs/extc/process.ml index 8e94f7d5..fef8c098 100644 --- a/libs/extc/process.ml +++ b/libs/extc/process.ml @@ -14,12 +14,12 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type process -external run : string -> string array -> process = "process_run" +external run : string -> string array option -> process = "process_run" external read_stdout : process -> string -> int -> int -> int = "process_stdout_read" external read_stderr : process -> string -> int -> int -> int = "process_stderr_read" external write_stdin : process -> string -> int -> int -> int = "process_stdin_write" diff --git a/libs/extc/process_stubs.c b/libs/extc/process_stubs.c index b083fb1a..97bb7fe9 100644 --- a/libs/extc/process_stubs.c +++ b/libs/extc/process_stubs.c @@ -35,7 +35,11 @@ # include # include # ifndef __APPLE__ -# include +# if defined(__FreeBSD__) || defined(__DragonFly__) +# include +# else +# include +# endif # endif #endif @@ -62,6 +66,7 @@ #define alloc_int(i) Val_int(i) #define val_gc(v,callb) #define val_null Val_int(0) +#define val_some(v) Field(v,0) #define val_int(v) Int_val(v) #define DEFINE_KIND(_) #define neko_error() failwith(__FUNCTION__) @@ -232,16 +237,24 @@ static void free_process( value vp ) { } /** - process_run : cmd:string -> args:string array -> 'process + process_run : cmd:string -> args:string array option -> 'process Start a process using a command and the specified arguments. + When args is not null, cmd and args will be auto-quoted/escaped. + If no auto-quoting/escaping is desired, you should append necessary + arguments to cmd as if it is inputted to the shell directly, and pass + null as args. **/ CAMLprim value process_run( value cmd, value vargs ) { - int i; + int i, isRaw; vprocess *p; val_check(cmd,string); - val_check(vargs,array); + isRaw = vargs == val_null; + if (!isRaw) { + val_check(vargs,array); + vargs = val_some(vargs); + } # ifdef _WIN32 { SECURITY_ATTRIBUTES sattr; @@ -251,30 +264,59 @@ CAMLprim value process_run( value cmd, value vargs ) { // creates commandline buffer b = alloc_buffer(NULL); char *sargs; - buffer_append_char(b,'"'); - buffer_append_str(b,val_string(cmd)); - buffer_append_char(b,'"'); - for(i=0;i buf:string -> pos:int -> len:int -> int Read up to [len] bytes in [buf] starting at [pos] from the process stdout. - Returns the number of bytes readed this way. Raise an exception if this + Returns the number of bytes read this way. Raise an exception if this process stdout is closed and no more data is available for reading. **/ @@ -405,7 +456,7 @@ CAMLprim value process_stdout_read( value vp, value str, value pos, value len ) process_stderr_read : 'process -> buf:string -> pos:int -> len:int -> int Read up to [len] bytes in [buf] starting at [pos] from the process stderr. - Returns the number of bytes readed this way. Raise an exception if this + Returns the number of bytes read this way. Raise an exception if this process stderr is closed and no more data is available for reading. **/ diff --git a/libs/extc/test.ml b/libs/extc/test.ml index 0dfccdf3..20eb2900 100644 --- a/libs/extc/test.ml +++ b/libs/extc/test.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) if Array.length Sys.argv > 1 then begin diff --git a/libs/extc/zlib/README.txt b/libs/extc/zlib/README.txt deleted file mode 100644 index a6bafaec..00000000 --- a/libs/extc/zlib/README.txt +++ /dev/null @@ -1 +0,0 @@ -1.2.3 static LIBCMT \ No newline at end of file diff --git a/libs/extc/zlib/zconf.h b/libs/extc/zlib/zconf.h deleted file mode 100644 index 557594c1..00000000 --- a/libs/extc/zlib/zconf.h +++ /dev/null @@ -1,332 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: zconf.h,v 1.1 2007-02-15 14:41:38 ncannasse Exp $ */ - -#ifndef ZCONF_H -#define ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - */ -#ifdef Z_PREFIX -# define deflateInit_ z_deflateInit_ -# define deflate z_deflate -# define deflateEnd z_deflateEnd -# define inflateInit_ z_inflateInit_ -# define inflate z_inflate -# define inflateEnd z_inflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateSetDictionary z_deflateSetDictionary -# define deflateCopy z_deflateCopy -# define deflateReset z_deflateReset -# define deflateParams z_deflateParams -# define deflateBound z_deflateBound -# define deflatePrime z_deflatePrime -# define inflateInit2_ z_inflateInit2_ -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateCopy z_inflateCopy -# define inflateReset z_inflateReset -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table -# define zError z_zError - -# define alloc_func z_alloc_func -# define free_func z_free_func -# define in_func z_in_func -# define out_func z_out_func -# define Byte z_Byte -# define uInt z_uInt -# define uLong z_uLong -# define Bytef z_Bytef -# define charf z_charf -# define intf z_intf -# define uIntf z_uIntf -# define uLongf z_uLongf -# define voidpf z_voidpf -# define voidp z_voidp -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ -# include /* for off_t */ -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ -# endif -# define z_off_t off_t -#endif -#ifndef SEEK_SET -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif -#ifndef z_off_t -# define z_off_t long -#endif - -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf -# ifdef FAR -# undef FAR -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) -# pragma map(deflateInit_,"DEIN") -# pragma map(deflateInit2_,"DEIN2") -# pragma map(deflateEnd,"DEEND") -# pragma map(deflateBound,"DEBND") -# pragma map(inflateInit_,"ININ") -# pragma map(inflateInit2_,"ININ2") -# pragma map(inflateEnd,"INEND") -# pragma map(inflateSync,"INSY") -# pragma map(inflateSetDictionary,"INSEDI") -# pragma map(compressBound,"CMBND") -# pragma map(inflate_table,"INTABL") -# pragma map(inflate_fast,"INFA") -# pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/libs/extc/zlib/zlib.h b/libs/extc/zlib/zlib.h deleted file mode 100644 index 02281792..00000000 --- a/libs/extc/zlib/zlib.h +++ /dev/null @@ -1,1357 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.3, July 18th, 2005 - - Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -#ifndef ZLIB_H -#define ZLIB_H - -#include "zconf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.2.3" -#define ZLIB_VERNUM 0x1230 - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms will be added later and will have the same - stream interface. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip streams in memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never - crash even in case of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - uLong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - Bytef *extra; /* pointer to extra field or Z_NULL if none */ - uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ - uInt extra_max; /* space at extra (only when reading header) */ - Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ - uInt name_max; /* space at name (only when reading header) */ - Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ - uInt comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ -} gz_header; - -typedef gz_header FAR *gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -/* Allowed flush values; see deflate() and inflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative - * values are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - /* basic functions */ - -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. - If zalloc and zfree are set to Z_NULL, deflateInit updates them to - use default allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at - all (the input data is simply copied a block at a time). - Z_DEFAULT_COMPRESSION requests a default compromise between speed and - compression (currently equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if level is not a valid compression level, - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). - msg is set to null if there is no error message. deflateInit does not - perform any compression: this will be done by deflate(). -*/ - - -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce some - output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). - Some output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating avail_in or avail_out accordingly; avail_out - should never be zero before the call. The application can consume the - compressed output when it wants, for example when the output buffer is full - (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK - and with zero avail_out, it must be called again after making room in the - output buffer because there might be more output pending. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumualte before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In particular - avail_in is zero after the call if enough output space has been provided - before the call.) Flushing may degrade compression for some compression - algorithms and so it should be used only when necessary. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there - was enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the - stream are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least - the value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect - the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, - msg may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the exact - value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller. msg is set to null if there is no error - message. inflateInit does not perform any decompression apart from reading - the zlib header if present: this will be done by inflate(). (So next_in and - avail_in may be modified, but next_out and avail_out are unchanged.) -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there - is no more input data or no more space in the output buffer (see below - about the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). If inflate returns Z_OK and with zero avail_out, it - must be called again after making room in the output buffer because there - might be more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, - Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() stop - if and when it gets to the next deflate block boundary. When decoding the - zlib or gzip format, this will cause inflate() to return immediately after - the header and before the first block. When doing a raw inflate, inflate() - will go ahead and process the first block, and will return when it gets to - the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 - if inflate() is currently decoding the last block in the deflate stream, - plus 128 if inflate() returned immediately after decoding an end-of-block - code or decoding the complete header up to just before the first byte of the - deflate stream. The end-of-block will not be indicated until all of the - uncompressed data from that block has been written to strm->next_out. The - number of unused bits may in general be greater than seven, except when - bit 7 of data_type is set, in which case the number of unused bits will be - less than eight. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster approach - may be used for the single inflate() call. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() will decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically. Any information - contained in the gzip header is not retained, so applications that need that - information should instead use raw inflate, see inflateInit2() below, or - inflateBack() and perform their own processing of the gzip header and - trailer. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may then - call inflateSync() to look for a good compression block if a partial recovery - of the data is desired. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by - the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), - no header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but - is slow and reduces compression ratio; memLevel=9 uses maximum memory - for optimal speed. The default value is 8. See zconf.h for total memory - usage as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as - Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy - parameter only affects the compression ratio but not the correctness of the - compressed output even if it is not set appropriately. Z_FIXED prevents the - use of dynamic Huffman codes, allowing for a simpler decoder for special - applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid - method). msg is set to null if there is no error message. deflateInit2 does - not perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any - call of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size in - deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. In addition, the - current implementation of deflate will use at most the window size minus - 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and - can consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. - The stream will keep the same compression level and any other attributes - that may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different - strategy. If the compression level is changed, the input available so far - is compressed with the old level (and may be flushed); the new level will - take effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to - be compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR - if strm->avail_out was zero. -*/ - -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() - or deflateInit2(). This would be used to allocate an output buffer - for deflation in a single pass, and so would be called before deflate(). -*/ - -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the - bits leftover from a previous deflate stream when appending to it. As such, - this function can only be used for raw deflate, and must be used before the - first deflate() call after a deflateInit2() or deflateReset(). bits must be - less than or equal to 16, and that many of the least significant bits of - value will be inserted in the output. - - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is - a crc32 instead of an adler32. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg - is set to null if there is no error message. inflateInit2 does not perform - any decompression apart from reading the zlib header if present: this will - be done by inflate(). (So next_in and avail_in may be modified, but next_out - and avail_out are unchanged.) -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been found, - or Z_STREAM_ERROR if the stream structure was inconsistent. In the success - case, the application may save the current current value of total_in which - indicates where valid compressed data was found. In the error case, the - application may repeatedly call inflateSync, providing more input each time, - until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. - The stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK can be used to - force inflate() to return immediately after header processing is complete - and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When - any of extra, name, or comment are not Z_NULL and the respective field is - not present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not - be allocated, or Z_VERSION_ERROR if the version of the library does not - match the version of the header file. -*/ - -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free - the allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects - only the raw deflate stream to decompress. This is different from the - normal behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format - error in the deflate stream (in which case strm->msg is set to indicate the - nature of the error), or Z_STREAM_ERROR if the stream was not properly - initialized. In the case of Z_BUF_ERROR, an input or output error can be - distinguished using strm->next_in which will be Z_NULL only if in() returned - an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to - out() returning non-zero. (in() will always be called before out(), so - strm->next_in is assured to be defined if out() returns non-zero.) Note - that inflateBack() cannot return Z_OK. -*/ - -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - - - /* utility functions */ - -/* - The following utility functions are implemented on top of the - basic stream-oriented functions. To simplify the interface, some - default options are assumed (compression level and memory usage, - standard memory allocation functions). The source code of these - utility functions can easily be modified if you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least the value returned - by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before - a compress() or compress2() call to allocate the destination buffer. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. -*/ - - -typedef voidp gzFile; - -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); -/* - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb") but can also include a compression level - ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for - Huffman only compression as in "wb1h", or 'R' for run-length encoding - as in "wb1R". (See the description of deflateInit2 for more information - about the strategy parameter.) - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. - - gzopen returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). */ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen() associates a gzFile with the file descriptor fd. File - descriptors are obtained from calls like open, dup, creat, pipe or - fileno (in the file has been previously opened with fopen). - The mode parameter is as in gzopen. - The next call of gzclose on the returned gzFile will also close the - file descriptor fd, just like fclose(fdopen(fd), mode) closes the file - descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). - gzdopen returns NULL if there was insufficient memory to allocate - the (de)compression state. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. - If the input file was not in gzip format, gzread copies the given number - of bytes into the buffer. - gzread returns the number of uncompressed bytes actually read (0 for - end of file, -1 for error). */ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes actually written - (0 in case of error). -*/ - -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). The number of - uncompressed bytes written is limited to 4095. The caller should assure that - this limit is not exceeded. If it is exceeded, then gzprintf() will return - return an error (0) with nothing written. In this case, there may also be a - buffer overflow with unpredictable consequences, which is possible only if - zlib was compiled with the insecure functions sprintf() or vsprintf() - because the secure snprintf() or vsnprintf() functions were not available. -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or - a newline character is read and transferred to buf, or an end-of-file - condition is encountered. The string is then terminated with a null - character. - gzgets returns buf, or Z_NULL in case of error. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ - -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read again later. - Only one character of push-back is allowed. gzungetc() returns the - character pushed, or -1 on failure. gzungetc() will fail if a - character has been pushed but not read yet, or if c is -1. The pushed - character will be discarded if the stream is repositioned with gzseek() - or gzrewind(). -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. The return value is the zlib - error number (see function gzerror below). gzflush returns Z_OK if - the flush parameter is Z_FINISH and all output could be flushed. - gzflush should be called only when strictly necessary because it can - degrade compression. -*/ - -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); -/* - Sets the starting position for the next gzread or gzwrite on the - given compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); -/* - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ - -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Returns 1 if file is being read directly without decompression, otherwise - zero. -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. The return value is the zlib - error number (see function gzerror below). -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ - -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the - compression library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns - the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); -/* - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is NULL, this function returns the required initial - value for the for the crc. Pre- and post-conditioning (one's complement) is - performed within this function so it shouldn't be done by the application. - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); - -/* - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) - - -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; /* hack for buggy compilers */ -#endif - -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H */ diff --git a/libs/extc/zlib/zlib.lib b/libs/extc/zlib/zlib.lib deleted file mode 100644 index 4d3d6fcda34af86d19ad70a565687481be72d878..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109512 zcmeFa34B!5**|_KGf5^3%m5=qjWWup(F9CLfW$$WEF^)f5C|ws2uTJ4A;DyZeV;@# zxrSoJrLDHM+G<-{eOq6_wS)j+sS4t*wWwVP5k;{eZux(|=iWO@7Qm(b_x*f+Cwb;< z&w0*sw&(2UUN*kGzGC4Gk=I&-RZ`Npq%kRJDJ+hb zbQ=8h21%#EgI`O!2fr?>u65RwyQ<2Z8!4(uBvrS7_+2mNnKCmY)9tg?BdMKi8(;7s9UnM+*LilrfR~NWmWYJpdLgz z-;rIIUX+p_P)a&Q;VcU0Gkf zU?FOkRt;U{C=IQKWMnytCue3%%F04vEkmTJ1tO*iV_YkjRt4p9#ze=&f})(v{G1{` z^7881%DUwf#xzu~>V=(CRG61PvADpou&TV0IbKm;fjU#&AnJZF?QBQE#7Q|5a}fz^ zO?^F@0V<>@@QQ_16^nz>a~wGZS=pHxImLcfn4jgf6;%!3rpnb5KR+XHQsJb$KJdX8 z3LzLj*O8r*mp3`5C^L{9rIdi*o1t7s{-lh8f=M~)fdPC8?;T*WBO^Z}BeSTW$lrb`deT>3cUt#hbV5>MgBO@Tp{A%Q_mYDjg zrB&rUvMb*)DK{@CD}CZbKXYu#thsE$X!x#$b;0d4qrj1!otm)A^4 z(qikK)dh}8lL~UuCl&S|tgmzxI`VVU)3b7l^8B$W&B0fLwM+>Vi5W$XiJ8R(=@4lC za9YhlrLU`-FveMqx;nqSN1cQ4%R%{OBY_Tqwxqmvr9T@Xk{~~o8i)$Ga>;y$ug&=k znP`qa%f#ABpE;+>l`9&F&t($2gwbU|R==&dzIqA7hT5d3R-wN8Y$a8$ET0_ryRNK- zm{J3jz*1aSUF#2&fzmiL5b6o>6 zWx=Y-YDy1bs#{tGDY{@)Rh?64iU41*O2|~YEU0oJUxW^sykM0UU}-(FM}%4GRxqFo z4D?bcw*{-}t0?-+Jye@oJyctd>fv|Q>YwT|&0Xtf79EqXAAu0( z_(W)MUoyX%h)5)z%9P%P?m}1qPc<=!YE)BPURhIBPg1JEN9-Gqj>o2`1Lb*iTxBqiJ`NiW|nNguu@NmJj%m@-5sjZfA|(TjD` z4L{XMUq7hh@LCF$qE(2H_!lZ{in;G!Vkm#%QsAFiGD{}$r{Y6Mo z;;%1GjFL_=N+FUSe<4zsk1O(a_Tl1Ln)TU7lIPv%&wIrA-!d%u_lAJBB*%IV+MX-33nMwc5hJT9?#XH#TjY>Y%wN zCXOA8oq^G5iK&XyyvTf=UeeXRJh3uDk}R0XP>pg`t#Bzu@%xi-NxBWDIHTei4b3VQ z&l|-BH<;;9WdPi-;s^))IHckoqbjTByBF9>ex~B>fct~J@XQ&VdYvS-PLi@wTGq-c zEdEs2F0f`|xy|aVuUlfxTv%V-U`?;Z>R>}%t+Yj5gS4tcm}`|494i-%B+XA-WKmq@ z?q2R#oUvjF$I9ZDbGWA~BVB45tV{N+c-kXvSy0VgYn0~SG zi=3)jw>x#?nOZE1xDz*ijx~cx?l{4;=@)HBjh-VW&u3xop{KF^v_W!*bVYZB3gYE&Fs2$%Z4vZ%LgRyaQ?34z=n1+Ig%|lB+5AA71?lm%b%}#`|$C`9qtR; zj+%dyw#H^Q-7+6lISnaVzN>QvjPk*@W9F8<51UPmpMva$cTKJjzo=$yBSaWzwwyvc##Ir}=oTF==5#s64qu>yz(~P?2`CR9I7Kx5?Z7X89 zmT-h3VopeNj^5K@IQg5-qhEJ-KkP6y4Md)5DIBp|zf+!OGs=cdolmL$@1bCO_(#+K zLc}BQl~K1&zk!HT$>%%3)$jMLu_a1wTYQ`T1iWMHZOi7xw}Cq_-&G3RRG%#u{)zUz z%M$c1TZ;Zf{KxSm$Pl9h4#t z`u9z>H8z83{V~%=`{da+W0!7=>2RCpE9>&XrrLj*YH#rDF_=z%?b&TLb#<8DI$~OP z#I*ix+2Aof@n=)*zWC1IS`>>kidytk=O7qGNwW?eK^dV6yDT7Xs@-c^*A{TcEozkU6Lvh-68T{=qVqNi(}h5_3&ABWAKsbft^x61oc`;^4q;tk_Uv-pH*3z^ zvUceR{0AeVFzI?!WyLhfXX=KK2P5wMNo0m{f7y?5w&9_Y!O@H(1MSE3H_mc44^CFuS&*ytcNy z0VC%OH&)->vpJ+4nKWwjsN_K7()zkZSod$3y{x*yU0zc$cJ>T0{Km#yS$au9+0?#< z-zn12L3*T`Tv3Hfk<#X21=SVxbq#e+mo;wc)z*S?*sSSbUwz_j+sp!AlD@|H zU_sb-=Dwn?)>U6UfA$j06jr2;^-mIDS7XvN2N%*uRab5v#*qkGPSE&{DbedVf@8n# zSK8Q)E=VwNSPH>P8`sg5-K}1?gT`KpA@c!@3q=fdsrXe~NF6KffJT5H=LXmkgIwmq zM#T^cod%dH0ZOPXFsb7^v9!YNUCbmatIEXoyEb*?WB_>nV-}bXHZ1mqR7aD6o9rTd zPzZMeh%Q;-3#1J*%P^e8(T#c$;@afk0l05A*mJzDj?0rqr>6PG<>8V8;T zP0UW8o<9vu_qxmRlUXqBa%+%dQGQlodcnk!%dHH$20JuV?(f_T&sT^9PR~=NA!b(L zFzoD5dMLk_1q+d)rLO8F)vJ{Gk2oL#K|L9H`Q=-gD&HJV98nmRm`Ltbi5Jjv=&ILI-UO?_R>Rcj zb!<1mDzL>U5|3?$O5PiRb8u8;)sq^Ei|gxX7C1rjmiT%d^N(?Kw0!+fMS8&^+Ml9Z z)%;|ysVKSxwl8$9phJJAhsuB*yWqJyWu#um5+WZ@?EeLdOvAneE>vNX7MDLqG#7`! z;7`xk(OvY2ojZq;R00TET?<-A4qBb-^MG3Lc{j0u7kTZt6h$bizvo=tNJ;bU?`o?X z#YSbc0rrAQgLVTFa~ll-$|@y7nklOr^zTmz>8P%5Xn21D@|GT9C~YxYGEARQTH^U2 zMLs4^Un9?1k#-*=UaoID7Lp-9%kB#k#zc9d%ihrtB7cUlUYzVsl?!Sxc(-{mGu3|# zQ?yea>Xc_EcW>OoVVVx}FOdO3p|HLs(qn2o*wgDDAfs@IZT#R+2Yg=co?egnys~?G-Rbih*3)a1 z&x;Z~h{H0~%e6MhIahOD737?xIX473U!*zL1UYlCDoV2|$oT`X$09PDZoLsxnobN$ zyIG{Brj=Y1KurkkyZ|_&m^aXF=nU2Dx6-cf{1?(8{5R7c()oAIekbj^&R0}B)(upe zVV!M0x4$Ar;)Qqq&gb@+>SpZxkK4)2R|2~h$?P_W2&ji1V{OEG@EGsXL6}N zd4}FKGV&!?_;aXbQr8q`6wQ?JT@yFHhh$5zQZROneU8$&>sn7om}gJelM`S$`H(Bt z^PxeW@n!PR$d}yaY=m}4W-H;`y6kwwVt3i%mJebx#p*@^8*b-qUv_sx3dFIKhPS!l za(G44OaFrYlR|hIo$`&{TA0q+z{gC_011!_%sB6yrIavxmxsu0o?R)k=9bNA9}t;S zTEGniYn>Q)G*neuIfcRuW~Ep;wemQUtE$$Tl$JJjWLm0q{z_|3bxloGgSE7-rl!2s zH6XI&-kI{=G3xBK8|7Ar)iU(9OX&Tgse^mg`p zT_+ULXhS-k7$hd*2-Ox;NG)Z=$r6Z*tjRUlSs~ z4oMj!*QX-w26<6U>zXkVgql_EIQ_ckh#nbbkuwrT3fXvceMs_g5Qk%|{sc42v~4(o zn@!thr*^{-Ew6IO7F*XvBlerNMHkthH{EgsQEfcNzSGqFGR&rJSxMdYb~k732Gcf! z&Yop6yI=HTQIQNFW<8gkEKhxgdfEC+su3-x_3=b%vSDu1M+1=Mn-o4nUoPgBQ0kjOV@|U?VepWwQ68W zi38=<<<+i*R?asQ`mH2ll|G}sy1dppwVY=;69Vf^>VQbL3~eUA`aeCBSI3NE&*a-p z{6zyF!M#%1q`e85Pz|Czit3PDDzN*l+}irxU@Hq|3Q3mp4WlIe9E#q?GzKPsK1 zjS)GLeHYGtmn+~h95PRFNrkP)s7_o(IM?-sYm<_KX34&}bB{YON!r{w8Ny2_Wlt*| zbLY+AOPT3Oy1*2IC21j`=crH2iR&BcD{P5L#G#rA_!N+@<{C8z{zoZzqhS>)71>tW zBWE4Jqf?5?#mG!7S`}qZFPOM4X?9^|dSPKY4EaTw>G>rvOsiV5baqYc;-uu{QLZIR z6EIISqQF=lR9tKNAj%RvPs}WxHgzIL-N8yH*4t1v8+y8vpTs`gBam0QDl*feDY_W} z;ZmwT1$rsQ_+|K=C{2ZFl2jxW!afPV*)UT*YxwAEmVO9;HBQsn4i zsH-mE#KHAy@SKFyr%7X^k%%!-=SYODliUbvm2%+1Jgfm7t8^ux050`7 zuWFUjMa)cvB#jsR7O8PD_sM~l|Freb_cfUH>7-(Wtpi0j^3xTNQh!9Nas?-Tn`^BN|xzN2k%N*GCwK>XI7L(xhU(U z@N?m>8ko$H95sg+!irj5C-RFSnd6L$^|Dmto0cQ~8Yy8d1kFa8hFBP;0ijv5{B~qQ69|Ti4*KoL{3lreP>}%4#vzx3@h*V-B^-eVD2KT>-T?TIJ`X$#@FtuG9`}Pv&I6C} z&OHx2(p!8Uc&rc0df}OS9_!0{z&Ra&*B?C{A|FHspqSpi_!|QE zi-9vL0IxrKsldq%!0U@%H0VtQ&fEaJ{^%_P&WZp$(hFJ^KaaKYmFn1~{y(->?mJ)h z?H9_CN9V05NWz2|ze1Qe*tuMonAO9DiH(4pFkxcRo6F!~VhMbxFwuv_941-uOWZKA zNUl%`ywz$|FSSa_rBbW7c#1tF|0P+gaz|F85L3OCo35&bJBg}M(mZe24{NxzeL8xScKY=6=ZGepd)J0m<%Ggh%%J!~a!5P#hvG{K z!iGb|hCr1H5CM&*N3ow@e3Xu!U50i_9`5Z?k}4TTT@(2{B%}mWLfpuWV$lyP_>7ba z{0fzc-#+#m4Bv6TL8*ilXw$yk)9-tCfjwQY3hcX>AIjQ2d$wSuc6lPtuqzNCVd)5jca%NLycD)#p-@=D3*&}r<4lj1uHVq8njX= zS3?meI20Gg^*Yu8sz*u;fAfdhtT>`Pdxm12^KY0Fi4Yb zKKd7bC|olWiZ}=r(BHD8^z3{@V;dau>8Ji?H(L!gK(h9Ti{-C`fJ2j?2<3E_M@o9m|n1YG>V{kD9^IUiyube!!01>cRHbH3J)*!O!D=W!P(y>0Gm_q@=Vl{#jM1m{skD@L|bQ^);({Tk-P$_A#q^8ope9 z4pd@R6(CjU_ZXlZcnzw+V@nsK%YZ(Hc$7WA)Py1(pv0^ypcT@MlHs?&ds@XM3*TlG zx>_BDy8dIM(11G(-+mnG`G9*FJi3~N_4V;Hu$Z5=3x)r2+qbtwXA+8HNUw`2? zB2t8M8Rb25%RIYM+vje_)>XGKf~Q#0n(8&F^bHEm6^N07F$~Kt%7(c`ngJ7w(IPH7 zvpcXz58ziZ`3IJ)I_y3S0$VZnF);hC2SK!Q!O*Oy`u7dh*nEOjVE3mC)tG)ZmrbAD z19`8tHUChJ!kmhEsVKT=H?jOKG;v0uDA5H3G(Kg3$L2>B+=*YKIBEmDfTl>kf;$eq z;58TSL9fiHXWRmBjRigB(2wMcymoZbH(EWy^Hs^p@;+DVM+rF>kCm+^H3@ymxvU;% zDx^N-9LLm4d*BH<7rZEhHBY>OWt5~U02MPxoaG3}YPzRlpm(>5Lpzm2aySBupKdJf z7dco7Q2ouy4+8IqimS=Pp7bg~=h%7DE5smXE(bDD{n6V6zlAD}K*Udf{3SpFjHeWU z>W^MB>T>yO?Nr1#gr8OrqlC^q^2=%oNBOU3Jt-p>)f5I7&52fYDStY8AD`lB}- za^Wf~%ETtn#0;uG{%!-#y((UR^e}mmex>3l6#Gwa-4(bQ1)%DW9*e@O;s`|i^vB=* zzX`yD_-I5Z0Yp?=MELGKYI6r%zePQK0%>}=Gch!R^dQk6A1)Z`&3#S8ttC+G#X(DO<-yXMiscgMTk@(3Oa#RjKIYt z!gp2VkGwH%^Ps_!F+3tHGBnB%tsf9FP-jA1MjW^>V(Zo@{TYw|cmz-b_y7mz%Kyv0q+42qx3_-RKQDs(SSby>H(hsA^|Oc$$KfL;$>iNq~KTs{y|TR0BEz7Xp3+xDoIMAPw*&U?t!T zAQaF9m7hnLO6;J?p9xxK{JHQgaalj>j z`v7wQe*s(%cowi0@D*SPQZPgpA>9G}4(KJ&OQ0Wyei(W(^knFNg#Jh94bU5)pM-uA zdKC01=rVK}dLHyV=m(%5fF2J$9{O*g{}%dU=!>CuLGOZoG4zX}{{;F^pwEIn3;J8o z--2$3ZioIf^rxY(hQ1p57tp_e9u7Sm`mNA!g`NXF2YLte4(L}wzY6+8&>w=n0Qv&x z|AhWe=)<57gMK&kyP?m3J_Gt|&|iZ-4*EFg+n{fQz8v~;=%=BdhHipxg8l>OKY(5Y zy$Je?&|idpE%a-lKMMU(=ylNRpnnAYBk04S4~PCU=s$yA2E7dWU!ngM`UL0`p#KT_ zpP;XYz8-ov^ls>s3=V)5Fb`k`6ax|gO94heE+7uD5D){H2}lL302lyS02`nZU;#`6 zqySt1Jt%kpnSge{2*3k?3c&jSN?R^4vnIy?cwK@^wS2fO77zm9GI1o}A^}Y_D~m{LtT6h75g34CErnr@(&F| zxkp4qMn*-kI9X&Y7G|wkRfAMDSXDz*#e54?%)>yX<)@}=`KswXvbUGDM|StJo+JA& zI#>3i;fZmQHa_4Oh+`IQtiqPbu?fc_0|8tgkwXfDM2h05ZMdTM%eh!&37p4o$7mCZCeKo!&&x4#On(>DEon5Rgw2E5L0HvgJt*V0~`hKRm+4ls`NyejgLR_v6>u zv1u#vRVU3Au~+)yCI5K!9S|-}k+&2hW2cwmT)0_&0aIRBAEQ`nbx5fMT7Gf%VU=`eQ=w18%buyNtEwko&l^EyT*iKa11v2bjh1a<- zGBvvZOqWiIU>SmSVp&$$QR0!jEV(rMlP)UZ|?A>6o*zn^)m+g&-Dbi7~bE z5>e}I+nGcr?n(N_zooNBIsC{W>Gl`ag~=~;^Gyp} zDM_<$L_X-O_m_>|W1vd>QF`vkmsi~S*0cvb9O~*}*?~^a?4NU0#OZlPxJa#Ah3<~@91EG`^js&oPC2`86K+mVW9|*$HpJOI&~rSb>G=BH zh&Zhof$rhUR_-T5}*^zZm7@qLCjhW=x5r#b+bLJMggYlZSO~|%?yw+gvaMjvB0b?<1 zBb~a(H?m!Kjl$l{1@_%8BZ^nJIJ-AKLl5lUM6Qp3Z3k`PFzkXsaBrObmkBRWCh8Cy1 zRnT@Geov*Vf3eUjI3TyCCMR;P^KO(hTL*X9?OmqEt>EpylHG0FpX(zBXPLG=#)|cC z$iN{^XUq5C6j%Aqvvd7SeeF1%pNt zP<2c{_(T-a_MPBP)Fb8s8`Sr}P|s?_Tp;OQxiH{+&4rV}xxhuRfLzdb9#c}hCosj7 z9RH>ilXP&3|K&Lop{98H_YkRP=josncMT3mZnzQ=WGaMI(?0nxJtSjizml;A-R>G& zjAyr@2=dAT$rNL1D*Qr`ke*%9qF3Pd5#_s18X#okIGAxLQAh^QnWz$8x}&tTl+IYU z0G+yJkc2c5|l(aVU=#PW>`DX4&g8)VnT=uHH1f2;7c=@tHR>|dE~Tf&hR z@2O&JIB802Gy9RFECR*K{4bs?ehv3cO(WQTgX?J zqk99V7p5nE$S5Y!{T_7N8_#g;(7IJv8X`T_ zuj!>3rp9cvQ!${Fw=kuqZ3&a*EljEDiIhRhE5ezz8eWf z=PXMx3P0Aeg*{!f zhfB#jT3aX?ot`ww9pUh_89bjwtoax}rY6q)wsY;OwdEjwg*bA0R(>g&nl`{Lf{cNK zL2_RY4SOOv(4r;x6liA2Jqr^@Pg{)VGwYhY^5EosFqpQsc_$~d)8+`adUk~LbkO&7 z0B;%v&yLVwl3)n?Kfx*wRwl7j{@C*mUDTdKorjK0ZhC3`i9<(~6{TUp_+kOhKOi!f z;E@__Muuw8-=wVDVM*TS^ft3XD#bsm-E+pcCWTc;3y;7~(-Y0CK5$d9l}ef6Y5NRw zJS`}B;z1BaVLS>o9l*YV4bJnqv1Hx1W-NK1{m?oKhHlCju2f!XX^tI@B+TuR0!GX8 zBZ^YkxCxeUsRWbhH{{PnzfKX{w69|WD=ZfrTz0k$-(0oW$adR2eh{L8Yqoc(rRBh> zL(S1cRR{UN=|gaAP8bRnn%;6<#sQ9?z;3H$IP)AqVaBJ(fard&Z0@Xf#zbD&GH^6e z{Bl^!)eIc{10b{TB9O8$>D?5Am7CU0oNs$KC34LPwVp$hj!jnBsJtyUm^wBksP>Lc zsjA88-6RTj6Z5`fla|mvUblnm20SBk-@|M<{9>iQ zG;iZ(v08|uy3Jb?xuz-~?Fz+%PPc}zzBue{Yxa4bV}OvgrJk=s)`m`$cXx#(@92w) zv%`SP7R}0ntGt;@f|KlTdWFFiW!jeI3Ay?ft_-Ra*ZiJ*BAys;wL!jxvHU20r~LY% zFYwOmnn5M<9#L^|Wh)O3Yd_*zjxy2`xboIp$h-VgE*Ix|h1(*XyvKVN9Yj$1F0pue z3mrgavRAS1_uea#EpMjxB(KoatZ>TFw>tIFKf{Ri(U#l9YIDohOU0t|q54qM6Z^aL zrYH7&-PU~DC^|a5HMfS~=Vu|_-!m36Fj0wHFoak=pM{uOCvog8%0d?GG1cIi@q5*D zD5*sQif+A&%dLV+8CMF8?Z;5=aR7^S1!|>Y`nk{aI!s(Qv|yiBsUsi@#Y0gjc~oSa zRE4SqU=u(-A#aXF1g*Dhg+r;r?dCY)!nUTkwBEw@r=9DL-p>9>SvY;78Afy}&ur#Y z1`o#MdOp*yJ*t#=>omt8Ec%Kvd;YoJnHJx$ zG;wk5u%R1T&NZJ4NT2bESSUZ zm6WPPJ!b~2EAaI}Y9Drv#PDfO3{O5}YLE&wK}uq}BK)k2>`Q*hKW#k|v2OA=j4Sz+ z64B|tB2rgFl$xZBHN`M0{*Y&9l;`sZQ|mv$shZ^fpAvl2_myCg%DGBM%5Drph_=8C z2=e+X5I7{TNW0M(71I%)2_6zp@=@u;ND+@L!Hk|;S=~WpH_MwF;gr0iY2S=>B~8bd zndC6fii8k%xcsVMrFAnq%_)lcE_RN}1r5jzRf5WQQ5MUah3wrK>1m5>JEq4w&-VSx z!_lM*LghoP*d_RU`6ZA(G3eVb;3ROy^b$o9cy^gPXMju3bIoAHU~1&N!M@+r_`lHQ z&0?f;W&ne<&M>T-CBJ$2eYw!c%OuW-pRz}m=UQ5Bp`qDupF7+cLn11+@B>8E0L zlFbHsz+BP<}az)2FCuZoP}5 zY^oyTihW&)rL(mc(>WpQrppI0=_$nOz927`T3Q6>9MsUPteTZ_b-z@ME(>hDO2&0ePg@|0d{3H1|GOESc)LrI^#9f&=v&4XfOE6afIS*hF z&$=iwa{}y&X%bA7J{F0^Liu8mu17I(8O9<_g^3dfi^SdmoMPzn7nnGZ4wL@o^ZgJe zW$5!2O#Y!74}?+~q@kkk*aUMQw`soXHD~2iW(A7wKY7hL;4%jL8oiEr#xnusx36c5 zRTX7-96;a*H}L+6$Ek34;K}?X#WV#p? z9HlU3(gkxwhEiNAVLAxL{dDT#QjC)HyKI2V_#l@SxSRm^aqfYQHOTMsOW3Fsm%!^G z%qRc#mmuk9o_;Y^B zZz_&bR4>Xr{}D`?r?!GA4-h!7t28ED^4v;4<$tKIyks4m8v{isHd&nyrzd4jg!DS@ zF$neYu%&+Nk5xxgFUq7D%(JN%&m8aRb*vGr)qlC==O6khf2mR))Qj@qUX*#xEjTy0 zjH1{5oWFpS-!H>(OG{z2Y8V2_!I#HHTh#^T22aQZQ@%h@=AsMh-_E_8Kl4-OE2>l% zfO2p?Q=$gv2G8OJQ>Lud>-OQ7YTm^Aoqoz!sg#HHq8tOVld@P z1dg^)Q8%ya*M7>{<93(yqRb;n!IXK{F_`jjfwKv}WbmUUL#=+w9Jo*o??u@P*I>%S zdr`hj;7}r=dPp}f9)+k>f>MQQxD1qoYu)9&C|}l#GW!j^j`Mq}>EREdOVB7UQ4J$N zIk?u@fEh+dSh5ICIsF`u4&<42u-%3PYHx}q25E8!YU`HEhYIUdpLI8S44SjRPO z_fu|EDPPr#vgkpB+Tc~aC|@lo-;ZC24(Y2+7l9p>AkJFD35rk81?TfMa1G}9>Ry!N z1r7(mGa15lt=ZV zJW^0@Lx?hbj@?yVQ8vE@AIfgPcfM77Ww2HAosW<6iO)<(Wx}X@eM~9~{BQ(p{4#|2 z2!)>>M_oQ!jbcNjb@lkLnN)^vuho}>iTTz1g1BO<478{|u6m8ZYJ6>-H;M7h_4ze* z75KXN(wi&mme($2T%8&fSQd-*ME!lB~iiS>ks&5Z8Qn zb&bY{Vn$9V91_35RaakC8AzeLrg{NVLQfH$>UZtvlyCIX!sxMMReat+R$f}LVk|@P zPu15AAA|h%m&2^;)pe_QkpLeJRKFj}2dl@79G#dr1|R0B zUu;e1XXLFEN4x+KhCv6f#zbO}H~=fugRlxP47*3eF)543w9k%3vJzY&Xu#Ei2XL+6 zeJMmOGk&K%@NW>p@^7&EHw2XUXHowyz#xWyW^BIf66M2hu9Jsw#6JKbFO)9BrJZzK z=-G%1K04h-oi0R&&+h2LbVgmY&a8{kS#^mzhi)E%`{LH()Z$_sL-98Ze=+#G5Puip z?_&JL;_njtp`PKu-x_(Vtr?WCwDA&F3&sN+fGhw%3YcGlpJ~(OM{KtN3Fg_Q_^DiW zp>n_vhgK(Ivp*|8w>3XM*J0mTe_Vdtb}vxnu%|h~1+p1i6EW&}45w$!>|88XaxJ;x z6MH+omKnHr(e#!(O>VT^!=Pp-Tn6sJdbk5W19V*W^G3>MoLTjny^$Wt&=JN0m^&wV z2Ucd+v_D5%Yo!hAp=(^Ae;xJ7lKXP%`I7q*>V=Z~BI?DGdzfcWsOM|bvV&db?5+Wx zJt192d>F4wj}N=?pkspp2mj1Zk*K^ANzBUCzZ8FH#g*JxSoRSP9LUeuw!m}UrA^(g zP$b250Zwap_I3+q{3aX=wV|imj)p5K`Q?i1)r-%yKf3&T4i;fUOyR?|9dT8+cr zUVl*T@Enz%!a8@i%bx2Rsy!eAJrRNUVTpvUG>jOqRviMiP&_Gq8?g8Qt<*IHCBaDO zO-GLVVNQgzC|iC@(#j=Vu?utf2*{=;A5VVE)2(YQ=CkyCfSgq+4n7Wd)b)>H6lC%& zMvQ*SHtfH&U;D-Xj4RKhg}n)7Xgutj6vzcw00Z$>h+Y=gT-t{ZOJMvTNmM_QtJ zhB*aaq%Z>+RfPxwc^>l{(-<%ogLSL%@drc^Vom9Q{MBI|f3N~Mt5rF=p#Q8j`bnO0 zh~F9iLema!n)?*!#?hx5Od;aJwV>6mdY!FPhYcbj@}{$Oln6yAK})mf0J9OHlTQZ|NidaheC2auegh5_*A2D(>H zXTqcuIzpEAx$O2`AF=Uuc@>N#Nd5a3;y5x1R)Nc99G>gZy(kzZ(YF`+agixv!Ajr= z=gaW>7{Ko`0k)+y$q{?MzBOkHT64Cb+H*c)+*@D0 zV4)b7D_@#ZzF2R3@l!TqY< z--LS_o;!NrIrvSu9^=$sVLZ879aC!bFn;Lu0?r(GUdHvO0M*}%66=7sS;b|A>+8jf zX>h;iJn4M^yf4o|uLJbL&_z5Cpkf{DkH0S9e4*m?#~&ASLeV=8XAcQQy#DB24V<(9 zyuQ-Q<(W+2%v13=a_Enq3pkDEpvSNGY*ukVN~r$mJ%Dw(KLV)wOK%)j+@1x_-#P1t zDgp?4J?aY=#lGO&JV5pJ-ZmxcV9v$^R9|>pfV%2D@VFp2@jUQifj8?s@JMg@dEl`g zw4MhZ<9+Bn@NB?qKMy=ELH_eR@K~>Kw>wDnmCvjymz)P4t4ZQ{;E}(q^T1<$nR6a^ zjMsG@cw9hj?h7yAIW(Y%KK}vW{ZYm3uiobZ_t_rw`fEp_=+IK>(G;-#2}EhtEP#{pVh? zRL4L3?9sPhUYWd4($;PDs)a8gBk~ti^b;fxBEA00}C;kS21NI~E z#{kFyburv`(w~Sz}O7Ph5ZD=V_;~U2CzsM7~e;D ztSlQ{0F+0>UW6Y2b0q)*G~!|C#BT&-!G09sNe@F(BLs28J(4B71m-n>@vy&+^gs|9 zYXE3a5!<0h18xK4!~PkKNIFvfa_p?8SxK+c@Y2=JmPWa%+D6UWY|ANcno%prGTN5 z14$VYjyh{x1{e$fKO=q<%uWE7?js(7&iuXwkPZ6>2#;!KoC`pQ8gVb;uYh?S;0D;= zM*I+*###XSl!#}b4+Lxm6vF@*aso~9<}^$h8=A?VkhX6-*UiZu>S%&8i;Wt zARYGi;7@*T1fXMx_@P?ht6{$y_CG);zh1y3*grvdmgjT;me7nLI;H&G zu#bWNezp9oV7~(P-#}-6H325VehlGR{urbh(IH0sSS|mxuwM`Rn`-$lfgNL)h^L^l zKD7c0VE-K9S^lguLy-P$07QOlosIs*1zK_|WkkO})g5T4~f3xIr%xJxbn z)v()Pe^o92#jvAZM?3+Y^+^Wg!F~$inVuPdVFBg89QJYWe?cw(1+ZTQ`|qJMzFPq~ zuz!f~%+E3a+HJ&7)$(5t`vlnEQOmy$cJy@-&p~H>`T?K__OI3Q@2~y0fj-NB9>5Cx zpF@`b8vqX2--SQReF)p*gFxP^kxHMVgHd@{%c?#5BnQx`Paan0Q-~BqXD-8@?k%N@GQ^% z+W&5~{O1Gba^U|GdI(?>AOrTlBRtFFCcs6o->H`WD%h`s{S~$R7r}lF?Eed$`Pl-P z4Ew(jp5@1IiI_&SmpZweixDfU`dbIz;YWY{g|7!UE z5jy$x0w%$J65&~%{k8uCYWY_I=L+Ee7CQ5*2`~}%E`(?K&jDNl`%l#JUkm&7u)n32 z{}R|o!u~Y$0f1IO0qkEOJj=ho_TQnFe+6(x0RJKA#Pv;1cPE{6SXwftAZ zZioFfwfq;u9uNCA=urR}kO%u|glBsCYyU5*<-Y(pR{{S~=#1}HKo0C5Aw2U_YyUq} z%U^5%e^txB4mj5W|4-0OfFA&gVDFa9p*m?;s7^N|bdYp$sLnhn6t5tK>I@fzrsMNU zI)^z_FU5rFLM)+|NwJ|i>)_A`>7r1bacJm9$pO~QSZ5m+x)I?oWcZjtq2UZ4c0p)4 z!_PB^8W>)02~A@7#KEBh7(RMvXqysVY^{JDv0V~|4I93+WRRjUfF6Lwq=6WanZ#8F z-rH~$$QiNrHdnSc7azm4cqbdZlVdtE#OjvU=*=~FbECbvR&Q>cH#fnXo9N9=_2!Om zZB7KI9S(~Gx#i8R@#YqLbMupTv~S0H1M}@%Yx1NYB^S=%T3k4Scd46cg$6yQ8f`8 z#GO!jRfp(QVvC-U+->hLH9}5G8&Z=@O%KE1S!1){3$^#b$Wz+U_S2@uW?0hJS-tCG z+>ssGR@fx(y12A;Hg|YOwvARfJ8og(6+Ag#++AwLy(_#bVVt`i_rbc$+PO4qf6<#A zyEfdr!g%_Pu0islw$BY2o->KwV&hu9=Uo%;?+o*tF|8k5>dm!zSEL*zRh+w@Th?9- z;-G57QCRP~*tsGb%i6bpE@-3Pt4pnraCl*hi>~+Mmsx57pd`dE7yeKzP?rEiX7kd5 z5zD`Z;wg(v+G$&J`(PDE2@N?bl$Lo+Z8%C7@|=Y{4ebFMdNgV?8ACf!%>djN!!H^D zOjL|GP+bj+dPX=}o)e2(J}2bN6c&j)PR_Hby9jbY95QuE_jDy!y_qTQNZ-PAd)n$a z_Yfef8x`KwiQd%--jX}~be$nI!)bxQola$8$x$jM*Idp+;!Pd*3) z5bDTGBvanJ1gv_u$LA&5_hNI#vMfv%x?GZopdg_C9EH{y5`O~W_bcIn7T@N=x5Y_a z-YXx9KcUc9{L8$ViE?J#TyJIq_u1Oz)wJr*$gkNCf>G2RC2F}O!G5qIRDZ}@k^qK? zN{+bnM5U9$n45U%P%SqD-otO&QDSPm^#WA9nXyf8nHty7m>b=+&(wG`jGk1<9VO=) zU~ej?-5%u*>(HY!CYD@mo-QvQUn(cgkXIPwOg^O_Cr5eC#B!5F>^`9pV1vPotF+_c zmWX|!6!NfakW%|_u9uJDqw-k0Z4mDun`dm==Z;e1=;YFx=PPqV+?J+pQ{yh!Oiv7z zpFjLwk!QCNL@oNA+3*)pV6&_KjZ>M%5ZA=(heK4mZ%95qefo6K0KAzoi$YovId(`= zhT~_9Ea$}(E62p)>Dd*7+c)M8J@ZQ5-T5UdubgRZ+R>3I^2`<9;YdU~=>~lrzMxJl zG)B4Yif$O&ju_iIjrz9am!2FB>*R zY;BzeIAH-+E5!yS&2p6Q$ zn;zXq%8_JjnSrCL<;<9=zS~47wB#L35mS$W74p!0YPZ3)jI4}QHmpVcM_mlaiGKO< zW;$HR6iXi*oGtGa4)A$(QG($e>7wd)=qZd9j?|i;=RhxnH=Q8cgidK8s(XnQ7yNSN zsb(Buz%Hfhdbz|Zud>Ju4tZ)!{MW51Y4%T+8RB2V#Q}JuSBz1mVW2FG#TKfCesYQV z)SeL6B`DKa7Fem$Tu}?-kYjX3;mIYA_%r&C;}0=6gvcpz$axM5tUJ+VbYwcfz0{#+ z*C7&NG&SB2GxO60gyeln{+gb!B&9P^BK6=t!8KBzf`_t1LM}%%_9@neix7D#`9of% zVsAE~*)XU(Q|zk3CxI0odaV7$`bR}%A+8HWBSmSKD#abZIS|RZ5>R8`)btL9`T>Q2 z2~t2Z!eJ4V&8Eg5tI7Bs0wnM2I{~(!1jPME5^zay0>rqcLvPeL4{;UwWX~rU)}OOR z$83C;pJK-VGDz4=McCxyLdsE6yM`iP+Rj9H-qm3giHfHVFc;xT;YE@nFCi-x0jXA= z4n2nTQs+QWqPP*_u&f`Jgven9tAB&SW#hYeN>yrm&#d2{{8Ed{Hn{Cw$h;W+etjDX zG+&9v->NYkL%E55bvt^`K&GZCOl2enF@@n{aj2>B5Rm0O^uMkc`FYQ~;fIgLcXsG0 zZP{8or@`CvmA=6y`o{-h>nk_)g6+R>xS~6B)SG7z1D68N8U6AGwcBkw8q%Rh$^}_G z6xaDVa)yqX`EW!tQU++5#fnV~&^q+!IeY>3sR8sHsF68Rc^r-b9Ylv7(=C$K{I}9y zOBafO?hWzczyjLm%kb?hJpxTFii7gr(=RC%1XA9F=x}s_#KOr92 z)J=`QfLO4E_FQe_K!E=1z#xs1)(pyr=1e1a{^)C+i*?tzOE?kF(4dBk^OX(U?mGPFq|z}SpWA{4<~-Dc{N_0H#5KWjuRLV zOl{4aRy?Hx<9sxpA+4E9i`6#GksHQzO*_zf%;JoTZ-|nFIYmI_>%0thUk;#aM-I%B zODgq;(!h&nFk+GOrfDaY^71E-I4DQoZhGPs`zxppj%DLnSm~gl78Z~>3f1rQ2g#-s z4-CihM%d-Mz=s3%)9Lx#+%VPj#Pjw}Rejz%V5(- zhT@!Bo|4H(FfzI`7X|KK2%4=^LhQ!`*?75|gtzudSV7ZhzowE!i(rjuoDXU^-j-Jj zLJ2}n;JO}KEL-zK$TOs15b^|7Jk~wAb+X>xi4h797$H8JKR*BX9IVG?3q(<$(f1!d z`X_$-ip0YOaeY@->*R1yx|&pYw6<4!P^kbZfXW$_%6d;*RNK+;_|JJn4m?WwkL1;r zsA2lm^Yn-8uZfi1dJjB=97W$Qcgw4pldG3P&za<1z0mz38>w6}PtL27ObPFmdaIVR7)IXL&bFQlVd@n`5%KClH(gRx6n=;#IKF6 zm(i`HhHapv*w+GP7EeKy?GV#oIkU336*Xb%qL8CZvOhu|TMHWPUrk~tTt!}cy2I)h zY=p$((b@VrLJLVfM$> z1cvP~Bi5C!X{hz704HcE*^h!2o-Ag)-FU;Z${JJ{sF@8P5P zL7P_CYUHV3G-#aC?9dNGiaM8LDsXD2)df4cA*pkLusecBLHTg>yl3*3vOjj@o{3g3Ee{*|_mbZYfB_huO{_$Eto&%2Lu|vc8bwO@WA7L z*_$W@%hJiq5(R`66t#dRX$8d2?Ys*pOD&)*wSZV-MB~j%h~JMYpO}`HwJd0mJQCzP z^g|gh&X00Pv!0xxmE)Vyd080kjE~=swJGsZO6)Q-Eh+kvIJSfMLwL`tBqjck9&1;y zvt4l>#0HkS>_T}z)*msQB_Rj>5QZy2d>S!e7=@V`#S4PKRN~NHm<7RvmO=Q9YbKQh z&b{IoO9o#vf5ZKE*9}jw^V*09^w>hb;?2=`ze&U zcS*YkBTb^`??GjX8AMhZKmhBS z=r$LRcMtT~W7a02!%4KKo3S*C;-E!aT{d98H>5+)xiQypxje4$=K@}-K`u1od7Sa+ zQ4{5CWBf6^T7a4MZvAWCY@-+N7UadsnMVDKh$=7EH3oMFl2EWsJ7%~B$=T6ZYKZSp zm!-N)aw!&aV&Y#@S8Fh@lj35;bqA((@6~5QN#92?6lnRrwnQ${q)xzyvn5u+n z0;WHlB!)@1`b@iEDubIvdIzSt!k4qQS;906(`Loj4HNbR5w;1YX~Og)pXtv&y!T+5 zB774ORRK&EsU0kFsvRcXgsDl6Fuey;rZDlNl1h4Sgh@%;A7Hv(_*&3SrwP+`m`1^5 zkuFDHql8F?NeS^FOt%TVhhf?vOpm~XeRstB7)+~$>2a7=3Db6%RtnQIFs%@#9WX5y zrd=>C6Q;c|)eF;~VY*qE4#Kolm|ljdPMBVY$tg^4!!%!*j=)qdOn-xEo-iGSX{IoJ z08^nboq&mLB24-erd(nA45ln$`VuCGF!6bh3BqK63H#{?fnz%2sk1OC8m6(r%?#5R zVY0xKB1|zbEfJgwyODqL3OnyIy7VO7Oq$?wcdnLfv5 zxFlI=<;~Ob+KMWxtFF%KEU&lDFBd_2`0^qq2q~^L)vl`g@|tV4SOWbtdJR_G0`-N! z)l!Y8`l_W><$j-FT1qIgvZTCrr52>F-p^*k$|dvbY8rf$$(V{49Hnw8)GF?}Y6!ki zimSMuiu{uEE4*2PQe%q_QQ!SahMDhvxopO!Q|QvOxl5cR7uqmx zzD9OHM!O=Ft5dH$} za+%m)Yo{^OsJ!jZDp5|>>m zb^~+FGme5PW`OJ!&G1n=Mx|G5N0(|pihadpSH_>v|4ZK6W9Jg+*s|=%j3(=1=khE0 zd9l=`|ID{4kM2DIWc^4Qqm)yMY$@`Y*lH9R1cUT9{y^!a5Q<-XFH75f1hbbaTlB+D zIk0QT!5|I;SUb`ai5RrepFkHVbQwb3i(l+LW6xPO@xtV?Ogs_Q?Kxv;NNuqsdd`Gg z{MN?zb;uvn6UR2TcLUqr<<_Tn4QhPJWxz^Qg!py@My_1Ui{^F7_Bpe>CYBDqSf?mt zh~W6=uxi`O{P4gL*s;yb-O^WRoQQ0n@h5a3l6zp<>hTQ`WplQRzP;UJzogVPQ_dVO zm!yi-j>GT8x8XoUM~9w!*xr&dDm)al~7-Y9ZKT-TL?yOCh1Y{nP;*R%uy>Mdl07If^WfTrk7zt*8?}IQ{tC( zUn$>T!R|YP5v!E%1)kIa?g4V{c^;+MlEVIr+;c^Rdn&pOn8s%gDpZB-bhJ z`|HQG-jQ$xP0L5dAK2JQSKQNUy{(ldZ$Z9XQXGGH<1yj>Io$75+>5co6X4#o!{<|j zO)qfRkfKezKa=+do(S+xOu=Z<;$0XE7Fk|kl!s!J4S$}YroxS8QGp+WxsS)HzK2_L zHRZ0VQ57Pxpr3!=t+}Uz;-Mw*hLj$5y^eRJsQ&zEV!#;M0GAE$5jetMi1Hwp>x8?8 z)B8r;9MwPlqF?V&&YaVMLq4kWzY!Nm8KYM4JWWu5xV$wEtwAk7F(jo&nAG#G9VJ2V zT|0gt54jO=i;vl$*LCn0kQl$W)K9qqE>uQAxolO1laF91igCdOFHY2{W!p1$w1OV7 z^D}V_DWY2T!Yiaqh-OAqXiBnD7%BFfBG7XjDu>6 zqTwK#6{!wPUVT#|4{Aorx+P;s`op$E4ydWH967IXMYDzm5X!%^~wauM;u@Cd0~?(N4A8 zaI2Jwqqseyx=4~$i7Rz1D4#(k>`j^6`gvYj_r6`Df>%OSI>f;p-GJMDEMKL4!63b9 zemmbE>X;geIKiP}L?|s4yEaTZ?GMGb*r|x4){QYpDVk(&o-YKBUS}gZlzs4vXZ&D#*#&!beMa39cv@i1EZ<}YC;r6 zEfjGSI%B}|A|D;J?!+; zB%y{k1i2&v$Lwj16&eu{V~X8Od7rg59%6DQfeAS3RUZ~z0lF6E;Sfn4RbclnVv7ArVBqOaoJRF^tgwo-1 zkD6lvw=FLRUT|;4&+rEKRwD#XE`F&F&c6|n>lBMLk^?EI5t5au2%t=95KOth=h*&6 zOu$8-tbEB&IZdT}MK8)%_M+V1b8Ol~aq5o?KJim7QYrH}wqTy)dQtB0Iku_5q%yAg zakigwxk{POu?3GeAQXD!Mt{$-ogyZn`~9~Y{gjuel;eBx%rpk)bAQjVkq4@;=iXW1 zr@Ts~eE!d|1&%7O1wFk^n_~=q<6w=S^8d%)cfdt;bbT-EN)dEXS4G80gxIj4SWr}! zwjfePz=9ys5dmRWtXLM5<%%Vim}W_0)D&YEyMT%%iDJjDF)A^}SfXg6eE&1|?y@Va z$@4z%_kQ2|`#qz3Id|@vGc#vq&Xjx3x$_0eJ?fMh1MiJ8_h7y5L!@wLp4Rl;KWN=T z;KVF3Wioq$zX|coXG6B|6lY>aA8MCX!xHFhOnVoSl`;XI(F6<3A#l*vE5_g!cY67V zVpN$p$4lVPnndpIF<$Z*XHP#lKIt&j-#6Gxt~>8@@57(ax%XiQf$okT9&%j*g*?z_ zh_8>Ir;mODIw7nVJy`DJ6%yzX?CT43cG~6MM|;-i-Ulak?tO52=-!8p4-GT&l?QkZ z9TGHTXh?l2>HN+RKTxhvC;~z}J*g%_PQodndrw`3bjh@gi%E>lR_bc!EB6ibR(N^( z){|+rdmr%MFw>!O&%nSCg(vu^%M^!}wH)M+Ee#U|%7+XI^z|4LWW1#H*NA7BMcU`WUpYL( z{I9TdCrR<|S-N*mOi9!7>@^N@ll~iytyrnz-ry;2|0j>FXr@FT>(lRF>0>>eu|Z`C zsE;*geQY6?rQt$d>g!`sw6xFm^jEe-f=<@FggIVIQeKbup*?t5WsMam z9l9XUO4^uLh+^Oz74R@z>h(TEyN=VqdH4_Lk&16KI>;~(HrzDxcA9_^_&`~y5HU)evvqaFP9 ze}G5rR{am~ngOplZLjnKUJ6Z0!EyMdUwTME>JN1YQRq2X$VA{^Lc&(2LMo@CFN+|9BAr4?N(7 z;y+$Q{^LdDf5eLjl-$EyF1wXU^DqQ?2OFONfLg6B9BeEG7*5(;Hf~QMmD8d3Yv*=f zsf6l?t-8iy`gnDXbY^1zXnRexp3{x!PW_|b=5(Ws_YJ}Hip$_|19r}ndEXE*XKqDn zl6z}LIBQ099i#P564Hs+!qDo?FsB-$%jjJ%4&m|sJ{nhgvw{~U2(&+GWh0zMG5yi zlz}}Q1|K7M&NbseQfH!UxA{QeP>SMhH?+1c$Yn3Tj#B!O) zKiB60*&2WWZ>@MdC3{Q7?cc2U^NRP#J{qP?&VpTW2SjI~2)9aZg+Y9M?Q$e;;T+X%#K-U>IrM%9s<)`_|W{GmsNgo5#1QI1aV zl7a*Qq+bQq_M6BFe)}EqB>`OfPiGLWpzcWeTgcBI#?$2gL@=ba=M8De^p5vHZ|8JW zT#Yi>lJz5s==3`xPH`pB)mOr_gnA(v9t@RB^ZP^NNidBvL&juK8z^+ixAdz9Kz$o~ z8|$%`%xhq!*bWA_yag^fm1qD9T&PjP-1b&G7~z5wHk{X3d<>iHZwG13Z-+)n=LIxC zR;BosfOMV*fnHHi{wsmargUx*ngHAwD3q55gC`2zlC?pkUK_v)4KKX41;!wt&Q1eC ze4GseVhCc`K-dp7*r&W{pi3o$kuIz)b(XfUv*lnmT~^q@ ztR=#yft4ihZYDYFC!HyzV3^38>5_deEOV!2MyA455bZ4Q;m6x0*4Hb;@YbGeEn(2; zl}wn@yc1YnVL;g+|DnURZhM9X_&JnvlG)N7-@|aw+p*K61Y(>KW_2X0=*Q9>rjQsn zv=RfI4onc2c%t*5S81($i8Ex;<`uw67U?p``J5F3Mm`u)iEtg2JyE*jFSm!;zN}l- zH&Uc|8*wyNe=E5?q;aHcq&-{(=aoz%5nrBg>;m?BWg^1qA=yybXuOiEHse@Bnoj~% zy5msMWK$5p_{k1M?)8sTX`VBmyCW!~>P<*k*7g(1njU!QN+QeJ%Bpx2a`_%I$KXQV z(!5oa^Gj;X z^H!n<)Xxvlma+6&wqzB9CE&*{W*dZD%~`JE`^d%|*#y9vndXW58Qc<sk-jH%h++8NqJ& zwV8AdbxM@LZuSeZ9)|3odrUaU-(C|!HeoW2pAEhZlPN(oWKmb%s0)_;;|FG&bEn7# zuq&i^?-2fLx@2$Fg3PrrWso-`n2}+KLkF5SE4E`z2TE0rRG&H=X-u(0heIGh1_ub* zvi=Si^oR4L*thndKX9H+<(BRkz>56CnY&u4Auj)C@?uRMG?0&j73*P)T#CQ2Ha&`Q z!kuD53>9+}pFDE|#kcWuC_z`Jk8F@|k?wd6cOkGwCh>Mwd;#{yB;b^bSbwj7UF4%H zZ@m(Z8M->Max->-pbav=#hrwp!`OE007K}Z0hm%Hu*KHpnNtKF*w83+dPseq?x+Tc z5X$QGFpo(IvQQ2Nr(iXqdJo10zJzA|LN9rNIi>RT z!~9AHmv(}&=1}0QuQhTWNVjry#X4=>9#7Oaq#7?jWd@{z;w`hlyFf)|Z0%?u3dvGe z<~H6>ClU5@)BISopVX>a>sdjgp}-C5$3sUDLv&M8h;~XkE3{b5TN-RBKdZg9gJ~_S zDKj=9h3NO-oHf+3j{WN$3sm$wmUM0oXfSUL#@F3HV_>7QDDJ<}ze4_n{^j&=J)8RK z6F=RlF#K4driU5zKWKdiO7vfC{aO?2+SW%WAKDe&&Ccy;n_~_qol5$9c~2rUXTzm` z)hy!f$GFha&aQUN92tUk?Svu)gw$O#e@p0Iu;?ZuSA5~e?PRtUQ0HeyZo3mz+)E_Nuws{hD-c^5dGCePk7Y#I$Ue z#Xu@YYb?0KWNK<(hB=Sv`t2iQmHU@yC_}Ql9o+}^iL#Hw3t=g&zeAAPkL?QhMZR(~ zkN?#^nyv4DF6?-T;NMxSnwglHnwg2s_#kOe4}LbX4#dxl*&hZls3FSZ&!EnLXuoVG z>IVo~x_~kP`7nq+qvgRv5RusC;;F9=nhR(U;$)%~fCjRsyRdZN<4ypA9wJiQ1k{&7 z&vj5&tgd*x!GP%Hl9^~NAX0^riLL_b&f<Zt8ha`; zxXw}$%z8TgnU2LUh(#ZGPW`o3scs9`gQc^>e3H zF|Qa-xf>dkOh60;GQlxa@Pv4HgR(Ib9O`~Fj+c&HUtC+SsYDimH^G5oc+dV20L;-h zV#Q?k0bOX3C{F0SLJWkHi!MgLb+GeAd9-ia4NWNKQAP-aW2kxzk%d&GNI=2RV4{SN zgqhBpsc?pZRHQCI!O$4u5g!SE&~K)KP(&(6;klvFKqnJEnsBHUU>z>RkmTc4>3e}c zVdzmbl+hM?${G-|dbKb#p`aOp0^u0e9c)A@I+dhgXhN}CNJTh?sc7D*t-GNK#W^7r z;TWbOxl^mCZfN>o%~zPsZ9FI!VzhPd>Dsdo|KZuXb#KBbx5br$p;<$)K!SN~!x-d6i!nYghSLi(vtCRum)_{l zG^f?#xS*ADk&iY8ILM1;&)OJLZ(pj5(N{um#%e*_Mm8+eHBF;skC?u0!$QBfzb@Be zZxw1P6WLP>>M5W!XQ}il%a{st8B)|$VfKV}#($d{GZ7c{a@JMvj_f^0o#JdCM%YQ&`H*k*s4ZR3tL{3h-(A7Z+7=nB?<(MY_c!$D zU}P6?UjGAn9l)Hv#2^G?^`)1aa^OS@`vr(rzI=L1aY|3^UaH+wPy|AKdefB8;W~IW za{Xl&rKMqe1bF8KTw~>P0NxGYF#nl=3C|e+8o}7JtzhtJjGhk$L`UGHk-{?q4Npez zjrtPXT4?tXgosdIeQBfVR3Dz+GLzC$eR~4WL%=mwK5EvXz=_erGgjXe;7rlOtFQkJ z06jHu_6c~p@%u)7Y5u(|-~eR7n7;N;zmV)%6Hiw?_}_!pr!Y(>bp;7D+@S!iyIK-oe`&+kdUs- zwvSDZw}&~FG9^7JJ1RXcHa$HyJ3ArDQM6*hEFZ-a0!ZaqwR zjS2l1-3OyOBONt}jQRK@k-Z3JfoI--4__B=487ilc zb3xuALaBH^Pbd=3`W56*GD2Ri7)Whc=x+@I&r0l-Ei?*zPDkObF{=rZaAt)Ta*dgE zM@bn?WF*97qHeg_G6)wDt!VWF2}C*>{XLS)m8fe>v*Y2x(vmYnF$!%8n!HiAlkk(~ zy_*LLl8o20;@Yb}*HjB|HMnso!X0u$| zN%Jd^`K-w%oHU=R&jm@;C9l;7O~W)n5{((7%vJLl)L3vArTNQ&^{niMG`|SI0UAVt zIt@b#R#iVMlPDea6XHuf;%caulm~<94S8DCHL8ct$}E(P*)8H5s1fz}S(%NpxjsF; zC#K3q2TYNjHXkl%Ah`k^t-kpxMib;3T{b!f{e@nTM3(^?L2VRWMnaHp12;f?8!Q7v zJeP?`rICk9bkL7F=$sCsJbAq5I*5E?@p1Hugop4@MEeUqkR<2rnaoA_S{Ytfnlq14 z_^6m71U0kNww#3bhxbmQB5Gic%7TAOf4||tER_`x!(kX#jgE;#t#yfT(}?G$Yg?sQ zeX@pAxaJ?6VM>_ZZ;4l1nxyz)(L>Y4x z$#ZrR?)emRbr5wEK5mr`0wDT|E-dhDqSXTiB)rh!ZGh*jDN$Lfff(cxbO)u2dP-W2 z3SWdt_K)PIxN1U^;rF%1M7p$8M;~( zRjYgZAk8brEy*Hj{zgFL8PJ9tpV{WuXu4~1CCZt?D@7)#9REg8sr)qx8%`0=oZu#l zOEmx$HsYhHq6ke;GHW7?D=s1)zVCvPH4#9B&u3D(giLV-3WhBcLyPWfMINUJhz#dj znua8KzYXBZW5zg@=tQ1B3eJl>6(ASF|Y` z?}$$si;D6bt??%$6nbzL$@FyCkvvB!{%WIKB%+qBKvQBg| zRCSyxsk_urcZp6`S*WZ3REagYuJG;GP@U^)0{@Da?>E>(Ly8FjY2Gx*L2yZ$mj!^E z;h#<-4;cqhM{AgGHs_V37-P zbvdSf2?)Cm*3jr@l-jVYN3Pdbr1kHi0Q93=kb7a0$7*`qs!QOuv4n!jeevE2;-vV zd=Vi`1#mQrh%RdbQhaCX4v4BGV~PYkM8lnC6`lb;fGB8R9FwfU@a3W~;apZVp|M{s zB881LHh2Qhu3nf!G5oAGCMYDO#Biyu30DbU|Fh9~L+9?@7jxrn;o{P4)(jl`NXd!l z4bxo~NaJ*r!`J5CnB%>M7lphbd`h`f++mVQI%!li+(xX+0`r4ch{|$}El9#wc^MZr zTo7IjJqwupdKSq|3khCS=xgGecTiQGxQ0rcs4*{WMADBtTo7yuHQbs)8+qPo)eGP{ zm2i)M9}N6ss_Hj9(|U!FOY}10TrPfQOq~LC1JnmsezqS3Xexd(Q53E`-ULAWY`+@N z6#QhO?{MXxUIH{3KQqx!I%t4BKm*~9ss_Xslh2|M~xb=xk&x%h%lNw!d)&yAD2F`60iQD#_dF;CJJ}e(!7@764|&& z@i!t>$#*yyLrC17Nb|^neppzThRj$THPM|k(cYSOG|_&VXlqTh4J5rLTCRzPKpv=x zj)z#*q^B_gB#yitCqvd~qC+&%BdFECaHP_ql?R-_oKq^-j$4TvEM106^UClP#Y=-n zS`&`~Q_lfqs%Hh!QJb?|r7CejP*kD$z#OGyV5~}VL=lyPJLl=v1N+akknX>ye&Bq+ z&%i`{+!lIlRR8-O2PX4()Ccaj8aRx<6Vsg)rd1g-fWD#3cR-oa8by_1;!k!fRV~5# z6Hx=O2K7O-O{!}$l88c5Em9w)T7>hGmFO(S28sGPi_Ewe)(;$o2&}RlS-OA8%wxKgfzcrH|5%Sf2AZ#!@@O0SsZ4v~S?!Ji+m0xHA)l0D2z~#swfD1t990GSOUJToE8X#Ycb^ zv!`1CwPMf-K#Lf32GBwVy#TZTkeR3k5LHnoYK^vihd~a23K{fXT-|>nw)@9pXlwzI zq_wH270Ei020wnNrPk0Q$VOn8MHxwVddiP2{z~ci@Dcvd*m9;NfNTD<8Rl@!tv=*j z7J-Ez7LW*hJAtMj8qr4hh9ugXp;1LY$IpzZ1g!?dZ#DQF2PVc3crSi1V)b!sVQg_b~0zhroFd)A&eKGA>YF?!yilXfH3#A4#Obz2RG$3ycR%E<9O$R0A*& zA67~gg=@lvT}C(@RLA3UGU3VmQ>O|n8?g*TVS%Fx=fY8?0H^cX4`br%#~PmiNGk3y zD}tL(fGR?OwSRmtAxiVFqR_naYCRX}I2J*2j>p(T)uM{>--hB@lm8HNYt?EzD)(Va ziK?Xx4dsO46e(8bADq+=F10xf^jae&-arYl;b;)jWwsMv6#wpY3R;+BtTif;Cfr7Y zc;fyfTW~8Bp8yMEH2__d3V4Aw)SBVoQL@u(@dbQ%q(&1Sk4D6*hUYEzQ=_BDl%Zg> zoUFqdB4iC?1hAwzH^Ei?>J<(tUe%~9kO~V(G(M$wDj8G8-||c8F=e|^L4GWs1w>P~ zOwS=)ZH7Q9BK1D0^W1ikPKztksi0CAjf>=cR zIJ~jM&s-FW`Ghu4-j3$An={%tnbXEeJd$<+Bg+~K`1~O6fIDQTTP@M%*j%vm%*R^e zH&{rpU2^UKT0+VA)ktuDO|EUKNd(^l;2O)N&`dF~q3S2M-;S7xM$<=GW}3xBLk|{y zvuPO8%9IMqXB-ZQf>=-%+zME?T9oFIIuWX411Iy+JYpAiIarm!$P%!+8pAyZ0L=!G zs`2^9SlLu!r|9_n%QMVJ^Xq+fD5ApLAlGhxt1;1|SLAvtuk4~dtINSBU*})Wbtonj zw~IJQq0hH_*B&=w*}ui&QZ}r{vVRX*KX&9)aCsrYFwWwELroWOfP&#^A$hxm}?7%U7%#6)Q)@{PZg( zT_DFGaH>W#RiYeJH`*kPLSlX@Bk9cViYoz8d&xw9;X0f_w#bFYBMq|JcBMmi3flA6 zV!*Q4kV~_5rR(+f(vyo`bXV?KseullQakDe((h#)!zO zQ!J7v;wv8Aot>!!e2l)ECyEuDbj8&$2(Qq>D3->g*o5k281yyhXhkMAu@DgUH7%nF zP6({40A@G_F2?DJ*d!KL%7cq2-dW2j8qO4Wy-k8>v&08`;KwB9Wa0BBdNKO1{Td+N z(8;ASz0D+GQtp#`b)QAH%mw@Rgo)q1^e+O1x+hK5br*8MUY{#m@CR-TwO#7X+@*DLH|C~2 zQ^UhI3sRiAP;;z-`TNx3;< z4Jq>)kNT8p6)!e9g)8;6-!I7z@|1DIw&wJ=1t=Si0y?=dq}-xTnQa*kEiH(0{_t&c zbY)IVQ)MS35=#&&b4;Qx0&#EFq7~u{^RlgzS8Ikt83OS&wX+j1apdr}RsaIRX8dA2aLzxzE zwJ!YU&Hae0tru+^DZEpMay!HtQhuinWqXFB?NQ(U+WJ?a%;>2B8R;aHLD!ziC|&1e zafUMCT}Fr2iYE9`u&d&G)O&}G@)tDwC2k(NIRy1d%6y!1z$152e(xqThVjts{~ zpq%!^2?CeO5tB4kCs-Xp*|5y-)uHTIhcYc+p^Xn>B+auYKgLueP{zcQk%dT62cEK? zaz#g$iuxdh+uoD+^1Yw#zN8BR;h@h?(EC0IqeIV1=)wXkvmWJ6h!vYq32Fn4D+(w0 zKkSH&kGmzr&>zFPcSek1-{?@M?$j&9Cd7Zr@5Ro`-|!G_MCc|gbkUW$T8N>RH_VG9 zpf}YEMr=ao2_#_;UEL(C0nmam8JP*`M7%2~(_E=cNK2!83Y1q&VrCW`zX~Jl zO^$T~R_)m7xZ&kp;sqZ}P58fr13EE@@!Gt!lxy$#7{U(}Qq{)L@eCi{%)L9J#U^IL z(@&=bA}ej~~&Ew+-9E zxejHL)nbzYbj9!Mr&oM+ly&^+#VE&Qzm4-)On{DdEo$|L`Q_TWlkEZp!ZEBnt+@+ulbO>Xo>oMB#l>g3gr;gB4l9K6*v z!*qEiB?z;5zdDpj${AAbSBG+chC}-vqAYa@tX(64GC!O5uS1!&3w!%YsVMZXL)i_n zViVdaQO~>K{0c*mu)!bQwC7fb@<5hKzt_3dp-e~hVw0x061}@;9u?{+>xSi^I+W?` z&5#>|7-e#iK_h%ZY*GqbIaBGBnXy^16S76xMPP_<3y#E$n}S6lmS^}zV+`-`TIc?m z`H~jajSNnjs!C_=1FAwNjft6*ovwxBGh+DF2A*dz-|#wGg17mksqrb~>sf1((JLS@ z(AU??!(Z<1;@(GaWsQYAKMx3I5zbygAwixVeqM3`VJdA7xGiDwFb~S#22_B+zJ`>@%8re@KOYN%6q!^?&aRw#lVku zKOfJap+O4&AQZwoFfkq#MPcG`6U^iF=q(rw2nGc@Z`#Hz40`wK)sNwlr{iwS!k{H& zeE~WI1^q2B-P1H+XHJk_sK>%!4<7ryfmfe}!4BYwA%WN{G{7{8%SG}!76$Yw+_qRW zI1&N^b#7yteBFUFSP!p0O+#8*_z5^fkAg9J6M#44Z|Kp`qz~EZ2V?Z;T8c2(D(#6&1e^fKuZ{7^g05kpMYnqe2bCZ z130GzyasQfC&8{xh93oE^bX?LI|2^jQ7~4%Yry;MZ|F5bM%BP+V8_#5rGQOM0JFsWn{GK`$Kq$kR8e}EX-lDoyPcq}~IlU4;=cc&| zpNrOgESf%cJamL+e41u_6r2dbW6zlz(jERLE+r0L!*S#W zO68|jT9r`{3!nUM2AF@GQX4X6$jsL|e-0!eBe)gFAI$OVrDv`nlu z1@rNk-ZN?z%_0aoGMa)#fHWb~4am}pi~>m_3J&;zEc9oKJl#v~nHBk)msE+xrA6K* zR-h+go=%2P6`HH3I7?Mh^^_2)%2KE3RYp5&l7c)dX@N#T%L|gD^folpf~$z+Cd*2G zu_%xY=0aqM@zjLK3aoo^elm|3jh`&Kj1mfhoF$`sI_fKs z$6`jS%s4-^s12Vx4KhBkG0Kh&@D>?L)}*o_%?pGK;8b=rKs*U#FLou;g?(_7e@r^R z8%6q%bJM)m0M#>~U1!BqDWv(9^h_Zc^bvTYvc$*7rTNb=zd%tS|Fp_x4bAKtAKPg5 zG4L_a-0Ol5$%jQkship|sM8)|sWksA{`8NwmFD*Vpr_EF@p0yYWSqj{h{U2Dr;u?G z78s3kjY4)rV#9H{GA_u%SA#$0K(GKKp}6mf*RTLy@}?0;Q6Opg1}0w8$vg?E6puj( zW)?CJ4KgYLJy1f8C@Uc!5v87+hl2X5t1T(FllaVd+5P7IR~8_029%$sOI!}#Z%|C^ zWf?YkgP>K7LWZ}^6Y;$29>ygX;>h`R%|8v*`PawQw`{=Wr6sSAIh-)9U?Yp&sc%}) zt@fe%ro^;D?TWHmNS7TnJyjr+Qo$nZ1RfL)lW^q)GRB1?{1v=L%OQ1KDE9}8T5qRlCy!-?gF36diOAVo} zvM9M}J-dXaG`F%Dj(nS;aayaZ&1RT0HKF@9Fj=TJlP)V2pW#a3<@sRA4Ku5woFWZ5 ziq*&Lxe}Mt2k7ko`E%}w&}2@>#V79}3f+RxT1j^X_R{LC1v<~ZNiU??bG@ERlZKD8 zI#=Q&%|FMIVr)`V<{hLv;)OjJ!JHPmoyyLJJ&r==2EDz0#DJ+?p<`eNg&bR_5@-fk zz(L|0jL>QWu|(WaWiLuL4DDxMC>y{+pFRuA%2n)fN)p%>NG z2VE?bvaxe3=ktKF1M;|Fm4!efvEZ~+!ft>{nto+O9$EsCY z1$%9WVb!240-c>mpTa_1ZqRq2U)&IkK%nwDwKWmi;JkVrWM5+OEMxSQq)3x*g9MP#EY;gHI3y!r&_m z?8%S3RFRyzE;OUn|VKgV<4-`$ftswphM>|2YLXG$h(Vp5Tp&|E~#Nsf5%K$=INpd%fq(QX&@EV%9u z;K!?0x5q~Pr&!g2i-7ThcVfAB$ZO;k6u{+r7X?_pX8yWKA&EQgaN@~V`s|SAJ-~7h zb(ZGe2f!(8^AFB!h>A0bLzA8SS-*aR2bfqV)!|zFua$6eCCC7 zxC>#Bq_tpTHrxVY7BLuT{0vwaZdoh+b#xo*)3wsl#bk8fxDeA;jjEB`;Q2+30(K;_ zn9(i=^N&SKm$LRIEzA7ZFhz(NEp!Fe5tz8o=i*C116WzCu-@s_-`LzL~*HKUcS z)ip_2%+^d)+RUz@0id*qVaAP6W0S+MO=$&**eRqY!V#l|W_=HDio|LxWS9_%2|`X5 zjaKmehwl*Zm?Rsaa9SsML?`&VW+*NPkt2wdST-yg_KH1?O+WWm`C%6#u9hiUlwg znyaYzrAQJ|BnuK(Xw+XIMzdrEu0`slC{__yV2SIJ={T>B(Wq^$@R)O?>k?;Nc>&HV z5<`QLgcg1813I*<0mqar0B=1&hu;X%$tVR=ktyq{3c%RMcuB&!du~xuDi{tlg-ld6W(e8NGMrB?J|aALRfc&E))BsbNYiFmf<`ih&Ahm=JUIjo4JI}0$TM4G}`xZ(y^+|c$E zH;^{Cp?#@z=PZZ?FxqpvCM!*o6{X2i7PEv|$(k&`XpQG&jpx|WRls3fmEx}%Q%vKb z(YWWKWF1rlC=@@w1?X&$5030l2(GAHkSo@vVTE=~5#PE{)>&L4{$aqG$f9DL#$bc> zKF|t7O$LORNb~0c#!^9DVpRC2r+e zpE#8_pdw&yo{n9J5}$rZ&zxixGlnY}UB*}gBakwx%0apyn24CEE7P`yWf*N!p(NiG zA7_DO3><0W%7rVrF#};H;B<)#?^?9fhR$Q0D&3A}WpFcG1-R(LVj%G=mj$&JIEGSXaP*p`{0lyc?JdHdS zU*vqSi>Kp+7%osrSo!~CsquL-^3_W^`E%i&WCQzAW&-tJru0_2qq&v*G zz!4fBb~F@3M?*ftaX0&=8Tggmn1gkJCyuqS$EKwg8G@0Vq2A1Q1v+M@0CPyz&#Ci3 z&7732tvN62aP`4I2hnOjB9bhT2+Ed_SmnHw7?L?MK|vpPhbWu8WYFV=rlGh%(hN z(+zBV)Q4OG(VX;~x!2y8N`Osn7qI#uiyrSUM`Vemu1Yzny>+q&D_eyB)Meo40YdR8Et1LB( zDe@MXj4Y$Wa_Sl~(QI5}8T205!$YTZ&<#NR@&qU%dgp=&NO~FTTw?)K=VGS$5wHb@ z6K@;zG&{~mIf!*w2Ywd8J^B+L1(Qx`-XEYu-HZN03SNdjYl6pI`?#VjIo!fkz{c`y)n>n<8V~Eb0AE2kk~sBsi^=s3-tgS6>Lm(bt<1- z#TvdOr#DwbG8zZH$|mX;Vr7#^?Hp%uzd0gQ&1hC?9LfE`Mkz|H@fpkcj70&tWvelJ zO6Pc?`rLM!PYaJGB7;OHpUhcRVw5R@TSgNsx1A8_tdFJelRxx|{h zW#nu-agfNQXg&k8t))8;N_Wgc`9${{Np~JCse%c}Y+^UC^J%{3ma&(Ls4ICeVRF*~VhY;Q9m7nhO^3UbI+Wo4{s>;&6-q3)BI0FYxdf9LS46Di*;pWHSd-6KzT*^e zYbl5o@qf5{#sJI@kyi8%30WfK&a;*!wB+m6_>CP6rKi2gaZt1 zcTCgxM3I=TPZZH{>pwqiW#_E4I$@`-dIzrB<5niJ+1}_DR#CdK{zeIL0)@Te($ZmI zW<3Sf4e~%y?I=frH%2*;&>Q9Lz%_o9?*o*ApGGD8(Vj_rwj{KIIQ_vUa?DWI| zEQH7oki>xlNRl{!D*-<)XapCL#-$JEa!DctX(a;8bsP@EriKZGm$2W#;G4=RdUHW( zxFLbi)t@DYK!`|V!r%c1qtT$u1IPvE8Iv_Z@HH?NU&1@(wtN<%vQx26;)1$59oC78 z5!?b26>cX5Ng>$PVw-fo8A*yJBq^-5;zL44sS3!620882`zfJ`60!tnD1lQ%=IodB z@@o>DK>%$s9!Td*2j}`L#!Ba91Hcl9O0b;u|CKZ%il$qGbD5M`&W6`q%D^8V7c51Ixd^3nY1uAn zY z5)Fz|y>bQhQ5^1$Wvv&KCe7PGBRnFCP2mdN6z+69RQKteG>syPGt&*4#%#<;^E2si zf`35<^C{|ZD?plhnZmWu+q8yTz*=CrAd~#@Yyo38<1L+1GrmiA9P}#6n@ciD!y*!E zfLP16A#Nq)H;WfRC?GF_A_Nhn9R_cd5rqg+dJfSddEReZNXUt3NG;X&Ek?1A6_1z2SacgDK*boRg*W@ z9Cel)WpoU{%OcV|;APQofOuIn8#Ux*(ON*f1lp#9X6j_oLO}d_ghWLw(#u3HI;m8t zi>uPb0YyZ*7!|n_!SD4ED9_4qx0sBKor@qb+ z@J=AyO1Se3A|uPuFtudcYWR6U5;y#0g1ZcYXq`8#@_(yh%F!H4&kv2-)~y z%LjKnIFdUZDL5;biuEM#M~OB7ILm~O4D&r^z`frD%dq*&0IC19lrCiNRMYT2{DE}- zEQ)+3nK_MHmmi&qJ60{ZW9qiR0@2E*oIkmPvPw14z9F^fzlstl`)Sx; z>CWYB$bK*jk(D4^0N-il25yB3=NS=5Nq&bSst45246vyt4Hr;79eBNv~D6(cukI-Cf$}h!MJedXHB#-%Ie6DtcwC`G(o+KhMJ$b zp$Q7XIRTE!6anxmF}(QeufF=~`OS)7G=qiHK23U8O~eQ;vQzjl| zfh>-En0T-_TtuWRMZrQ?IpqRoeUQFJNWL^I$kl^IC|*Taq)JmQbT7s1%i02!(0M8F z9v})5{*Ndhf9tWqZSZf};A%CM;)HDU{>cBYS>^80%Y_H)TIKG*1Jbz-UHi_+T6E&Z zCj3Y;^3t&*AQBa|G1M#+C4;J>KmcDEmSh@J)01wr`YN^E>u zLY7M}KF*%#=-Gwf%o%jB?qhTahjgp(20$+_5(#1xZ7XJWoa|JKoj^$t%tUWeHb<-> zWn(tD+FJhk-M}@ql(lD}WP@v1W|9wvl#SWo4x*wV47&f@t6IwWd?ecBP0ChyVo2GT z?JUiJCitCH`mU>`OlOr8c-vWmR?~%rH}h(QSi`)GS<_O#pb)!w_QKk{zT+eDr7U~& z5B)Z!sl|}8F-zHafyS}DjyRm7`cT-*|6%%bhLoG&i6LcURawFL&pCYFA4c?_^mZYg)rHw?w>QnT=V~(wHDFWi?EJW(MU!!Abzg zn%1zrTH&c7Wn;FpbnMdrzoB=3*vwOoNt*!6k`yLz$aa>OQO&iPBF3;5ZR+G@%u@Cs zFe!ZY)cQ$nE#4I<+p)a#`!n?;!&(@#l%;cJBGb6?TMRFOps0@kkfp34f9UAJkg_pL zSvpiC{#Z<_j;f{XDNwd&l<`+160;4pwLw(hSSBoSsn+ZGOW8X`&!zVSOdFlyC09&mgggZGTGM}a`nAB zlpX8T6hZ;HQ?H|$?8nHWezla>3zR#6GA|Q$2r+fJO0vrn1grxslp4lR_ZZw&u5a#bzmlLBSlQubf{?ir@oH|k}~c9ytJ zSv`HfcX4g**M!{3cGj>TcB?~~w=w+{DcmPaiJ6p;m7S82E_d(g?rva8#(xeeCN3jA zF(pZr6{`eRj52my8f^0fL_8EUyLD0UDDIsSN4T+BQ}ko~;L#%iCUHX2kgSvmwSNn^&T63I+k8JEnG$+X>)&O7aSU{uraz3Ua11$r=R8w?2BU#5frOP5_N>gtyTd*x9g-=s6`>c(t`g~dZ%3cMR8-G!JWy(8M=WY~Kp8mioV296>%S zyA|JE-1fktc$=MVAKPzA^_#fs$u*Dtc{9#lYJLCq)d`{7&ps{BKckLVk=E?s`tk8o zUyOV8>#>Bw;3yMWWtv%B+#u=8KN?vS9kow)i?&G#xa~3aT-L;-&nj+<2l}3s41JZ~ z==AvQ4cES0zr9b|iY=b!kL|fEf3f$QpVBV&Qbk?&Ioas^m63xgzW&C!vcmw;wa{6i z7ml`wJ#}FF({1lM9NHT3;j-N)rEB*UuPiq0WKqx{W=o~@5yvX4&GV*b^k@>0JmTxN zu_c4LCGJ?{ab=R(#LFgo?N6`hVsq}HCV%t9cH4KDt-XCsvd-AD!N;?C*Q-m+x{;f7-mm zWr@1QmF%WgaX;m`#V;M4I-$|}QK?g{PBy;%X^rKQjvGY{H?K6G;k`uq`{~au<|RKi zdFOShS<0BmanDaACCr-GH?7rOv+?PZ+MIoT!|9A>)YMBh-}_%p%DBGk#fyjg7kKU8 z+49_iO=ItUe*S#!l8QBlN-w$&dwf0kQPQ4@q{zKrUNzh9KD6%^ze`SyE(Ww|_}w#q zao@31B_3rD$6gP=p0xhqg7ltK_NOT3Z;d_CTAjFe_34cF`rb+&wk*f`d$F(8o?R_W z+xO_uAbh{u?!%p|_HB88)HWwc>ei@rH5W>Io;=(9i?}o!G_gtHKa*Jdye&`%|ZTNwtN{8-K6So%o#~w0mlRRdrQ%0A5`>nRESzuk(=6Zus zMGsAxNcQO2rq!HreS4LKb#sy&PK)<>nloeWx=|73%RPcE3M-Ee*;86kc<*iO@XwfUky_pWNWyC|>mlxrK_bA7mF zV9k^#+57$OrOs$`*kfRqYa<#2Px;+DcU;xHZo#ET?1o=9DQvz}zNc}K`kup=rIoG+ z8XaEk8t`<_y9?JXZ}{W#qGpz&@1y*BUhv_@y-YtIb~9)Am_56jr>*|{yn9i>2aT66 z4q0*GT9Xamm!E!l^VcOOUj7kvVO&<*J5$DA+df>rDld5Ch^CEOv~p-Jy_D(d__2q> zpmpP4CEOWxXZm}VCnDorPX&Fxak0s*RfV?ie!tFT?5n+9zPsu8?Qf^tw{=rDU6r=Q za_-lTe#d@k9(Jm;BKObaoP=A?rnvXm>F3y2*~YSMpDs-$kN1WR-CE=~Ec05zl%5ZB z$G(1Y=k9^hSFfipK6P%;>J#6;>|3bbW4`#K$;0<O^w}u;5v_JN8yJf+N zjW)q!9>z3Id#d=sy>i0*#-&QHrlX#iI(Yn2l9^UA%OmHa?}fe}nBD2N;P7_Q+Pu6r zds`QJOdP#uRPu^@IbM~OX`|i=?$$gex3Bdl-P&}#Y9|`pRJ3AOSWorpMdLPd6=B=o zZ*lnP)ySt04=r6+`taQH%4b!3%{Q(uvfDZSTF+0qJnWMHV9NO8-}q&o$!IgCx_cMJ z&6|C%C9XCo&^56-WTCP%xjkD8nJ>80rMPIgXD^KCaX{r)&LKD4h|F*Rq) zn7E(|FHcDC+&umL_U~U59wu4}yY%JSx4wGj>fc~sBfzdjr{?!v{e zDL=LhzBwc!_hrbkZWpGVwflZtv%;co!}cuiz4+dqcBd*=oBjGEH~QPs1mE<tEacu|1{L(Z_w7)~tBm?8^?Dn=B5*!Ipl z5ZQC3F?41Ni$*iv9d~m27s^>vmb~LR`S@zd)K|xk zOxx6bZ`wTX+zHoSx@J@@dYPU!cl-F!zviTx4(plR$Ms2y#mw)m-w|)Y-mZ< z*s~YDO!#SEeEe>4`^2J@8%g#jF8H-v(|kx!yRe~CREz!pin|tk!qP72{hgx%)?Qr^ zxZmTY>+x!nDs_xj%&bv?{}^xOxDBR9|cVnpx7_s59;>>M@9CnI`7k8fjU zwdr$n=fvkXemlAOR^{64pQ5%7yfeP?_1#`c#XmP_H1)Qte}{)s``f=oto-cP*r#J3 z+`iT0-kE|2RfT=OzP~Rj<(J=!o4qPOUGdk-v=3fyFbl8gYSa2Cs7#+tt__5W$` z<-LDQyvD8Cdj0gfe_Z`}Xum5Lt;b(@n7HBmj*Ab^&fe1PoaBpfr(AwqU6Go3=ggSa zj;C#2M<4FE^piumT`nCNBDXF7J|eR8&wIe4<$F4G_7%fDNk^Vft$-94S&Z`G-4$tQ!qT>ka&_zxcc(tg?D zSvQtem+xJ5^4r{%%bU4=vS!N5PaQM1uV~gF=R^NJJwKjN@#G`tKAIx)n4$BdZ#G(x z!kt|B>!-5{FF*I><_wW&wmTdtD2V?^eW3A(Id?X_Gppj#mD$6;Uy>L1WoZ5Y+m`bh zWu2S5`qZrrAMCbY|Dz=Fs~72Cd_8^g{f$GLcK)vEHyPi)cjVh|Y-c}O*Wl>DF=5 zA)CV!xJ}9JFYJl&Yrfm;Sy*w;PZsamR(Nf%`i9-UOVOhaJm|e*KaKx{q`k%5QOmD> z`)+&F$PdOX?DhM#eph0~zqiZv!lw^AZ97~TY%wGL#=Z=bc_tT%51jYEdNK8}OV0Hh z5jJrnRzcF z{=5%<9#k=JZo;-31Fnt=UU<^IlS|HAo7=zqlrv&jql*vZ$p=EK*HkG zo({a;JRtvWX~m6Mxhai%oR~J=FQ@D?X`>V6$(yq~mrG&;Ru@^Smp(-)r?SlhMUbb0p73rYPKPd@GRv|aiV@$(LDiHkl`7r6IW z{9weA&cnxgZ|iAZZGC-x;5)ldKKk<4>+iqT6n9r7wfuOvX=cY?_xSxj@mi07W6rZ) zTn@kM6Zgq#_wg^v)n{5J_bthi7EU?QZ_MqDAvdGsHN%76TXFAMb^*7s#lwCrs^xPe zpLQI)*RfsIyB?FnKm6{(4et1+C>OUKBOgRp{2ab1H^lc`t6yu<-gO&ishD@^ZdI?N za~3SfJiGEir_C=y7sW)}o-?55hyiNLh3oF5yR@??ncHZ>mjkwcaZ|ppWbR)LdUPJr z(m&{r@19I*-)ni3m4%b{JFRG2`GNh=V^1e{-{^PnpvkM#YZEP3BJ9sk~V({h`w4{q_65>7r=T z%GF`g+F7c^BNuHig&>K4!lKPKwh!`mv~k z_mz7d)$yTIdc5fU&JvGHn>&OZIRDZ8sv|G9&R^qWHLmgRt;|yb*6a`cc;Mx}9rOBp z`2O;c*WJ5+xNCTazpmX|*>vKV`8h3a_WrSZ-wj_6DQx0%$6ahcTfJw};u}9TdlohN z)yS$LD+Y%@de>}Dns@BrvtRwl9XYw7U#_di%=2S9l%;RgOqzcFx8sL0&bJ-eaPyj* zx8IRHnLTCw&slnvEuDC2 zaMx=YU5D&Cv-J1b63b{ppdRB)VGTIEaWptvH7Mt``a+aC=`v57u6 z*5mePNfWaMif>m8m7MiG-6;Rn+J@W5_u0PwrRSCvX_xmLJO9nz7xG>g(|+=~9;Lc+ zzR}6AD+Z11Q0e?l=rz%RqZdMF9XJ)+;@xdew?}L}*t(A5%EnXSZpupmY zb>)`LR#lEYGN#WPksQ#ZB)09>I}*DMnsmiuk;&zWW-CtH?|pdArpv_5`5Lnw+uN-= zaC_~&;>CUPUZh!GFf9)!mKJIGU>&-898#4dQ z^e2Cw4M+&w5<6nR_Rt?c-z!p{-Q#@A|N2^wK^K=@_@d&_gfr)#{^^xcmD)SK@~>}` z3KW;d7N7E#bjx-TxBdC6h5<2G8%;kJ(qQ7ij;0=8?YFYAIc9A?H!^wqd-fUmTX!X% zwfr&m_NwS>FB*5QJho!fsTJ+ZFRb4-a_gX$-M2NGy>nlb+riyw-##c-+kbRm>kjdb zTh_|Wr$74ToNxb6Pv?9mx!j?7_LUaupW>{VE{%7~YcwHs@YK{%>u)zcX|=?%=F^6v zjU8v0uiX5*bcy#oi_cHLWAZpT#jN!8^Kp@5W+fz@XqDD?V)}TqyRXl-nWQ=6bi?M- z)KN)S{l9;)>w3n5{SRNX+_~Rt?4||h&Y%DM-kORfxvm#W4+UR;Jgj0*(xWf;Mkcv$ zH@oV$rSH&-jhrrh*RV}MU$Or)56RTA*T+6ATc312yl47?hl-T_Q%=Ngoxe9x-TJ+Z z)2oLi-|G9lb$aad*|Tfq zN^bPEjcq@UFWvNO+~W?a)XzULov@_gCzfU#?lhkq>=bkxz_R-l}p2=6YR=2yPPM^KM#ShPRbr_wo zDd(o`PT!mYi&1xKq^X&SW^Tuum{>(EOjub{J#J%4?D(29Ez(ZsE>VF1r1`VeiJUYkO86_T6%F zrt|iis(t$&+a2FsS{SxLj&%fM#s&9iIE|@JDel4=ILuJx|t%*~+ABy!a9+TY0 zv`dE5(rs4z`;}QQSTm}@^)}s19~RO0Z`G!!N3Xu)<~Vf=D~nG%ESZt>)F)!py1Bs~ z%gc{e7Ftx4?iup(;l0A2o>rdtW_z&p_KmrLE7jc=%v)i1(!aE6Xjr9#&E%(<|EIVs z0jH|#{+D}Akts@%#7(7;ZlO{ri6(@IP>K?jGNrtVOT|gjfJPe8pi-o$TtcQy$xw-s zs3e&czO~P}_qZCq@BcmT^M3#RJnsJ8bN5+iowfH~>zw2K)-GS)s((~1vC>j2xlu|k zI=PaM859{P8@=WnK6ZA4ZfyDA*@&Jy5k$XmC`S5ST#})} zqXeJzZB6x8n%YY~WYse1HQ7l{c6NzZ4Gd#GZFeo4;_cq=GDpKTQ9;F~Raii1x}==; z);ETl?KyS=NiFUcJ33sQW~8aKcVE!RObL;T@H!$8J8Mi#`ghTwum_V8YJGK*TD3je zeFwKR89ma^mi^1RRz>HluL)nXqrX9>iRyuu7IHbqr9*kbMAP)HC^a!3YgcD#$7YY5 znAWj;L}Xm}sIbUqYYQntiz_vZw)Ht;KK17L57O)`F2=e^9}Lrd5fLdGRa+Ttnp>D4 z@wvXQth2A+*iOgFwXVL6zn09X|W zON>Zl_!9ijQ-eGmja)OffoPgivx{o_J!xL5Eg56T=QS(XG|GMV^_WhuUo< z7k$)M;$^wHv#Nab_eE(|E;+2)$bXrVoSiNk6tqJ>blhf}G}}c!P0==P)z#9fCh{Vh z{tlC6RnIJ-$i2QFO_7XcYM5h*jz^9ro0q=s$R7QqwZp14Gwyg-b!0`NKzj2%xv=;% z8nv#$@Bkp+)wiYG-ROFco$U5{LlrgWTFv^s*#fa}`@dmDyOSbsQu}+^gv?7bf+99e zjfqum$WBb{uZ`(_(Ox*WxT$~7z696wlSwxHNijkTt_5lDoi0beHCsTsO`KA9pa8obFQdZE8X0@c#DFJrl5K|p|Z_JnAq4*NTzac8eeN4|P*L6QAo zqG40%=y>v(uX&Ymy~!BUKL6EwDpgN77Ro(W4GSGLD>7}>gtVpz{@Cggd;j*&OPn%q zxEV!k^D>WBpDU@^q$DJeAV{~^BBARvEi%rxAw1pa@}&q_=ZB#xlfMsZ~`sw9)j|=b!iyv9lRh(YzAM$F~-eoB!e~lCz?N{tL(RZKcrCkfGUyY_6yn|lQ}Y?ansKkb_Hx@MM{)0N8S8#g|D=d4J5 zu&K@^%&4+J!C3nIm}TY@RxXY3@-?a5@MEQ%P{DGWdq-D9zrJkv#giE z2&A+0i)I?=iCKFrG;UN`gdG}h(YD#tlEJ&l$}4@r>U%GQ%zH8pt(to^&D2lot=S|0 z3Y)icnrs!!->h+N*>8R6z-_xv5wq4#{Z6&tzSzd$hWgg}*|PiUx_8`rd%O6{JCDoN zjXHPMei*2BeV@8%X2b50e67k$wZAkdh<(0rZgtDLj`dCIZyTCh4wiqqrWyLtW$nZM zQK?^ll$PZVM7fi0ot*d&VWmWSdMD*o?cXMiYbf&+#6NA0(oLKfsYuWosSCOh0 z3C^w0TdPtkRFeWq952yIW1lg~8{M~*(Z|_k+Yg98Idgn+PK}Cxu8f{>rq$}gtP?ul zS>=HjG9;Q#6s))zpC6tb^E7WyPM)wtTcLq~XVLzxi;6SK$35e{uNrYPQt!ytA3jH? zEmS+!JY{U;l?7*_HdZ&vC*|kgCdJ{kG^1C@za@mdT*Cnst z$e9$^79ewl@k#xXm!jCwG0EhcU&0-uth8#s&Ya}x@ak-(_WkU;Q(FHLGzs1Qux?`|JOEhw;&JM? zEmg1U-uN)AH;At`9cvZSba_T!pLmSa!s|Ud-t5VEx+ypAhSyHPMMclHE1$Tr*IiXY zMq2mMz3&HPO3sZdZkl|-BYfel9EIzGyO-p}&b+xm=I~S75%V@BCmo=asGDlLM16J; z310K{?fmyq2b}gFD1AM*?rw3oiH#3qitfh-@%^i;ectJ{RE_L0d%XGUw4U=uQ87nSJ zmwuyDn)xBv#eZMjo&t5zEFUA+f{|huJZ^8!T~EuMTAdoZ++cfj=a2HiBVU|N{a4p$ z$%@{eyds59Z_1@xtvPZc2QLP^yftplrpmq3%63H@+cu$No^m&pdFqIBgu3p*smH8a z?i#GK5a|)nkY5r1=1N=fgMp)OJ{zi~hFF{)v+46>citUejneX#tJl8l-8W;y;t!Ut zy0K@h#{Ss6ETZ5m+RyfX^=vH&UQ0VE*<`3?N4+l1$2Z&`*>qFPx$PsSE~=gZxZ_HrgFbA0V$BBS0bwS8ORI+m}q(tq6t z$I``AetobtX=*ih?Y6GUq7WYq{YpVTm$Zm(^toqSD z37TrpBtng^QFR*^r!fN*-ql5T+pg^zW!$``zs+(%v|Awm#ODjv8{}ZmuKH^w6u;Q3 zue~ix+0M^9QkAKdbGYJFx z=+YVl+=7}NnbWt|PCs6L-&lwi@bz|T;w!rB7 zwl%8FFT1kLHbq=1yp=G)Q{>rh=lkoA*YfeV!E0c!swsNqVI=&aS7JDyIK)5D8{dc& zy&C%#+|^y;sr-owt9o^@sGh(u36)@!K)Nkxg2^HB4TaSt$jH)P>Gg&=pkQew7AOnv zabN?iRz3y~R>JxyE|&5Nn|>B$FB3~C!=z52m--kLuq+}FN?4y{&~HfC8XBVlUu>8m z6^z~}WI!S_Ruk-9%if#Gq5*9UqXpvvvauS-wfB>NY(g;x?F23%3wHT?Dj)&FwHQ(X zt6^mSq5@liY-~EN0_@MoW@KR{0B}=q41ni>NqNPP!VQB}aT#Llf3U-l1`IF)*N$L8 zT%q3?VW<;^sex57Dt_q)q8BQ#>3Bb&Q>gf*GlrBvW*AZe8Dwa5pl-}Y0k1mPnJVgBqiuDgkB{b@1=x{V*exWVJa=jh~cRAR3 zDiSo^e={^2?7K^B*JROQoDrjbC5fy_w1q@_NOXuqCrNaTL=Q<+N}`t}LZOy88hX2% zK$0-=2qZ@$H4^EO2(83PwA(}?4-zp+beu%zNOYY=R|A}`Jr)QDRa=olwssza>0n24DA@@ z;Dzdu7Yft=Ar`0zN5lOPW=(_fo6q(nKs#bJgImc1Iv`r+l2OFWpyAF$iap@qy?nGw z5qlnqoIvs!1(3N1IkVTu9f1(oi|x;lkP56CmVW+8LIvbdgi~Yy^$STTM+f?o8ZeED zVDb!?z}BFM!O;Op7_P>U4p=p#V%QlVh1eRvWX5%X{qf114*;xy4hWVQvJ7bxtcEx? zmp~cDkREI$aBl{u4^}~*46Fj#T?v=YHev;r5*#yN=;%Yo1U;~tq5eQRan74d7Q`B` zA!Z8w!YE)M3I9h!3@L!g5&Zz(jBrQq*zRaK_6*V_K>{*H;X^#1RWD9u z!C}N1d7*A}NmiYp1M8!Vy)C3U%FJ2_V~3bL+ekFznvRg$E|BOBi84r3Mxq81b&`me zbOKT&QYO({5*d&Pkr)WA5T~0!2T2r8qKhO-B++9M<&mg@M4w3XgG9nGiHT!OB+(QS zEh5nh64{c-jYNpWOGvpwqPrx@B2fd0z(5rAJ}xRe>;!gbc>n>(`wWy}@h%pRCohAy zw3(R+X_CCYW}$}Yg6zq7huqacBAB_ffWdtL{7SGhbQ##OD~rcd9-U;^AzZMh*iR>kWtM&q ze(AZDG00xc8asrG!jE;F*oSRnuETlihzuR82pvQgKL{{R|8Rs5LLaeU4U~=G5FHJ2 zpscfO*``_wS|fu>QEW&AfP!94)`OapWE}B5!03>`8# z@PAOiQQ(C=de}*^)qo7(#QtRfqQa)XyQ(blF7O7>^B?1{q8IRomtXm-6a}J1RQ!~8 zLv3knh-?7-A1=Nq`h{5g3`|Usj)96iQQ=I~;d~^-`WY_yPfS$g4v^%>qT{%jY17$~1wrTGk`YU5xa2=EQ8|7i zq^7QQNM|5D;RP{Khf5azMe@I6q9P$Kvx`lJBpc&$2`1`r$;e3#*ZEJpQ#3=s)RZgs zRgnLJW9PMO$%uD4ya&a8k^Cp#DVje>UWUjme*$syJjH*JEb)tEf_Lf)+tHpJ8WLJ8 zjO!~te;nLgJUtOdiTLK|f|lfRo{3mIJ6(1;cmnMRRvqKo;<3XER_o%lhneT-0%Roh zS#t;i44XFd9~m>6np#9t#F!Dn88f9Yye5LmsQhjPEI(uu?lMB0L+mx@Y)%Id|5H1h zF~cV7f zA8cOR-y?l6KWjtmGJ>F`13}9GrSCAom%KQVlD>&RnwGH^uxIg~6*pFPv@WLI%(LAE^AUA?s2gP?v z#gG*^#-mbD3_u0-8Bx#{4i|A~3qrEQSNOyu2bUunx?(_0hOd@7mAw~gGd$k>dc{D+ zb>%(_a5K6=%3!JM2?Vnzst2cr0ya^>3)f?tM5 zU*d{k9c(8Vt}{ska#K?glhc8-DCHm4b0kF!2_xvTBh+Uz80^r6SN}PFX=x9|FMd3J zwLl+0b{f3=E`FgKlwsvJ@hc4)%=oF@@8Xv}j4O1v$X)*A_ostiI%s@ALA(4ej)cK> zLv|a~4wXO2D~ERPev&|L6nw>$4dj; zDm)q!r{)Lrw!yZY`~l6VruGI5vcI>Y8p~zXi8}~Gie!{wQ7X90OUT{<&&_0;#r!Vr z!GL>0VaOj$eQHSUUFOv}TpE_kD0_s&ba&Z1*uvw#I&ooER>1dLFwevS^P$gDZzgQB z?|x^AePp!=V}k*o&`+th(Czr0wphw&Dm;H%%|q?QYhHFuW!E%z&Bw0!*|h+>7G&2# z?0N*d7G~EX?0O`-7G>9BsHXNZbHt6rf_>1PD6GbEA3u{eEcY>PnS4fBclQdkypJI? zutOPUQH%krhy_Lfz_M6P@X+l4@dO~Z7v~&2LB*fCYS<~^y@a7t>caZ4TzgKh!+B89 z+(m_RYfXk}ks+I)akd(33ur_G%nHj%LncDc3H!uu!XW5whw&x_|1@b54|s=~Kuo?X z{}sTr;(!6vHY{ias=TEFzMz`e=*>@joBwu@hvLnrimLf|Gd@*R;ab8K3Le{$OF)H6 zk;Cgz@c9qKcFw%~HMIYO_w~rl4lmqMk%;Y_ZtAWMoJTlL2d-REL~Q524L}}oc + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/libs/extlib/Makefile b/libs/extlib/Makefile index 488d5072..9ed56c46 100644 --- a/libs/extlib/Makefile +++ b/libs/extlib/Makefile @@ -4,7 +4,7 @@ OCAMLC=ocamlc MODULES = \ enum bitSet dynArray extArray extHashtbl extList extString global rbuffer IO option \ - pMap std uChar uTF8 base64 unzip refList optParse dllist multiArray + pMap std uChar uTF8 base64 unzip refList optParse dllist multiArray sMap # the list is topologically sorted diff --git a/libs/extlib/README.txt b/libs/extlib/README.txt index fc31848f..70e68e7d 100644 --- a/libs/extlib/README.txt +++ b/libs/extlib/README.txt @@ -13,7 +13,7 @@ OCaml Extended standard Library - ExtLib. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA What is ExtLib ? ---------------- diff --git a/libs/extlib/base64.ml b/libs/extlib/base64.ml index 0ac96136..87893a0a 100644 --- a/libs/extlib/base64.ml +++ b/libs/extlib/base64.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) exception Invalid_char diff --git a/libs/extlib/base64.mli b/libs/extlib/base64.mli index 38dd9b4c..c812efcd 100644 --- a/libs/extlib/base64.mli +++ b/libs/extlib/base64.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Base64 codec. diff --git a/libs/extlib/bitSet.ml b/libs/extlib/bitSet.ml index 7f10f47c..18440845 100644 --- a/libs/extlib/bitSet.ml +++ b/libs/extlib/bitSet.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type intern diff --git a/libs/extlib/bitSet.mli b/libs/extlib/bitSet.mli index aeff7f7e..9412f446 100644 --- a/libs/extlib/bitSet.mli +++ b/libs/extlib/bitSet.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Efficient bit sets. diff --git a/libs/extlib/dllist.ml b/libs/extlib/dllist.ml index 07182917..308cfabc 100644 --- a/libs/extlib/dllist.ml +++ b/libs/extlib/dllist.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type 'a node_t = { diff --git a/libs/extlib/dllist.mli b/libs/extlib/dllist.mli index 0e0990eb..1c992ae8 100644 --- a/libs/extlib/dllist.mli +++ b/libs/extlib/dllist.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** A mutable, imperative, circular, doubly linked list library diff --git a/libs/extlib/dynArray.ml b/libs/extlib/dynArray.ml index a94dbb34..0f6f14b0 100644 --- a/libs/extlib/dynArray.ml +++ b/libs/extlib/dynArray.ml @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type resizer_t = currslots:int -> oldlength:int -> newlength:int -> int diff --git a/libs/extlib/dynArray.mli b/libs/extlib/dynArray.mli index 29660e16..2ce39e98 100644 --- a/libs/extlib/dynArray.mli +++ b/libs/extlib/dynArray.mli @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Dynamic arrays. diff --git a/libs/extlib/enum.ml b/libs/extlib/enum.ml index 3b7708d0..4528ad3e 100644 --- a/libs/extlib/enum.ml +++ b/libs/extlib/enum.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type 'a t = { diff --git a/libs/extlib/enum.mli b/libs/extlib/enum.mli index 96e0b759..79c102e8 100644 --- a/libs/extlib/enum.mli +++ b/libs/extlib/enum.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Enumeration over abstract collection of elements. diff --git a/libs/extlib/extArray.ml b/libs/extlib/extArray.ml index 545151a7..07c83905 100644 --- a/libs/extlib/extArray.ml +++ b/libs/extlib/extArray.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) module Array = struct diff --git a/libs/extlib/extArray.mli b/libs/extlib/extArray.mli index 73842792..ae198618 100755 --- a/libs/extlib/extArray.mli +++ b/libs/extlib/extArray.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Additional and modified functions for arrays. diff --git a/libs/extlib/extHashtbl.ml b/libs/extlib/extHashtbl.ml index 52ff0734..aaac6494 100644 --- a/libs/extlib/extHashtbl.ml +++ b/libs/extlib/extHashtbl.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) diff --git a/libs/extlib/extHashtbl.mli b/libs/extlib/extHashtbl.mli index 8df3f4f8..d6254d1e 100644 --- a/libs/extlib/extHashtbl.mli +++ b/libs/extlib/extHashtbl.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Extra functions over hashtables. *) diff --git a/libs/extlib/extLib.ml b/libs/extlib/extLib.ml index 17ddb56c..bfaf31b6 100755 --- a/libs/extlib/extLib.ml +++ b/libs/extlib/extLib.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (* diff --git a/libs/extlib/extList.ml b/libs/extlib/extList.ml old mode 100755 new mode 100644 index 9380df5c..f699fecc --- a/libs/extlib/extList.ml +++ b/libs/extlib/extList.ml @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) module List = struct diff --git a/libs/extlib/extList.mli b/libs/extlib/extList.mli index a8af16df..87db836e 100755 --- a/libs/extlib/extList.mli +++ b/libs/extlib/extList.mli @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Additional and modified functions for lists. diff --git a/libs/extlib/extString.ml b/libs/extlib/extString.ml index 4365d7c0..ffe96a2f 100644 --- a/libs/extlib/extString.ml +++ b/libs/extlib/extString.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) exception Invalid_string diff --git a/libs/extlib/extString.mli b/libs/extlib/extString.mli index e3c94a93..93213c0c 100644 --- a/libs/extlib/extString.mli +++ b/libs/extlib/extString.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Additional functions for string manipulations. *) diff --git a/libs/extlib/global.ml b/libs/extlib/global.ml index 16d2af7a..7cfe6232 100644 --- a/libs/extlib/global.ml +++ b/libs/extlib/global.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) exception Global_not_initialized of string diff --git a/libs/extlib/global.mli b/libs/extlib/global.mli index 904a7d41..76436bb3 100644 --- a/libs/extlib/global.mli +++ b/libs/extlib/global.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Mutable global variable. diff --git a/libs/extlib/install.ml b/libs/extlib/install.ml index 009ebab8..862adeff 100644 --- a/libs/extlib/install.ml +++ b/libs/extlib/install.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open Printf diff --git a/libs/extlib/multiArray.ml b/libs/extlib/multiArray.ml index e9d439d0..29ea2052 100644 --- a/libs/extlib/multiArray.ml +++ b/libs/extlib/multiArray.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type 'a intern diff --git a/libs/extlib/multiArray.mli b/libs/extlib/multiArray.mli index 72bbba76..0c046f25 100644 --- a/libs/extlib/multiArray.mli +++ b/libs/extlib/multiArray.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Dynamic Big arrays. diff --git a/libs/extlib/optParse.ml b/libs/extlib/optParse.ml index 4ff4488b..ef64e72d 100644 --- a/libs/extlib/optParse.ml +++ b/libs/extlib/optParse.ml @@ -19,7 +19,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open Printf open ExtString diff --git a/libs/extlib/optParse.mli b/libs/extlib/optParse.mli index 76025804..65fa7120 100644 --- a/libs/extlib/optParse.mli +++ b/libs/extlib/optParse.mli @@ -19,7 +19,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Modules for GNU [getopt(3)]-style command line parsing. *) diff --git a/libs/extlib/option.ml b/libs/extlib/option.ml index ab6fffdd..46601008 100644 --- a/libs/extlib/option.ml +++ b/libs/extlib/option.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) exception No_value diff --git a/libs/extlib/option.mli b/libs/extlib/option.mli index 0fba89e7..21960d68 100644 --- a/libs/extlib/option.mli +++ b/libs/extlib/option.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Functions for the option type. diff --git a/libs/extlib/pMap.ml b/libs/extlib/pMap.ml index b63c64e7..c6dcbc75 100644 --- a/libs/extlib/pMap.ml +++ b/libs/extlib/pMap.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type ('k, 'v) map = diff --git a/libs/extlib/pMap.mli b/libs/extlib/pMap.mli index 01f2c8cd..0e703d84 100644 --- a/libs/extlib/pMap.mli +++ b/libs/extlib/pMap.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Polymorphic Map. diff --git a/libs/extlib/rbuffer.ml b/libs/extlib/rbuffer.ml index fe9f0bd7..9c4d15c5 100644 --- a/libs/extlib/rbuffer.ml +++ b/libs/extlib/rbuffer.ml @@ -15,7 +15,7 @@ (* Ropes-based implementation of Buffer *) -type rope = +type rope = | Str of string | App of rope * rope * int (* total length *) @@ -26,7 +26,7 @@ let rope_length = function | App (_, _, n) -> n let rec rope_nth i = function - | Str s -> + | Str s -> String.unsafe_get s i | App (l, r, _) -> let ll = rope_length l in @@ -50,12 +50,12 @@ let reset b = let clear = reset -let length b = +let length b = rope_length b.rope + b.position (* [blit s i r] blits the contents of rope [r] in string [s] at index [i] *) let rec blit_rope s i = function - | Str str -> + | Str str -> String.blit str 0 s i (String.length str) | App (l, r, _) -> let ll = rope_length l in @@ -81,10 +81,10 @@ let rec blit_subrope s i ofs len = function String.blit str ofs s i len | App (l, r, _) -> let ll = rope_length l in - if ofs + len <= ll then + if ofs + len <= ll then blit_subrope s i ofs len l - else if ofs >= ll then - blit_subrope s i (ofs - ll) len r + else if ofs >= ll then + blit_subrope s i (ofs - ll) len r else begin let lenl = ll - ofs in blit_subrope s i ofs lenl l; @@ -93,11 +93,11 @@ let rec blit_subrope s i ofs len = function let sub b ofs len = let r = rope_length b.rope in - if len > Sys.max_string_length || + if len > Sys.max_string_length || ofs < 0 || len < 0 || ofs > r + b.position - len then invalid_arg "Buffer.sub"; let s = String.create len in - if ofs + len <= r then + if ofs + len <= r then blit_subrope s 0 ofs len b.rope else if ofs >= r then String.blit b.buffer (ofs - r) s 0 len @@ -128,8 +128,8 @@ let move_buffer_to_rope b = end; b.position <- 0 end - -let add_char b c = + +let add_char b c = if b.position = String.length b.buffer then move_buffer_to_rope b; let pos = b.position in b.buffer.[pos] <- c; @@ -155,7 +155,7 @@ let alloc b len = end else begin (* buffer and len require two strings, allocated in the rope *) let str = String.create len in - b.rope <- App (b.rope, + b.rope <- App (b.rope, App (Str (String.sub b.buffer 0 pos), Str str, len'), rope_length b.rope + len'); b.position <- 0; @@ -191,19 +191,29 @@ let rec add_channel b ic len = end let output_buffer oc b = - let rec output_rope = function - | Str s -> output oc s 0 (String.length s) - | App (l, r, _) -> output_rope l; output_rope r + let rec loop wl = match wl with + | Str s :: wl -> + output oc s 0 (String.length s); + loop wl + | App( l, r, _) :: wl -> + loop (l :: r :: wl) + | [] -> + () in - output_rope b.rope; + loop [b.rope]; output oc b.buffer 0 b.position open Format let print fmt b = - let rec print_rope = function - | Str s -> pp_print_string fmt s - | App (l, r, _) -> print_rope l; print_rope r + let rec loop wl = match wl with + | Str s :: wl -> + pp_print_string fmt s; + loop wl + | App( l, r, _) :: wl -> + loop (l :: r :: wl) + | [] -> + () in - print_rope b.rope; + loop [b.rope]; pp_print_string fmt (String.sub b.buffer 0 b.position) diff --git a/libs/extlib/refList.ml b/libs/extlib/refList.ml index b16b6f21..c031cebb 100644 --- a/libs/extlib/refList.ml +++ b/libs/extlib/refList.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open ExtList diff --git a/libs/extlib/refList.mli b/libs/extlib/refList.mli index ea7bc06f..fac93435 100644 --- a/libs/extlib/refList.mli +++ b/libs/extlib/refList.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Reference on lists. diff --git a/libs/extlib/sMap.ml b/libs/extlib/sMap.ml new file mode 100644 index 00000000..025f3cc4 --- /dev/null +++ b/libs/extlib/sMap.ml @@ -0,0 +1,169 @@ +(* + * SMap - Fast String maps + * Copyright (C) 2016 Nicolas Cannasse + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version, + * with the special exception on linking described in file LICENSE. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + *) + +type 'a t = + | Empty + | Node of 'a t * string * 'a * 'a t * int + +let height = function + | Node (_, _, _, _, h) -> h + | Empty -> 0 + +type bucket = + | Eof + | Entry of string * int * bucket + +let size = 256 +let string_h = Array.make size Eof +let string_a = DynArray.create() + +let string_id s = s +let id_to_string x = x + +let make l k v r = Node (l, k, v, r, max (height l) (height r) + 1) + +let bal l k v r = + let hl = height l in + let hr = height r in + if hl > hr + 2 then + match l with + | Node (ll, lk, lv, lr, _) -> + if height ll >= height lr then make ll lk lv (make lr k v r) + else + (match lr with + | Node (lrl, lrk, lrv, lrr, _) -> + make (make ll lk lv lrl) lrk lrv (make lrr k v r) + | Empty -> assert false) + | Empty -> assert false + else if hr > hl + 2 then + match r with + | Node (rl, rk, rv, rr, _) -> + if height rr >= height rl then make (make l k v rl) rk rv rr + else + (match rl with + | Node (rll, rlk, rlv, rlr, _) -> + make (make l k v rll) rlk rlv (make rlr rk rv rr) + | Empty -> assert false) + | Empty -> assert false + else Node (l, k, v, r, max hl hr + 1) + +let rec min_binding = function + | Node (Empty, k, v, _, _) -> k, v + | Node (l, _, _, _, _) -> min_binding l + | Empty -> raise Not_found + +let rec remove_min_binding = function + | Node (Empty, _, _, r, _) -> r + | Node (l, k, v, r, _) -> bal (remove_min_binding l) k v r + | Empty -> invalid_arg "PMap.remove_min_binding" + +let merge t1 t2 = + match t1, t2 with + | Empty, _ -> t2 + | _, Empty -> t1 + | _ -> + let k, v = min_binding t2 in + bal t1 k v (remove_min_binding t2) + +let empty = Empty + +let is_empty x = x = Empty + +let add x d map = + let x = string_id x in + let rec loop = function + | Node (l, k, v, r, h) -> + if x = k then Node (l, x, d, r, h) + else if x < k then + let nl = loop l in + bal nl k v r + else + let nr = loop r in + bal l k v nr + | Empty -> Node (Empty, x, d, Empty, 1) in + loop map + +let find x map = + let x = string_id x in + let rec loop = function + | Node (l, k, v, r, _) -> + if x < k then loop l + else if x > k then loop r + else v + | Empty -> raise Not_found in + loop map + +let remove x map = + let x = string_id x in + let rec loop = function + | Node (l, k, v, r, _) -> + if x = k then merge l r else + if x < k then bal (loop l) k v r else bal l k v (loop r) + | Empty -> Empty in + loop map + +let mem x map = + let x = string_id x in + let rec loop = function + | Node (l, k, v, r, _) -> + x = k || loop (if x < k then l else r) + | Empty -> false in + loop map + +let exists = mem + +let iter f map = + let rec loop = function + | Empty -> () + | Node (l, k, v, r, _) -> loop l; f (id_to_string k) v; loop r in + loop map + +let map f map = + let rec loop = function + | Empty -> Empty + | Node (l, k, v, r, h) -> + let l = loop l in + let r = loop r in + Node (l, k, f v, r, h) in + loop map + +let mapi f map = + let rec loop = function + | Empty -> Empty + | Node (l, k, v, r, h) -> + let l = loop l in + let r = loop r in + Node (l, k, f (id_to_string k) v, r, h) in + loop map + +let fold f map acc = + let rec loop acc = function + | Empty -> acc + | Node (l, k, v, r, _) -> + loop (f v (loop acc l)) r in + loop acc map + +let foldi f map acc = + let rec loop acc = function + | Empty -> acc + | Node (l, k, v, r, _) -> + loop (f (id_to_string k) v (loop acc l)) r in + loop acc map + diff --git a/libs/extlib/sMap.mli b/libs/extlib/sMap.mli new file mode 100644 index 00000000..e3574676 --- /dev/null +++ b/libs/extlib/sMap.mli @@ -0,0 +1,83 @@ +(* + * SMap - Polymorphic maps + * Copyright (C) 2016 Nicolas Cannasse + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version, + * with the special exception on linking described in file LICENSE. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + *) + +(** Polymorphic Map. + + This is a polymorphic map, similar to standard library [Map] module + but in a defunctorized style. +*) + +type 'a t + +val empty : 'a t +(** The empty map, using [compare] as key comparison function. *) + +val is_empty : 'a t -> bool +(** returns true if the map is empty. *) + +val add : string -> 'a -> 'a t -> 'a t +(** [add x y m] returns a map containing the same bindings as + [m], plus a binding of [x] to [y]. If [x] was already bound + in [m], its previous binding disappears. *) + +val find : string -> 'a t -> 'a +(** [find x m] returns the current binding of [x] in [m], + or raises [Not_found] if no such binding exists. *) + +val remove : string -> 'a t -> 'a t +(** [remove x m] returns a map containing the same bindings as + [m], except for [x] which is unbound in the returned map. *) + +val mem : string -> 'a t -> bool +(** [mem x m] returns [true] if [m] contains a binding for [x], + and [false] otherwise. *) + +val exists : string -> 'a t -> bool +(** same as [mem]. *) + +val iter : (string -> 'a -> unit) -> 'a t -> unit +(** [iter f m] applies [f] to all bindings in map [m]. + [f] receives the key as first argument, and the associated value + as second argument. The order in which the bindings are passed to + [f] is unspecified. Only current bindings are presented to [f]: + bindings hidden by more recent bindings are not passed to [f]. *) + +val map : ('a -> 'b) -> 'a t -> 'b t +(** [map f m] returns a map with same domain as [m], where the + associated value [a] of all bindings of [m] has been + replaced by the result of the application of [f] to [a]. + The order in which the associated values are passed to [f] + is unspecified. *) + +val mapi : (string -> 'a -> 'b) -> 'a t -> 'b t +(** Same as [map], but the function receives as arguments both the + key and the associated value for each binding of the map. *) + +val fold : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b +(** [fold f m a] computes [(f kN dN ... (f k1 d1 a)...)], + where [k1 ... kN] are the keys of all bindings in [m], + and [d1 ... dN] are the associated data. + The order in which the bindings are presented to [f] is + unspecified. *) + +val foldi : (string -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b +(** Same as [fold], but the function receives as arguments both the + key and the associated value for each binding of the map. *) + diff --git a/libs/extlib/std.ml b/libs/extlib/std.ml index 4903b829..157bb372 100644 --- a/libs/extlib/std.ml +++ b/libs/extlib/std.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) let input_lines ch = diff --git a/libs/extlib/std.mli b/libs/extlib/std.mli index 128d969d..ce243161 100644 --- a/libs/extlib/std.mli +++ b/libs/extlib/std.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Additional functions. *) diff --git a/libs/extlib/uChar.ml b/libs/extlib/uChar.ml index 194a7532..b8d52dc9 100644 --- a/libs/extlib/uChar.ml +++ b/libs/extlib/uChar.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type t = int diff --git a/libs/extlib/uChar.mli b/libs/extlib/uChar.mli index 23015053..864b423b 100644 --- a/libs/extlib/uChar.mli +++ b/libs/extlib/uChar.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Unicode (ISO-UCS) characters. diff --git a/libs/extlib/uTF8.ml b/libs/extlib/uTF8.ml index b7da7b94..3929228b 100644 --- a/libs/extlib/uTF8.ml +++ b/libs/extlib/uTF8.ml @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open UChar diff --git a/libs/extlib/uTF8.mli b/libs/extlib/uTF8.mli index 72d9a13d..55720d14 100644 --- a/libs/extlib/uTF8.mli +++ b/libs/extlib/uTF8.mli @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** UTF-8 encoded Unicode strings. diff --git a/libs/extlib/unzip.ml b/libs/extlib/unzip.ml index a27e12cc..bce81032 100644 --- a/libs/extlib/unzip.ml +++ b/libs/extlib/unzip.ml @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type huffman = diff --git a/libs/extlib/unzip.mli b/libs/extlib/unzip.mli index 5a21cfce..7de37173 100644 --- a/libs/extlib/unzip.mli +++ b/libs/extlib/unzip.mli @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (** Decompression algorithm. diff --git a/libs/ilib/ilData.mli b/libs/ilib/ilData.mli index d8776bdf..377fa234 100644 --- a/libs/ilib/ilData.mli +++ b/libs/ilib/ilData.mli @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open IlMeta;; diff --git a/libs/ilib/ilMeta.mli b/libs/ilib/ilMeta.mli index abe9beda..4c77746b 100644 --- a/libs/ilib/ilMeta.mli +++ b/libs/ilib/ilMeta.mli @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open PeData;; diff --git a/libs/ilib/ilMetaDebug.ml b/libs/ilib/ilMetaDebug.ml index 50972581..023a14e5 100644 --- a/libs/ilib/ilMetaDebug.ml +++ b/libs/ilib/ilMetaDebug.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open IlMeta;; open IlMetaTools;; diff --git a/libs/ilib/ilMetaReader.ml b/libs/ilib/ilMetaReader.ml index 3d4a62b1..b123d19b 100644 --- a/libs/ilib/ilMetaReader.ml +++ b/libs/ilib/ilMetaReader.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open PeData;; diff --git a/libs/ilib/ilMetaTools.ml b/libs/ilib/ilMetaTools.ml index 402099bb..5630e99b 100644 --- a/libs/ilib/ilMetaTools.ml +++ b/libs/ilib/ilMetaTools.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open IlMeta;; open IlData;; diff --git a/libs/ilib/ilMetaWriter.ml b/libs/ilib/ilMetaWriter.ml index 48956d5f..7e9b5465 100644 --- a/libs/ilib/ilMetaWriter.ml +++ b/libs/ilib/ilMetaWriter.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open PeData;; diff --git a/libs/ilib/peData.ml b/libs/ilib/peData.ml index 5cd4d5d5..0a3881aa 100644 --- a/libs/ilib/peData.ml +++ b/libs/ilib/peData.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) (* diff --git a/libs/ilib/peDataDebug.ml b/libs/ilib/peDataDebug.ml index 50a76051..2c41a51d 100644 --- a/libs/ilib/peDataDebug.ml +++ b/libs/ilib/peDataDebug.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open PeData;; open Printf;; diff --git a/libs/ilib/peReader.ml b/libs/ilib/peReader.ml index 6016ff19..1bd1f7e8 100644 --- a/libs/ilib/peReader.ml +++ b/libs/ilib/peReader.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open PeData;; diff --git a/libs/ilib/peWriter.ml b/libs/ilib/peWriter.ml index cd8d4091..c6f976fb 100644 --- a/libs/ilib/peWriter.ml +++ b/libs/ilib/peWriter.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open PeData;; diff --git a/libs/javalib/Makefile b/libs/javalib/Makefile index 2032fc62..e5b1d78f 100644 --- a/libs/javalib/Makefile +++ b/libs/javalib/Makefile @@ -1,6 +1,6 @@ OCAMLOPT=ocamlopt OCAMLC=ocamlc -SRC=jData.ml jReader.ml +SRC=jData.ml jReader.ml jWriter.ml all: bytecode native diff --git a/libs/javalib/jData.ml b/libs/javalib/jData.ml index 82fe19c7..12f2561e 100644 --- a/libs/javalib/jData.ml +++ b/libs/javalib/jData.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type jpath = (string list) * string @@ -129,7 +129,7 @@ type jannotation = { } and jannotation_value = - | ValConst of jconstant (* B, C, D, E, F, I, J, S, Z, s *) + | ValConst of jsignature * jconstant (* B, C, D, E, F, I, J, S, Z, s *) | ValEnum of jsignature * string (* e *) | ValClass of jsignature (* c *) (* V -> Void *) | ValAnnotation of jannotation (* @ *) diff --git a/libs/javalib/jReader.ml b/libs/javalib/jReader.ml index 6752d40f..95a7c524 100644 --- a/libs/javalib/jReader.ml +++ b/libs/javalib/jReader.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open JData;; open IO.BigEndian;; @@ -82,11 +82,11 @@ let parse_constant max idx ch = (* TODO: correctly decode modified UTF8 *) KUtf8String str | 15 -> - let reft = get_reference_type (IO.read_byte ch) idx in - let dynref = index() in - KMethodHandle (reft, dynref) + let reft = get_reference_type (IO.read_byte ch) idx in + let dynref = index() in + KMethodHandle (reft, dynref) | 16 -> - KMethodType (index()) + KMethodType (index()) | 18 -> let bootstrapref = read_ui16 ch in (* not index *) let nametyperef = index() in @@ -368,8 +368,14 @@ let get_string consts ch = let rec parse_element_value consts ch = let tag = IO.read_byte ch in match Char.chr tag with - | 'B' | 'C' | 'D' | 'E' | 'F' | 'I' | 'J' | 'S' | 'Z' | 's' -> - ValConst (get_constant consts (read_ui16 ch)) + | 'B' | 'C' | 'D' | 'F' | 'I' | 'J' | 'S' | 'Z' | 's' -> + let jsig = match (Char.chr tag) with + | 's' -> + TObject( (["java";"lang"],"String"), [] ) + | tag -> + fst (parse_signature_part (Char.escaped tag)) + in + ValConst(jsig, get_constant consts (read_ui16 ch)) | 'e' -> let path = parse_signature (get_string consts ch) in let name = get_string consts ch in @@ -500,23 +506,23 @@ let parse_class ch = let constant_count = read_ui16 ch in let const_big = ref true in let consts = Array.init constant_count (fun idx -> - if !const_big then begin - const_big := false; - KUnusable - end else - let c = parse_constant constant_count idx ch in - (match c with KLong _ | KDouble _ -> const_big := true | _ -> ()); - c + if !const_big then begin + const_big := false; + KUnusable + end else + let c = parse_constant constant_count idx ch in + (match c with KLong _ | KDouble _ -> const_big := true | _ -> ()); + c ) in let consts = Array.mapi (fun i _ -> expand_constant consts i) consts in let flags = parse_access_flags ch [JPublic; JUnusable; JUnusable; JUnusable; JFinal; JSuper; JUnusable; JUnusable; JUnusable; JInterface; JAbstract; JUnusable; JSynthetic; JAnnotation; JEnum] in let this = get_class consts ch in let super_idx = read_ui16 ch in let super = match super_idx with - | 0 -> TObject((["java";"lang"], "Object"), []); - | idx -> match get_constant consts idx with - | ConstClass path -> TObject(path,[]) - | _ -> error "Invalid super index" + | 0 -> TObject((["java";"lang"], "Object"), []); + | idx -> match get_constant consts idx with + | ConstClass path -> TObject(path,[]) + | _ -> error "Invalid super index" in let interfaces = List.init (read_ui16 ch) (fun _ -> TObject (get_class consts ch, [])) in let fields = List.init (read_ui16 ch) (fun _ -> parse_field JKField consts ch) in @@ -575,7 +581,7 @@ let parse_class ch = None | _ -> do_default() ) consts ch attribs in - IO.close_in ch; + IO.close_in ch; { cversion = majorv, minorv; cpath = this; diff --git a/libs/javalib/jWriter.ml b/libs/javalib/jWriter.ml index 76486a43..2288854c 100644 --- a/libs/javalib/jWriter.ml +++ b/libs/javalib/jWriter.ml @@ -14,19 +14,20 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open JData;; open IO.BigEndian;; +open IO;; open ExtString;; open ExtList;; exception Writer_error_message of string type context = { - cpool : unit output; + cpool : unit IO.output; mutable ccount : int; - ch : string output; + ch : string IO.output; mutable constants : (jconstant,int) PMap.t; } @@ -47,15 +48,91 @@ let get_reference_type i = let encode_path ctx (pack,name) = String.concat "/" (pack @ [name]) -let encode_sig ctx jsig = "" +let rec encode_param ctx ch param = + match param with + | TAny -> write_byte ch (Char.code '*') + | TType(w, s) -> + (match w with + | WExtends -> write_byte ch (Char.code '+') + | WSuper -> write_byte ch (Char.code '-') + | WNone -> ()); + encode_sig_part ctx ch s -let encode_utf8 ctx s = s (* TODO *) +and encode_sig_part ctx ch jsig = match jsig with + | TByte -> write_byte ch (Char.code 'B') + | TChar -> write_byte ch (Char.code 'C') + | TDouble -> write_byte ch (Char.code 'D') + | TFloat -> write_byte ch (Char.code 'F') + | TInt -> write_byte ch (Char.code 'I') + | TLong -> write_byte ch (Char.code 'J') + | TShort -> write_byte ch (Char.code 'S') + | TBool -> write_byte ch (Char.code 'Z') + | TObject(path, params) -> + write_byte ch (Char.code 'L'); + write_string ch (encode_path ctx path); + if params <> [] then begin + write_byte ch (Char.code '<'); + List.iter (encode_param ctx ch) params; + write_byte ch (Char.code '>') + end; + write_byte ch (Char.code ';') + | TObjectInner(pack, inners) -> + write_byte ch (Char.code 'L'); + List.iter (fun p -> + write_string ch p; + write_byte ch (Char.code '/') + ) pack; + + let first = ref true in + List.iter (fun (name,params) -> + (if !first then first := false else write_byte ch (Char.code '.')); + write_string ch name; + if params <> [] then begin + write_byte ch (Char.code '<'); + List.iter (encode_param ctx ch) params; + write_byte ch (Char.code '>') + end; + ) inners; + write_byte ch (Char.code ';') + | TArray(s,size) -> + write_byte ch (Char.code '['); + (match size with + | Some size -> + write_string ch (string_of_int size); + | None -> ()); + encode_sig_part ctx ch s + | TMethod(args, ret) -> + write_byte ch (Char.code '('); + List.iter (encode_sig_part ctx ch) args; + (match ret with + | None -> write_byte ch (Char.code 'V') + | Some jsig -> encode_sig_part ctx ch jsig) + | TTypeParameter name -> + write_byte ch (Char.code 'T'); + write_string ch name; + write_byte ch (Char.code ';') + +let encode_sig ctx jsig = + let buf = IO.output_string() in + encode_sig_part ctx buf jsig; + close_out buf + +let write_utf8 ch s = + String.iter (fun c -> + let c = Char.code c in + if c = 0 then begin + write_byte ch 0xC0; + write_byte ch 0x80 + end else + write_byte ch c + ) s let rec const ctx c = try PMap.find c ctx.constants with | Not_found -> + let ret = ctx.ccount in (match c with (** references a class or an interface - jpath must be encoded as StringUtf8 *) | ConstClass path -> (* tag = 7 *) @@ -72,7 +149,7 @@ let rec const ctx c = write_ui16 ctx.cpool (const ctx (ConstClass jpath)); write_ui16 ctx.cpool (const ctx (ConstNameAndType (unqualified_name, TMethod jmethod_signature))) (** interface method reference *) - | ConstInterfaceMethod of (jpath, unqualified_name, jmethod_signature) (* tag = 11 *) -> + | ConstInterfaceMethod (jpath, unqualified_name, jmethod_signature) (* tag = 11 *) -> write_byte ctx.cpool 11; write_ui16 ctx.cpool (const ctx (ConstClass jpath)); write_ui16 ctx.cpool (const ctx (ConstNameAndType (unqualified_name, TMethod jmethod_signature))) @@ -88,16 +165,15 @@ let rec const ctx c = (match classify_float f with | FP_normal | FP_subnormal | FP_zero -> write_real_i32 ctx.cpool (Int32.bits_of_float f) - | FP_infinity when f > 0 -> + | FP_infinite when f > 0.0 -> write_real_i32 ctx.cpool 0x7f800000l - | FP_infinity when f < 0 -> + | FP_infinite -> write_real_i32 ctx.cpool 0xff800000l | FP_nan -> write_real_i32 ctx.cpool 0x7f800001l) | ConstLong i (* tag = 5 *) -> write_byte ctx.cpool 5; write_i64 ctx.cpool i; - ctx.ccount <- ctx.ccount + 1 | ConstDouble d (* tag = 6 *) -> write_byte ctx.cpool 6; write_double ctx.cpool d; @@ -112,7 +188,7 @@ let rec const ctx c = | ConstUtf8 s -> write_byte ctx.cpool 1; write_ui16 ctx.cpool (String.length s); - write_string ctx.cpool (encode_utf8 s) + write_utf8 ctx.cpool s (** invokeDynamic-specific *) | ConstMethodHandle (reference_type, jconstant) (* tag = 15 *) -> write_byte ctx.cpool 15; @@ -126,6 +202,88 @@ let rec const ctx c = write_ui16 ctx.cpool bootstrap_method; write_ui16 ctx.cpool (const ctx (ConstNameAndType(unqualified_name, jsignature))) | ConstUnusable -> assert false); - let ret = ctx.ccount in ctx.ccount <- ret + 1; ret + +let write_const ctx ch cconst = + write_ui16 ch (const ctx cconst) +;; + +let write_formal_type_params ctx ch tparams = + write_byte ch (Char.code '<'); + List.iter (fun (name,ext,impl) -> + write_string ch name; + (match ext with + | None -> () + | Some jsig -> + write_byte ch (Char.code ':'); + write_string ch (encode_sig ctx jsig)); + List.iter (fun jsig -> + write_byte ch (Char.code ':'); + write_string ch (encode_sig ctx jsig) + ) impl + ) tparams; + write_byte ch (Char.code '>'); +;; + +let write_complete_method_signature ctx ch (tparams : jtypes) msig throws = + if tparams <> [] then write_formal_type_params ctx ch tparams; + write_string ch (encode_sig ctx (TMethod(msig))); + if throws <> [] then List.iter (fun jsig -> + write_byte ch (Char.code '^'); + write_string ch (encode_sig ctx jsig) + ) throws +;; + +let write_access_flags ctx ch all_flags flags = + let value = List.fold_left (fun acc flag -> + try + acc lor (Hashtbl.find all_flags flag) + with Not_found -> + error ("Not found flag: " ^ (string_of_int (Obj.magic flag))) + ) 0 flags in + write_ui16 ch value +;; + +let rec write_ann_element ctx ch (name,eval) = + write_const ctx ch (ConstUtf8 name); + write_element_value ctx ch eval + +and write_annotation ctx ch ann = + write_const ctx ch (ConstUtf8 (encode_sig ctx ann.ann_type)); + write_ui16 ch (List.length ann.ann_elements); + List.iter (write_ann_element ctx ch) ann.ann_elements + +and write_element_value ctx ch value = match value with + | ValConst(jsig, cconst) -> (match jsig with + | TObject((["java";"lang"],"String"), []) -> + write_byte ch (Char.code 's') + | TByte | TChar | TDouble | TFloat | TInt | TLong | TShort | TBool -> + write_string ch (encode_sig ctx jsig) + | _ -> + let s = encode_sig ctx jsig in + error ("Invalid signature " ^ s ^ " for constant value")); + write_ui16 ch (const ctx cconst) + | ValEnum(jsig,name) -> + write_byte ch (Char.code 'e'); + write_const ctx ch (ConstUtf8 (encode_sig ctx jsig)); + write_const ctx ch (ConstUtf8 name) + | ValClass(jsig) -> + write_byte ch (Char.code 'c'); + let esig = match jsig with + | TObject(([],"Void"),[]) + | TObject((["java";"lang"],"Void"),[]) -> + "V" + | _ -> + encode_sig ctx jsig + in + write_const ctx ch (ConstUtf8 (esig)) + | ValAnnotation ann -> + write_byte ch (Char.code '@'); + write_annotation ctx ch ann + | ValArray(lvals) -> + write_byte ch (Char.code '['); + write_ui16 ch (List.length lvals); + List.iter (write_element_value ctx ch) lvals +;; + diff --git a/libs/neko/binast.ml b/libs/neko/binast.ml index 26b5cf86..c7339873 100644 --- a/libs/neko/binast.ml +++ b/libs/neko/binast.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open Nast diff --git a/libs/neko/nast.ml b/libs/neko/nast.ml index 90c84a72..c265794b 100644 --- a/libs/neko/nast.ml +++ b/libs/neko/nast.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type pos = { diff --git a/libs/neko/nxml.ml b/libs/neko/nxml.ml index 8dbe61dc..4e373e0b 100644 --- a/libs/neko/nxml.ml +++ b/libs/neko/nxml.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open Nast diff --git a/libs/objsize/Makefile b/libs/objsize/Makefile index 93f3b8eb..756c62a1 100644 --- a/libs/objsize/Makefile +++ b/libs/objsize/Makefile @@ -1,4 +1,4 @@ -CFLAGS = -I . +ALL_CFLAGS = $(CFLAGS) -I . LIBS = OCAMLOPT=ocamlopt OCAMLC=ocamlc @@ -17,10 +17,10 @@ objsize.cmxa: c_objsize.o $(SRC) $(OCAMLOPT) -a -o objsize.cmxa $(LIBS) $(SRC) c_objsize.o: c_objsize.c - $(OCAMLC) $(CFLAGS) c_objsize.c + $(OCAMLC) $(ALL_CFLAGS) c_objsize.c clean: - rm -rf $(wildcard *.cma) $(wildcard *.cmxa) $(wildcard *.cmx) $(wildcard *.cmi) $(wildcard *.cmo) $(wildcard *.obj) $(wildcard *.o) + rm -rf $(wildcard *.cma) $(wildcard *.cmxa) $(wildcard *.cmx) $(wildcard *.cmi) $(wildcard *.cmo) $(wildcard *.obj) $(wildcard *.o) $(wildcard *.a) .PHONY: all bytecode native clean diff --git a/libs/ocamake/ocamake.ml b/libs/ocamake/ocamake.ml index ac0317c9..e0bda81b 100644 --- a/libs/ocamake/ocamake.ml +++ b/libs/ocamake/ocamake.ml @@ -613,7 +613,7 @@ match files with fprint "# http://tech.motion-twin.com"; fprint ".SUFFIXES : .ml .mli .cmo .cmi .cmx .mll .mly"; fprint ""; - fprint ("CFLAGS="^(flatten (!cflags @ p4param::paths))); + fprint ("ALL_CFLAGS= $(CFLAGS) "^(flatten (!cflags @ p4param::paths))); fprint ("LIBS="^(flatten (List.map (fun f -> f.name) libs))); let targets = flatten (List.map (fun f -> f.target) cmos) in (match output_file with @@ -645,9 +645,9 @@ match files with fprint ("\t-@del "^cleanfiles^" 2>NUL"); fprint ""; fprint "# SUFFIXES"; - fprint ".ml.cmo:\n\tocamlc $(CFLAGS) -c $<\n"; - fprint ".ml.cmx:\n\tocamlopt $(CFLAGS) -c $<\n"; - fprint ".mli.cmi:\n\tocamlc $(CFLAGS) $<\n"; + fprint ".ml.cmo:\n\tocamlc $(ALL_CFLAGS) -c $<\n"; + fprint ".ml.cmx:\n\tocamlopt $(ALL_CFLAGS) -c $<\n"; + fprint ".mli.cmi:\n\tocamlc $(ALL_CFLAGS) $<\n"; fprint ".mll.ml:\n\tocamllex $<\n"; fprint ".mly.ml:\n\tocamlyacc $<\n"; close_out out diff --git a/libs/pcre/Makefile b/libs/pcre/Makefile new file mode 100644 index 00000000..8561650a --- /dev/null +++ b/libs/pcre/Makefile @@ -0,0 +1,27 @@ +ALL_CFLAGS = $(CFLAGS) -I pcre +OCAMLOPT=ocamlopt +OCAMLC=ocamlc +SRC = pcre.ml pcre_stubs.c + +all: bytecode native + +bytecode: pcre.cma + +native: pcre.cmxa + +pcre.cma: pcre_stubs.o pcre.ml + $(OCAMLC) -a -o pcre.cma $(LIBS) pcre.ml + +pcre.cmxa: pcre.ml pcre_stubs.o + $(OCAMLOPT) -a -o pcre.cmxa $(LIBS) pcre.ml + +pcre_stubs.o: pcre_stubs.c + $(OCAMLC) $(ALL_CFLAGS) pcre_stubs.c + +clean: + rm -f pcre.cma pcre.cmi pcre.cmx pcre.cmxa pcre.o pcre.obj pcre_stubs.obj pcre_stubs.o + rm -f pcre.a libpcre.a libpcre.lib pcre.cmo + +.PHONY: all bytecode native clean +Makefile: ; +$(SRC): ; diff --git a/libs/pcre/pcre.ml b/libs/pcre/pcre.ml new file mode 100644 index 00000000..59eaad11 --- /dev/null +++ b/libs/pcre/pcre.ml @@ -0,0 +1,1034 @@ +(* + PCRE-OCAML - Perl Compatibility Regular Expressions for OCaml + + Copyright (C) 1999- Markus Mottl + email: markus.mottl@gmail.com + WWW: http://www.ocaml.info + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*) + +(* Public exceptions and their registration with the C runtime *) + +(* Copied from pcre_compat.ml *) +let string_copy str = str + +type error = + | Partial + | BadPartial + | BadPattern of string * int + | BadUTF8 + | BadUTF8Offset + | MatchLimit + | RecursionLimit + | InternalError of string + +exception Error of error +exception Backtrack +exception Regexp_or of string * error + +(* Puts exceptions into global C-variables for fast retrieval *) +external pcre_ocaml_init : unit -> unit = "pcre_ocaml_init" + +(* Registers exceptions with the C runtime and caches polymorphic variants *) +let () = + Callback.register_exception "Pcre.Error" (Error (InternalError "")); + Callback.register_exception "Pcre.Backtrack" Backtrack; + pcre_ocaml_init () + + +(* Compilation and runtime flags and their conversion functions *) + +type icflag = int +type irflag = int + +(* Compilation flags *) + +type cflag = + [ + | `CASELESS + | `MULTILINE + | `DOTALL + | `EXTENDED + | `ANCHORED + | `DOLLAR_ENDONLY + | `EXTRA + | `UNGREEDY + | `UTF8 + | `NO_UTF8_CHECK + | `NO_AUTO_CAPTURE + | `AUTO_CALLOUT + | `FIRSTLINE + ] + +let int_of_cflag = function + | `CASELESS -> 0x0001 + | `MULTILINE -> 0x0002 + | `DOTALL -> 0x0004 + | `EXTENDED -> 0x0008 + | `ANCHORED -> 0x0010 + | `DOLLAR_ENDONLY -> 0x0020 + | `EXTRA -> 0x0040 + | `UNGREEDY -> 0x0200 + | `UTF8 -> 0x0800 + | `NO_AUTO_CAPTURE -> 0x1000 + | `NO_UTF8_CHECK -> 0x2000 + | `AUTO_CALLOUT -> 0x4000 + | `FIRSTLINE -> 0x40000 + +let coll_icflag icflag flag = int_of_cflag flag lor icflag +let cflags flags = List.fold_left coll_icflag 0 flags + +let cflag_of_int = function + | 0x0001 -> `CASELESS + | 0x0002 -> `MULTILINE + | 0x0004 -> `DOTALL + | 0x0008 -> `EXTENDED + | 0x0010 -> `ANCHORED + | 0x0020 -> `DOLLAR_ENDONLY + | 0x0040 -> `EXTRA + | 0x0200 -> `UNGREEDY + | 0x0800 -> `UTF8 + | 0x1000 -> `NO_AUTO_CAPTURE + | 0x2000 -> `NO_UTF8_CHECK + | 0x4000 -> `AUTO_CALLOUT + | 0x40000 -> `FIRSTLINE + | _ -> failwith "Pcre.cflag_list: unknown compilation flag" + +let all_cflags = + [ + 0x0001; 0x0002; 0x0004; 0x0008; 0x0010; 0x0020; + 0x0040; 0x0200; 0x0800; 0x1000; 0x2000; 0x4000; 0x40000; + ] + +let cflag_list icflags = + let coll flag_list flag = + if icflags land flag <> 0 then cflag_of_int flag :: flag_list + else flag_list in + List.fold_left coll [] all_cflags + + +(* Runtime flags *) + +type rflag = + [ + | `ANCHORED + | `NOTBOL + | `NOTEOL + | `NOTEMPTY + | `PARTIAL + ] + +let int_of_rflag = function + | `ANCHORED -> 0x0010 + | `NOTBOL -> 0x0080 + | `NOTEOL -> 0x0100 + | `NOTEMPTY -> 0x0400 + | `PARTIAL -> 0x8000 + +let coll_irflag irflag flag = int_of_rflag flag lor irflag +let rflags flags = List.fold_left coll_irflag 0 flags + +let rflag_of_int = function + | 0x0010 -> `ANCHORED + | 0x0080 -> `NOTBOL + | 0x0100 -> `NOTEOL + | 0x0400 -> `NOTEMPTY + | 0x8000 -> `PARTIAL + | _ -> failwith "Pcre.rflag_list: unknown runtime flag" + +let all_rflags = [0x0010; 0x0080; 0x0100; 0x0400; 0x8000] + +let rflag_list irflags = + let coll flag_list flag = + if irflags land flag <> 0 then rflag_of_int flag :: flag_list + else flag_list in + List.fold_left coll [] all_rflags + + +(* Information on the PCRE-configuration (build-time options) *) + +external pcre_version : unit -> string = "pcre_version_stub" + +external pcre_config_utf8 : unit -> bool = "pcre_config_utf8_stub" "noalloc" + +external pcre_config_newline : + unit -> char = "pcre_config_newline_stub" "noalloc" + +external pcre_config_link_size : + unit -> int = "pcre_config_link_size_stub" "noalloc" + +external pcre_config_match_limit : + unit -> int = "pcre_config_match_limit_stub" "noalloc" + +external pcre_config_match_limit_recursion : + unit -> int = "pcre_config_match_limit_recursion_stub" "noalloc" + +external pcre_config_stackrecurse : + unit -> bool = "pcre_config_stackrecurse_stub" "noalloc" + +let version = pcre_version () +let config_utf8 = pcre_config_utf8 () +let config_newline = pcre_config_newline () +let config_link_size = pcre_config_link_size () +let config_match_limit = pcre_config_match_limit () +let config_match_limit_recursion = pcre_config_match_limit_recursion () +let config_stackrecurse = pcre_config_stackrecurse () + + +(* Information on patterns *) + +type firstbyte_info = + [ `Char of char + | `Start_only + | `ANCHORED ] + +type study_stat = + [ `Not_studied + | `Studied + | `Optimal ] + +type regexp + +external options : regexp -> icflag = "pcre_options_stub" +external size : regexp -> int = "pcre_size_stub" +external studysize : regexp -> int = "pcre_studysize_stub" +external capturecount : regexp -> int = "pcre_capturecount_stub" +external backrefmax : regexp -> int = "pcre_backrefmax_stub" +external namecount : regexp -> int = "pcre_namecount_stub" +external names : regexp -> string array = "pcre_names_stub" +external nameentrysize : regexp -> int = "pcre_nameentrysize_stub" +external firstbyte : regexp -> firstbyte_info = "pcre_firstbyte_stub" +external firsttable : regexp -> string option = "pcre_firsttable_stub" +external lastliteral : regexp -> char option = "pcre_lastliteral_stub" +external study_stat : regexp -> study_stat = "pcre_study_stat_stub" "noalloc" + + +(* Compilation of patterns *) + +type chtables + +external maketables : unit -> chtables = "pcre_maketables_stub" + +(* Internal use only! *) +external pcre_study : regexp -> unit = "pcre_study_stub" + +external compile : + icflag -> chtables option -> string -> regexp = "pcre_compile_stub" + +external get_match_limit : regexp -> int option = "pcre_get_match_limit_stub" + +(* Internal use only! *) +external set_imp_match_limit : + regexp -> int -> regexp = "pcre_set_imp_match_limit_stub" "noalloc" + +external get_match_limit_recursion : + regexp -> int option = "pcre_get_match_limit_recursion_stub" + +(* Internal use only! *) +external set_imp_match_limit_recursion : + regexp -> int -> regexp = "pcre_set_imp_match_limit_recursion_stub" "noalloc" + +let regexp + ?(study = true) ?limit ?limit_recursion + ?(iflags = 0) ?flags ?chtables pat = + let rex = + match flags with + | Some flag_list -> compile (cflags flag_list) chtables pat + | _ -> compile iflags chtables pat + in + if study then pcre_study rex; + let rex = + match limit with + | None -> rex + | Some lim -> set_imp_match_limit rex lim + in + match limit_recursion with + | None -> rex + | Some lim -> set_imp_match_limit_recursion rex lim + +let regexp_or + ?study ?limit ?limit_recursion ?(iflags = 0) ?flags ?chtables pats = + let check pat = + try ignore (regexp ~study:false ~iflags ?flags ?chtables pat) + with Error error -> raise (Regexp_or (pat, error)) + in + List.iter check pats; + let big_pat = + let cnv pat = "(?:" ^ pat ^ ")" in + String.concat "|" (List.rev (List.rev_map cnv pats)) + in + regexp ?study ?limit ?limit_recursion ~iflags ?flags ?chtables big_pat + +let bytes_unsafe_blit_string str str_ofs bts bts_ofs len = + let str_bts = str in + String.unsafe_blit str_bts str_ofs bts bts_ofs len + +let string_unsafe_sub str ofs len = + let res = String.create len in + bytes_unsafe_blit_string str ofs res 0 len; + res + +let quote s = + let len = String.length s in + let buf = String.create (len lsl 1) in + let pos = ref 0 in + for i = 0 to len - 1 do + match String.unsafe_get s i with + | '\\' | '^' | '$' | '.' | '[' | '|' + | '(' | ')' | '?' | '*' | '+' | '{' as c -> + String.unsafe_set buf !pos '\\'; + incr pos; + String.unsafe_set buf !pos c; + incr pos + | c -> String.unsafe_set buf !pos c; incr pos + done; + string_unsafe_sub (buf) 0 !pos + + +(* Matching of patterns and subpattern extraction *) + +(* Default regular expression when none is provided by the user *) +let def_rex = regexp "\\s+" + +type substrings = string * int array + +type callout_data = + { + callout_number : int; + substrings : substrings; + start_match : int; + current_position : int; + capture_top : int; + capture_last : int; + pattern_position : int; + next_item_length : int; + } + +type callout = callout_data -> unit + +let get_subject (subj, _) = subj + +let num_of_subs (_, ovector) = Array.length ovector / 3 + +let get_offset_start ovector str_num = + if str_num < 0 || str_num >= Array.length ovector / 3 then + invalid_arg "Pcre.get_offset_start: illegal offset"; + let offset = str_num lsl 1 in + offset, Array.unsafe_get ovector offset + +let get_substring_aux (subj, ovector) offset start = + if start < 0 then raise Not_found + else + string_unsafe_sub subj start (Array.unsafe_get ovector (offset + 1) - start) + +let get_substring (_, ovector as substrings) str_num = + let offset, start = get_offset_start ovector str_num in + get_substring_aux substrings offset start + +let get_substring_ofs (_subj, ovector) str_num = + let offset, start = get_offset_start ovector str_num in + if start < 0 then raise Not_found + else start, Array.unsafe_get ovector (offset + 1) + +let unsafe_get_substring (_, ovector as substrings) str_num = + let offset = str_num lsl 1 in + try get_substring_aux substrings offset (Array.unsafe_get ovector offset) + with Not_found -> "" + +let get_substrings ?(full_match = true) (_, ovector as substrings) = + if full_match then + Array.init (Array.length ovector / 3) (unsafe_get_substring substrings) + else + let len = (Array.length ovector / 3) - 1 in + Array.init len (fun n -> unsafe_get_substring substrings (n + 1)) + +let unsafe_get_opt_substring (_, ovector as substrings) str_num = + let offset = str_num lsl 1 in + try + let start = Array.unsafe_get ovector offset in + let str = get_substring_aux substrings offset start in + Some str + with Not_found -> None + +let get_opt_substrings ?(full_match = true) (_, ovector as substrings) = + if full_match then + Array.init (Array.length ovector / 3) (unsafe_get_opt_substring substrings) + else + let len = (Array.length ovector / 3) - 1 in + Array.init len (fun n -> unsafe_get_opt_substring substrings (n + 1)) + +external get_stringnumber : + regexp -> string -> int = "pcre_get_stringnumber_stub" + +let get_named_substring rex name substrings = + get_substring substrings (get_stringnumber rex name) + +let get_named_substring_ofs rex name substrings = + get_substring_ofs substrings (get_stringnumber rex name) + +external unsafe_pcre_exec : + irflag -> + regexp -> + pos : int -> + subj_start : int -> + subj : string -> + int array -> + callout option -> + unit = "pcre_exec_stub_bc" "pcre_exec_stub" + +let make_ovector rex = + let subgroups1 = capturecount rex + 1 in + let subgroups2 = subgroups1 lsl 1 in + subgroups2, Array.make (subgroups1 + subgroups2) 0 + +let pcre_exec ?(iflags = 0) ?flags ?(rex = def_rex) ?pat ?(pos = 0) + ?callout subj = + let rex = match pat with Some str -> regexp str | _ -> rex in + let iflags = match flags with Some flags -> rflags flags | _ -> iflags in + let _, ovector = make_ovector rex in + unsafe_pcre_exec iflags rex ~pos ~subj_start:0 ~subj ovector callout; + ovector + +let exec ?iflags ?flags ?rex ?pat ?pos ?callout subj = + subj, pcre_exec ?iflags ?flags ?rex ?pat ?pos ?callout subj + +let next_match ?iflags ?flags ?rex ?pat ?(pos = 0) ?callout (subj, ovector) = + let pos = Array.unsafe_get ovector 1 + pos in + let subj_len = String.length subj in + if pos < 0 || pos > subj_len then + invalid_arg "Pcre.next_match: illegal offset"; + subj, pcre_exec ?iflags ?flags ?rex ?pat ~pos ?callout subj + +let rec copy_lst ar n = function + | [] -> ar + | h :: t -> Array.unsafe_set ar n h; copy_lst ar (n - 1) t + +let exec_all ?(iflags = 0) ?flags ?(rex = def_rex) ?pat ?pos ?callout subj = + let rex = match pat with Some str -> regexp str | _ -> rex in + let iflags = match flags with Some flags -> rflags flags | _ -> iflags in + let (_, ovector as sstrs) = exec ~iflags ~rex ?pos ?callout subj in + let null_flags = iflags lor 0x0400 in + let subj_len = String.length subj in + let rec loop pos (subj, ovector as sstrs) n lst = + let maybe_ovector = + try + let first = Array.unsafe_get ovector 0 in + if first = pos && Array.unsafe_get ovector 1 = pos then + if pos = subj_len then None + else Some (pcre_exec ~iflags:null_flags ~rex ~pos ?callout subj) + else Some (pcre_exec ~iflags ~rex ~pos ?callout subj) + with Not_found -> None in + match maybe_ovector with + | Some ovector -> + let new_pos = Array.unsafe_get ovector 1 in + loop new_pos (subj, ovector) (n + 1) (sstrs :: lst) + | None -> copy_lst (Array.make (n + 1) sstrs) (n - 1) lst in + loop (Array.unsafe_get ovector 1) sstrs 0 [] + +let extract ?iflags ?flags ?rex ?pat ?pos ?full_match ?callout subj = + get_substrings ?full_match (exec ?iflags ?flags ?rex ?pat ?pos ?callout subj) + +let extract_opt ?iflags ?flags ?rex ?pat ?pos ?full_match ?callout subj = + get_opt_substrings + ?full_match (exec ?iflags ?flags ?rex ?pat ?pos ?callout subj) + +let extract_all ?iflags ?flags ?rex ?pat ?pos ?full_match ?callout subj = + let many_sstrs = exec_all ?iflags ?flags ?rex ?pat ?pos ?callout subj in + Array.map (get_substrings ?full_match) many_sstrs + +let extract_all_opt ?iflags ?flags ?rex ?pat ?pos ?full_match ?callout subj = + let many_sstrs = exec_all ?iflags ?flags ?rex ?pat ?pos ?callout subj in + Array.map (get_opt_substrings ?full_match) many_sstrs + +let pmatch ?iflags ?flags ?rex ?pat ?pos ?callout subj = + try ignore (pcre_exec ?iflags ?flags ?rex ?pat ?pos ?callout subj); true + with Not_found -> false + + +(* String substitution *) + +(* Elements of a substitution pattern *) +type subst = + | SubstString of int * int (* Denotes a substring in the substitution *) + | Backref of int (* nth backreference ($0 is program name!) *) + | Match (* The whole matched string *) + | PreMatch (* The string before the match *) + | PostMatch (* The string after the match *) + | LastParenMatch (* The last matched group *) + +(* Information on substitution patterns *) +type substitution = string (* The substitution string *) + * int (* Highest group number of backreferences *) + * bool (* Makes use of "LastParenMatch" *) + * subst list (* The list of substitution elements *) + +(* Only used internally in "subst" *) +exception FoundAt of int + +let zero = Char.code '0' + +let subst str = + let max_br = ref 0 in + let with_lp = ref false in + let lix = String.length str - 1 in + let rec loop acc n = + if lix < n then acc + else + try + for i = n to lix do + if String.unsafe_get str i = '$' then raise (FoundAt i) + done; + SubstString (n, lix - n + 1) :: acc + with FoundAt i -> + if i = lix then SubstString (n, lix - n + 1) :: acc + else + let i1 = i + 1 in + let acc = if n = i then acc else SubstString (n, i - n) :: acc in + match String.unsafe_get str i1 with + | '0'..'9' as c -> + let subpat_nr = ref (Char.code c - zero) in + (try + for j = i1 + 1 to lix do + let c = String.unsafe_get str j in + if c >= '0' && c <= '9' then + subpat_nr := 10 * !subpat_nr + Char.code c - zero + else raise (FoundAt j) + done; + max_br := max !subpat_nr !max_br; + Backref !subpat_nr :: acc + with FoundAt j -> + max_br := max !subpat_nr !max_br; + loop (Backref !subpat_nr :: acc) j) + | '!' -> loop acc (i1 + 1) + | '$' -> loop (SubstString (i1, 1) :: acc) (i1 + 1) + | '&' -> loop (Match :: acc) (i1 + 1) + | '`' -> loop (PreMatch :: acc) (i1 + 1) + | '\'' -> loop (PostMatch :: acc) (i1 + 1) + | '+' -> + with_lp := true; + loop (LastParenMatch :: acc) (i1 + 1) + | _ -> loop acc i1 in + let subst_lst = loop [] 0 in + str, !max_br, !with_lp, subst_lst + +let def_subst = subst "" + +(* Calculates a list of tuples (str, offset, len) which contain + substrings to be copied on substitutions. Internal use only! *) +let calc_trans_lst subgroups2 ovector subj templ subst_lst = + let prefix_len = Array.unsafe_get ovector 0 in + let last = Array.unsafe_get ovector 1 in + let coll (res_len, trans_lst as accu) = + let return_lst (_str, _ix, len as el) = + if len = 0 then accu else res_len + len, el :: trans_lst in + function + | SubstString (ix, len) -> return_lst (templ, ix, len) + | Backref 0 -> + let prog_name = Sys.argv.(0) in + return_lst (prog_name, 0, String.length prog_name) + | Backref n -> + let offset = n lsl 1 in + let start = Array.unsafe_get ovector offset in + let len = Array.unsafe_get ovector (offset + 1) - start in + return_lst (subj, start, len) + | Match -> return_lst (subj, prefix_len, last - prefix_len) + | PreMatch -> return_lst (subj, 0, prefix_len) + | PostMatch -> return_lst (subj, last, String.length subj - last) + | LastParenMatch -> + let subgroups2_2 = subgroups2 - 2 in + let pos = ref subgroups2_2 in + let ix = ref (Array.unsafe_get ovector subgroups2_2) in + while !ix < 0 do + let pos_2 = !pos - 2 in + pos := pos_2; + ix := Array.unsafe_get ovector pos_2 + done; + return_lst (subj, !ix, Array.unsafe_get ovector (!pos + 1) - !ix) in + List.fold_left coll (0, []) subst_lst + +let replace ?(iflags = 0) ?flags ?(rex = def_rex) ?pat + ?(pos = 0) ?(itempl = def_subst) ?templ ?callout subj = + let rex = match pat with Some str -> regexp str | _ -> rex in + let iflags = match flags with Some flags -> rflags flags | _ -> iflags in + let templ, max_br, with_lp, subst_lst = + match templ with + | Some str -> subst str + | _ -> itempl in + let subj_len = String.length subj in + if pos < 0 || pos > subj_len then invalid_arg "Pcre.replace: illegal offset"; + let subgroups2, ovector = make_ovector rex in + let nsubs = (subgroups2 lsr 1) - 1 in + if max_br > nsubs then + failwith "Pcre.replace: backreference denotes nonexistent subpattern"; + if with_lp && nsubs = 0 then failwith "Pcre.replace: no backreferences"; + let rec loop full_len trans_lsts cur_pos = + if + cur_pos > subj_len || + try + unsafe_pcre_exec + iflags rex ~pos:cur_pos ~subj_start:0 ~subj + ovector callout; + false + with Not_found -> true + then + let postfix_len = max (subj_len - cur_pos) 0 in + let left = pos + full_len in + let res = String.create (left + postfix_len) in + bytes_unsafe_blit_string subj 0 res 0 pos; + bytes_unsafe_blit_string subj cur_pos res left postfix_len; + let inner_coll ofs (templ, ix, len) = + bytes_unsafe_blit_string templ ix res ofs len; ofs + len in + let coll ofs (res_len, trans_lst) = + let new_ofs = ofs - res_len in + let _ = List.fold_left inner_coll new_ofs trans_lst in + new_ofs in + let _ = List.fold_left coll left trans_lsts in + res + else + let first = Array.unsafe_get ovector 0 in + let len = first - cur_pos in + let res_len, _ as trans_lst_el = + calc_trans_lst subgroups2 ovector subj templ subst_lst in + let trans_lsts = + if len > 0 then + trans_lst_el :: (len, [(subj, cur_pos, len)]) :: trans_lsts + else trans_lst_el :: trans_lsts in + let full_len = full_len + len + res_len in + let next = first + 1 in + let last = Array.unsafe_get ovector 1 in + if last < next then + if first < subj_len then + let new_trans_lsts = (1, [(subj, cur_pos + len, 1)]) :: trans_lsts in + loop (full_len + 1) new_trans_lsts next + else loop full_len trans_lsts next + else loop full_len trans_lsts last in + loop 0 [] pos + +let qreplace ?(iflags = 0) ?flags ?(rex = def_rex) ?pat + ?(pos = 0) ?(templ = "") ?callout subj = + let rex = match pat with Some str -> regexp str | _ -> rex in + let iflags = match flags with Some flags -> rflags flags | _ -> iflags in + let subj_len = String.length subj in + if pos < 0 || pos > subj_len then invalid_arg "Pcre.qreplace: illegal offset"; + let templ_len = String.length templ in + let _, ovector = make_ovector rex in + let rec loop full_len subst_lst cur_pos = + if + cur_pos > subj_len || + try + unsafe_pcre_exec + iflags rex ~pos:cur_pos ~subj_start:0 ~subj ovector callout; + false + with Not_found -> true + then + let postfix_len = max (subj_len - cur_pos) 0 in + let left = pos + full_len in + let res = String.create (left + postfix_len) in + bytes_unsafe_blit_string subj 0 res 0 pos; + bytes_unsafe_blit_string subj cur_pos res left postfix_len; + let coll ofs = function + | Some (substr, ix, len) -> + let new_ofs = ofs - len in + bytes_unsafe_blit_string substr ix res new_ofs len; + new_ofs + | None -> + let new_ofs = ofs - templ_len in + bytes_unsafe_blit_string templ 0 res new_ofs templ_len; + new_ofs in + let _ = List.fold_left coll left subst_lst in + res + else + let first = Array.unsafe_get ovector 0 in + let len = first - cur_pos in + let subst_lst = + if len > 0 then None :: Some (subj, cur_pos, len) :: subst_lst + else None :: subst_lst in + let last = Array.unsafe_get ovector 1 in + let full_len = full_len + len + templ_len in + let next = first + 1 in + if last < next then + if first < subj_len then + loop (full_len + 1) (Some (subj, cur_pos + len, 1) :: subst_lst) next + else loop full_len subst_lst next + else loop full_len subst_lst last in + loop 0 [] pos + +let substitute_substrings ?(iflags = 0) ?flags ?(rex = def_rex) ?pat + ?(pos = 0) ?callout ~subst subj = + let rex = match pat with Some str -> regexp str | _ -> rex in + let iflags = match flags with Some flags -> rflags flags | _ -> iflags in + let subj_len = String.length subj in + if pos < 0 || pos > subj_len then invalid_arg "Pcre.substitute: illegal offset"; + let _, ovector = make_ovector rex in + let rec loop full_len subst_lst cur_pos = + if + cur_pos > subj_len || + try + unsafe_pcre_exec + iflags rex ~pos:cur_pos ~subj_start:0 ~subj ovector callout; + false + with Not_found -> true + then + let postfix_len = max (subj_len - cur_pos) 0 in + let left = pos + full_len in + let res = String.create (left + postfix_len) in + bytes_unsafe_blit_string subj 0 res 0 pos; + bytes_unsafe_blit_string subj cur_pos res left postfix_len; + let coll ofs (templ, ix, len) = + let new_ofs = ofs - len in + bytes_unsafe_blit_string templ ix res new_ofs len; + new_ofs in + let _ = List.fold_left coll left subst_lst in + res + else + let first = Array.unsafe_get ovector 0 in + let len = first - cur_pos in + let templ = subst (subj, ovector) in + let templ_len = String.length templ in + let subst_lst = + if len > 0 then + (templ, 0, templ_len) :: (subj, cur_pos, len) :: subst_lst + else (templ, 0, templ_len) :: subst_lst in + let last = Array.unsafe_get ovector 1 in + let full_len = full_len + len + templ_len in + let next = first + 1 in + if last < next then + if first < subj_len then + loop (full_len + 1) ((subj, cur_pos + len, 1) :: subst_lst) next + else loop full_len subst_lst next + else loop full_len subst_lst last in + loop 0 [] pos + +let substitute ?iflags ?flags ?rex ?pat ?pos ?callout ~subst:str_subst subj = + let subst (subj, ovector) = + let first = Array.unsafe_get ovector 0 in + let last = Array.unsafe_get ovector 1 in + str_subst (string_unsafe_sub subj first (last - first)) in + substitute_substrings ?iflags ?flags ?rex ?pat ?pos ?callout ~subst subj + +let replace_first ?(iflags = 0) ?flags ?(rex = def_rex) ?pat ?(pos = 0) + ?(itempl = def_subst) ?templ ?callout subj = + let rex = match pat with Some str -> regexp str | _ -> rex in + let iflags = match flags with Some flags -> rflags flags | _ -> iflags in + let templ, max_br, with_lp, subst_lst = + match templ with + | Some str -> subst str + | _ -> itempl in + let subgroups2, ovector = make_ovector rex in + let nsubs = (subgroups2 lsr 1) - 1 in + if max_br > nsubs then + failwith "Pcre.replace_first: backreference denotes nonexistent subpattern"; + if with_lp && nsubs = 0 then failwith "Pcre.replace_first: no backreferences"; + try + unsafe_pcre_exec iflags rex ~pos ~subj_start:0 ~subj ovector callout; + let res_len, trans_lst = + calc_trans_lst subgroups2 ovector subj templ subst_lst in + let first = Array.unsafe_get ovector 0 in + let last = Array.unsafe_get ovector 1 in + let rest = String.length subj - last in + let res = String.create (first + res_len + rest) in + bytes_unsafe_blit_string subj 0 res 0 first; + let coll ofs (templ, ix, len) = + bytes_unsafe_blit_string templ ix res ofs len; ofs + len in + let ofs = List.fold_left coll first trans_lst in + bytes_unsafe_blit_string subj last res ofs rest; + res + with Not_found -> string_copy subj + +let qreplace_first ?(iflags = 0) ?flags ?(rex = def_rex) ?pat + ?(pos = 0) ?(templ = "") ?callout subj = + let rex = match pat with Some str -> regexp str | _ -> rex in + let iflags = match flags with Some flags -> rflags flags | _ -> iflags in + let _, ovector = make_ovector rex in + try + unsafe_pcre_exec iflags rex ~pos ~subj_start:0 ~subj ovector callout; + let first = Array.unsafe_get ovector 0 in + let last = Array.unsafe_get ovector 1 in + let len = String.length templ in + let rest = String.length subj - last in + let postfix_start = first + len in + let res = String.create (postfix_start + rest) in + bytes_unsafe_blit_string subj 0 res 0 first; + bytes_unsafe_blit_string templ 0 res first len; + bytes_unsafe_blit_string subj last res postfix_start rest; + res + with Not_found -> string_copy subj + +let substitute_substrings_first ?(iflags = 0) ?flags ?(rex = def_rex) ?pat + ?(pos = 0) ?callout ~subst subj = + let rex = match pat with Some str -> regexp str | _ -> rex in + let iflags = match flags with Some flags -> rflags flags | _ -> iflags in + let _, ovector = make_ovector rex in + try + unsafe_pcre_exec iflags rex ~pos ~subj_start:0 ~subj ovector callout; + let subj_len = String.length subj in + let prefix_len = Array.unsafe_get ovector 0 in + let last = Array.unsafe_get ovector 1 in + let templ = subst (subj, ovector) in + let postfix_len = subj_len - last in + let templ_len = String.length templ in + let postfix_start = prefix_len + templ_len in + let res = String.create (postfix_start + postfix_len) in + bytes_unsafe_blit_string subj 0 res 0 prefix_len; + bytes_unsafe_blit_string templ 0 res prefix_len templ_len; + bytes_unsafe_blit_string subj last res postfix_start postfix_len; + res + with Not_found -> string_copy subj + +let substitute_first ?iflags ?flags ?rex ?pat ?pos + ?callout ~subst:str_subst subj = + let subst (subj, ovector) = + let first = Array.unsafe_get ovector 0 in + let last = Array.unsafe_get ovector 1 in + str_subst (string_unsafe_sub subj first (last - first)) in + substitute_substrings_first + ?iflags ?flags ?rex ?pat ?pos ?callout ~subst subj + + +(* Splitting *) + +let internal_psplit flags rex max pos callout subj = + let subj_len = String.length subj in + if subj_len = 0 then [] + else if max = 1 then [string_copy subj] + else + let subgroups2, ovector = make_ovector rex in + + (* Adds contents of subgroups to the string accumulator *) + let handle_subgroups strs = + let strs = ref strs in + let i = ref 2 in + while !i < subgroups2 do + let first = Array.unsafe_get ovector !i in + incr i; + let last = Array.unsafe_get ovector !i in + let str = + if first < 0 then "" + else string_unsafe_sub subj first (last - first) in + strs := str :: !strs; incr i + done; + !strs in + + (* Performs the recursive split *) + let rec loop strs cnt pos prematch = + let len = subj_len - pos in + if len < 0 then strs + else + (* Checks termination due to max restriction *) + if cnt = 0 then + if prematch && + try + unsafe_pcre_exec + flags rex ~pos ~subj_start:pos ~subj ovector callout; + true + with Not_found -> false + then + let last = Array.unsafe_get ovector 1 in + let strs = handle_subgroups strs in + string_unsafe_sub subj last (subj_len - last) :: strs + else string_unsafe_sub subj pos len :: strs + + (* Calculates next accumulator state for splitting *) + else + if + try + unsafe_pcre_exec + flags rex ~pos ~subj_start:pos ~subj ovector callout; + false + with Not_found -> true + then string_unsafe_sub subj pos len :: strs + else + let first = Array.unsafe_get ovector 0 in + let last = Array.unsafe_get ovector 1 in + if first = pos then + if last = pos then + let strs = if prematch then handle_subgroups strs else strs in + if len = 0 then "" :: strs + else if + try + unsafe_pcre_exec + (flags lor 0x0410) rex ~pos ~subj_start:pos ~subj + ovector callout; + true + with Not_found -> false + then + let new_strs = handle_subgroups ("" :: strs) in + loop new_strs (cnt - 1) (Array.unsafe_get ovector 1) false + else + let new_strs = string_unsafe_sub subj pos 1 :: strs in + loop new_strs (cnt - 1) (pos + 1) true + else + if prematch then loop (handle_subgroups strs) cnt last false + else loop (handle_subgroups ("" :: strs)) (cnt - 1) last false + else + let new_strs = string_unsafe_sub subj pos (first - pos) :: strs in + loop (handle_subgroups new_strs) (cnt - 1) last false in + loop [] (max - 1) pos false + +let rec strip_all_empty = function "" :: t -> strip_all_empty t | l -> l + +external isspace : char -> bool = "pcre_isspace_stub" "noalloc" + +let rec find_no_space ix len str = + if ix = len || not (isspace (String.unsafe_get str ix)) then ix + else find_no_space (ix + 1) len str + +let split ?(iflags = 0) ?flags ?rex ?pat ?(pos = 0) ?(max = 0) ?callout subj = + let iflags = match flags with Some flags -> rflags flags | _ -> iflags in + let res = + match pat, rex with + | Some str, _ -> internal_psplit iflags (regexp str) max pos callout subj + | _, Some rex -> internal_psplit iflags rex max pos callout subj + | _ -> + (* special case for Perl-splitting semantics *) + let len = String.length subj in + if pos > len || pos < 0 then failwith "Pcre.split: illegal offset"; + let new_pos = find_no_space pos len subj in + internal_psplit iflags def_rex max new_pos callout subj in + List.rev (if max = 0 then strip_all_empty res else res) + +let asplit ?iflags ?flags ?rex ?pat ?pos ?max ?callout subj = + Array.of_list (split ?iflags ?flags ?rex ?pat ?pos ?max ?callout subj) + + +(* Full splitting *) + +type split_result = Text of string + | Delim of string + | Group of int * string + | NoGroup + +let rec strip_all_empty_full = function + | Delim _ :: rest -> strip_all_empty_full rest + | l -> l + +let full_split ?(iflags = 0) ?flags ?(rex = def_rex) ?pat + ?(pos = 0) ?(max = 0) ?callout subj = + let rex = match pat with Some str -> regexp str | _ -> rex in + let iflags = match flags with Some flags -> rflags flags | _ -> iflags in + let subj_len = String.length subj in + if subj_len = 0 then [] + else if max = 1 then [Text (string_copy subj)] + else + let subgroups2, ovector = make_ovector rex in + + (* Adds contents of subgroups to the string accumulator *) + let handle_subgroups strs = + let strs = ref strs in + let i = ref 2 in + while !i < subgroups2 do + let group_nr = !i lsr 1 in + let first = Array.unsafe_get ovector !i in + incr i; + let last = Array.unsafe_get ovector !i in + let str = + if first < 0 then NoGroup + else + let group_str = string_unsafe_sub subj first (last - first) in + Group (group_nr, group_str) in + strs := str :: !strs; incr i + done; + !strs in + + (* Performs the recursive split *) + let rec loop strs cnt pos prematch = + let len = subj_len - pos in + if len < 0 then strs + else + (* Checks termination due to max restriction *) + if cnt = 0 then + if prematch && + try + unsafe_pcre_exec + iflags rex ~pos ~subj_start:pos ~subj ovector callout; + true + with Not_found -> false + then + let first = Array.unsafe_get ovector 0 in + let last = Array.unsafe_get ovector 1 in + let delim = Delim (string_unsafe_sub subj first (last - first)) in + Text (string_unsafe_sub subj last (subj_len - last)) + :: handle_subgroups (delim :: strs) + else + if len = 0 then strs + else Text (string_unsafe_sub subj pos len) :: strs + + (* Calculates next accumulator state for splitting *) + else + if + try + unsafe_pcre_exec + iflags rex ~pos ~subj_start:pos ~subj ovector callout; + false + with Not_found -> true + then + if len = 0 then strs + else Text (string_unsafe_sub subj pos len) :: strs + else + let first = Array.unsafe_get ovector 0 in + let last = Array.unsafe_get ovector 1 in + if first = pos then + if last = pos then + if len = 0 then handle_subgroups (Delim "" :: strs) + else + let empty_groups = handle_subgroups [] in + if + try + unsafe_pcre_exec + (iflags lor 0x0410) rex ~pos ~subj_start:pos ~subj + ovector callout; + true + with Not_found -> false + then + let first = Array.unsafe_get ovector 0 in + let last = Array.unsafe_get ovector 1 in + let delim = + Delim (string_unsafe_sub subj first (last - first)) in + let new_strs = + handle_subgroups ( + delim :: (if prematch then strs + else empty_groups @ (Delim "" :: strs))) in + loop new_strs (cnt - 1) last false + else + let new_strs = + Text (string_unsafe_sub subj pos 1) + :: empty_groups @ Delim "" :: strs in + loop new_strs (cnt - 1) (pos + 1) true + else + let delim = + Delim (string_unsafe_sub subj first (last - first)) in + loop (handle_subgroups (delim :: strs)) cnt last false + else + let delim = Delim (string_unsafe_sub subj first (last - first)) in + let pre_strs = + Text (string_unsafe_sub subj pos (first - pos)) :: strs in + loop + (handle_subgroups (delim :: pre_strs)) (cnt - 1) last false in + let res = loop [] (max - 1) pos true in + List.rev (if max = 0 then strip_all_empty_full res else res) + + +(* Additional convenience functions useful in combination with this library *) + +let foreach_line ?(ic = stdin) f = + try while true do f (input_line ic) done with End_of_file -> () + +let foreach_file filenames f = + let do_with_file filename = + let file = open_in filename in + try f filename file; close_in file + with exn -> close_in file; raise exn in + List.iter do_with_file filenames diff --git a/libs/pcre/pcre_stubs.c b/libs/pcre/pcre_stubs.c new file mode 100644 index 00000000..733831d8 --- /dev/null +++ b/libs/pcre/pcre_stubs.c @@ -0,0 +1,737 @@ +/* + PCRE-OCAML - Perl Compatibility Regular Expressions for OCaml + + Copyright (C) 1999- Markus Mottl + email: markus.mottl@gmail.com + WWW: http://www.ocaml.info + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#if defined(_WIN32) +# define snprintf _snprintf +# if defined(_DLL) +# define PCREextern __declspec(dllexport) +# else +# define PCREextern +# endif +#endif + +#if _WIN64 + typedef long long *ovec_dst_ptr; +#else + typedef long *ovec_dst_ptr; +#endif + +#if __GNUC__ >= 3 +# define inline inline __attribute__ ((always_inline)) +# define __unused __attribute__ ((unused)) +#else +# define __unused +# define inline +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "pcre.h" + +/* Error codes as defined for pcre 7.9, undefined in pcre 4.5 */ +#ifndef PCRE_ERROR_PARTIAL +#define PCRE_ERROR_PARTIAL (-12) +#endif +#ifndef PCRE_ERROR_BADPARTIAL +#define PCRE_ERROR_BADPARTIAL (-13) +#endif +#ifndef PCRE_ERROR_RECURSIONLIMIT +#define PCRE_ERROR_RECURSIONLIMIT (-21) +#endif + +typedef const unsigned char *chartables; /* Type of chartable sets */ + +/* Contents of callout data */ +struct cod { + long subj_start; /* Start of subject string */ + value *v_substrings_p; /* Pointer to substrings matched so far */ + value *v_cof_p; /* Pointer to callout function */ + value v_exn; /* Possible exception raised by callout function */ +}; + +/* Cache for exceptions */ +static value *pcre_exc_Error = NULL; /* Exception [Error] */ +static value *pcre_exc_Backtrack = NULL; /* Exception [Backtrack] */ + +/* Cache for polymorphic variants */ +static value var_Start_only; /* Variant [`Start_only] */ +static value var_ANCHORED; /* Variant [`ANCHORED] */ +static value var_Char; /* Variant [`Char char] */ +static value var_Not_studied; /* Variant [`Not_studied] */ +static value var_Studied; /* Variant [`Studied] */ +static value var_Optimal; /* Variant [`Optimal] */ + +static value None = Val_int(0); + +/* Converts subject offsets from C-integers to OCaml-Integers. + + This is a bit tricky, because there are 32- and 64-bit platforms around + and OCaml chooses the larger possibility for representing integers when + available (also in arrays) - not so the PCRE! +*/ +static inline void copy_ovector( + long subj_start, const int *ovec_src, ovec_dst_ptr ovec_dst, int subgroups2) +{ + if (subj_start == 0) + while (subgroups2--) { + *ovec_dst = Val_int(*ovec_src); + --ovec_src; --ovec_dst; + } + else + while (subgroups2--) { + *ovec_dst = Val_long(*ovec_src + subj_start); + --ovec_src; --ovec_dst; + } +} + +/* Callout handler */ +static int pcre_callout_handler(pcre_callout_block* cb) +{ + struct cod *cod = (struct cod *) cb->callout_data; + + if (cod != NULL) { + /* Callout is available */ + value v_res; + + /* Set up parameter array */ + value v_callout_data = caml_alloc_small(8, 0); + + const value v_substrings = *cod->v_substrings_p; + + const int capture_top = cb->capture_top; + int subgroups2 = capture_top << 1; + const int subgroups2_1 = subgroups2 - 1; + + const int *ovec_src = cb->offset_vector + subgroups2_1; + ovec_dst_ptr ovec_dst = &Field(Field(v_substrings, 1), 0) + subgroups2_1; + long subj_start = cod->subj_start; + + copy_ovector(subj_start, ovec_src, ovec_dst, subgroups2); + + Field(v_callout_data, 0) = Val_int(cb->callout_number); + Field(v_callout_data, 1) = v_substrings; + Field(v_callout_data, 2) = Val_int(cb->start_match + subj_start); + Field(v_callout_data, 3) = Val_int(cb->current_position + subj_start); + Field(v_callout_data, 4) = Val_int(capture_top); + Field(v_callout_data, 5) = Val_int(cb->capture_last); + Field(v_callout_data, 6) = Val_int(cb->pattern_position); + Field(v_callout_data, 7) = Val_int(cb->next_item_length); + + /* Perform callout */ + v_res = caml_callback_exn(*cod->v_cof_p, v_callout_data); + + if (Is_exception_result(v_res)) { + /* Callout raised an exception */ + const value v_exn = Extract_exception(v_res); + if (Field(v_exn, 0) == *pcre_exc_Backtrack) return 1; + cod->v_exn = v_exn; + return PCRE_ERROR_CALLOUT; + } + } + + return 0; +} + +/* Fetchs the named OCaml-values + caches them and + calculates + caches the variant hash values */ +CAMLprim value pcre_ocaml_init(value __unused v_unit) +{ + pcre_exc_Error = caml_named_value("Pcre.Error"); + pcre_exc_Backtrack = caml_named_value("Pcre.Backtrack"); + + var_Start_only = caml_hash_variant("Start_only"); + var_ANCHORED = caml_hash_variant("ANCHORED"); + var_Char = caml_hash_variant("Char"); + var_Not_studied = caml_hash_variant("Not_studied"); + var_Studied = caml_hash_variant("Studied"); + var_Optimal = caml_hash_variant("Optimal"); + + pcre_callout = &pcre_callout_handler; + + return Val_unit; +} + +/* Finalizing deallocation function for chartable sets */ +static void pcre_dealloc_tables(value v_table) +{ (pcre_free)((void *) Field(v_table, 1)); } + +/* Finalizing deallocation function for compiled regular expressions */ +static void pcre_dealloc_regexp(value v_rex) +{ + void *extra = (void *) Field(v_rex, 2); + (pcre_free)((void *) Field(v_rex, 1)); + if (extra != NULL) +#ifdef PCRE_STUDY_JIT_COMPILE + pcre_free_study(extra); +#else + pcre_free(extra); +#endif +} + +/* Makes OCaml-string from PCRE-version */ +CAMLprim value pcre_version_stub(value __unused v_unit) +{ + return caml_copy_string((char *) pcre_version()); +} + + +/* Raising exceptions */ + +static inline void raise_pcre_error(value v_arg) Noreturn; +static inline void raise_partial() Noreturn; +static inline void raise_bad_partial() Noreturn; +static inline void raise_bad_utf8() Noreturn; +static inline void raise_bad_utf8_offset() Noreturn; +static inline void raise_match_limit() Noreturn; +static inline void raise_recursion_limit() Noreturn; +static inline void raise_bad_pattern(const char *msg, int pos) Noreturn; +static inline void raise_internal_error(char *msg) Noreturn; + +static inline void raise_pcre_error(value v_arg) +{ caml_raise_with_arg(*pcre_exc_Error, v_arg); } + +static inline void raise_partial() { raise_pcre_error(Val_int(0)); } +static inline void raise_bad_partial() { raise_pcre_error(Val_int(1)); } +static inline void raise_bad_utf8() { raise_pcre_error(Val_int(2)); } +static inline void raise_bad_utf8_offset() { raise_pcre_error(Val_int(3)); } +static inline void raise_match_limit() { raise_pcre_error(Val_int(4)); } +static inline void raise_recursion_limit() { raise_pcre_error(Val_int(5)); } + +static inline void raise_bad_pattern(const char *msg, int pos) +{ + CAMLparam0(); + CAMLlocal1(v_msg); + value v_arg; + v_msg = caml_copy_string(msg); + v_arg = caml_alloc_small(2, 0); + Field(v_arg, 0) = v_msg; + Field(v_arg, 1) = Val_int(pos); + raise_pcre_error(v_arg); + CAMLnoreturn; +} + +static inline void raise_internal_error(char *msg) +{ + CAMLparam0(); + CAMLlocal1(v_msg); + value v_arg; + v_msg = caml_copy_string(msg); + v_arg = caml_alloc_small(1, 1); + Field(v_arg, 0) = v_msg; + raise_pcre_error(v_arg); + CAMLnoreturn; +} + +/* PCRE pattern compilation */ + +/* Makes compiled regular expression from compilation options, an optional + value of chartables and the pattern string */ +CAMLprim value pcre_compile_stub(value v_opt, value v_tables, value v_pat) +{ + value v_rex; /* Final result -> value of type [regexp] */ + const char *error = NULL; /* pointer to possible error message */ + int error_ofs = 0; /* offset in the pattern at which error occurred */ + + /* If v_tables = [None], then pointer to tables is NULL, otherwise + set it to the appropriate value */ + chartables tables = + (v_tables == None) ? NULL : (chartables) Field(Field(v_tables, 0), 1); + + /* Compiles the pattern */ + pcre *regexp = pcre_compile(String_val(v_pat), Int_val(v_opt), &error, + &error_ofs, tables); + + /* Raises appropriate exception with [BadPattern] if the pattern + could not be compiled */ + if (regexp == NULL) raise_bad_pattern(error, error_ofs); + + /* GC will do a full cycle every 1_000_000 regexp allocations (a typical + regexp probably consumes less than 100 bytes -> maximum of 100_000_000 + bytes unreclaimed regexps) */ + v_rex = caml_alloc_final(4, pcre_dealloc_regexp, 1, 1000000); + + /* Field[1]: compiled regular expression (Field[0] is finalizing + function! See above!) */ + Field(v_rex, 1) = (value) regexp; + + /* Field[2]: extra information about regexp when it has been studied + successfully */ + Field(v_rex, 2) = (value) NULL; + + /* Field[3]: If 0 -> regexp has not yet been studied + 1 -> regexp has already been studied */ + Field(v_rex, 3) = 0; + + return v_rex; +} + +/* Studies a regexp */ +CAMLprim value pcre_study_stub(value v_rex) +{ + /* If it has not yet been studied */ + if (! (int) Field(v_rex, 3)) { + const char *error = NULL; + pcre_extra *extra = pcre_study((pcre *) Field(v_rex, 1), 0, &error); + if (error != NULL) caml_invalid_argument((char *) error); + Field(v_rex, 2) = (value) extra; + Field(v_rex, 3) = Val_int(1); + } + return v_rex; +} + +/* Sets a match limit recursion for a regular expression imperatively */ +CAMLprim value pcre_set_imp_match_limit_recursion_stub(value v_rex, value v_lim) +{ + pcre_extra *extra = (pcre_extra *) Field(v_rex, 2); + if (extra == NULL) { + extra = pcre_malloc(sizeof(pcre_extra)); + extra->flags = PCRE_EXTRA_MATCH_LIMIT_RECURSION; + Field(v_rex, 2) = (value) extra; + } else { + unsigned long *flags_ptr = &extra->flags; + *flags_ptr = PCRE_EXTRA_MATCH_LIMIT_RECURSION | *flags_ptr; + } + extra->match_limit_recursion = Int_val(v_lim); + return v_rex; +} + +/* Gets the match limit recursion of a regular expression if it exists */ +CAMLprim value pcre_get_match_limit_recursion_stub(value v_rex) +{ + pcre_extra *extra = (pcre_extra *) Field(v_rex, 2); + if (extra == NULL) return None; + if (extra->flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) { + value v_lim = Val_int(extra->match_limit_recursion); + value v_res = caml_alloc_small(1, 0); + Field(v_res, 0) = v_lim; + return v_res; + } + return None; +} + +/* Sets a match limit for a regular expression imperatively */ +CAMLprim value pcre_set_imp_match_limit_stub(value v_rex, value v_lim) +{ + pcre_extra *extra = (pcre_extra *) Field(v_rex, 2); + if (extra == NULL) { + extra = pcre_malloc(sizeof(pcre_extra)); + extra->flags = PCRE_EXTRA_MATCH_LIMIT; + Field(v_rex, 2) = (value) extra; + } else { + unsigned long *flags_ptr = &extra->flags; + *flags_ptr = PCRE_EXTRA_MATCH_LIMIT | *flags_ptr; + } + extra->match_limit = Int_val(v_lim); + return v_rex; +} + +/* Gets the match limit of a regular expression if it exists */ +CAMLprim value pcre_get_match_limit_stub(value v_rex) +{ + pcre_extra *extra = (pcre_extra *) Field(v_rex, 2); + if (extra == NULL) return None; + if (extra->flags & PCRE_EXTRA_MATCH_LIMIT) { + value v_lim = Val_int(extra->match_limit); + value v_res = caml_alloc_small(1, 0); + Field(v_res, 0) = v_lim; + return v_res; + } + return None; +} + +/* Performs the call to the pcre_fullinfo function */ +static inline int pcre_fullinfo_stub(value v_rex, int what, void *where) +{ + return pcre_fullinfo((pcre *) Field(v_rex, 1), (pcre_extra *) Field(v_rex, 2), + what, where); +} + +/* Some stubs for info-functions */ + +/* Generic macro for getting integer results from pcre_fullinfo */ +#define make_info(tp, cnv, name, option) \ + CAMLprim value pcre_##name##_stub(value v_rex) \ + { \ + tp options; \ + const int ret = pcre_fullinfo_stub(v_rex, PCRE_INFO_##option, &options); \ + if (ret != 0) raise_internal_error("pcre_##name##_stub"); \ + return cnv(options); \ + } + +make_info(unsigned long, Val_long, options, OPTIONS) +make_info(size_t, Val_long, size, SIZE) +make_info(size_t, Val_long, studysize, STUDYSIZE) +make_info(int, Val_int, capturecount, CAPTURECOUNT) +make_info(int, Val_int, backrefmax, BACKREFMAX) +make_info(int, Val_int, namecount, NAMECOUNT) +make_info(int, Val_int, nameentrysize, NAMEENTRYSIZE) + +CAMLprim value pcre_firstbyte_stub(value v_rex) +{ + int firstbyte; + const int ret = pcre_fullinfo_stub(v_rex, PCRE_INFO_FIRSTBYTE, &firstbyte); + + if (ret != 0) raise_internal_error("pcre_firstbyte_stub"); + + switch (firstbyte) { + case -1 : return var_Start_only; break; /* [`Start_only] */ + case -2 : return var_ANCHORED; break; /* [`ANCHORED] */ + default : + if (firstbyte < 0 ) /* Should not happen */ + raise_internal_error("pcre_firstbyte_stub"); + else { + value v_firstbyte; + /* Allocates the non-constant constructor [`Char of char] and fills + in the appropriate value */ + v_firstbyte = caml_alloc_small(2, 0); + Field(v_firstbyte, 0) = var_Char; + Field(v_firstbyte, 1) = Val_int(firstbyte); + return v_firstbyte; + } + } +} + +CAMLprim value pcre_firsttable_stub(value v_rex) +{ + const unsigned char *ftable; + + int ret = + pcre_fullinfo_stub(v_rex, PCRE_INFO_FIRSTTABLE, (void *) &ftable); + + if (ret != 0) raise_internal_error("pcre_firsttable_stub"); + + if (ftable == NULL) return None; + else { + value v_res, v_res_str; + char *ptr; + int i; + + Begin_roots1(v_rex); + v_res_str = caml_alloc_string(32); + End_roots(); + + ptr = String_val(v_res_str); + for (i = 0; i <= 31; ++i) { *ptr = *ftable; ++ptr; ++ftable; } + + Begin_roots1(v_res_str); + /* Allocates [Some string] from firsttable */ + v_res = caml_alloc_small(1, 0); + End_roots(); + + Field(v_res, 0) = v_res_str; + + return v_res; + } +} + +CAMLprim value pcre_lastliteral_stub(value v_rex) +{ + int lastliteral; + const int ret = pcre_fullinfo_stub(v_rex, PCRE_INFO_LASTLITERAL, + &lastliteral); + + if (ret != 0) raise_internal_error("pcre_lastliteral_stub"); + + if (lastliteral == -1) return None; + if (lastliteral < 0) raise_internal_error("pcre_lastliteral_stub"); + else { + /* Allocates [Some char] */ + value v_res = caml_alloc_small(1, 0); + Field(v_res, 0) = Val_int(lastliteral); + return v_res; + } +} + +CAMLprim value pcre_study_stat_stub(value v_rex) +{ + /* Generates the appropriate constant constructor [`Optimal] or + [`Studied] if regexp has already been studied */ + if (Field(v_rex, 3)) + return ((pcre_extra *) Field(v_rex, 2) == NULL) ? var_Optimal : var_Studied; + + return var_Not_studied; /* otherwise [`Not_studied] */ +} + +static inline void handle_exec_error(char *loc, const int ret) Noreturn; + +static inline void handle_exec_error(char *loc, const int ret) +{ + switch (ret) { + /* Dedicated exceptions */ + case PCRE_ERROR_NOMATCH : caml_raise_not_found(); + case PCRE_ERROR_PARTIAL : raise_partial(); + case PCRE_ERROR_MATCHLIMIT : raise_match_limit(); + case PCRE_ERROR_BADPARTIAL : raise_bad_partial(); + case PCRE_ERROR_BADUTF8 : raise_bad_utf8(); + case PCRE_ERROR_BADUTF8_OFFSET : raise_bad_utf8_offset(); + case PCRE_ERROR_RECURSIONLIMIT : raise_recursion_limit(); + /* Unknown error */ + default : { + char err_buf[100]; + snprintf(err_buf, 100, "%s: unhandled PCRE error code: %d", loc, ret); + raise_internal_error(err_buf); + } + } +} + +static inline void handle_pcre_exec_result( + int *ovec, value v_ovec, long ovec_len, long subj_start, int ret) +{ + ovec_dst_ptr ocaml_ovec = (ovec_dst_ptr) &Field(v_ovec, 0); + const int subgroups2 = ret * 2; + const int subgroups2_1 = subgroups2 - 1; + const int *ovec_src = ovec + subgroups2_1; + ovec_dst_ptr ovec_clear_stop = ocaml_ovec + (ovec_len * 2) / 3; + ovec_dst_ptr ovec_dst = ocaml_ovec + subgroups2_1; + copy_ovector(subj_start, ovec_src, ovec_dst, subgroups2); + while (++ovec_dst < ovec_clear_stop) *ovec_dst = -1; +} + +/* Executes a pattern match with runtime options, a regular expression, a + matching position, the start of the the subject string, a subject string, + a number of subgroup offsets, an offset vector and an optional callout + function */ +CAMLprim value pcre_exec_stub(value v_opt, value v_rex, value v_pos, + value v_subj_start, value v_subj, + value v_ovec, value v_maybe_cof) +{ + int ret; + long + pos = Long_val(v_pos), + len = caml_string_length(v_subj), + subj_start = Long_val(v_subj_start); + long ovec_len = Wosize_val(v_ovec); + + if (pos > len || pos < subj_start) + caml_invalid_argument("Pcre.pcre_exec_stub: illegal position"); + + if (subj_start > len || subj_start < 0) + caml_invalid_argument("Pcre.pcre_exec_stub: illegal subject start"); + + pos -= subj_start; + len -= subj_start; + + { + const pcre *code = (pcre *) Field(v_rex, 1); /* Compiled pattern */ + const pcre_extra *extra = (pcre_extra *) Field(v_rex, 2); /* Extra info */ + const char *ocaml_subj = + String_val(v_subj) + subj_start; /* Subject string */ + const int opt = Int_val(v_opt); /* Runtime options */ + + /* Special case when no callout functions specified */ + if (v_maybe_cof == None) { + int *ovec = (int *) &Field(v_ovec, 0); + + /* Performs the match */ + ret = pcre_exec(code, extra, ocaml_subj, len, pos, opt, ovec, ovec_len); + + if (ret < 0) handle_exec_error("pcre_exec_stub", ret); + else handle_pcre_exec_result(ovec, v_ovec, ovec_len, subj_start, ret); + } + + /* There are callout functions */ + else { + value v_cof = Field(v_maybe_cof, 0); + value v_substrings; + char *subj = caml_stat_alloc(sizeof(char) * len); + int *ovec = caml_stat_alloc(sizeof(int) * ovec_len); + struct cod cod = { 0, (value *) NULL, (value *) NULL, (value) NULL }; + struct pcre_extra new_extra = +#ifdef PCRE_EXTRA_MATCH_LIMIT_RECURSION +# ifdef PCRE_EXTRA_MARK +# ifdef PCRE_EXTRA_EXECUTABLE_JIT + { PCRE_EXTRA_CALLOUT_DATA, NULL, 0, NULL, NULL, 0, NULL, NULL }; +# else + { PCRE_EXTRA_CALLOUT_DATA, NULL, 0, NULL, NULL, 0, NULL }; +# endif +# else + { PCRE_EXTRA_CALLOUT_DATA, NULL, 0, NULL, NULL, 0 }; +# endif +#else + { PCRE_EXTRA_CALLOUT_DATA, NULL, 0, NULL, NULL }; +#endif + + cod.subj_start = subj_start; + memcpy(subj, ocaml_subj, len); + + Begin_roots4(v_rex, v_cof, v_substrings, v_ovec); + Begin_roots1(v_subj); + v_substrings = caml_alloc_small(2, 0); + End_roots(); + + Field(v_substrings, 0) = v_subj; + Field(v_substrings, 1) = v_ovec; + + cod.v_substrings_p = &v_substrings; + cod.v_cof_p = &v_cof; + new_extra.callout_data = &cod; + + if (extra == NULL) { + ret = pcre_exec(code, &new_extra, subj, len, pos, opt, ovec, + ovec_len); + } + else { + new_extra.flags = PCRE_EXTRA_CALLOUT_DATA | extra->flags; + new_extra.study_data = extra->study_data; + new_extra.match_limit = extra->match_limit; + new_extra.tables = extra->tables; +#ifdef PCRE_EXTRA_MATCH_LIMIT_RECURSION + new_extra.match_limit_recursion = extra->match_limit_recursion; +#endif + + ret = pcre_exec(code, &new_extra, subj, len, pos, opt, ovec, + ovec_len); + } + + caml_stat_free(subj); + End_roots(); + + if (ret < 0) { + caml_stat_free(ovec); + if (ret == PCRE_ERROR_CALLOUT) caml_raise(cod.v_exn); + else handle_exec_error("pcre_exec_stub(callout)", ret); + } else { + handle_pcre_exec_result(ovec, v_ovec, ovec_len, subj_start, ret); + caml_stat_free(ovec); + } + } + } + + return Val_unit; +} + +/* Byte-code hook for pcre_exec_stub + Needed, because there are more than 5 arguments */ +CAMLprim value pcre_exec_stub_bc(value *argv, int __unused argn) +{ + return pcre_exec_stub(argv[0], argv[1], argv[2], argv[3], + argv[4], argv[5], argv[6]); +} + +/* Generates a new set of chartables for the current locale (see man + page of PCRE */ +CAMLprim value pcre_maketables_stub(value __unused v_unit) +{ + /* GC will do a full cycle every 1_000_000 table set allocations (one + table set consumes 864 bytes -> maximum of 864_000_000 bytes unreclaimed + table sets) */ + const value v_res = caml_alloc_final(2, pcre_dealloc_tables, 1, 1000000); + Field(v_res, 1) = (value) pcre_maketables(); + return v_res; +} + +/* Wraps around the isspace-function */ +CAMLprim value pcre_isspace_stub(value v_c) +{ + return Val_bool(isspace(Int_val(v_c))); +} + +/* Returns number of substring associated with a name */ +CAMLprim value pcre_get_stringnumber_stub(value v_rex, value v_name) +{ + const int ret = pcre_get_stringnumber((pcre *) Field(v_rex, 1), + String_val(v_name)); + if (ret == PCRE_ERROR_NOSUBSTRING) + caml_invalid_argument("Named string not found"); + + return Val_int(ret); +} + +/* Returns array of names of named substrings in a regexp */ +CAMLprim value pcre_names_stub(value v_rex) +{ + CAMLparam0(); + CAMLlocal1(v_res); + int name_count; + int entry_size; + const char *tbl_ptr; + int i; + + int ret = pcre_fullinfo_stub(v_rex, PCRE_INFO_NAMECOUNT, &name_count); + if (ret != 0) raise_internal_error("pcre_names_stub: namecount"); + + ret = pcre_fullinfo_stub(v_rex, PCRE_INFO_NAMEENTRYSIZE, &entry_size); + if (ret != 0) raise_internal_error("pcre_names_stub: nameentrysize"); + + ret = pcre_fullinfo_stub(v_rex, PCRE_INFO_NAMETABLE, &tbl_ptr); + if (ret != 0) raise_internal_error("pcre_names_stub: nametable"); + + v_res = caml_alloc(name_count, 0); + + for (i = 0; i < name_count; ++i) { + value v_name = caml_copy_string(tbl_ptr + 2); + Store_field(v_res, i, v_name); + tbl_ptr += entry_size; + } + + CAMLreturn(v_res); +} + +/* Generic stub for getting integer results from pcre_config */ +static inline int pcre_config_int(int what) +{ + int ret; + pcre_config(what, (void *) &ret); + return ret; +} + +/* Generic stub for getting long integer results from pcre_config */ +static inline int pcre_config_long(int what) +{ + long ret; + pcre_config(what, (void *) &ret); + return ret; +} + +/* Some stubs for config-functions */ + +/* Returns boolean indicating UTF8-support */ +CAMLprim value pcre_config_utf8_stub(value __unused v_unit) +{ return Val_bool(pcre_config_int(PCRE_CONFIG_UTF8)); } + +/* Returns character used as newline */ +CAMLprim value pcre_config_newline_stub(value __unused v_unit) +{ return Val_int(pcre_config_int(PCRE_CONFIG_NEWLINE)); } + +/* Returns number of bytes used for internal linkage of regular expressions */ +CAMLprim value pcre_config_link_size_stub(value __unused v_unit) +{ return Val_int(pcre_config_int(PCRE_CONFIG_LINK_SIZE)); } + +/* Returns boolean indicating use of stack recursion */ +CAMLprim value pcre_config_stackrecurse_stub(value __unused v_unit) +{ return Val_bool(pcre_config_int(PCRE_CONFIG_STACKRECURSE)); } + +/* Returns default limit for calls to internal matching function */ +CAMLprim value pcre_config_match_limit_stub(value __unused v_unit) +{ return Val_long(pcre_config_long(PCRE_CONFIG_MATCH_LIMIT)); } + +/* Returns default limit for calls to internal matching function */ +CAMLprim value pcre_config_match_limit_recursion_stub(value __unused v_unit) +{ return Val_long(pcre_config_long(PCRE_CONFIG_MATCH_LIMIT_RECURSION)); } diff --git a/libs/swflib/LICENSE b/libs/swflib/LICENSE index 5b6e7c66..ecbc0593 100644 --- a/libs/swflib/LICENSE +++ b/libs/swflib/LICENSE @@ -1,12 +1,12 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to +the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not @@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - - GNU GENERAL PUBLIC LICENSE + + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions: License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) - + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in @@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - + 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is @@ -225,7 +225,7 @@ impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - + 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License @@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -303,10 +303,9 @@ the "copyright" line and a pointer to where the full notice is found. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. @@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names: This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. \ No newline at end of file diff --git a/libs/swflib/Makefile b/libs/swflib/Makefile index f299a1e7..ed80b6f5 100644 --- a/libs/swflib/Makefile +++ b/libs/swflib/Makefile @@ -4,7 +4,7 @@ OCAMLOPT=ocamlopt OCAMLC=ocamlc .SUFFIXES : .ml .mli .cmo .cmi .cmx .mll .mly -CFLAGS= -I ../extlib -I ../extc -g +ALL_CFLAGS= $(CFLAGS) -I ../extlib -I ../extc -g LIBS= SRC=actionScript.ml as3hl.mli as3.mli png.ml swflib.sln swf.ml swfPic.ml as3code.ml as3hlparse.ml as3parse.ml png.mli swfParser.ml @@ -61,13 +61,13 @@ clean: # SUFFIXES .ml.cmo: - $(OCAMLC) $(CFLAGS) -c $< + $(OCAMLC) $(ALL_CFLAGS) -c $< .ml.cmx: - $(OCAMLOPT) $(CFLAGS) -c $< + $(OCAMLOPT) $(ALL_CFLAGS) -c $< .mli.cmi: - $(OCAMLC) $(CFLAGS) $< + $(OCAMLC) $(ALL_CFLAGS) $< .mll.ml: ocamllex $< diff --git a/libs/swflib/actionScript.ml b/libs/swflib/actionScript.ml index f8d9f040..69ad6f5e 100644 --- a/libs/swflib/actionScript.ml +++ b/libs/swflib/actionScript.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open Swf open IO diff --git a/libs/swflib/as3.mli b/libs/swflib/as3.mli index ce8f2695..283f3ab9 100644 --- a/libs/swflib/as3.mli +++ b/libs/swflib/as3.mli @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type 'a index diff --git a/libs/swflib/as3code.ml b/libs/swflib/as3code.ml index 17a7b478..859da70a 100644 --- a/libs/swflib/as3code.ml +++ b/libs/swflib/as3code.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open IO open As3 diff --git a/libs/swflib/as3hl.mli b/libs/swflib/as3hl.mli index d4a18538..8d6ee2d7 100644 --- a/libs/swflib/as3hl.mli +++ b/libs/swflib/as3hl.mli @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open As3 diff --git a/libs/swflib/as3hlparse.ml b/libs/swflib/as3hlparse.ml index ae7baba1..9e81184f 100644 --- a/libs/swflib/as3hlparse.ml +++ b/libs/swflib/as3hlparse.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open As3 open As3hl @@ -383,7 +383,7 @@ let rec parse_name names ctx = function | A3MRuntimeNameLate -> HMRuntimeNameLate | A3MMultiNameLate ns -> HMMultiNameLate ctx.nsets.(idx ns) | A3MAttrib multi -> HMAttrib (parse_name names ctx multi) - | A3MParams (id,pl) -> HMParams (parse_name names ctx names.(idx id),List.map (fun id -> parse_name names ctx names.(idx id)) pl) + | A3MParams (id,pl) -> HMParams (parse_name names ctx names.(idx id),List.map (fun id -> if idx id = -1 then HMAny else parse_name names ctx names.(idx id)) pl) let parse_try_catch ctx t = { diff --git a/libs/swflib/as3parse.ml b/libs/swflib/as3parse.ml index 45ecf54f..95c4a71f 100644 --- a/libs/swflib/as3parse.ml +++ b/libs/swflib/as3parse.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open As3 @@ -451,7 +451,7 @@ let read_field ctx ch = let has_meta = kind land 0x40 <> 0 in let slot = read_int ch in let kind = (match kind land 0xF with - | 0x00 | 0x06 -> + | 0x00 | 0x06 as kind -> let t = index_opt ctx.as3_names (read_int ch) in let value = read_value ctx ch false in A3FVar { diff --git a/libs/swflib/png.ml b/libs/swflib/png.ml index 43e91dba..38804a05 100644 --- a/libs/swflib/png.ml +++ b/libs/swflib/png.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type grey_bits = diff --git a/libs/swflib/png.mli b/libs/swflib/png.mli index c8b5a420..5d0a9f64 100644 --- a/libs/swflib/png.mli +++ b/libs/swflib/png.mli @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type grey_bits = diff --git a/libs/swflib/swf.ml b/libs/swflib/swf.ml index 5bcc9a6f..a753df45 100644 --- a/libs/swflib/swf.ml +++ b/libs/swflib/swf.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) type float16 = int diff --git a/libs/swflib/swfParser.ml b/libs/swflib/swfParser.ml index 91714b6b..4cd9698c 100644 --- a/libs/swflib/swfParser.ml +++ b/libs/swflib/swfParser.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open Swf open ActionScript @@ -2021,7 +2021,7 @@ let rec write_tag_data ch = function List.iter (fun (n,s) -> As3parse.write_int ch n; write_string ch s; - ) sl; + ) fl; | TBinaryData (id,data) -> write_ui16 ch id; write_i32 ch 0; diff --git a/libs/swflib/swfPic.ml b/libs/swflib/swfPic.ml index 58edb1ae..6fb95f1b 100644 --- a/libs/swflib/swfPic.ml +++ b/libs/swflib/swfPic.ml @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *) open Png diff --git a/libs/xml-light/Makefile b/libs/xml-light/Makefile index a3b69dea..06ae73f7 100644 --- a/libs/xml-light/Makefile +++ b/libs/xml-light/Makefile @@ -8,7 +8,7 @@ OCAMLFIND=ocamlfind .SUFFIXES : .ml .mli .cmo .cmx .cmi .mll .mly INSTALLDIR=`$(OCAMLC) -where` -CFLAGS= +ALL_CFLAGS= $(CFLAGS) LFLAGS= -a LIBS= SRC=dtd.mli xml.dsp xml_lexer.mli xml.ml xmlParser.ml xml_parser.mly dtd.ml test.ml xml.dsw xml_lexer.mll xml.mli xmlParser.mli @@ -97,13 +97,13 @@ clean: # SUFFIXES .ml.cmo: - $(OCAMLC) $(CFLAGS) -c $< + $(OCAMLC) $(ALL_CFLAGS) -c $< .ml.cmx: - $(OCAMLOPT) $(CFLAGS) -c $< + $(OCAMLOPT) $(ALL_CFLAGS) -c $< .mli.cmi: - $(OCAMLC) $(CFLAGS) $< + $(OCAMLC) $(ALL_CFLAGS) $< .mll.ml: ocamllex $< diff --git a/main.ml b/main.ml deleted file mode 100644 index 4f4c32c5..00000000 --- a/main.ml +++ /dev/null @@ -1,1749 +0,0 @@ -(* - * Copyright (C)2005-2013 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. - *) - -(* - Conventions: - - e: expression (typed or untyped) - - c: class - - en: enum - - td: typedef (tdef) - - a: abstract - - an: anon - - tf: tfunc - - cf: class_field - - ef: enum_field - - t: type (t) - - ct: complex_type - - v: local variable (tvar) - - m: module (module_def) - - mt: module_type - - p: pos - - "param" refers to type parameters - "arg" refers to function arguments - leading s_ means function returns string - trailing l means list (but we also use natural plurals such as "metas") - semantic suffixes may be used freely (e.g. e1, e_if, e') -*) - -open Printf -open Ast -open Genswf -open Common -open Type - -type context = { - com : Common.context; - mutable flush : unit -> unit; - mutable setup : unit -> unit; - mutable messages : string list; - mutable has_next : bool; - mutable has_error : bool; -} - -type cache = { - mutable c_haxelib : (string list, string list) Hashtbl.t; - mutable c_files : (string, float * Ast.package) Hashtbl.t; - mutable c_modules : (path * string, module_def) Hashtbl.t; -} - -exception Abort -exception Completion of string - - -let version = 3201 -let version_major = version / 1000 -let version_minor = (version mod 1000) / 100 -let version_revision = (version mod 100) -let version_is_stable = version_minor land 1 = 0 - -let measure_times = ref false -let prompt = ref false -let start_time = ref (get_time()) -let global_cache = ref None - -let path_sep = if Sys.os_type = "Unix" then "/" else "\\" - -let get_real_path p = - try - Extc.get_real_path p - with _ -> - p - -let executable_path() = - Extc.executable_path() - -let is_debug_run() = - try Sys.getenv "HAXEDEBUG" = "1" with _ -> false - -let s_version = - Printf.sprintf "%d.%d.%d%s" version_major version_minor version_revision (match Version.version_extra with None -> "" | Some v -> " " ^ v) - -let format msg p = - if p = Ast.null_pos then - msg - else begin - let error_printer file line = sprintf "%s:%d:" file line in - let epos = Lexer.get_error_pos error_printer p in - let msg = String.concat ("\n" ^ epos ^ " : ") (ExtString.String.nsplit msg "\n") in - sprintf "%s : %s" epos msg - end - -let ssend sock str = - let rec loop pos len = - if len = 0 then - () - else - let s = Unix.send sock str pos len [] in - loop (pos + s) (len - s) - in - loop 0 (String.length str) - -let message ctx msg p = - ctx.messages <- format msg p :: ctx.messages - -let deprecated = [ - "Type not found : IntIter","IntIter was renamed to IntIterator"; - "EReg has no field customReplace","EReg.customReplace was renamed to EReg.map"; - "#StringTools has no field isEOF","StringTools.isEOF was renamed to StringTools.isEof"; - "Type not found : haxe.BaseCode","haxe.BaseCode was moved to haxe.crypto.BaseCode"; - "Type not found : haxe.Md5","haxe.Md5 was moved to haxe.crypto.Md5"; - "Type not found : haxe.SHA1","haxe.SHA1 was moved to haxe.crypto.SHA1"; - "Type not found : Hash","Hash has been removed, use Map instead"; - "Type not found : IntHash","IntHash has been removed, use Map instead"; - "Type not found : haxe.FastList","haxe.FastList was moved to haxe.ds.GenericStack"; - "#Std has no field format","Std.format has been removed, use single quote 'string ${escape}' syntax instead"; - "Identifier 'EType' is not part of enum haxe.macro.ExprDef","EType has been removed, use EField instead"; - "Identifier 'CType' is not part of enum haxe.macro.Constant","CType has been removed, use CIdent instead"; - "Type not found : haxe.rtti.Infos","Use @:rtti instead of implementing haxe.rtti.Infos"; - "Type not found : haxe.rtti.Generic","Use @:generic instead of implementing haxe.Generic"; - "Type not found : flash.utils.TypedDictionary","flash.utils.TypedDictionary has been removed, use Map instead"; - "Type not found : haxe.Stack", "haxe.Stack has been renamed to haxe.CallStack"; - "Type not found : neko.zip.Reader", "neko.zip.Reader has been removed, use haxe.zip.Reader instead"; - "Type not found : neko.zip.Writer", "neko.zip.Writer has been removed, use haxe.zip.Writer instead"; - "Type not found : haxe.Public", "Use @:publicFields instead of implementing or extending haxe.Public"; - "#Xml has no field createProlog", "Xml.createProlog was renamed to Xml.createProcessingInstruction" -] - -let limit_string s offset = - let rest = 80 - offset in - let words = ExtString.String.nsplit s " " in - let rec loop i words = match words with - | word :: words -> - if String.length word + i + 1 > rest then (Printf.sprintf "\n%*s" offset "") :: word :: loop (String.length word) words - else (if i = 0 then "" else " ") :: word :: loop (i + 1 + String.length word) words - | [] -> - [] - in - String.concat "" (loop 0 words) - -let error ctx msg p = - let msg = try List.assoc msg deprecated with Not_found -> msg in - message ctx msg p; - ctx.has_error <- true - -let htmlescape s = - let s = String.concat "&" (ExtString.String.nsplit s "&") in - let s = String.concat "<" (ExtString.String.nsplit s "<") in - let s = String.concat ">" (ExtString.String.nsplit s ">") in - s - -let reserved_flags = [ - "cross";"js";"neko";"flash";"php";"cpp";"cs";"java";"python"; - "as3";"swc";"macro";"sys" - ] - -let complete_fields com fields = - let b = Buffer.create 0 in - let details = Common.raw_defined com "display-details" in - Buffer.add_string b "\n"; - List.iter (fun (n,t,k,d) -> - let s_kind = match k with - | Some k -> (match k with - | Typer.FKVar -> "var" - | Typer.FKMethod -> "method" - | Typer.FKType -> "type" - | Typer.FKPackage -> "package") - | None -> "" - in - if details then - Buffer.add_string b (Printf.sprintf "%s%s\n" n s_kind (htmlescape t) (htmlescape d)) - else - Buffer.add_string b (Printf.sprintf "%s%s\n" n (htmlescape t) (htmlescape d)) - ) (List.sort (fun (a,_,ak,_) (b,_,bk,_) -> compare (ak,a) (bk,b)) fields); - Buffer.add_string b "\n"; - raise (Completion (Buffer.contents b)) - -let report_times print = - let tot = ref 0. in - Hashtbl.iter (fun _ t -> tot := !tot +. t.total) Common.htimers; - print (Printf.sprintf "Total time : %.3fs" !tot); - if !tot > 0. then begin - print "------------------------------------"; - let timers = List.sort (fun t1 t2 -> compare t1.name t2.name) (Hashtbl.fold (fun _ t acc -> t :: acc) Common.htimers []) in - List.iter (fun t -> print (Printf.sprintf " %s : %.3fs, %.0f%%" t.name t.total (t.total *. 100. /. !tot))) timers - end - -let make_path f = - let f = String.concat "/" (ExtString.String.nsplit f "\\") in - let cl = ExtString.String.nsplit f "." in - let cl = (match List.rev cl with - | ["hx";path] -> ExtString.String.nsplit path "/" - | _ -> cl - ) in - let error msg = - let msg = "Could not process argument " ^ f ^ "\n" ^ msg in - failwith msg - in - let invalid_char x = - for i = 1 to String.length x - 1 do - match x.[i] with - | 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' -> () - | c -> error ("invalid character: " ^ (String.make 1 c)) - done - in - let rec loop = function - | [] -> - error "empty part" - | [x] -> - if String.length x = 0 then - error "empty part" - else if not (x.[0] = '_' || (x.[0] >= 'A' && x.[0] <= 'Z')) then - error "Class name must start with uppercase character"; - invalid_char x; - [],x - | x :: l -> - if String.length x = 0 then - error "empty part" - else if x.[0] < 'a' || x.[0] > 'z' then - error "Package name must start with a lower case character"; - invalid_char x; - let path,name = loop l in - x :: path,name - in - loop cl - -let unique l = - let rec _unique = function - | [] -> [] - | x1 :: x2 :: l when x1 = x2 -> _unique (x2 :: l) - | x :: l -> x :: _unique l - in - _unique (List.sort compare l) - -let rec read_type_path com p = - let classes = ref [] in - let packages = ref [] in - let p = (match p with - | x :: l -> - (try - match PMap.find x com.package_rules with - | Directory d -> d :: l - | Remap s -> s :: l - | _ -> p - with - Not_found -> p) - | _ -> p - ) in - List.iter (fun path -> - let dir = path ^ String.concat "/" p in - let r = (try Sys.readdir dir with _ -> [||]) in - Array.iter (fun f -> - if (try (Unix.stat (dir ^ "/" ^ f)).Unix.st_kind = Unix.S_DIR with _ -> false) then begin - if f.[0] >= 'a' && f.[0] <= 'z' then begin - if p = ["."] then - match read_type_path com [f] with - | [] , [] -> () - | _ -> - try - match PMap.find f com.package_rules with - | Forbidden -> () - | Remap f -> packages := f :: !packages - | Directory _ -> raise Not_found - with Not_found -> - packages := f :: !packages - else - packages := f :: !packages - end; - end else if file_extension f = "hx" then begin - let c = Filename.chop_extension f in - if String.length c < 2 || String.sub c (String.length c - 2) 2 <> "__" then classes := c :: !classes; - end; - ) r; - ) com.class_path; - List.iter (fun (_,_,extract) -> - Hashtbl.iter (fun (path,name) _ -> - if path = p then classes := name :: !classes else - let rec loop p1 p2 = - match p1, p2 with - | [], _ -> () - | x :: _, [] -> packages := x :: !packages - | a :: p1, b :: p2 -> if a = b then loop p1 p2 - in - loop path p - ) (extract()); - ) com.swf_libs; - List.iter (fun (path,std,close,all_files,lookup) -> - List.iter (fun (path, name) -> - if path = p then classes := name :: !classes else - let rec loop p1 p2 = - match p1, p2 with - | [], _ -> () - | x :: _, [] -> packages := x :: !packages - | a :: p1, b :: p2 -> if a = b then loop p1 p2 - in - loop path p - ) (all_files()) - ) com.java_libs; - List.iter (fun (path,std,all_files,lookup) -> - List.iter (fun (path, name) -> - if path = p then classes := name :: !classes else - let rec loop p1 p2 = - match p1, p2 with - | [], _ -> () - | x :: _, [] -> packages := x :: !packages - | a :: p1, b :: p2 -> if a = b then loop p1 p2 - in - loop path p - ) (all_files()) - ) com.net_libs; - unique !packages, unique !classes - -let delete_file f = try Sys.remove f with _ -> () - -let expand_env ?(h=None) path = - let r = Str.regexp "%\\([A-Za-z0-9_]+\\)%" in - Str.global_substitute r (fun s -> - let key = Str.matched_group 1 s in - try - Sys.getenv key - with Not_found -> try - match h with - | None -> raise Not_found - | Some h -> Hashtbl.find h key - with Not_found -> - "%" ^ key ^ "%" - ) path - -let unquote v = - let len = String.length v in - if len > 0 && v.[0] = '"' && v.[len - 1] = '"' then String.sub v 1 (len - 2) else v - -let parse_hxml_data data = - let lines = Str.split (Str.regexp "[\r\n]+") data in - List.concat (List.map (fun l -> - let l = unquote (ExtString.String.strip l) in - if l = "" || l.[0] = '#' then - [] - else if l.[0] = '-' then - try - let a, b = ExtString.String.split l " " in - [unquote a; unquote (ExtString.String.strip b)] - with - _ -> [l] - else - [l] - ) lines) - -let parse_hxml file = - let ch = IO.input_channel (try open_in_bin file with _ -> raise Not_found) in - let data = IO.read_all ch in - IO.close_in ch; - parse_hxml_data data - -let lookup_classes com spath = - let rec loop = function - | [] -> [] - | cp :: l -> - let cp = (if cp = "" then "./" else cp) in - let c = normalize_path (get_real_path (Common.unique_full_path cp)) in - let clen = String.length c in - if clen < String.length spath && String.sub spath 0 clen = c then begin - let path = String.sub spath clen (String.length spath - clen) in - (try - let path = make_path path in - (match loop l with - | [x] when String.length (Ast.s_type_path x) < String.length (Ast.s_type_path path) -> [x] - | _ -> [path]) - with _ -> loop l) - end else - loop l - in - loop com.class_path - -let add_libs com libs = - let call_haxelib() = - let t = Common.timer "haxelib" in - let cmd = "haxelib path " ^ String.concat " " libs in - let pin, pout, perr = Unix.open_process_full cmd (Unix.environment()) in - let lines = Std.input_list pin in - let err = Std.input_list perr in - let ret = Unix.close_process_full (pin,pout,perr) in - if ret <> Unix.WEXITED 0 then failwith (match lines, err with - | [], [] -> "Failed to call haxelib (command not found ?)" - | [], [s] when ExtString.String.ends_with (ExtString.String.strip s) "Module not found : path" -> "The haxelib command has been strip'ed, please install it again" - | _ -> String.concat "\n" (lines@err)); - t(); - lines - in - match libs with - | [] -> [] - | _ -> - let lines = match !global_cache with - | Some cache -> - (try - (* if we are compiling, really call haxelib since library path might have changed *) - if com.display = DMNone then raise Not_found; - Hashtbl.find cache.c_haxelib libs - with Not_found -> - let lines = call_haxelib() in - Hashtbl.replace cache.c_haxelib libs lines; - lines) - | _ -> call_haxelib() - in - let extra_args = ref [] in - let lines = List.fold_left (fun acc l -> - let l = ExtString.String.strip l in - if l = "" then acc else - if l.[0] <> '-' then l :: acc else - match (try ExtString.String.split l " " with _ -> l, "") with - | ("-L",dir) -> - com.neko_libs <- String.sub l 3 (String.length l - 3) :: com.neko_libs; - acc - | param, value -> - extra_args := param :: !extra_args; - if value <> "" then extra_args := value :: !extra_args; - acc - ) [] lines in - com.class_path <- lines @ com.class_path; - List.rev !extra_args - -let run_command ctx cmd = - let h = Hashtbl.create 0 in - Hashtbl.add h "__file__" ctx.com.file; - Hashtbl.add h "__platform__" (platform_name ctx.com.platform); - let t = Common.timer "command" in - let cmd = expand_env ~h:(Some h) cmd in - let len = String.length cmd in - if len > 3 && String.sub cmd 0 3 = "cd " then begin - Sys.chdir (String.sub cmd 3 (len - 3)); - 0 - end else - let binary_string s = - if Sys.os_type <> "Win32" && Sys.os_type <> "Cygwin" then s else String.concat "\n" (Str.split (Str.regexp "\r\n") s) - in - let pout, pin, perr = Unix.open_process_full cmd (Unix.environment()) in - let iout = Unix.descr_of_in_channel pout in - let ierr = Unix.descr_of_in_channel perr in - let berr = Buffer.create 0 in - let bout = Buffer.create 0 in - let tmp = String.create 1024 in - let result = ref None in - (* - we need to read available content on process out/err if we want to prevent - the process from blocking when the pipe is full - *) - let is_process_running() = - let pid, r = Unix.waitpid [Unix.WNOHANG] (-1) in - if pid = 0 then - true - else begin - result := Some r; - false; - end - in - let rec loop ins = - let (ch,_,_), timeout = (try Unix.select ins [] [] 0.02, true with _ -> ([],[],[]),false) in - match ch with - | [] -> - (* make sure we read all *) - if timeout && is_process_running() then - loop ins - else begin - Buffer.add_string berr (IO.read_all (IO.input_channel perr)); - Buffer.add_string bout (IO.read_all (IO.input_channel pout)); - end - | s :: _ -> - let n = Unix.read s tmp 0 (String.length tmp) in - if s == iout && n > 0 then - ctx.com.print (String.sub tmp 0 n) - else - Buffer.add_substring (if s == iout then bout else berr) tmp 0 n; - loop (if n = 0 then List.filter ((!=) s) ins else ins) - in - (try loop [iout;ierr] with Unix.Unix_error _ -> ()); - let serr = binary_string (Buffer.contents berr) in - let sout = binary_string (Buffer.contents bout) in - if serr <> "" then ctx.messages <- (if serr.[String.length serr - 1] = '\n' then String.sub serr 0 (String.length serr - 1) else serr) :: ctx.messages; - if sout <> "" then ctx.com.print sout; - let r = (match (try Unix.close_process_full (pout,pin,perr) with Unix.Unix_error (Unix.ECHILD,_,_) -> (match !result with None -> assert false | Some r -> r)) with - | Unix.WEXITED e -> e - | Unix.WSIGNALED s | Unix.WSTOPPED s -> if s = 0 then -1 else s - ) in - t(); - r - -let display_memory ctx = - let verbose = ctx.com.verbose in - let print = print_endline in - let fmt_size sz = - if sz < 1024 then - string_of_int sz ^ " B" - else if sz < 1024*1024 then - string_of_int (sz asr 10) ^ " KB" - else - Printf.sprintf "%.1f MB" ((float_of_int sz) /. (1024.*.1024.)) - in - let size v = - fmt_size (mem_size v) - in - Gc.full_major(); - Gc.compact(); - let mem = Gc.stat() in - print ("Total Allocated Memory " ^ fmt_size (mem.Gc.heap_words * (Sys.word_size asr 8))); - print ("Free Memory " ^ fmt_size (mem.Gc.free_words * (Sys.word_size asr 8))); - (match !global_cache with - | None -> - print "No cache found"; - | Some c -> - print ("Total cache size " ^ size c); - print (" haxelib " ^ size c.c_haxelib); - print (" parsed ast " ^ size c.c_files ^ " (" ^ string_of_int (Hashtbl.length c.c_files) ^ " files stored)"); - print (" typed modules " ^ size c.c_modules ^ " (" ^ string_of_int (Hashtbl.length c.c_modules) ^ " modules stored)"); - let rec scan_module_deps m h = - if Hashtbl.mem h m.m_id then - () - else begin - Hashtbl.add h m.m_id m; - PMap.iter (fun _ m -> scan_module_deps m h) m.m_extra.m_deps - end - in - let all_modules = Hashtbl.fold (fun _ m acc -> PMap.add m.m_id m acc) c.c_modules PMap.empty in - let modules = Hashtbl.fold (fun (path,key) m acc -> - let mdeps = Hashtbl.create 0 in - scan_module_deps m mdeps; - let deps = ref [] in - let out = ref all_modules in - Hashtbl.iter (fun _ md -> - out := PMap.remove md.m_id !out; - if m == md then () else begin - deps := Obj.repr md :: !deps; - List.iter (fun t -> - match t with - | TClassDecl c -> - deps := Obj.repr c :: !deps; - List.iter (fun f -> deps := Obj.repr f :: !deps) c.cl_ordered_statics; - List.iter (fun f -> deps := Obj.repr f :: !deps) c.cl_ordered_fields; - | TEnumDecl e -> - deps := Obj.repr e :: !deps; - List.iter (fun n -> deps := Obj.repr (PMap.find n e.e_constrs) :: !deps) e.e_names; - | TTypeDecl t -> deps := Obj.repr t :: !deps; - | TAbstractDecl a -> deps := Obj.repr a :: !deps; - ) md.m_types; - end - ) mdeps; - let chk = Obj.repr Common.memory_marker :: PMap.fold (fun m acc -> Obj.repr m :: acc) !out [] in - let inf = Objsize.objsize m !deps chk in - (m,Objsize.size_with_headers inf, (inf.Objsize.reached,!deps,!out)) :: acc - ) c.c_modules [] in - let cur_key = ref "" and tcount = ref 0 and mcount = ref 0 in - List.iter (fun (m,size,(reached,deps,out)) -> - let key = m.m_extra.m_sign in - if key <> !cur_key then begin - print (Printf.sprintf (" --- CONFIG %s ----------------------------") (Digest.to_hex key)); - cur_key := key; - end; - let sign md = - if md.m_extra.m_sign = key then "" else "(" ^ (try Digest.to_hex md.m_extra.m_sign with _ -> "???" ^ md.m_extra.m_sign) ^ ")" - in - print (Printf.sprintf " %s : %s" (Ast.s_type_path m.m_path) (fmt_size size)); - (if reached then try - incr mcount; - let lcount = ref 0 in - let leak l = - incr lcount; - incr tcount; - print (Printf.sprintf " LEAK %s" l); - if !lcount >= 3 && !tcount >= 100 && not verbose then begin - print (Printf.sprintf " ..."); - raise Exit; - end; - in - if (Objsize.objsize m deps [Obj.repr Common.memory_marker]).Objsize.reached then leak "common"; - PMap.iter (fun _ md -> - if (Objsize.objsize m deps [Obj.repr md]).Objsize.reached then leak (Ast.s_type_path md.m_path ^ sign md); - ) out; - with Exit -> - ()); - if verbose then begin - print (Printf.sprintf " %d total deps" (List.length deps)); - PMap.iter (fun _ md -> - print (Printf.sprintf " dep %s%s" (Ast.s_type_path md.m_path) (sign md)); - ) m.m_extra.m_deps; - end; - flush stdout - ) (List.sort (fun (m1,s1,_) (m2,s2,_) -> - let k1 = m1.m_extra.m_sign and k2 = m2.m_extra.m_sign in - if k1 = k2 then s1 - s2 else if k1 > k2 then 1 else -1 - ) modules); - if !mcount > 0 then print ("*** " ^ string_of_int !mcount ^ " modules have leaks !"); - print "Cache dump complete") - - -let default_flush ctx = - List.iter prerr_endline (List.rev ctx.messages); - if ctx.has_error && !prompt then begin - print_endline "Press enter to exit..."; - ignore(read_line()); - end; - if ctx.has_error then exit 1 - -let create_context params = - let ctx = { - com = Common.create version params; - flush = (fun()->()); - setup = (fun()->()); - messages = []; - has_next = false; - has_error = false; - } in - ctx.flush <- (fun() -> default_flush ctx); - ctx - -let rec process_params create pl = - let each_params = ref [] in - let rec loop acc = function - | [] -> - let ctx = create (!each_params @ (List.rev acc)) in - init ctx; - ctx.flush() - | "--next" :: l when acc = [] -> (* skip empty --next *) - loop [] l - | "--next" :: l -> - let ctx = create (!each_params @ (List.rev acc)) in - ctx.has_next <- true; - init ctx; - ctx.flush(); - loop [] l - | "--each" :: l -> - each_params := List.rev acc; - loop [] l - | "--cwd" :: dir :: l -> - (* we need to change it immediately since it will affect hxml loading *) - (try Unix.chdir dir with _ -> raise (Arg.Bad "Invalid directory")); - loop acc l - | "--connect" :: hp :: l -> - (match !global_cache with - | None -> - let host, port = (try ExtString.String.split hp ":" with _ -> "127.0.0.1", hp) in - do_connect host (try int_of_string port with _ -> raise (Arg.Bad "Invalid port")) ((List.rev acc) @ l) - | Some _ -> - (* already connected : skip *) - loop acc l) - | "--run" :: cl :: args -> - let acc = cl :: "-main" :: "--interp" :: acc in - let ctx = create (!each_params @ (List.rev acc)) in - ctx.com.sys_args <- args; - init ctx; - ctx.flush() - | arg :: l -> - match List.rev (ExtString.String.nsplit arg ".") with - | "hxml" :: _ when (match acc with "-cmd" :: _ -> false | _ -> true) -> - let acc, l = (try acc, parse_hxml arg @ l with Not_found -> (arg ^ " (file not found)") :: acc, l) in - loop acc l - | _ -> loop (arg :: acc) l - in - (* put --display in front if it was last parameter *) - let pl = (match List.rev pl with - | file :: "--display" :: pl when file <> "memory" -> "--display" :: file :: List.rev pl - | "use_rtti_doc" :: "-D" :: file :: "--display" :: pl -> "--display" :: file :: List.rev pl - | _ -> pl - ) in - loop [] pl - -and wait_loop boot_com host port = - let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in - (try Unix.setsockopt sock Unix.SO_REUSEADDR true with _ -> ()); - (try Unix.bind sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with _ -> failwith ("Couldn't wait on " ^ host ^ ":" ^ string_of_int port)); - Unix.listen sock 10; - Sys.catch_break false; - let verbose = boot_com.verbose in - let has_parse_error = ref false in - if verbose then print_endline ("Waiting on " ^ host ^ ":" ^ string_of_int port); - let bufsize = 1024 in - let tmp = String.create bufsize in - let cache = { - c_haxelib = Hashtbl.create 0; - c_files = Hashtbl.create 0; - c_modules = Hashtbl.create 0; - } in - global_cache := Some cache; - Typer.macro_enable_cache := true; - Typeload.parse_hook := (fun com2 file p -> - let sign = get_signature com2 in - let ffile = Common.unique_full_path file in - let ftime = file_time ffile in - let fkey = ffile ^ "!" ^ sign in - try - let time, data = Hashtbl.find cache.c_files fkey in - if time <> ftime then raise Not_found; - data - with Not_found -> - has_parse_error := false; - let data = Typeload.parse_file com2 file p in - if verbose then print_endline ("Parsed " ^ ffile); - if not !has_parse_error && ffile <> (!Parser.resume_display).Ast.pfile then Hashtbl.replace cache.c_files fkey (ftime,data); - data - ); - let cache_module m = - Hashtbl.replace cache.c_modules (m.m_path,m.m_extra.m_sign) m; - in - let check_module_path com m p = - if m.m_extra.m_file <> Common.unique_full_path (Typeload.resolve_module_file com m.m_path (ref[]) p) then begin - if verbose then print_endline ("Module path " ^ s_type_path m.m_path ^ " has been changed"); - raise Not_found; - end - in - let compilation_step = ref 0 in - let compilation_mark = ref 0 in - let mark_loop = ref 0 in - Typeload.type_module_hook := (fun (ctx:Typecore.typer) mpath p -> - let t = Common.timer "module cache check" in - let com2 = ctx.Typecore.com in - let sign = get_signature com2 in - let dep = ref None in - incr mark_loop; - let mark = !mark_loop in - let start_mark = !compilation_mark in - let rec check m = - if m.m_extra.m_dirty then begin - dep := Some m; - false - end else if m.m_extra.m_mark = mark then - true - else try - if m.m_extra.m_mark <= start_mark then begin - (match m.m_extra.m_kind with - | MFake | MSub -> () (* don't get classpath *) - | MExtern -> - (* if we have a file then this will override our extern type *) - let has_file = (try ignore(Typeload.resolve_module_file com2 m.m_path (ref[]) p); true with Not_found -> false) in - if has_file then begin - if verbose then print_endline ("A file is masking the library file " ^ s_type_path m.m_path); - raise Not_found; - end; - let rec loop = function - | [] -> - if verbose then print_endline ("No library file was found for " ^ s_type_path m.m_path); - raise Not_found (* no extern registration *) - | load :: l -> - match load m.m_path p with - | None -> loop l - | Some (file,_) -> - if Common.unique_full_path file <> m.m_extra.m_file then begin - if verbose then print_endline ("Library file was changed for " ^ s_type_path m.m_path); - raise Not_found; - end - in - loop com2.load_extern_type - | MCode -> check_module_path com2 m p - | MMacro when ctx.Typecore.in_macro -> check_module_path com2 m p - | MMacro -> - let _, mctx = Typer.get_macro_context ctx p in - check_module_path mctx.Typecore.com m p - ); - if file_time m.m_extra.m_file <> m.m_extra.m_time then begin - if verbose then print_endline ("File " ^ m.m_extra.m_file ^ (if m.m_extra.m_time = -1. then " not cached (macro-in-macro)" else " has been modified")); - if m.m_extra.m_kind = MFake then Hashtbl.remove Typecore.fake_modules m.m_extra.m_file; - raise Not_found; - end; - end; - m.m_extra.m_mark <- mark; - PMap.iter (fun _ m2 -> if not (check m2) then begin dep := Some m2; raise Not_found end) m.m_extra.m_deps; - true - with Not_found -> - m.m_extra.m_dirty <- true; - false - in - let rec add_modules m0 m = - if m.m_extra.m_added < !compilation_step then begin - (match m0.m_extra.m_kind, m.m_extra.m_kind with - | MCode, MMacro | MMacro, MCode -> - (* this was just a dependency to check : do not add to the context *) - () - | _ -> - if verbose then print_endline ("Reusing cached module " ^ Ast.s_type_path m.m_path); - m.m_extra.m_added <- !compilation_step; - List.iter (fun t -> - match t with - | TClassDecl c -> c.cl_restore() - | TEnumDecl e -> - let rec loop acc = function - | [] -> () - | (Ast.Meta.RealPath,[Ast.EConst (Ast.String path),_],_) :: l -> - e.e_path <- Ast.parse_path path; - e.e_meta <- (List.rev acc) @ l; - | x :: l -> loop (x::acc) l - in - loop [] e.e_meta - | TAbstractDecl a -> - a.a_meta <- List.filter (fun (m,_,_) -> m <> Ast.Meta.ValueUsed) a.a_meta - | _ -> () - ) m.m_types; - if m.m_extra.m_kind <> MSub then Typeload.add_module ctx m p; - PMap.iter (Hashtbl.add com2.resources) m.m_extra.m_binded_res; - PMap.iter (fun _ m2 -> add_modules m0 m2) m.m_extra.m_deps); - List.iter (Typer.call_init_macro ctx) m.m_extra.m_macro_calls - end - in - try - let m = Hashtbl.find cache.c_modules (mpath,sign) in - if not (check m) then begin - if verbose then print_endline ("Skipping cached module " ^ Ast.s_type_path mpath ^ (match !dep with None -> "" | Some m -> "(" ^ Ast.s_type_path m.m_path ^ ")")); - raise Not_found; - end; - add_modules m m; - t(); - Some m - with Not_found -> - t(); - None - ); - let run_count = ref 0 in - while true do - let sin, _ = Unix.accept sock in - let t0 = get_time() in - Unix.set_nonblock sin; - if verbose then print_endline "Client connected"; - let b = Buffer.create 0 in - let rec read_loop count = - let r = try - Unix.recv sin tmp 0 bufsize [] - with Unix.Unix_error((Unix.EWOULDBLOCK|Unix.EAGAIN),_,_) -> - 0 - in - if verbose then begin - if r > 0 then Printf.printf "Reading %d bytes\n" r else print_endline "Waiting for data..."; - end; - Buffer.add_substring b tmp 0 r; - if r > 0 && tmp.[r-1] = '\000' then - Buffer.sub b 0 (Buffer.length b - 1) - else begin - if r = 0 then ignore(Unix.select [] [] [] 0.05); (* wait a bit *) - if count = 100 then - failwith "Aborting unactive connection" - else - read_loop (count + 1); - end; - in - let rec cache_context com = - if com.display = DMNone then begin - List.iter cache_module com.modules; - if verbose then print_endline ("Cached " ^ string_of_int (List.length com.modules) ^ " modules"); - end; - match com.get_macros() with - | None -> () - | Some com -> cache_context com - in - let create params = - let ctx = create_context params in - ctx.flush <- (fun() -> - incr compilation_step; - compilation_mark := !mark_loop; - List.iter (fun s -> ssend sin (s ^ "\n"); if verbose then print_endline ("> " ^ s)) (List.rev ctx.messages); - if ctx.has_error then ssend sin "\x02\n" else cache_context ctx.com; - ); - ctx.setup <- (fun() -> - Parser.display_error := (fun e p -> has_parse_error := true; ctx.com.error (Parser.error_msg e) p); - if ctx.com.display <> DMNone then begin - let file = (!Parser.resume_display).Ast.pfile in - let fkey = file ^ "!" ^ get_signature ctx.com in - (* force parsing again : if the completion point have been changed *) - Hashtbl.remove cache.c_files fkey; - (* force module reloading (if cached) *) - Hashtbl.iter (fun _ m -> if m.m_extra.m_file = file then m.m_extra.m_dirty <- true) cache.c_modules - end - ); - ctx.com.print <- (fun str -> ssend sin ("\x01" ^ String.concat "\x01" (ExtString.String.nsplit str "\n") ^ "\n")); - ctx - in - (try - let data = parse_hxml_data (read_loop 0) in - Unix.clear_nonblock sin; - if verbose then print_endline ("Processing Arguments [" ^ String.concat "," data ^ "]"); - (try - Common.display_default := DMNone; - Parser.resume_display := Ast.null_pos; - Typeload.return_partial_type := false; - measure_times := false; - close_times(); - stats.s_files_parsed := 0; - stats.s_classes_built := 0; - stats.s_methods_typed := 0; - stats.s_macros_called := 0; - Hashtbl.clear Common.htimers; - let _ = Common.timer "other" in - incr compilation_step; - compilation_mark := !mark_loop; - start_time := get_time(); - process_params create data; - close_times(); - if !measure_times then report_times (fun s -> ssend sin (s ^ "\n")) - with Completion str -> - if verbose then print_endline ("Completion Response =\n" ^ str); - ssend sin str - ); - if verbose then begin - print_endline (Printf.sprintf "Stats = %d files, %d classes, %d methods, %d macros" !(stats.s_files_parsed) !(stats.s_classes_built) !(stats.s_methods_typed) !(stats.s_macros_called)); - print_endline (Printf.sprintf "Time spent : %.3fs" (get_time() -. t0)); - end - with Unix.Unix_error _ -> - if verbose then print_endline "Connection Aborted" - | e -> - let estr = Printexc.to_string e in - if verbose then print_endline ("Uncaught Error : " ^ estr); - (try ssend sin estr with _ -> ()); - ); - Unix.close sin; - (* prevent too much fragmentation by doing some compactions every X run *) - incr run_count; - if !run_count mod 10 = 0 then begin - let t0 = get_time() in - Gc.compact(); - if verbose then begin - let stat = Gc.quick_stat() in - let size = (float_of_int stat.Gc.heap_words) *. 4. in - print_endline (Printf.sprintf "Compacted memory %.3fs %.1fMB" (get_time() -. t0) (size /. (1024. *. 1024.))); - end - end else Gc.minor(); - done - -and do_connect host port args = - let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in - (try Unix.connect sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with _ -> failwith ("Couldn't connect on " ^ host ^ ":" ^ string_of_int port)); - let args = ("--cwd " ^ Unix.getcwd()) :: args in - ssend sock (String.concat "" (List.map (fun a -> a ^ "\n") args) ^ "\000"); - let has_error = ref false in - let rec print line = - match (if line = "" then '\x00' else line.[0]) with - | '\x01' -> - print_string (String.concat "\n" (List.tl (ExtString.String.nsplit line "\x01"))); - flush stdout - | '\x02' -> - has_error := true; - | _ -> - prerr_endline line; - in - let buf = Buffer.create 0 in - let process() = - let lines = ExtString.String.nsplit (Buffer.contents buf) "\n" in - (* the last line ends with \n *) - let lines = (match List.rev lines with "" :: l -> List.rev l | _ -> lines) in - List.iter print lines; - in - let tmp = String.create 1024 in - let rec loop() = - let b = Unix.recv sock tmp 0 1024 [] in - Buffer.add_substring buf tmp 0 b; - if b > 0 then begin - if String.get tmp (b - 1) = '\n' then begin - process(); - Buffer.reset buf; - end; - loop(); - end - in - loop(); - process(); - if !has_error then exit 1 - -and init ctx = - let usage = Printf.sprintf - "Haxe Compiler %s - (C)2005-2015 Haxe Foundation\n Usage : haxe%s -main [-swf|-js|-neko|-php|-cpp|-as3] [options]\n Options :" - s_version (if Sys.os_type = "Win32" then ".exe" else "") - in - let com = ctx.com in - let classes = ref [([],"Std")] in -try - let xml_out = ref None in - let swf_header = ref None in - let cmds = ref [] in - let config_macros = ref [] in - let cp_libs = ref [] in - let added_libs = Hashtbl.create 0 in - let no_output = ref false in - let did_something = ref false in - let force_typing = ref false in - let pre_compilation = ref [] in - let interp = ref false in - let swf_version = ref false in - let evals = ref [] in - Common.define_value com Define.HaxeVer (float_repres (float_of_int version /. 1000.)); - Common.define_value com Define.HxcppApiLevel "321"; - Common.raw_define com "haxe3"; - Common.define_value com Define.Dce "std"; - com.warning <- (fun msg p -> message ctx ("Warning : " ^ msg) p); - com.error <- error ctx; - if !global_cache <> None then com.run_command <- run_command ctx; - Parser.display_error := (fun e p -> com.error (Parser.error_msg e) p); - Parser.use_doc := !Common.display_default <> DMNone || (!global_cache <> None); - (try - let p = Sys.getenv "HAXE_STD_PATH" in - let rec loop = function - | drive :: path :: l -> - if String.length drive = 1 && ((drive.[0] >= 'a' && drive.[0] <= 'z') || (drive.[0] >= 'A' && drive.[0] <= 'Z')) then - (drive ^ ":" ^ path) :: loop l - else - drive :: loop (path :: l) - | l -> - l - in - let parts = Str.split_delim (Str.regexp "[;:]") p in - com.class_path <- "" :: List.map normalize_path (loop parts) - with - Not_found -> - if Sys.os_type = "Unix" then - com.class_path <- ["/usr/lib/haxe/std/";"/usr/share/haxe/std/";"/usr/local/lib/haxe/std/";"/usr/lib/haxe/extraLibs/";"/usr/local/lib/haxe/extraLibs/";""] - else - let base_path = normalize_path (get_real_path (try executable_path() with _ -> "./")) in - com.class_path <- [base_path ^ "std/";base_path ^ "extraLibs/";""]); - com.std_path <- List.filter (fun p -> ExtString.String.ends_with p "std/" || ExtString.String.ends_with p "std\\") com.class_path; - let set_platform pf file = - if com.platform <> Cross then failwith "Multiple targets"; - Common.init_platform com pf; - com.file <- file; - if (pf = Flash) && file_extension file = "swc" then Common.define com Define.Swc; - in - let define f = Arg.Unit (fun () -> Common.define com f) in - let process_ref = ref (fun args -> ()) in - let process_libs() = - let libs = List.filter (fun l -> not (Hashtbl.mem added_libs l)) (List.rev !cp_libs) in - cp_libs := []; - List.iter (fun l -> Hashtbl.add added_libs l ()) libs; - (* immediately process the arguments to insert them at the place -lib was defined *) - match add_libs com libs with - | [] -> () - | args -> (!process_ref) args - in - let arg_delays = ref [] in - let basic_args_spec = [ - ("-cp",Arg.String (fun path -> - process_libs(); - com.class_path <- normalize_path path :: com.class_path - )," : add a directory to find source files"); - ("-js",Arg.String (set_platform Js)," : compile code to JavaScript file"); - ("-swf",Arg.String (set_platform Flash)," : compile code to Flash SWF file"); - ("-as3",Arg.String (fun dir -> - set_platform Flash dir; - Common.define com Define.As3; - Common.define com Define.NoInline; - )," : generate AS3 code into target directory"); - ("-neko",Arg.String (set_platform Neko)," : compile code to Neko Binary"); - ("-php",Arg.String (fun dir -> - classes := (["php"],"Boot") :: !classes; - set_platform Php dir; - )," : generate PHP code into target directory"); - ("-cpp",Arg.String (fun dir -> - set_platform Cpp dir; - )," : generate C++ code into target directory"); - ("-cs",Arg.String (fun dir -> - cp_libs := "hxcs" :: !cp_libs; - set_platform Cs dir; - )," : generate C# code into target directory"); - ("-java",Arg.String (fun dir -> - cp_libs := "hxjava" :: !cp_libs; - set_platform Java dir; - )," : generate Java code into target directory"); - ("-python",Arg.String (fun dir -> - set_platform Python dir; - )," : generate Python code as target file"); - ("-xml",Arg.String (fun file -> - Parser.use_doc := true; - xml_out := Some file - )," : generate XML types description"); - ("-main",Arg.String (fun cl -> - if com.main_class <> None then raise (Arg.Bad "Multiple -main"); - let cpath = make_path cl in - com.main_class <- Some cpath; - classes := cpath :: !classes - )," : select startup class"); - ("-lib",Arg.String (fun l -> - cp_libs := l :: !cp_libs; - Common.raw_define com l; - )," : use a haxelib library"); - ("-D",Arg.String (fun var -> - begin match var with - | "no_copt" | "no-copt" -> com.foptimize <- false; - | "use_rtti_doc" | "use-rtti-doc" -> Parser.use_doc := true; - | _ -> if List.mem var reserved_flags then raise (Arg.Bad (var ^ " is a reserved compiler flag and cannot be defined from command line")); - end; - Common.raw_define com var; - )," : define a conditional compilation flag"); - ("-v",Arg.Unit (fun () -> - com.verbose <- true - ),": turn on verbose mode"); - ("-debug", Arg.Unit (fun() -> - Common.define com Define.Debug; - com.debug <- true; - ), ": add debug information to the compiled code"); - ] in - let adv_args_spec = [ - ("-dce", Arg.String (fun mode -> - (match mode with - | "std" | "full" | "no" -> () - | _ -> raise (Arg.Bad "Invalid DCE mode, expected std | full | no")); - Common.define_value com Define.Dce mode - ),"[std|full|no] : set the dead code elimination mode"); - ("-swf-version",Arg.Float (fun v -> - if not !swf_version || com.flash_version < v then com.flash_version <- v; - swf_version := true; - )," : change the SWF version"); - ("-swf-header",Arg.String (fun h -> - try - swf_header := Some (match ExtString.String.nsplit h ":" with - | [width; height; fps] -> - (int_of_string width,int_of_string height,float_of_string fps,0xFFFFFF) - | [width; height; fps; color] -> - let color = if ExtString.String.starts_with color "0x" then color else "0x" ^ color in - (int_of_string width, int_of_string height, float_of_string fps, int_of_string color) - | _ -> raise Exit) - with - _ -> raise (Arg.Bad "Invalid SWF header format, expected width:height:fps[:color]") - ),"
: define SWF header (width:height:fps:color)"); - ("-swf-lib",Arg.String (fun file -> - process_libs(); (* linked swf order matters, and lib might reference swf as well *) - Genswf.add_swf_lib com file false - )," : add the SWF library to the compiled SWF"); - ("-swf-lib-extern",Arg.String (fun file -> - Genswf.add_swf_lib com file true - )," : use the SWF library for type checking"); - ("-java-lib",Arg.String (fun file -> - let std = file = "lib/hxjava-std.jar" in - arg_delays := (fun () -> Genjava.add_java_lib com file std) :: !arg_delays; - )," : add an external JAR or class directory library"); - ("-net-lib",Arg.String (fun file -> - let file, is_std = match ExtString.String.nsplit file "@" with - | [file] -> - file,false - | [file;"std"] -> - file,true - | _ -> raise Exit - in - arg_delays := (fun () -> Gencs.add_net_lib com file is_std) :: !arg_delays; - ),"[@std] : add an external .NET DLL file"); - ("-net-std",Arg.String (fun file -> - Gencs.add_net_std com file - )," : add a root std .NET DLL search path"); - ("-c-arg",Arg.String (fun arg -> - com.c_args <- arg :: com.c_args - )," : pass option to the native Java/C# compiler"); - ("-x", Arg.String (fun file -> - let neko_file = file ^ ".n" in - set_platform Neko neko_file; - if com.main_class = None then begin - let cpath = make_path file in - com.main_class <- Some cpath; - classes := cpath :: !classes - end; - cmds := ("neko " ^ neko_file) :: !cmds; - )," : shortcut for compiling and executing a neko file"); - ("-resource",Arg.String (fun res -> - let file, name = (match ExtString.String.nsplit res "@" with - | [file; name] -> file, name - | [file] -> file, file - | _ -> raise (Arg.Bad "Invalid Resource format, expected file@name") - ) in - let file = (try Common.find_file com file with Not_found -> file) in - let data = (try - let s = Std.input_file ~bin:true file in - if String.length s > 12000000 then raise Exit; - s; - with - | Sys_error _ -> failwith ("Resource file not found : " ^ file) - | _ -> failwith ("Resource '" ^ file ^ "' excess the maximum size of 12MB") - ) in - if Hashtbl.mem com.resources name then failwith ("Duplicate resource name " ^ name); - Hashtbl.add com.resources name data - ),"[@name] : add a named resource file"); - ("-prompt", Arg.Unit (fun() -> prompt := true),": prompt on error"); - ("-cmd", Arg.String (fun cmd -> - cmds := unquote cmd :: !cmds - ),": run the specified command after successful compilation"); - ("--flash-strict", define Define.FlashStrict, ": more type strict flash API"); - ("--no-traces", define Define.NoTraces, ": don't compile trace calls in the program"); - ("--gen-hx-classes", Arg.Unit (fun() -> - force_typing := true; - pre_compilation := (fun() -> - List.iter (fun (_,_,extract) -> - Hashtbl.iter (fun n _ -> classes := n :: !classes) (extract()) - ) com.swf_libs; - List.iter (fun (_,std,_,all_files,_) -> - if not std then - List.iter (fun path -> if path <> (["java";"lang"],"String") then classes := path :: !classes) (all_files()) - ) com.java_libs; - List.iter (fun (_,std,all_files,_) -> - if not std then - List.iter (fun path -> classes := path :: !classes) (all_files()) - ) com.net_libs; - ) :: !pre_compilation; - xml_out := Some "hx" - ),": generate hx headers for all input classes"); - ("--next", Arg.Unit (fun() -> assert false), ": separate several haxe compilations"); - ("--each", Arg.Unit (fun() -> assert false), ": append preceding parameters to all haxe compilations separated by --next"); - ("--display", Arg.String (fun file_pos -> - match file_pos with - | "classes" -> - pre_compilation := (fun() -> raise (Parser.TypePath (["."],None,true))) :: !pre_compilation; - | "keywords" -> - complete_fields com (Hashtbl.fold (fun k _ acc -> (k,"",None,"") :: acc) Lexer.keywords []) - | "memory" -> - did_something := true; - (try display_memory ctx with e -> prerr_endline (Printexc.get_backtrace ())); - | _ -> - let file, pos = try ExtString.String.split file_pos "@" with _ -> failwith ("Invalid format : " ^ file_pos) in - let file = unquote file in - let pos, smode = try ExtString.String.split pos "@" with _ -> pos,"" in - let activate_special_display_mode () = - Common.define com Define.NoCOpt; - Parser.use_parser_resume := false - in - let mode = match smode with - | "position" -> - activate_special_display_mode(); - DMPosition - | "usage" -> - activate_special_display_mode(); - DMUsage - | "type" -> - activate_special_display_mode(); - DMType - | "toplevel" -> - activate_special_display_mode(); - DMToplevel - | "" -> - Parser.use_parser_resume := true; - DMDefault - | _ -> - let smode,arg = try ExtString.String.split smode "@" with _ -> pos,"" in - match smode with - | "resolve" -> - activate_special_display_mode(); - DMResolve arg - | _ -> - Parser.use_parser_resume := true; - DMDefault - in - let pos = try int_of_string pos with _ -> failwith ("Invalid format : " ^ pos) in - com.display <- mode; - Common.display_default := mode; - Common.define_value com Define.Display (if smode <> "" then smode else "1"); - Parser.use_doc := true; - Parser.resume_display := { - Ast.pfile = Common.unique_full_path file; - Ast.pmin = pos; - Ast.pmax = pos; - }; - ),": display code tips"); - ("--no-output", Arg.Unit (fun() -> no_output := true),": compiles but does not generate any file"); - ("--times", Arg.Unit (fun() -> measure_times := true),": measure compilation times"); - ("--no-inline", define Define.NoInline, ": disable inlining"); - ("--no-opt", Arg.Unit (fun() -> - com.foptimize <- false; - Common.define com Define.NoOpt; - ), ": disable code optimizations"); - ("--php-front",Arg.String (fun f -> - if com.php_front <> None then raise (Arg.Bad "Multiple --php-front"); - com.php_front <- Some f; - )," : select the name for the php front file"); - ("--php-lib",Arg.String (fun f -> - if com.php_lib <> None then raise (Arg.Bad "Multiple --php-lib"); - com.php_lib <- Some f; - )," : select the name for the php lib folder"); - ("--php-prefix", Arg.String (fun f -> - if com.php_prefix <> None then raise (Arg.Bad "Multiple --php-prefix"); - com.php_prefix <- Some f; - Common.define com Define.PhpPrefix; - )," : prefix all classes with given name"); - ("--remap", Arg.String (fun s -> - let pack, target = (try ExtString.String.split s ":" with _ -> raise (Arg.Bad "Invalid remap format, expected source:target")) in - com.package_rules <- PMap.add pack (Remap target) com.package_rules; - )," : remap a package to another one"); - ("--interp", Arg.Unit (fun() -> - Common.define com Define.Interp; - set_platform Neko ""; - no_output := true; - interp := true; - ),": interpret the program using internal macro system"); - ("--macro", Arg.String (fun e -> - force_typing := true; - config_macros := e :: !config_macros - )," : call the given macro before typing anything else"); - ("--eval", Arg.String (fun s -> - force_typing := true; - evals := s :: !evals; - ), " : evaluates argument as Haxe module code"); - ("--wait", Arg.String (fun hp -> - let host, port = (try ExtString.String.split hp ":" with _ -> "127.0.0.1", hp) in - wait_loop com host (try int_of_string port with _ -> raise (Arg.Bad "Invalid port")) - ),"<[host:]port> : wait on the given port for commands to run)"); - ("--connect",Arg.String (fun _ -> - assert false - ),"<[host:]port> : connect on the given port and run commands there)"); - ("--cwd", Arg.String (fun dir -> - assert false - )," : set current working directory"); - ("-version",Arg.Unit (fun() -> - message ctx s_version Ast.null_pos; - did_something := true; - ),": print version and exit"); - ("--help-defines", Arg.Unit (fun() -> - let m = ref 0 in - let rec loop i = - let d = Obj.magic i in - if d <> Define.Last then begin - let t, doc = Define.infos d in - if String.length t > !m then m := String.length t; - ((String.concat "-" (ExtString.String.nsplit t "_")),doc) :: (loop (i + 1)) - end else - [] - in - let all = List.sort (fun (s1,_) (s2,_) -> String.compare s1 s2) (loop 0) in - let all = List.map (fun (n,doc) -> Printf.sprintf " %-*s: %s" !m n (limit_string doc (!m + 3))) all in - List.iter (fun msg -> ctx.com.print (msg ^ "\n")) all; - did_something := true - ),": print help for all compiler specific defines"); - ("--help-metas", Arg.Unit (fun() -> - let m = ref 0 in - let rec loop i = - let d = Obj.magic i in - if d <> Meta.Last then begin - let t, (doc,flags) = MetaInfo.to_string d in - if not (List.mem MetaInfo.Internal flags) then begin - let params = ref [] and used = ref [] and pfs = ref [] in - List.iter (function - | MetaInfo.HasParam s -> params := s :: !params - | MetaInfo.Platform f -> pfs := f :: !pfs - | MetaInfo.Platforms fl -> pfs := fl @ !pfs - | MetaInfo.UsedOn u -> used := u :: !used - | MetaInfo.UsedOnEither ul -> used := ul @ !used - | MetaInfo.Internal -> assert false - ) flags; - let params = (match List.rev !params with - | [] -> "" - | l -> "(" ^ String.concat "," l ^ ")" - ) in - let pfs = (match List.rev !pfs with - | [] -> "" - | [p] -> " (" ^ platform_name p ^ " only)" - | pl -> " (for " ^ String.concat "," (List.map platform_name pl) ^ ")" - ) in - let str = "@" ^ t in - if String.length str > !m then m := String.length str; - (str,params ^ doc ^ pfs) :: loop (i + 1) - end else - loop (i + 1) - end else - [] - in - let all = List.sort (fun (s1,_) (s2,_) -> String.compare s1 s2) (loop 0) in - let all = List.map (fun (n,doc) -> Printf.sprintf " %-*s: %s" !m n (limit_string doc (!m + 3))) all in - List.iter (fun msg -> ctx.com.print (msg ^ "\n")) all; - did_something := true - ),": print help for all compiler metadatas"); - ] in - let args_callback cl = classes := make_path cl :: !classes in - let all_args_spec = basic_args_spec @ adv_args_spec in - let process args = - let current = ref 0 in - (try - Arg.parse_argv ~current (Array.of_list ("" :: List.map expand_env args)) all_args_spec args_callback usage; - List.iter (fun fn -> fn()) !arg_delays - with (Arg.Bad msg) as exc -> - let r = Str.regexp "unknown option `\\([-A-Za-z]+\\)'" in - try - ignore(Str.search_forward r msg 0); - let s = Str.matched_group 1 msg in - let sl = List.map (fun (s,_,_) -> s) all_args_spec in - let msg = Typecore.string_error_raise s sl (Printf.sprintf "Invalid command: %s" s) in - raise (Arg.Bad msg) - with Not_found -> - raise exc); - arg_delays := [] - in - process_ref := process; - process ctx.com.args; - process_libs(); - if com.display <> DMNone then begin - com.warning <- message ctx; - com.error <- error ctx; - com.main_class <- None; - let real = get_real_path (!Parser.resume_display).Ast.pfile in - classes := lookup_classes com real; - if !classes = [] then begin - if not (Sys.file_exists real) then failwith "Display file does not exist"; - (match List.rev (ExtString.String.nsplit real path_sep) with - | file :: _ when file.[0] >= 'a' && file.[1] <= 'z' -> failwith ("Display file '" ^ file ^ "' should not start with a lowercase letter") - | _ -> ()); - failwith "Display file was not found in class path"; - end; - Common.log com ("Display file : " ^ real); - Common.log com ("Classes found : [" ^ (String.concat "," (List.map Ast.s_type_path !classes)) ^ "]"); - end; - let add_std dir = - com.class_path <- List.filter (fun s -> not (List.mem s com.std_path)) com.class_path @ List.map (fun p -> p ^ dir ^ "/_std/") com.std_path @ com.std_path - in - let ext = (match com.platform with - | Cross -> - (* no platform selected *) - set_platform Cross ""; - "?" - | Flash -> - let rec loop = function - | [] -> () - | (v,_) :: _ when v > com.flash_version -> () - | (v,def) :: l -> - Common.raw_define com ("flash" ^ def); - loop l - in - loop Common.flash_versions; - Common.raw_define com "flash"; - com.package_rules <- PMap.remove "flash" com.package_rules; - add_std "flash"; - "swf" - | Neko -> - add_std "neko"; - "n" - | Js -> - add_std "js"; - "js" - | Php -> - add_std "php"; - "php" - | Cpp -> - add_std "cpp"; - "cpp" - | Cs -> - let old_flush = ctx.flush in - ctx.flush <- (fun () -> - com.net_libs <- []; - old_flush() - ); - Gencs.before_generate com; - add_std "cs"; "cs" - | Java -> - let old_flush = ctx.flush in - ctx.flush <- (fun () -> - List.iter (fun (_,_,close,_,_) -> close()) com.java_libs; - com.java_libs <- []; - old_flush() - ); - Genjava.before_generate com; - add_std "java"; "java" - | Python -> - add_std "python"; - "python" - ) in - (* if we are at the last compilation step, allow all packages accesses - in case of macros or opening another project file *) - begin match com.display with - | DMNone | DMToplevel -> - () - | _ -> - if not ctx.has_next then com.package_rules <- PMap.foldi (fun p r acc -> match r with Forbidden -> acc | _ -> PMap.add p r acc) com.package_rules PMap.empty; - end; - com.config <- get_config com; (* make sure to adapt all flags changes defined after platform *) - - List.iter (fun f -> f()) (List.rev (!pre_compilation)); - if !classes = [([],"Std")] && not !force_typing then begin - let help_spec = basic_args_spec @ [ - ("-help", Arg.Unit (fun () -> ()),": show extended help information"); - ("--help", Arg.Unit (fun () -> ()),": show extended help information"); - ("--help-defines", Arg.Unit (fun () -> ()),": print help for all compiler specific defines"); - ("--help-metas", Arg.Unit (fun () -> ()),": print help for all compiler metadatas"); - ("", Arg.Unit (fun () -> ()),": compile the module specified by dot-path"); - ] in - if !cmds = [] && not !did_something then Arg.usage help_spec usage; - end else begin - ctx.setup(); - Common.log com ("Classpath : " ^ (String.concat ";" com.class_path)); - Common.log com ("Defines : " ^ (String.concat ";" (PMap.foldi (fun v _ acc -> v :: acc) com.defines []))); - let t = Common.timer "typing" in - Typecore.type_expr_ref := (fun ctx e with_type -> Typer.type_expr ctx e with_type); - let tctx = Typer.create com in - List.iter (Typer.call_init_macro tctx) (List.rev !config_macros); - List.iter (Typer.eval tctx) !evals; - List.iter (fun cpath -> ignore(tctx.Typecore.g.Typecore.do_load_module tctx cpath Ast.null_pos)) (List.rev !classes); - Typer.finalize tctx; - t(); - if ctx.has_error then raise Abort; - begin match com.display with - | DMNone | DMUsage | DMPosition | DMType | DMResolve _ -> - () - | _ -> - if ctx.has_next then raise Abort; - failwith "No completion point was found"; - end; - let t = Common.timer "filters" in - let main, types, modules = Typer.generate tctx in - com.main <- main; - com.types <- types; - com.modules <- modules; - Filters.run com tctx main; - if ctx.has_error then raise Abort; - (* check file extension. In case of wrong commandline, we don't want - to accidentaly delete a source file. *) - if not !no_output && file_extension com.file = ext then delete_file com.file; - (match !xml_out with - | None -> () - | Some "hx" -> - Genxml.generate_hx com - | Some file -> - Common.log com ("Generating xml : " ^ file); - Common.mkdir_from_path file; - Genxml.generate com file); - if com.platform = Flash || com.platform = Cpp then List.iter (Codegen.fix_overrides com) com.types; - if Common.defined com Define.Dump then Codegen.dump_types com; - if Common.defined com Define.DumpDependencies then Codegen.dump_dependencies com; - t(); - if not !no_output then begin match com.platform with - | Neko when !interp -> () - | Cpp when Common.defined com Define.Cppia -> () - | Cpp | Cs | Java | Php -> Common.mkdir_from_path (com.file ^ "/.") - | _ -> Common.mkdir_from_path com.file - end; - (match com.platform with - | _ when !no_output -> - if !interp then begin - let ctx = Interp.create com (Typer.make_macro_api tctx Ast.null_pos) in - Interp.add_types ctx com.types (fun t -> ()); - (match com.main with - | None -> () - | Some e -> ignore(Interp.eval_expr ctx e)); - end; - | Cross -> - () - | Flash when Common.defined com Define.As3 -> - Common.log com ("Generating AS3 in : " ^ com.file); - Genas3.generate com; - | Flash -> - Common.log com ("Generating swf : " ^ com.file); - Genswf.generate com !swf_header; - | Neko -> - Common.log com ("Generating neko : " ^ com.file); - Genneko.generate com; - | Js -> - Common.log com ("Generating js : " ^ com.file); - Genjs.generate com - | Php -> - Common.log com ("Generating PHP in : " ^ com.file); - Genphp.generate com; - | Cpp -> - Common.log com ("Generating Cpp in : " ^ com.file); - Gencpp.generate com; - | Cs -> - Common.log com ("Generating Cs in : " ^ com.file); - Gencs.generate com; - | Java -> - Common.log com ("Generating Java in : " ^ com.file); - Genjava.generate com; - | Python -> - Common.log com ("Generating python in : " ^ com.file); - Genpy.generate com; - ); - end; - Sys.catch_break false; - List.iter (fun f -> f()) (List.rev com.final_filters); - if not !no_output then begin - List.iter (fun c -> - let r = run_command ctx c in - if r <> 0 then failwith ("Command failed with error " ^ string_of_int r) - ) (List.rev !cmds) - end -with - | Abort -> - () - | Ast.Error (m,p) -> - error ctx m p - | Typecore.Fatal_error (m,p) -> - error ctx m p - | Common.Abort (m,p) -> - error ctx m p - | Lexer.Error (m,p) -> - error ctx (Lexer.error_msg m) p - | Parser.Error (m,p) -> - error ctx (Parser.error_msg m) p - | Typecore.Forbid_package ((pack,m,p),pl,pf) -> - if !Common.display_default <> DMNone && ctx.has_next then begin - ctx.has_error <- false; - ctx.messages <- []; - end else begin - error ctx (Printf.sprintf "You cannot access the %s package while %s (for %s)" pack (if pf = "macro" then "in a macro" else "targeting " ^ pf) (Ast.s_type_path m) ) p; - List.iter (error ctx " referenced here") (List.rev pl); - end - | Typecore.Error (m,p) -> - error ctx (Typecore.error_msg m) p - | Interp.Error (msg,p :: l) -> - message ctx msg p; - List.iter (message ctx "Called from") l; - error ctx "Aborted" Ast.null_pos; - | Codegen.Generic_Exception(m,p) -> - error ctx m p - | Arg.Bad msg -> - error ctx ("Error: " ^ msg) Ast.null_pos - | Failure msg when not (is_debug_run()) -> - error ctx ("Error: " ^ msg) Ast.null_pos - | Arg.Help msg -> - message ctx msg Ast.null_pos - | Typer.DisplayFields fields -> - let ctx = print_context() in - let fields = List.map (fun (name,t,kind,doc) -> name, s_type ctx t, kind, (match doc with None -> "" | Some d -> d)) fields in - let fields = if !measure_times then begin - close_times(); - let tot = ref 0. in - Hashtbl.iter (fun _ t -> tot := !tot +. t.total) Common.htimers; - let fields = ("@TOTAL", Printf.sprintf "%.3fs" (get_time() -. !start_time), None, "") :: fields in - if !tot > 0. then - Hashtbl.fold (fun _ t acc -> - ("@TIME " ^ t.name, Printf.sprintf "%.3fs (%.0f%%)" t.total (t.total *. 100. /. !tot), None, "") :: acc - ) Common.htimers fields - else fields - end else - fields - in - complete_fields com fields - | Typecore.DisplayTypes tl -> - let ctx = print_context() in - let b = Buffer.create 0 in - List.iter (fun t -> - Buffer.add_string b "\n"; - Buffer.add_string b (htmlescape (s_type ctx t)); - Buffer.add_string b "\n\n"; - ) tl; - raise (Completion (Buffer.contents b)) - | Typecore.DisplayPosition pl -> - let b = Buffer.create 0 in - let error_printer file line = sprintf "%s:%d:" (Common.unique_full_path file) line in - Buffer.add_string b "\n"; - List.iter (fun p -> - let epos = Lexer.get_error_pos error_printer p in - Buffer.add_string b ""; - Buffer.add_string b epos; - Buffer.add_string b "\n"; - ) pl; - Buffer.add_string b ""; - raise (Completion (Buffer.contents b)) - | Typer.DisplayToplevel il -> - let b = Buffer.create 0 in - Buffer.add_string b "\n"; - let ctx = print_context() in - let s_type t = htmlescape (s_type ctx t) in - List.iter (fun id -> match id with - | Typer.ITLocal v -> Buffer.add_string b (Printf.sprintf "%s\n" (s_type v.v_type) v.v_name); - | Typer.ITMember(c,cf) -> Buffer.add_string b (Printf.sprintf "%s\n" (s_type cf.cf_type) cf.cf_name); - | Typer.ITStatic(c,cf) -> Buffer.add_string b (Printf.sprintf "%s\n" (s_type cf.cf_type) cf.cf_name); - | Typer.ITEnum(en,ef) -> Buffer.add_string b (Printf.sprintf "%s\n" (s_type ef.ef_type) ef.ef_name); - | Typer.ITGlobal(mt,s,t) -> Buffer.add_string b (Printf.sprintf "%s\n" (s_type_path (t_infos mt).mt_path) (s_type t) s); - | Typer.ITType(mt) -> Buffer.add_string b (Printf.sprintf "%s\n" (s_type_path (t_infos mt).mt_path) (snd (t_infos mt).mt_path)); - | Typer.ITPackage s -> Buffer.add_string b (Printf.sprintf "%s\n" s) - ) il; - Buffer.add_string b ""; - raise (Completion (Buffer.contents b)) - | Parser.TypePath (p,c,is_import) -> - (match c with - | None -> - let packs, classes = read_type_path com p in - if packs = [] && classes = [] then - error ctx ("No classes found in " ^ String.concat "." p) Ast.null_pos - else - complete_fields com ( - let convert k f = (f,"",Some k,"") in - (List.map (convert Typer.FKPackage) packs) @ (List.map (convert Typer.FKType) classes) - ) - | Some (c,cur_package) -> - try - let sl_pack,s_module = match List.rev p with - | s :: sl when s.[0] >= 'A' && s.[0] <= 'Z' -> List.rev sl,s - | _ -> p,c - in - let ctx = Typer.create com in - let rec lookup p = - try - Typeload.load_module ctx (p,s_module) Ast.null_pos - with e -> - if cur_package then - match List.rev p with - | [] -> raise e - | _ :: p -> lookup (List.rev p) - else - raise e - in - let m = lookup sl_pack in - let statics = ref None in - let public_types = List.filter (fun t -> - let tinfos = t_infos t in - let is_module_type = snd tinfos.mt_path = c in - if is_import && is_module_type then begin match t with - | TClassDecl c -> - ignore(c.cl_build()); - statics := Some c.cl_ordered_statics - | _ -> () - end; - not tinfos.mt_private - ) m.m_types in - let types = if c <> s_module then [] else List.map (fun t -> snd (t_path t),"",Some Typer.FKType,"") public_types in - let ctx = print_context() in - let make_field_doc cf = - cf.cf_name, - s_type ctx cf.cf_type, - Some (match cf.cf_kind with Method _ -> Typer.FKMethod | Var _ -> Typer.FKVar), - (match cf.cf_doc with Some s -> s | None -> "") - in - let types = match !statics with - | None -> types - | Some cfl -> types @ (List.map make_field_doc (List.filter (fun cf -> cf.cf_public) cfl)) - in - complete_fields com types - with Completion c -> - raise (Completion c) - | _ -> - error ctx ("Could not load module " ^ (Ast.s_type_path (p,c))) Ast.null_pos) - | Interp.Sys_exit i -> - ctx.flush(); - exit i - | e when (try Sys.getenv "OCAMLRUNPARAM" <> "b" || !global_cache <> None with _ -> true) && not (is_debug_run()) -> - error ctx (Printexc.to_string e) Ast.null_pos - -;; -let other = Common.timer "other" in -Sys.catch_break true; -let args = List.tl (Array.to_list Sys.argv) in -(try - let server = Sys.getenv "HAXE_COMPILATION_SERVER" in - let host, port = (try ExtString.String.split server ":" with _ -> "127.0.0.1", server) in - do_connect host (try int_of_string port with _ -> failwith "Invalid HAXE_COMPILATION_SERVER port") args -with Not_found -> try - process_params create_context args -with Completion c -> - prerr_endline c; - exit 0 -); -other(); -if !measure_times then report_times prerr_endline diff --git a/matcher.ml b/matcher.ml deleted file mode 100644 index 49397060..00000000 --- a/matcher.ml +++ /dev/null @@ -1,1454 +0,0 @@ -(* - * Copyright (C)2005-2013 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. - *) - -open Ast -open Common -open Type -open Typecore - -type pvar = tvar * pos - -type con_def = - | CEnum of tenum * tenum_field - | CConst of tconstant - | CAny - | CType of module_type - | CArray of int - | CFields of int * (string * tclass_field) list - | CExpr of texpr - -and con = { - c_def : con_def; - c_type : t; - c_pos : pos; -} - -and st_def = - | SVar of tvar - | SField of st * tclass_field - | SEnum of st * tenum_field * int - | SArray of st * int - | STuple of st * int * int - -and st = { - st_def : st_def; - st_type : t; - st_pos : pos; -} - -and dt = - | Switch of st * (con * dt) list - | Bind of ((tvar * pos) * st) list * dt - | Goto of int - | Expr of int - | Guard of int * dt * dt option - -(* Pattern *) - -type pat_def = - | PAny - | PVar of pvar - | PCon of con * pat list - | POr of pat * pat - | PBind of pvar * pat - | PTuple of pat array - -and pat = { - p_def : pat_def; - p_type : t; - p_pos : pos; -} - -type out = { - mutable o_pos : pos; - o_id : int; - o_catch_all : bool; - mutable o_num_paths : int; -} - -type pat_vec = pat array * out -type pat_matrix = pat_vec list - -(* Context *) - -type pattern_ctx = { - mutable pc_locals : (string, pvar) PMap.t; - mutable pc_sub_vars : (string, pvar) PMap.t option; - mutable pc_reify : bool; - mutable pc_is_complex : bool; -} - -type matcher = { - ctx : typer; - need_val : bool; - dt_lut : dt DynArray.t; - dt_cache : (dt,int) Hashtbl.t; - mutable dt_count : int; - mutable outcomes : out list; - mutable toplevel_or : bool; - mutable has_extractor : bool; - mutable expr_map : (int,texpr * texpr option) PMap.t; - mutable is_exhaustive : bool; -} - -type type_finiteness = - | Infinite (* type has inifite constructors (e.g. Int, String) *) - | CompileTimeFinite (* type is considered finite only at compile-time but has inifite possible run-time values (enum abstracts) *) - | RunTimeFinite (* type is truly finite (Bool, enums) *) - -exception Not_exhaustive of pat * st -exception Unrecognized_pattern of Ast.expr - -let arity con = match con.c_def with - | CEnum (_,{ef_type = TFun(args,_)}) -> List.length args - | CEnum _ -> 0 - | CConst _ -> 0 - | CType mt -> 0 - | CArray i -> i - | CFields (i,_) -> i - | CExpr _ -> 0 - | CAny -> 0 - -let mk_st def t p = { - st_def = def; - st_type = t; - st_pos = p; -} - -let mk_out mctx id e eg is_catch_all p = - let out = { - o_pos = p; - o_id = id; - o_catch_all = is_catch_all; - o_num_paths = 0; - } in - mctx.outcomes <- out :: mctx.outcomes; - mctx.expr_map <- PMap.add id (e,eg) mctx.expr_map; - out - -let clone_out mctx out p = - let out = {out with o_pos = p; } in - mctx.outcomes <- out :: mctx.outcomes; - out - -let get_guard mctx id = - snd (PMap.find id mctx.expr_map) - -let get_expr mctx id = - fst (PMap.find id mctx.expr_map) - -let mk_pat pdef t p = { - p_def = pdef; - p_type = t; - p_pos = p; -} - -let mk_con cdef t p = { - c_def = cdef; - c_type = t; - c_pos = p; -} - -let mk_con_pat cdef pl t p = mk_pat (PCon(mk_con cdef t p,pl)) t p - -let mk_any t p = mk_pat PAny t p - -let any = mk_any t_dynamic Ast.null_pos - -let fake_tuple_type = TInst(mk_class null_module ([],"-Tuple") null_pos, []) - -let mk_type_pat ctx mt t p = - let rec loop = function - | TClassDecl _ -> "Class" - | TEnumDecl _ -> "Enum" - | TAbstractDecl a when Meta.has Meta.RuntimeValue a.a_meta -> "Class" - | TTypeDecl t -> - begin match follow (monomorphs t.t_params t.t_type) with - | TInst(c,_) -> loop (TClassDecl c) - | TEnum(en,_) -> loop (TEnumDecl en) - | TAbstract(a,_) -> loop (TAbstractDecl a) - | _ -> error "Cannot use this type as a value" p - end - | _ -> error "Cannot use this type as a value" p - in - let tcl = Typeload.load_instance ctx {tname=loop mt;tpackage=[];tsub=None;tparams=[]} p true in - let t2 = match tcl with TAbstract(a,_) -> TAbstract(a,[mk_mono()]) | _ -> assert false in - unify ctx t t2 p; - mk_con_pat (CType mt) [] t2 p - -let mk_subs st con = - let map = match follow st.st_type with - | TInst(c,pl) -> apply_params c.cl_params pl - | TEnum(en,pl) -> apply_params en.e_params pl - | TAbstract(a,pl) -> apply_params a.a_params pl - | _ -> fun t -> t - in - match con.c_def with - | CFields (_,fl) -> List.map (fun (s,cf) -> mk_st (SField(st,cf)) (map cf.cf_type) st.st_pos) fl - | CEnum (en,({ef_type = TFun _} as ef)) -> - let rec loop t = match follow t with - | TEnum(_,pl) -> pl - | TAbstract({a_path = [],"EnumValue"},[]) -> [] - | TAbstract(a,pl) -> loop (Abstract.get_underlying_type a pl) - | _ -> [] - in - let pl = loop con.c_type in - begin match apply_params en.e_params pl (monomorphs ef.ef_params ef.ef_type) with - | TFun(args,r) -> - ExtList.List.mapi (fun i (_,_,t) -> - mk_st (SEnum(st,ef,i)) t st.st_pos - ) args - | _ -> - assert false - end - | CArray 0 -> [] - | CArray i -> - let t = match follow con.c_type with TInst({cl_path=[],"Array"},[t]) -> t | TDynamic _ as t -> t | _ -> assert false in - ExtList.List.init i (fun i -> mk_st (SArray(st,i)) t st.st_pos) - | CEnum _ | CConst _ | CType _ | CExpr _ | CAny -> - [] - -let get_tuple_params t = match t with - | TFun(tl,tr) when tr == fake_tuple_type -> Some tl - | _ -> None - -(* Printing *) - -let s_type = s_type (print_context()) - -let rec s_con con = match con.c_def with - | CEnum(_,ef) -> ef.ef_name - | CAny -> "_" - | CConst c -> s_const c - | CType mt -> s_type_path (t_path mt) - | CArray i -> "[" ^(string_of_int i) ^ "]" - | CFields (_,fl) -> String.concat "," (List.map (fun (s,_) -> s) fl) - | CExpr e -> s_expr s_type e - -let rec s_pat pat = match pat.p_def with - | PVar (v,_) -> v.v_name - | PCon (c,[]) -> s_con c - | PCon (c,pl) -> s_con c ^ "(" ^ (String.concat "," (List.map s_pat pl)) ^ ")" - | POr (pat1,pat2) -> s_pat pat1 ^ " | " ^ s_pat pat2 - | PAny -> "_" - | PBind((v,_),pat) -> v.v_name ^ "=" ^ s_pat pat - | PTuple pl -> "(" ^ (String.concat " " (Array.to_list (Array.map s_pat pl))) ^ ")" - -let rec s_pat_vec pl = - String.concat " " (Array.to_list (Array.map s_pat pl)) - -let rec s_pat_matrix pmat = - String.concat "\n" (List.map (fun (pl,out) -> (s_pat_vec pl) ^ "->" ^ "") pmat) - -let st_args l r v = - (if l > 0 then (String.concat "," (ExtList.List.make l "_")) ^ "," else "") - ^ v ^ - (if r > 0 then "," ^ (String.concat "," (ExtList.List.make r "_")) else "") - -let rec s_st st = - (match st.st_def with - | SVar v -> v.v_name - | SEnum (st,ef,i) -> s_st st ^ "." ^ ef.ef_name ^ "." ^ (string_of_int i) - | SArray (st,i) -> s_st st ^ "[" ^ (string_of_int i) ^ "]" - | STuple (st,i,a) -> "(" ^ (st_args i (a - i - 1) (s_st st)) ^ ")" - | SField (st,cf) -> s_st st ^ "." ^ cf.cf_name) - -(* Pattern parsing *) - -let unify_enum_field en pl ef t = - let t2 = match follow ef.ef_type with - | TFun(_,r) -> r - | t2 -> t2 - in - let t2 = (apply_params en.e_params pl (monomorphs ef.ef_params t2)) in - Type.unify t2 t - -let unify ctx a b p = - try unify_raise ctx a b p with Error (Unify l,p) -> error (error_msg (Unify l)) p - -let rec is_value_type = function - | TMono r -> - (match !r with None -> false | Some t -> is_value_type t) - | TType (t,tl) -> - is_value_type (apply_params t.t_params tl t.t_type) - | TInst({cl_path=[],"String"},[]) -> - true - | TAbstract _ -> - true - | _ -> - false - -(* Determines if a type allows null-matching. This is similar to is_nullable, but it infers Null on monomorphs *) -let rec matches_null ctx t = match t with - | TMono r -> - (match !r with None -> r := Some (ctx.t.tnull (mk_mono())); true | Some t -> matches_null ctx t) - | TType ({ t_path = ([],"Null") },[_]) -> - true - | TLazy f -> - matches_null ctx (!f()) - | TType (t,tl) -> - matches_null ctx (apply_params t.t_params tl t.t_type) - | TFun _ -> - false - | TAbstract (a,_) -> not (Meta.has Meta.NotNull a.a_meta) - | _ -> - true - -let to_pattern ctx e t = - let perror p = error "Unrecognized pattern" p in - let verror n p = error ("Variable " ^ n ^ " must appear exactly once in each sub-pattern") p in - let mk_var tctx s t p = - let v = match tctx.pc_sub_vars with - | Some vmap -> fst (try PMap.find s vmap with Not_found -> verror s p) - | None -> alloc_var s t - in - unify ctx t v.v_type p; - if PMap.mem s tctx.pc_locals then verror s p; - tctx.pc_locals <- PMap.add s (v,p) tctx.pc_locals; - v - in - let check_texpr_pattern e t p = - let ec = match Optimizer.make_constant_expression ctx ~concat_strings:true e with Some e -> e | None -> e in - match ec.eexpr with - | TField (_,FEnum (en,ef)) -> - begin try unify_raise ctx ec.etype t ec.epos with Error (Unify _,_) -> raise Not_found end; - begin try - unify_enum_field en (List.map (fun _ -> mk_mono()) en.e_params) ef t; - with Unify_error l -> - error (error_msg (Unify l)) p - end; - mk_con_pat (CEnum(en,ef)) [] t p - | TConst c | TCast({eexpr = TConst c},None) -> - begin try unify_raise ctx ec.etype t ec.epos with Error (Unify _,_) -> raise Not_found end; - unify ctx ec.etype t p; - mk_con_pat (CConst c) [] t p - | TTypeExpr mt -> - mk_type_pat ctx mt t p - | _ -> - raise Not_found - in - let rec loop pctx e t = - let p = pos e in - match fst e with - | ECheckType(e, CTPath({tpackage=["haxe";"macro"]; tname="Expr"})) -> - let old = pctx.pc_reify in - pctx.pc_reify <- true; - let e = loop pctx e t in - pctx.pc_reify <- old; - e - | EParenthesis e -> - loop pctx e t - | ECast(e1,None) -> - loop pctx e1 t - | EConst(Ident "null") -> - if not (matches_null ctx t) then error ("Null-patterns are only allowed on nullable types (found " ^ (s_type t) ^ ")") p; - mk_con_pat (CConst TNull) [] t p - | EConst((Ident ("false" | "true") | Int _ | String _ | Float _) as c) -> - let e = Codegen.type_constant ctx.com c p in - unify ctx e.etype t p; - let c = match e.eexpr with TConst c -> c | _ -> assert false in - mk_con_pat (CConst c) [] t p - | EMeta((Meta.Macro,[],_),(ECall (e1,args),_)) -> - let path, field, args = Codegen.get_macro_path ctx e1 args p in - begin match ctx.g.do_macro ctx MExpr path field args p with - | Some e -> loop pctx e t - | None -> error "Macro failure" p - end - | EField _ -> - let e = type_expr ctx e (WithType t) in - let e = match Optimizer.make_constant_expression ctx ~concat_strings:true e with Some e -> e | None -> e in - (match e.eexpr with - | TConst c | TCast({eexpr = TConst c},None) -> - mk_con_pat (CConst c) [] t p - | TTypeExpr mt -> - mk_type_pat ctx mt t p - | TField(_, FStatic(_,cf)) when is_value_type cf.cf_type -> - ignore (follow cf.cf_type); - begin match cf.cf_expr with - | Some e -> - (try check_texpr_pattern e t p with Not_found -> mk_con_pat (CExpr e) [] cf.cf_type p) - | None -> - mk_con_pat (CExpr e) [] cf.cf_type p - end - | TField(_, FEnum(en,ef)) -> - begin try - unify_enum_field en (List.map (fun _ -> mk_mono()) en.e_params) ef t - with Unify_error l -> - error (error_msg (Unify l)) p - end; - mk_con_pat (CEnum(en,ef)) [] t p - | _ -> error "Constant expression expected" p) - | ECall(ec,el) -> - let ec = type_expr ctx ec (WithType t) in - (match follow ec.etype with - | TEnum(en,pl) - | TFun(_,TEnum(en,pl)) -> - let ef = match ec.eexpr with - | TField (_,FEnum (_,f)) -> f - | _ -> error ("Expected constructor for enum " ^ (s_type_path en.e_path)) p - in - let monos = List.map (fun _ -> mk_mono()) ef.ef_params in - let tl,r = match apply_params en.e_params pl (apply_params ef.ef_params monos ef.ef_type) with - | TFun(args,r) -> - unify ctx r t p; - List.map (fun (n,_,t) -> t) args,r - | _ -> error "No arguments expected" p - in - let rec loop2 i el tl = match el,tl with - | (EConst(Ident "_"),pany) :: [], t :: tl -> - let pat = mk_pat PAny t_dynamic pany in - (ExtList.List.make ((List.length tl) + 1) pat) - | e :: el, t :: tl -> - let pat = loop pctx e t in - pat :: loop2 (i + 1) el tl - | e :: _, [] -> - error "Too many arguments" (pos e); - | [],_ :: _ -> - error "Not enough arguments" p; - | [],[] -> - [] - in - let el = loop2 0 el tl in - List.iter2 (fun m (_,t) -> match follow m with TMono _ -> Type.unify m t | _ -> ()) monos ef.ef_params; - pctx.pc_is_complex <- true; - mk_con_pat (CEnum(en,ef)) el r p - | _ -> perror p) - | EConst(Ident "_") -> - begin match get_tuple_params t with - | Some tl -> - let pl = List.map (fun (_,_,t) -> mk_any t p) tl in - mk_pat (PTuple (Array.of_list pl)) t_dynamic p - | None -> - mk_any t p - end - | EConst(Ident s) -> - begin try - let ec = match follow t with - | TEnum(en,pl) -> - let ef = try - PMap.find s en.e_constrs - with Not_found when not (is_lower_ident s) -> - error (string_error s en.e_names ("Expected constructor for enum " ^ (s_type_path en.e_path))) p - in - (match ef.ef_type with - | TFun (args,_) -> - let msg = Printf.sprintf "Enum constructor %s.%s requires parameters %s" - (s_type_path en.e_path) - ef.ef_name - (String.concat ", " (List.map (fun (n,_,t) -> n ^ ":" ^ (s_type t)) args)) - in - error msg p - | _ -> ()); - let et = mk (TTypeExpr (TEnumDecl en)) (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics en) }) p in - mk (TField (et,FEnum (en,ef))) (apply_params en.e_params pl ef.ef_type) p - | TAbstract({a_impl = Some c} as a,_) when Meta.has Meta.Enum a.a_meta -> - let cf = PMap.find s c.cl_statics in - Type.unify (follow cf.cf_type) t; - let e = begin match cf.cf_expr with - | Some ({eexpr = TConst c | TCast({eexpr = TConst c},None)} as e) -> e - | _ -> raise Not_found - end in - e - | _ -> - let old = ctx.untyped in - ctx.untyped <- true; - let e = try type_expr ctx e (WithType t) with _ -> ctx.untyped <- old; raise Not_found in - ctx.untyped <- old; - e - in - check_texpr_pattern ec t p - with Not_found -> - begin match get_tuple_params t with - | Some tl -> - let s = String.concat "," (List.map (fun (_,_,t) -> s_type t) tl) in - error ("Pattern should be tuple [" ^ s ^ "]") p - | None -> - if not (is_lower_ident s) && s.[0] <> '`' then error "Capture variables must be lower-case" p; - let v = mk_var pctx s t p in - mk_pat (PVar (v,p)) v.v_type p - end - end - | (EObjectDecl fl) -> - let is_matchable cf = match cf.cf_kind with Method _ -> false | _ -> true in - let is_valid_field_name fields co n p = - try - let cf = PMap.find n fields in - begin match co with - | Some c when not (Typer.can_access ctx c cf false) -> error ("Cannot match against private field " ^ n) p - | _ -> () - end - with Not_found -> - error ((s_type t) ^ " has no field " ^ n ^ " that can be matched against") p; - in - pctx.pc_is_complex <- true; - let loop_fields fields = - let sl,pl,i = PMap.foldi (fun n cf (sl,pl,i) -> - if not (is_matchable cf) then - sl,pl,i - else - let pat = try - if pctx.pc_reify && cf.cf_name = "pos" then raise Not_found; - loop pctx (List.assoc cf.cf_name fl) cf.cf_type - with Not_found -> - (mk_any cf.cf_type p) - in - (n,cf) :: sl,pat :: pl,i + 1 - ) fields ([],[],0) in - mk_con_pat (CFields(i,sl)) pl t p - in - let fields = match follow t with - | TAnon {a_fields = fields} -> - fields - | TInst(c,tl) -> - let fields = ref PMap.empty in - let rec loop c tl = - begin match c.cl_super with - | Some (csup,tlsup) -> loop csup (List.map (apply_params c.cl_params tl) tlsup) - | None -> () - end; - PMap.iter (fun n cf -> fields := PMap.add n {cf with cf_type = apply_params c.cl_params tl (monomorphs cf.cf_params cf.cf_type)} !fields) c.cl_fields - in - loop c tl; - !fields - | TAbstract({a_impl = Some c} as a,tl) -> - let fields = List.fold_left (fun acc cf -> - if Meta.has Meta.Impl cf.cf_meta then - PMap.add cf.cf_name cf acc - else acc - ) PMap.empty c.cl_ordered_statics in - PMap.map (fun cf -> {cf with cf_type = apply_params a.a_params tl (monomorphs cf.cf_params cf.cf_type)}) fields - | _ -> - error ((s_type t) ^ " cannot be matched against a structure") p - in - List.iter (fun (n,(_,p)) -> is_valid_field_name fields None n p) fl; - loop_fields fields - | EArrayDecl [] -> - mk_con_pat (CArray 0) [] t p - | EArrayDecl el -> - pctx.pc_is_complex <- true; - begin match follow t with - | TInst({cl_path=[],"Array"},[t2]) | (TDynamic _ as t2) -> - let pl = ExtList.List.mapi (fun i e -> - loop pctx e t2 - ) el in - mk_con_pat (CArray (List.length el)) pl t p - | TFun(tl,tr) when tr == fake_tuple_type -> - let pl = try - List.map2 (fun e (_,_,t) -> loop pctx e t) el tl - with Invalid_argument _ -> - error ("Invalid number of arguments: expected " ^ (string_of_int (List.length tl)) ^ ", found " ^ (string_of_int (List.length el))) p - in - mk_pat (PTuple (Array.of_list pl)) t p - | _ -> - error ((s_type t) ^ " should be Array") p - end - | EBinop(OpAssign,(EConst(Ident s),p2),e1) -> - let v = mk_var pctx s t p in - let pat1 = loop pctx e1 t in - mk_pat (PBind((v,p),pat1)) t p2 - | EBinop(OpOr,(EBinop(OpOr,e1,e2),p2),e3) -> - loop pctx (EBinop(OpOr,e1,(EBinop(OpOr,e2,e3),p2)),p) t - | EBinop(OpOr,e1,e2) -> - let old = pctx.pc_locals in - let pat1 = loop pctx e1 t in - begin match pat1.p_def with - | PAny | PVar _ -> - display_error ctx "This pattern is unused" (pos e2); - pat1 - | _ -> - let pctx2 = { - pc_sub_vars = Some pctx.pc_locals; - pc_locals = old; - pc_reify = pctx.pc_reify; - pc_is_complex = pctx.pc_is_complex; - } in - let pat2 = loop pctx2 e2 t in - pctx.pc_is_complex <- pctx2.pc_is_complex; - PMap.iter (fun s (_,p) -> if not (PMap.mem s pctx2.pc_locals) then verror s p) pctx.pc_locals; - mk_pat (POr(pat1,pat2)) pat2.p_type (punion pat1.p_pos pat2.p_pos); - end - | _ -> - raise (Unrecognized_pattern e) - in - let pctx = { - pc_locals = PMap.empty; - pc_sub_vars = None; - pc_reify = false; - pc_is_complex = false; - } in - let x = loop pctx e t in - x, pctx.pc_locals, pctx.pc_is_complex - -let get_pattern_locals ctx e t = - try - let _,locals,_ = to_pattern ctx e t in - PMap.foldi (fun n v acc -> PMap.add n v acc) locals PMap.empty - with Unrecognized_pattern _ -> - PMap.empty - -(* Match compilation *) - -let expr_eq e1 e2 = e1 == e2 || match e1.eexpr,e2.eexpr with - | TConst ct1,TConst ct2 -> - ct1 = ct2 - | TField(_,FStatic(c1,cf1)),TField(_,FStatic(c2,cf2)) -> - c1 == c2 && cf1.cf_name = cf2.cf_name - | _ -> - false - -let unify_con con1 con2 = match con1.c_def,con2.c_def with - | CExpr e1, CExpr e2 -> - expr_eq e1 e2 - | CConst c1,CConst c2 -> - c1 = c2 - | CEnum(e1,ef1),CEnum(e2,ef2) -> - e1 == e2 && ef1.ef_name = ef2.ef_name - | CFields (i1,fl1),CFields (i2,fl2) -> - (try - List.iter (fun (s,_) -> if not (List.mem_assoc s fl1) then raise Not_found) fl2; - true - with Not_found -> - false) - | CType mt1,CType mt2 -> - t_path mt1 = t_path mt2 - | CArray a1, CArray a2 -> - a1 == a2 - | CAny, CAny -> - true - | _ -> - false - -let array_tl arr = Array.sub arr 1 (Array.length arr - 1) - -let spec mctx con pmat = - let a = arity con in - let r = DynArray.create () in - let add pv out = - DynArray.add r (pv,out) - in - let rec loop2 pv out = match pv.(0).p_def with - | PCon(c2,pl) when unify_con c2 con -> - add (Array.append (Array.of_list pl) (array_tl pv)) out - | PCon(c2,pl) -> - () - | PAny | PVar _-> - add (Array.append (Array.make a (mk_any (pv.(0).p_type) (pv.(0).p_pos))) (array_tl pv)) out - | PBind(_,pat) -> - loop2 (Array.append [|pat|] (array_tl pv)) out - | PTuple tl -> - loop2 tl out - | POr _ -> - assert false - in - let rec loop pmat = match pmat with - | (pv,out) :: pl -> - loop2 pv out; - loop pl - | [] -> - () - in - loop pmat; - DynArray.to_list r - -let default mctx pmat = - let r = DynArray.create () in - let add pv out = - DynArray.add r (pv,out) - in - let rec loop2 pv out = match pv.(0).p_def with - | PCon _ -> - () - | PAny | PVar _-> - add (array_tl pv) out - | PBind(_,pat) -> - loop2 (Array.append [|pat|] (array_tl pv)) out - | PTuple tl -> - loop2 tl out - | POr _ -> - assert false - in - let rec loop pmat = match pmat with - | (pv,out) :: pl -> - loop2 pv out; - loop pl; - | [] -> - () - in - loop pmat; - DynArray.to_list r - -let pick_column pmat = - let rec loop i pv = if Array.length pv = 0 then -1 else match pv.(0).p_def with - | PVar _ | PAny -> - loop (i + 1) (array_tl pv) - | PTuple pl -> - loop i pl - | _ -> - i - in - loop 0 (fst (List.hd pmat)) - -let swap_pmat_columns i pmat = - List.map (fun (pv,out) -> - let pv = match pv with [|{p_def = PTuple pt}|] -> pt | _ -> pv in - let tmp = pv.(i) in - Array.set pv i pv.(0); - Array.set pv 0 tmp; - pv,out - ) pmat - -let swap_columns i (row : 'a list) : 'a list = - match row with - | rh :: rt -> - let rec loop count acc col = match col with - | [] -> acc - | ch :: cl when i = count -> - ch :: (List.rev acc) @ [rh] @ cl - | ch :: cl -> - loop (count + 1) (ch :: acc) cl - in - loop 1 [] rt - | _ -> - [] - -let expand_or mctx (pmat : pat_matrix) = - let rec loop pat = match pat.p_def with - | POr(pat1,pat2) -> - let pat1 = loop pat1 in - let pat2 = loop pat2 in - pat1 @ pat2 - | PBind(v,pat1) -> - let pat1 = loop pat1 in - List.map (fun pat1 -> - {pat with p_def = PBind(v,pat1)} - ) pat1 - | PTuple(pl) -> - let pat1 = loop pl.(0) in - List.map (fun pat1 -> - let a1 = Array.copy pl in - a1.(0) <- pat1; - {pat with p_def = PTuple a1} - ) pat1 - | _ -> - [pat] - in - let rec loop2 pmat = match pmat with - | (pv,out) :: pmat -> - let pat = loop pv.(0) in - let pat' = ExtList.List.mapi (fun i pat -> - (* TODO: This should really be active, but currently causes problems with or-patterns in - tuples (issue #2610). We will disable this for the 3.1.0 release, which means issue - #2508 is open again. *) - (* let out = if i = 0 then out else clone_out mctx out pat.p_pos in *) - let a1 = Array.copy pv in - a1.(0) <- pat; - a1,out - ) pat in - pat' @ (loop2 pmat) - | [] -> - [] - in - loop2 pmat - -let column_sigma mctx st pmat = - let acc = ref [] in - let bindings = ref [] in - let unguarded = Hashtbl.create 0 in - let add c g = - if not (List.exists (fun c2 -> unify_con c2 c) !acc) then acc := c :: !acc; - if not g then Hashtbl.replace unguarded c.c_def true; - in - let bind_st out st v = - if not (List.exists (fun ((v2,p),_) -> v2.v_id == (fst v).v_id) !bindings) then bindings := (v,st) :: !bindings - in - let rec loop pmat = match pmat with - | (pv,out) :: pr -> - let rec loop2 out = function - | PCon (c,_) -> - add c ((get_guard mctx out.o_id) <> None); - | PVar v -> - bind_st out st v; - | PBind(v,pat) -> - bind_st out st v; - loop2 out pat.p_def - | PAny -> - () - | PTuple tl -> - loop2 out tl.(0).p_def - | POr _ -> - assert false - in - loop2 out pv.(0).p_def; - loop pr - | [] -> - () - in - loop pmat; - List.rev_map (fun con -> con,not (Hashtbl.mem unguarded con.c_def)) !acc,!bindings - -let rec all_ctors mctx t = - let h = ref PMap.empty in - if is_explicit_null t then h := PMap.add (CConst TNull) Ast.null_pos !h; - match follow t with - | TAbstract({a_path = [],"Bool"},_) -> - h := PMap.add (CConst(TBool true)) Ast.null_pos !h; - h := PMap.add (CConst(TBool false)) Ast.null_pos !h; - h,RunTimeFinite - | TAbstract({a_impl = Some c} as a,pl) when Meta.has Meta.Enum a.a_meta -> - List.iter (fun cf -> - ignore(follow cf.cf_type); - if Meta.has Meta.Impl cf.cf_meta then match cf.cf_expr with - | Some {eexpr = TConst c | TCast ({eexpr = TConst c},None)} -> h := PMap.add (CConst c) cf.cf_pos !h - | _ -> () - ) c.cl_ordered_statics; - h,CompileTimeFinite - | TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) -> all_ctors mctx (Abstract.get_underlying_type a pl) - | TInst({cl_path=[],"String"},_) - | TInst({cl_path=[],"Array"},_) -> - h,Infinite - | TEnum(en,pl) -> - PMap.iter (fun _ ef -> - let tc = monomorphs mctx.ctx.type_params t in - try unify_enum_field en pl ef tc; - h := PMap.add (CEnum(en,ef)) ef.ef_pos !h - with Unify_error _ -> - () - ) en.e_constrs; - h,RunTimeFinite - | TAnon a -> - h,CompileTimeFinite - | TInst(_,_) -> - h,CompileTimeFinite - | _ -> - h,Infinite - -let rec collapse_pattern pl = match pl with - | pat :: [] -> - pat - | pat :: pl -> - let pat2 = collapse_pattern pl in - mk_pat (POr(pat,pat2)) pat.p_type (punion pat.p_pos pat2.p_pos) - | [] -> - assert false - -let bind_remaining out pv stl = - let rec loop stl pv = - if Array.length pv = 0 then - [] - else - match stl,pv.(0).p_def with - | st :: stl,PAny -> - loop stl (array_tl pv) - | st :: stl,PVar v -> - (v,st) :: loop stl (array_tl pv) - | stl,PTuple pl -> - loop stl pl - | _ :: _,_-> - loop stl (array_tl pv) - | [],_ -> - [] - in - loop stl pv - -let get_cache mctx dt = - match dt with Goto _ -> dt | _ -> - try - Goto (Hashtbl.find mctx.dt_cache dt) - with Not_found -> - Hashtbl.replace mctx.dt_cache dt mctx.dt_count; - mctx.dt_count <- mctx.dt_count + 1; - DynArray.add mctx.dt_lut dt; - dt - -let rec compile mctx stl pmat toplevel = - let guard id dt1 dt2 = get_cache mctx (Guard(id,dt1,dt2)) in - let expr id = get_cache mctx (Expr id) in - let bind bl dt = get_cache mctx (Bind(bl,dt)) in - let switch st cl = get_cache mctx (Switch(st,cl)) in - get_cache mctx (match pmat with - | [] -> - (match stl with - | st :: stl -> - let all,inf = all_ctors mctx st.st_type in - let pl = PMap.foldi (fun cd p acc -> (mk_con_pat cd [] t_dynamic p) :: acc) !all [] in - begin match pl,inf with - | _,Infinite - | [],_ -> - raise (Not_exhaustive(any,st)) - | _ -> - raise (Not_exhaustive(collapse_pattern pl,st)) - end - | _ -> - (* This can happen in cases a value is required and all default cases are guarded (issue #3150). - Not a particularly elegant solution, may want to revisit this later. *) - raise Exit) - | ([|{p_def = PTuple pt}|],out) :: pl -> - compile mctx stl ((pt,out) :: pl) toplevel - | (pv,out) :: pl -> - let i = pick_column pmat in - if i = -1 then begin - out.o_num_paths <- out.o_num_paths + 1; - let bl = bind_remaining out pv stl in - let dt = match (get_guard mctx out.o_id) with - | None -> - expr out.o_id - | Some _ -> - let dt = match pl,mctx.need_val with - | [],false -> - None - | _ -> - Some (compile mctx stl pl false) - in - guard out.o_id (expr out.o_id) dt - in - (if bl = [] then dt else bind bl dt) - end else if i > 0 then begin - let pmat = swap_pmat_columns i pmat in - let stls = swap_columns i stl in - compile mctx stls pmat toplevel - end else begin - let st_head,st_tail = match stl with st :: stl -> st,stl | _ -> assert false in - let pmat = expand_or mctx pmat in - let sigma,bl = column_sigma mctx st_head pmat in - let all,inf = all_ctors mctx pv.(0).p_type in - let cases = List.map (fun (c,g) -> - if not g then all := PMap.remove c.c_def !all; - let spec = spec mctx c pmat in - let hsubs = mk_subs st_head c in - let subs = hsubs @ st_tail in - let dt = compile mctx subs spec false in - c,dt - ) sigma in - let def = default mctx pmat in - let dt = match def,cases with - | _ when inf = RunTimeFinite && PMap.is_empty !all -> - switch st_head cases - | [],_ when inf = CompileTimeFinite && PMap.is_empty !all -> - switch st_head cases - | [],_ when inf = Infinite && not mctx.need_val && toplevel -> - (* ignore exhaustiveness, but mark context so we do not generate @:exhaustive metadata *) - mctx.is_exhaustive <- false; - switch st_head cases - | [],_ when inf = Infinite -> - raise (Not_exhaustive(any,st_head)) - | [],_ -> - let pl = PMap.foldi (fun cd p acc -> (mk_con_pat cd [] t_dynamic p) :: acc) !all [] in - (* toplevel null can be omitted because the French dig runtime errors (issue #3054) *) - if toplevel && (match pl with - | [{p_def = PCon ({c_def = (CConst TNull)},_)}] -> true - | _ -> false) then - switch st_head cases - else - raise (Not_exhaustive(collapse_pattern pl,st_head)) - | def,[] -> - compile mctx st_tail def false - | def,_ -> - let cdef = mk_con CAny t_dynamic st_head.st_pos in - let def = try - compile mctx st_tail def false - with Exit -> - raise (Not_exhaustive(any,st_head)) - in - let cases = cases @ [cdef,def] in - switch st_head cases - in - if bl = [] then dt else bind bl dt - end) - -let rec collapse_case el = match el with - | e :: [] -> - e - | e :: el -> - let e2 = collapse_case el in - EBinop(OpOr,e,e2),punion (pos e) (pos e2) - | [] -> - assert false - -let mk_const ctx p = function - | TString s -> mk (TConst (TString s)) ctx.com.basic.tstring p - | TInt i -> mk (TConst (TInt i)) ctx.com.basic.tint p - | TFloat f -> mk (TConst (TFloat f)) ctx.com.basic.tfloat p - | TBool b -> mk (TConst (TBool b)) ctx.com.basic.tbool p - | TNull -> mk (TConst TNull) (ctx.com.basic.tnull (mk_mono())) p - | _ -> error "Unsupported constant" p - -let rec convert_st ctx st = match st.st_def with - | SVar v -> mk (TLocal v) v.v_type st.st_pos - | SField (sts,cf) -> - let e = convert_st ctx sts in - Typer.acc_get ctx (Typer.type_field ctx e cf.cf_name st.st_pos Typer.MGet) st.st_pos - | SArray (sts,i) -> mk (TArray(convert_st ctx sts,mk_const ctx st.st_pos (TInt (Int32.of_int i)))) st.st_type st.st_pos - | STuple (st,_,_) -> convert_st ctx st - | SEnum (sts,ef,i) -> mk (TEnumParameter(convert_st ctx sts, ef, i)) st.st_type st.st_pos - -let convert_con ctx con = match con.c_def with - | CConst c -> mk_const ctx con.c_pos c - | CType mt -> mk (TTypeExpr mt) t_dynamic con.c_pos - | CExpr e -> e - | CEnum(e,ef) -> mk_const ctx con.c_pos (TInt (Int32.of_int ef.ef_index)) - | CArray i -> mk_const ctx con.c_pos (TInt (Int32.of_int i)) - | CAny | CFields _ -> assert false - -let convert_switch mctx st cases loop = - let ctx = mctx.ctx in - let e_st = convert_st ctx st in - let p = e_st.epos in - let mk_index_call () = - let ttype = match follow (Typeload.load_instance ctx { tpackage = ["std"]; tname="Type"; tparams=[]; tsub = None} p true) with TInst(c,_) -> c | t -> assert false in - let cf = PMap.find "enumIndex" ttype.cl_statics in - let ec = (!type_module_type_ref) ctx (TClassDecl ttype) None p in - let ef = mk (TField(ec, FStatic(ttype,cf))) (tfun [e_st.etype] ctx.t.tint) p in - let e = make_call ctx ef [e_st] ctx.t.tint p in - e - in - let wrap_exhaustive e = - if mctx.is_exhaustive then - mk (TMeta((Meta.Exhaustive,[],e.epos),e)) e.etype e.epos - else - e - in - let e = match follow st.st_type with - | TEnum(_) -> - wrap_exhaustive (mk_index_call()) - | TAbstract(a,pl) when (match Abstract.get_underlying_type a pl with TEnum(_) -> true | _ -> false) -> - wrap_exhaustive (mk_index_call()) - | TInst({cl_path = [],"Array"},_) as t -> - mk (TField (e_st,quick_field t "length")) ctx.t.tint p - | TAbstract(a,_) when Meta.has Meta.Enum a.a_meta -> - wrap_exhaustive (e_st) - | TAbstract({a_path = [],"Bool"},_) -> - wrap_exhaustive (e_st) - | _ -> - let rec loop cases = match cases with - | [] -> e_st - | (con,_) :: cases -> - begin match con.c_def with - | CEnum _ -> mk_index_call() - | CArray _ -> mk (TField (e_st,FDynamic "length")) ctx.t.tint p - | _ -> loop cases - end - in - loop cases - in - let null = ref None in - let def = ref None in - let cases = List.filter (fun (con,dt) -> - match con.c_def with - | CConst TNull -> - null := Some (loop dt); - false - | CAny -> - def := Some (loop dt); - false - | _ -> - true - ) cases in - let dt = match cases with - | [{c_def = CFields _},dt] -> loop dt - | _ -> DTSwitch(e, List.map (fun (c,dt) -> convert_con ctx c, loop dt) cases, !def) - in - match !null with - | None when is_explicit_null st.st_type && (!def <> None || not mctx.need_val) -> - let econd = mk (TBinop(OpNotEq,e_st,mk (TConst TNull) st.st_type p)) ctx.t.tbool p in - DTGuard(econd,dt,!def) - | None -> - dt - | Some dt_null -> - let t = match ctx.t.tnull ctx.t.tint with - | TType(t,_) ->TType(t,[st.st_type]) - | t -> t - in - let e_null = mk (TConst TNull) t p in - let econd = mk (TBinop(OpEq,e_st, e_null)) ctx.t.tbool p in - DTGuard(econd,dt_null,Some dt) - -(* Decision tree compilation *) - -let transform_extractors eval cases p = - let efail = (EThrow(EConst(Ident "false"),p)),p in - let cfail = [(EConst (Ident "_"),p)],None,Some efail in - let has_extractor = ref false in - let rec loop cases = match cases with - | (epat,eg,e) :: cases -> - let ex = ref [] in - let exc = ref 0 in - let rec find_ex in_or e = match fst e with - | EBinop(OpArrow,_,_) when in_or -> - error "Extractors in or patterns are not allowed" (pos e) - | EBinop(OpArrow, e1, e2) -> - let ec = EConst (Ident ("__ex" ^ string_of_int (!exc))),snd e in - let rec map_left e = match fst e with - | EConst(Ident "_") -> ec - | _ -> Ast.map_expr map_left e - in - let ecall = map_left e1 in - ex := (ecall,e2) :: !ex; - incr exc; - has_extractor := true; - ec - | EBinop(OpOr,e1,e2) -> - let e1 = find_ex true e1 in - let e2 = find_ex true e2 in - (EBinop(OpOr,e1,e2)),(pos e) - | _ -> - Ast.map_expr (find_ex in_or) e - in - let p = match e with None -> p | Some e -> pos e in - let epat = match epat with - | [epat] -> [find_ex false epat] - | _ -> List.map (find_ex true) epat - in - let cases = loop cases in - if !exc = 0 then - (epat,eg,e) :: cases - else begin - let esubjects = EArrayDecl (List.map fst !ex),p in - let case1 = [EArrayDecl (List.map snd !ex),p],eg,e in - let cases2 = match cases with - | [] -> [case1] - | [[EConst (Ident "_"),_],_,e] -> case1 :: [[(EConst (Ident "_"),p)],None,e] - | _ -> - case1 :: [[(EConst (Ident "_"),p)],None,Some (ESwitch(eval,cases,None),p)] - in - let eswitch = (ESwitch(esubjects,cases2,None)),p in - let case = epat,None,Some eswitch in - begin match epat with - | [EConst(Ident _),_] -> - [case;cfail] - | _ -> - case :: cases - end - end - | [] -> - [] - in - let cases = loop cases in - cases,!has_extractor - -let extractor_depth = ref 0 - -let match_expr ctx e cases def with_type p = - let need_val,with_type,tmono = match with_type with - | NoValue -> false,NoValue,None - | WithType t | WithTypeResume t when (match follow t with TMono _ -> true | _ -> false) -> - (* we don't want to unify with each case individually, but instead at the end after unify_min *) - true,Value,Some with_type - | t -> true,t,None - in - (* turn default into case _ *) - let cases = match cases,def with - | [],None -> [] - | cases,Some def -> - let p = match def with - | None -> p - | Some (_,p) -> p - in - cases @ [[(EConst(Ident "_")),p],None,def] - | _ -> cases - in - let cases,has_extractor = transform_extractors e cases p in - (* type subject(s) *) - let array_match = ref false in - let evals = match fst e with - | EArrayDecl el | EParenthesis(EArrayDecl el,_) when (match el with [(EFor _ | EWhile _),_] -> false | _ -> true) -> - array_match := true; - List.map (fun e -> type_expr ctx e Value) el - | _ -> - let e = type_expr ctx e Value in - begin match follow e.etype with - (* TODO: get rid of the XmlType check *) - | TEnum(en,_) when (match en.e_path with (["neko" | "php" | "flash" | "cpp"],"XmlType") -> true | _ -> Meta.has Meta.FakeEnum en.e_meta) -> - raise Exit - | TAbstract({a_path=[],("Int" | "Float" | "Bool")},_) | TInst({cl_path = [],"String"},_) when (Common.defined ctx.com Common.Define.NoPatternMatching) -> - raise Exit; - | _ -> - () - end; - [e] - in - let var_inits = ref [] in - let save = save_locals ctx in - let a = List.length evals in - (* turn subjects to subterms and handle variable initialization where necessary *) - let stl = ExtList.List.mapi (fun i e -> - let rec loop e = match e.eexpr with - | TParenthesis e | TMeta(_,e) -> - loop e - | TLocal v -> - mk_st (SVar v) e.etype e.epos - | _ -> - let v = gen_local ctx e.etype in - var_inits := (v, Some e) :: !var_inits; - ctx.locals <- PMap.add v.v_name v ctx.locals; - mk_st (SVar v) e.etype e.epos - in - let st = loop e in - if a = 1 then st else mk_st (STuple(st,i,a)) st.st_type st.st_pos - ) evals in - let tl = List.map (fun st -> st.st_type) stl in - (* create matcher context *) - let mctx = { - ctx = ctx; - need_val = need_val; - outcomes = []; - toplevel_or = false; - dt_lut = DynArray.create (); - dt_cache = Hashtbl.create 0; - dt_count = 0; - has_extractor = has_extractor; - expr_map = PMap.empty; - is_exhaustive = true; - } in - (* flatten cases *) - let cases = List.map (fun (el,eg,e) -> - List.iter (fun e -> match fst e with EBinop(OpOr,_,_) -> mctx.toplevel_or <- true; | _ -> ()) el; - match el with - | [] -> - let p = match e with None -> p | Some e -> pos e in - error "case without a pattern is not allowed" p - | _ -> - collapse_case el,eg,e - ) cases in - let is_complex = ref false in - if mctx.has_extractor then incr extractor_depth; - let add_pattern_locals (pat,locals,complex) = - PMap.iter (fun n (v,p) -> ctx.locals <- PMap.add n v ctx.locals) locals; - if complex then is_complex := true; - pat - in - (* evaluate patterns *) - let pl = ExtList.List.mapi (fun i (ep,eg,e) -> - let save = save_locals ctx in - (* type case patterns *) - let pl,restore,with_type = - try - (* context type parameters are turned into monomorphs until the pattern has been typed *) - let monos = List.map (fun _ -> mk_mono()) ctx.type_params in - let t = match tl with [t] when not !array_match -> t | tl -> tfun tl fake_tuple_type in - let t = apply_params ctx.type_params monos t in - let pl = [add_pattern_locals (to_pattern ctx ep t)] in - let old_ret = ctx.ret in - ctx.ret <- apply_params ctx.type_params monos ctx.ret; - let restore = PMap.fold (fun v acc -> - (* apply context monomorphs to locals and replace them back after typing the case body *) - let t = v.v_type in - v.v_type <- apply_params ctx.type_params monos v.v_type; - (fun () -> v.v_type <- t) :: acc - ) ctx.locals [fun() -> ctx.ret <- old_ret] in - (* turn any still unknown types back to type parameters *) - List.iter2 (fun m (_,t) -> match follow m with TMono _ -> Type.unify m t | _ -> ()) monos ctx.type_params; - pl,restore,(match with_type with - | WithType t -> WithType (apply_params ctx.type_params monos t) - | WithTypeResume t -> WithTypeResume (apply_params ctx.type_params monos t) - | _ -> with_type); - with Unrecognized_pattern (e,p) -> - error "Case expression must be a constant value or a pattern, not an arbitrary expression" p - in - let is_catch_all = match pl with - | [{p_def = PAny | PVar _}] -> true - | _ -> false - in - (* type case body *) - let e = match e with - | None -> - mk (TBlock []) ctx.com.basic.tvoid (pos ep) - | Some e -> - type_expr ctx e with_type - in - let e = match with_type with - | WithType t -> - Codegen.AbstractCast.cast_or_unify ctx t e e.epos; - | WithTypeResume t -> - (try Codegen.AbstractCast.cast_or_unify_raise ctx t e e.epos with Error (Unify l,p) -> raise (Typer.WithTypeError (l,p))); - | _ -> e - in - (* type case guard *) - let eg = match eg with - | None -> None - | Some e -> - let eg = type_expr ctx e (WithType ctx.com.basic.tbool) in - unify ctx eg.etype ctx.com.basic.tbool eg.epos; - Some eg - in - List.iter (fun f -> f()) restore; - save(); - let out = mk_out mctx i e eg is_catch_all (pos ep) in - Array.of_list pl,out - ) cases in - let check_unused () = - let unused p = - display_error ctx "This pattern is unused" p; - let old_error = ctx.on_error in - ctx.on_error <- (fun ctx s p -> ctx.on_error <- old_error; raise Exit); - let check_expr e p = - try begin match fst e with - | EConst(Ident ("null" | "true" | "false")) -> () - | EConst(Ident _) -> - ignore (type_expr ctx e Value); - display_error ctx "Case expression must be a constant value or a pattern, not an arbitrary expression" (pos e) - | _ -> () - end with Exit -> () - in - let rec loop prev cl = match cl with - | (_,Some _,_) :: cl -> loop prev cl - | ((e,p2),_,_) :: cl -> - if p2.pmin >= p.pmin then check_expr prev p else loop (e,p2) cl - | [] -> - check_expr prev p - in - (match cases with (e,_,_) :: cl -> loop e cl | [] -> assert false); - ctx.on_error <- old_error; - in - let had_catch_all = ref false in - List.iter (fun out -> - if out.o_catch_all && not !had_catch_all then - had_catch_all := true - else if out.o_num_paths = 0 then begin - unused out.o_pos; - if mctx.toplevel_or then begin match evals with - | [{etype = t}] when (match follow t with TAbstract({a_path=[],"Int"},[]) -> true | _ -> false) -> - display_error ctx "Note: Int | Int is an or-pattern now" p; - | _ -> () - end; - end - ) (List.rev mctx.outcomes); - in - let dt = try - (* compile decision tree *) - compile mctx stl pl true - with Not_exhaustive(pat,st) -> - let rec s_st_r top pre st v = match st.st_def with - | SVar v1 -> - if not pre then v else begin try - let e = match List.assoc v1 !var_inits with Some e -> e | None -> assert false in - (Type.s_expr_pretty "" (Type.s_type (print_context())) e) ^ v - with Not_found -> - v1.v_name ^ v - end - | STuple(st,i,a) -> - let r = a - i - 1 in - Printf.sprintf "[%s]" (st_args i r (s_st_r top false st v)) - | SArray(st,i) -> - s_st_r false true st (Printf.sprintf "[%i]%s" i (if top then " = " ^ v else v)) - | SField({st_def = SVar v1},cf) when v1.v_name.[0] = '`' -> - cf.cf_name ^ (if top then " = " ^ v else v) - | SField(st,cf) -> - s_st_r false true st (Printf.sprintf ".%s%s" cf.cf_name (if top then " = " ^ v else v)) - | SEnum(st,ef,i) -> - let len = match follow ef.ef_type with TFun(args,_) -> List.length args | _ -> 0 in - s_st_r false false st (Printf.sprintf "%s(%s)" ef.ef_name (st_args i (len - 1 - i) v)) - in - let pat = match follow st.st_type with - | TAbstract({a_impl = Some cl} as a,_) when Meta.has Meta.Enum a.a_meta -> - let rec s_pat pat = match pat.p_def with - | PCon ({c_def = CConst c},[]) when c <> TNull -> - let cf = List.find (fun cf -> - match cf.cf_expr with - | Some ({eexpr = TConst c2 | TCast({eexpr = TConst c2},None)}) -> c = c2 - | _ -> false - ) cl.cl_ordered_statics in - cf.cf_name - | PVar (v,_) -> v.v_name - | PCon (c,[]) -> s_con c - | PCon (c,pl) -> s_con c ^ "(" ^ (String.concat "," (List.map s_pat pl)) ^ ")" - | POr (pat1,pat2) -> s_pat pat1 ^ " | " ^ s_pat pat2 - | PAny -> "_" - | PBind((v,_),pat) -> v.v_name ^ "=" ^ s_pat pat - | PTuple pl -> "(" ^ (String.concat " " (Array.to_list (Array.map s_pat pl))) ^ ")" - in - s_pat pat - | _ -> - s_pat pat - in - let msg = "Unmatched patterns: " ^ (s_st_r true false st pat) in - if !extractor_depth > 0 then begin - display_error ctx msg st.st_pos; - error "Note: Patterns with extractors may require a default pattern" st.st_pos; - end else - error msg st.st_pos - in - save(); - (* check for unused patterns *) - if !extractor_depth = 0 then check_unused(); - if mctx.has_extractor then decr extractor_depth; - (* determine type of switch statement *) - let t = if not need_val then - mk_mono() - else match with_type with - | WithType t | WithTypeResume t -> t - | _ -> try Typer.unify_min_raise ctx (List.rev_map (fun (_,out) -> get_expr mctx out.o_id) (List.rev pl)) with Error (Unify l,p) -> error (error_msg (Unify l)) p - in - (* unify with expected type if necessary *) - begin match tmono with - | None -> () - | Some (WithType t2) -> unify ctx t2 t p - | Some (WithTypeResume t2) -> (try unify_raise ctx t2 t p with Error (Unify l,p) -> raise (Typer.WithTypeError (l,p))) - | _ -> assert false - end; - (* count usage *) - let usage = Array.make (DynArray.length mctx.dt_lut) 0 in - (* we always want to keep the first part *) - let first = (match dt with Goto i -> i | _ -> Hashtbl.find mctx.dt_cache dt) in - Array.set usage first 2; - let rec loop dt = match dt with - | Goto i -> Array.set usage i ((Array.get usage i) + 1) - | Switch(st,cl) -> List.iter (fun (_,dt) -> loop dt) cl - | Bind(bl,dt) -> loop dt - | Expr e -> () - | Guard(e,dt1,dt2) -> - loop dt1; - match dt2 with None -> () | Some dt -> (loop dt) - in - DynArray.iter loop mctx.dt_lut; - (* filter parts that will be inlined and keep a map to them*) - let map = Array.make (DynArray.length mctx.dt_lut) 0 in - let lut = DynArray.create() in - let rec loop i c = - if c < DynArray.length mctx.dt_lut then begin - let i' = if usage.(c) > 1 then begin - DynArray.add lut (DynArray.get mctx.dt_lut c); - i + 1 - end else i in - Array.set map c i; - loop i' (c + 1) - end - in - loop 0 0; - (* reindex *) - let rec loop dt = match dt with - | Goto i -> if usage.(i) > 1 then DTGoto (map.(i)) else loop (DynArray.get mctx.dt_lut i) - | Switch(st,cl) -> convert_switch mctx st cl loop - | Bind(bl,dt) -> DTBind(List.map (fun (v,st) -> v,convert_st ctx st) bl,loop dt) - | Expr id -> DTExpr (get_expr mctx id) - | Guard(id,dt1,dt2) -> DTGuard((match get_guard mctx id with Some e -> e | None -> assert false),loop dt1, match dt2 with None -> None | Some dt -> Some (loop dt)) - in - let lut = DynArray.map loop lut in - { - dt_first = map.(first); - dt_dt_lookup = DynArray.to_array lut; - dt_type = t; - dt_var_init = List.rev !var_inits; - dt_is_complex = !is_complex; - } -;; -match_expr_ref := match_expr; -get_pattern_locals_ref := get_pattern_locals \ No newline at end of file diff --git a/src/context/common.ml b/src/context/common.ml new file mode 100644 index 00000000..52b67c6b --- /dev/null +++ b/src/context/common.ml @@ -0,0 +1,1149 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Ast +open Type +open Globals + +type package_rule = + | Forbidden + | Directory of string + | Remap of string + +type pos = Globals.pos + +type basic_types = { + mutable tvoid : t; + mutable tint : t; + mutable tfloat : t; + mutable tbool : t; + mutable tnull : t -> t; + mutable tstring : t; + mutable tarray : t -> t; +} + +type stats = { + s_files_parsed : int ref; + s_classes_built : int ref; + s_methods_typed : int ref; + s_macros_called : int ref; +} + +(** + The capture policy tells which handling we make of captured locals + (the locals which are referenced in local functions) + + See details/implementation in Codegen.captured_vars +*) +type capture_policy = + (** do nothing, let the platform handle it *) + | CPNone + (** wrap all captured variables into a single-element array to allow modifications *) + | CPWrapRef + (** similar to wrap ref, but will only apply to the locals that are declared in loops *) + | CPLoopVars + +type platform_config = { + (** has a static type system, with not-nullable basic types (Int/Float/Bool) *) + pf_static : bool; + (** has access to the "sys" package *) + pf_sys : bool; + (** captured variables handling (see before) *) + pf_capture_policy : capture_policy; + (** when calling a method with optional args, do we replace the missing args with "null" constants *) + pf_pad_nulls : bool; + (** add a final return to methods not having one already - prevent some compiler warnings *) + pf_add_final_return : bool; + (** does the platform natively support overloaded functions *) + pf_overload : bool; + (** can the platform use default values for non-nullable arguments *) + pf_can_skip_non_nullable_argument : bool; + (** type paths that are reserved on the platform *) + pf_reserved_type_paths : path list; +} + +module DisplayMode = struct + type t = + | DMNone + | DMField + | DMUsage of bool (* true = also report definition *) + | DMPosition + | DMToplevel + | DMResolve of string + | DMPackage + | DMType + | DMModuleSymbols of string option + | DMDiagnostics of bool (* true = global, false = only in display file *) + | DMStatistics + | DMSignature + + type error_policy = + | EPIgnore + | EPCollect + | EPShow + + type display_file_policy = + | DFPOnly + | DFPAlso + | DFPNo + + type settings = { + dms_kind : t; + dms_display : bool; + dms_full_typing : bool; + dms_force_macro_typing : bool; + dms_error_policy : error_policy; + dms_collect_data : bool; + dms_check_core_api : bool; + dms_inline : bool; + dms_display_file_policy : display_file_policy; + dms_exit_during_typing : bool; + } + + let default_display_settings = { + dms_kind = DMField; + dms_display = true; + dms_full_typing = false; + dms_force_macro_typing = false; + dms_error_policy = EPIgnore; + dms_collect_data = false; + dms_check_core_api = false; + dms_inline = false; + dms_display_file_policy = DFPOnly; + dms_exit_during_typing = true; + } + + let default_compilation_settings = { + dms_kind = DMNone; + dms_display = false; + dms_full_typing = true; + dms_force_macro_typing = true; + dms_error_policy = EPShow; + dms_collect_data = false; + dms_check_core_api = true; + dms_inline = true; + dms_display_file_policy = DFPNo; + dms_exit_during_typing = false; + } + + let create dm = + let settings = { default_display_settings with dms_kind = dm } in + match dm with + | DMNone -> default_compilation_settings + | DMField | DMPosition | DMResolve _ | DMPackage | DMType | DMSignature -> settings + | DMUsage _ -> { settings with + dms_full_typing = true; + dms_collect_data = true; + dms_display_file_policy = DFPAlso; + dms_exit_during_typing = false + } + | DMToplevel -> { settings with dms_full_typing = true; } + | DMModuleSymbols filter -> { settings with + dms_display_file_policy = if filter = None then DFPOnly else DFPNo; + dms_exit_during_typing = false; + dms_force_macro_typing = false; + } + | DMDiagnostics global -> { settings with + dms_full_typing = true; + dms_error_policy = EPCollect; + dms_collect_data = true; + dms_inline = true; + dms_display_file_policy = if global then DFPNo else DFPAlso; + dms_exit_during_typing = false; + } + | DMStatistics -> { settings with + dms_full_typing = true; + dms_collect_data = true; + dms_inline = false; + dms_display_file_policy = DFPAlso; + dms_exit_during_typing = false + } + + let to_string = function + | DMNone -> "none" + | DMField -> "field" + | DMPosition -> "position" + | DMResolve s -> "resolve " ^ s + | DMPackage -> "package" + | DMType -> "type" + | DMUsage true -> "rename" + | DMUsage false -> "references" + | DMToplevel -> "toplevel" + | DMModuleSymbols None -> "module-symbols" + | DMModuleSymbols (Some s) -> "workspace-symbols " ^ s + | DMDiagnostics b -> (if b then "global " else "") ^ "diagnostics" + | DMStatistics -> "statistics" + | DMSignature -> "signature" +end + +type compiler_callback = { + mutable after_typing : (module_type list -> unit) list; + mutable before_dce : (unit -> unit) list; + mutable after_generation : (unit -> unit) list; +} + +module IdentifierType = struct + type t = + | ITLocal of tvar + | ITMember of tclass * tclass_field + | ITStatic of tclass * tclass_field + | ITEnum of tenum * tenum_field + | ITEnumAbstract of tabstract * tclass_field + | ITGlobal of module_type * string * Type.t + | ITType of module_type + | ITPackage of string + | ITLiteral of string + | ITTimer of string + + let get_name = function + | ITLocal v -> v.v_name + | ITMember(_,cf) | ITStatic(_,cf) | ITEnumAbstract(_,cf) -> cf.cf_name + | ITEnum(_,ef) -> ef.ef_name + | ITGlobal(_,s,_) -> s + | ITType mt -> snd (t_infos mt).mt_path + | ITPackage s -> s + | ITLiteral s -> s + | ITTimer s -> s +end + +type shared_display_information = { + mutable import_positions : (pos,bool ref * placed_name list) PMap.t; + mutable diagnostics_messages : (string * pos * DisplayTypes.DiagnosticsSeverity.t) list; + mutable type_hints : (pos,Type.t) Hashtbl.t; + mutable document_symbols : (string * DisplayTypes.SymbolInformation.t DynArray.t) list; + mutable removable_code : (string * pos * pos) list; +} + +type display_information = { + mutable unresolved_identifiers : (string * pos * (string * IdentifierType.t) list) list; + mutable interface_field_implementations : (tclass * tclass_field * tclass * tclass_field option) list; +} + +(* This information is shared between normal and macro context. *) +type shared_context = { + shared_display_information : shared_display_information; +} + +type context = { + (* config *) + version : int; + args : string list; + shared : shared_context; + display_information : display_information; + mutable sys_args : string list; + mutable display : DisplayMode.settings; + mutable debug : bool; + mutable verbose : bool; + mutable foptimize : bool; + mutable platform : platform; + mutable config : platform_config; + mutable std_path : string list; + mutable class_path : string list; + mutable main_class : Type.path option; + mutable defines : (string,string) PMap.t; + mutable package_rules : (string,package_rule) PMap.t; + mutable error : string -> pos -> unit; + mutable warning : string -> pos -> unit; + mutable load_extern_type : (path -> pos -> (string * Ast.package) option) list; (* allow finding types which are not in sources *) + callbacks : compiler_callback; + mutable defines_signature : string option; + mutable print : string -> unit; + mutable get_macros : unit -> context option; + mutable run_command : string -> int; + file_lookup_cache : (string,string option) Hashtbl.t; + parser_cache : (string,(type_def * pos) list) Hashtbl.t; + cached_macros : (path * string,((string * bool * t) list * t * tclass * Type.tclass_field)) Hashtbl.t; + mutable stored_typed_exprs : (int, texpr) PMap.t; + (* output *) + mutable file : string; + mutable flash_version : float; + mutable features : (string,bool) Hashtbl.t; + mutable modules : Type.module_def list; + mutable main : Type.texpr option; + mutable types : Type.module_type list; + mutable resources : (string,string) Hashtbl.t; + mutable neko_libs : string list; + mutable include_files : (string * string) list; + mutable php_front : string option; + mutable php_lib : string option; + mutable php_prefix : string option; + mutable swf_libs : (string * (unit -> Swf.swf) * (unit -> ((string list * string),As3hl.hl_class) Hashtbl.t)) list; + mutable java_libs : (string * bool * (unit -> unit) * (unit -> (path list)) * (path -> ((JData.jclass * string * string) option))) list; (* (path,std,close,all_files,lookup) *) + mutable net_libs : (string * bool * (unit -> path list) * (path -> IlData.ilclass option)) list; (* (path,std,all_files,lookup) *) + mutable net_std : string list; + net_path_map : (path,string list * string list * string) Hashtbl.t; + mutable c_args : string list; + mutable js_gen : (unit -> unit) option; + (* typing *) + mutable basic : basic_types; + memory_marker : float array; +} + +exception Abort of string * pos + +let display_default = ref DisplayMode.DMNone + +let get_signature com = + match com.defines_signature with + | Some s -> s + | None -> + let defines = PMap.foldi (fun k v acc -> + (* don't make much difference between these special compilation flags *) + match String.concat "_" (ExtString.String.nsplit k "-") with + (* If we add something here that might be used in conditional compilation it should be added to + Parser.parse_macro_ident as well (issue #5682). *) + | "display" | "use_rtti_doc" | "macro_times" | "display_details" | "no_copt" | "display_stdin" -> acc + | _ -> (k ^ "=" ^ v) :: acc + ) com.defines [] in + let str = String.concat "@" (List.sort compare defines) in + let s = Digest.string str in + com.defines_signature <- Some s; + s + +let is_php7 com = com.platform = Php && PMap.exists "php7" com.defines + +module CompilationServer = struct + type cache = { + c_haxelib : (string list, string list) Hashtbl.t; + c_files : ((string * string), float * Ast.package) Hashtbl.t; + c_modules : (path * string, module_def) Hashtbl.t; + c_directories : (string, (string * float ref) list) Hashtbl.t; + } + + type t = { + cache : cache; + mutable signs : (string * string) list; + } + + type context_options = + | NormalContext + | MacroContext + | NormalAndMacroContext + + let instance : t option ref = ref None + + let create_cache () = { + c_haxelib = Hashtbl.create 0; + c_files = Hashtbl.create 0; + c_modules = Hashtbl.create 0; + c_directories = Hashtbl.create 0; + } + + let create () = + let cs = { + cache = create_cache(); + signs = []; + } in + instance := Some cs; + cs + + let get () = + !instance + + let runs () = + !instance <> None + + let get_context_files cs signs = + Hashtbl.fold (fun (file,sign) (_,data) acc -> + if (List.mem sign signs) then (file,data) :: acc + else acc + ) cs.cache.c_files [] + + (* signatures *) + + let get_sign cs sign = + List.assoc sign cs.signs + + let add_sign cs sign = + let i = string_of_int (List.length cs.signs) in + cs.signs <- (sign,i) :: cs.signs; + i + + (* modules *) + + let find_module cs key = + Hashtbl.find cs.cache.c_modules key + + let cache_module cs key value = + Hashtbl.replace cs.cache.c_modules key value + + let taint_modules cs file = + Hashtbl.iter (fun _ m -> if m.m_extra.m_file = file then m.m_extra.m_dirty <- Some m) cs.cache.c_modules + + (* files *) + + let find_file cs key = + Hashtbl.find cs.cache.c_files key + + let cache_file cs key value = + Hashtbl.replace cs.cache.c_files key value + + let remove_file cs key = + Hashtbl.remove cs.cache.c_files key + + let remove_files cs file = + List.iter (fun (sign,_) -> remove_file cs (sign,file)) cs.signs + + (* haxelibs *) + + let find_haxelib cs key = + Hashtbl.find cs.cache.c_haxelib key + + let cache_haxelib cs key value = + Hashtbl.replace cs.cache.c_haxelib key value + + (* directories *) + + let find_directories cs key = + Hashtbl.find cs.cache.c_directories key + + let add_directories cs key value = + Hashtbl.replace cs.cache.c_directories key value + + let remove_directory cs key value = + try + let current = find_directories cs key in + Hashtbl.replace cs.cache.c_directories key (List.filter (fun (s,_) -> s <> value) current); + with Not_found -> + () + + let has_directory cs key value = + try + List.mem_assoc value (find_directories cs key) + with Not_found -> + false + + let add_directory cs key value = + try + let current = find_directories cs key in + add_directories cs key (value :: current) + with Not_found -> + add_directories cs key [value] + + let clear_directories cs key = + Hashtbl.remove cs.cache.c_directories key +end + +module Define = struct + + type strict_defined = + | AbsolutePath + | AdvancedTelemetry + | AnnotateSource + (* | Analyzer *) + | As3 + | CheckXmlProxy + | CoreApi + | CoreApiSerialize + | Cppia + | Dce + | DceDebug + | Debug + | Display + | DisplayStdin + | DllExport + | DllImport + | DocGen + | Dump + | DumpDependencies + | DumpIgnoreVarIds + | DynamicInterfaceClosures + | EraseGenerics + | FastCast + | Fdb + | FileExtension + | FlashStrict + | FlashUseStage + | ForceLibCheck + | ForceNativeProperty + | FormatWarning + | GencommonDebug + | HaxeBoot + | HaxeVer + | HxcppApiLevel + | HxcppGcGenerational + | HxcppDebugger + | IncludePrefix + | Interp + | JavaVer + | JqueryVer + | JsClassic + | JsEs + | JsUnflatten + | JsSourceMap + | KeepOldOutput + | LoopUnrollMaxCost + | LuaVer + | LuaJit + | Macro + | MacroDebug + | MacroTimes + | NekoSource + | NekoV1 + | NetworkSandbox + | NetVer + | NetTarget + | NoCompilation + | NoCOpt + | NoDeprecationWarnings + | NoFlashOverride + | NoDebug + | NoInline + | NoOpt + | NoPatternMatching + | NoRoot + | NoSwfCompress + | NoTraces + | Objc + | PhpPrefix + | RealPosition + | ReplaceFiles + | Scriptable + | ShallowExpose + | SourceHeader + | SourceMapContent + | Swc + | SwfCompressLevel + | SwfDebugPassword + | SwfDirectBlit + | SwfGpu + | SwfMetadata + | SwfPreloaderFrame + | SwfProtected + | SwfScriptTimeout + | SwfUseDoAbc + | Sys + | Unsafe + | UseNekoc + | UseRttiDoc + | Vcproj + | NoMacroCache + | Last (* must be last *) + + let infos = function + | AbsolutePath -> ("absolute_path","Print absolute file path in trace output") + | AdvancedTelemetry -> ("advanced-telemetry","Allow the SWF to be measured with Monocle tool") + | AnnotateSource -> ("annotate_source","Add additional comments to generated source code") + (* | Analyzer -> ("analyzer","Use static analyzer for optimization (experimental)") *) + | As3 -> ("as3","Defined when outputing flash9 as3 source code") + | CheckXmlProxy -> ("check_xml_proxy","Check the used fields of the xml proxy") + | CoreApi -> ("core_api","Defined in the core api context") + | CoreApiSerialize -> ("core_api_serialize","Mark some generated core api classes with the Serializable attribute on C#") + | Cppia -> ("cppia", "Generate cpp instruction assembly") + | Dce -> ("dce"," Set the dead code elimination mode (default std)") + | DceDebug -> ("dce_debug","Show DCE log") + | Debug -> ("debug","Activated when compiling with -debug") + | Display -> ("display","Activated during completion") + | DisplayStdin -> ("display_stdin","Read the contents of a file specified in --display from standard input") + | DllExport -> ("dll_export", "GenCPP experimental linking") + | DllImport -> ("dll_import", "GenCPP experimental linking") + | DocGen -> ("doc_gen","Do not perform any removal/change in order to correctly generate documentation") + | Dump -> ("dump"," Dump typed AST in dump subdirectory using specified mode or non-prettified default") + | DumpDependencies -> ("dump_dependencies","Dump the classes dependencies in a dump subdirectory") + | DumpIgnoreVarIds -> ("dump_ignore_var_ids","Remove variable IDs from non-pretty dumps (helps with diff)") + | DynamicInterfaceClosures -> ("dynamic_interface_closures","Use slow path for interface closures to save space") + | EraseGenerics -> ("erase_generics","Erase generic classes on C#") + | FastCast -> ("fast_cast","Enables an experimental casts cleanup on C# and Java") + | Fdb -> ("fdb","Enable full flash debug infos for FDB interactive debugging") + | FileExtension -> ("file_extension","Output filename extension for cpp source code") + | FlashStrict -> ("flash_strict","More strict typing for flash target") + | FlashUseStage -> ("flash_use_stage","Keep the SWF library initial stage") + (* force_lib_check is only here as a debug facility - compiler checking allows errors to be found more easily *) + | ForceLibCheck -> ("force_lib_check","Force the compiler to check -net-lib and -java-lib added classes (internal)") + | ForceNativeProperty -> ("force_native_property","Tag all properties with :nativeProperty metadata for 3.1 compatibility") + | FormatWarning -> ("format_warning","Print a warning for each formated string, for 2.x compatibility") + | GencommonDebug -> ("gencommon_debug","GenCommon internal") + | HaxeBoot -> ("haxe_boot","Given the name 'haxe' to the flash boot class instead of a generated name") + | HaxeVer -> ("haxe_ver","The current Haxe version value") + | HxcppApiLevel -> ("hxcpp_api_level","Provided to allow compatibility between hxcpp versions") + | HxcppGcGenerational -> ("HXCPP_GC_GENERATIONAL","Experimental Garbage Collector") + | HxcppDebugger -> ("HXCPP_DEBUGGER","Include additional information for HXCPP_DEBUGGER") + | IncludePrefix -> ("include_prefix","prepend path to generated include files") + | Interp -> ("interp","The code is compiled to be run with --interp") + | JavaVer -> ("java_ver", " Sets the Java version to be targeted") + | JqueryVer -> ("jquery_ver", "The jQuery version supported by js.jquery.*. The version is encoded as an interger. e.g. 1.11.3 is encoded as 11103") + | JsClassic -> ("js_classic","Don't use a function wrapper and strict mode in JS output") + | JsEs -> ("js_es","Generate JS compilant with given ES standard version (default 5)") + | JsUnflatten -> ("js_unflatten","Generate nested objects for packages and types") + | JsSourceMap -> ("js_source_map","Generate JavaScript source map even in non-debug mode") + | KeepOldOutput -> ("keep_old_output","Keep old source files in the output directory (for C#/Java)") + | LoopUnrollMaxCost -> ("loop_unroll_max_cost","Maximum cost (number of expressions * iterations) before loop unrolling is canceled (default 250)") + | LuaJit -> ("lua_jit","Enable the jit compiler for lua (version 5.2 only") + | LuaVer -> ("lua_ver","The lua version to target") + | Macro -> ("macro","Defined when code is compiled in the macro context") + | MacroDebug -> ("macro_debug","Show warnings for potential macro problems (e.g. macro-in-macro calls)") + | MacroTimes -> ("macro_times","Display per-macro timing when used with --times") + | NetVer -> ("net_ver", " Sets the .NET version to be targeted") + | NetTarget -> ("net_target", " Sets the .NET target. Defaults to \"net\". xbox, micro (Micro Framework), compact (Compact Framework) are some valid values") + | NekoSource -> ("neko_source","Output neko source instead of bytecode") + | NekoV1 -> ("neko_v1","Keep Neko 1.x compatibility") + | NetworkSandbox -> ("network-sandbox","Use local network sandbox instead of local file access one") + | NoCompilation -> ("no-compilation","Disable final compilation for Cs, Cpp and Java") + | NoCOpt -> ("no_copt","Disable completion optimization (for debug purposes)") + | NoDebug -> ("no_debug","Remove all debug macros from cpp output") + | NoDeprecationWarnings -> ("no-deprecation-warnings","Do not warn if fields annotated with @:deprecated are used") + | NoFlashOverride -> ("no-flash-override", "Change overrides on some basic classes into HX suffixed methods, flash only") + | NoOpt -> ("no_opt","Disable optimizations") + | NoPatternMatching -> ("no_pattern_matching","Disable pattern matching") + | NoInline -> ("no_inline","Disable inlining") + | NoRoot -> ("no_root","Generate top-level types into haxe.root namespace") + | NoMacroCache -> ("no_macro_cache","Disable macro context caching") + | NoSwfCompress -> ("no_swf_compress","Disable SWF output compression") + | NoTraces -> ("no_traces","Disable all trace calls") + | Objc -> ("objc","Sets the hxcpp output to objective-c++ classes. Must be defined for interop") + | PhpPrefix -> ("php_prefix","Compiled with --php-prefix") + | RealPosition -> ("real_position","Disables Haxe source mapping when targetting C#, removes position comments in Java output") + | ReplaceFiles -> ("replace_files","GenCommon internal") + | Scriptable -> ("scriptable","GenCPP internal") + | ShallowExpose -> ("shallow-expose","Expose types to surrounding scope of Haxe generated closure without writing to window object") + | SourceHeader -> ("source-header","Print value as comment on top of generated files, use '' value to disable") + | SourceMapContent -> ("source-map-content","Include the hx sources as part of the JS source map") + | Swc -> ("swc","Output a SWC instead of a SWF") + | SwfCompressLevel -> ("swf_compress_level"," Set the amount of compression for the SWF output") + | SwfDebugPassword -> ("swf_debug_password", "Set a password for debugging") + | SwfDirectBlit -> ("swf_direct_blit", "Use hardware acceleration to blit graphics") + | SwfGpu -> ("swf_gpu", "Use GPU compositing features when drawing graphics") + | SwfMetadata -> ("swf_metadata", " Include contents of as metadata in the swf") + | SwfPreloaderFrame -> ("swf_preloader_frame", "Insert empty first frame in swf") + | SwfProtected -> ("swf_protected","Compile Haxe private as protected in the SWF instead of public") + | SwfScriptTimeout -> ("swf_script_timeout", "Maximum ActionScript processing time before script stuck dialog box displays (in seconds)") + | SwfUseDoAbc -> ("swf_use_doabc", "Use DoAbc swf-tag instead of DoAbcDefine") + | Sys -> ("sys","Defined for all system platforms") + | Unsafe -> ("unsafe","Allow unsafe code when targeting C#") + | UseNekoc -> ("use_nekoc","Use nekoc compiler instead of internal one") + | UseRttiDoc -> ("use_rtti_doc","Allows access to documentation during compilation") + | Vcproj -> ("vcproj","GenCPP internal") + | Last -> assert false +end + +let short_platform_name = function + | Cross -> "x" + | Js -> "js" + | Lua -> "lua" + | Neko -> "n" + | Flash -> "swf" + | Php -> "php" + | Cpp -> "cpp" + | Cs -> "cs" + | Java -> "jav" + | Python -> "py" + | Hl -> "hl" + +let stats = + { + s_files_parsed = ref 0; + s_classes_built = ref 0; + s_methods_typed = ref 0; + s_macros_called = ref 0; + } + +let default_config = + { + pf_static = true; + pf_sys = true; + pf_capture_policy = CPNone; + pf_pad_nulls = false; + pf_add_final_return = false; + pf_overload = false; + pf_can_skip_non_nullable_argument = true; + pf_reserved_type_paths = []; + } + +let get_config com = + let defined f = PMap.mem (fst (Define.infos f)) com.defines in + match com.platform with + | Cross -> + default_config + | Js -> + { + default_config with + pf_static = false; + pf_sys = false; + pf_capture_policy = CPLoopVars; + pf_reserved_type_paths = [([],"Object");([],"Error")]; + } + | Lua -> + { + default_config with + pf_static = false; + pf_capture_policy = CPLoopVars; + } + | Neko -> + { + default_config with + pf_static = false; + pf_pad_nulls = true; + } + | Flash when defined Define.As3 -> + { + default_config with + pf_sys = false; + pf_capture_policy = CPLoopVars; + pf_add_final_return = true; + pf_can_skip_non_nullable_argument = false; + } + | Flash -> + { + default_config with + pf_sys = false; + pf_capture_policy = CPLoopVars; + pf_can_skip_non_nullable_argument = false; + pf_reserved_type_paths = [([],"Object");([],"Error")]; + } + | Php -> + if is_php7 com then + { + default_config with + pf_static = false; + } + else + { + default_config with + pf_static = false; + pf_pad_nulls = true; + } + | Cpp -> + { + default_config with + pf_capture_policy = CPWrapRef; + pf_pad_nulls = true; + pf_add_final_return = true; + } + | Cs -> + { + default_config with + pf_capture_policy = CPWrapRef; + pf_pad_nulls = true; + pf_overload = true; + } + | Java -> + { + default_config with + pf_capture_policy = CPWrapRef; + pf_pad_nulls = true; + pf_overload = true; + } + | Python -> + { + default_config with + pf_static = false; + pf_capture_policy = CPLoopVars; + } + | Hl -> + { + default_config with + pf_capture_policy = CPWrapRef; + pf_pad_nulls = true; + pf_can_skip_non_nullable_argument = false; + } + +let memory_marker = [|Unix.time()|] + +let create_callbacks () = + { + after_typing = []; + before_dce = []; + after_generation = []; + } + +let create version s_version args = + let m = Type.mk_mono() in + let defines = + PMap.add "true" "1" ( + PMap.add "source-header" ("Generated by Haxe " ^ s_version) ( + if !display_default <> DisplayMode.DMNone then PMap.add "display" "1" PMap.empty else PMap.empty)) + in + { + version = version; + args = args; + shared = { + shared_display_information = { + import_positions = PMap.empty; + diagnostics_messages = []; + type_hints = Hashtbl.create 0; + document_symbols = []; + removable_code = []; + } + }; + display_information = { + unresolved_identifiers = []; + interface_field_implementations = []; + }; + sys_args = args; + debug = false; + display = DisplayMode.create !display_default; + verbose = false; + foptimize = true; + features = Hashtbl.create 0; + platform = Cross; + config = default_config; + print = (fun s -> print_string s; flush stdout); + run_command = Sys.command; + std_path = []; + class_path = []; + main_class = None; + defines = defines; + package_rules = PMap.empty; + file = ""; + types = []; + callbacks = create_callbacks(); + modules = []; + main = None; + flash_version = 10.; + resources = Hashtbl.create 0; + php_front = None; + php_lib = None; + swf_libs = []; + java_libs = []; + net_libs = []; + net_std = []; + net_path_map = Hashtbl.create 0; + c_args = []; + neko_libs = []; + include_files = []; + php_prefix = None; + js_gen = None; + load_extern_type = []; + defines_signature = None; + get_macros = (fun() -> None); + warning = (fun _ _ -> assert false); + error = (fun _ _ -> assert false); + basic = { + tvoid = m; + tint = m; + tfloat = m; + tbool = m; + tnull = (fun _ -> assert false); + tstring = m; + tarray = (fun _ -> assert false); + }; + file_lookup_cache = Hashtbl.create 0; + stored_typed_exprs = PMap.empty; + cached_macros = Hashtbl.create 0; + memory_marker = memory_marker; + parser_cache = Hashtbl.create 0; + } + +let log com str = + if com.verbose then com.print (str ^ "\n") + +let clone com = + let t = com.basic in + { com with + basic = { t with tvoid = t.tvoid }; + main_class = None; + features = Hashtbl.create 0; + file_lookup_cache = Hashtbl.create 0; + parser_cache = Hashtbl.create 0 ; + callbacks = create_callbacks(); + display_information = { + unresolved_identifiers = []; + interface_field_implementations = []; + }; + } + +let file_time file = Extc.filetime file + +let file_extension file = + match List.rev (ExtString.String.nsplit file ".") with + | e :: _ -> String.lowercase e + | [] -> "" + +let flash_versions = List.map (fun v -> + let maj = int_of_float v in + let min = int_of_float (mod_float (v *. 10.) 10.) in + v, string_of_int maj ^ (if min = 0 then "" else "_" ^ string_of_int min) +) [9.;10.;10.1;10.2;10.3;11.;11.1;11.2;11.3;11.4;11.5;11.6;11.7;11.8;11.9;12.0;13.0;14.0;15.0;16.0;17.0] + +let flash_version_tag = function + | 6. -> 6 + | 7. -> 7 + | 8. -> 8 + | 9. -> 9 + | 10. | 10.1 -> 10 + | 10.2 -> 11 + | 10.3 -> 12 + | 11. -> 13 + | 11.1 -> 14 + | 11.2 -> 15 + | 11.3 -> 16 + | 11.4 -> 17 + | 11.5 -> 18 + | 11.6 -> 19 + | 11.7 -> 20 + | 11.8 -> 21 + | 11.9 -> 22 + | v when v >= 12.0 && float_of_int (int_of_float v) = v -> int_of_float v + 11 + | v -> failwith ("Invalid SWF version " ^ string_of_float v) + +let raw_defined ctx v = + PMap.mem v ctx.defines + +let defined ctx v = + raw_defined ctx (fst (Define.infos v)) + +let raw_defined_value ctx k = + PMap.find k ctx.defines + +let defined_value ctx v = + raw_defined_value ctx (fst (Define.infos v)) + +let defined_value_safe ctx v = + try defined_value ctx v + with Not_found -> "" + +let raw_define ctx v = + let k,v = try ExtString.String.split v "=" with _ -> v,"1" in + ctx.defines <- PMap.add k v ctx.defines; + let k = String.concat "_" (ExtString.String.nsplit k "-") in + ctx.defines <- PMap.add k v ctx.defines; + ctx.defines_signature <- None + +let define_value ctx k v = + raw_define ctx (fst (Define.infos k) ^ "=" ^ v) + +let define ctx v = + raw_define ctx (fst (Define.infos v)) + +let init_platform com pf = + com.platform <- pf; + let name = platform_name pf in + let forbid acc p = if p = name || PMap.mem p acc then acc else PMap.add p Forbidden acc in + com.package_rules <- List.fold_left forbid com.package_rules (List.map platform_name platforms); + com.config <- get_config com; +(* if com.config.pf_static then define com "static"; *) + if com.config.pf_sys then define com Define.Sys else com.package_rules <- PMap.add "sys" Forbidden com.package_rules; + raw_define com name + +let add_feature com f = + Hashtbl.replace com.features f true + +let has_dce com = + (try defined_value com Define.Dce <> "no" with Not_found -> false) + +(* + TODO: The has_dce check is there because we mark types with @:directlyUsed in the DCE filter, + which is not run in dce=no and thus we can't know if a type is used directly or not, + so we just assume that they are. + + If we had dce filter always running (even with dce=no), we would have types marked with @:directlyUsed + and we wouldn't need to generate unnecessary imports in dce=no, but that's good enough for now. +*) +let is_directly_used com meta = + not (has_dce com) || Meta.has Meta.DirectlyUsed meta + +let rec has_feature com f = + try + Hashtbl.find com.features f + with Not_found -> + if com.types = [] then not (has_dce com) else + match List.rev (ExtString.String.nsplit f ".") with + | [] -> assert false + | [cl] -> has_feature com (cl ^ ".*") + | meth :: cl :: pack -> + let r = (try + let path = List.rev pack, cl in + (match List.find (fun t -> t_path t = path && not (Meta.has Meta.RealPath (t_infos t).mt_meta)) com.types with + | t when meth = "*" -> (match t with TAbstractDecl a -> Meta.has Meta.ValueUsed a.a_meta | _ -> + Meta.has Meta.Used (t_infos t).mt_meta) + | TClassDecl ({cl_extern = true} as c) when com.platform <> Js || cl <> "Array" && cl <> "Math" -> + Meta.has Meta.Used (try PMap.find meth c.cl_statics with Not_found -> PMap.find meth c.cl_fields).cf_meta + | TClassDecl c -> + PMap.exists meth c.cl_statics || PMap.exists meth c.cl_fields + | _ -> + false) + with Not_found -> + false + ) in + let r = r || not (has_dce com) in + Hashtbl.add com.features f r; + r + +let allow_package ctx s = + try + if (PMap.find s ctx.package_rules) = Forbidden then ctx.package_rules <- PMap.remove s ctx.package_rules + with Not_found -> + () + +let abort msg p = raise (Abort (msg,p)) + +let platform ctx p = ctx.platform = p + +let add_typing_filter ctx f = + ctx.callbacks.after_typing <- f :: ctx.callbacks.after_typing + +let add_filter ctx f = + ctx.callbacks.before_dce <- f :: ctx.callbacks.before_dce + +let add_final_filter ctx f = + ctx.callbacks.after_generation <- f :: ctx.callbacks.after_generation + +let find_file ctx f = + try + (match Hashtbl.find ctx.file_lookup_cache f with + | None -> raise Exit + | Some f -> f) + with Exit -> + raise Not_found + | Not_found -> + let rec loop had_empty = function + | [] when had_empty -> raise Not_found + | [] -> loop true [""] + | p :: l -> + let file = p ^ f in + if Sys.file_exists file then begin + (try + let ext = String.rindex file '.' in + let file_pf = String.sub file 0 (ext + 1) ^ platform_name ctx.platform ^ String.sub file ext (String.length file - ext) in + if not (defined ctx Define.CoreApi) && Sys.file_exists file_pf then file_pf else file + with Not_found -> + file) + end else + loop (had_empty || p = "") l + in + let r = (try Some (loop false ctx.class_path) with Not_found -> None) in + Hashtbl.add ctx.file_lookup_cache f r; + (match r with + | None -> raise Not_found + | Some f -> f) + +let rec mkdir_recursive base dir_list = + match dir_list with + | [] -> () + | dir :: remaining -> + let path = match base with + | "" -> dir + | "/" -> "/" ^ dir + | _ -> base ^ "/" ^ dir + in + if not ( (path = "") || ( ((String.length path) = 2) && ((String.sub path 1 1) = ":") ) ) then + if not (Sys.file_exists path) then + Unix.mkdir path 0o755; + mkdir_recursive (if (path = "") then "/" else path) remaining + +let mkdir_from_path path = + let parts = Str.split_delim (Str.regexp "[\\/]+") path in + match parts with + | [] -> (* path was "" *) () + | _ -> + let dir_list = List.rev (List.tl (List.rev parts)) in + mkdir_recursive "" dir_list + +let mem_size v = + Objsize.size_with_headers (Objsize.objsize v [] []) + +(* ------------------------- TIMERS ----------------------------- *) + +type timer_infos = { + id : string list; + mutable start : float list; + mutable total : float; + mutable calls : int; +} + +let get_time = Extc.time +let htimers = Hashtbl.create 0 + +let new_timer id = + let key = String.concat "." id in + try + let t = Hashtbl.find htimers key in + t.start <- get_time() :: t.start; + t.calls <- t.calls + 1; + t + with Not_found -> + let t = { id = id; start = [get_time()]; total = 0.; calls = 1; } in + Hashtbl.add htimers key t; + t + +let curtime = ref [] + +let close t = + let start = (match t.start with + | [] -> assert false + | s :: l -> t.start <- l; s + ) in + let now = get_time() in + let dt = now -. start in + t.total <- t.total +. dt; + let rec loop() = + match !curtime with + | [] -> failwith ("Timer " ^ (String.concat "." t.id) ^ " closed while not active") + | tt :: l -> curtime := l; if t != tt then loop() + in + loop(); + (* because of rounding errors while adding small times, we need to make sure that we don't have start > now *) + List.iter (fun ct -> ct.start <- List.map (fun t -> let s = t +. dt in if s > now then now else s) ct.start) !curtime + +let timer id = + let t = new_timer id in + curtime := t :: !curtime; + (function() -> close t) + +let rec close_times() = + match !curtime with + | [] -> () + | t :: _ -> close t; close_times() + +;; + +(* Taken from OCaml source typing/oprint.ml + + This is a better version of string_of_float which prints without loss of precision + so that float_of_string (float_repres x) = x for all floats x +*) +let valid_float_lexeme s = + let l = String.length s in + let rec loop i = + if i >= l then s ^ "." else + match s.[i] with + | '0' .. '9' | '-' -> loop (i+1) + | _ -> s + in loop 0 + +let float_repres f = + match classify_float f with + | FP_nan -> "nan" + | FP_infinite -> + if f < 0.0 then "neg_infinity" else "infinity" + | _ -> + let float_val = + let s1 = Printf.sprintf "%.12g" f in + if f = float_of_string s1 then s1 else + let s2 = Printf.sprintf "%.15g" f in + if f = float_of_string s2 then s2 else + Printf.sprintf "%.18g" f + in valid_float_lexeme float_val + +let add_diagnostics_message com s p sev = + let di = com.shared.shared_display_information in + di.diagnostics_messages <- (s,p,sev) :: di.diagnostics_messages + +open Printer + +let dump_context com = s_record_fields "" [ + "version",string_of_int com.version; + "args",s_list ", " (fun s -> s) com.args; + "debug",string_of_bool com.debug; + "platform",platform_name com.platform; + "std_path",s_list ", " (fun s -> s) com.std_path; + "class_path",s_list ", " (fun s -> s) com.class_path; + "defines",s_pmap (fun s -> s) (fun s -> s) com.defines; + "defines_signature",s_opt (fun s -> Digest.to_hex s) com.defines_signature; +] diff --git a/src/context/meta.ml b/src/context/meta.ml new file mode 100644 index 00000000..0cbba02d --- /dev/null +++ b/src/context/meta.ml @@ -0,0 +1,430 @@ +open Globals + +type strict_meta = + | Abi + | Abstract + | Access + | Accessor + | Allow + | Analyzer + | Annotation + | ArrayAccess + | Ast + | AstSource + | AutoBuild + | Bind + | Bitmap + | BridgeProperties + | Build + | BuildXml + | Callable + | Class + | ClassCode + | Commutative + | CompilerGenerated + | Const + | CoreApi + | CoreType + | CppFileCode + | CppInclude + | CppNamespaceCode + | CsNative + | Dce + | Debug + | Decl + | DefParam + | Delegate + | Depend + | Deprecated + | DirectlyUsed + | DynamicObject + | Eager + | Enum + | EnumConstructorParam + | Event + | Exhaustive + | Expose + | Extern + | FakeEnum + | File + | FileXml + | Final + | Fixed + | FlatEnum + | Font + | Forward + | ForwardStatics + | From + | FunctionCode + | FunctionTailCode + | Generic + | GenericBuild + | GenericInstance + | Getter + | Hack + | HasUntyped + | HaxeGeneric + | HeaderClassCode + | HeaderCode + | HeaderInclude + | HeaderNamespaceCode + | HxGen + | IfFeature + | Impl + | PythonImport + | ImplicitCast + | Include + | InitPackage + | InlineConstructorVariable + | Internal + | IsVar + | JavaCanonical + | JavaNative + | JsRequire + | Keep + | KeepInit + | KeepSub + | LibType + | LuaRequire + | Meta + | Macro + | MaybeUsed + | MergeBlock + | MultiReturn + | MultiType + | Native + | NativeChildren + | NativeGen + | NativeGeneric + | NativeProperty + | NativeStaticExtension + | NoCompletion + | NoDebug + | NoDoc + | NoExpr + | NoImportGlobal + | NonVirtual + | NoPackageRestrict + | NoPrivateAccess + | NoStack + | NotNull + | NoUsing + | Ns + | Objc + | ObjcProtocol + | Op + | Optional + | Overload + | PhpConstants + | PhpGlobal + | PhpClassConst + | PhpMagic + | PhpNoConstructor + | PrivateAccess + | Property + | Protected + | Public + | PublicFields + | Pure + | QuotedField + | ReadOnly + | RealPath + | Remove + | Require + | RequiresAssign + | Resolve + | Rtti + | Runtime + | RuntimeValue + | Scalar + | SelfCall + | Setter + | SkipCtor + | SkipReflection + | Sound + | SourceFile + | StackOnly + | StoredTypedExpr + | Strict + | Struct + | StructAccess + | StructInit + | SuppressWarnings + | This + | Throws + | To + | ToString + | Transient + | TemplatedCall + | ValueUsed + | Volatile + | Unbound + | UnifyMinDynamic + | Unreflective + | Unsafe + | Usage + | Used + | UserVariable + | Value + | Void + | Last + (* do not put any custom metadata after Last *) + | Dollar of string + | Custom of string + +let has m ml = List.exists (fun (m2,_,_) -> m = m2) ml +let get m ml = List.find (fun (m2,_,_) -> m = m2) ml + +type meta_usage = + | TClass + | TClassField + | TAbstract + | TAbstractField + | TEnum + | TTypedef + | TAnyField + | TExpr + | TTypeParameter + +type meta_parameter = + | HasParam of string + | Platform of platform + | Platforms of platform list + | UsedOn of meta_usage + | UsedOnEither of meta_usage list + | UsedInternally + +let get_info = function + | Abi -> ":abi",("Function ABI/calling convention",[Platforms [Cpp]]) + | Abstract -> ":abstract",("Sets the underlying class implementation as 'abstract'",[Platforms [Java;Cs]]) + | Access -> ":access",("Forces private access to package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]]) + | Accessor -> ":accessor",("Used internally by DCE to mark property accessors",[UsedOn TClassField;UsedInternally]) + | Allow -> ":allow",("Allows private access from package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]]) + | Analyzer -> ":analyzer",("Used to configure the static analyzer",[]) + | Annotation -> ":annotation",("Annotation (@interface) definitions on -java-lib imports will be annotated with this metadata. Has no effect on types compiled by Haxe",[Platform Java; UsedOn TClass]) + | ArrayAccess -> ":arrayAccess",("Allows [] access on an abstract",[UsedOnEither [TAbstract;TAbstractField]]) + | Ast -> ":ast",("Internally used to pass the AST source into the typed AST",[UsedInternally]) + | AstSource -> ":astSource",("Filled by the compiler with the parsed expression of the field",[UsedOn TClassField]) + | AutoBuild -> ":autoBuild",("Extends @:build metadata to all extending and implementing classes",[HasParam "Build macro call";UsedOn TClass]) + | Bind -> ":bind",("Override Swf class declaration",[Platform Flash;UsedOn TClass]) + | Bitmap -> ":bitmap",("Embeds given bitmap data into the class (must extend flash.display.BitmapData)",[HasParam "Bitmap file path";UsedOn TClass;Platform Flash]) + | BridgeProperties -> ":bridgeProperties",("Creates native property bridges for all Haxe properties in this class",[UsedOn TClass;Platform Cs]) + | Build -> ":build",("Builds a class or enum from a macro",[HasParam "Build macro call";UsedOnEither [TClass;TEnum]]) + | BuildXml -> ":buildXml",("Specify xml data to be injected into Build.xml",[Platform Cpp]) + | Callable -> ":callable",("Abstract forwards call to its underlying type",[UsedOn TAbstract]) + | Class -> ":class",("Used internally to annotate an enum that will be generated as a class",[Platforms [Java;Cs]; UsedOn TEnum; UsedInternally]) + | ClassCode -> ":classCode",("Used to inject platform-native code into a class",[Platforms [Java;Cs]; UsedOn TClass]) + | Commutative -> ":commutative",("Declares an abstract operator as commutative",[UsedOn TAbstractField]) + | CompilerGenerated -> ":compilerGenerated",("Marks a field as generated by the compiler. Shouldn't be used by the end user",[Platforms [Java;Cs]]) + | Const -> ":const",("Allows a type parameter to accept expression values",[UsedOn TTypeParameter]) + | CoreApi -> ":coreApi",("Identifies this class as a core api class (forces Api check)",[UsedOnEither [TClass;TEnum;TTypedef;TAbstract]]) + | CoreType -> ":coreType",("Identifies an abstract as core type so that it requires no implementation",[UsedOn TAbstract]) + | CppFileCode -> ":cppFileCode",("Code to be injected into generated cpp file",[Platform Cpp]) + | CppInclude -> ":cppInclude",("File to be included in generated cpp file",[Platform Cpp]) + | CppNamespaceCode -> ":cppNamespaceCode",("",[Platform Cpp]) + | CsNative -> ":csNative",("Automatically added by -net-lib on classes generated from .NET DLL files",[Platform Cs; UsedOnEither[TClass;TEnum]; UsedInternally]) + | Dce -> ":dce",("Forces dead code elimination even when -dce full is not specified",[UsedOnEither [TClass;TEnum]]) + | Debug -> ":debug",("Forces debug information to be generated into the Swf even without -debug",[UsedOnEither [TClass;TClassField]; Platform Flash]) + | Decl -> ":decl",("",[Platform Cpp]) + | DefParam -> ":defParam",("Default function argument value loaded from the SWF and used for documentation in Genxml",[Platform Flash;UsedInternally]) + | Delegate -> ":delegate",("Automatically added by -net-lib on delegates",[Platform Cs; UsedOn TAbstract]) + | Depend -> ":depend",("",[Platform Cpp]) + | Deprecated -> ":deprecated",("Mark a type or field as deprecated",[]) + | DirectlyUsed -> ":directlyUsed",("Marks types that are directly referenced by non-extern code",[UsedInternally]) + | DynamicObject -> ":dynamicObject",("Used internally to identify the Dynamic Object implementation",[Platforms [Java;Cs]; UsedOn TClass; UsedInternally]) + | Eager -> ":eager",("Forces typedefs to be followed early",[UsedOn TTypedef]) + | Enum -> ":enum",("Defines finite value sets to abstract definitions",[UsedOn TAbstract]) + | EnumConstructorParam -> ":enumConstructorParam",("Used internally to annotate GADT type parameters",[UsedOn TClass; UsedInternally]) + | Event -> ":event",("Automatically added by -net-lib on events. Has no effect on types compiled by Haxe",[Platform Cs; UsedOn TClassField]) + | Exhaustive -> ":exhaustive",("",[UsedInternally]) + | Expose -> ":expose",("Makes the class available on the window object",[HasParam "?Name=Class path";UsedOn TClass;Platform Js]) + | Extern -> ":extern",("Marks the field as extern so it is not generated",[UsedOn TClassField]) + | FakeEnum -> ":fakeEnum",("Treat enum as collection of values of the specified type",[HasParam "Type name";UsedOn TEnum]) + | File -> ":file",("Includes a given binary file into the target Swf and associates it with the class (must extend flash.utils.ByteArray)",[HasParam "File path";UsedOn TClass;Platform Flash]) + | FileXml -> ":fileXml",("Include xml attribute snippet in Build.xml entry for file",[UsedOn TClass;Platform Cpp]) + | Final -> ":final",("Prevents a class from being extended",[UsedOn TClass]) + | Fixed -> ":fixed",("Delcares an anonymous object to have fixed fields",[ (*UsedOn TObjectDecl(_)*)]) + | FlatEnum -> ":flatEnum",("Internally used to mark an enum as being flat, i.e. having no function constructors",[UsedOn TEnum; UsedInternally]) + | Font -> ":font",("Embeds the given TrueType font into the class (must extend flash.text.Font)",[HasParam "TTF path";HasParam "Range String";UsedOn TClass]) + | Forward -> ":forward",("Forwards field access to underlying type",[HasParam "List of field names";UsedOn TAbstract]) + | ForwardStatics -> ":forwardStatics",("Forwards static field access to underlying type",[HasParam "List of field names";UsedOn TAbstract]) + | From -> ":from",("Specifies that the field of the abstract is a cast operation from the type identified in the function",[UsedOn TAbstractField]) + | FunctionCode -> ":functionCode",("Used to inject platform-native code into a function",[Platforms [Cpp;Java;Cs]]) + | FunctionTailCode -> ":functionTailCode",("",[Platform Cpp]) + | Generic -> ":generic",("Marks a class or class field as generic so each type parameter combination generates its own type/field",[UsedOnEither [TClass;TClassField]]) + | GenericBuild -> ":genericBuild",("Builds instances of a type using the specified macro",[UsedOn TClass]) + | GenericInstance -> ":genericInstance",("Internally used to mark instances of @:generic methods",[UsedOn TClassField;UsedInternally]) + | Getter -> ":getter",("Generates a native getter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash]) + | Hack -> ":hack",("Allows extending classes marked as @:final",[UsedOn TClass]) + | HasUntyped -> (":has_untyped",("Used by the typer to mark fields that have untyped expressions",[UsedInternally])) + | HaxeGeneric -> ":haxeGeneric",("Used internally to annotate non-native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; UsedInternally]) + | HeaderClassCode -> ":headerClassCode",("Code to be injected into the generated class, in the header",[Platform Cpp]) + | HeaderCode -> ":headerCode",("Code to be injected into the generated header file",[Platform Cpp]) + | HeaderInclude -> ":headerInclude",("File to be included in generated header file",[Platform Cpp]) + | HeaderNamespaceCode -> ":headerNamespaceCode",("",[Platform Cpp]) + | HxGen -> ":hxGen",("Annotates that an extern class was generated by Haxe",[Platforms [Java;Cs]; UsedOnEither [TClass;TEnum]]) + | IfFeature -> ":ifFeature",("Causes a field to be kept by DCE if the given feature is part of the compilation",[HasParam "Feature name";UsedOn TClassField]) + | Impl -> ":impl",("Used internally to mark abstract implementation fields",[UsedOn TAbstractField; UsedInternally]) + | PythonImport -> ":pythonImport",("Generates python import statement for extern classes",[Platforms [Python]; UsedOn TClass]) + | ImplicitCast -> ":implicitCast",("Generated automatically on the AST when an implicit abstract cast happens",[UsedInternally; UsedOn TExpr]) + | Include -> ":include",("",[Platform Cpp]) + | InitPackage -> ":initPackage",("Some weird thing for Genjs we want to remove someday",[UsedInternally; Platform Js]) + | InlineConstructorVariable -> ":inlineConstructorVariable",("Internally used to mark variables that come from inlined constructors",[UsedInternally]) + | Internal -> ":internal",("Generates the annotated field/class with 'internal' access",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum;TClassField]]) + | IsVar -> ":isVar",("Forces a physical field to be generated for properties that otherwise would not require one",[UsedOn TClassField]) + | JavaCanonical -> ":javaCanonical",("Used by the Java target to annotate the canonical path of the type",[HasParam "Output type package";HasParam "Output type name";UsedOnEither [TClass;TEnum]; Platform Java]) + | JavaNative -> ":javaNative",("Automatically added by -java-lib on classes generated from JAR/class files",[Platform Java; UsedOnEither[TClass;TEnum]; UsedInternally]) + | JsRequire -> ":jsRequire",("Generate javascript module require expression for given extern",[Platform Js; UsedOn TClass]) + | LuaRequire -> ":luaRequire",("Generate lua module require expression for given extern",[Platform Lua; UsedOn TClass]) + | Keep -> ":keep",("Causes a field or type to be kept by DCE",[]) + | KeepInit -> ":keepInit",("Causes a class to be kept by DCE even if all its field are removed",[UsedOn TClass]) + | KeepSub -> ":keepSub",("Extends @:keep metadata to all implementing and extending classes",[UsedOn TClass]) + | LibType -> ":libType",("Used by -net-lib and -java-lib to mark a class that shouldn't be checked (overrides, interfaces, etc) by the type loader",[UsedInternally; UsedOn TClass; Platforms [Java;Cs]]) + | Meta -> ":meta",("Internally used to mark a class field as being the metadata field",[]) + | Macro -> ":macro",("(deprecated)",[]) + | MaybeUsed -> ":maybeUsed",("Internally used by DCE to mark fields that might be kept",[UsedInternally]) + | MergeBlock -> ":mergeBlock",("Merge the annotated block into the current scope",[UsedOn TExpr]) + | MultiReturn -> ":multiReturn",("Annotates an extern class as the result of multi-return function",[UsedOn TClass; Platform Lua]) + | MultiType -> ":multiType",("Specifies that an abstract chooses its this-type from its @:to functions",[UsedOn TAbstract; HasParam "Relevant type parameters"]) + | Native -> ":native",("Rewrites the path of a class or enum during generation",[HasParam "Output type path";UsedOnEither [TClass;TEnum]]) + | NativeChildren -> ":nativeChildren",("Annotates that all children from a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs]; UsedOn TClass]) + | NativeGen -> ":nativeGen",("Annotates that a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs;Python]; UsedOnEither[TClass;TEnum]]) + | NativeGeneric -> ":nativeGeneric",("Used internally to annotate native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; UsedInternally]) + | NativeProperty -> ":nativeProperty",("Use native properties which will execute even with dynamic usage",[Platform Cpp]) + | NativeStaticExtension -> ":nativeStaticExtension",("Converts static function syntax into member call",[Platform Cpp]) + | NoCompletion -> ":noCompletion",("Prevents the compiler from suggesting completion on this field",[UsedOn TClassField]) + | NoDebug -> ":noDebug",("Does not generate debug information into the Swf even if -debug is set",[UsedOnEither [TClass;TClassField];Platform Flash]) + | NoDoc -> ":noDoc",("Prevents a type from being included in documentation generation",[]) + | NoExpr -> ":noExpr",("Internally used to mark abstract fields which have no expression by design",[UsedInternally]) + | NoImportGlobal -> ":noImportGlobal",("Prevents a static field from being imported with import Class.*",[UsedOn TAnyField]) + | NonVirtual -> ":nonVirtual",("Declares function to be non-virtual in cpp",[Platform Cpp]) + | NoPackageRestrict -> ":noPackageRestrict",("Allows a module to be accessed across all targets if found on its first type",[UsedInternally]) + | NoPrivateAccess -> ":noPrivateAccess",("Disallow private access to anything for the annotated expression",[UsedOn TExpr]) + | NoStack -> ":noStack",("",[Platform Cpp]) + | NotNull -> ":notNull",("Declares an abstract type as not accepting null values",[UsedOn TAbstract]) + | NoUsing -> ":noUsing",("Prevents a field from being used with 'using'",[UsedOn TClassField]) + | Ns -> ":ns",("Internally used by the Swf generator to handle namespaces",[Platform Flash]) + | Objc -> ":objc",("Declares a class or interface that is used to interoperate with Objective-C code",[Platform Cpp;UsedOn TClass]) + | ObjcProtocol -> ":objcProtocol",("Associates an interface with, or describes a function in, a native Objective-C protocol.",[Platform Cpp;UsedOnEither [TClass;TClassField] ]) + | Op -> ":op",("Declares an abstract field as being an operator overload",[HasParam "The operation";UsedOn TAbstractField]) + | Optional -> ":optional",("Marks the field of a structure as optional",[UsedOn TClassField]) + | Overload -> ":overload",("Allows the field to be called with different argument types",[HasParam "Function specification (no expression)";UsedOn TClassField]) + | PhpConstants -> ":phpConstants",("Marks the static fields of a class as PHP constants, without $",[Platform Php;UsedOn TClass]) + | PhpGlobal -> ":phpGlobal",("(php7) Puts the static fields of a class in the global PHP namespace",[Platforms [Php;Php];UsedOn TClass]) + | PhpClassConst -> ":phpClassConst",("(php7) Generate static var of an extern class as a PHP class constant",[Platform Php;UsedOn TClass]) + | PhpMagic -> ":phpMagic",("(php7) Treat annotated field as special PHP magic field",[Platform Php;UsedOn TClassField]) + | PhpNoConstructor -> ":phpNoConstructor",("(php7) Special meta for extern classes which does not have native constructor in PHP, but need a constructor in Haxe extern",[Platform Php;UsedOn TClass]) + | Public -> ":public",("Marks a class field as being public",[UsedOn TClassField;UsedInternally]) + | PublicFields -> ":publicFields",("Forces all class fields of inheriting classes to be public",[UsedOn TClass]) + | QuotedField -> ":quotedField",("Used internally to mark structure fields which are quoted in syntax",[UsedInternally]) + | PrivateAccess -> ":privateAccess",("Allow private access to anything for the annotated expression",[UsedOn TExpr]) + | Protected -> ":protected",("Marks a class field as being protected",[UsedOn TClassField;Platforms [Cs;Java;Flash]]) + | Property -> ":property",("Marks a property field to be compiled as a native C# property",[UsedOn TClassField;Platform Cs]) + | Pure -> ":pure",("Marks a class field, class or expression as pure (side-effect free)",[UsedOnEither [TClass;TClassField;TExpr]]) + | ReadOnly -> ":readOnly",("Generates a field with the 'readonly' native keyword",[Platform Cs; UsedOn TClassField]) + | RealPath -> ":realPath",("Internally used on @:native types to retain original path information",[UsedInternally]) + | Remove -> ":remove",("Causes an interface to be removed from all implementing classes before generation",[UsedOn TClass]) + | Require -> ":require",("Allows access to a field only if the specified compiler flag is set",[HasParam "Compiler flag to check";UsedOn TClassField]) + | RequiresAssign -> ":requiresAssign",("Used internally to mark certain abstract operator overloads",[UsedInternally]) + | Resolve -> ":resolve",("Abstract fields marked with this metadata can be used to resolve unknown fields",[UsedOn TClassField]) + | Rtti -> ":rtti",("Adds runtime type informations",[UsedOn TClass]) + | Runtime -> ":runtime",("?",[]) + | RuntimeValue -> ":runtimeValue",("Marks an abstract as being a runtime value",[UsedOn TAbstract]) + | Scalar -> ":scalar",("Used by hxcpp to mark a custom coreType abstract",[UsedOn TAbstract; Platform Cpp]) + | SelfCall -> ":selfCall",("Translates method calls into calling object directly",[UsedOn TClassField; Platform Js]) + | Setter -> ":setter",("Generates a native setter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash]) + | StackOnly -> ":stackOnly",("Instances of this type can only appear on the stack",[Platform Cpp]) + | StoredTypedExpr -> ":storedTypedExpr",("Used internally to reference a typed expression returned from a macro",[UsedInternally]) + | SkipCtor -> ":skipCtor",("Used internally to generate a constructor as if it were a native type (no __hx_ctor)",[Platforms [Java;Cs]; UsedInternally]) + | SkipReflection -> ":skipReflection",("Used internally to annotate a field that shouldn't have its reflection data generated",[Platforms [Java;Cs]; UsedOn TClassField; UsedInternally]) + | Sound -> ":sound",( "Includes a given .wav or .mp3 file into the target Swf and associates it with the class (must extend flash.media.Sound)",[HasParam "File path";UsedOn TClass;Platform Flash]) + | SourceFile -> ":sourceFile",("Source code filename for external class",[Platform Cpp]) + | Strict -> ":strict",("Used to declare a native C# attribute or a native Java metadata. Is type checked",[Platforms [Java;Cs]]) + | Struct -> ":struct",("Marks a class definition as a struct",[Platform Cs; UsedOn TClass]) + | StructAccess -> ":structAccess",("Marks an extern class as using struct access('.') not pointer('->')",[Platform Cpp; UsedOn TClass]) + | StructInit -> ":structInit",("Allows to initialize the class with a structure that matches constructor parameters",[UsedOn TClass]) + | SuppressWarnings -> ":suppressWarnings",("Adds a SuppressWarnings annotation for the generated Java class",[Platform Java; UsedOn TClass]) + | TemplatedCall -> ":templatedCall",("Indicates that the first parameter of static call should be treated as a template arguement",[Platform Cpp; UsedOn TClassField]) + | Throws -> ":throws",("Adds a 'throws' declaration to the generated function",[HasParam "Type as String"; Platform Java; UsedOn TClassField]) + | This -> ":this",("Internally used to pass a 'this' expression to macros",[UsedInternally; UsedOn TExpr]) + | To -> ":to",("Specifies that the field of the abstract is a cast operation to the type identified in the function",[UsedOn TAbstractField]) + | ToString -> ":toString",("Internally used",[UsedInternally]) + | Transient -> ":transient",("Adds the 'transient' flag to the class field",[Platform Java; UsedOn TClassField]) + | ValueUsed -> ":valueUsed",("Internally used by DCE to mark an abstract value as used",[UsedInternally]) + | Volatile -> ":volatile",("",[Platforms [Java;Cs]]) + | Unbound -> ":unbound", ("Compiler internal to denote unbounded global variable",[UsedInternally]) + | UnifyMinDynamic -> ":unifyMinDynamic",("Allows a collection of types to unify to Dynamic",[UsedOn TClassField]) + | Unreflective -> ":unreflective",("",[Platform Cpp]) + | Unsafe -> ":unsafe",("Declares a class, or a method with the C#'s 'unsafe' flag",[Platform Cs; UsedOnEither [TClass;TClassField]]) + | Usage -> ":usage",("Internal metadata used to mark a symbol for which usage request was invoked",[UsedInternally]) + | Used -> ":used",("Internally used by DCE to mark a class or field as used",[UsedInternally]) + | UserVariable -> ":userVariable",("Internally used to mark variables that come from user code",[UsedInternally]) + | Value -> ":value",("Used to store default values for fields and function arguments",[UsedOn TClassField]) + | Void -> ":void",("Use Cpp native 'void' return type",[Platform Cpp]) + | Last -> assert false + (* do not put any custom metadata after Last *) + | Dollar s -> "$" ^ s,("",[]) + | Custom s -> s,("",[]) + +let to_string m = fst (get_info m) + +let hmeta = + let h = Hashtbl.create 0 in + let rec loop i = + let m = Obj.magic i in + if m <> Last then begin + Hashtbl.add h (fst (get_info m)) m; + loop (i + 1); + end; + in + loop 0; + h + +let parse s = try Hashtbl.find hmeta (":" ^ s) with Not_found -> Custom (":" ^ s) + +let from_string s = + if s = "" then Custom "" else match s.[0] with + | ':' -> (try Hashtbl.find hmeta s with Not_found -> Custom s) + | '$' -> Dollar (String.sub s 1 (String.length s - 1)) + | _ -> Custom s + +let get_documentation d = + let t, (doc,flags) = get_info d in + if not (List.mem UsedInternally flags) then begin + let params = ref [] and used = ref [] and pfs = ref [] in + List.iter (function + | HasParam s -> params := s :: !params + | Platform f -> pfs := f :: !pfs + | Platforms fl -> pfs := fl @ !pfs + | UsedOn u -> used := u :: !used + | UsedOnEither ul -> used := ul @ !used + | UsedInternally -> assert false + ) flags; + let params = (match List.rev !params with + | [] -> "" + | l -> "(" ^ String.concat "," l ^ ")" + ) in + let pfs = (match List.rev !pfs with + | [] -> "" + | [p] -> " (" ^ platform_name p ^ " only)" + | pl -> " (for " ^ String.concat "," (List.map platform_name pl) ^ ")" + ) in + let str = "@" ^ t in + Some (str,params ^ doc ^ pfs) + end else + None + +let get_documentation_list () = + let m = ref 0 in + let rec loop i = + let d = Obj.magic i in + if d <> Last then begin match get_documentation d with + | None -> loop (i + 1) + | Some (str,desc) -> + if String.length str > !m then m := String.length str; + (str,desc) :: loop (i + 1) + end else + [] + in + let all = List.sort (fun (s1,_) (s2,_) -> String.compare s1 s2) (loop 0) in + all,!m \ No newline at end of file diff --git a/src/display/display.ml b/src/display/display.ml new file mode 100644 index 00000000..466bd411 --- /dev/null +++ b/src/display/display.ml @@ -0,0 +1,926 @@ +open Ast +open Common +open Common.DisplayMode +open Type +open Typecore +open Globals + +type display_field_kind = + | FKVar of t + | FKMethod of t + | FKType of t + | FKModule + | FKPackage + | FKMetadata + | FKTimer of string + +let display_field_kind_index = function + | FKVar _ -> 0 + | FKMethod _ -> 1 + | FKType _ -> 2 + | FKModule -> 3 + | FKPackage -> 4 + | FKMetadata -> 5 + | FKTimer _ -> 6 + +exception Diagnostics of string +exception Statistics of string +exception ModuleSymbols of string +exception Metadata of string +exception DisplaySignatures of (t * documentation) list * int +exception DisplayType of t * pos * string option +exception DisplayPosition of pos list +exception DisplayFields of (string * display_field_kind * documentation) list +exception DisplayToplevel of IdentifierType.t list +exception DisplayPackage of string list + +let is_display_file file = + file <> "?" && Path.unique_full_path file = (!Parser.resume_display).pfile + +let encloses_position p_target p = + p.pmin <= p_target.pmin && p.pmax >= p_target.pmax + +let is_display_position p = + encloses_position !Parser.resume_display p + +module ExprPreprocessing = struct + let find_enclosing com e = + let display_pos = ref (!Parser.resume_display) in + let mk_null p = (EDisplay(((EConst(Ident "null")),p),false),p) in + let encloses_display_pos p = + if encloses_position !display_pos p then begin + let p = !display_pos in + display_pos := { pfile = ""; pmin = -2; pmax = -2 }; + Some p + end else + None + in + let rec loop e = match fst e with + | EBlock el -> + let p = pos e in + (* We want to find the innermost block which contains the display position. *) + let el = List.map loop el in + let el = match encloses_display_pos p with + | None -> + el + | Some p2 -> + let b,el = List.fold_left (fun (b,el) e -> + let p = pos e in + if b || p.pmax <= p2.pmin then begin + (b,e :: el) + end else begin + let e_d = (EDisplay(mk_null p,false)),p in + (true,e :: e_d :: el) + end + ) (false,[]) el in + let el = if b then + el + else begin + mk_null p :: el + end in + List.rev el + in + (EBlock el),(pos e) + | _ -> + Ast.map_expr loop e + in + loop e + + let find_before_pos com e = + let display_pos = ref (!Parser.resume_display) in + let is_annotated p = + if p.pmin <= !display_pos.pmin && p.pmax >= !display_pos.pmax then begin + display_pos := { pfile = ""; pmin = -2; pmax = -2 }; + true + end else + false + in + let loop e = + if is_annotated (pos e) then + (EDisplay(e,false),(pos e)) + else + e + in + let rec map e = + loop (Ast.map_expr map e) + in + map e + + let find_display_call e = + let found = ref false in + let loop e = if !found then e else match fst e with + | ECall _ | ENew _ when is_display_position (pos e) -> + found := true; + (EDisplay(e,true),(pos e)) + | _ -> + e + in + let rec map e = match fst e with + | EDisplay(_,true) -> + found := true; + e + | EDisplay(e1,false) -> map e1 + | _ -> loop (Ast.map_expr map e) + in + map e + + + let process_expr com e = match com.display.dms_kind with + | DMToplevel -> find_enclosing com e + | DMPosition | DMUsage _ | DMType -> find_before_pos com e + | DMSignature -> find_display_call e + | _ -> e +end + +module DisplayEmitter = struct + let display_module_type dm mt p = match dm.dms_kind with + | DMPosition -> raise (DisplayPosition [(t_infos mt).mt_pos]); + | DMUsage _ -> + let ti = t_infos mt in + ti.mt_meta <- (Meta.Usage,[],ti.mt_pos) :: ti.mt_meta + | DMType -> raise (DisplayType (type_of_module_type mt,p,None)) + | _ -> () + + let rec display_type dm t p = match dm.dms_kind with + | DMType -> raise (DisplayType (t,p,None)) + | _ -> + try display_module_type dm (module_type_of_type t) p + with Exit -> match follow t,follow !t_dynamic_def with + | _,TDynamic _ -> () (* sanity check in case it's still t_dynamic *) + | TDynamic _,_ -> display_type dm !t_dynamic_def p + | _ -> () + + let check_display_type ctx t p = + let add_type_hint () = + Hashtbl.replace ctx.com.shared.shared_display_information.type_hints p t; + in + let maybe_display_type () = + if ctx.is_display_file && is_display_position p then + display_type ctx.com.display t p + in + match ctx.com.display.dms_kind with + | DMStatistics -> add_type_hint() + | DMUsage _ -> add_type_hint(); maybe_display_type() + | _ -> maybe_display_type() + + let display_variable dm v p = match dm.dms_kind with + | DMPosition -> raise (DisplayPosition [v.v_pos]) + | DMUsage _ -> v.v_meta <- (Meta.Usage,[],v.v_pos) :: v.v_meta; + | DMType -> raise (DisplayType (v.v_type,p,None)) + | _ -> () + + let display_field dm cf p = match dm.dms_kind with + | DMPosition -> raise (DisplayPosition [cf.cf_pos]); + | DMUsage _ -> cf.cf_meta <- (Meta.Usage,[],cf.cf_pos) :: cf.cf_meta; + | DMType -> raise (DisplayType (cf.cf_type,p,cf.cf_doc)) + | _ -> () + + let maybe_display_field ctx p cf = + if is_display_position p then display_field ctx.com.display cf p + + let display_enum_field dm ef p = match dm.dms_kind with + | DMPosition -> raise (DisplayPosition [p]); + | DMUsage _ -> ef.ef_meta <- (Meta.Usage,[],p) :: ef.ef_meta; + | DMType -> raise (DisplayType (ef.ef_type,p,ef.ef_doc)) + | _ -> () + + let display_meta dm meta = match dm.dms_kind with + | DMType -> + begin match meta with + | Meta.Custom _ | Meta.Dollar _ -> () + | _ -> match Meta.get_documentation meta with + | None -> () + | Some (_,s) -> + (* TODO: hack until we support proper output for hover display mode *) + raise (Metadata ("" ^ s ^ "")); + end + | DMField -> + let all,_ = Meta.get_documentation_list() in + let all = List.map (fun (s,doc) -> (s,FKMetadata,Some doc)) all in + raise (DisplayFields all) + | _ -> + () + + let check_display_metadata ctx meta = + List.iter (fun (meta,args,p) -> + if is_display_position p then display_meta ctx.com.display meta; + List.iter (fun e -> + if is_display_position (pos e) then begin + let e = ExprPreprocessing.process_expr ctx.com e in + delay ctx PTypeField (fun _ -> ignore(type_expr ctx e Value)); + end + ) args + ) meta +end + +module DocumentSymbols = struct + open DisplayTypes.SymbolKind + + let collect_module_symbols (pack,decls) = + let l = DynArray.create() in + let add name kind location parent = + let si = DisplayTypes.SymbolInformation.make name kind location (if parent = "" then None else Some parent) in + DynArray.add l si; + in + let rec expr parent (e,p) = + let add name kind location = add name kind location parent in + begin match e with + | EVars vl -> + List.iter (fun ((s,p),_,eo) -> + add s Variable p; + expr_opt parent eo + ) vl + | ETry(e1,catches) -> + expr parent e1; + List.iter (fun ((s,p),_,e,_) -> + add s Variable p; + expr parent e + ) catches; + | EFunction(Some s,f) -> + add s Function p; + func parent f + | EIn((EConst(Ident s),p),e2) -> + add s Variable p; + expr parent e2; + | _ -> + iter_expr (expr parent) (e,p) + end + and expr_opt parent eo = match eo with + | None -> () + | Some e -> expr parent e + and func parent f = + List.iter (fun ((s,p),_,_,_,eo) -> + add s Variable p parent; + expr_opt parent eo + ) f.f_args; + expr_opt parent f.f_expr + in + let field parent cff = + let field_parent = parent ^ "." ^ (fst cff.cff_name) in + match cff.cff_kind with + | FVar(_,eo) -> + add (fst cff.cff_name) Field cff.cff_pos parent; + expr_opt field_parent eo + | FFun f -> + add (fst cff.cff_name) (if fst cff.cff_name = "new" then Constructor else Method) cff.cff_pos parent; + func field_parent f + | FProp(_,_,_,eo) -> + add (fst cff.cff_name) Property cff.cff_pos parent; + expr_opt field_parent eo + in + List.iter (fun (td,p) -> match td with + | EImport _ | EUsing _ -> + () (* TODO: Can we do anything with these? *) + | EClass d -> + add (fst d.d_name) (if List.mem HInterface d.d_flags then Interface else Class) p ""; + List.iter (field (fst d.d_name)) d.d_data + | EEnum d -> + add (fst d.d_name) Enum p ""; + List.iter (fun ef -> + add (fst ef.ec_name) Method ef.ec_pos (fst d.d_name) + ) d.d_data + | ETypedef d -> + add (fst d.d_name) Typedef p ""; + (match d.d_data with + | CTAnonymous fields,_ -> + List.iter (field (fst d.d_name)) fields + | _ -> ()) + | EAbstract d -> + add (fst d.d_name) Abstract p ""; + List.iter (field (fst d.d_name)) d.d_data + ) decls; + l +end + +module DeprecationCheck = struct + + let curclass = ref null_class + + let warned_positions = Hashtbl.create 0 + + let print_deprecation_message com meta s p_usage = + let s = match meta with + | _,[EConst(String s),_],_ -> s + | _ -> Printf.sprintf "Usage of this %s is deprecated" s + in + if not (Hashtbl.mem warned_positions p_usage) then begin + Hashtbl.replace warned_positions p_usage true; + com.warning s p_usage; + end + + let check_meta com meta s p_usage = + try + print_deprecation_message com (Meta.get Meta.Deprecated meta) s p_usage; + with Not_found -> + () + + let check_cf com cf p = check_meta com cf.cf_meta "field" p + + let check_class com c p = if c != !curclass then check_meta com c.cl_meta "class" p + + let check_enum com en p = check_meta com en.e_meta "enum" p + + let check_ef com ef p = check_meta com ef.ef_meta "enum field" p + + let check_typedef com t p = check_meta com t.t_meta "typedef" p + + let check_module_type com mt p = match mt with + | TClassDecl c -> check_class com c p + | TEnumDecl en -> check_enum com en p + | _ -> () + + let run_on_expr com e = + let rec expr e = match e.eexpr with + | TField(e1,fa) -> + expr e1; + begin match fa with + | FStatic(c,cf) | FInstance(c,_,cf) -> + check_class com c e.epos; + check_cf com cf e.epos + | FAnon cf -> + check_cf com cf e.epos + | FClosure(co,cf) -> + (match co with None -> () | Some (c,_) -> check_class com c e.epos); + check_cf com cf e.epos + | FEnum(en,ef) -> + check_enum com en e.epos; + check_ef com ef e.epos; + | _ -> + () + end + | TNew(c,_,el) -> + List.iter expr el; + check_class com c e.epos; + (match c.cl_constructor with None -> () | Some cf -> check_cf com cf e.epos) + | TTypeExpr(mt) | TCast(_,Some mt) -> + check_module_type com mt e.epos + | TMeta((Meta.Deprecated,_,_) as meta,e1) -> + print_deprecation_message com meta "field" e1.epos; + expr e1; + | _ -> + Type.iter expr e + in + expr e + + let run_on_field com cf = match cf.cf_expr with None -> () | Some e -> run_on_expr com e + + let run com = + List.iter (fun t -> match t with + | TClassDecl c -> + curclass := c; + (match c.cl_constructor with None -> () | Some cf -> run_on_field com cf); + (match c.cl_init with None -> () | Some e -> run_on_expr com e); + List.iter (run_on_field com) c.cl_ordered_statics; + List.iter (run_on_field com) c.cl_ordered_fields; + | _ -> + () + ) com.types +end + +module Diagnostics = struct + module DiagnosticsKind = struct + type t = + | DKUnusedImport + | DKUnresolvedIdentifier + | DKCompilerError + | DKRemovableCode + + let to_int = function + | DKUnusedImport -> 0 + | DKUnresolvedIdentifier -> 1 + | DKCompilerError -> 2 + | DKRemovableCode -> 3 + end + + open DiagnosticsKind + open DisplayTypes + + let add_removable_code com s p prange = + let di = com.shared.shared_display_information in + di.removable_code <- (s,p,prange) :: di.removable_code + + let find_unused_variables com e = + let vars = Hashtbl.create 0 in + let pmin_map = Hashtbl.create 0 in + let rec loop e = match e.eexpr with + | TVar(v,eo) when Meta.has Meta.UserVariable v.v_meta -> + Hashtbl.add pmin_map e.epos.pmin v; + let p = match eo with + | None -> e.epos + | Some e1 -> + loop e1; + { e.epos with pmax = e1.epos.pmin } + in + Hashtbl.replace vars v.v_id (v,p); + | TLocal v when Meta.has Meta.UserVariable v.v_meta -> + Hashtbl.remove vars v.v_id; + | _ -> + Type.iter loop e + in + loop e; + Hashtbl.iter (fun _ (v,p) -> + let p = match (Hashtbl.find_all pmin_map p.pmin) with [_] -> p | _ -> null_pos in + add_removable_code com "Unused variable" v.v_pos p + ) vars + + let check_other_things com e = + let had_effect = ref false in + let no_effect p = + add_diagnostics_message com "This code has no effect" p DiagnosticsSeverity.Warning; + in + let pointless_compound s p = + add_diagnostics_message com (Printf.sprintf "This %s has no effect, but some of its sub-expressions do" s) p DiagnosticsSeverity.Warning; + in + let rec compound s el p = + let old = !had_effect in + had_effect := false; + List.iter (loop true) el; + if not !had_effect then no_effect p else pointless_compound s p; + had_effect := old; + and loop in_value e = match e.eexpr with + | TBlock el -> + let rec loop2 el = match el with + | [] -> () + | [e] -> loop in_value e + | e :: el -> loop false e; loop2 el + in + loop2 el + | TMeta((Meta.Extern,_,_),_) -> + (* This is so something like `[inlineFunc()]` is not reported. *) + had_effect := true; + | TLocal v when not (Meta.has Meta.UserVariable v.v_meta) -> + () + | TConst _ | TLocal _ | TTypeExpr _ | TFunction _ when not in_value -> + no_effect e.epos; + | TConst _ | TLocal _ | TTypeExpr _ | TEnumParameter _ | TVar _ -> + () + | TFunction tf -> + loop false tf.tf_expr + | TNew _ | TCall _ | TBinop ((Ast.OpAssignOp _ | Ast.OpAssign),_,_) | TUnop ((Ast.Increment | Ast.Decrement),_,_) + | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) + | TIf _ | TTry _ | TSwitch _ | TWhile _ | TFor _ -> + had_effect := true; + Type.iter (loop true) e + | TParenthesis e1 | TMeta(_,e1) -> + loop in_value e1 + | TArray _ | TCast (_,None) | TBinop _ | TUnop _ + | TField _ | TArrayDecl _ | TObjectDecl _ when in_value -> + Type.iter (loop true) e; + | TArray(e1,e2) -> compound "array access" [e1;e2] e.epos + | TCast(e1,None) -> compound "cast" [e1] e.epos + | TBinop(op,e1,e2) -> compound (Printf.sprintf "'%s' operator" (s_binop op)) [e1;e2] e.epos + | TUnop(op,_,e1) -> compound (Printf.sprintf "'%s' operator" (s_unop op)) [e1] e.epos + | TField(e1,_) -> compound "field access" [e1] e.epos + | TArrayDecl el -> compound "array declaration" el e.epos + | TObjectDecl fl -> compound "object declaration" (List.map snd fl) e.epos + in + loop true e + + let prepare_field com cf = match cf.cf_expr with + | None -> () + | Some e -> + find_unused_variables com e; + check_other_things com e; + DeprecationCheck.run_on_expr com e + + let prepare com global = + List.iter (function + | TClassDecl c when global || is_display_file c.cl_pos.pfile -> + List.iter (prepare_field com) c.cl_ordered_fields; + List.iter (prepare_field com) c.cl_ordered_statics; + (match c.cl_constructor with None -> () | Some cf -> prepare_field com cf); + | _ -> + () + ) com.types + + let is_diagnostics_run ctx = match ctx.com.display.dms_kind with + | DMDiagnostics true -> true + | DMDiagnostics false -> ctx.is_display_file + | _ -> false + + let secure_generated_code ctx e = + if is_diagnostics_run ctx then mk (TMeta((Meta.Extern,[],e.epos),e)) e.etype e.epos else e +end + +module ImportHandling = struct + type import_display_kind = + | IDKPackage of string list + | IDKModule of string list * string + | IDKSubType of string list * string * string + | IDKModuleField of string list * string * string + | IDKSubTypeField of string list * string * string * string + | IDK + + type import_display = import_display_kind * pos + + let convert_import_to_something_usable pt path = + let rec loop pack m t = function + | (s,p) :: l -> + let is_lower = is_lower_ident s in + let is_display_pos = encloses_position pt p in + begin match is_lower,m,t with + | _,None,Some _ -> + assert false (* impossible, I think *) + | true,Some m,None -> + if is_display_pos then (IDKModuleField(List.rev pack,m,s),p) + else (IDK,p) (* assume that we're done *) + | _,Some m,Some t -> + if is_display_pos then (IDKSubTypeField(List.rev pack,m,t,s),p) + else (IDK,p) + | true,None,None -> + if is_display_pos then (IDKPackage (List.rev (s :: pack)),p) + else loop (s :: pack) m t l + | false,Some sm,None -> + if is_display_pos then (IDKSubType (List.rev pack,sm,s),p) + else loop pack m (Some s) l + | false,None,None -> + if is_display_pos then (IDKModule (List.rev pack,s),p) + else loop pack (Some s) None l + end + | [] -> + (IDK,null_pos) + in + loop [] None None path + + let add_import_position com p path = + com.shared.shared_display_information.import_positions <- PMap.add p (ref false,path) com.shared.shared_display_information.import_positions + + let mark_import_position com p = + try + let r = fst (PMap.find p com.shared.shared_display_information.import_positions) in + r := true + with Not_found -> + () + + let maybe_mark_import_position ctx p = + if Diagnostics.is_diagnostics_run ctx then mark_import_position ctx.com p +end + +module Statistics = struct + open ImportHandling + + type relation = + | Implemented + | Extended + | Overridden + | Referenced + + type symbol = + | SKClass of tclass + | SKInterface of tclass + | SKEnum of tenum + | SKField of tclass_field + | SKEnumField of tenum_field + | SKVariable of tvar + + let is_usage_symbol symbol = + let meta = match symbol with + | SKClass c | SKInterface c -> c.cl_meta + | SKEnum en -> en.e_meta + | SKField cf -> cf.cf_meta + | SKEnumField ef -> ef.ef_meta + | SKVariable v -> v.v_meta + in + Meta.has Meta.Usage meta + + let collect_statistics ctx = + let relations = Hashtbl.create 0 in + let symbols = Hashtbl.create 0 in + let add_relation pos r = + if is_display_file pos.pfile then try + Hashtbl.replace relations pos (r :: Hashtbl.find relations pos) + with Not_found -> + Hashtbl.add relations pos [r] + in + let declare kind p = + if is_display_file p.pfile then begin + if not (Hashtbl.mem relations p) then Hashtbl.add relations p []; + Hashtbl.replace symbols p kind; + end + in + let collect_overrides c = + List.iter (fun cf -> + let rec loop c = match c.cl_super with + | Some (c,_) -> + begin try + let cf' = PMap.find cf.cf_name c.cl_fields in + add_relation cf'.cf_name_pos (Overridden,cf.cf_pos) + with Not_found -> + loop c + end + | _ -> + () + in + loop c + ) c.cl_overrides + in + let rec find_real_constructor c = match c.cl_constructor,c.cl_super with + (* The pos comparison might be a bit weak, not sure... *) + | Some cf,_ when not (Meta.has Meta.CompilerGenerated cf.cf_meta) && c.cl_pos <> cf.cf_pos -> cf + | _,Some(c,_) -> find_real_constructor c + | _,None -> raise Not_found + in + let var_decl v = declare (SKVariable v) v.v_pos in + let patch_string_pos p s = { p with pmin = p.pmax - String.length s } in + let patch_string_pos_front p s = { p with pmax = p.pmin + String.length s } in + let field_reference cf p = + add_relation cf.cf_name_pos (Referenced,patch_string_pos p cf.cf_name) + in + let collect_references c e = + let rec loop e = match e.eexpr with + | TField(e1,fa) -> + (* Check if the sub-expression is actually shorter than the whole one. This should + detect cases where it was automatically generated. *) + if e1.epos.pmin = e.epos.pmin && e1.epos.pmax <> e.epos.pmax then + loop e1; + begin match fa with + | FStatic(_,cf) | FInstance(_,_,cf) | FClosure(_,cf) -> + field_reference cf e.epos + | FAnon cf -> + declare (SKField cf) cf.cf_name_pos; + field_reference cf e.epos + | FEnum(_,ef) -> + add_relation ef.ef_name_pos (Referenced,patch_string_pos e.epos ef.ef_name) + | FDynamic _ -> + () + end + | TTypeExpr mt -> + let tinfos = t_infos mt in + add_relation tinfos.mt_name_pos (Referenced,patch_string_pos e.epos (snd tinfos.mt_path)) + | TNew(c,_,el) -> + List.iter loop el; + (try add_relation (find_real_constructor c).cf_name_pos (Referenced,e.epos) with Not_found -> ()); + | TCall({eexpr = TConst TSuper},el) -> + List.iter loop el; + begin match c.cl_super with + | Some(c,_) -> (try add_relation (find_real_constructor c).cf_name_pos (Referenced,e.epos) with Not_found -> ()) + | None -> () + end + | TVar(v,eo) -> + Option.may loop eo; + var_decl v; + | TFor(v,e1,e2) -> + var_decl v; + loop e1; + loop e2; + | TFunction tf -> + List.iter (fun (v,_) -> var_decl v) tf.tf_args; + loop tf.tf_expr; + | TLocal v when e.epos.pmax - e.epos.pmin = String.length v.v_name -> + add_relation v.v_pos (Referenced,e.epos) + | _ -> + Type.iter loop e + in + loop e + in + List.iter (function + | TClassDecl c -> + declare (if c.cl_interface then (SKInterface c) else (SKClass c)) c.cl_name_pos; + List.iter (fun (c',_) -> add_relation c'.cl_name_pos ((if c.cl_interface then Extended else Implemented),c.cl_name_pos)) c.cl_implements; + begin match c.cl_super with + | None -> () + | Some (c',_) -> add_relation c'.cl_name_pos (Extended,c.cl_name_pos); + end; + collect_overrides c; + let field cf = + if cf.cf_pos.pmin > c.cl_name_pos.pmin then declare (SKField cf) cf.cf_name_pos; + let _ = follow cf.cf_type in + match cf.cf_expr with None -> () | Some e -> collect_references c e + in + Option.may field c.cl_constructor; + List.iter field c.cl_ordered_fields; + List.iter field c.cl_ordered_statics; + | TEnumDecl en -> + declare (SKEnum en) en.e_name_pos; + PMap.iter (fun _ ef -> declare (SKEnumField ef) ef.ef_name_pos) en.e_constrs + | _ -> + () + ) ctx.com.types; + let explore_type_hint p t = match follow t with + | TInst(c,_) -> add_relation c.cl_name_pos (Referenced,(patch_string_pos_front p (snd c.cl_path))) + | _ -> () + in + Hashtbl.iter (fun p t -> + explore_type_hint p t + ) ctx.com.shared.shared_display_information.type_hints; + let l = List.fold_left (fun acc (_,cfi,_,cfo) -> match cfo with + | Some cf -> if List.mem_assoc cf.cf_name_pos acc then acc else (cf.cf_name_pos,cfi.cf_name_pos) :: acc + | None -> acc + ) [] ctx.com.display_information.interface_field_implementations in + List.iter (fun (p,p') -> add_relation p' (Implemented,p)) l; + let deal_with_imports paths = + let check_subtype m s p = + try + let mt = List.find (fun mt -> snd (t_infos mt).mt_path = s) m.m_types in + add_relation (t_infos mt).mt_name_pos (Referenced,p); + Some mt + with Not_found -> + None + in + let check_module path p = + let m = ctx.g.do_load_module ctx path p in + m + in + let check_field c s p = + let cf = PMap.find s c.cl_statics in + add_relation cf.cf_name_pos (Referenced,p) + in + let check_subtype_field m ssub psub sfield pfield = match check_subtype m ssub psub with + | Some (TClassDecl c) -> check_field c sfield pfield + | _ -> () + in + PMap.iter (fun p (_,path) -> + match ImportHandling.convert_import_to_something_usable { p with pmin = p.pmax - 1; pmax = p.pmax - 1 } path,List.rev path with + | (IDKSubType(sl,s1,s2),_),(_,psubtype) :: (_,pmodule) :: _ -> + let m = check_module (sl,s1) pmodule in + (*ignore(check_subtype m s1 pmodule);*) + ignore(check_subtype m s2 psubtype) + | (IDKModuleField(sl,s1,s2),_),(_,pfield) :: (_,pmodule) :: _ -> + let m = check_module (sl,s1) pmodule in + check_subtype_field m s1 pmodule s2 pfield + | (IDKSubTypeField(sl,s1,s2,s3),_),(_,pfield) :: (_,psubtype) :: (_,pmodule) :: _ -> + let m = check_module (sl,s1) pmodule in + check_subtype_field m s2 psubtype s3 pfield + | (IDKModule(sl,s),_),(_,pmodule) :: _ -> + let m = check_module (sl,s) pmodule in + ignore(check_subtype m s pmodule); + | _ -> + () + ) paths + in + if false then deal_with_imports ctx.com.shared.shared_display_information.import_positions; + symbols,relations +end + +let explore_class_paths ctx class_paths recusive f_pack f_module f_type = + let rec loop dir pack = + try + let entries = Sys.readdir dir in + Array.iter (fun file -> + match file with + | "." | ".." -> + () + | _ when Sys.is_directory (dir ^ file) && file.[0] >= 'a' && file.[0] <= 'z' -> + f_pack file; + if recusive then loop (dir ^ file ^ "/") (file :: pack) + | _ -> + let l = String.length file in + if l > 3 && String.sub file (l - 3) 3 = ".hx" then begin + try + let name = String.sub file 0 (l - 3) in + let path = (List.rev pack,name) in + let md = ctx.g.do_load_module ctx path null_pos in + f_module md; + List.iter (fun mt -> f_type mt) md.m_types + with _ -> + () + end + ) entries; + with Sys_error _ -> + () + in + List.iter (fun dir -> loop dir []) class_paths + +module ToplevelCollector = struct + open IdentifierType + + let run ctx only_types = + let acc = DynArray.create () in + + if not only_types then begin + (* locals *) + PMap.iter (fun _ v -> + if not (is_gen_local v) then + DynArray.add acc (ITLocal v) + ) ctx.locals; + + (* member vars *) + if ctx.curfun <> FunStatic then begin + let rec loop c = + List.iter (fun cf -> + DynArray.add acc (ITMember(ctx.curclass,cf)) + ) c.cl_ordered_fields; + match c.cl_super with + | None -> + () + | Some (csup,tl) -> + loop csup; (* TODO: type parameters *) + in + loop ctx.curclass; + (* TODO: local using? *) + end; + + (* statics *) + List.iter (fun cf -> + DynArray.add acc (ITStatic(ctx.curclass,cf)) + ) ctx.curclass.cl_ordered_statics; + + (* enum constructors *) + let rec enum_ctors t = + match t with + | TAbstractDecl ({a_impl = Some c} as a) when Meta.has Meta.Enum a.a_meta -> + List.iter (fun cf -> + if (Meta.has Meta.Enum cf.cf_meta) then DynArray.add acc (ITEnumAbstract(a,cf)); + ) c.cl_ordered_statics + | TClassDecl _ | TAbstractDecl _ -> + () + | TTypeDecl t -> + begin match follow t.t_type with + | TEnum (e,_) -> enum_ctors (TEnumDecl e) + | _ -> () + end + | TEnumDecl e -> + PMap.iter (fun _ ef -> + DynArray.add acc (ITEnum(e,ef)) + ) e.e_constrs; + in + List.iter enum_ctors ctx.m.curmod.m_types; + List.iter enum_ctors (List.map fst ctx.m.module_types); + + (* imported globals *) + PMap.iter (fun _ (mt,s,_) -> + try + let t = match resolve_typedef mt with + | TClassDecl c -> (PMap.find s c.cl_statics).cf_type + | TEnumDecl en -> (PMap.find s en.e_constrs).ef_type + | TAbstractDecl {a_impl = Some c} -> (PMap.find s c.cl_statics).cf_type + | _ -> raise Not_found + in + DynArray.add acc (ITGlobal(mt,s,t)) + with Not_found -> + () + ) ctx.m.module_globals; + + (* literals *) + DynArray.add acc (ITLiteral "null"); + DynArray.add acc (ITLiteral "true"); + DynArray.add acc (ITLiteral "false"); + end; + + let module_types = ref [] in + + let add_type mt = + match mt with + | TClassDecl {cl_kind = KAbstractImpl _} -> () + | _ -> + let path = (t_infos mt).mt_path in + if not (List.exists (fun mt2 -> (t_infos mt2).mt_path = path) !module_types) then begin + (match mt with + | TClassDecl c | TAbstractDecl { a_impl = Some c } when Meta.has Meta.CoreApi c.cl_meta -> + !merge_core_doc_ref ctx c + | _ -> ()); + module_types := mt :: !module_types + end + in + + (* module types *) + List.iter add_type ctx.m.curmod.m_types; + + (* module imports *) + List.iter add_type (List.map fst ctx.m.module_types); + + (* module using *) + List.iter (fun (c,_) -> + add_type (TClassDecl c) + ) ctx.m.module_using; + + (* TODO: wildcard packages. How? *) + + (* packages and toplevel types *) + let class_paths = ctx.com.class_path in + let class_paths = List.filter (fun s -> s <> "") class_paths in + + let packages = ref [] in + let add_package pack = + try + begin match PMap.find pack ctx.com.package_rules with + | Forbidden -> + () + | _ -> + raise Not_found + end + with Not_found -> + if not (List.mem pack !packages) then packages := pack :: !packages + in + + explore_class_paths ctx class_paths false add_package (fun _ -> ()) add_type; + + List.iter (fun pack -> + DynArray.add acc (ITPackage pack) + ) !packages; + + List.iter (fun mt -> + DynArray.add acc (ITType mt) + ) !module_types; + DynArray.to_list acc + + let handle_unresolved_identifier ctx i p only_types = + let l = run ctx only_types in + let cl = List.map (fun it -> + let s = IdentifierType.get_name it in + (s,it),StringError.levenshtein i s + ) l in + let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in + let cl = StringError.filter_similar (fun (s,_) r -> r > 0 && r <= (min (String.length s) (String.length i)) / 3) cl in + ctx.com.display_information.unresolved_identifiers <- (i,p,cl) :: ctx.com.display_information.unresolved_identifiers +end \ No newline at end of file diff --git a/src/display/displayOutput.ml b/src/display/displayOutput.ml new file mode 100644 index 00000000..778b9b4e --- /dev/null +++ b/src/display/displayOutput.ml @@ -0,0 +1,803 @@ +open Globals +open Common +open Common.DisplayMode +open Type +open Display +open Typecore + +(* Old XML stuff *) + +let htmlescape s = + let s = String.concat "&" (ExtString.String.nsplit s "&") in + let s = String.concat "<" (ExtString.String.nsplit s "<") in + let s = String.concat ">" (ExtString.String.nsplit s ">") in + let s = String.concat """ (ExtString.String.nsplit s "\"") in + s + +let get_timer_fields start_time = + let tot = ref 0. in + Hashtbl.iter (fun _ t -> tot := !tot +. t.total) Common.htimers; + let fields = [("@TOTAL", Printf.sprintf "%.3fs" (get_time() -. start_time))] in + if !tot > 0. then + Hashtbl.fold (fun _ t acc -> + ((String.concat "." t.id),(Printf.sprintf "%.3fs (%.0f%%)" t.total (t.total *. 100. /. !tot))) :: acc + ) Common.htimers fields + else + fields + +let print_keywords () = + let b = Buffer.create 0 in + Buffer.add_string b "\n"; + Hashtbl.iter (fun k _ -> + Buffer.add_string b (Printf.sprintf "\n" k) + ) Lexer.keywords; + Buffer.add_string b "\n"; + Buffer.contents b + +let print_fields fields = + let b = Buffer.create 0 in + Buffer.add_string b "\n"; + List.iter (fun (n,k,d) -> + let s_kind, t = match k with + | FKVar t -> "var", s_type (print_context()) t + | FKMethod t -> "method", s_type (print_context()) t + | FKType t -> "type", s_type (print_context()) t + | FKPackage -> "package", "" + | FKModule -> "type", "" + | FKMetadata -> "metadata", "" + | FKTimer s -> "timer", s + in + Buffer.add_string b (Printf.sprintf "%s%s\n" n s_kind (htmlescape t) (htmlescape d)) + ) (List.sort (fun (a,ak,_) (b,bk,_) -> compare (display_field_kind_index ak,a) (display_field_kind_index bk,b)) fields); + Buffer.add_string b "\n"; + Buffer.contents b + +let maybe_print_doc d = + Option.map_default (fun s -> Printf.sprintf " d=\"%s\"" (htmlescape s)) "" d + +let print_toplevel il = + let b = Buffer.create 0 in + Buffer.add_string b "\n"; + let s_type t = htmlescape (s_type (print_context()) t) in + let s_doc d = maybe_print_doc d in + List.iter (fun id -> match id with + | IdentifierType.ITLocal v -> + Buffer.add_string b (Printf.sprintf "%s\n" (s_type v.v_type) v.v_name); + | IdentifierType.ITMember(c,cf) -> + Buffer.add_string b (Printf.sprintf "%s\n" (s_type cf.cf_type) (s_doc cf.cf_doc) cf.cf_name); + | IdentifierType.ITStatic(c,cf) -> + Buffer.add_string b (Printf.sprintf "%s\n" (s_type cf.cf_type) (s_doc cf.cf_doc) cf.cf_name); + | IdentifierType.ITEnum(en,ef) -> + Buffer.add_string b (Printf.sprintf "%s\n" (s_type ef.ef_type) (s_doc ef.ef_doc) ef.ef_name); + | IdentifierType.ITEnumAbstract(a,cf) -> + Buffer.add_string b (Printf.sprintf "%s\n" (s_type cf.cf_type) (s_doc cf.cf_doc) cf.cf_name); + | IdentifierType.ITGlobal(mt,s,t) -> + Buffer.add_string b (Printf.sprintf "%s\n" (s_type_path (t_infos mt).mt_path) (s_type t) s); + | IdentifierType.ITType(mt) -> + let infos = t_infos mt in + Buffer.add_string b (Printf.sprintf "%s\n" (s_type_path infos.mt_path) (s_doc infos.mt_doc) (snd infos.mt_path)); + | IdentifierType.ITPackage s -> + Buffer.add_string b (Printf.sprintf "%s\n" s) + | IdentifierType.ITLiteral s -> + Buffer.add_string b (Printf.sprintf "%s\n" s) + | IdentifierType.ITTimer s -> + Buffer.add_string b (Printf.sprintf "%s\n" s) + ) il; + Buffer.add_string b ""; + Buffer.contents b + +let print_type t p doc = + let b = Buffer.create 0 in + if p = null_pos then + Buffer.add_string b "\n"; + Buffer.add_string b (htmlescape (s_type (print_context()) t)); + Buffer.add_string b "\n\n"; + Buffer.contents b + +let print_signatures tl = + let b = Buffer.create 0 in + List.iter (fun (t,doc) -> + Buffer.add_string b " Buffer.add_string b (Printf.sprintf " d=\"%s\"" (htmlescape s))) doc; + Buffer.add_string b ">\n"; + Buffer.add_string b (htmlescape (s_type (print_context()) (follow t))); + Buffer.add_string b "\n\n"; + ) tl; + Buffer.contents b + +let print_positions pl = + let b = Buffer.create 0 in + let error_printer file line = Printf.sprintf "%s:%d:" (Path.get_real_path file) line in + Buffer.add_string b "\n"; + List.iter (fun p -> + let epos = Lexer.get_error_pos error_printer p in + Buffer.add_string b ""; + Buffer.add_string b epos; + Buffer.add_string b "\n"; + ) pl; + Buffer.add_string b ""; + Buffer.contents b + +let display_memory com = + let verbose = com.verbose in + let print = print_endline in + let fmt_size sz = + if sz < 1024 then + string_of_int sz ^ " B" + else if sz < 1024*1024 then + string_of_int (sz asr 10) ^ " KB" + else + Printf.sprintf "%.1f MB" ((float_of_int sz) /. (1024.*.1024.)) + in + let size v = + fmt_size (mem_size v) + in + Gc.full_major(); + Gc.compact(); + let mem = Gc.stat() in + print ("Total Allocated Memory " ^ fmt_size (mem.Gc.heap_words * (Sys.word_size asr 8))); + print ("Free Memory " ^ fmt_size (mem.Gc.free_words * (Sys.word_size asr 8))); + (match CompilationServer.get() with + | None -> + print "No cache found"; + | Some {CompilationServer.cache = c} -> + print ("Total cache size " ^ size c); + print (" haxelib " ^ size c.CompilationServer.c_haxelib); + print (" parsed ast " ^ size c.CompilationServer.c_files ^ " (" ^ string_of_int (Hashtbl.length c.CompilationServer.c_files) ^ " files stored)"); + print (" typed modules " ^ size c.CompilationServer.c_modules ^ " (" ^ string_of_int (Hashtbl.length c.CompilationServer.c_modules) ^ " modules stored)"); + let rec scan_module_deps m h = + if Hashtbl.mem h m.m_id then + () + else begin + Hashtbl.add h m.m_id m; + PMap.iter (fun _ m -> scan_module_deps m h) m.m_extra.m_deps + end + in + let all_modules = Hashtbl.fold (fun _ m acc -> PMap.add m.m_id m acc) c.CompilationServer.c_modules PMap.empty in + let modules = Hashtbl.fold (fun (path,key) m acc -> + let mdeps = Hashtbl.create 0 in + scan_module_deps m mdeps; + let deps = ref [] in + let out = ref all_modules in + Hashtbl.iter (fun _ md -> + out := PMap.remove md.m_id !out; + if m == md then () else begin + deps := Obj.repr md :: !deps; + List.iter (fun t -> + match t with + | TClassDecl c -> + deps := Obj.repr c :: !deps; + List.iter (fun f -> deps := Obj.repr f :: !deps) c.cl_ordered_statics; + List.iter (fun f -> deps := Obj.repr f :: !deps) c.cl_ordered_fields; + | TEnumDecl e -> + deps := Obj.repr e :: !deps; + List.iter (fun n -> deps := Obj.repr (PMap.find n e.e_constrs) :: !deps) e.e_names; + | TTypeDecl t -> deps := Obj.repr t :: !deps; + | TAbstractDecl a -> deps := Obj.repr a :: !deps; + ) md.m_types; + end + ) mdeps; + let chk = Obj.repr Common.memory_marker :: PMap.fold (fun m acc -> Obj.repr m :: acc) !out [] in + let inf = Objsize.objsize m !deps chk in + (m,Objsize.size_with_headers inf, (inf.Objsize.reached,!deps,!out)) :: acc + ) c.CompilationServer.c_modules [] in + let cur_key = ref "" and tcount = ref 0 and mcount = ref 0 in + List.iter (fun (m,size,(reached,deps,out)) -> + let key = m.m_extra.m_sign in + if key <> !cur_key then begin + print (Printf.sprintf (" --- CONFIG %s ----------------------------") (Digest.to_hex key)); + cur_key := key; + end; + let sign md = + if md.m_extra.m_sign = key then "" else "(" ^ (try Digest.to_hex md.m_extra.m_sign with _ -> "???" ^ md.m_extra.m_sign) ^ ")" + in + print (Printf.sprintf " %s : %s" (s_type_path m.m_path) (fmt_size size)); + (if reached then try + incr mcount; + let lcount = ref 0 in + let leak l = + incr lcount; + incr tcount; + print (Printf.sprintf " LEAK %s" l); + if !lcount >= 3 && !tcount >= 100 && not verbose then begin + print (Printf.sprintf " ..."); + raise Exit; + end; + in + if (Objsize.objsize m deps [Obj.repr Common.memory_marker]).Objsize.reached then leak "common"; + PMap.iter (fun _ md -> + if (Objsize.objsize m deps [Obj.repr md]).Objsize.reached then leak (s_type_path md.m_path ^ sign md); + ) out; + with Exit -> + ()); + if verbose then begin + print (Printf.sprintf " %d total deps" (List.length deps)); + PMap.iter (fun _ md -> + print (Printf.sprintf " dep %s%s" (s_type_path md.m_path) (sign md)); + ) m.m_extra.m_deps; + end; + flush stdout + ) (List.sort (fun (m1,s1,_) (m2,s2,_) -> + let k1 = m1.m_extra.m_sign and k2 = m2.m_extra.m_sign in + if k1 = k2 then s1 - s2 else if k1 > k2 then 1 else -1 + ) modules); + if !mcount > 0 then print ("*** " ^ string_of_int !mcount ^ " modules have leaks !"); + print "Cache dump complete") + +module TypePathHandler = struct + let unique l = + let rec _unique = function + | [] -> [] + | x1 :: x2 :: l when x1 = x2 -> _unique (x2 :: l) + | x :: l -> x :: _unique l + in + _unique (List.sort compare l) + + let rec read_type_path com p = + let classes = ref [] in + let packages = ref [] in + let p = (match p with + | x :: l -> + (try + match PMap.find x com.package_rules with + | Directory d -> d :: l + | Remap s -> s :: l + | _ -> p + with + Not_found -> p) + | _ -> p + ) in + List.iter (fun path -> + let dir = path ^ String.concat "/" p in + let r = (try Sys.readdir dir with _ -> [||]) in + Array.iter (fun f -> + if (try (Unix.stat (dir ^ "/" ^ f)).Unix.st_kind = Unix.S_DIR with _ -> false) then begin + if f.[0] >= 'a' && f.[0] <= 'z' then begin + if p = ["."] then + match read_type_path com [f] with + | [] , [] -> () + | _ -> + try + match PMap.find f com.package_rules with + | Forbidden -> () + | Remap f -> packages := f :: !packages + | Directory _ -> raise Not_found + with Not_found -> + packages := f :: !packages + else + packages := f :: !packages + end; + end else if file_extension f = "hx" then begin + let c = Filename.chop_extension f in + if String.length c < 2 || String.sub c (String.length c - 2) 2 <> "__" then classes := c :: !classes; + end; + ) r; + ) com.class_path; + List.iter (fun (_,_,extract) -> + Hashtbl.iter (fun (path,name) _ -> + if path = p then classes := name :: !classes else + let rec loop p1 p2 = + match p1, p2 with + | [], _ -> () + | x :: _, [] -> packages := x :: !packages + | a :: p1, b :: p2 -> if a = b then loop p1 p2 + in + loop path p + ) (extract()); + ) com.swf_libs; + List.iter (fun (path,std,close,all_files,lookup) -> + List.iter (fun (path, name) -> + if path = p then classes := name :: !classes else + let rec loop p1 p2 = + match p1, p2 with + | [], _ -> () + | x :: _, [] -> packages := x :: !packages + | a :: p1, b :: p2 -> if a = b then loop p1 p2 + in + loop path p + ) (all_files()) + ) com.java_libs; + List.iter (fun (path,std,all_files,lookup) -> + List.iter (fun (path, name) -> + if path = p then classes := name :: !classes else + let rec loop p1 p2 = + match p1, p2 with + | [], _ -> () + | x :: _, [] -> packages := x :: !packages + | a :: p1, b :: p2 -> if a = b then loop p1 p2 + in + loop path p + ) (all_files()) + ) com.net_libs; + unique !packages, unique !classes + + (** raise field completion listing packages and modules in a given package *) + let complete_type_path com p = + let packs, modules = read_type_path com p in + if packs = [] && modules = [] then + (abort ("No classes found in " ^ String.concat "." p) null_pos) + else + let packs = List.map (fun n -> n,Display.FKPackage,"") packs in + let modules = List.map (fun n -> n,Display.FKModule,"") modules in + Some (packs @ modules) + + (** raise field completion listing module sub-types and static fields *) + let complete_type_path_inner com p c cur_package is_import = + try + let sl_pack,s_module = match List.rev p with + | s :: sl when s.[0] >= 'A' && s.[0] <= 'Z' -> List.rev sl,s + | _ -> p,c + in + let ctx = Typer.create com in + let rec lookup p = + try + Typeload.load_module ctx (p,s_module) null_pos + with e -> + if cur_package then + match List.rev p with + | [] -> raise e + | _ :: p -> lookup (List.rev p) + else + raise e + in + let m = lookup sl_pack in + let statics = ref None in + let public_types = List.filter (fun t -> + let tinfos = t_infos t in + let is_module_type = snd tinfos.mt_path = c in + if is_import && is_module_type then begin match t with + | TClassDecl c -> + ignore(c.cl_build()); + statics := Some c.cl_ordered_statics + | _ -> () + end; + not tinfos.mt_private + ) m.m_types in + let types = + if c <> s_module then + [] + else + List.map (fun t -> + let infos = t_infos t in + (snd infos.mt_path), Display.FKModule, (Option.default "" infos.mt_doc) + ) public_types + in + let make_field_doc cf = + cf.cf_name, + (match cf.cf_kind with Method _ -> Display.FKMethod cf.cf_type | Var _ -> Display.FKVar cf.cf_type), + (match cf.cf_doc with Some s -> s | None -> "") + in + let fields = match !statics with + | None -> types + | Some cfl -> types @ (List.map make_field_doc (List.filter (fun cf -> cf.cf_public) cfl)) + in + Some fields + with _ -> + abort ("Could not load module " ^ (s_type_path (p,c))) null_pos +end + +(* New JSON stuff *) + +open Json + +(** return a range JSON structure for given position + positions are 0-based and the result object looks like this: + { + start: {line: 0, character: 0}, + end: {line: 3, character: 42}, + } +*) +let pos_to_json_range p = + if p.pmin = -1 then + JNull + else + let l1, p1, l2, p2 = Lexer.get_pos_coords p in + let to_json l c = JObject [("line", JInt (l - 1)); ("character", JInt c)] in + JObject [ + ("start", to_json l1 p1); + ("end", to_json l2 p2); + ] + +let print_signature tl display_arg = + let st = s_type (print_context()) in + let s_arg (n,o,t) = Printf.sprintf "%s%s:%s" (if o then "?" else "") n (st t) in + let s_fun args ret = Printf.sprintf "(%s):%s" (String.concat ", " (List.map s_arg args)) (st ret) in + let siginf = List.map (fun (t,doc) -> + let label = match follow t with TFun(args,ret) -> s_fun args ret | _ -> st t in + let parameters = match follow t with + | TFun(args,_) -> + List.map (fun arg -> + let label = s_arg arg in + JObject [ + "label",JString label + ] + ) args + | _ -> [] + in + let js = [ + "label",JString label; + "parameters",JArray parameters; + ] in + JObject (match doc with None -> js | Some s -> ("documentation",JString s) :: js) + ) tl in + let jo = JObject [ + "signatures",JArray siginf; + "activeParameter",JInt display_arg; + "activeSignature",JInt 0; + ] in + let b = Buffer.create 0 in + write_json (Buffer.add_string b) jo; + Buffer.contents b + +module StatisticsPrinter = struct + open Statistics + + let relation_to_string = function + | Implemented -> "implementers" + | Extended -> "subclasses" + | Overridden -> "overrides" + | Referenced -> "references" + + let symbol_to_string = function + | SKClass _ -> "class type" + | SKInterface _ -> "interface type" + | SKEnum _ -> "enum type" + | SKField _ -> "class field" + | SKEnumField _ -> "enum field" + | SKVariable _ -> "variable" + + let print_statistics (kinds,relations) = + let files = Hashtbl.create 0 in + Hashtbl.iter (fun p rl -> + let file = Path.get_real_path p.pfile in + try + Hashtbl.replace files file ((p,rl) :: Hashtbl.find files file) + with Not_found -> + Hashtbl.add files file [p,rl] + ) relations; + let ja = Hashtbl.fold (fun file relations acc -> + let l = List.map (fun (p,rl) -> + let h = Hashtbl.create 0 in + List.iter (fun (r,p) -> + let s = relation_to_string r in + let jo = JObject [ + "range",pos_to_json_range p; + "file",JString (Path.get_real_path p.pfile); + ] in + try Hashtbl.replace h s (jo :: Hashtbl.find h s) + with Not_found -> Hashtbl.add h s [jo] + ) rl; + let l = Hashtbl.fold (fun s js acc -> (s,JArray js) :: acc) h [] in + let l = ("range",pos_to_json_range p) :: l in + let l = try ("kind",JString (symbol_to_string (Hashtbl.find kinds p))) :: l with Not_found -> l in + JObject l + ) relations in + (JObject [ + "file",JString file; + "statistics",JArray l + ]) :: acc + ) files [] in + let b = Buffer.create 0 in + write_json (Buffer.add_string b) (JArray ja); + Buffer.contents b +end + +module DiagnosticsPrinter = struct + open Diagnostics + open Diagnostics.DiagnosticsKind + open DisplayTypes + + type t = DiagnosticsKind.t * pos + + module UnresolvedIdentifierSuggestion = struct + type t = + | UISImport + | UISTypo + + let to_int = function + | UISImport -> 0 + | UISTypo -> 1 + end + + let print_diagnostics ctx global = + let com = ctx.com in + let diag = Hashtbl.create 0 in + let add dk p sev args = + let file = Path.get_real_path p.pfile in + let diag = try + Hashtbl.find diag file + with Not_found -> + let d = DynArray.create() in + Hashtbl.add diag file d; + d + in + DynArray.add diag (dk,p,sev,args) + in + let add dk p sev args = + if global || is_display_file p.pfile then add dk p sev args + in + let find_type i = + let types = ref [] in + Hashtbl.iter (fun _ m -> + List.iter (fun mt -> + let s_full_type_path (p,s) n = s_type_path (p,s) ^ if (s <> n) then "." ^ n else "" in + let tinfos = t_infos mt in + if snd tinfos.mt_path = i then + types := JObject [ + "kind",JInt (UnresolvedIdentifierSuggestion.to_int UnresolvedIdentifierSuggestion.UISImport); + "name",JString (s_full_type_path m.m_path i) + ] :: !types + ) m.m_types; + ) ctx.g.modules; + !types + in + List.iter (fun (s,p,suggestions) -> + let suggestions = List.map (fun (s,_) -> + JObject [ + "kind",JInt (UnresolvedIdentifierSuggestion.to_int UnresolvedIdentifierSuggestion.UISTypo); + "name",JString s + ] + ) suggestions in + add DKUnresolvedIdentifier p DiagnosticsSeverity.Error (JArray (suggestions @ (find_type s))); + ) com.display_information.unresolved_identifiers; + PMap.iter (fun p (r,_) -> + if not !r then add DKUnusedImport p DiagnosticsSeverity.Warning (JArray []) + ) com.shared.shared_display_information.import_positions; + List.iter (fun (s,p,sev) -> + add DKCompilerError p sev (JString s) + ) com.shared.shared_display_information.diagnostics_messages; + List.iter (fun (s,p,prange) -> + add DKRemovableCode p DiagnosticsSeverity.Warning (JObject ["description",JString s;"range",if prange = null_pos then JNull else pos_to_json_range prange]) + ) com.shared.shared_display_information.removable_code; + let jl = Hashtbl.fold (fun file diag acc -> + let jl = DynArray.fold_left (fun acc (dk,p,sev,jargs) -> + (JObject [ + "kind",JInt (to_int dk); + "severity",JInt (DiagnosticsSeverity.to_int sev); + "range",pos_to_json_range p; + "args",jargs + ]) :: acc + ) [] diag in + (JObject [ + "file",JString file; + "diagnostics",JArray jl + ]) :: acc + ) diag [] in + let js = JArray jl in + let b = Buffer.create 0 in + write_json (Buffer.add_string b) js; + Buffer.contents b +end + +module ModuleSymbolsPrinter = struct + open DisplayTypes.SymbolKind + open DisplayTypes.SymbolInformation + + let print_module_symbols com symbols filter = + let regex = Option.map Str.regexp_case_fold filter in + let reported = Hashtbl.create 0 in + let add si = + if Hashtbl.mem reported si.pos then false + else begin + let b = match regex with + | None -> true + | Some regex -> (try ignore(Str.search_forward regex si.name 0); true with Not_found -> false) + in + Hashtbl.replace reported si.pos true; + b + end + in + let ja = List.fold_left (fun acc (file,l) -> + let jl = ExtList.List.filter_map (fun si -> + if not (add si) then + None + else begin + let l = + ("name",JString si.name) :: + ("kind",JInt (to_int si.kind)) :: + ("range", pos_to_json_range si.pos) :: + (match si.container_name with None -> [] | Some s -> ["containerName",JString s]) + in + Some (JObject l) + end + ) (DynArray.to_list l) in + if jl = [] then + acc + else + (JObject [ + "file",JString file; + "symbols",JArray jl + ]) :: acc + ) [] symbols in + let js = JArray ja in + let b = Buffer.create 0 in + write_json (Buffer.add_string b) js; + Buffer.contents b +end + +(* Mode processing *) + +exception Completion of string + +let unquote v = + let len = String.length v in + if len > 0 && v.[0] = '"' && v.[len - 1] = '"' then String.sub v 1 (len - 2) else v + +let handle_display_argument com file_pos pre_compilation did_something = + match file_pos with + | "classes" -> + pre_compilation := (fun() -> raise (Parser.TypePath (["."],None,true))) :: !pre_compilation; + | "keywords" -> + raise (Completion (print_keywords ())) + | "memory" -> + did_something := true; + (try display_memory com with e -> prerr_endline (Printexc.get_backtrace ())); + | "diagnostics" -> + Common.define com Define.NoCOpt; + com.display <- DisplayMode.create (DMDiagnostics true); + Common.display_default := DMDiagnostics true; + | _ -> + let file, pos = try ExtString.String.split file_pos "@" with _ -> failwith ("Invalid format: " ^ file_pos) in + let file = unquote file in + let pos, smode = try ExtString.String.split pos "@" with _ -> pos,"" in + let mode = match smode with + | "position" -> + Common.define com Define.NoCOpt; + DMPosition + | "usage" -> + Common.define com Define.NoCOpt; + DMUsage false + (*| "rename" -> + Common.define com Define.NoCOpt; + DMUsage true*) + | "package" -> + DMPackage + | "type" -> + Common.define com Define.NoCOpt; + DMType + | "toplevel" -> + Common.define com Define.NoCOpt; + DMToplevel + | "module-symbols" -> + Common.define com Define.NoCOpt; + DMModuleSymbols None; + | "diagnostics" -> + Common.define com Define.NoCOpt; + DMDiagnostics false; + | "statistics" -> + Common.define com Define.NoCOpt; + DMStatistics + | "signature" -> + DMSignature + | "" -> + DMField + | _ -> + let smode,arg = try ExtString.String.split smode "@" with _ -> pos,"" in + match smode with + | "resolve" -> + DMResolve arg + | "workspace-symbols" -> + Common.define com Define.NoCOpt; + DMModuleSymbols (Some arg) + | _ -> + DMField + in + let pos = try int_of_string pos with _ -> failwith ("Invalid format: " ^ pos) in + com.display <- DisplayMode.create mode; + Common.display_default := mode; + Common.define_value com Define.Display (if smode <> "" then smode else "1"); + Parser.use_doc := true; + Parser.resume_display := { + pfile = Path.unique_full_path file; + pmin = pos; + pmax = pos; + } + +let process_display_file com classes = + let get_module_path_from_file_path com spath = + let rec loop = function + | [] -> None + | cp :: l -> + let cp = (if cp = "" then "./" else cp) in + let c = Path.add_trailing_slash (Path.get_real_path cp) in + let clen = String.length c in + if clen < String.length spath && String.sub spath 0 clen = c then begin + let path = String.sub spath clen (String.length spath - clen) in + (try + let path = Path.parse_type_path path in + (match loop l with + | Some x as r when String.length (s_type_path x) < String.length (s_type_path path) -> r + | _ -> Some path) + with _ -> loop l) + end else + loop l + in + loop com.class_path + in + match com.display.dms_display_file_policy with + | DFPNo -> + () + | dfp -> + if dfp = DFPOnly then begin + classes := []; + com.main_class <- None; + end; + let real = Path.get_real_path (!Parser.resume_display).pfile in + (match get_module_path_from_file_path com real with + | Some path -> + if com.display.dms_kind = DMPackage then raise (DisplayPackage (fst path)); + classes := path :: !classes + | None -> + if not (Sys.file_exists real) then failwith "Display file does not exist"; + (match List.rev (ExtString.String.nsplit real Path.path_sep) with + | file :: _ when file.[0] >= 'a' && file.[1] <= 'z' -> failwith ("Display file '" ^ file ^ "' should not start with a lowercase letter") + | _ -> ()); + failwith "Display file was not found in class path" + ); + Common.log com ("Display file : " ^ real); + Common.log com ("Classes found : [" ^ (String.concat "," (List.map s_type_path !classes)) ^ "]") + +let process_global_display_mode com tctx = match com.display.dms_kind with + | DMUsage with_definition -> + let symbols,relations = Statistics.collect_statistics tctx in + let rec loop acc relations = match relations with + | (Statistics.Referenced,p) :: relations -> loop (p :: acc) relations + | _ :: relations -> loop acc relations + | [] -> acc + in + let usages = Hashtbl.fold (fun p sym acc -> + if Statistics.is_usage_symbol sym then begin + let acc = if with_definition then p :: acc else acc in + (try loop acc (Hashtbl.find relations p) + with Not_found -> acc) + end else + acc + ) symbols [] in + let usages = List.sort (fun p1 p2 -> + let c = compare p1.pfile p2.pfile in + if c <> 0 then c else compare p1.pmin p2.pmin + ) usages in + raise (DisplayPosition usages) + | DMDiagnostics global -> + Diagnostics.prepare com global; + raise (Diagnostics (DiagnosticsPrinter.print_diagnostics tctx global)) + | DMStatistics -> + let stats = Statistics.collect_statistics tctx in + raise (Statistics (StatisticsPrinter.print_statistics stats)) + | DMModuleSymbols filter -> + let symbols = com.shared.shared_display_information.document_symbols in + let symbols = match CompilationServer.get() with + | None -> symbols + | Some cs -> + let l = CompilationServer.get_context_files cs ((get_signature com) :: (match com.get_macros() with None -> [] | Some com -> [get_signature com])) in + List.fold_left (fun acc (file,data) -> + print_endline (Printf.sprintf "%s %b" file (is_display_file file)); + if (filter <> None || is_display_file file) then + (file,DocumentSymbols.collect_module_symbols data) :: acc + else + acc + ) symbols l + in + raise (ModuleSymbols(ModuleSymbolsPrinter.print_module_symbols com symbols filter)) + | _ -> () + +let find_doc t = + let doc = match follow t with + | TAnon an -> + begin match !(an.a_status) with + | Statics c -> c.cl_doc + | EnumStatics en -> en.e_doc + | AbstractStatics a -> a.a_doc + | _ -> None + end + | _ -> + None + in + doc \ No newline at end of file diff --git a/src/display/displayTypes.ml b/src/display/displayTypes.ml new file mode 100644 index 00000000..83c13cf4 --- /dev/null +++ b/src/display/displayTypes.ml @@ -0,0 +1,59 @@ +open Ast + +module SymbolKind = struct + type t = + | Class + | Interface + | Enum + | Typedef + | Abstract + | Field + | Property + | Method + | Constructor + | Function + | Variable + + let to_int = function + | Class -> 1 + | Interface -> 2 + | Enum -> 3 + | Typedef -> 4 + | Abstract -> 5 + | Field -> 6 + | Property -> 7 + | Method -> 8 + | Constructor -> 9 + | Function -> 10 + | Variable -> 11 +end + +module SymbolInformation = struct + type t = { + name : string; + kind : SymbolKind.t; + pos : Globals.pos; + container_name : string option; + } + + let make name kind pos container_name = { + name = name; + kind = kind; + pos = pos; + container_name = container_name; + } +end + +module DiagnosticsSeverity = struct + type t = + | Error + | Warning + | Information + | Hint + + let to_int = function + | Error -> 1 + | Warning -> 2 + | Information -> 3 + | Hint -> 4 +end \ No newline at end of file diff --git a/src/generators/codegen.ml b/src/generators/codegen.ml new file mode 100644 index 00000000..1e9b0843 --- /dev/null +++ b/src/generators/codegen.ml @@ -0,0 +1,889 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Ast +open Type +open Common +open Error +open Globals + +(* -------------------------------------------------------------------------- *) +(* TOOLS *) + +(* Collection of functions that return expressions *) +module ExprBuilder = struct + let make_static_this c p = + let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in + mk (TTypeExpr (TClassDecl c)) ta p + + let make_static_field c cf p = + let e_this = make_static_this c p in + mk (TField(e_this,FStatic(c,cf))) cf.cf_type p + + let make_int com i p = + mk (TConst (TInt (Int32.of_int i))) com.basic.tint p + + let make_float com f p = + mk (TConst (TFloat f)) com.basic.tfloat p + + let make_bool com b p = + mk (TConst(TBool b)) com.basic.tbool p + + let make_string com s p = + mk (TConst (TString s)) com.basic.tstring p + + let make_null t p = + mk (TConst TNull) t p + + let make_local v p = + mk (TLocal v) v.v_type p + + let make_const_texpr com ct p = match ct with + | TString s -> mk (TConst (TString s)) com.basic.tstring p + | TInt i -> mk (TConst (TInt i)) com.basic.tint p + | TFloat f -> mk (TConst (TFloat f)) com.basic.tfloat p + | TBool b -> mk (TConst (TBool b)) com.basic.tbool p + | TNull -> mk (TConst TNull) (com.basic.tnull (mk_mono())) p + | _ -> error "Unsupported constant" p +end + +let field e name t p = + mk (TField (e,try quick_field e.etype name with Not_found -> assert false)) t p + +let fcall e name el ret p = + let ft = tfun (List.map (fun e -> e.etype) el) ret in + mk (TCall (field e name ft p,el)) ret p + +let mk_parent e = + mk (TParenthesis e) e.etype e.epos + +let binop op a b t p = + mk (TBinop (op,a,b)) t p + +let index com e index t p = + mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) com.basic.tint p)) t p + +let maybe_cast e t = + try + type_eq EqDoNotFollowNull e.etype t; + e + with + Unify_error _ -> mk (TCast(e,None)) t e.epos + +let type_constant com c p = + let t = com.basic in + match c with + | Int s -> + if String.length s > 10 && String.sub s 0 2 = "0x" then error "Invalid hexadecimal integer" p; + (try mk (TConst (TInt (Int32.of_string s))) t.tint p + with _ -> mk (TConst (TFloat s)) t.tfloat p) + | Float f -> mk (TConst (TFloat f)) t.tfloat p + | String s -> mk (TConst (TString s)) t.tstring p + | Ident "true" -> mk (TConst (TBool true)) t.tbool p + | Ident "false" -> mk (TConst (TBool false)) t.tbool p + | Ident "null" -> mk (TConst TNull) (t.tnull (mk_mono())) p + | Ident t -> error ("Invalid constant : " ^ t) p + | Regexp _ -> error "Invalid constant" p + +let rec type_constant_value com (e,p) = + match e with + | EConst c -> + type_constant com c p + | EParenthesis e -> + type_constant_value com e + | EObjectDecl el -> + mk (TObjectDecl (List.map (fun ((n,_),e) -> n, type_constant_value com e) el)) (TAnon { a_fields = PMap.empty; a_status = ref Closed }) p + | EArrayDecl el -> + mk (TArrayDecl (List.map (type_constant_value com) el)) (com.basic.tarray t_dynamic) p + | _ -> + error "Constant value expected" p + +let rec has_properties c = + List.exists (fun f -> + match f.cf_kind with + | Var { v_read = AccCall } -> true + | Var { v_write = AccCall } -> true + | _ when Meta.has Meta.Accessor f.cf_meta -> true + | _ -> false + ) c.cl_ordered_fields || (match c.cl_super with Some (c,_) -> has_properties c | _ -> false) + +let get_properties fields = + List.fold_left (fun acc f -> + if Meta.has Meta.Accessor f.cf_meta then + (f.cf_name, f.cf_name) :: acc + else + let acc = (match f.cf_kind with + | Var { v_read = AccCall } -> ("get_" ^ f.cf_name , "get_" ^ f.cf_name) :: acc + | _ -> acc) in + match f.cf_kind with + | Var { v_write = AccCall } -> ("set_" ^ f.cf_name , "set_" ^ f.cf_name) :: acc + | _ -> acc + ) [] fields + +let add_property_field com c = + let p = c.cl_pos in + let props = get_properties (c.cl_ordered_statics @ c.cl_ordered_fields) in + match props with + | [] -> () + | _ -> + let fields,values = List.fold_left (fun (fields,values) (n,v) -> + let cf = mk_field n com.basic.tstring p null_pos in + PMap.add n cf fields,(n, ExprBuilder.make_string com v p) :: values + ) (PMap.empty,[]) props in + let t = mk_anon fields in + let e = mk (TObjectDecl values) t p in + let cf = mk_field "__properties__" t p null_pos in + cf.cf_expr <- Some e; + c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics; + c.cl_ordered_statics <- cf :: c.cl_ordered_statics + +let escape_res_name name allow_dirs = + ExtString.String.replace_chars (fun chr -> + if (chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') || (chr >= '0' && chr <= '9') || chr = '_' || chr = '.' then + Char.escaped chr + else if chr = '/' && allow_dirs then + "/" + else + "-x" ^ (string_of_int (Char.code chr))) name + +(* -------------------------------------------------------------------------- *) +(* BUILD META DATA OBJECT *) + +let build_metadata com t = + let api = com.basic in + let p, meta, fields, statics = (match t with + | TClassDecl c -> + let fields = List.map (fun f -> f.cf_name,f.cf_meta) (c.cl_ordered_fields @ (match c.cl_constructor with None -> [] | Some f -> [{ f with cf_name = "_" }])) in + let statics = List.map (fun f -> f.cf_name,f.cf_meta) c.cl_ordered_statics in + (c.cl_pos, ["",c.cl_meta],fields,statics) + | TEnumDecl e -> + (e.e_pos, ["",e.e_meta],List.map (fun n -> n, (PMap.find n e.e_constrs).ef_meta) e.e_names, []) + | TTypeDecl t -> + (t.t_pos, ["",t.t_meta],(match follow t.t_type with TAnon a -> PMap.fold (fun f acc -> (f.cf_name,f.cf_meta) :: acc) a.a_fields [] | _ -> []),[]) + | TAbstractDecl a -> + (a.a_pos, ["",a.a_meta],[],[]) + ) in + let filter l = + let l = List.map (fun (n,ml) -> n, ExtList.List.filter_map (fun (m,el,p) -> match m with Meta.Custom s when String.length s > 0 && s.[0] <> ':' -> Some (s,el,p) | _ -> None) ml) l in + List.filter (fun (_,ml) -> ml <> []) l + in + let meta, fields, statics = filter meta, filter fields, filter statics in + let make_meta_field ml = + let h = Hashtbl.create 0 in + mk (TObjectDecl (List.map (fun (f,el,p) -> + if Hashtbl.mem h f then error ("Duplicate metadata '" ^ f ^ "'") p; + Hashtbl.add h f (); + f, mk (match el with [] -> TConst TNull | _ -> TArrayDecl (List.map (type_constant_value com) el)) (api.tarray t_dynamic) p + ) ml)) t_dynamic p + in + let make_meta l = + mk (TObjectDecl (List.map (fun (f,ml) -> f,make_meta_field ml) l)) t_dynamic p + in + if meta = [] && fields = [] && statics = [] then + None + else + let meta_obj = [] in + let meta_obj = (if fields = [] then meta_obj else ("fields",make_meta fields) :: meta_obj) in + let meta_obj = (if statics = [] then meta_obj else ("statics",make_meta statics) :: meta_obj) in + let meta_obj = (try ("obj", make_meta_field (List.assoc "" meta)) :: meta_obj with Not_found -> meta_obj) in + Some (mk (TObjectDecl meta_obj) t_dynamic p) + +let update_cache_dependencies t = + let rec check_t m t = match t with + | TInst(c,tl) -> + add_dependency m c.cl_module; + List.iter (check_t m) tl; + | TEnum(en,tl) -> + add_dependency m en.e_module; + List.iter (check_t m) tl; + | TType(t,tl) -> + add_dependency m t.t_module; + List.iter (check_t m) tl; + | TAbstract(a,tl) -> + add_dependency m a.a_module; + List.iter (check_t m) tl; + | TFun(targs,tret) -> + List.iter (fun (_,_,t) -> check_t m t) targs; + check_t m tret; + | TAnon an -> + PMap.iter (fun _ cf -> check_field m cf) an.a_fields + | TMono r -> + (match !r with + | Some t -> check_t m t + | _ -> ()) + | TLazy f -> + check_t m (!f()) + | TDynamic t -> + if t == t_dynamic then + () + else + check_t m t + and check_field m cf = + check_t m cf.cf_type + in + match t with + | TClassDecl c -> + List.iter (check_field c.cl_module) c.cl_ordered_statics; + List.iter (check_field c.cl_module) c.cl_ordered_fields; + (match c.cl_constructor with None -> () | Some cf -> check_field c.cl_module cf); + | _ -> + () + +(* -------------------------------------------------------------------------- *) +(* STACK MANAGEMENT EMULATION *) + +type stack_context = { + stack_var : string; + stack_exc_var : string; + stack_pos_var : string; + stack_pos : pos; + stack_expr : texpr; + stack_pop : texpr; + stack_save_pos : texpr; + stack_restore : texpr list; + stack_push : tclass -> string -> texpr; + stack_return : texpr -> texpr; +} + +let stack_context_init com stack_var exc_var pos_var tmp_var use_add p = + let t = com.basic in + let st = t.tarray t.tstring in + let stack_var = alloc_var stack_var st p in + let exc_var = alloc_var exc_var st p in + let pos_var = alloc_var pos_var t.tint p in + let stack_e = mk (TLocal stack_var) st p in + let exc_e = mk (TLocal exc_var) st p in + let stack_pop = fcall stack_e "pop" [] t.tstring p in + let stack_push c m = + fcall stack_e "push" [ + if use_add then + binop OpAdd (ExprBuilder.make_string com (s_type_path c.cl_path ^ "::") p) (ExprBuilder.make_string com m p) t.tstring p + else + ExprBuilder.make_string com (s_type_path c.cl_path ^ "::" ^ m) p + ] t.tvoid p + in + let stack_return e = + let tmp = alloc_var tmp_var e.etype e.epos in + mk (TBlock [ + mk (TVar (tmp, Some e)) t.tvoid e.epos; + stack_pop; + mk (TReturn (Some (mk (TLocal tmp) e.etype e.epos))) e.etype e.epos + ]) e.etype e.epos + in + { + stack_var = stack_var.v_name; + stack_exc_var = exc_var.v_name; + stack_pos_var = pos_var.v_name; + stack_pos = p; + stack_expr = stack_e; + stack_pop = stack_pop; + stack_save_pos = mk (TVar (pos_var, Some (field stack_e "length" t.tint p))) t.tvoid p; + stack_push = stack_push; + stack_return = stack_return; + stack_restore = [ + binop OpAssign exc_e (mk (TArrayDecl []) st p) st p; + mk (TWhile ( + mk_parent (binop OpGte (field stack_e "length" t.tint p) (mk (TLocal pos_var) t.tint p) t.tbool p), + fcall exc_e "unshift" [fcall stack_e "pop" [] t.tstring p] t.tvoid p, + NormalWhile + )) t.tvoid p; + fcall stack_e "push" [index com exc_e 0 t.tstring p] t.tvoid p + ]; + } + +let stack_init com use_add = + stack_context_init com "$s" "$e" "$spos" "$tmp" use_add null_pos + +let rec stack_block_loop ctx e = + match e.eexpr with + | TFunction _ -> + e + | TReturn None | TReturn (Some { eexpr = TConst _ }) | TReturn (Some { eexpr = TLocal _ }) -> + mk (TBlock [ + ctx.stack_pop; + e; + ]) e.etype e.epos + | TReturn (Some e) -> + ctx.stack_return (stack_block_loop ctx e) + | TTry (v,cases) -> + let v = stack_block_loop ctx v in + let cases = List.map (fun (v,e) -> + let e = stack_block_loop ctx e in + let e = (match (mk_block e).eexpr with + | TBlock l -> mk (TBlock (ctx.stack_restore @ l)) e.etype e.epos + | _ -> assert false + ) in + v , e + ) cases in + mk (TTry (v,cases)) e.etype e.epos + | _ -> + map_expr (stack_block_loop ctx) e + +let stack_block ctx c m e = + match (mk_block e).eexpr with + | TBlock l -> + mk (TBlock ( + ctx.stack_push c m :: + ctx.stack_save_pos :: + List.map (stack_block_loop ctx) l + @ [ctx.stack_pop] + )) e.etype e.epos + | _ -> + assert false + +(* -------------------------------------------------------------------------- *) +(* FIX OVERRIDES *) + +(* + on some platforms which doesn't support type parameters, we must have the + exact same type for overriden/implemented function as the original one +*) + +let rec find_field com c f = + try + (match c.cl_super with + | None -> + raise Not_found + | Some ( {cl_path = (["cpp"],"FastIterator")}, _ ) -> + raise Not_found (* This is a strongly typed 'extern' and the usual rules don't apply *) + | Some (c,_) -> + find_field com c f) + with Not_found -> try + if com.platform = Cpp || com.platform = Hl then (* uses delegation for interfaces *) + raise Not_found; + let rec loop = function + | [] -> + raise Not_found + | (c,_) :: l -> + try + find_field com c f + with + Not_found -> loop l + in + loop c.cl_implements + with Not_found -> + let f = PMap.find f.cf_name c.cl_fields in + (match f.cf_kind with Var { v_read = AccRequire _ } -> raise Not_found | _ -> ()); + f + +let fix_override com c f fd = + let f2 = (try Some (find_field com c f) with Not_found -> None) in + match f2,fd with + | Some (f2), Some(fd) -> + let targs, tret = (match follow f2.cf_type with TFun (args,ret) -> args, ret | _ -> assert false) in + let changed_args = ref [] in + let prefix = "_tmp_" in + let nargs = List.map2 (fun ((v,ct) as cur) (_,_,t2) -> + try + type_eq EqStrict (monomorphs c.cl_params (monomorphs f.cf_params v.v_type)) t2; + (* Flash generates type parameters with a single constraint as that constraint type, so we + have to detect this case and change the variable (issue #2712). *) + begin match follow v.v_type with + | TInst({cl_kind = KTypeParameter [tc]} as cp,_) when com.platform = Flash -> + if List.mem_assoc (snd cp.cl_path) c.cl_params then raise (Unify_error []) + | _ -> + () + end; + cur + with Unify_error _ -> + let v2 = alloc_var (prefix ^ v.v_name) t2 v.v_pos in + changed_args := (v,v2) :: !changed_args; + v2,ct + ) fd.tf_args targs in + let fd2 = { + tf_args = nargs; + tf_type = tret; + tf_expr = (match List.rev !changed_args with + | [] -> fd.tf_expr + | args -> + let e = fd.tf_expr in + let el = (match e.eexpr with TBlock el -> el | _ -> [e]) in + let p = (match el with [] -> e.epos | e :: _ -> e.epos) in + let el_v = List.map (fun (v,v2) -> + mk (TVar (v,Some (mk (TCast (mk (TLocal v2) v2.v_type p,None)) v.v_type p))) com.basic.tvoid p + ) args in + { e with eexpr = TBlock (el_v @ el) } + ); + } in + (* as3 does not allow wider visibility, so the base method has to be made public *) + if Common.defined com Define.As3 && f.cf_public then f2.cf_public <- true; + let targs = List.map (fun(v,c) -> (v.v_name, Option.is_some c, v.v_type)) nargs in + let fde = (match f.cf_expr with None -> assert false | Some e -> e) in + f.cf_expr <- Some { fde with eexpr = TFunction fd2 }; + f.cf_type <- TFun(targs,tret); + | Some(f2), None when c.cl_interface -> + let targs, tret = (match follow f2.cf_type with TFun (args,ret) -> args, ret | _ -> assert false) in + f.cf_type <- TFun(targs,tret) + | _ -> + () + +let fix_overrides com t = + match t with + | TClassDecl c -> + (* overrides can be removed from interfaces *) + if c.cl_interface then + c.cl_ordered_fields <- List.filter (fun f -> + try + if find_field com c f == f then raise Not_found; + c.cl_fields <- PMap.remove f.cf_name c.cl_fields; + false; + with Not_found -> + true + ) c.cl_ordered_fields; + List.iter (fun f -> + match f.cf_expr, f.cf_kind with + | Some { eexpr = TFunction fd }, Method (MethNormal | MethInline) -> + fix_override com c f (Some fd) + | None, Method (MethNormal | MethInline) when c.cl_interface -> + fix_override com c f None + | _ -> + () + ) c.cl_ordered_fields + | _ -> + () + +(* + PHP does not allow abstract classes extending other abstract classes to override any fields, so these duplicates + must be removed from the child interface +*) +let fix_abstract_inheritance com t = + match t with + | TClassDecl c when c.cl_interface -> + c.cl_ordered_fields <- List.filter (fun f -> + let b = try (find_field com c f) == f + with Not_found -> false in + if not b then c.cl_fields <- PMap.remove f.cf_name c.cl_fields; + b; + ) c.cl_ordered_fields + | _ -> () + +(* -------------------------------------------------------------------------- *) +(* MISC FEATURES *) + +let rec is_volatile t = + match t with + | TMono r -> + (match !r with + | Some t -> is_volatile t + | _ -> false) + | TLazy f -> + is_volatile (!f()) + | TType (t,tl) -> + (match t.t_path with + | _ -> is_volatile (apply_params t.t_params tl t.t_type)) + | _ -> + false + +let set_default ctx a c p = + let t = a.v_type in + let ve = mk (TLocal a) t p in + let cond = TBinop (OpEq,ve,mk (TConst TNull) t p) in + mk (TIf (mk_parent (mk cond ctx.basic.tbool p), mk (TBinop (OpAssign,ve,mk (TConst c) t p)) t p,None)) ctx.basic.tvoid p + +let bytes_serialize data = + let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" in + let tbl = Array.init (String.length b64) (fun i -> String.get b64 i) in + Base64.str_encode ~tbl data + +(* + Tells if the constructor might be called without any issue whatever its parameters +*) +let rec constructor_side_effects e = + match e.eexpr with + | TBinop (op,_,_) when op <> OpAssign -> + true + | TField (_,FEnum _) -> + false + | TUnop _ | TArray _ | TField _ | TEnumParameter _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TReturn _ | TThrow _ -> + true + | TBinop _ | TTry _ | TIf _ | TBlock _ | TVar _ + | TFunction _ | TArrayDecl _ | TObjectDecl _ + | TParenthesis _ | TTypeExpr _ | TLocal _ | TMeta _ + | TConst _ | TContinue | TBreak | TCast _ -> + try + Type.iter (fun e -> if constructor_side_effects e then raise Exit) e; + false; + with Exit -> + true + +module Dump = struct + let make_valid_filename s = + let r = Str.regexp "[^A-Za-z0-9_\\-\\.,]" in + Str.global_substitute r (fun s -> "_") s + + let rec create_file ext acc = function + | [] -> assert false + | d :: [] -> + let d = make_valid_filename d in + let maxlen = 200 - String.length ext in + let d = if String.length d > maxlen then String.sub d 0 maxlen else d in + let ch = open_out (String.concat "/" (List.rev (d :: acc)) ^ ext) in + ch + | d :: l -> + let dir = String.concat "/" (List.rev (d :: acc)) in + if not (Sys.file_exists dir) then Unix.mkdir dir 0o755; + create_file ext (d :: acc) l + + (* + Make a dump of the full typed AST of all types + *) + let create_dumpfile acc l = + let ch = create_file ".dump" acc l in + let buf = Buffer.create 0 in + buf, (fun () -> + output_string ch (Buffer.contents buf); + close_out ch) + + let create_dumpfile_from_path com path = + let buf,close = create_dumpfile [] ("dump" :: (platform_name com.platform) :: fst path @ [snd path]) in + buf,close + + let dump_types com s_expr = + let s_type = s_type (Type.print_context()) in + let params tl = match tl with [] -> "" | l -> Printf.sprintf "<%s>" (String.concat "," (List.map (fun (n,t) -> n ^ " : " ^ s_type t) l)) in + List.iter (fun mt -> + let path = Type.t_path mt in + let buf,close = create_dumpfile_from_path com path in + let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in + let s_metas ml tabs = + let args el = + match el with + | [] -> "" + | el -> Printf.sprintf "(%s)" (String.concat ", " (List.map (fun e -> Ast.s_expr e) el)) in + match ml with + | [] -> "" + | ml -> String.concat " " (List.map (fun me -> match me with (m,el,_) -> "@" ^ Meta.to_string m ^ args el) ml) ^ "\n" ^ tabs in + (match mt with + | Type.TClassDecl c -> + let s_cf_expr f = + match f.cf_expr with + | None -> "" + | Some e -> Printf.sprintf "%s" (s_expr s_type e) in + let is_inline_var v : bool = v = Var { v_read = AccInline; v_write = AccNever } in + let rec print_field stat f = + print "\n\t%s%s%s%s%s %s%s" + (s_metas f.cf_meta "\t") + (if (f.cf_public && not (c.cl_extern || c.cl_interface)) then "public " else "") + (if stat then "static " else "") + (match f.cf_kind with + | Var v when (is_inline_var f.cf_kind) -> "inline " + | Var v -> "" + | Method m -> + match m with + | MethNormal -> "" + | MethDynamic -> "dynamic " + | MethInline -> "inline " + | MethMacro -> "macro ") + (match f.cf_kind with Var v -> "var" | Method m -> "function") + (f.cf_name ^ match f.cf_kind with + | Var { v_read = AccNormal; v_write = AccNormal } -> "" + | Var v when (is_inline_var f.cf_kind) -> "" + | Var v -> "(" ^ s_access true v.v_read ^ "," ^ s_access false v.v_write ^ ")" + | _ -> "") + (params f.cf_params); + (match f.cf_kind with + | Var v -> print ":%s%s;" (s_type f.cf_type) + (match f.cf_expr with + | None -> "" + | Some e -> " = " ^ (s_cf_expr f)); + | Method m -> if (c.cl_extern || c.cl_interface) then ( + match f.cf_type with + | TFun(al,t) -> print "(%s):%s;" (String.concat ", " ( + List.map (fun (n,o,t) -> n ^ ":" ^ (s_type t)) al)) + (s_type t) + | _ -> () + ) else print "%s" (s_cf_expr f)); + print "\n"; + List.iter (fun f -> print_field stat f) f.cf_overloads + in + print "%s%s%s%s %s%s" (s_metas c.cl_meta "") (if c.cl_private then "private " else "") (if c.cl_extern then "extern " else "") (if c.cl_interface then "interface" else "class") (s_type_path path) (params c.cl_params); + (match c.cl_super with None -> () | Some (c,pl) -> print " extends %s" (s_type (TInst (c,pl)))); + List.iter (fun (c,pl) -> print " implements %s" (s_type (TInst (c,pl)))) c.cl_implements; + (match c.cl_dynamic with None -> () | Some t -> print " implements Dynamic<%s>" (s_type t)); + (match c.cl_array_access with None -> () | Some t -> print " implements ArrayAccess<%s>" (s_type t)); + print " {\n"; + (match c.cl_constructor with + | None -> () + | Some f -> print_field false f); + List.iter (print_field false) c.cl_ordered_fields; + List.iter (print_field true) c.cl_ordered_statics; + (match c.cl_init with + | None -> () + | Some e -> + print "\n\tstatic function __init__() "; + print "%s" (s_expr s_type e); + print "\n"); + print "}"; + | Type.TEnumDecl e -> + print "%s%s%senum %s%s {\n" (s_metas e.e_meta "") (if e.e_private then "private " else "") (if e.e_extern then "extern " else "") (s_type_path path) (params e.e_params); + List.iter (fun n -> + let f = PMap.find n e.e_constrs in + print "\t%s%s;\n" f.ef_name ( + match f.ef_type with + | TFun (al,t) -> Printf.sprintf "(%s)" (String.concat ", " + (List.map (fun (n,o,t) -> (if o then "?" else "") ^ n ^ ":" ^ (s_type t)) al)) + | _ -> "") + ) e.e_names; + print "}" + | Type.TTypeDecl t -> + print "%s%stypedef %s%s = %s" (s_metas t.t_meta "") (if t.t_private then "private " else "") (s_type_path path) (params t.t_params) (s_type t.t_type); + | Type.TAbstractDecl a -> + print "%s%sabstract %s%s%s%s {}" (s_metas a.a_meta "") (if a.a_private then "private " else "") (s_type_path path) (params a.a_params) + (String.concat " " (List.map (fun t -> " from " ^ s_type t) a.a_from)) + (String.concat " " (List.map (fun t -> " to " ^ s_type t) a.a_to)); + ); + close(); + ) com.types + + let dump_record com = + List.iter (fun mt -> + let buf,close = create_dumpfile_from_path com (t_path mt) in + let s = match mt with + | TClassDecl c -> Printer.s_tclass "" c + | TEnumDecl en -> Printer.s_tenum "" en + | TTypeDecl t -> Printer.s_tdef "" t + | TAbstractDecl a -> Printer.s_tabstract "" a + in + Buffer.add_string buf s; + close(); + ) com.types + + let dump_types com = + match Common.defined_value_safe com Define.Dump with + | "pretty" -> dump_types com (Type.s_expr_pretty false "\t" true) + | "legacy" -> dump_types com Type.s_expr + | "record" -> dump_record com + | _ -> dump_types com (Type.s_expr_ast (not (Common.defined com Define.DumpIgnoreVarIds)) "\t") + + let dump_dependencies ?(target_override=None) com = + let target_name = match target_override with + | None -> platform_name com.platform + | Some s -> s + in + let buf,close = create_dumpfile [] ["dump";target_name;".dependencies"] in + let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in + let dep = Hashtbl.create 0 in + List.iter (fun m -> + print "%s:\n" m.m_extra.m_file; + PMap.iter (fun _ m2 -> + print "\t%s\n" (m2.m_extra.m_file); + let l = try Hashtbl.find dep m2.m_extra.m_file with Not_found -> [] in + Hashtbl.replace dep m2.m_extra.m_file (m :: l) + ) m.m_extra.m_deps; + ) com.Common.modules; + close(); + let buf,close = create_dumpfile [] ["dump";target_name;".dependants"] in + let print fmt = Printf.kprintf (fun s -> Buffer.add_string buf s) fmt in + Hashtbl.iter (fun n ml -> + print "%s:\n" n; + List.iter (fun m -> + print "\t%s\n" (m.m_extra.m_file); + ) ml; + ) dep; + close() +end + +(* + Build a default safe-cast expression : + { var $t = ; if( Std.is($t,) ) $t else throw "Class cast error"; } +*) +let default_cast ?(vtmp="$t") com e texpr t p = + let api = com.basic in + let mk_texpr = function + | TClassDecl c -> TAnon { a_fields = PMap.empty; a_status = ref (Statics c) } + | TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) } + | TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) } + | TTypeDecl _ -> assert false + in + let vtmp = alloc_var vtmp e.etype e.epos in + let var = mk (TVar (vtmp,Some e)) api.tvoid p in + let vexpr = mk (TLocal vtmp) e.etype p in + let texpr = mk (TTypeExpr texpr) (mk_texpr texpr) p in + let std = (try List.find (fun t -> t_path t = ([],"Std")) com.types with Not_found -> assert false) in + let fis = (try + let c = (match std with TClassDecl c -> c | _ -> assert false) in + FStatic (c, PMap.find "is" c.cl_statics) + with Not_found -> + assert false + ) in + let std = mk (TTypeExpr std) (mk_texpr std) p in + let is = mk (TField (std,fis)) (tfun [t_dynamic;t_dynamic] api.tbool) p in + let is = mk (TCall (is,[vexpr;texpr])) api.tbool p in + let exc = mk (TThrow (mk (TConst (TString "Class cast error")) api.tstring p)) t p in + let check = mk (TIf (mk_parent is,mk (TCast (vexpr,None)) t p,Some exc)) t p in + mk (TBlock [var;check;vexpr]) t p + +module UnificationCallback = struct + let tf_stack = ref [] + + let check_call_params f el tl = + let rec loop acc el tl = match el,tl with + | e :: el, (n,_,t) :: tl -> + loop ((f e t) :: acc) el tl + | [], [] -> + acc + | [],_ -> + acc + | e :: el, [] -> + loop (e :: acc) el [] + in + List.rev (loop [] el tl) + + let check_call f el t = match follow t with + | TFun(args,_) -> + check_call_params f el args + | _ -> + List.map (fun e -> f e t_dynamic) el + + let rec run ff e = + let f e t = + if not (type_iseq e.etype t) then + ff e t + else + e + in + let check e = match e.eexpr with + | TBinop((OpAssign | OpAssignOp _),e1,e2) -> + assert false; (* this trigger #4347, to be fixed before enabling + let e2 = f e2 e1.etype in + {e with eexpr = TBinop(op,e1,e2)} *) + | TVar(v,Some ev) -> + let eo = Some (f ev v.v_type) in + { e with eexpr = TVar(v,eo) } + | TCall(e1,el) -> + let el = check_call f el e1.etype in + {e with eexpr = TCall(e1,el)} + | TNew(c,tl,el) -> + begin try + let tcf,_ = get_constructor (fun cf -> apply_params c.cl_params tl cf.cf_type) c in + let el = check_call f el tcf in + {e with eexpr = TNew(c,tl,el)} + with Not_found -> + e + end + | TArrayDecl el -> + begin match follow e.etype with + | TInst({cl_path=[],"Array"},[t]) -> {e with eexpr = TArrayDecl(List.map (fun e -> f e t) el)} + | _ -> e + end + | TObjectDecl fl -> + begin match follow e.etype with + | TAnon an -> + let fl = List.map (fun (n,e) -> + let e = try + let t = (PMap.find n an.a_fields).cf_type in + f e t + with Not_found -> + e + in + n,e + ) fl in + { e with eexpr = TObjectDecl fl } + | _ -> e + end + | TReturn (Some e1) -> + begin match !tf_stack with + | tf :: _ -> { e with eexpr = TReturn (Some (f e1 tf.tf_type))} + | _ -> e + end + | _ -> + e + in + match e.eexpr with + | TFunction tf -> + tf_stack := tf :: !tf_stack; + let etf = {e with eexpr = TFunction({tf with tf_expr = run f tf.tf_expr})} in + tf_stack := List.tl !tf_stack; + etf + | _ -> + check (Type.map_expr (run ff) e) +end;; + +let interpolate_code com code tl f_string f_expr p = + let exprs = Array.of_list tl in + let i = ref 0 in + let err msg = + let pos = { p with pmin = p.pmin + !i } in + com.error msg pos + in + let regex = Str.regexp "[{}]" in + let rec loop m = match m with + | [] -> + () + | Str.Text txt :: tl -> + i := !i + String.length txt; + f_string txt; + loop tl + | Str.Delim a :: Str.Delim b :: tl when a = b -> + i := !i + 2; + f_string a; + loop tl + | Str.Delim "{" :: Str.Text n :: Str.Delim "}" :: tl -> + begin try + let expr = Array.get exprs (int_of_string n) in + f_expr expr; + with + | Failure "int_of_string" -> + f_string ("{" ^ n ^ "}"); + | Invalid_argument _ -> + err ("Out-of-bounds special parameter: " ^ n) + end; + i := !i + 2 + String.length n; + loop tl + | Str.Delim x :: tl -> + f_string x; + incr i; + loop tl + in + loop (Str.full_split regex code) + +let map_source_header com f = + match Common.defined_value_safe com Define.SourceHeader with + | "" -> () + | s -> f s + + +(* Static extensions for classes *) +module ExtClass = struct + + let add_cl_init c e = match c.cl_init with + | None -> c.cl_init <- Some e + | Some e' -> c.cl_init <- Some (concat e' e) + + let add_static_init c cf e p = + let ethis = ExprBuilder.make_static_this c p in + let ef1 = mk (TField(ethis,FStatic(c,cf))) cf.cf_type p in + let e_assign = mk (TBinop(OpAssign,ef1,e)) e.etype p in + add_cl_init c e_assign +end + +let for_remap com v e1 e2 p = + let v' = alloc_var v.v_name e1.etype e1.epos in + let ev' = mk (TLocal v') e1.etype e1.epos in + let t1 = (Abstract.follow_with_abstracts e1.etype) in + let ehasnext = mk (TField(ev',quick_field t1 "hasNext")) (tfun [] com.basic.tbool) e1.epos in + let ehasnext = mk (TCall(ehasnext,[])) com.basic.tbool ehasnext.epos in + let enext = mk (TField(ev',quick_field t1 "next")) (tfun [] v.v_type) e1.epos in + let enext = mk (TCall(enext,[])) v.v_type e1.epos in + let eassign = mk (TVar(v,Some enext)) com.basic.tvoid p in + let ebody = Type.concat eassign e2 in + mk (TBlock [ + mk (TVar (v',Some e1)) com.basic.tvoid e1.epos; + mk (TWhile((mk (TParenthesis ehasnext) ehasnext.etype ehasnext.epos),ebody,NormalWhile)) com.basic.tvoid e1.epos; + ]) com.basic.tvoid p \ No newline at end of file diff --git a/genas3.ml b/src/generators/genas3.ml similarity index 90% rename from genas3.ml rename to src/generators/genas3.ml index 5f999bd5..7b717f23 100644 --- a/genas3.ml +++ b/src/generators/genas3.ml @@ -1,23 +1,20 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Type @@ -62,6 +59,20 @@ let is_special_compare e1 e2 = | TInst ({ cl_path = ["flash"],"NativeXml" } as c,_) , _ | _ , TInst ({ cl_path = ["flash"],"NativeXml" } as c,_) -> Some c | _ -> None +let is_fixed_override cf t = + let is_type_parameter c = match c.cl_kind with + | KTypeParameter _ -> true + | _ -> false + in + match follow cf.cf_type,follow t with + | TFun(_,r1),TFun(_,r2) -> + begin match follow r1,follow r2 with + | TInst(c1,_),TInst(c2,_) when c1 != c2 && not (is_type_parameter c1) && not (is_type_parameter c2) -> true + | _ -> false + end + | _ -> + false + let protect name = match name with | "Error" | "Namespace" -> "_" ^ name @@ -98,7 +109,7 @@ let s_path ctx stat path p = let name = protect name in let packs = (try Hashtbl.find ctx.imports name with Not_found -> []) in if not (List.mem pack packs) then Hashtbl.replace ctx.imports name (pack :: packs); - Ast.s_type_path (pack,name) + Globals.s_type_path (pack,name) let reserved = let h = Hashtbl.create 0 in @@ -135,7 +146,7 @@ let valid_as3_ident s = let anon_field s = let s = s_ident s in - if not (valid_as3_ident s) then "\"" ^ s ^ "\"" else s + if not (valid_as3_ident s) then "\"" ^ (Ast.s_escape s) ^ "\"" else s let rec create_dir acc = function | [] -> () @@ -179,7 +190,7 @@ let close ctx = Hashtbl.iter (fun name paths -> List.iter (fun pack -> let path = pack, name in - if path <> ctx.path then output_string ctx.ch ("\timport " ^ Ast.s_type_path path ^ ";\n"); + if path <> ctx.path then output_string ctx.ch ("\timport " ^ Globals.s_type_path path ^ ";\n"); ) paths ) ctx.imports; output_string ctx.ch (Buffer.contents ctx.buf); @@ -192,7 +203,7 @@ let gen_local ctx l = let spr ctx s = Buffer.add_string ctx.buf s let print ctx = Printf.kprintf (fun s -> Buffer.add_string ctx.buf s) -let unsupported p = error "This expression cannot be generated to AS3" p +let unsupported p = abort "This expression cannot be generated to AS3" p let newline ctx = let rec loop p = @@ -236,7 +247,7 @@ let rec type_str ctx t p = match t with | TEnum _ | TInst _ when List.memq t ctx.local_types -> "*" - | TAbstract (a,pl) when not (Ast.Meta.has Ast.Meta.CoreType a.a_meta) -> + | TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) -> type_str ctx (Abstract.get_underlying_type a pl) p | TAbstract (a,_) -> (match a.a_path with @@ -253,7 +264,7 @@ let rec type_str ctx t p = | _ -> let rec loop = function | [] -> "Object" - | (Ast.Meta.FakeEnum,[Ast.EConst (Ast.Ident n),_],_) :: _ -> + | (Meta.FakeEnum,[Ast.EConst (Ast.Ident n),_],_) :: _ -> (match n with | "Int" -> "int" | "UInt" -> "uint" @@ -270,7 +281,7 @@ let rec type_str ctx t p = | TInst (c,_) -> (match c.cl_kind with | KNormal | KGeneric | KGenericInstance _ | KAbstractImpl _ -> s_path ctx false c.cl_path p - | KTypeParameter _ | KExtension _ | KExpr _ | KMacroType | KGenericBuild _ -> "*") + | KTypeParameter _ | KExpr _ | KMacroType | KGenericBuild _ -> "*") | TFun _ -> "Function" | TMono r -> @@ -287,10 +298,7 @@ let rec type_str ctx t p = | TAbstract ({ a_path = [],"UInt" },_) | TAbstract ({ a_path = [],"Int" },_) | TAbstract ({ a_path = [],"Float" },_) - | TAbstract ({ a_path = [],"Bool" },_) - | TInst ({ cl_path = [],"Int" },_) - | TInst ({ cl_path = [],"Float" },_) - | TEnum ({ e_path = [],"Bool" },_) -> "*" + | TAbstract ({ a_path = [],"Bool" },_) -> "*" | _ -> type_str ctx t p) | _ -> assert false); | _ -> type_str ctx (apply_params t.t_params args t.t_type) p) @@ -389,8 +397,8 @@ let gen_function_header ctx name f params p = print ctx "function%s(" (match name with None -> "" | Some (n,meta) -> let rec loop = function | [] -> n - | (Ast.Meta.Getter,[Ast.EConst (Ast.Ident i),_],_) :: _ -> "get " ^ i - | (Ast.Meta.Setter,[Ast.EConst (Ast.Ident i),_],_) :: _ -> "set " ^ i + | (Meta.Getter,[Ast.EConst (Ast.Ident i),_],_) :: _ -> "get " ^ i + | (Meta.Setter,[Ast.EConst (Ast.Ident i),_],_) :: _ -> "set " ^ i | _ :: l -> loop l in " " ^ loop meta @@ -521,6 +529,14 @@ let rec gen_call ctx e el r = spr ctx "("; concat ctx "," (gen_value ctx) el; spr ctx ")" + | TField (e1,FInstance(_,_,cf)),el when is_fixed_override cf e.etype -> + let s = type_str ctx r e.epos in + spr ctx "(("; + gen_value ctx e; + spr ctx "("; + concat ctx "," (gen_value ctx) el; + spr ctx ")"; + print ctx ") as %s)" s | _ -> gen_value ctx e; spr ctx "("; @@ -824,7 +840,7 @@ and gen_value ctx e = let value block = let old = ctx.in_value in let t = type_str ctx e.etype e.epos in - let r = alloc_var (gen_local ctx "$r") e.etype in + let r = alloc_var (gen_local ctx "$r") e.etype e.epos in ctx.in_value <- Some r; if ctx.in_static then print ctx "function() : %s " t @@ -948,7 +964,7 @@ and gen_value ctx e = v() let final m = - if Ast.Meta.has Ast.Meta.Final m then "final " else "" + if Meta.has Meta.Final m then " final " else "" let generate_field ctx static f = newline ctx; @@ -956,12 +972,12 @@ let generate_field ctx static f = ctx.gen_uid <- 0; List.iter (fun(m,pl,_) -> match m,pl with - | Ast.Meta.Meta, [Ast.ECall ((Ast.EConst (Ast.Ident n),_),args),_] -> + | Meta.Meta, [Ast.ECall ((Ast.EConst (Ast.Ident n),_),args),_] -> let mk_arg (a,p) = match a with | Ast.EConst (Ast.String s) -> (None, s) | Ast.EBinop (Ast.OpAssign,(Ast.EConst (Ast.Ident n),_),(Ast.EConst (Ast.String s),_)) -> (Some n, s) - | _ -> error "Invalid meta definition" p + | _ -> abort "Invalid meta definition" p in print ctx "[%s" n; (match args with @@ -978,7 +994,7 @@ let generate_field ctx static f = | _ -> () ) f.cf_meta; let public = f.cf_public || Hashtbl.mem ctx.get_sets (f.cf_name,static) || (f.cf_name = "main" && static) - || f.cf_name = "resolve" || Ast.Meta.has Ast.Meta.Public f.cf_meta + || f.cf_name = "resolve" || Meta.has Meta.Public f.cf_meta (* consider all abstract methods public to avoid issues with inlined private access *) || (match ctx.curclass.cl_kind with KAbstractImpl _ -> true | _ -> false) in @@ -1008,8 +1024,8 @@ let generate_field ctx static f = | TFun (args,r) when (match f.cf_kind with Method MethDynamic | Var _ -> false | _ -> true) -> let rec loop = function | [] -> f.cf_name - | (Ast.Meta.Getter,[Ast.EConst (Ast.String name),_],_) :: _ -> "get " ^ name - | (Ast.Meta.Setter,[Ast.EConst (Ast.String name),_],_) :: _ -> "set " ^ name + | (Meta.Getter,[Ast.EConst (Ast.String name),_],_) :: _ -> "get " ^ name + | (Meta.Setter,[Ast.EConst (Ast.String name),_],_) :: _ -> "set " ^ name | _ :: l -> loop l in print ctx "function %s(" (loop f.cf_meta); @@ -1024,8 +1040,11 @@ let generate_field ctx static f = let gen_init () = match f.cf_expr with | None -> () | Some e -> - print ctx " = "; - gen_value ctx e + if not static || (match e.eexpr with | TConst _ | TFunction _ | TTypeExpr _ -> true | _ -> false) then begin + print ctx " = "; + gen_value ctx e + end else + Codegen.ExtClass.add_static_init ctx.curclass f e e.epos in if is_getset then begin let t = type_str ctx f.cf_type p in @@ -1100,20 +1119,40 @@ let generate_class ctx c = ); List.iter (generate_field ctx false) c.cl_ordered_fields; List.iter (generate_field ctx true) c.cl_ordered_statics; + let has_init = match c.cl_init with + | None -> false + | Some e -> + newline ctx; + spr ctx "static static_init function init() : void"; + gen_expr ctx (mk_block e); + true; + in cl(); newline ctx; print ctx "}"; pack(); newline ctx; print ctx "}"; - newline ctx + if has_init then begin + newline ctx; + spr ctx "namespace static_init"; + newline ctx; + print ctx "%s.static_init::init()" (s_path ctx true ctx.curclass.cl_path Globals.null_pos); + end; + newline ctx; + if c.cl_interface && Meta.has (Meta.Custom ":hasMetadata") c.cl_meta then begin + (* we have to reference the metadata class in order for it to be compiled *) + let path = fst c.cl_path,snd c.cl_path ^ "_HxMeta" in + spr ctx (Globals.s_type_path path); + newline ctx + end let generate_main ctx inits = ctx.curclass <- { null_class with cl_path = [],"__main__" }; let pack = open_block ctx in print ctx "\timport flash.Lib"; newline ctx; - print ctx "public class __main__ extends %s {" (s_path ctx true (["flash"],"Boot") Ast.null_pos); + print ctx "public class __main__ extends %s {" (s_path ctx true (["flash"],"Boot") Globals.null_pos); let cl = open_block ctx in newline ctx; spr ctx "public function __main__() {"; @@ -1214,11 +1253,10 @@ let generate com = | ["flash"],"FlashXml__" -> { c with cl_path = [],"Xml" } | (pack,name) -> { c with cl_path = (pack,protect name) } ) in - (match c.cl_init with - | None -> () - | Some e -> inits := e :: !inits); if c.cl_extern then - () + (match c.cl_init with + | None -> () + | Some e -> inits := e :: !inits) else let ctx = init infos c.cl_path in generate_class ctx c; diff --git a/gencommon.ml b/src/generators/gencommon.ml similarity index 72% rename from gencommon.ml rename to src/generators/gencommon.ml index a8b955e5..39fe80a8 100644 --- a/gencommon.ml +++ b/src/generators/gencommon.ml @@ -1,55 +1,69 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) (* Gen Common API - This module intends to be a common set of utilities common to all targets. - - It's intended to provide a set of tools to be able to make targets in Haxe more easily, and to - allow the programmer to have more control of how the target language will handle the program. - - For example, as of now, the hxcpp target, while greatly done, relies heavily on cpp's own operator - overloading, and implicit conversions, which make it very hard to deliver a similar solution for languages - that lack these features. - - So this little framework is here so you can manipulate the Haxe AST and start bringing the AST closer - to how it's intenteded to be in your host language. - - Rules - - Design goals - - Naming convention - - Weaknesses and TODO's + This is the key module for generation of Java and C# sources + In order for both modules to share as much code as possible, some + rules were devised: + + - every feature has its own submodule, and may contain the following methods: + - configure + sets all the configuration variables for the module to run. If a module has this method, + it *should* be called once before running any filter + - run_filter -> + runs the filter immediately on the context + - add_filter -> + adds the filter to an expr->expr list. Most filter modules will provide this option so the filter + function can only run once. + - most submodules will have side-effects so the order of operations will matter. + When running configure / add_filter this might be taken care of with the rule-based dispatch system working + underneath, but still there might be some incompatibilities. There will be an effort to document it. + The modules can hint on the order by suffixing their functions with _first or _last. + - any of those methods might have different parameters, that configure how the filter will run. + For example, a simple filter that maps switch() expressions to if () .. else if... might receive + a function that filters what content should be mapped + - Other targets can use those filters on their own code. In order to do that, + a simple configuration step is needed: you need to initialize a generator_ctx type with + Gencommon.new_gen (context:Common.context) + with a generator_ctx context you will be able to add filters to your code, and execute them with + Gencommon.run_filters (gen_context:Gencommon.generator_ctx) + + After running the filters, you can run your own generator normally. + + (* , or you can run + Gencommon.generate_modules (gen_context:Gencommon.generator_ctx) (extension:string) (module_gen:module_type list->bool) + where module_gen will take a whole module (can be *) *) open Unix open Ast open Type open Common +open Globals open Option open Printf open ExtString +open Codegen +open Overloads + +let alloc_var n t = alloc_var n t null_pos let debug_type_ctor = function | TMono _ -> "TMono" @@ -83,12 +97,9 @@ let rec like_int t = let rec like_i64 t = match follow t with - | TInst({ cl_path = (["cs"], "Int64") },[]) | TAbstract({ a_path = (["cs"], "Int64") },[]) - | TInst({ cl_path = (["cs"], "UInt64") },[]) - | TInst({ cl_path = (["java"], "Int64") },[]) + | TAbstract({ a_path = (["cs"], "UInt64") },[]) | TAbstract({ a_path = (["java"], "Int64") },[]) - | TInst({ cl_path = (["haxe"], "Int64") },[]) | TAbstract({ a_path = (["haxe"], "Int64") },[]) -> true | TAbstract(a, _) -> List.exists (fun t -> like_i64 t) a.a_from || List.exists (fun t -> like_i64 t) a.a_to | _ -> false @@ -114,86 +125,13 @@ let reset_temps () = tmp_count := 0 (* the undefined is a special var that works like null, but can have special meaning *) let v_undefined = alloc_var "__undefined__" t_dynamic -let undefined pos = { eexpr = TLocal(v_undefined); etype = t_dynamic; epos = pos } - -module ExprHashtblHelper = -struct - type hash_texpr_t = - { - hepos : pos; - heexpr : int; - hetype : int; - } - - let mk_heexpr = function - | TConst _ -> 0 | TLocal _ -> 1 | TArray _ -> 3 | TBinop _ -> 4 | TField _ -> 5 | TTypeExpr _ -> 7 | TParenthesis _ -> 8 | TObjectDecl _ -> 9 - | TArrayDecl _ -> 10 | TCall _ -> 11 | TNew _ -> 12 | TUnop _ -> 13 | TFunction _ -> 14 | TVar _ -> 15 | TBlock _ -> 16 | TFor _ -> 17 | TIf _ -> 18 | TWhile _ -> 19 - | TSwitch _ -> 20 (* | TPatMatch _ -> 21 *) | TTry _ -> 22 | TReturn _ -> 23 | TBreak -> 24 | TContinue -> 25 | TThrow _ -> 26 | TCast _ -> 27 | TMeta _ -> 28 | TEnumParameter _ -> 29 - - let mk_heetype = function - | TMono _ -> 0 | TEnum _ -> 1 | TInst _ -> 2 | TType _ -> 3 | TFun _ -> 4 - | TAnon _ -> 5 | TDynamic _ -> 6 | TLazy _ -> 7 | TAbstract _ -> 8 - - let mk_type e = - { - hepos = e.epos; - heexpr = mk_heexpr e.eexpr; - hetype = mk_heetype e.etype; - } -end;; +let undefined pos = ExprBuilder.make_local v_undefined pos let path_of_md_def md_def = match md_def.m_types with | [TClassDecl c] -> c.cl_path | _ -> md_def.m_path -open ExprHashtblHelper;; -(* Expression Hashtbl. This shouldn't be kept indefinately as it's not a weak Hashtbl. *) -module ExprHashtbl = Hashtbl.Make( - struct - type t = Type.texpr - - let equal = (==) - let hash t = Hashtbl.hash (mk_type t) - end -);; - -(* ******************************************* *) -(* Gen Common - -This is the key module for generation of Java and C# sources -In order for both modules to share as much code as possible, some -rules were devised: - -- every feature has its own submodule, and may contain the following methods: - - configure - sets all the configuration variables for the module to run. If a module has this method, - it *should* be called once before running any filter - - run_filter -> - runs the filter immediately on the context - - add_filter -> - adds the filter to an expr->expr list. Most filter modules will provide this option so the filter - function can only run once. -- most submodules will have side-effects so the order of operations will matter. - When running configure / add_filter this might be taken care of with the rule-based dispatch system working - underneath, but still there might be some incompatibilities. There will be an effort to document it. - The modules can hint on the order by suffixing their functions with _first or _last. -- any of those methods might have different parameters, that configure how the filter will run. - For example, a simple filter that maps switch() expressions to if () .. else if... might receive - a function that filters what content should be mapped -- Other targets can use those filters on their own code. In order to do that, - a simple configuration step is needed: you need to initialize a generator_ctx type with - Gencommon.new_gen (context:Common.context) - with a generator_ctx context you will be able to add filters to your code, and execute them with - Gencommon.run_filters (gen_context:Gencommon.generator_ctx) - - After running the filters, you can run your own generator normally. - - (* , or you can run - Gencommon.generate_modules (gen_context:Gencommon.generator_ctx) (extension:string) (module_gen:module_type list->bool) - where module_gen will take a whole module (can be *) - -*) (* ******************************************* *) (* common helpers *) @@ -204,7 +142,10 @@ let debug_mode = ref false let trace s = if !debug_mode then print_endline s else () let timer name = if !debug_mode then Common.timer name else fun () -> () -let is_string t = match follow t with | TInst({ cl_path = ([], "String") }, []) -> true | _ -> false +let is_string t = + match follow t with + | TInst({ cl_path = ([], "String") }, []) -> true + | _ -> false (* helper function for creating Anon types of class / enum modules *) @@ -233,17 +174,14 @@ let anon_of_mt mt = match mt with | _ -> assert false let anon_class t = - match follow t with - | TAnon anon -> - (match !(anon.a_status) with - | Statics (cl) -> Some(TClassDecl(cl)) - | EnumStatics (e) -> Some(TEnumDecl(e)) - | AbstractStatics (a) -> Some(TAbstractDecl(a)) - | _ -> None) - | _ -> None - -let path_s path = - match path with | ([], s) -> s | (p, s) -> (String.concat "." (fst path)) ^ "." ^ (snd path) + match follow t with + | TAnon anon -> + (match !(anon.a_status) with + | Statics cl -> Some(TClassDecl cl) + | EnumStatics e -> Some(TEnumDecl e) + | AbstractStatics a -> Some(TAbstractDecl a) + | _ -> None) + | _ -> None let rec t_to_md t = match t with | TInst (cl,_) -> TClassDecl cl @@ -260,36 +198,34 @@ let path_s path = | TMono r -> (match !r with | Some t -> t_to_md t | None -> assert false) | _ -> assert false -let get_cl mt = match mt with | TClassDecl cl -> cl | _ -> failwith ("Unexpected module type of '" ^ path_s (t_path mt) ^ "'") +let get_cl mt = match mt with | TClassDecl cl -> cl | _ -> failwith (Printf.sprintf "Unexpected module type (class expected) for %s: %s" (s_type_path (t_path mt)) (s_module_type_kind mt)) -let get_abstract mt = match mt with | TAbstractDecl a -> a | _ -> failwith ("Unexpected module type of '" ^ path_s (t_path mt) ^ "'") +let get_abstract mt = match mt with | TAbstractDecl a -> a | _ -> failwith (Printf.sprintf "Unexpected module type (abstract expected) for %s: %s" (s_type_path (t_path mt)) (s_module_type_kind mt)) let get_tdef mt = match mt with | TTypeDecl t -> t | _ -> assert false let mk_mt_access mt pos = { eexpr = TTypeExpr(mt); etype = anon_of_mt mt; epos = pos } -let is_void t = match follow t with - | TAbstract ({ a_path = ([], "Void") },[]) -> - true - | _ -> false - -let mk_local var pos = { eexpr = TLocal(var); etype = var.v_type; epos = pos } +let mk_local = ExprBuilder.make_local (* this function is used by CastDetection module *) let get_fun t = - match follow t with | TFun(r1,r2) -> (r1,r2) | _ -> (trace (s_type (print_context()) (follow t) )); assert false + match follow t with + | TFun(r1,r2) -> (r1,r2) + | t -> (trace (debug_type t)); assert false -let mk_cast t e = - { eexpr = TCast(e, None); etype = t; epos = e.epos } +let mk_cast t e = Type.mk_cast e t e.epos -let mk_classtype_access cl pos = - { eexpr = TTypeExpr(TClassDecl(cl)); etype = anon_of_classtype cl; epos = pos } +(** TODO: when adding new AST, make a new cast type for those fast casts. For now, we're using this hack + * of using null_class to tell a fast cast from a normal one. Also note that this only works since both + * C# and Java do not use the second part of TCast for anything *) +let mk_castfast t e = { e with eexpr = TCast(e, Some (TClassDecl null_class)); etype = t } let mk_static_field_access_infer cl field pos params = try let cf = (PMap.find field cl.cl_statics) in - { eexpr = TField(mk_classtype_access cl pos, FStatic(cl, cf)); etype = (if params = [] then cf.cf_type else apply_params cf.cf_params params cf.cf_type); epos = pos } - with | Not_found -> failwith ("Cannot find field " ^ field ^ " in type " ^ (path_s cl.cl_path)) + { eexpr = TField(ExprBuilder.make_static_this cl pos, FStatic(cl, cf)); etype = (if params = [] then cf.cf_type else apply_params cf.cf_params params cf.cf_type); epos = pos } + with | Not_found -> failwith ("Cannot find field " ^ field ^ " in type " ^ (s_type_path cl.cl_path)) let mk_static_field_access cl field fieldt pos = { (mk_static_field_access_infer cl field pos []) with etype = fieldt } @@ -432,7 +368,7 @@ class ['tp, 'ret] rule_dispatcher name ignore_not_found = if key < priority then begin let q = Hashtbl.find tbl key in Stack.iter (fun (n, rule) -> - let t = if !debug_mode then Common.timer ("rule dispatcher rule: " ^ n) else fun () -> () in + let t = if !debug_mode then Common.timer [("rule dispatcher rule: " ^ n)] else fun () -> () in let r = rule(tp) in t(); if is_some r then begin ret := r; raise Exit end @@ -470,7 +406,7 @@ class ['tp] rule_map_dispatcher name = let q = Hashtbl.find tbl key in Stack.iter (fun (n, rule) -> trace ("running rule " ^ n); - let t = if !debug_mode then Common.timer ("rule map dispatcher rule: " ^ n) else fun () -> () in + let t = if !debug_mode then Common.timer [("rule map dispatcher rule: " ^ n)] else fun () -> () in let r = rule(!cur) in t(); if is_some r then begin cur := get r end @@ -488,7 +424,7 @@ type generator_ctx = { (* these are the basic context fields. If another target is using this context, *) (* this is all you need to care about *) - mutable gcon : Common.context; + gcon : Common.context; gclasses : gen_classes; @@ -499,7 +435,7 @@ type generator_ctx = to ensure that it will not be called from outside. To avoid name clashes between internal names, user must specify two strings: a "namespace" and the name itself *) - mutable gmk_internal_name : string->string->string; + gmk_internal_name : string->string->string; (* module filters run before module filters and they should generate valid haxe syntax as a result. @@ -609,12 +545,6 @@ type generator_ctx = *) mutable gallow_tp_dynamic_conversion : bool; - (* - Does the target support type parameter constraints? - If not, they will be ignored when detecting casts - *) - mutable guse_tp_constraints : bool; - (* internal apis *) (* param_func_call : used by TypeParams and CastDetection *) mutable gparam_func_call : texpr->texpr->tparams->texpr list->texpr; @@ -636,8 +566,6 @@ and gen_classes = cl_type : tclass; cl_dyn : tclass; - t_iterator : tdef; - mutable nativearray_len : texpr -> pos -> texpr; mutable nativearray_type : Type.t -> Type.t; mutable nativearray : Type.t -> Type.t; @@ -646,21 +574,17 @@ and gen_classes = (* add here all reflection transformation additions *) and gen_tools = { - (* (klass : texpr, t : t) : texpr *) - mutable r_create_empty : texpr->t->texpr; (* Reflect.fields(). The bool is if we are iterating in a read-only manner. If it is read-only we might not need to allocate a new array *) - mutable r_fields : bool->texpr->texpr; + r_fields : bool->texpr->texpr; (* (first argument = return type. should be void in most cases) Reflect.setField(obj, field, val) *) - mutable r_set_field : t->texpr->texpr->texpr->texpr; + r_set_field : t->texpr->texpr->texpr->texpr; (* Reflect.field. bool indicates if is safe (no error throwing) or unsafe; t is the expected return type true = safe *) - mutable r_field : bool->t->texpr->texpr->texpr; + r_field : bool->t->texpr->texpr->texpr; (* - these are now the functions that will later be used when creating the reflection classes + return an expression that creates an unitialized instance of a class, used for the generic cast helper method. *) - - (* on the default implementation (at OverloadingCtors), it will be new SomeClass(EmptyInstance) *) - mutable rf_create_empty : tclass->tparams->pos->texpr; + mutable r_create_empty : tclass->tparams->pos->texpr; } let get_type types path = @@ -685,7 +609,7 @@ let new_ctx con = let cl_dyn = match get_type con.types ([], "Dynamic") with | TClassDecl c -> c | TAbstractDecl a -> - mk_class a.a_module ([], "Dynamic") a.a_pos + mk_class a.a_module ([], "Dynamic") a.a_pos null_pos | _ -> assert false in @@ -696,17 +620,11 @@ let new_ctx con = cl_type = get_cl (get_type con.types ([], "Type")); cl_dyn = cl_dyn; - t_iterator = get_tdef (get_type con.types ([], "Iterator")); - nativearray = (fun _ -> assert false); nativearray_type = (fun _ -> assert false); nativearray_len = (fun _ -> assert false); }; gtools = { - r_create_empty = (fun eclass t -> - let fieldcall = mk_static_field_access_infer gen.gclasses.cl_type "createEmptyInstance" eclass.epos [t] in - { eexpr = TCall(fieldcall, [eclass]); etype = t; epos = eclass.epos } - ); r_fields = (fun is_used_only_by_iteration expr -> let fieldcall = mk_static_field_access_infer gen.gclasses.cl_reflect "fields" expr.epos [] in { eexpr = TCall(fieldcall, [expr]); etype = gen.gcon.basic.tarray gen.gcon.basic.tstring; epos = expr.epos } @@ -723,9 +641,7 @@ let new_ctx con = mk_cast t { eexpr = TCall(fieldcall, [obj; field]); etype = t_dynamic; epos = obj.epos } ); - rf_create_empty = (fun cl p pos -> - gen.gtools.r_create_empty { eexpr = TTypeExpr(TClassDecl cl); epos = pos; etype = t_dynamic } (TInst(cl,p)) - ); (* TODO: Maybe implement using normal reflection? Type.createEmpty(MyClass) *) + r_create_empty = (fun _ _ pos -> gen.gcon.error "r_create_empty implementation is not provided" pos; assert false); }; gmk_internal_name = (fun ns s -> sprintf "__%s_%s" ns s); gexpr_filters = new rule_map_dispatcher "gexpr_filters"; @@ -746,11 +662,11 @@ let new_ctx con = gadd_type = (fun md should_filter -> if should_filter then begin gen.gtypes_list <- md :: gen.gtypes_list; - gen.gmodules <- { m_id = alloc_mid(); m_path = (t_path md); m_types = [md]; m_extra = module_extra "" "" 0. MFake } :: gen.gmodules; + gen.gmodules <- { m_id = alloc_mid(); m_path = (t_path md); m_types = [md]; m_extra = module_extra "" "" 0. MFake [] } :: gen.gmodules; Hashtbl.add gen.gtypes (t_path md) md; end else gen.gafter_filters_ended <- (fun () -> gen.gtypes_list <- md :: gen.gtypes_list; - gen.gmodules <- { m_id = alloc_mid(); m_path = (t_path md); m_types = [md]; m_extra = module_extra "" "" 0. MFake } :: gen.gmodules; + gen.gmodules <- { m_id = alloc_mid(); m_path = (t_path md); m_types = [md]; m_extra = module_extra "" "" 0. MFake [] } :: gen.gmodules; Hashtbl.add gen.gtypes (t_path md) md; ) :: gen.gafter_filters_ended; ); @@ -772,8 +688,6 @@ let new_ctx con = gallow_tp_dynamic_conversion = false; - guse_tp_constraints = false; - (* as a default, ignore the params *) gparam_func_call = (fun ecall efield params elist -> { ecall with eexpr = TCall(efield, elist) }); ghas_tparam_cast_handler = false; @@ -781,11 +695,6 @@ let new_ctx con = gspecial_vars = Hashtbl.create 0; } in - - (*gen.gtools.r_create_empty <- - gen.gtools.r_get_class <- - gen.gtools.r_fields <- *) - gen let init_ctx gen = @@ -825,47 +734,46 @@ let reorder_modules gen = let run_filters_from gen t filters = match t with - | TClassDecl c -> - trace (snd c.cl_path); - gen.gcurrent_path <- c.cl_path; - gen.gcurrent_class <- Some(c); + | TClassDecl c -> + trace (snd c.cl_path); + gen.gcurrent_path <- c.cl_path; + gen.gcurrent_class <- Some(c); - List.iter (fun fn -> fn()) gen.gon_new_module_type; + List.iter (fun fn -> fn()) gen.gon_new_module_type; - gen.gcurrent_classfield <- None; - let rec process_field f = - reset_temps(); - gen.gcurrent_classfield <- Some(f); - List.iter (fun fn -> fn()) gen.gon_classfield_start; + gen.gcurrent_classfield <- None; + let rec process_field f = + reset_temps(); + gen.gcurrent_classfield <- Some(f); + List.iter (fun fn -> fn()) gen.gon_classfield_start; - trace f.cf_name; - (match f.cf_expr with - | None -> () - | Some e -> - f.cf_expr <- Some (List.fold_left (fun e f -> f e) e filters)); - List.iter process_field f.cf_overloads; - in - List.iter process_field c.cl_ordered_fields; - List.iter process_field c.cl_ordered_statics; - - (match c.cl_constructor with - | None -> () - | Some f -> process_field f); - gen.gcurrent_classfield <- None; - (match c.cl_init with - | None -> () - | Some e -> - c.cl_init <- Some (List.fold_left (fun e f -> f e) e filters)); - | TEnumDecl _ -> () - | TTypeDecl _ -> () - | TAbstractDecl _ -> () + trace f.cf_name; + (match f.cf_expr with + | None -> () + | Some e -> + f.cf_expr <- Some (List.fold_left (fun e f -> f e) e filters)); + List.iter process_field f.cf_overloads; + in + List.iter process_field c.cl_ordered_fields; + List.iter process_field c.cl_ordered_statics; + + (match c.cl_constructor with + | None -> () + | Some f -> process_field f); + gen.gcurrent_classfield <- None; + (match c.cl_init with + | None -> () + | Some e -> + c.cl_init <- Some (List.fold_left (fun e f -> f e) e filters)); + | TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ -> + () let run_filters gen = let last_error = gen.gcon.error in let has_errors = ref false in gen.gcon.error <- (fun msg pos -> has_errors := true; last_error msg pos); (* first of all, we have to make sure that the filters won't trigger a major Gc collection *) - let t = Common.timer "gencommon_filters" in + let t = Common.timer ["gencommon_filters"] in (if Common.defined gen.gcon Define.GencommonDebug then debug_mode := true else debug_mode := false); let run_filters filter = let rec loop acc mds = @@ -961,7 +869,7 @@ let run_filters gen = (* ******************************************* *) let write_file gen w source_dir path extension out_files = - let t = timer "write file" in + let t = timer ["write";"file"] in let s_path = source_dir ^ "/" ^ (snd path) ^ "." ^ (extension) in (* create the folders if they don't exist *) mkdir_from_path s_path; @@ -980,7 +888,7 @@ let write_file gen w source_dir path extension out_files = close_out f end; - out_files := (unique_full_path s_path) :: !out_files; + out_files := (Path.unique_full_path s_path) :: !out_files; t() @@ -995,7 +903,7 @@ let clean_files path excludes verbose = let pack = pack @ [file] in iter_files (pack) (Unix.opendir filepath) filepath; try Unix.rmdir filepath with Unix.Unix_error (ENOTEMPTY,_,_) -> (); - else if not (String.ends_with filepath ".meta") && not (List.mem (unique_full_path filepath) excludes) then begin + else if not (String.ends_with filepath ".meta") && not (List.mem (Path.unique_full_path filepath) excludes) then begin if verbose then print_endline ("Removing " ^ filepath); Sys.remove filepath end @@ -1120,65 +1028,6 @@ let dump_descriptor gen name path_s module_s = output_string f contents; close_out f -let path_regex = Str.regexp "[/\\]+" - -let normalize path = - let rec normalize acc m = match m with - | [] -> - List.rev acc - | Str.Text "." :: Str.Delim _ :: tl when acc = [] -> - normalize [] tl - | Str.Text ".." :: Str.Delim _ :: tl -> (match acc with - | [] -> raise Exit - | _ :: acc -> normalize acc tl) - | Str.Text t :: Str.Delim _ :: tl -> - normalize (t :: acc) tl - | Str.Delim _ :: tl -> - normalize ("" :: acc) tl - | Str.Text t :: [] -> - List.rev (t :: acc) - | Str.Text _ :: Str.Text _ :: _ -> assert false - in - String.concat "/" (normalize [] (Str.full_split path_regex path)) - -let is_relative cwd rel = - try - let rel = normalize rel in - Filename.is_relative rel || (String.starts_with rel cwd || String.starts_with (Common.unique_full_path rel) cwd) - with | Exit -> - String.starts_with rel cwd || String.starts_with (Common.unique_full_path rel) cwd - -(* - helper function to create the source structure. Will send each module_def to the function passed. - If received true, it means that module_gen has generated this content, so the file must be saved. - See that it will write a whole module -*) -let generate_modules gen extension source_dir (module_gen : SourceWriter.source_writer->module_def->bool) out_files = - List.iter (fun md_def -> - let source_dir = - gen.gcon.file ^ "/" ^ source_dir ^ "/" ^ (String.concat "/" (fst (path_of_md_def md_def))) - in - let w = SourceWriter.new_source_writer () in - (*let should_write = List.fold_left (fun should md -> module_gen w md or should) false md_def.m_types in*) - let should_write = module_gen w md_def in - if should_write then begin - let path = path_of_md_def md_def in - write_file gen w source_dir path extension out_files - end - ) gen.gmodules - -let generate_modules_t gen extension source_dir change_path (module_gen : SourceWriter.source_writer->module_type->bool) out_files = - let source_dir = gen.gcon.file ^ "/" ^ source_dir in - List.iter (fun md -> - let w = SourceWriter.new_source_writer () in - (*let should_write = List.fold_left (fun should md -> module_gen w md or should) false md_def.m_types in*) - let should_write = module_gen w md in - if should_write then begin - let path = change_path (t_path md) in - write_file gen w (source_dir ^ "/" ^ (String.concat "/" (fst path))) path extension out_files; - end - ) gen.gtypes_list - (* various helper functions *) @@ -1193,8 +1042,6 @@ let get_real_fun gen t = | TFun(args,t) -> TFun(List.map (fun (n,o,t) -> n,o,gen.greal_type t) args, gen.greal_type t) | _ -> t -let mk_int gen i pos = { eexpr = TConst(TInt ( Int32.of_int i)); etype = gen.gcon.basic.tint; epos = pos } - let mk_return e = { eexpr = TReturn (Some e); etype = e.etype; epos = e.epos } let mk_temp gen name t = @@ -1305,11 +1152,13 @@ let mk_class_field name t public pos kind params = cf_type = t; cf_public = public; cf_pos = pos; + cf_name_pos = null_pos; cf_doc = None; - cf_meta = [ Meta.CompilerGenerated, [], Ast.null_pos ]; (* annotate that this class field was generated by the compiler *) + cf_meta = [ Meta.CompilerGenerated, [], null_pos ]; (* annotate that this class field was generated by the compiler *) cf_kind = kind; cf_params = params; cf_expr = None; + cf_expr_unoptimized = None; cf_overloads = []; } @@ -1317,7 +1166,7 @@ let mk_class_field name t public pos kind params = (* This is so we can use class parameters on function parameters, without running the risk of name clash *) (* between both *) let map_param cl = - let ret = mk_class cl.cl_module (fst cl.cl_path, snd cl.cl_path ^ "_c") cl.cl_pos in + let ret = mk_class cl.cl_module (fst cl.cl_path, snd cl.cl_path ^ "_c") cl.cl_pos null_pos in ret.cl_implements <- cl.cl_implements; ret.cl_kind <- cl.cl_kind; ret @@ -1326,8 +1175,8 @@ let get_cl_t t = match follow t with | TInst (cl,_) -> cl | _ -> assert false let mk_class m path pos = - let cl = Type.mk_class m path pos in - cl.cl_meta <- [ Meta.CompilerGenerated, [], Ast.null_pos ]; + let cl = Type.mk_class m path pos null_pos in + cl.cl_meta <- [ Meta.CompilerGenerated, [], null_pos ]; cl type tfield_access = @@ -1354,7 +1203,7 @@ let find_first_declared_field gen orig_cl ?get_vmtype ?exact_field field = | _, Some f2 -> List.iter (fun f -> let declared_t = apply_params c.cl_params tl f.cf_type in - if Typeload.same_overload_args ~get_vmtype declared_t f2.cf_type f f2 then + if same_overload_args ~get_vmtype declared_t f2.cf_type f f2 then chosen := Some(depth,f,c,tl,tlch) ) (ret :: ret.cf_overloads) with | Not_found -> ()); @@ -1375,7 +1224,8 @@ let find_first_declared_field gen orig_cl ?get_vmtype ?exact_field field = in loop_cl 0 orig_cl (List.map snd orig_cl.cl_params) (List.map snd orig_cl.cl_params); match !chosen with - | None -> None + | None -> + None | Some(_,f,c,tl,tlch) -> if !is_overload && not (Meta.has Meta.Overload f.cf_meta) then f.cf_meta <- (Meta.Overload,[],f.cf_pos) :: f.cf_meta; @@ -1491,11 +1341,6 @@ let mk_field_access gen expr field pos = { eexpr = TField(expr, FDynamic field); etype = t_dynamic; epos = pos } | FEnumField _ -> assert false -let mk_iterator_access gen t expr = - let pos = expr.epos in - let itf = mk_field_access gen expr "iterator" pos in - { eexpr = TCall(itf, []); epos = pos; etype = snd (get_fun itf.etype) } - (* ******************************************* *) (* Module dependency resolution *) (* ******************************************* *) @@ -1533,58 +1378,36 @@ exception TypeNotFound of path let get_type gen path = try Hashtbl.find gen.gtypes path with | Not_found -> raise (TypeNotFound path) -(* ******************************************* *) -(* follow all module *) -(* ******************************************* *) - -(* - this module will follow each and every type using the rules defined in - gen.gfollow. This is a minor helper module, so we don't end up - having to follow the same time multiple times in the many filter iterations - because of this, it will be one of the first modules to run. -*) -module FollowAll = -struct - - let follow gen e = - let follow_func = gen.gfollow#run_f in - Some (Type.map_expr_type (fun e->e) (follow_func) (fun tvar-> tvar.v_type <- (follow_func tvar.v_type); tvar) e) - - let priority = max_dep - - (* will add an expression filter as the first filter *) - let configure gen = - gen.gexpr_filters#add ~name:"follow_all" ~priority:(PCustom(priority)) (follow gen) - -end;; (* ******************************************* *) (* set hxgen module *) (* ******************************************* *) - (* - goes through all module types and sets the :hxgen meta on all which - then is_hxgen_func returns true. There is a default is_hxgen_func implementation also + Goes through all module types and adds the @:hxGen or @:nativeGen meta to them. + Basically, everything that is extern is assumed to not be hxgen, unless meta :hxGen is set, + and everything that is not extern is assumed to be hxgen, unless meta :nativeGgen is set. *) - module SetHXGen = struct - (* - basically, everything that is extern is assumed to not be hxgen, unless meta :hxgen is set, and - everything that is not extern is assumed to be hxgen, unless meta :nativegen is set + The only option is to run this filter eagerly, because it must be one of the first filters to run, + since many others depend of it. *) - let rec default_hxgen_func md = - match md with + let run_filter gen = + let rec is_hxgen md = + match md with | TClassDecl { cl_kind = KAbstractImpl a } -> - default_hxgen_func (TAbstractDecl a) + is_hxgen (TAbstractDecl a) | TClassDecl cl -> let rec is_hxgen_class (c,_) = if c.cl_extern then begin - if Meta.has Meta.HxGen c.cl_meta then true else Option.map_default (is_hxgen_class) false c.cl_super || List.exists is_hxgen_class c.cl_implements + if Meta.has Meta.HxGen c.cl_meta then + true + else + Option.map_default (is_hxgen_class) false c.cl_super || List.exists is_hxgen_class c.cl_implements end else begin if Meta.has Meta.NativeChildren c.cl_meta || Meta.has Meta.NativeGen c.cl_meta then - Option.map_default (is_hxgen_class) false c.cl_super || List.exists is_hxgen_class c.cl_implements + Option.map_default is_hxgen_class false c.cl_super || List.exists is_hxgen_class c.cl_implements else let rec has_nativec (c,p) = if is_hxgen_class (c,p) then @@ -1599,41 +1422,47 @@ struct true end in - is_hxgen_class (cl,[]) - | TEnumDecl e -> if e.e_extern then Meta.has Meta.HxGen e.e_meta else not (Meta.has Meta.NativeGen e.e_meta) - | TAbstractDecl a when Meta.has Meta.CoreType a.a_meta -> not (Meta.has Meta.NativeGen a.a_meta) - | TAbstractDecl a -> (match follow a.a_this with + | TEnumDecl e -> + if e.e_extern then + Meta.has Meta.HxGen e.e_meta + else if Meta.has Meta.NativeGen e.e_meta then + if Meta.has Meta.FlatEnum e.e_meta then + false + else begin + gen.gcon.error "Only flat enums may be @:nativeGen" e.e_pos; + true + end + else + true + | TAbstractDecl a when Meta.has Meta.CoreType a.a_meta -> + not (Meta.has Meta.NativeGen a.a_meta) + | TAbstractDecl a -> + (match follow a.a_this with | TInst _ | TEnum _ | TAbstract _ -> - default_hxgen_func (t_to_md (follow a.a_this)) + is_hxgen (t_to_md (follow a.a_this)) | _ -> not (Meta.has Meta.NativeGen a.a_meta)) | TTypeDecl t -> (* TODO see when would we use this *) false + in - (* - by now the only option is to run it eagerly, because it must be one of the first filters to run, - since many others depend of it - *) - let run_filter gen is_hxgen_func = let filter md = - let meta = if is_hxgen_func md then Meta.HxGen else Meta.NativeGen in - begin - match md with - | TClassDecl cl -> cl.cl_meta <- (meta, [], cl.cl_pos) :: cl.cl_meta - | TEnumDecl e -> e.e_meta <- (meta, [], e.e_pos) :: e.e_meta - | TTypeDecl t -> t.t_meta <- (meta, [], t.t_pos) :: t.t_meta - | TAbstractDecl a -> a.a_meta <- (meta, [], a.a_pos) :: a.a_meta - end + let meta = if is_hxgen md then Meta.HxGen else Meta.NativeGen in + match md with + | TClassDecl cl -> cl.cl_meta <- (meta, [], cl.cl_pos) :: cl.cl_meta + | TEnumDecl e -> e.e_meta <- (meta, [], e.e_pos) :: e.e_meta + | TTypeDecl t -> t.t_meta <- (meta, [], t.t_pos) :: t.t_meta + | TAbstractDecl a -> a.a_meta <- (meta, [], a.a_pos) :: a.a_meta in - List.iter filter gen.gtypes_list + List.iter filter gen.gtypes_list end;; + (* ******************************************* *) (* overloading reflection constructors *) (* ******************************************* *) - (* this module works on languages that support function overloading and enable function hiding via static functions. @@ -1641,11 +1470,11 @@ end;; static function. The static function will receive the same parameters as the constructor, plus the special "me" var, which will replace "this" - Then it always adds two constructors to the function: one that receives a special class, - indicating that it should be constructed without any parameters, and one that receives its normal constructor. + Then it always adds two constructors to the class: one that receives a special marker class, + indicating that the object should be constructed without executing constructor body, + and one that executes its normal constructor. Both will only include a super() call to the superclasses' emtpy constructor. - This enables two things: empty construction without the need of incompatibility with the platform's native construction method the ability to call super() constructor in any place in the constructor @@ -1654,93 +1483,95 @@ end;; *) module OverloadingConstructor = struct - let priority = 0.0 - let name = "overloading_constructor" - let set_new_create_empty gen empty_ctor_expr = - let old = gen.gtools.rf_create_empty in - gen.gtools.rf_create_empty <- (fun cl params pos -> - if is_hxgen (TClassDecl cl) then - { eexpr = TNew(cl,params,[empty_ctor_expr]); etype = TInst(cl,params); epos = pos } - else - old cl params pos - ) - let rec cur_ctor c tl = match c.cl_constructor with - | Some ctor -> ctor, c, tl - | None -> match c.cl_super with - | None -> raise Not_found - | Some (sup,stl) -> - cur_ctor sup (List.map (apply_params c.cl_params tl) stl) + | Some ctor -> + ctor, c, tl + | None -> + match c.cl_super with + | None -> + raise Not_found + | Some (sup,stl) -> + cur_ctor sup (List.map (apply_params c.cl_params tl) stl) let rec prev_ctor c tl = match c.cl_super with - | None -> raise Not_found + | None -> + raise Not_found | Some (sup,stl) -> let stl = List.map (apply_params c.cl_params tl) stl in match sup.cl_constructor with | None -> prev_ctor sup stl | Some ctor -> ctor, sup, stl + let make_static_ctor_name gen cl = + let name = gen.gmk_internal_name "hx" "ctor" in + name ^ "_" ^ (String.concat "_" (fst cl.cl_path)) ^ "_" ^ (snd cl.cl_path) + (* replaces super() call with last static constructor call *) - let replace_super_call gen name c tl with_params me p = - let rec loop_super c tl = match c.cl_super with - | None -> raise Not_found + let replace_super_call gen c tl with_params me p = + let rec loop_super c tl = + match c.cl_super with + | None -> + raise Not_found | Some(sup,stl) -> let stl = List.map (apply_params c.cl_params tl) stl in try - let static_ctor_name = name ^ "_" ^ (String.concat "_" (fst sup.cl_path)) ^ "_" ^ (snd sup.cl_path) in + let static_ctor_name = make_static_ctor_name gen sup in sup, stl, PMap.find static_ctor_name sup.cl_statics - with | Not_found -> + with Not_found -> loop_super sup stl in let sup, stl, cf = loop_super c tl in - let with_params = { eexpr = TLocal me; etype = me.v_type; epos = p } :: with_params in - let cf = match cf.cf_overloads with - (* | [] -> cf *) - | _ -> try - (* choose best super function *) - List.iter (fun e -> replace_mono e.etype) with_params; - List.find (fun cf -> - replace_mono cf.cf_type; - let args, _ = get_fun (apply_params cf.cf_params stl cf.cf_type) in - try - List.for_all2 (fun (_,_,t) e -> try - let e_etype = run_follow gen e.etype in - let t = run_follow gen t in - unify e_etype t; true - with | Unify_error _ -> false) args with_params - with | Invalid_argument("List.for_all2") -> false - ) (cf :: cf.cf_overloads) - with | Not_found -> - gen.gcon.error "No suitable overload for the super call arguments was found" p; cf + let with_params = (mk (TLocal me) me.v_type p) :: with_params in + let cf = + try + (* choose best super function *) + List.iter (fun e -> replace_mono e.etype) with_params; + List.find (fun cf -> + replace_mono cf.cf_type; + let args, _ = get_fun (apply_params cf.cf_params stl cf.cf_type) in + try + List.for_all2 (fun (_,_,t) e -> try + let e_etype = run_follow gen e.etype in + let t = run_follow gen t in + unify e_etype t; true + with Unify_error _ -> + false + ) args with_params + with Invalid_argument("List.for_all2") -> + false + ) (cf :: cf.cf_overloads) + with Not_found -> + gen.gcon.error "No suitable overload for the super call arguments was found" p; cf in { - eexpr = TCall({ - eexpr = TField( - mk_classtype_access sup p, - FStatic(sup,cf)); - etype = apply_params cf.cf_params stl cf.cf_type; - epos = p}, - with_params); + eexpr = TCall( + { + eexpr = TField(ExprBuilder.make_static_this sup p, FStatic(sup,cf)); + etype = apply_params cf.cf_params stl cf.cf_type; + epos = p + }, + with_params + ); etype = gen.gcon.basic.tvoid; epos = p; } (* will create a static counterpart of 'ctor', and replace its contents to a call to the static version*) - let create_static_ctor gen ~empty_ctor_expr cl name ctor = + let create_static_ctor gen ~empty_ctor_expr cl ctor = match Meta.has Meta.SkipCtor ctor.cf_meta with | true -> () | false when is_none ctor.cf_expr -> () | false -> - let static_ctor_name = name ^ "_" ^ (String.concat "_" (fst cl.cl_path)) ^ "_" ^ (snd cl.cl_path) in + let static_ctor_name = make_static_ctor_name gen cl in (* create the static constructor *) let basic = gen.gcon.basic in let ctor_types = List.map (fun (s,t) -> (s, TInst(map_param (get_cl_t t), []))) cl.cl_params in - let me = mk_temp gen "me" (TInst(cl, List.map snd ctor_types)) in + let me = alloc_var "__hx_this" (TInst(cl, List.map snd ctor_types)) in me.v_capture <- true; let fn_args, _ = get_fun ctor.cf_type in @@ -1769,7 +1600,7 @@ struct | TCall (({ eexpr = TConst TSuper } as tsuper), params) -> (try let params = List.map (fun e -> map_expr ~is_first:false e) params in actual_super_call := Some { e with eexpr = TCall(tsuper, [empty_ctor_expr]) }; - replace_super_call gen name cl ctor_params params me e.epos + replace_super_call gen cl ctor_params params me e.epos with | Not_found -> (* last static function was not found *) actual_super_call := Some e; @@ -1819,7 +1650,7 @@ struct eexpr = TCall( { eexpr = TField( - mk_classtype_access cl p, + ExprBuilder.make_static_this cl p, FStatic(cl, static_ctor)); etype = apply_params static_ctor.cf_params (List.map snd cl.cl_params) static_ctor.cf_type; epos = p @@ -1865,587 +1696,556 @@ struct ncf in (* take off createEmpty *) - let all = List.filter (fun cf -> replace_mono cf.cf_type; not (Meta.has Meta.SkipCtor cf.cf_meta)) (ctor :: ctor.cf_overloads) in - let clones = List.map clone all in - match clones with - | [] -> - (* raise Not_found *) - assert false (* should never happen *) - | cf :: [] -> cf - | cf :: overl -> - cf.cf_meta <- (Meta.Overload,[],cf.cf_pos) :: cf.cf_meta; - cf.cf_overloads <- overl; cf - - let rec descends_from_native_or_skipctor cl = - not (is_hxgen (TClassDecl cl)) || Meta.has Meta.SkipCtor cl.cl_meta || match cl.cl_super with - | None -> false - | Some(c,_) -> descends_from_native_or_skipctor c - - let ensure_super_is_first gen cf = - let rec loop e = - match e.eexpr with - | TBlock (b :: block) -> - loop b - | TBlock [] - | TCall({ eexpr = TConst TSuper },_) -> () - | _ -> - gen.gcon.error "Types that derive from a native class must have its super() call as the first statement in the constructor" cf.cf_pos - in - match cf.cf_expr with - | None -> () - | Some e -> Type.iter loop e + let all = List.filter (fun cf -> replace_mono cf.cf_type; not (Meta.has Meta.SkipCtor cf.cf_meta)) (ctor :: ctor.cf_overloads) in + let clones = List.map clone all in + match clones with + | [] -> + (* raise Not_found *) + assert false (* should never happen *) + | cf :: [] -> cf + | cf :: overl -> + cf.cf_meta <- (Meta.Overload,[],cf.cf_pos) :: cf.cf_meta; + cf.cf_overloads <- overl; cf + + let rec descends_from_native_or_skipctor cl = + not (is_hxgen (TClassDecl cl)) || Meta.has Meta.SkipCtor cl.cl_meta || match cl.cl_super with + | None -> false + | Some(c,_) -> descends_from_native_or_skipctor c - (* major restructring made at r6493 *) - let configure ~(empty_ctor_type : t) ~(empty_ctor_expr : texpr) ~supports_ctor_inheritance gen = - set_new_create_empty gen empty_ctor_expr; + let ensure_super_is_first gen cf = + let rec loop e = + match e.eexpr with + | TBlock (b :: block) -> + loop b + | TBlock [] + | TCall({ eexpr = TConst TSuper },_) -> () + | _ -> + gen.gcon.error "Types that derive from a native class must have its super() call as the first statement in the constructor" cf.cf_pos + in + match cf.cf_expr with + | None -> () + | Some e -> Type.iter loop e - let basic = gen.gcon.basic in - let should_change cl = not cl.cl_interface && (not cl.cl_extern || is_hxgen (TClassDecl cl)) && (match cl.cl_kind with KAbstractImpl _ -> false | _ -> true) in - let static_ctor_name = gen.gmk_internal_name "hx" "ctor" in - let msize = List.length gen.gtypes_list in - let processed, empty_ctors = Hashtbl.create msize, Hashtbl.create msize in + let configure ~(empty_ctor_type : t) ~(empty_ctor_expr : texpr) gen = + gen.gtools.r_create_empty <- (fun cl params pos -> mk (TNew(cl,params,[empty_ctor_expr])) (TInst(cl,params)) pos); + let basic = gen.gcon.basic in + let should_change cl = not cl.cl_interface && (not cl.cl_extern || is_hxgen (TClassDecl cl)) && (match cl.cl_kind with KAbstractImpl _ -> false | _ -> true) in + let msize = List.length gen.gtypes_list in + let processed, empty_ctors = Hashtbl.create msize, Hashtbl.create msize in - let rec get_last_empty cl = - try - Hashtbl.find empty_ctors cl.cl_path - with | Not_found -> - match cl.cl_super with - | None -> raise Not_found - | Some (sup,_) -> get_last_empty sup - in - let rec change cl = - match Hashtbl.mem processed cl.cl_path with - | true -> () - | false -> - Hashtbl.add processed cl.cl_path true; - (* make sure we've processed the super types *) - (match cl.cl_super with - | Some (super,_) when should_change super && not (Hashtbl.mem processed super.cl_path) -> - change super - | _ -> ()); - - (* implement static hx_ctor and reimplement constructors *) - (try - let ctor = match cl.cl_constructor with - | Some ctor -> ctor - | None -> try - let sctor, sup, stl = prev_ctor cl (List.map snd cl.cl_params) in - (* we have a previous constructor. if we support inheritance, exit *) - if supports_ctor_inheritance then raise Exit; - (* we'll make constructors that will only call super() *) - let ctor = clone_ctors gen sctor sup stl cl in - cl.cl_constructor <- Some ctor; + let rec get_last_empty cl = + try + Hashtbl.find empty_ctors cl.cl_path + with | Not_found -> + match cl.cl_super with + | None -> raise Not_found + | Some (sup,_) -> get_last_empty sup + in + + let rec change cl = + if not (Hashtbl.mem processed cl.cl_path) then begin + Hashtbl.add processed cl.cl_path true; + + (* make sure we've processed the super types *) + Option.may (fun (super,_) -> if should_change super then change super) cl.cl_super; + + (* implement static hx_ctor and reimplement constructors *) + (try + let ctor = + match cl.cl_constructor with + | Some ctor -> ctor - with | Not_found -> (* create default constructor *) - let ctor = mk_class_field "new" (TFun([], basic.tvoid)) false cl.cl_pos (Method MethNormal) [] in - ctor.cf_expr <- Some - { - eexpr = TFunction { - tf_args = []; - tf_type = basic.tvoid; - tf_expr = { eexpr = TBlock[]; etype = basic.tvoid; epos = cl.cl_pos }; + | None -> + try + let sctor, sup, stl = prev_ctor cl (List.map snd cl.cl_params) in + (* we'll make constructors that will only call super() *) + let ctor = clone_ctors gen sctor sup stl cl in + cl.cl_constructor <- Some ctor; + ctor + with Not_found -> (* create default constructor *) + let ctor = mk_class_field "new" (TFun ([], basic.tvoid)) false cl.cl_pos (Method MethNormal) [] in + ctor.cf_expr <- Some { + eexpr = TFunction { + tf_args = []; + tf_type = basic.tvoid; + tf_expr = mk (TBlock []) basic.tvoid cl.cl_pos; + }; + etype = ctor.cf_type; + epos = ctor.cf_pos; }; - etype = ctor.cf_type; - epos = ctor.cf_pos; - }; - cl.cl_constructor <- Some ctor; - ctor - in - (* now that we made sure we have a constructor, exit if native gen *) - if not (is_hxgen (TClassDecl cl)) || Meta.has Meta.SkipCtor cl.cl_meta then begin - if descends_from_native_or_skipctor cl && is_some cl.cl_super then - List.iter (fun cf -> ensure_super_is_first gen cf) (ctor :: ctor.cf_overloads); - raise Exit - end; - - (* if cl descends from a native class, we cannot use the static constructor strategy *) + cl.cl_constructor <- Some ctor; + ctor + in + (* now that we made sure we have a constructor, exit if native gen *) + if not (is_hxgen (TClassDecl cl)) || Meta.has Meta.SkipCtor cl.cl_meta then begin if descends_from_native_or_skipctor cl && is_some cl.cl_super then - List.iter (fun cf -> ensure_super_is_first gen cf) (ctor :: ctor.cf_overloads) - else - (* now that we have a current ctor, create the static counterparts *) - List.iter (fun cf -> - create_static_ctor gen ~empty_ctor_expr:empty_ctor_expr cl static_ctor_name cf - ) (ctor :: ctor.cf_overloads) - with | Exit ->()); + List.iter (fun cf -> ensure_super_is_first gen cf) (ctor :: ctor.cf_overloads); + raise Exit + end; - (* implement empty ctor *) - (try - (* now that we made sure we have a constructor, exit if native gen *) - if not (is_hxgen (TClassDecl cl)) then raise Exit; - (* get first *) - let empty_type = TFun(["empty",false,empty_ctor_type],basic.tvoid) in - let super = match cl.cl_super with + (* if cl descends from a native class, we cannot use the static constructor strategy *) + if descends_from_native_or_skipctor cl && is_some cl.cl_super then + List.iter (fun cf -> ensure_super_is_first gen cf) (ctor :: ctor.cf_overloads) + else + (* now that we have a current ctor, create the static counterparts *) + List.iter (fun cf -> create_static_ctor gen ~empty_ctor_expr:empty_ctor_expr cl cf) (ctor :: ctor.cf_overloads) + with Exit -> ()); + + (* implement empty ctor *) + (try + (* now that we made sure we have a constructor, exit if native gen *) + if not (is_hxgen (TClassDecl cl)) then raise Exit; + + (* get first *) + let empty_type = TFun (["empty",false,empty_ctor_type],basic.tvoid) in + let super = + match cl.cl_super with | None -> (* implement empty *) [] - | Some (sup,_) -> try - ignore (get_last_empty sup); - if supports_ctor_inheritance && is_none cl.cl_constructor then raise Exit; - [{ - eexpr = TCall( - { eexpr = TConst TSuper; etype = TInst(cl, List.map snd cl.cl_params); epos = cl.cl_pos }, - [ empty_ctor_expr ]); - etype = basic.tvoid; - epos = cl.cl_pos - }] - with | Not_found -> try - (* super type is native: find super constructor with least arguments *) - let sctor, sup, stl = prev_ctor cl (List.map snd cl.cl_params) in - let rec loop remaining (best,n) = - match remaining with - | [] -> best - | cf :: r -> - let args,_ = get_fun cf.cf_type in - if (List.length args) < n then - loop r (cf,List.length args) - else - loop r (best,n) - in - let args,_ = get_fun sctor.cf_type in - let best = loop sctor.cf_overloads (sctor, List.length args) in - let args,_ = get_fun (apply_params sup.cl_params stl best.cf_type) in - [{ - eexpr = TCall( - { eexpr = TConst TSuper; etype = TInst(sup, stl); epos = cl.cl_pos }, - List.map (fun (n,o,t) -> null t cl.cl_pos) args); - etype = basic.tvoid; - epos = cl.cl_pos - }] - with | Not_found -> - (* extends native type, but no ctor found *) - [] - in - let ctor = mk_class_field "new" empty_type false cl.cl_pos (Method MethNormal) [] in - ctor.cf_expr <- Some { - eexpr = TFunction { - tf_type = basic.tvoid; - tf_args = [alloc_var "empty" empty_ctor_type, None]; - tf_expr = { eexpr = TBlock super; etype = basic.tvoid; epos = cl.cl_pos } - }; - etype = empty_type; - epos = cl.cl_pos; + | Some (sup,_) -> + try + ignore (get_last_empty sup); + let esuper = mk (TConst TSuper) (TInst (cl, List.map snd cl.cl_params)) cl.cl_pos in + [mk (TCall (esuper, [empty_ctor_expr])) basic.tvoid cl.cl_pos] + with Not_found -> + try + (* super type is native: find super constructor with least arguments *) + let sctor, sup, stl = prev_ctor cl (List.map snd cl.cl_params) in + let rec loop remaining (best,n) = + match remaining with + | [] -> best + | cf :: r -> + let args,_ = get_fun cf.cf_type in + if (List.length args) < n then + loop r (cf,List.length args) + else + loop r (best,n) + in + let args,_ = get_fun sctor.cf_type in + let best = loop sctor.cf_overloads (sctor, List.length args) in + let args,_ = get_fun (apply_params sup.cl_params stl best.cf_type) in + let esuper = mk (TConst TSuper) (TInst (sup, stl)) cl.cl_pos in + [mk (TCall (esuper, List.map (fun (n,o,t) -> null t cl.cl_pos) args)) basic.tvoid cl.cl_pos] + with Not_found -> + (* extends native type, but no ctor found *) + [] + in + let ctor = mk_class_field "new" empty_type false cl.cl_pos (Method MethNormal) [] in + ctor.cf_expr <- Some { + eexpr = TFunction { + tf_type = basic.tvoid; + tf_args = [alloc_var "empty" empty_ctor_type, None]; + tf_expr = mk (TBlock super) basic.tvoid cl.cl_pos }; - ctor.cf_meta <- [Meta.SkipCtor, [], ctor.cf_pos]; - Hashtbl.add empty_ctors cl.cl_path ctor; - match cl.cl_constructor with - | None -> cl.cl_constructor <- Some ctor - | Some c -> c.cf_overloads <- ctor :: c.cf_overloads - with | Exit -> ()); - - in - let module_filter md = match md with - | TClassDecl cl when should_change cl && not (Hashtbl.mem processed cl.cl_path) -> - change cl; - None - | _ -> None - in - gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) module_filter - - end;; + etype = empty_type; + epos = cl.cl_pos; + }; + ctor.cf_meta <- [Meta.SkipCtor, [], ctor.cf_pos]; + Hashtbl.add empty_ctors cl.cl_path ctor; + match cl.cl_constructor with + | None -> + cl.cl_constructor <- Some ctor + | Some c -> + c.cf_overloads <- ctor :: c.cf_overloads + with Exit -> ()); + end + in - (* ******************************************* *) - (* init function module *) - (* ******************************************* *) + let module_filter md = + (match md with + | TClassDecl cl when should_change cl -> + change cl; + | _ -> + ()); + None + in + gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) module_filter - (* - This module will take proper care of the init function, by taking off all expressions from static vars and putting them - in order in the init function. - It will also initialize dynamic functions, both by putting them in the constructor and in the init function - - depends on: - (syntax) must run before ExprStatement module - (ok) must run before OverloadingCtor module so the constructor can be in the correct place - (syntax) must run before FunctionToClass module - *) +end;; - module InitFunction = - struct +(* ******************************************* *) +(* init function module *) +(* ******************************************* *) +(* + This module will take proper care of the init function, by taking off all expressions from static vars and putting them + in order in the init function. + It will also initialize dynamic functions, both by putting them in the constructor and in the init function - let name = "init_funcs" + depends on: + (syntax) must run before ExprStatement module + (ok) must run before OverloadingConstructor module so the constructor can be in the correct place + (syntax) must run before FunctionToClass module +*) +module InitFunction = +struct + let name = "init_funcs" + let priority = solve_deps name [DBefore OverloadingConstructor.priority] + + let ensure_simple_expr gen e = + let rec iter e = match e.eexpr with + | TConst _ | TLocal _ | TArray _ | TBinop _ + | TField _ | TTypeExpr _ | TParenthesis _ | TCast _ | TMeta _ + | TCall _ | TNew _ | TUnop _ -> + Type.iter iter e + | _ -> + print_endline (debug_expr e); + gen.gcon.error "Expression is too complex for a readonly variable initialization" e.epos + in + iter e - let priority = solve_deps name [DBefore OverloadingConstructor.priority] + let configure gen = + let handle_override_dynfun acc e this field = + let add_expr = ref None in + let v = mk_temp gen ("super_" ^ field) e.etype in + v.v_capture <- true; - let ensure_simple_expr gen e = - let rec iter e = match e.eexpr with - | TConst _ | TLocal _ | TArray _ | TBinop _ - | TField _ | TTypeExpr _ | TParenthesis _ | TCast _ - | TCall _ | TNew _ | TUnop _ -> - Type.iter iter e - | _ -> - print_endline (debug_expr e); - gen.gcon.error "Expression is too complex for a readonly variable initialization" e.epos + let rec loop e = + match e.eexpr with + | TField({ eexpr = TConst(TSuper) }, f) -> + let n = field_name f in + (if n <> field then assert false); + let local = mk_local v e.epos in + (match !add_expr with + | None -> + add_expr := Some { e with eexpr = TVar(v, Some this) } + | Some _ -> ()); + local + | TConst TSuper -> assert false + | _ -> Type.map_expr loop e in - iter e - - let configure gen should_handle_dynamic_functions readonly_support = - let handle_override_dynfun acc e this field = - let add_expr = ref None in - let v = mk_temp gen ("super_" ^ field) e.etype in - v.v_capture <- true; + let e = loop e in - let rec loop e = - match e.eexpr with - | TField({ eexpr = TConst(TSuper) }, f) -> - let n = field_name f in - (if n <> field then assert false); - let local = mk_local v e.epos in - (match !add_expr with - | None -> - add_expr := Some { e with eexpr = TVar(v, Some this) } - | Some _ -> ()); - local - | TConst TSuper -> assert false - | _ -> Type.map_expr loop e - in - let e = loop e in + match !add_expr with + | None -> e :: acc + | Some add_expr -> add_expr :: e :: acc + in - match !add_expr with - | None -> e :: acc - | Some add_expr -> add_expr :: e :: acc + let handle_class cl = + let init = match cl.cl_init with + | None -> [] + | Some i -> [i] in - - let handle_class cl = - let init = match cl.cl_init with - | None -> [] - | Some i -> [i] - in - let init = List.fold_left (fun acc cf -> - match cf.cf_kind, should_handle_dynamic_functions with - | (Var v, _) when Meta.has Meta.ReadOnly cf.cf_meta && readonly_support -> - if v.v_write <> AccNever && not (Meta.has Meta.CoreApi cl.cl_meta) then gen.gcon.warning "@:readOnly variable declared without `never` setter modifier" cf.cf_pos; - (match cf.cf_expr with - | None -> gen.gcon.warning "Uninitialized readonly variable" cf.cf_pos; acc - | Some e -> ensure_simple_expr gen e; acc) - | (Var _, _) - | (Method (MethDynamic), true) when not (Type.is_extern_field cf) -> + let init = List.fold_left (fun acc cf -> + match cf.cf_kind with + | Var v when Meta.has Meta.ReadOnly cf.cf_meta -> + if v.v_write <> AccNever && not (Meta.has Meta.CoreApi cl.cl_meta) then gen.gcon.warning "@:readOnly variable declared without `never` setter modifier" cf.cf_pos; (match cf.cf_expr with - | Some e -> - (match cf.cf_params with - | [] -> - let var = { eexpr = TField(mk_classtype_access cl cf.cf_pos, FStatic(cl,cf)); etype = cf.cf_type; epos = cf.cf_pos } in - let ret = ({ eexpr = TBinop(Ast.OpAssign, var, e); etype = cf.cf_type; epos = cf.cf_pos; }) in - cf.cf_expr <- None; - - ret :: acc - | _ -> - let params = List.map (fun _ -> t_dynamic) cf.cf_params in - let fn = apply_params cf.cf_params params in - let var = { eexpr = TField(mk_classtype_access cl cf.cf_pos, FStatic(cl,cf)); etype = fn cf.cf_type; epos = cf.cf_pos } in - let rec change_expr e = - Type.map_expr_type (change_expr) fn (fun v -> v.v_type <- fn v.v_type; v) e - in - - let ret = ({ eexpr = TBinop(Ast.OpAssign, var, change_expr e); etype = fn cf.cf_type; epos = cf.cf_pos; }) in - cf.cf_expr <- None; - ret :: acc - ) - | None -> acc) - | _ -> acc - ) init cl.cl_ordered_statics - in - let init = List.rev init in - (match init with - | [] -> cl.cl_init <- None - | _ -> cl.cl_init <- Some { eexpr = TBlock(init); epos = cl.cl_pos; etype = gen.gcon.basic.tvoid; }); - - (* FIXME: find a way to tell OverloadingCtors to execute this code even with empty constructors *) - if should_handle_dynamic_functions then begin - let vars, funs = List.fold_left (fun (acc_vars,acc_funs) cf -> - match cf.cf_kind with - | Var v when Meta.has Meta.ReadOnly cf.cf_meta && readonly_support -> - if v.v_write <> AccNever && not (Meta.has Meta.CoreApi cl.cl_meta) then gen.gcon.warning "@:readOnly variable declared without `never` setter modifier" cf.cf_pos; - (match cf.cf_expr with - | None -> (acc_vars,acc_funs) - | Some e -> ensure_simple_expr gen e; (acc_vars,acc_funs)) - | Var _ - | Method(MethDynamic) -> - let is_var = match cf.cf_kind with | Var _ -> true | _ -> false in - (match cf.cf_expr, cf.cf_params with - | Some e, [] -> - let var = { eexpr = TField({ eexpr = TConst(TThis); epos = cf.cf_pos; etype = TInst(cl, List.map snd cl.cl_params); }, FInstance(cl, List.map snd cl.cl_params, cf)); etype = cf.cf_type; epos = cf.cf_pos } in + | None -> gen.gcon.warning "Uninitialized readonly variable" cf.cf_pos; acc + | Some e -> ensure_simple_expr gen e; acc) + | Var _ + | Method MethDynamic when not (Type.is_extern_field cf) -> + (match cf.cf_expr with + | Some e -> + (match cf.cf_params with + | [] -> + let var = { eexpr = TField(ExprBuilder.make_static_this cl cf.cf_pos, FStatic(cl,cf)); etype = cf.cf_type; epos = cf.cf_pos } in let ret = ({ eexpr = TBinop(Ast.OpAssign, var, e); etype = cf.cf_type; epos = cf.cf_pos; }) in cf.cf_expr <- None; - let is_override = List.memq cf cl.cl_overrides in - - if is_override then begin - cl.cl_ordered_fields <- List.filter (fun f -> f.cf_name <> cf.cf_name) cl.cl_ordered_fields; - cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields; - acc_vars, handle_override_dynfun acc_funs ret var cf.cf_name - end else if is_var then - ret :: acc_vars, acc_funs - else - acc_vars, ret :: acc_funs - | Some e, _ -> + + ret :: acc + | _ -> let params = List.map (fun _ -> t_dynamic) cf.cf_params in let fn = apply_params cf.cf_params params in - let var = { eexpr = TField({ eexpr = TConst(TThis); epos = cf.cf_pos; etype = TInst(cl, List.map snd cl.cl_params); }, FInstance(cl, List.map snd cl.cl_params, cf)); etype = cf.cf_type; epos = cf.cf_pos } in + let var = { eexpr = TField(ExprBuilder.make_static_this cl cf.cf_pos, FStatic(cl,cf)); etype = fn cf.cf_type; epos = cf.cf_pos } in let rec change_expr e = Type.map_expr_type (change_expr) fn (fun v -> v.v_type <- fn v.v_type; v) e in let ret = ({ eexpr = TBinop(Ast.OpAssign, var, change_expr e); etype = fn cf.cf_type; epos = cf.cf_pos; }) in cf.cf_expr <- None; - let is_override = List.memq cf cl.cl_overrides in - - if is_override then begin - cl.cl_ordered_fields <- List.filter (fun f -> f.cf_name <> cf.cf_name) cl.cl_ordered_fields; - cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields; - acc_vars, handle_override_dynfun acc_funs ret var cf.cf_name - end else if is_var then - ret :: acc_vars, acc_funs - else - acc_vars, ret :: acc_funs - | None, _ -> acc_vars,acc_funs) - | _ -> acc_vars,acc_funs - ) ([],[]) cl.cl_ordered_fields - in - (* let vars = List.rev vars in *) - (* let funs = List.rev funs in *) - (* see if there is any *) - (match vars, funs with - | [], [] -> () - | _ -> - (* if there is, we need to find the constructor *) - let ctors = match cl.cl_constructor with - | Some ctor -> ctor - | None -> try - let sctor, sup, stl = OverloadingConstructor.prev_ctor cl (List.map snd cl.cl_params) in - let ctor = OverloadingConstructor.clone_ctors gen sctor sup stl cl in - cl.cl_constructor <- Some ctor; - ctor - with | Not_found -> - let basic = gen.gcon.basic in - let ctor = mk_class_field "new" (TFun([], basic.tvoid)) false cl.cl_pos (Method MethNormal) [] in - ctor.cf_expr <- Some - { - eexpr = TFunction { - tf_args = []; - tf_type = basic.tvoid; - tf_expr = { eexpr = TBlock[]; etype = basic.tvoid; epos = cl.cl_pos }; - }; - etype = ctor.cf_type; - epos = ctor.cf_pos; - }; - cl.cl_constructor <- Some ctor; - ctor - in - - let process ctor = - let func = match ctor.cf_expr with - | Some({eexpr = TFunction(tf)} as e) -> - let rec add_fn e = match e.eexpr with - | TBlock(hd :: tl) -> (match hd.eexpr with - | TCall({ eexpr = TConst TSuper }, _) -> - if not (OverloadingConstructor.descends_from_native_or_skipctor cl) then - { e with eexpr = TBlock(vars @ (hd :: (funs @ tl))) } - else - { e with eexpr = TBlock(hd :: (vars @ funs @ tl)) } - | TBlock(_) -> - { e with eexpr = TBlock( (add_fn hd) :: tl ) } - | _ -> - { e with eexpr = TBlock( vars @ funs @ (hd :: tl) ) }) - | _ -> Type.concat { e with eexpr = TBlock(vars @ funs) } e - in - let tf_expr = add_fn (mk_block tf.tf_expr) in - { e with eexpr = TFunction({ tf with tf_expr = tf_expr }) } - | _ -> assert false - in - ctor.cf_expr <- Some(func) - in - List.iter process (ctors :: ctors.cf_overloads) - ) - end - + ret :: acc + ) + | None -> acc) + | _ -> acc + ) init cl.cl_ordered_statics in + let init = List.rev init in + (match init with + | [] -> cl.cl_init <- None + | _ -> cl.cl_init <- Some { eexpr = TBlock(init); epos = cl.cl_pos; etype = gen.gcon.basic.tvoid; }); + + (* FIXME: find a way to tell OverloadingConstructor to execute this code even with empty constructors *) + let vars, funs = List.fold_left (fun (acc_vars,acc_funs) cf -> + match cf.cf_kind with + | Var v when Meta.has Meta.ReadOnly cf.cf_meta -> + if v.v_write <> AccNever && not (Meta.has Meta.CoreApi cl.cl_meta) then gen.gcon.warning "@:readOnly variable declared without `never` setter modifier" cf.cf_pos; + (match cf.cf_expr with + | None -> (acc_vars,acc_funs) + | Some e -> ensure_simple_expr gen e; (acc_vars,acc_funs)) + | Var _ + | Method MethDynamic -> + let is_var = match cf.cf_kind with | Var _ -> true | _ -> false in + (match cf.cf_expr, cf.cf_params with + | Some e, [] -> + let var = { eexpr = TField({ eexpr = TConst(TThis); epos = cf.cf_pos; etype = TInst(cl, List.map snd cl.cl_params); }, FInstance(cl, List.map snd cl.cl_params, cf)); etype = cf.cf_type; epos = cf.cf_pos } in + let ret = ({ eexpr = TBinop(Ast.OpAssign, var, e); etype = cf.cf_type; epos = cf.cf_pos; }) in + cf.cf_expr <- None; + let is_override = List.memq cf cl.cl_overrides in + + if is_override then begin + cl.cl_ordered_fields <- List.filter (fun f -> f.cf_name <> cf.cf_name) cl.cl_ordered_fields; + cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields; + acc_vars, handle_override_dynfun acc_funs ret var cf.cf_name + end else if is_var then + ret :: acc_vars, acc_funs + else + acc_vars, ret :: acc_funs + | Some e, _ -> + let params = List.map (fun _ -> t_dynamic) cf.cf_params in + let fn = apply_params cf.cf_params params in + let var = { eexpr = TField({ eexpr = TConst(TThis); epos = cf.cf_pos; etype = TInst(cl, List.map snd cl.cl_params); }, FInstance(cl, List.map snd cl.cl_params, cf)); etype = cf.cf_type; epos = cf.cf_pos } in + let rec change_expr e = + Type.map_expr_type (change_expr) fn (fun v -> v.v_type <- fn v.v_type; v) e + in - let mod_filter = function - | TClassDecl cl -> (if not cl.cl_extern then handle_class cl); None - | _ -> None in - - gen.gmodule_filters#add ~name:"init_funcs" ~priority:(PCustom priority) mod_filter - - end;; + let ret = ({ eexpr = TBinop(Ast.OpAssign, var, change_expr e); etype = fn cf.cf_type; epos = cf.cf_pos; }) in + cf.cf_expr <- None; + let is_override = List.memq cf cl.cl_overrides in - (* ******************************************* *) - (* Dynamic Binop/Unop handler *) - (* ******************************************* *) + if is_override then begin + cl.cl_ordered_fields <- List.filter (fun f -> f.cf_name <> cf.cf_name) cl.cl_ordered_fields; + cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields; + acc_vars, handle_override_dynfun acc_funs ret var cf.cf_name + end else if is_var then + ret :: acc_vars, acc_funs + else + acc_vars, ret :: acc_funs + | None, _ -> acc_vars,acc_funs) + | _ -> acc_vars,acc_funs + ) ([],[]) cl.cl_ordered_fields + in + (* let vars = List.rev vars in *) + (* let funs = List.rev funs in *) + (* see if there is any *) + (match vars, funs with + | [], [] -> () + | _ -> + (* if there is, we need to find the constructor *) + let ctors = match cl.cl_constructor with + | Some ctor -> ctor + | None -> try + let sctor, sup, stl = OverloadingConstructor.prev_ctor cl (List.map snd cl.cl_params) in + let ctor = OverloadingConstructor.clone_ctors gen sctor sup stl cl in + cl.cl_constructor <- Some ctor; + ctor + with | Not_found -> + let basic = gen.gcon.basic in + let ctor = mk_class_field "new" (TFun([], basic.tvoid)) false cl.cl_pos (Method MethNormal) [] in + ctor.cf_expr <- Some + { + eexpr = TFunction { + tf_args = []; + tf_type = basic.tvoid; + tf_expr = { eexpr = TBlock[]; etype = basic.tvoid; epos = cl.cl_pos }; + }; + etype = ctor.cf_type; + epos = ctor.cf_pos; + }; + cl.cl_constructor <- Some ctor; + ctor + in - (* - On some languages there is limited support for operations on - dynamic variables, so those operations must be changed. + let process ctor = + let func = match ctor.cf_expr with + | Some({eexpr = TFunction(tf)} as e) -> + let rec add_fn e = match e.eexpr with + | TBlock(hd :: tl) -> (match hd.eexpr with + | TCall({ eexpr = TConst TSuper }, _) -> + if not (OverloadingConstructor.descends_from_native_or_skipctor cl) then + { e with eexpr = TBlock(vars @ (hd :: (funs @ tl))) } + else + { e with eexpr = TBlock(hd :: (vars @ funs @ tl)) } + | TBlock(_) -> + { e with eexpr = TBlock( (add_fn hd) :: tl ) } + | _ -> + { e with eexpr = TBlock( vars @ funs @ (hd :: tl) ) }) + | _ -> Type.concat { e with eexpr = TBlock(vars @ funs) } e + in + let tf_expr = add_fn (mk_block tf.tf_expr) in + { e with eexpr = TFunction({ tf with tf_expr = tf_expr }) } + | _ -> assert false + in + ctor.cf_expr <- Some(func) + in + List.iter process (ctors :: ctors.cf_overloads) + ) + in - There are 5 types of binary operators: - 1 - can take any variable and returns a bool (== and !=) - 2 - can take either a string, or a number and returns either a bool or the underlying type ( >, < for bool and + for returning its type) - 3 - take numbers and return a number ( *, /, ...) - 4 - take ints and return an int (bit manipulation) - 5 - take a bool and returns a bool ( &&, || ...) + let mod_filter = function + | TClassDecl cl -> (if not cl.cl_extern then handle_class cl); None + | _ -> None in - On the default implementation, type 1 and the plus function will be handled with a function call; - Type 2 will be handled with the parameter "compare_handler", which will do something like Reflect.compare(x1, x2); - Types 3, 4 and 5 will perform a cast to double, int and bool, which will then be handled normally by the platform + gen.gmodule_filters#add ~name:"init_funcs" ~priority:(PCustom priority) mod_filter - Unary operators are the most difficult to handle correctly. - With unary operators, there are 2 types: +end;; - 1 - can take a number, changes and returns the result (++, --, ~) - 2 - can take a number (-) or bool (!), and returns the result - The first case is much trickier, because it doesn't seem a good idea to change any variable to double just because it is dynamic, - but this is how we will handle right now. - something like that: +(* ******************************************* *) +(* Dynamic Binop/Unop handler *) +(* ******************************************* *) +(* + On some languages there is limited support for operations on + dynamic variables, so those operations must be changed. - var x:Dynamic = 10; - x++; + There are 5 types of binary operators: + 1 - can take any variable and returns a bool (== and !=) + 2 - can take either a string, or a number and returns either a bool or the underlying type ( >, < for bool and + for returning its type) + 3 - take numbers and return a number ( *, /, ...) + 4 - take ints and return an int (bit manipulation) + 5 - take a bool and returns a bool ( &&, || ...) - will be: - object x = 10; - x = ((IConvertible)x).ToDouble(null) + 1; + On the default implementation, type 1 and the plus function will be handled with a function call; + Type 2 will be handled with the parameter "compare_handler", which will do something like Reflect.compare(x1, x2); + Types 3, 4 and 5 will perform a cast to double, int and bool, which will then be handled normally by the platform - depends on: - (syntax) must run before expression/statment normalization because it may generate complex expressions - must run before OverloadingCtor due to later priority conflicts. Since ExpressionUnwrap is only - defined afterwards, we will set this value with absolute values - *) + Unary operators are the most difficult to handle correctly. + With unary operators, there are 2 types: - module DynamicOperators = - struct + 1 - can take a number, changes and returns the result (++, --, ~) + 2 - can take a number (-) or bool (!), and returns the result - let name = "dyn_ops" + The first case is much trickier, because it doesn't seem a good idea to change any variable to double just because it is dynamic, + but this is how we will handle right now. + something like that: - let priority = 0.0 + var x:Dynamic = 10; + x++; - let priority_as_synf = 100.0 (*solve_deps name [DBefore ExpressionUnwrap.priority]*) + will be: + object x = 10; + x = ((IConvertible)x).ToDouble(null) + 1; - let abstract_implementation gen ?(handle_strings = true) (should_change:texpr->bool) (equals_handler:texpr->texpr->texpr) (dyn_plus_handler:texpr->texpr->texpr->texpr) (compare_handler:texpr->texpr->texpr) = + depends on: + (syntax) must run before expression/statment normalization because it may generate complex expressions + must run before OverloadingConstructor due to later priority conflicts. Since ExpressionUnwrap is only + defined afterwards, we will set this value with absolute values +*) +module DynamicOperators = +struct + let name = "dyn_ops" + let priority = 0.0 + let configure gen ?(handle_strings = true) (should_change:texpr->bool) (equals_handler:texpr->texpr->texpr) (dyn_plus_handler:texpr->texpr->texpr->texpr) (compare_handler:texpr->texpr->texpr) = + let get_etype_one e = + if like_int e.etype then + ExprBuilder.make_int gen.gcon 1 e.epos + else + ExprBuilder.make_float gen.gcon "1.0" e.epos + in - let get_etype_one e = - if like_int e.etype then - (gen.gcon.basic.tint, { eexpr = TConst(TInt(Int32.one)); etype = gen.gcon.basic.tint; epos = e.epos }) - else - (gen.gcon.basic.tfloat, { eexpr = TConst(TFloat("1.0")); etype = gen.gcon.basic.tfloat; epos = e.epos }) - in + let basic = gen.gcon.basic in - let basic = gen.gcon.basic in + let rec run e = + match e.eexpr with + | TBinop (OpAssignOp op, e1, e2) when should_change e -> (* e1 will never contain another TBinop *) + (match e1.eexpr with + | TLocal _ -> + mk_paren { e with eexpr = TBinop(OpAssign, e1, run { e with eexpr = TBinop(op, e1, e2) }) } + | TField _ | TArray _ -> + let eleft, rest = match e1.eexpr with + | TField(ef, f) -> + let v = mk_temp gen "dynop" ef.etype in + { e1 with eexpr = TField(mk_local v ef.epos, f) }, [ { eexpr = TVar(v,Some (run ef)); etype = basic.tvoid; epos = ef.epos } ] + | TArray(e1a, e2a) -> + let v = mk_temp gen "dynop" e1a.etype in + let v2 = mk_temp gen "dynopi" e2a.etype in + { e1 with eexpr = TArray(mk_local v e1a.epos, mk_local v2 e2a.epos) }, [ + { eexpr = TVar(v,Some (run e1a)); etype = basic.tvoid; epos = e1.epos }; + { eexpr = TVar(v2, Some (run e2a)); etype = basic.tvoid; epos = e1.epos } + ] + | _ -> assert false + in + { e with + eexpr = TBlock (rest @ [ { e with eexpr = TBinop(OpAssign, eleft, run { e with eexpr = TBinop(op, eleft, e2) }) } ]); + } + | _ -> + assert false + ) - let rec run e = - match e.eexpr with - | TBinop (OpAssignOp op, e1, e2) when should_change e -> (* e1 will never contain another TBinop *) - (match e1.eexpr with - | TLocal _ -> - mk_paren { e with eexpr = TBinop(OpAssign, e1, run { e with eexpr = TBinop(op, e1, e2) }) } - | TField _ | TArray _ -> - let eleft, rest = match e1.eexpr with - | TField(ef, f) -> - let v = mk_temp gen "dynop" ef.etype in - { e1 with eexpr = TField(mk_local v ef.epos, f) }, [ { eexpr = TVar(v,Some (run ef)); etype = basic.tvoid; epos = ef.epos } ] - | TArray(e1a, e2a) -> - let v = mk_temp gen "dynop" e1a.etype in - let v2 = mk_temp gen "dynopi" e2a.etype in - { e1 with eexpr = TArray(mk_local v e1a.epos, mk_local v2 e2a.epos) }, [ - { eexpr = TVar(v,Some (run e1a)); etype = basic.tvoid; epos = e1.epos }; - { eexpr = TVar(v2, Some (run e2a)); etype = basic.tvoid; epos = e1.epos } - ] - | _ -> assert false - in - { e with - eexpr = TBlock (rest @ [ { e with eexpr = TBinop(OpAssign, eleft, run { e with eexpr = TBinop(op, eleft, e2) }) } ]); - } + | TBinop (OpAssign, e1, e2) + | TBinop (OpInterval, e1, e2) -> Type.map_expr run e + | TBinop (op, e1, e2) when should_change e-> + (match op with + | OpEq -> (* type 1 *) + equals_handler (run e1) (run e2) + | OpNotEq -> (* != -> !equals() *) + mk_paren { eexpr = TUnop(Ast.Not, Prefix, (equals_handler (run e1) (run e2))); etype = gen.gcon.basic.tbool; epos = e.epos } + | OpAdd -> + if handle_strings && (is_string e.etype || is_string e1.etype || is_string e2.etype) then + { e with eexpr = TBinop(op, mk_cast gen.gcon.basic.tstring (run e1), mk_cast gen.gcon.basic.tstring (run e2)) } + else + dyn_plus_handler e (run e1) (run e2) + | OpGt | OpGte | OpLt | OpLte -> (* type 2 *) + { eexpr = TBinop(op, compare_handler (run e1) (run e2), { eexpr = TConst(TInt(Int32.zero)); etype = gen.gcon.basic.tint; epos = e.epos} ); etype = gen.gcon.basic.tbool; epos = e.epos } + | OpMult | OpDiv | OpSub | OpMod -> (* always cast everything to double *) + let etype = (get_etype_one e).etype in + { e with eexpr = TBinop(op, mk_cast etype (run e1), mk_cast etype (run e2)) } + | OpBoolAnd | OpBoolOr -> + { e with eexpr = TBinop(op, mk_cast gen.gcon.basic.tbool (run e1), mk_cast gen.gcon.basic.tbool (run e2)) } + | OpAnd | OpOr | OpXor | OpShl | OpShr | OpUShr -> + { e with eexpr = TBinop(op, mk_cast gen.gcon.basic.tint (run e1), mk_cast gen.gcon.basic.tint (run e2)) } + | OpAssign | OpAssignOp _ | OpInterval | OpArrow -> assert false) + | TUnop (Increment as op, flag, e1) + | TUnop (Decrement as op, flag, e1) when should_change e -> + (* + some naming definitions: + * ret => the returning variable + * _g => the get body + * getvar => the get variable expr + + This will work like this: + - if e1 is a TField, set _g = get body, getvar = (get body).varname + - if Prefix, return getvar = getvar + 1.0 + - if Postfix, set ret = getvar; getvar = getvar + 1.0; ret; + *) + let one = get_etype_one e in + let etype = one.etype in + let op = (match op with Increment -> OpAdd | Decrement -> OpSub | _ -> assert false) in + + let var, getvar = + match e1.eexpr with + | TField(fexpr, field) -> + let tmp = mk_temp gen "getvar" fexpr.etype in + let var = { eexpr = TVar(tmp, Some(run fexpr)); etype = gen.gcon.basic.tvoid; epos = e.epos } in + (Some var, { eexpr = TField( { fexpr with eexpr = TLocal(tmp) }, field); etype = etype; epos = e1.epos }) | _ -> - assert false - ) - - | TBinop (OpAssign, e1, e2) - | TBinop (OpInterval, e1, e2) -> Type.map_expr run e - | TBinop (op, e1, e2) when should_change e-> - (match op with - | OpEq -> (* type 1 *) - equals_handler (run e1) (run e2) - | OpNotEq -> (* != -> !equals() *) - mk_paren { eexpr = TUnop(Ast.Not, Prefix, (equals_handler (run e1) (run e2))); etype = gen.gcon.basic.tbool; epos = e.epos } - | OpAdd -> - if handle_strings && (is_string e.etype || is_string e1.etype || is_string e2.etype) then - { e with eexpr = TBinop(op, mk_cast gen.gcon.basic.tstring (run e1), mk_cast gen.gcon.basic.tstring (run e2)) } - else - dyn_plus_handler e (run e1) (run e2) - | OpGt | OpGte | OpLt | OpLte -> (* type 2 *) - { eexpr = TBinop(op, compare_handler (run e1) (run e2), { eexpr = TConst(TInt(Int32.zero)); etype = gen.gcon.basic.tint; epos = e.epos} ); etype = gen.gcon.basic.tbool; epos = e.epos } - | OpMult | OpDiv | OpSub | OpMod -> (* always cast everything to double *) - let etype, _ = get_etype_one e in - { e with eexpr = TBinop(op, mk_cast etype (run e1), mk_cast etype (run e2)) } - | OpBoolAnd | OpBoolOr -> - { e with eexpr = TBinop(op, mk_cast gen.gcon.basic.tbool (run e1), mk_cast gen.gcon.basic.tbool (run e2)) } - | OpAnd | OpOr | OpXor | OpShl | OpShr | OpUShr -> - { e with eexpr = TBinop(op, mk_cast gen.gcon.basic.tint (run e1), mk_cast gen.gcon.basic.tint (run e2)) } - | OpAssign | OpAssignOp _ | OpInterval | OpArrow -> assert false) - | TUnop (Increment as op, flag, e1) - | TUnop (Decrement as op, flag, e1) when should_change e -> - (* - some naming definitions: - * ret => the returning variable - * _g => the get body - * getvar => the get variable expr - - This will work like this: - - if e1 is a TField, set _g = get body, getvar = (get body).varname - - if Prefix, return getvar = getvar + 1.0 - - if Postfix, set ret = getvar; getvar = getvar + 1.0; ret; - *) - let etype, one = get_etype_one e in - let op = (match op with Increment -> OpAdd | Decrement -> OpSub | _ -> assert false) in - - let var, getvar = - match e1.eexpr with - | TField(fexpr, field) -> - let tmp = mk_temp gen "getvar" fexpr.etype in - let var = { eexpr = TVar(tmp, Some(run fexpr)); etype = gen.gcon.basic.tvoid; epos = e.epos } in - (Some var, { eexpr = TField( { fexpr with eexpr = TLocal(tmp) }, field); etype = etype; epos = e1.epos }) - | _ -> - (None, e1) - in + (None, e1) + in - (match flag with - | Prefix -> - let block = (match var with | Some e -> [e] | None -> []) @ - [ - mk_cast etype { e with eexpr = TBinop(OpAssign, getvar,{ eexpr = TBinop(op, mk_cast etype getvar, one); etype = etype; epos = e.epos }); etype = getvar.etype; } - ] - in - { eexpr = TBlock(block); etype = etype; epos = e.epos } - | Postfix -> - let ret = mk_temp gen "ret" etype in - let vars = (match var with Some e -> [e] | None -> []) @ [{ eexpr = TVar(ret, Some (mk_cast etype getvar)); etype = gen.gcon.basic.tvoid; epos = e.epos }] in - let retlocal = { eexpr = TLocal(ret); etype = etype; epos = e.epos } in - let block = vars @ - [ - { e with eexpr = TBinop(OpAssign, getvar, { eexpr = TBinop(op, retlocal, one); etype = getvar.etype; epos = e.epos }) }; - retlocal - ] in + (match flag with + | Prefix -> + let block = (match var with | Some e -> [e] | None -> []) @ + [ + mk_cast etype { e with eexpr = TBinop(OpAssign, getvar,{ eexpr = TBinop(op, mk_cast etype getvar, one); etype = etype; epos = e.epos }); etype = getvar.etype; } + ] + in { eexpr = TBlock(block); etype = etype; epos = e.epos } - ) - | TUnop (op, flag, e1) when should_change e -> - let etype = match op with | Not -> gen.gcon.basic.tbool | _ -> gen.gcon.basic.tint in - mk_paren { eexpr = TUnop(op, flag, mk_cast etype (run e1)); etype = etype; epos = e.epos } - | _ -> Type.map_expr run e + | Postfix -> + let ret = mk_temp gen "ret" etype in + let vars = (match var with Some e -> [e] | None -> []) @ [{ eexpr = TVar(ret, Some (mk_cast etype getvar)); etype = gen.gcon.basic.tvoid; epos = e.epos }] in + let retlocal = { eexpr = TLocal(ret); etype = etype; epos = e.epos } in + let block = vars @ + [ + { e with eexpr = TBinop(OpAssign, getvar, { eexpr = TBinop(op, retlocal, one); etype = getvar.etype; epos = e.epos }) }; + retlocal + ] in + { eexpr = TBlock(block); etype = etype; epos = e.epos } + ) + | TUnop (op, flag, e1) when should_change e -> + let etype = match op with | Not -> gen.gcon.basic.tbool | _ -> gen.gcon.basic.tint in + mk_paren { eexpr = TUnop(op, flag, mk_cast etype (run e1)); etype = etype; epos = e.epos } + | _ -> Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gexpr_filters#add ~name:"dyn_ops" ~priority:(PCustom priority) map - - let configure_as_synf gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in - gen.gexpr_filters#add ~name:"dyn_ops" ~priority:(PCustom priority_as_synf) map - end;; + (* ******************************************* *) (* Dynamic Field Access *) (* ******************************************* *) - (* This module will filter every dynamic field access in haxe. @@ -2470,117 +2270,85 @@ end;; var m = Math; for (i in 0...1000) Math.cos(10); - (addendum:) - configure_generate_classes will already take care of generating the reflection-enabled class fields and calling abstract_implementation - with the right arguments. - - Also - depends on: (ok) must run AFTER Binop/Unop handler - so Unops / Binops are already unrolled *) - module DynamicFieldAccess = struct - let name = "dynamic_field_access" - let priority = solve_deps name [DAfter DynamicOperators.priority] - let priority_as_synf = solve_deps name [DAfter DynamicOperators.priority_as_synf] - (* is_dynamic (expr) (field_access_expr) (field) : a function that indicates if the field access should be changed - change_expr (expr) (field_access_expr) (field) (setting expr) (is_unsafe) : changes the expression call_expr (expr) (field_access_expr) (field) (call_params) : changes a call expression *) - let abstract_implementation gen (is_dynamic:texpr->texpr->Type.tfield_access->bool) (change_expr:texpr->texpr->string->texpr option->bool->texpr) (call_expr:texpr->texpr->string->texpr list->texpr) = + let configure gen (is_dynamic:texpr->texpr->Type.tfield_access->bool) (change_expr:texpr->texpr->string->texpr option->bool->texpr) (call_expr:texpr->texpr->string->texpr list->texpr) = let rec run e = match e.eexpr with - (* class types *) - | TField(fexpr, f) when is_some (anon_class fexpr.etype) -> - let decl = get (anon_class fexpr.etype) in - let name = field_name f in - (try - match decl with - | TClassDecl cl -> - let cf = PMap.find name cl.cl_statics in - { e with eexpr = TField({ fexpr with eexpr = TTypeExpr decl }, FStatic(cl, cf)) } - | TEnumDecl en -> - let ef = PMap.find name en.e_constrs in - { e with eexpr = TField({ fexpr with eexpr = TTypeExpr decl }, FEnum(en, ef)) } - | TAbstractDecl _ -> (* abstracts don't have TFields *) assert false - | TTypeDecl _ -> (* anon_class doesn't return TTypeDecl *) assert false - with - | Not_found -> match f with - | FStatic(cl,cf) when Meta.has Meta.Extern cf.cf_meta -> - { e with eexpr = TField({ fexpr with eexpr = TTypeExpr decl }, FStatic(cl, cf)) } - | _ -> - change_expr e { fexpr with eexpr = TTypeExpr decl } (field_name f) None true + (* class types *) + | TField(fexpr, f) when is_some (anon_class fexpr.etype) -> + let decl = get (anon_class fexpr.etype) in + let name = field_name f in + (try + match decl with + | TClassDecl cl -> + let cf = PMap.find name cl.cl_statics in + { e with eexpr = TField({ fexpr with eexpr = TTypeExpr decl }, FStatic(cl, cf)) } + | TEnumDecl en -> + let ef = PMap.find name en.e_constrs in + { e with eexpr = TField({ fexpr with eexpr = TTypeExpr decl }, FEnum(en, ef)) } + | TAbstractDecl _ -> (* abstracts don't have TFields *) assert false + | TTypeDecl _ -> (* anon_class doesn't return TTypeDecl *) assert false + with + | Not_found -> match f with + | FStatic(cl,cf) when Meta.has Meta.Extern cf.cf_meta -> + { e with eexpr = TField({ fexpr with eexpr = TTypeExpr decl }, FStatic(cl, cf)) } + | _ -> + change_expr e { fexpr with eexpr = TTypeExpr decl } (field_name f) None true + ) + | TField(fexpr, f) when is_dynamic e fexpr (f) -> + change_expr e (run fexpr) (field_name f) None true + | TCall( + { eexpr = TField(_, FStatic({ cl_path = ([], "Reflect") }, { cf_name = "field" })) } , + [obj; { eexpr = TConst(TString(field)) }] + ) -> + let t = match gen.greal_type obj.etype with + | TDynamic _ | TAnon _ | TMono _ -> t_dynamic + | t -> t + in + change_expr (mk_field_access gen { obj with etype = t } field obj.epos) (run obj) field None false + | TCall( + { eexpr = TField(_, FStatic({ cl_path = ([], "Reflect") }, { cf_name = "setField" } )) }, + [obj; { eexpr = TConst(TString(field)) }; evalue] + ) -> + change_expr (mk_field_access gen obj field obj.epos) (run obj) field (Some (run evalue)) false + | TBinop(OpAssign, ({eexpr = TField(fexpr, f)}), evalue) when is_dynamic e fexpr (f) -> + change_expr e (run fexpr) (field_name f) (Some (run evalue)) true + | TBinop(OpAssign, { eexpr = TField(fexpr, f) }, evalue) -> + (match field_access_esp gen fexpr.etype (f) with + | FClassField(_,_,_,cf,false,t,_) when (try PMap.find cf.cf_name gen.gbase_class_fields == cf with Not_found -> false) -> + change_expr e (run fexpr) (field_name f) (Some (run evalue)) true + | _ -> Type.map_expr run e ) - | TField(fexpr, f) when is_dynamic e fexpr (f) -> - change_expr e (run fexpr) (field_name f) None true - | TCall( - { eexpr = TField(_, FStatic({ cl_path = ([], "Reflect") }, { cf_name = "field" })) } , - [obj; { eexpr = TConst(TString(field)) }] - ) -> - let t = match gen.greal_type obj.etype with - | TDynamic _ | TAnon _ | TMono _ -> t_dynamic - | t -> t - in - change_expr (mk_field_access gen { obj with etype = t } field obj.epos) (run obj) field None false - | TCall( - { eexpr = TField(_, FStatic({ cl_path = ([], "Reflect") }, { cf_name = "setField" } )) }, - [obj; { eexpr = TConst(TString(field)) }; evalue] - ) -> - change_expr (mk_field_access gen obj field obj.epos) (run obj) field (Some (run evalue)) false - | TBinop(OpAssign, ({eexpr = TField(fexpr, f)}), evalue) when is_dynamic e fexpr (f) -> - change_expr e (run fexpr) (field_name f) (Some (run evalue)) true - | TBinop(OpAssign, { eexpr = TField(fexpr, f) }, evalue) -> - (match field_access_esp gen fexpr.etype (f) with - | FClassField(_,_,_,cf,false,t,_) when (try PMap.find cf.cf_name gen.gbase_class_fields == cf with Not_found -> false) -> - change_expr e (run fexpr) (field_name f) (Some (run evalue)) true - | _ -> Type.map_expr run e - ) -(* #if debug *) - | TBinop(OpAssignOp op, ({eexpr = TField(fexpr, f)}), evalue) when is_dynamic e fexpr (f) -> assert false (* this case shouldn't happen *) - | TUnop(Increment, _, ({eexpr = TField( ( { eexpr=TLocal(local) } as fexpr ), f)})) - | TUnop(Decrement, _, ({eexpr = TField( ( { eexpr=TLocal(local) } as fexpr ), f)})) when is_dynamic e fexpr (f) -> assert false (* this case shouldn't happen *) -(* #end *) - | TCall( ({ eexpr = TField(fexpr, f) }), params ) when is_dynamic e fexpr (f) -> - call_expr e (run fexpr) (field_name f) (List.map run params) - | _ -> Type.map_expr run e - in run - - (* - this function will already configure with the abstract implementation, and also will create the needed class fields to - enable reflection on platforms that don't support reflection. - - this means it will create the following class methods: - - getField(field, isStatic) - gets the value of the field. isStatic - - setField - - - - *) - let configure_generate_classes gen optimize (runtime_getset_field:texpr->texpr->string->texpr option->texpr) (runtime_call_expr:texpr->texpr->string->texpr list->texpr) = - () - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + (* #if debug *) + | TBinop(OpAssignOp op, ({eexpr = TField(fexpr, f)}), evalue) when is_dynamic e fexpr (f) -> assert false (* this case shouldn't happen *) + | TUnop(Increment, _, ({eexpr = TField( ( { eexpr=TLocal(local) } as fexpr ), f)})) + | TUnop(Decrement, _, ({eexpr = TField( ( { eexpr=TLocal(local) } as fexpr ), f)})) when is_dynamic e fexpr (f) -> assert false (* this case shouldn't happen *) + (* #end *) + | TCall( ({ eexpr = TField(fexpr, f) }), params ) when is_dynamic e fexpr (f) -> + call_expr e (run fexpr) (field_name f) (List.map run params) + | _ -> Type.map_expr run e + in + let map e = Some(run e) in gen.gexpr_filters#add ~name:"dynamic_field_access" ~priority:(PCustom(priority)) map - - let configure_as_synf gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in - gen.gexpr_filters#add ~name:"dynamic_field_access" ~priority:(PCustom(priority_as_synf)) map - end;; + (* ******************************************* *) (* Closure Detection *) (* ******************************************* *) - (* - Just a small utility filter that detects when a closure must be created. On the default implementation, this means when a function field is being accessed not via reflection and not to be called instantly @@ -2588,15 +2356,12 @@ end;; dependencies: must run after DynamicFieldAccess, so any TAnon { Statics / EnumStatics } will be changed to the corresponding TTypeExpr *) - module FilterClosures = struct - let name = "filter_closures" - let priority = solve_deps name [DAfter DynamicFieldAccess.priority] - let traverse gen (should_change:texpr->string->bool) (filter:texpr->texpr->string->bool->texpr) = + let configure gen (should_change:texpr->string->bool) (filter:texpr->texpr->string->bool->texpr) = let rec run e = match e.eexpr with (*(* this is precisely the only case where we won't even ask if we should change, because it is a direct use of TClosure *) @@ -2646,41 +2411,30 @@ struct filter e (run e1) cf.cf_name false) | _ -> Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gexpr_filters#add ~name:name ~priority:(PCustom priority) map - end;; + (* ******************************************* *) (* Dynamic TArray Handling *) (* ******************************************* *) - (* In some languages you cannot overload the [] operator, so we need to decide what is kept as TArray and what gets mapped. - - in order to do this you must ensure that - depends on: (syntax) must run before expression/statment normalization because it may generate complex expressions (ok) must run before binop transformations because it may generate some untreated binop ops (ok) must run before dynamic field access is transformed into reflection *) - module TArrayTransform = struct - let name = "dyn_tarray" - let priority = solve_deps name [DBefore DynamicOperators.priority; DBefore DynamicFieldAccess.priority] - let priority_as_synf = solve_deps name [DBefore DynamicOperators.priority_as_synf; DBefore DynamicFieldAccess.priority_as_synf] - (* should change signature: tarray expr -> binop operation -> should change? *) - let default_implementation gen (should_change:texpr->Ast.binop option->bool) (get_fun:string) (set_fun:string) = + let configure gen (should_change:texpr->Ast.binop option->bool) (get_fun:string) (set_fun:string) = let basic = gen.gcon.basic in let mk_get e e1 e2 = let efield = mk_field_access gen e1 get_fun e.epos in @@ -2743,25 +2497,16 @@ struct end else Type.map_expr run e | _ -> Type.map_expr run e - - in run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + in + let map e = Some(run e) in gen.gexpr_filters#add ~name:"dyn_tarray" ~priority:(PCustom priority) map - - let configure_as_synf gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in - gen.gexpr_filters#add ~name:"dyn_tarray" ~priority:(PCustom priority_as_synf) map - end;; + (* ******************************************* *) (* Try / Catch + throw native types handling *) (* ******************************************* *) - (* - Some languages/vm's do not support throwing any kind of value. For them, only special kinds of objects can be thrown. Because of this, we must wrap some throw statements with an expression, and also we must unwrap it on the catch() phase, and @@ -2770,12 +2515,9 @@ end;; dependencies: must run before dynamic field access (?) TODO review It's a syntax filter, as it alters types (throw wrapper) - *) - module TryCatchWrapper = struct - let priority = solve_deps "try_catch" [DBefore DynamicFieldAccess.priority] (* @@ -2787,7 +2529,7 @@ struct wrapper_type : the wrapper type, so we can test if exception is of type 'wrapper' catch_map : maps the catch expression to include some intialization code (e.g. setting up Stack.exceptionStack) *) - let traverse gen (should_wrap:t->bool) (wrap_throw:texpr->texpr->texpr) (unwrap_expr:tvar->pos->texpr) (rethrow_expr:texpr->texpr) (catchall_type:t) (wrapper_type:t) (catch_map:tvar->texpr->texpr) = + let configure gen (should_wrap:t->bool) (wrap_throw:texpr->texpr->texpr) (unwrap_expr:tvar->pos->texpr) (rethrow_expr:texpr->texpr) (catchall_type:t) (wrapper_type:t) (catch_map:tvar->texpr->texpr) = let rec run e = match e.eexpr with | TThrow texpr when should_wrap texpr.etype -> wrap_throw e (run texpr) @@ -2855,14 +2597,11 @@ struct { e with eexpr = TTry(run ttry, (List.rev nowrap_catches) @ dyn_catch) } | _ -> Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gsyntax_filters#add ~name:"try_catch" ~priority:(PCustom priority) map - end;; + let fun_args = List.map (function | (v,s) -> (v.v_name, (match s with | None -> false | Some _ -> true), v.v_type)) (* ******************************************* *) @@ -2879,7 +2618,7 @@ let fun_args = List.map (function | (v,s) -> (v.v_name, (match s with | None -> dependencies: must run after dynamic field access, because of conflicting ways to deal with invokeField - (module filter) must run after OverloadingCtor so we can also change the dynamic function expressions + (module filter) must run after OverloadingConstructor so we can also change the dynamic function expressions uses TArray expressions for array. TODO see interaction uses TThrow expressions. @@ -2887,18 +2626,11 @@ let fun_args = List.map (function | (v,s) -> (v.v_name, (match s with | None -> module ClosuresToClass = struct - let name = "closures_to_class" - let priority = solve_deps name [ DAfter DynamicFieldAccess.priority ] - let priority_as_synf = solve_deps name [ DAfter DynamicFieldAccess.priority_as_synf ] - - type closures_ctx = - { - fgen : generator_ctx; - - mutable func_class : tclass; + type closures_ctx = { + func_class : tclass; (* this is what will actually turn the function into class field. @@ -2906,38 +2638,20 @@ struct It will also return the super arguments to be called *) - mutable closure_to_classfield : tfunc->t->pos->tclass_field * (texpr list); + closure_to_classfield : tfunc->t->pos->tclass_field * (texpr list); (* when a dynamic function call is made, we need to convert it as if it were calling the dynamic function interface. TCall expr -> new TCall expr *) - mutable dynamic_fun_call : texpr->texpr; - - (* - called once so the implementation can make one of a time initializations in the base class - for all functions - *) - mutable initialize_base_class : tclass->unit; - - (* - Base classfields are the class fields for the abstract implementation of either the Function implementation, - or the invokeField implementation for the classes - They will either try to call the right function or will fail with - - (tclass - subject (so we know the type of this)) -> is_function_base -> additional arguments for each function (at the beginning) -> list of the abstract implementation class fields - *) - mutable get_base_classfields_for : tclass->bool->(unit->(tvar * tconstant option) list)->tclass_field list; + dynamic_fun_call : texpr->texpr; (* - This is a more complex version of get_base_classfields_for. - It's meant to provide a toolchain so we can easily create classes that extend Function - and add more functionality on top of it. + Provide a toolchain so we can easily create classes that extend Function and add more functionality on top of it. arguments: tclass -> subject (so we know the type of this) - bool -> is it a function type ( int -> (int->t->tconstant option->texpr) -> ( (tvar * tconstant option) list * texpr) ) int -> current arity of the function whose member will be mapped; -1 for dynamic function. It is guaranteed that dynamic function will be called last t -> the return type of the function @@ -2949,10 +2663,7 @@ struct should return a list with additional arguments (only works if is_function_base = true) and the underlying function expression *) - mutable map_base_classfields : tclass->bool->( int -> t -> (tvar list) -> (int->t->tconstant option->texpr) -> ( (tvar * tconstant option) list * texpr) )->tclass_field list; - - mutable transform_closure : texpr->texpr->string->texpr; - + map_base_classfields : tclass->( int -> t -> (tvar list) -> (int->t->tconstant option->texpr) -> texpr )->tclass_field list; } type map_info = { @@ -2998,23 +2709,23 @@ struct etype = ret; epos = e.epos; } in - let body = if not (is_void ret) then + let body = if not (ExtType.is_void ret) then { body with eexpr = TReturn( Some body ) } else body in let body = { - eexpr = TBlock(block @ [body]); + eexpr = TBlock([body]); etype = body.etype; epos = body.epos; } in - { + block, { tf_args = tf_args; tf_expr = body; tf_type = ret; } - let traverse gen ?tparam_anon_decl ?tparam_anon_acc (transform_closure:texpr->texpr->string->texpr) (handle_anon_func:texpr->tfunc->map_info->t option->texpr) (dynamic_func_call:texpr->texpr) e = + let traverse gen ?tparam_anon_decl ?tparam_anon_acc (handle_anon_func:texpr->tfunc->map_info->t option->texpr) (dynamic_func_call:texpr->texpr) e = let info = ref null_map_info in let rec run e = match e.eexpr with @@ -3034,9 +2745,15 @@ struct let ret = handle_anon_func clean { tf with tf_expr = run tf.tf_expr } !info (Some e.etype) in replace_delegate ret | _ -> try - let tf = mk_conversion_fun gen del in - let ret = handle_anon_func del { tf with tf_expr = run tf.tf_expr } !info (Some e.etype) in - replace_delegate ret + let block, tf = mk_conversion_fun gen del in + let block = List.map run block in + let tf = { tf with tf_expr = run tf.tf_expr } in + let ret = handle_anon_func { clean with eexpr = TFunction(tf) } { tf with tf_expr = run tf.tf_expr } !info (Some e.etype) in + let ret = replace_delegate ret in + if block = [] then + ret + else + { ret with eexpr = TBlock(block @ [ret]) } with Not_found -> gen.gcon.error "This delegate construct is unsupported" e.epos; replace_delegate (run clean)) @@ -3083,7 +2800,7 @@ struct | _ -> let i = ref 0 in let t = TFun(List.map (fun e -> incr i; "arg" ^ (string_of_int !i), false, e.etype) params, e.etype) in - dynamic_func_call { e with eexpr = TCall( mk_cast t (run e1), List.map run params ) } + dynamic_func_call { e with eexpr = TCall( mk_castfast t (run e1), List.map run params ) } ) (* | FNotFound -> { e with eexpr = TCall({ e1 with eexpr = TField(run ecl, f) }, List.map run params) } @@ -3095,10 +2812,8 @@ struct | _ -> let i = ref 0 in let t = TFun(List.map (fun e -> incr i; "arg" ^ (string_of_int !i), false, e.etype) params, e.etype) in - dynamic_func_call { e with eexpr = TCall( mk_cast t (run e1), List.map run params ) } + dynamic_func_call { e with eexpr = TCall( mk_castfast t (run e1), List.map run params ) } ) - | TField(ecl, FClosure (_,cf)) -> - transform_closure e (run ecl) cf.cf_name | TFunction tf -> handle_anon_func e { tf with tf_expr = run tf.tf_expr } !info None | TCall({ eexpr = TConst(TSuper) }, _) -> @@ -3115,7 +2830,7 @@ struct ("p" ^ (string_of_int !i), false, e.etype) ) params, e.etype) in - fun e -> mk_cast t e + fun e -> mk_castfast t e in dynamic_func_call { e with eexpr = TCall(run (may_cast tc), List.map run params) } | _ -> Type.map_expr run e @@ -3217,22 +2932,9 @@ struct This means that it also imposes that the dynamic function return types may only be Dynamic or Float, and all other basic types must be converted to/from it. *) - - let default_implementation ft parent_func_class (* e.g. new haxe.lang.ClassClosure *) = - let gen = ft.fgen in - ft.initialize_base_class parent_func_class; - let cfs = ft.get_base_classfields_for parent_func_class true (fun () -> []) in - List.iter (fun cf -> - (if cf.cf_name = "new" then parent_func_class.cl_constructor <- Some cf else - parent_func_class.cl_fields <- PMap.add cf.cf_name cf parent_func_class.cl_fields - ) - ) cfs; - - parent_func_class.cl_ordered_fields <- (List.filter (fun cf -> cf.cf_name <> "new") cfs) @ parent_func_class.cl_ordered_fields; - ft.func_class <- parent_func_class; + let configure gen ft = let handle_anon_func fexpr tfunc mapinfo delegate_type : texpr * (tclass * texpr list) = - let gen = ft.fgen in let in_unsafe = mapinfo.in_unsafe || match gen.gcurrent_class, gen.gcurrent_classfield with | Some c, _ when Meta.has Meta.Unsafe c.cl_meta -> true | _, Some cf when Meta.has Meta.Unsafe cf.cf_meta -> true @@ -3251,19 +2953,19 @@ struct let cltypes = List.map (fun cl -> (snd cl.cl_path, TInst(cl, []) )) tparams in (* create a new class that extends abstract function class, with a ctor implementation that will setup all captured variables *) - let cfield = match ft.fgen.gcurrent_classfield with + let cfield = match gen.gcurrent_classfield with | None -> "Anon" | Some cf -> cf.cf_name in let cur_line = Lexer.get_error_line fexpr.epos in - let path = (fst ft.fgen.gcurrent_path, Printf.sprintf "%s_%s_%d__Fun" (snd ft.fgen.gcurrent_path) cfield cur_line) in - let cls = mk_class (get ft.fgen.gcurrent_class).cl_module path tfunc.tf_expr.epos in - if in_unsafe then cls.cl_meta <- (Meta.Unsafe,[],Ast.null_pos) :: cls.cl_meta; + let path = (fst gen.gcurrent_path, Printf.sprintf "%s_%s_%d__Fun" (snd gen.gcurrent_path) cfield cur_line) in + let cls = mk_class (get gen.gcurrent_class).cl_module path tfunc.tf_expr.epos in + if in_unsafe then cls.cl_meta <- (Meta.Unsafe,[],null_pos) :: cls.cl_meta; if Common.defined gen.gcon Define.EraseGenerics then begin - cls.cl_meta <- (Meta.HaxeGeneric,[],Ast.null_pos) :: cls.cl_meta + cls.cl_meta <- (Meta.HaxeGeneric,[],null_pos) :: cls.cl_meta end; - cls.cl_module <- (get ft.fgen.gcurrent_class).cl_module; + cls.cl_module <- (get gen.gcurrent_class).cl_module; cls.cl_params <- cltypes; let mk_this v pos = @@ -3327,7 +3029,7 @@ struct etype = tfunc.tf_type; epos = pos } in - let ibody = if not (is_void tfunc.tf_type) then + let ibody = if not (ExtType.is_void tfunc.tf_type) then { ibody with eexpr = TReturn( Some ibody ) } else ibody @@ -3339,24 +3041,24 @@ struct (* create the constructor *) (* todo properly abstract how type var is set *) - cls.cl_super <- Some(parent_func_class, []); + cls.cl_super <- Some(ft.func_class, []); let pos = cls.cl_pos in let super_call = { - eexpr = TCall({ eexpr = TConst(TSuper); etype = TInst(parent_func_class,[]); epos = pos }, super_args); - etype = ft.fgen.gcon.basic.tvoid; + eexpr = TCall({ eexpr = TConst(TSuper); etype = TInst(ft.func_class,[]); epos = pos }, super_args); + etype = gen.gcon.basic.tvoid; epos = pos; } in - let ctor_type = (TFun(ctor_sig, ft.fgen.gcon.basic.tvoid)) in + let ctor_type = (TFun(ctor_sig, gen.gcon.basic.tvoid)) in let ctor = mk_class_field "new" ctor_type true cls.cl_pos (Method(MethNormal)) [] in ctor.cf_expr <- Some( { eexpr = TFunction( { tf_args = ctor_args; - tf_type = ft.fgen.gcon.basic.tvoid; - tf_expr = { eexpr = TBlock(super_call :: ctor_exprs); etype = ft.fgen.gcon.basic.tvoid; epos = cls.cl_pos } + tf_type = gen.gcon.basic.tvoid; + tf_expr = { eexpr = TBlock(super_call :: ctor_exprs); etype = gen.gcon.basic.tvoid; epos = cls.cl_pos } }); etype = ctor_type; epos = cls.cl_pos; @@ -3368,14 +3070,13 @@ struct cls.cl_fields <- PMap.add invoke_field.cf_name invoke_field cls.cl_fields; cls.cl_overrides <- invoke_field :: cls.cl_overrides; - (* add this class to the module with gadd_to_module *) - ft.fgen.gadd_to_module (TClassDecl(cls)) priority; + gen.gadd_to_module (TClassDecl cls) priority; (* if there are no captured variables, we can create a cache so subsequent calls don't need to create a new function *) let expr, clscapt = match captured, tparams with | [], [] -> - let cache_var = ft.fgen.gmk_internal_name "hx" "current" in + let cache_var = gen.gmk_internal_name "hx" "current" in let cache_cf = mk_class_field cache_var (TInst(cls,[])) false func_expr.epos (Var({ v_read = AccNormal; v_write = AccNormal })) [] in cls.cl_ordered_statics <- cache_cf :: cls.cl_ordered_statics; cls.cl_statics <- PMap.add cache_var cache_cf cls.cl_statics; @@ -3387,10 +3088,11 @@ struct let pos = func_expr.epos in { fexpr with + etype = hx_current.etype; eexpr = TIf( { eexpr = TBinop(OpNotEq, hx_current, null (TInst(cls,[])) pos); - etype = ft.fgen.gcon.basic.tbool; + etype = gen.gcon.basic.tbool; epos = pos; }, hx_current, @@ -3418,8 +3120,8 @@ struct let tvar_to_cdecl = Hashtbl.create 0 in - traverse - ft.fgen + let run = traverse + gen ~tparam_anon_decl:(fun v e fn -> let _, info = handle_anon_func e fn null_map_info None in Hashtbl.add tvar_to_cdecl v.v_id info @@ -3460,25 +3162,18 @@ struct gen.gcon.warning "This expression may be invalid" e.epos; e | Unify_error el -> - List.iter (fun el -> gen.gcon.warning (Typecore.unify_error_msg (print_context()) el) e.epos) el; + List.iter (fun el -> gen.gcon.warning (Error.unify_error_msg (print_context()) el) e.epos) el; gen.gcon.warning "This expression may be invalid" e.epos; e ) - (* (transform_closure:texpr->texpr->string->texpr) (handle_anon_func:texpr->tfunc->texpr) (dynamic_func_call:texpr->texpr->texpr list->texpr) *) - ft.transform_closure + (* (handle_anon_func:texpr->tfunc->texpr) (dynamic_func_call:texpr->texpr->texpr list->texpr) *) (fun e f info delegate_type -> fst (handle_anon_func e f info delegate_type)) ft.dynamic_fun_call (* (dynamic_func_call:texpr->texpr->texpr list->texpr) *) - - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + in + let map e = Some(run e) in gen.gexpr_filters#add ~name:name ~priority:(PCustom priority) map - let configure_as_synf gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in - gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority_as_synf) map - (* this submodule will provide the default implementation for the C# and Java targets. @@ -3487,13 +3182,10 @@ struct *) module DoubleAndDynamicClosureImpl = struct - - let get_ctx gen max_arity = - + let get_ctx gen parent_func_class max_arity (* e.g. new haxe.lang.ClassClosure *) = let basic = gen.gcon.basic in let func_args_i i = - let rec loop i (acc) = if i = 0 then (acc) else begin let vfloat = alloc_var (gen.gmk_internal_name "fn" ("float" ^ string_of_int i)) basic.tfloat in @@ -3503,11 +3195,9 @@ struct end in loop i [] - in let args_real_to_func args = - let arity = List.length args in if arity >= max_arity then [ alloc_var (gen.gmk_internal_name "fn" "dynargs") (basic.tarray t_dynamic), None ] @@ -3515,7 +3205,6 @@ struct in let func_sig_i i = - let rec loop i acc = if i = 0 then acc else begin let vfloat = gen.gmk_internal_name "fn" ("float" ^ string_of_int i) in @@ -3525,18 +3214,15 @@ struct end in loop i [] - in let args_real_to_func_sig args = - let arity = List.length args in if arity >= max_arity then [gen.gmk_internal_name "fn" "dynargs", false, basic.tarray t_dynamic] else begin func_sig_i arity end - in let rettype_real_to_func t = match run_follow gen t with @@ -3548,7 +3234,7 @@ struct (0, t_dynamic) in - let args_real_to_func_call el (pos:Ast.pos) = + let args_real_to_func_call el (pos:pos) = if List.length el >= max_arity then [{ eexpr = TArrayDecl el; etype = basic.tarray t_dynamic; epos = pos }] else begin @@ -3563,22 +3249,25 @@ struct let const_type c def = match c with - | TString _ -> basic.tstring | TInt _ -> basic.tint - | TFloat _ -> basic.tfloat | TBool _ -> basic.tbool - | _ -> def + | TString _ -> basic.tstring + | TInt _ -> basic.tint + | TFloat _ -> basic.tfloat + | TBool _ -> basic.tbool + | _ -> def in let get_args_func args changed_args pos = let arity = List.length args in let mk_const const elocal t = match const with - | None -> mk_cast t elocal - | Some const -> - { eexpr = TIf( - { elocal with eexpr = TBinop(Ast.OpEq, elocal, null elocal.etype elocal.epos); etype = basic.tbool }, - { elocal with eexpr = TConst(const); etype = const_type const t }, - Some ( mk_cast t elocal ) - ); etype = t; epos = elocal.epos } + | None -> + mk_cast t elocal + | Some const -> + { eexpr = TIf( + { elocal with eexpr = TBinop(Ast.OpEq, elocal, null elocal.etype elocal.epos); etype = basic.tbool }, + { elocal with eexpr = TConst(const); etype = const_type const t }, + Some ( mk_cast t elocal ) + ); etype = t; epos = elocal.epos } in if arity >= max_arity then begin @@ -3587,12 +3276,7 @@ struct let mk_varray i = { eexpr = TArray(varray_local, { eexpr = TConst(TInt(Int32.of_int i)); etype = basic.tint; epos = pos }); etype = t_dynamic; epos = pos } in snd (List.fold_left (fun (count,acc) (v,const) -> - (count + 1, - { - eexpr = TVar(v, Some(mk_const const ( mk_varray count ) v.v_type)); - etype = basic.tvoid; - epos = pos; - } :: acc) + (count + 1, (mk (TVar(v, Some(mk_const const (mk_varray count) v.v_type))) basic.tvoid pos) :: acc) ) (0,[]) args) end else begin let _, dyn_args, float_args = List.fold_left (fun (count,fargs, dargs) arg -> @@ -3640,7 +3324,7 @@ struct let is_dynamic_func = arity >= max_arity in let ret_t = if is_dynamic_func then t_dynamic else ret_t in - (TFun(args_real_to_func_sig _sig, ret_t), arity, type_n, ret_t, is_void ret, is_dynamic_func) + (TFun(args_real_to_func_sig _sig, ret_t), arity, type_n, ret_t, ExtType.is_void ret, is_dynamic_func) | _ -> (print_endline (s_type (print_context()) (follow old_sig) )); assert false in @@ -3678,86 +3362,82 @@ struct let invoke_name = if is_dynamic_func then "invokeDynamic" else ("invoke" ^ (string_of_int arity) ^ (if type_number = 0 then "_o" else "_f")) in let invoke_name = gen.gmk_internal_name "hx" invoke_name in let invoke_field = mk_class_field invoke_name changed_sig false func_expr.epos (Method(MethNormal)) [] in - let invoke_fun = - { - eexpr = TFunction( - { + let invoke_fun = { + eexpr = TFunction { tf_args = changed_args; tf_type = changed_sig_ret; tf_expr = func_expr; - }); + }; etype = changed_sig; epos = func_expr.epos; } in - invoke_field.cf_expr <- Some(invoke_fun); + invoke_field.cf_expr <- Some invoke_fun; - (invoke_field, [ - { eexpr = TConst(TInt( Int32.of_int arity )); etype = gen.gcon.basic.tint; epos = pos }; - { eexpr = TConst(TInt( Int32.of_int type_number )); etype = gen.gcon.basic.tint; epos = pos }; - ]) + invoke_field, [ + ExprBuilder.make_int gen.gcon arity pos; + ExprBuilder.make_int gen.gcon type_number pos; + ] in let dynamic_fun_call call_expr = let tc, params = match call_expr.eexpr with - | TCall(tc, params) -> (tc, params) + | TCall(tc, params) -> tc, params | _ -> assert false in - let ct = gen.greal_type call_expr.etype in - let postfix, ret_t = - if like_float ct && not (like_i64 ct) then - "_f", gen.gcon.basic.tfloat - else - "_o", t_dynamic - in - let params_len = List.length params in - let ret_t = if params_len >= max_arity then t_dynamic else ret_t in - - let invoke_fun = if params_len >= max_arity then "invokeDynamic" else "invoke" ^ (string_of_int params_len) ^ postfix in - let invoke_fun = gen.gmk_internal_name "hx" invoke_fun in - let fun_t = match follow tc.etype with - | TFun(_sig, _) -> - TFun(args_real_to_func_sig _sig, ret_t) - | _ -> - let i = ref 0 in - let _sig = List.map (fun p -> let name = "arg" ^ (string_of_int !i) in incr i; (name,false,p.etype) ) params in - TFun(args_real_to_func_sig _sig, ret_t) - in + let ct = gen.greal_type call_expr.etype in + let postfix, ret_t = + if like_float ct && not (like_i64 ct) then + "_f", gen.gcon.basic.tfloat + else + "_o", t_dynamic + in + let params_len = List.length params in + let ret_t = if params_len >= max_arity then t_dynamic else ret_t in + + let invoke_fun = if params_len >= max_arity then "invokeDynamic" else "invoke" ^ (string_of_int params_len) ^ postfix in + let invoke_fun = gen.gmk_internal_name "hx" invoke_fun in + let fun_t = match follow tc.etype with + | TFun(_sig, _) -> + TFun(args_real_to_func_sig _sig, ret_t) + | _ -> + let i = ref 0 in + let _sig = List.map (fun p -> let name = "arg" ^ (string_of_int !i) in incr i; (name,false,p.etype) ) params in + TFun(args_real_to_func_sig _sig, ret_t) + in - let may_cast = match follow call_expr.etype with - | TAbstract ({ a_path = ([], "Void") },[]) -> (fun e -> e) - | _ -> mk_cast call_expr.etype - in + let may_cast = match follow call_expr.etype with + | TAbstract ({ a_path = ([], "Void") },[]) -> (fun e -> e) + | _ -> mk_cast call_expr.etype + in - may_cast - { - eexpr = TCall( - { (mk_field_access gen { tc with etype = gen.greal_type tc.etype } invoke_fun tc.epos) with etype = fun_t }, - args_real_to_func_call params call_expr.epos - ); - etype = ret_t; - epos = call_expr.epos - } + may_cast + { + eexpr = TCall( + { (mk_field_access gen { tc with etype = gen.greal_type tc.etype } invoke_fun tc.epos) with etype = fun_t }, + args_real_to_func_call params call_expr.epos + ); + etype = ret_t; + epos = call_expr.epos + } in - let iname is_function i is_float = + let iname i is_float = let postfix = if is_float then "_f" else "_o" in - gen.gmk_internal_name "hx" ("invoke" ^ (if not is_function then "Field" else "") ^ string_of_int i) ^ postfix + gen.gmk_internal_name "hx" ("invoke" ^ string_of_int i) ^ postfix in - let map_base_classfields cl is_function map_fn = - + let map_base_classfields cl map_fn = let pos = cl.cl_pos in let this_t = TInst(cl,List.map snd cl.cl_params) in let this = { eexpr = TConst(TThis); etype = this_t; epos = pos } in let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in let mk_invoke_i i is_float = - let cf = mk_class_field (iname is_function i is_float) (TFun(func_sig_i i, if is_float then basic.tfloat else t_dynamic)) false pos (Method MethNormal) [] in + let cf = mk_class_field (iname i is_float) (TFun(func_sig_i i, if is_float then basic.tfloat else t_dynamic)) false pos (Method MethNormal) [] in cf in let type_name = gen.gmk_internal_name "fn" "type" in - let dynamic_arg = alloc_var (gen.gmk_internal_name "fn" "dynargs") (basic.tarray t_dynamic) in let mk_invoke_complete_i i is_float = @@ -3810,8 +3490,7 @@ struct let ret = if is_float then basic.tfloat else t_dynamic in - let added_args, fn_expr = map_fn i ret (List.map fst args) api in - let args = added_args @ args in + let fn_expr = map_fn i ret (List.map fst args) api in let t = TFun(fun_args args, ret) in @@ -3842,7 +3521,7 @@ struct let cfs = loop max_arity [] in - let added_s_args, switch = + let switch = let api i t const = match i with | -1 -> @@ -3859,255 +3538,180 @@ struct map_fn (-1) t_dynamic [dynamic_arg] api in - let args = added_s_args @ [dynamic_arg, None] in + let args = [dynamic_arg, None] in let dyn_t = TFun(fun_args args, t_dynamic) in let dyn_cf = mk_class_field (gen.gmk_internal_name "hx" "invokeDynamic") dyn_t false pos (Method MethNormal) [] in - dyn_cf.cf_expr <- - Some { - eexpr = TFunction({ + dyn_cf.cf_expr <- Some { + eexpr = TFunction { tf_args = args; tf_type = t_dynamic; tf_expr = mk_block switch - }); + }; etype = dyn_t; epos = pos; }; - let additional_cfs = if is_function then begin + let additional_cfs = begin let new_t = TFun(["arity", false, basic.tint; "type", false, basic.tint],basic.tvoid) in let new_cf = mk_class_field "new" (new_t) true pos (Method MethNormal) [] in let v_arity, v_type = alloc_var "arity" basic.tint, alloc_var "type" basic.tint in - let mk_assign v field = { eexpr = TBinop(Ast.OpAssign, mk_this field v.v_type, mk_local v pos); etype = v.v_type; epos = pos } in + let mk_assign v field = mk (TBinop (OpAssign, mk_this field v.v_type, mk_local v pos)) v.v_type pos in let arity_name = gen.gmk_internal_name "hx" "arity" in - new_cf.cf_expr <- - Some { - eexpr = TFunction({ - tf_args = [v_arity, None; v_type, None]; - tf_type = basic.tvoid; - tf_expr = - { - eexpr = TBlock([ - mk_assign v_type type_name; - mk_assign v_arity arity_name - ]); - etype = basic.tvoid; - epos = pos; - } - }); - etype = new_t; - epos = pos; - } - ; + new_cf.cf_expr <- Some { + eexpr = TFunction({ + tf_args = [v_arity, None; v_type, None]; + tf_type = basic.tvoid; + tf_expr = + { + eexpr = TBlock([ + mk_assign v_type type_name; + mk_assign v_arity arity_name + ]); + etype = basic.tvoid; + epos = pos; + } + }); + etype = new_t; + epos = pos; + }; [ new_cf; mk_class_field type_name basic.tint true pos (Var { v_read = AccNormal; v_write = AccNormal }) []; mk_class_field arity_name basic.tint true pos (Var { v_read = AccNormal; v_write = AccNormal }) []; ] - end else [] in + end in dyn_cf :: (additional_cfs @ cfs) in - (* maybe another param for prefix *) - let get_base_classfields_for cl is_function mk_additional_args = - let pos = cl.cl_pos in + begin + (* + setup fields for the abstract implementation of the Function class - let this_t = TInst(cl,List.map snd cl.cl_params) in - let this = { eexpr = TConst(TThis); etype = this_t; epos = pos } in - let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in + new(arity, type) + { + this.arity = arity; + this.type = type; + } - let rec mk_dyn_call arity api = - let zero = { eexpr = TConst(TFloat("0.0")); etype = basic.tfloat; epos = pos } in - let rec loop i acc = - if i = 0 then acc else begin - let arr = api (i-1) t_dynamic None in + hx::invokeX_f|o (where X is from 0 to max_arity) (args) + { + if (this.type == 0|1) return invokeX_o|f(args); else throw "Invalid number of arguments." + } + + hx::invokeDynamic, which will work in the same way + *) + let cl = parent_func_class in + let pos = cl.cl_pos in + + let rec mk_dyn_call arity api = + let zero = ExprBuilder.make_float gen.gcon "0.0" pos in + let rec loop i acc = + if i = 0 then + acc + else begin + let arr = api (i - 1) t_dynamic None in loop (i - 1) (zero :: arr :: acc) end in - loop arity ([]) + loop arity [] in - let mk_invoke_switch i (api:(int->t->tconstant option->texpr)) = - - let t = TFun(func_sig_i i,t_dynamic) in + let this = mk (TConst TThis) (TInst (cl, List.map snd cl.cl_params)) pos in + let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in + let mk_invoke_switch i api = + let t = TFun (func_sig_i i, t_dynamic) in (* case i: return this.invokeX_o(0, 0, 0, 0, 0, ... arg[0], args[1]....); *) - ( [{ eexpr = TConst(TInt(Int32.of_int i)); etype = basic.tint; epos = pos }], - { - eexpr = TReturn(Some( { - eexpr = TCall(mk_this (iname is_function i false) t, mk_dyn_call i api); - etype = t_dynamic; - epos = pos; - } )); - etype = t_dynamic; - epos = pos; - } ) + [ExprBuilder.make_int gen.gcon i pos], mk_return (mk (TCall(mk_this (iname i false) t, mk_dyn_call i api)) t_dynamic pos) + in + let rec loop_cases api arity acc = + if arity < 0 then + acc + else + loop_cases api (arity - 1) (mk_invoke_switch arity api :: acc) in - let cl_t = TInst(cl,List.map snd cl.cl_params) in - let this = { eexpr = TConst(TThis); etype = cl_t; epos = pos } in - let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in - let mk_int i = { eexpr = TConst(TInt ( Int32.of_int i)); etype = basic.tint; epos = pos } in - let mk_string s = { eexpr = TConst(TString s); etype = basic.tstring; epos = pos } in - - (* - if it is the Function class, the base class fields will be - * hx::invokeX_d|o (where X is from 0 to max_arity) (args) - { - if (this.type == 0|1) return invokeX_o|d(args); else throw "Invalid number of arguments." - } - - hx::invokeDynamic, which will work in the same way - - new(arity, type) - { - if (type != 0 && type != 1) throw "Invalid type"; - this.arity = arity; - this.type = type; - } - *) let type_name = gen.gmk_internal_name "fn" "type" in - let mk_expr i is_float vars = - - let name = if is_function then "invoke" else "invokeField" in - - let look_ahead = alloc_var "lookAhead" basic.tbool in - let add_args = if not is_function then mk_additional_args() else [] in - let vars = if not is_function then (List.map fst add_args) @ (look_ahead :: vars) else vars in - let call_expr = - let call_t = TFun(List.map (fun v -> (v.v_name, false, v.v_type)) vars, if is_float then t_dynamic else basic.tfloat) in { - eexpr = TCall(mk_this (gen.gmk_internal_name "hx" (name ^ (string_of_int i) ^ (if is_float then "_o" else "_f"))) call_t, List.map (fun v -> if v.v_id = look_ahead.v_id then ( { eexpr = TConst(TBool false); etype = basic.tbool; epos = pos } ) else mk_local v pos) vars ); + eexpr = TCall(mk_this (iname i (not is_float)) call_t, List.map (fun v -> mk_local v pos) vars); etype = if is_float then t_dynamic else basic.tfloat; epos = pos } in - (*let call_expr = if is_float then mk_cast basic.tfloat call_expr else call_expr in*) - - let if_cond = if is_function then - { eexpr=TBinop(Ast.OpNotEq, mk_this type_name basic.tint, mk_int (if is_float then 0 else 1) ); etype = basic.tbool; epos = pos } - else - mk_local look_ahead pos - in - - let if_expr = if is_function then - { - eexpr = TIf(if_cond, - { eexpr = TThrow(mk_string "Wrong number of arguments"); etype = basic.tstring; epos = pos }, - Some( { eexpr = TReturn( Some( call_expr ) ); etype = call_expr.etype; epos = pos } ) - ); - etype = t_dynamic; - epos = pos; - } - else - { - eexpr = TIf(if_cond, - { eexpr = TReturn( Some( call_expr ) ); etype = call_expr.etype; epos = pos }, - Some( { eexpr = TThrow(mk_string "Field not found or wrong number of arguments"); etype = basic.tstring; epos = pos } ) - ); - etype = t_dynamic; - epos = pos; - } - in - - let args = if not is_function then (mk_additional_args()) @ [look_ahead, None] else [] in - (args, if_expr) + { + eexpr = TIf( + mk (TBinop (Ast.OpNotEq, mk_this type_name basic.tint, (ExprBuilder.make_int gen.gcon (if is_float then 0 else 1) pos))) basic.tbool pos, + mk (TThrow (ExprBuilder.make_string gen.gcon "Wrong number of arguments" pos)) t_dynamic pos, + Some (mk_return call_expr) + ); + etype = t_dynamic; + epos = pos; + } in let arities_processed = Hashtbl.create 10 in let max_arity = ref 0 in - let rec loop_cases api arity acc = - if arity < 0 then acc else - loop_cases api (arity - 1) (mk_invoke_switch arity api :: acc) - in - (* let rec loop goes here *) - let map_fn cur_arity fun_ret_type vars (api:(int->t->tconstant option->texpr)) = + let map_fn cur_arity fun_ret_type vars (api:int->t->tconstant option->texpr) = let is_float = like_float fun_ret_type && not (like_i64 fun_ret_type) in match cur_arity with - | -1 -> - let dynargs = api (-1) (t_dynamic) None in - let switch_cond = mk_field_access gen dynargs "length" pos in - let switch_cond = { - eexpr = TIf( - { eexpr = TBinop(Ast.OpEq, dynargs, null dynargs.etype pos); etype = basic.tbool; epos = pos; }, - { eexpr = TConst(TInt(Int32.zero)); etype = basic.tint; epos = pos }, - Some switch_cond); - etype = basic.tint; - epos = pos; - } in + | -1 -> + let dynargs = api (-1) t_dynamic None in - let switch = - { - eexpr = TSwitch( switch_cond, - loop_cases api !max_arity [], - Some({ eexpr = TThrow(mk_string "Too many arguments"); etype = basic.tvoid; epos = pos; }) ); - etype = basic.tvoid; - epos = pos; - } in + (* (dynargs == null) ? 0 : dynargs.length *) + let switch_cond = { + eexpr = TIf( + mk (TBinop (OpEq, dynargs, null dynargs.etype pos)) basic.tbool pos, + mk (TConst (TInt Int32.zero)) basic.tint pos, + Some (mk_field_access gen dynargs "length" pos)); + etype = basic.tint; + epos = pos; + } in - ( (if not is_function then mk_additional_args () else []), switch ) - | _ -> - if not (Hashtbl.mem arities_processed cur_arity) then begin - Hashtbl.add arities_processed cur_arity true; - if cur_arity > !max_arity then max_arity := cur_arity - end; + { + eexpr = TSwitch( + switch_cond, + loop_cases api !max_arity [], + Some(mk (TThrow (ExprBuilder.make_string gen.gcon "Too many arguments" pos)) basic.tvoid pos)); + etype = basic.tvoid; + epos = pos; + } + | _ -> + if not (Hashtbl.mem arities_processed cur_arity) then begin + Hashtbl.add arities_processed cur_arity true; + if cur_arity > !max_arity then max_arity := cur_arity + end; - mk_expr cur_arity is_float vars + mk_expr cur_arity is_float vars in - map_base_classfields cl is_function map_fn - in - - let initialize_base_class cl = - () - in + let cfs = map_base_classfields cl map_fn in + List.iter (fun cf -> + if cf.cf_name = "new" then + parent_func_class.cl_constructor <- Some cf + else + parent_func_class.cl_fields <- PMap.add cf.cf_name cf parent_func_class.cl_fields + ) cfs; + parent_func_class.cl_ordered_fields <- (List.filter (fun cf -> cf.cf_name <> "new") cfs) @ parent_func_class.cl_ordered_fields + end; { - fgen = gen; - - func_class = null_class; - + func_class = parent_func_class; closure_to_classfield = closure_to_classfield; - dynamic_fun_call = dynamic_fun_call; - - (* - called once so the implementation can make one of a time initializations in the base class - for all functions - *) - initialize_base_class = initialize_base_class; - - (* - Base classfields are the class fields for the abstract implementation of either the Function implementation, - or the invokeField implementation for the classes - They will either try to call the right function or will fail with - - (tclass - subject (so we know the type of this)) -> is_function_base -> list of the abstract implementation class fields - *) - get_base_classfields_for = get_base_classfields_for; - map_base_classfields = map_base_classfields; - - (* - for now we won't deal with the closures. - They can be dealt with the module ReflectionCFs, - or a custom implementation - *) - transform_closure = (fun tclosure texpr str -> tclosure); - } - end;; - end;; + (* ******************************************* *) (* Type Parameters *) (* ******************************************* *) @@ -4145,19 +3749,6 @@ struct let priority = max_dep -. 20. - let rec deep_follow gen t = match run_follow gen t with - | TInst(c,tl) -> - TInst(c,List.map (deep_follow gen) tl) - | TEnum(e,tl) -> - TEnum(e,List.map (deep_follow gen) tl) - | TAbstract(a,tl) -> - TAbstract(a,List.map (deep_follow gen) tl) - | TType(t,tl) -> - TType(t,List.map (deep_follow gen) tl) - | TFun(args,ret) -> - TFun(List.map (fun (n,o,t) -> n,o,deep_follow gen t) args, deep_follow gen ret) - | t -> t - (* this function will receive the original function argument, the applied function argument and the original function parameters. *) (* from this info, it will infer the applied tparams for the function *) (* this function is used by CastDetection module *) @@ -4173,8 +3764,6 @@ struct (try List.iter2 (fun a o -> - let o = deep_follow gen o in - let a = deep_follow gen a in unify a o (* type_eq EqStrict a o *) ) applied original @@ -4229,8 +3818,6 @@ struct let priority = priority - let cast_field_name = "cast" - let rec has_type_params t = match follow t with | TInst( { cl_kind = KTypeParameter _ }, _) -> true @@ -4493,6 +4080,8 @@ struct get_fields gen cs (List.map (apply_params cl.cl_params params_cl) tls) (List.map (apply_params cl.cl_params params_cf) tls) (fields @ acc) | None -> (fields @ acc) + let get_cast_name cl = String.concat "_" ((fst cl.cl_path) @ [snd cl.cl_path; "cast"]) (* explicitly define it *) + (* overrides all needed cast functions from super classes / interfaces to call the new cast function *) let create_stub_casts gen cl cast_cfield = (* go through superclasses and interfaces *) @@ -4502,7 +4091,7 @@ struct let rec loop cls tls level reverse_params = if (level <> 0 || cls.cl_interface) && tls <> [] && is_hxgeneric (TClassDecl cls) then begin let cparams = List.map (fun (s,t) -> (s, TInst (map_param (get_cl_t t), []))) cls.cl_params in - let name = String.concat "_" ((fst cls.cl_path) @ [snd cls.cl_path; cast_field_name]) in + let name = get_cast_name cls in if not (PMap.mem name cl.cl_fields) then begin let reverse_params = List.map (apply_params cls.cl_params (List.map snd cparams)) reverse_params in let cfield = mk_class_field name (TFun([], t_dynamic)) false cl.cl_pos (Method MethNormal) cparams in @@ -4630,13 +4219,13 @@ struct epos = pos; } in - ([{ eexpr = TConst(TString(cf.cf_name)); etype = gen.gcon.basic.tstring; epos = pos }], expr) + [ExprBuilder.make_string gen.gcon cf.cf_name pos], expr ) fields in let mk_typehandle = let thandle = alloc_var "__typeof__" t_dynamic in - (fun cl -> { eexpr = TCall(mk_local thandle pos, [ mk_classtype_access cl pos ]); etype = t_dynamic; epos = pos }) + (fun cl -> { eexpr = TCall(mk_local thandle pos, [ ExprBuilder.make_static_this cl pos ]); etype = t_dynamic; epos = pos }) in let mk_eq cl1 cl2 = { eexpr = TBinop(Ast.OpEq, mk_typehandle cl1, mk_typehandle cl2); etype = basic.tbool; epos = pos } @@ -4676,7 +4265,7 @@ struct }; (* var new_me = /*special create empty with tparams construct*/ *) { - eexpr = TVar(new_me_var, Some(gen.gtools.rf_create_empty cl params pos)); + eexpr = TVar(new_me_var, Some(gen.gtools.r_create_empty cl params pos)); etype = gen.gcon.basic.tvoid; epos = pos }; @@ -4688,7 +4277,7 @@ struct }; (* var i = 0; *) { - eexpr = TVar(i_var, Some(mk_int gen 0 pos)); + eexpr = TVar(i_var, Some(ExprBuilder.make_int gen.gcon 0 pos)); etype = gen.gcon.basic.tvoid; epos = pos }; @@ -4792,8 +4381,6 @@ struct in cfield, delay - let get_cast_name cl = String.concat "_" ((fst cl.cl_path) @ [snd cl.cl_path; cast_field_name]) (* explicitly define it *) - let default_implementation gen ifaces base_generic = let add_iface cl = gen.gadd_to_module (TClassDecl cl) (max_dep); @@ -4838,6 +4425,7 @@ struct iface.cl_array_access <- Option.map (apply_params (cl.cl_params) (List.map (fun _ -> t_dynamic) cl.cl_params)) cl.cl_array_access; iface.cl_extern <- cl.cl_extern; iface.cl_module <- cl.cl_module; + iface.cl_private <- cl.cl_private; iface.cl_meta <- (Meta.HxGen, [], cl.cl_pos) :: @@ -4879,14 +4467,15 @@ struct | _ -> let is_override = List.memq cf cl.cl_overrides in let cf_type = if is_override && not (Meta.has Meta.Overload cf.cf_meta) then - match field_access gen (TInst(cl, List.map snd cl.cl_params)) cf.cf_name with - | FClassField(_,_,_,_,_,actual_t,_) -> actual_t + match find_first_declared_field gen cl cf.cf_name with + | Some(_,_,declared_t,_,_,_,_) -> declared_t | _ -> assert false else cf.cf_type in - not (has_type_params cf_type)) cl.cl_ordered_fields + not (has_type_params cf_type) + ) cl.cl_ordered_fields in let fields = List.map (fun f -> mk_class_field f.cf_name f.cf_type f.cf_public f.cf_pos f.cf_kind f.cf_params) fields in let fields = iface_cf :: fields in @@ -4945,13 +4534,11 @@ struct in run - let configure gen traverse = + let configure gen (dyn_tparam_cast:texpr->t->texpr) ifaces base_generic = gen.ghas_tparam_cast_handler <- true; + let traverse = default_implementation gen dyn_tparam_cast ifaces in let map e = Some(traverse e) in - gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map - - let default_config gen (dyn_tparam_cast:texpr->t->texpr) ifaces base_generic = - configure gen (default_implementation gen dyn_tparam_cast ifaces); + gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map; RealTypeParamsModf.configure gen (RealTypeParamsModf.default_implementation gen ifaces base_generic) end;; @@ -5053,12 +4640,6 @@ struct end;; - - let configure gen (param_func_call:texpr->texpr->tparams->texpr list->texpr) = - (*let map e = Some(mapping_func e) in - gen.gexpr_filters#add ~name:name ~priority:(PCustom priority) map*) - gen.gparam_func_call <- param_func_call - end;; (**************************************************************************************************************************) @@ -5068,9 +4649,7 @@ end;; (* ******************************************* *) (* Expression Unwrap *) (* ******************************************* *) - (* - This is the most important module for source-code based targets. It will follow a convention of what's an expression and what's a statement, and will unwrap statements where expressions are expected, and vice-versa. @@ -5091,10 +4670,8 @@ end;; TODO : While statement must become do / while, with the actual block inside an if for the condition, and else for 'break' *) - module ExpressionUnwrap = struct - let name = "expression_unwrap" (* priority: first syntax filter *) @@ -5226,8 +4803,6 @@ struct { expr with eexpr = TWhile(fn cond, block, flag) } | TSwitch(cond, el_block_l, default) -> { expr with eexpr = TSwitch( fn cond, List.map (fun (el,block) -> (List.map fn el, block)) el_block_l, default ) } -(* | TMatch(cond, enum, cases, default) -> - { expr with eexpr = TMatch(fn cond, enum, cases, default) } *) | TReturn(eopt) -> { expr with eexpr = TReturn(Option.map fn eopt) } | TThrow (texpr) -> @@ -5267,7 +4842,7 @@ struct (* statement (CS0201). *) let rec shallow_expr_type expr : shallow_expr_type = match expr.eexpr with - | TCall _ when not (is_void expr.etype) -> Both expr + | TCall _ when not (ExtType.is_void expr.etype) -> Both expr | TNew _ | TUnop (Ast.Increment, _, _) | TUnop (Ast.Decrement, _, _) @@ -5419,8 +4994,6 @@ struct { right with eexpr = TBlock(apply_assign_block assign_fun el) } | TSwitch (cond, elblock_l, default) -> { right with eexpr = TSwitch(cond, List.map (fun (el,block) -> (el, mk_get_block assign_fun block)) elblock_l, Option.map (mk_get_block assign_fun) default) } -(* | TMatch (cond, ep, il_vlo_e_l, default) -> - { right with eexpr = TMatch(cond, ep, List.map (fun (il,vlo,e) -> (il,vlo,mk_get_block assign_fun e)) il_vlo_e_l, Option.map (mk_get_block assign_fun) default) } *) | TTry (block, catches) -> { right with eexpr = TTry(mk_get_block assign_fun block, List.map (fun (v,block) -> (v,mk_get_block assign_fun block) ) catches) } | TIf (cond,eif,eelse) -> @@ -5580,14 +5153,14 @@ struct let handle_assign op left right = let left = check_left left in - Some (apply_assign (fun e -> { e with eexpr = TBinop(op, left, if is_void left.etype then e else gen.ghandle_cast left.etype e.etype e) }) right ) + Some (apply_assign (fun e -> { e with eexpr = TBinop(op, left, if ExtType.is_void left.etype then e else gen.ghandle_cast left.etype e.etype e) }) right ) in let handle_return e = Some( apply_assign (fun e -> match e.eexpr with | TThrow _ -> e - | _ when is_void e.etype -> + | _ when ExtType.is_void e.etype -> { e with eexpr = TBlock([e; { e with eexpr = TReturn None }]) } | _ -> { e with eexpr = TReturn( Some e ) } @@ -5631,9 +5204,7 @@ struct Some (null expr.etype expr.epos) | _ -> None - - let traverse gen (on_expr_as_statement:texpr->texpr option) = - + let configure gen (on_expr_as_statement:texpr->texpr option) = let add_assign = add_assign gen in let problematic_expression_unwrap add_statement expr e_type = @@ -5726,8 +5297,6 @@ struct { e with eexpr = TBlock(block) } | TTry (block, catches) -> { e with eexpr = TTry(traverse (mk_block block), List.map (fun (v,block) -> (v, traverse (mk_block block))) catches) } -(* | TMatch (cond,ep,il_vol_e_l,default) -> - { e with eexpr = TMatch(cond,ep,List.map (fun (il,vol,e) -> (il,vol,traverse (mk_block e))) il_vol_e_l, Option.map (fun e -> traverse (mk_block e)) default) } *) | TSwitch (cond,el_e_l, default) -> { e with eexpr = TSwitch(cond, List.map (fun (el,e) -> (el, traverse (mk_block e))) el_e_l, Option.map (fun e -> traverse (mk_block e)) default) } | TWhile (cond,block,flag) -> @@ -5740,12 +5309,8 @@ struct { e with eexpr = TFunction({ tfunc with tf_expr = traverse (mk_block tfunc.tf_expr) }) } | _ -> e (* if expression doesn't have a block, we will exit *) in - traverse - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(traverse e) in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map - end;; (* ******************************************* *) @@ -5820,7 +5385,7 @@ struct (* a return must be inside a function *) let ret_type = match !current_ret_type with | Some(s) -> s | None -> gen.gcon.error "Invalid return outside function declaration." e.epos; assert false in (match eopt with - | None when not (is_void ret_type) -> + | None when not (ExtType.is_void ret_type) -> { e with eexpr = TReturn( Some(null ret_type e.epos)) } | None -> e | Some eret -> @@ -5867,8 +5432,6 @@ struct | TFun(args,ret) -> args,ret | _ -> trace (debug_type t); assert false - let s_path (pack,n) = (String.concat "." (pack @ [n])) - (* Since this function is applied under native-context only, the type paraters will already be changed *) @@ -5876,14 +5439,18 @@ struct let rec loop c tl = if c == super then fn c tl - else (match c.cl_super with - | None -> false - | Some (cs,tls) -> - let tls = gen.greal_type_param (TClassDecl cs) tls in - loop cs (List.map (apply_params c.cl_params tl) tls) - ) || (if also_implements then List.exists (fun (cs,tls) -> - loop cs (List.map (apply_params c.cl_params tl) tls) - ) c.cl_implements else false) + else + (match c.cl_super with + | None -> false + | Some (cs,tls) -> + let tls = gen.greal_type_param (TClassDecl cs) tls in + loop cs (List.map (apply_params c.cl_params tl) tls) + ) + || + (if also_implements then + List.exists (fun (cs,tls) -> loop cs (List.map (apply_params c.cl_params tl) tls)) c.cl_implements + else + false) in loop @@ -5961,9 +5528,19 @@ struct (* will return true if both arguments are compatible. If it's not the case, a runtime error is very likely *) let is_cl_related gen cl tl super superl = - let is_cl_related cl tl super superl = map_cls gen (gen.guse_tp_constraints || (match cl.cl_kind,super.cl_kind with KTypeParameter _, _ | _,KTypeParameter _ -> false | _ -> true)) (fun _ _ -> true) super cl tl in + let is_cl_related cl tl super superl = map_cls gen (match cl.cl_kind,super.cl_kind with KTypeParameter _, _ | _,KTypeParameter _ -> false | _ -> true) (fun _ _ -> true) super cl tl in is_cl_related cl tl super superl || is_cl_related super superl cl tl + let is_exactly_basic gen t1 t2 = + match gen.gfollow#run_f t1, gen.gfollow#run_f t2 with + | TAbstract(a1, []), TAbstract(a2, []) -> + a1 == a2 && Common.defined gen.gcon Define.FastCast + | TInst(c1, []), TInst(c2, []) -> + c1 == c2 && Common.defined gen.gcon Define.FastCast + | TEnum(e1, []), TEnum(e2, []) -> + e1 == e2 && Common.defined gen.gcon Define.FastCast + | _ -> + false let rec is_unsafe_cast gen to_t from_t = match (follow to_t, follow from_t) with @@ -6049,19 +5626,21 @@ struct let do_unsafe_cast () = do_unsafe_cast gen real_from_t real_to_t { e with etype = real_from_t } in let to_t, from_t = real_to_t, real_from_t in - let mk_cast t e = + let mk_cast fast t e = match e.eexpr with (* TThrow is always typed as Dynamic, we just need to type it accordingly *) | TThrow _ -> { e with etype = t } - | _ -> mk_cast t e + | _ -> if fast then mk_castfast t e else mk_cast t e in let e = { e with etype = real_from_t } in if try fast_eq real_to_t real_from_t with Invalid_argument("List.for_all2") -> false then e else match real_to_t, real_from_t with (* string is the only type that can be implicitly converted from any other *) + | TInst( { cl_path = ([], "String") }, []), TInst( { cl_path = ([], "String") }, [] ) -> + mk_cast true to_t e | TInst( { cl_path = ([], "String") }, []), _ -> - mk_cast to_t e + mk_cast false to_t e | TInst(cl_to, params_to), TInst(cl_from, params_from) -> let ret = ref None in (* @@ -6072,7 +5651,7 @@ struct If a class is found - meaning that the cl_from can be converted without a cast into cl_to, we still need to check their type parameters. *) - ignore (map_cls gen (gen.guse_tp_constraints || (match cl_from.cl_kind,cl_to.cl_kind with KTypeParameter _, _ | _,KTypeParameter _ -> false | _ -> true)) (fun _ tl -> + ignore (map_cls gen (match cl_from.cl_kind,cl_to.cl_kind with KTypeParameter _, _ | _,KTypeParameter _ -> false | _ -> true) (fun _ tl -> try (* type found, checking type parameters *) List.iter2 (type_eq gen EqStrict) tl params_to; @@ -6085,7 +5664,7 @@ struct if we are already handling type parameter casts on other part of code (e.g. RealTypeParameters), we'll just make a cast to indicate that this place needs type parameter-involved casting *) - ret := Some (mk_cast to_t e); + ret := Some (mk_cast true to_t e); true end else (* @@ -6094,16 +5673,16 @@ struct *) try List.iter2 (type_eq gen EqRightDynamic) tl params_to; - ret := Some (mk_cast to_t e); + ret := Some (mk_cast true to_t e); true with | Unify_error _ -> - ret := Some (mk_cast to_t (mk_cast (TInst(cl_to, List.map (fun _ -> t_dynamic) params_to)) e)); + ret := Some (mk_cast true to_t (mk_cast true (TInst(cl_to, List.map (fun _ -> t_dynamic) params_to)) e)); true ) cl_to cl_from params_from); if is_some !ret then get !ret else if is_cl_related gen cl_from params_from cl_to params_to then - mk_cast to_t e + mk_cast true to_t e else (* potential unsafe cast *) (do_unsafe_cast ()) @@ -6115,18 +5694,18 @@ struct | TMono _, _ | TDynamic _, _ | TAnon _, _ when gen.gneeds_box real_from_t -> - mk_cast to_t e + mk_cast false to_t e | TMono _, _ | TDynamic _, _ -> e | _, TMono _ - | _, TDynamic _ -> mk_cast to_t e + | _, TDynamic _ -> mk_cast false to_t e | TAnon (a_to), TAnon (a_from) -> if a_to == a_from then e else if type_iseq gen to_t from_t then (* FIXME apply unify correctly *) e else - mk_cast to_t e + mk_cast true to_t e | _, TAnon(anon) -> (try let p2 = match !(anon.a_status) with | Statics c -> TInst(c,List.map (fun _ -> t_dynamic) c.cl_params) @@ -6139,7 +5718,7 @@ struct | _ -> assert false in handle_cast gen e real_to_t (gen.greal_type (TAbstract(tclass, [p2]))) with | Not_found -> - mk_cast to_t e) + mk_cast false to_t e) | TAbstract (a_to, _), TAbstract(a_from, _) when a_to == a_from -> e | TAbstract _, TInst({ cl_kind = KTypeParameter _ }, _) @@ -6149,11 +5728,11 @@ struct | _, TAbstract _ -> (try unify from_t to_t; - mk_cast to_t e + mk_cast true to_t e with | Unify_error _ -> try unify to_t from_t; - mk_cast to_t e + mk_cast true to_t e with | Unify_error _ -> do_unsafe_cast()) | TEnum(e_to, []), TEnum(e_from, []) -> @@ -6200,13 +5779,13 @@ struct e | TType(t_to, _), TType(t_from,_) -> if gen.gspecial_needs_cast real_to_t real_from_t then - mk_cast to_t e + mk_cast false to_t e else e | TType _, _ when gen.gspecial_needs_cast real_to_t real_from_t -> - mk_cast to_t e + mk_cast false to_t e | _, TType _ when gen.gspecial_needs_cast real_to_t real_from_t -> - mk_cast to_t e + mk_cast false to_t e (*| TType(t_to, _), TType(t_from, _) -> if t_to.t_path = t_from.t_path then e @@ -6219,15 +5798,15 @@ struct if is_unsafe_cast gen real_to_t real_from_t then (* is_unsafe_cast will already follow both *) (do_unsafe_cast ()) else - mk_cast to_t e + mk_cast false to_t e | TAnon anon, _ -> if PMap.is_empty anon.a_fields then e else - mk_cast to_t e + mk_cast true to_t e | TFun(args, ret), TFun(args2, ret2) -> let get_args = List.map (fun (_,_,t) -> t) in - (try List.iter2 (type_eq gen (EqBothDynamic)) (ret :: get_args args) (ret2 :: get_args args2); e with | Unify_error _ | Invalid_argument("List.iter2") -> mk_cast to_t e) + (try List.iter2 (type_eq gen (EqBothDynamic)) (ret :: get_args args) (ret2 :: get_args args2); e with | Unify_error _ | Invalid_argument("List.iter2") -> mk_cast true to_t e) | _, _ -> do_unsafe_cast () @@ -6245,12 +5824,6 @@ struct in loop sup - let does_unify a b = - try - unify a b; - true - with | Unify_error _ -> false - (* this is a workaround for issue #1743, as FInstance() is returning the incorrect classfield *) let rec clean_t t = match follow t with | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> @@ -6361,8 +5934,16 @@ struct let args,ret = get_fun tfun in TFun(loop [] args elist, ret) - (* + let fastcast_if_needed gen expr real_to_t real_from_t = + if Common.defined gen.gcon Define.FastCast then begin + if type_iseq gen real_to_t real_from_t then + { expr with etype = real_to_t } + else + mk_castfast real_to_t { expr with etype=real_from_t } + end else + handle_cast gen expr real_to_t real_from_t + (* Type parameter handling It will detect if/what type parameters were used, and call the cast handler It will handle both TCall(TField) and TCall by receiving a texpr option field: e @@ -6402,6 +5983,14 @@ struct | TInst(_,params) -> params | _ -> params in + let local_mk_cast t expr = + (* handle_cast gen expr t expr.etype *) + if is_exactly_basic gen t expr.etype then + expr + else + mk_castfast t expr + in + let ecall = get e in let ef = ref ef in let is_overload = cf.cf_overloads <> [] || Meta.has Meta.Overload cf.cf_meta || (is_static && is_static_overload cl (field_name f)) in @@ -6419,9 +6008,9 @@ struct | FInstance(c,_,cf) | FClosure(Some (c,_),cf) -> (* get from overloads *) (* FIXME: this is a workaround for issue #1743 . Uncomment this code after it was solved *) - (* let t, cf = List.find (fun (t,cf2) -> cf == cf2) (Typeload.get_overloads cl (field_name f)) in *) + (* let t, cf = List.find (fun (t,cf2) -> cf == cf2) (Overloads.get_overloads cl (field_name f)) in *) (* cf, t, false *) - select_overload gen e1.etype (Typeload.get_overloads cl (field_name f)) cl.cl_params params, false + select_overload gen e1.etype (Overloads.get_overloads cl (field_name f)) cl.cl_params params, false | FStatic(c,f) -> (* workaround for issue #1743 *) (* f,f.cf_type, false *) @@ -6467,10 +6056,10 @@ struct in let error = error || (match follow actual_t with | TFun _ -> false | _ -> true) in if error then (* if error, ignore arguments *) - if is_void ecall.etype then + if ExtType.is_void ecall.etype then { ecall with eexpr = TCall({ e1 with eexpr = TField(!ef, f) }, elist ) } else - mk_cast ecall.etype { ecall with eexpr = TCall({ e1 with eexpr = TField(!ef, f) }, elist ) } + local_mk_cast ecall.etype { ecall with eexpr = TCall({ e1 with eexpr = TField(!ef, f) }, elist ) } else begin (* infer arguments *) (* let called_t = TFun(List.map (fun e -> "arg",false,e.etype) elist, ecall.etype) in *) @@ -6493,14 +6082,14 @@ struct (* check types list *) let new_ecall, elist = try let elist = List.map2 (fun applied (_,_,funct) -> - match is_overload, applied.eexpr with + match is_overload || real_fparams <> [], applied.eexpr with | true, TConst TNull -> - mk_cast (gen.greal_type funct) applied + mk_castfast (gen.greal_type funct) applied | true, _ -> (* when not (type_iseq gen (gen.greal_type applied.etype) funct) -> *) let ret = handle_cast gen applied (funct) (gen.greal_type applied.etype) in (match ret.eexpr with | TCast _ -> ret - | _ -> mk_cast (funct) ret) + | _ -> local_mk_cast (funct) ret) | _ -> handle_cast gen applied (funct) (gen.greal_type applied.etype) ) applied args_ft in @@ -6579,7 +6168,7 @@ struct (** overloads_cast_to_base argument will cast overloaded function types to the class that declared it. **) (** This is necessary for C#, and if true, will require the target to implement __as__, as a `quicker` form of casting **) - let default_implementation gen ?(native_string_cast = true) ?(overloads_cast_to_base = false) maybe_empty_t calls_parameters_explicitly = + let configure gen ?(overloads_cast_to_base = false) maybe_empty_t calls_parameters_explicitly = let handle e t1 t2 = handle_cast gen e (gen.greal_type t1) (gen.greal_type t2) in let in_value = ref false in @@ -6604,6 +6193,73 @@ struct | _ -> false in + let binop_type op main_expr e1 e2 = + let name = platform_name gen.gcon.platform in + let basic = gen.gcon.basic in + (* If either operand is of type decimal, the other operand is converted to type decimal, or a compile-time error occurs if the other operand is of type float or double. + * Otherwise, if either operand is of type double, the other operand is converted to type double. + * Otherwise, if either operand is of type float, the other operand is converted to type float. + * Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a compile-time error occurs if the other operand is of type sbyte, short, int, or long. + * Otherwise, if either operand is of type long, the other operand is converted to type long. + * Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int, both operands are converted to type long. + * Otherwise, if either operand is of type uint, the other operand is converted to type uint. + * Otherwise, both operands are converted to type int. + * *) + let t1, t2 = follow (run_follow gen e1.etype), follow (run_follow gen e2.etype) in + match t1, t2 with + | TAbstract(a1,[]), TAbstract(a2,[]) when a1 == a2 -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype } + | TInst(i1,[]), TInst(i2,[]) when i1 == i2 -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype } + | TInst({ cl_path = ([],"String") },[]), _ when op = OpAdd -> + { main_expr with eexpr = TBinop(op, e1, mk_cast basic.tstring e2); etype = basic.tstring } + | _, TInst({ cl_path = ([],"String") },[]) when op = OpAdd -> + { main_expr with eexpr = TBinop(op, mk_cast basic.tstring e1, e2); etype = basic.tstring } + | TAbstract({ a_path = ([], "Float") }, []), _ -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype } + | _, TAbstract({ a_path = ([], "Float") }, []) -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = e2.etype } + | TAbstract({ a_path = ([], "Single") }, []), _ -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype } + | _, TAbstract({ a_path = ([], "Single") }, []) -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = e2.etype } + | TAbstract({ a_path = ([pf], "UInt64") }, []), _ when pf = name -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype } + | _, TAbstract({ a_path = ([pf], "UInt64") }, []) when pf = name -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = e2.etype } + | TAbstract({ a_path = ([pf], "Int64") }, []), _ when pf = name -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype } + | _, TAbstract({ a_path = ([pf], "Int64") }, []) when pf = name -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = e2.etype } + | TAbstract({ a_path = ([], "UInt") }, []), tother when like_int tother -> + let ti64 = mt_to_t_dyn ( get_type gen ([name], "Int64") ) in + let ret = { main_expr with eexpr = TBinop(op, e1, e2); etype = ti64 } in + if op <> OpDiv then + mk_cast t1 ret + else + ret + | tother, TAbstract({ a_path = ([], "UInt") }, []) when like_int tother -> + let ti64 = mt_to_t_dyn ( get_type gen ([name], "Int64") ) in + let ret = { main_expr with eexpr = TBinop(op, e1, e2); etype = ti64 } in + if op <> OpDiv then + mk_cast t2 ret + else + ret + | TAbstract({ a_path = ([], "UInt") }, []), _ -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype } + | _, TAbstract({ a_path = ([], "UInt") }, []) -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = e2.etype } + | TAbstract(a1,[]), TAbstract(a2,[]) -> + { main_expr with eexpr = TBinop(op, e1, e2); etype = basic.tint } + | _ -> + { main_expr with eexpr = TBinop(op, e1, e2) } + in + let binop_type = if Common.defined gen.gcon Define.FastCast then + binop_type + else + fun op main_expr e1 e2 -> { main_expr with eexpr = TBinop(op, e1, e2) } + in + let rec run ?(just_type = false) e = let handle = if not just_type then handle else fun e t1 t2 -> { e with etype = gen.greal_type t2 } in let was_in_value = !in_value in @@ -6632,7 +6288,12 @@ struct | TBinop ( (Ast.OpShl | Ast.OpShr | Ast.OpUShr as op), e1, e2 ) -> let e1 = run e1 in let e2 = handle (run e2) (gen.gcon.basic.tint) e2.etype in - { e with eexpr = TBinop(op, e1, e2) } + let rett = binop_type op e e1 e2 in + { e with eexpr = TBinop(op, e1, e2); etype = rett.etype } + | TBinop( (OpAdd | OpMult | OpDiv | OpSub | OpAnd | OpOr | OpXor | OpMod) as op, e1, e2 ) -> + binop_type op e (run e1) (run e2) + | TBinop( (OpEq | OpNotEq | OpGt | OpGte | OpLt | OpLte | OpBoolAnd | OpBoolOr) as op, e1, e2 ) -> + handle { e with eexpr = TBinop(op, run e1, run e2) } e.etype gen.gcon.basic.tbool | TField(ef, f) -> handle_type_parameter gen None e (run ef) ~clean_ef:ef ~overloads_cast_to_base:overloads_cast_to_base f [] calls_parameters_explicitly | TArrayDecl el -> @@ -6642,7 +6303,7 @@ struct | _ -> gen.gcon.warning (debug_type et) e.epos; (match gen.gcurrent_class with - | Some cl -> print_endline (path_s cl.cl_path) + | Some cl -> print_endline (s_type_path cl.cl_path) | _ -> ()); assert false in @@ -6718,15 +6379,17 @@ struct { e with eexpr = TNew(cl, tparams, List.map run eparams) }) | TArray(arr, idx) -> let arr_etype = match follow arr.etype with - | (TInst _ as t) -> t - | TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) -> - follow (Abstract.get_underlying_type a pl) - | t -> t in + | (TInst _ as t) -> t + | TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) -> + follow (Abstract.get_underlying_type a pl) + | t -> t + in + let idx = run idx in let idx = match gen.greal_type idx.etype with - | TAbstract({ a_path = [],"Int" },_) -> run idx - | _ -> match handle (run idx) gen.gcon.basic.tint (gen.greal_type idx.etype) with - | ({ eexpr = TCast _ } as idx) -> idx - | idx -> mk_cast gen.gcon.basic.tint idx + | TAbstract({ a_path = [],"Int" },_) -> idx + | _ -> match handle idx gen.gcon.basic.tint (gen.greal_type idx.etype) with + | ({ eexpr = TCast _ } as idx) -> idx + | idx -> mk_cast gen.gcon.basic.tint idx in let e = { e with eexpr = TArray(run arr, idx) } in (* get underlying class (if it's a class *) @@ -6742,7 +6405,8 @@ struct let real_t = apply_params cl.cl_params params param in (* see if it needs a cast *) - handle (e) (gen.greal_type e.etype) (gen.greal_type real_t) + fastcast_if_needed gen e (gen.greal_type e.etype) (gen.greal_type real_t) + (* handle (e) (gen.greal_type e.etype) (gen.greal_type real_t) *) ) | _ -> Type.map_expr run e) | TVar (v, eopt) -> @@ -6759,8 +6423,6 @@ struct { e with eexpr = TWhile (handle (run econd) gen.gcon.basic.tbool econd.etype, (in_value := false; run (mk_block e1)), flag) } | TSwitch (cond, el_e_l, edef) -> { e with eexpr = TSwitch(run cond, List.map (fun (el,e) -> (List.map run el, (in_value := false; run (mk_block e)))) el_e_l, Option.map (fun e -> in_value := false; run (mk_block e)) edef) } -(* | TMatch (cond, en, il_vl_e_l, edef) -> - { e with eexpr = TMatch(run cond, en, List.map (fun (il, vl, e) -> (il, vl, run (mk_block e))) il_vl_e_l, Option.map (fun e -> run (mk_block e)) edef) } *) | TFor (v,cond,e1) -> { e with eexpr = TFor(v, run cond, (in_value := false; run (mk_block e1))) } | TTry (e, ve_l) -> @@ -6774,7 +6436,7 @@ struct in_value := false; run e ) el ) } - | TCast (expr, md) when is_void (follow e.etype) -> + | TCast (expr, md) when ExtType.is_void (follow e.etype) -> run expr | TCast (expr, md) -> let rec get_null e = @@ -6792,6 +6454,8 @@ struct mk_cast (gen.greal_type e.etype) enull | _ when is_abstract_to_struct expr.etype && type_iseq gen e.etype (get_abstract_impl expr.etype) -> run { expr with etype = expr.etype } + | _ when is_exactly_basic gen expr.etype e.etype -> + run { expr with etype = expr.etype } | _ -> match gen.greal_type e.etype, gen.greal_type expr.etype with | (TInst(c,tl) as tinst1), TAbstract({ a_path = ["cs"],"Pointer" }, [tinst2]) when type_iseq gen tinst1 (gen.greal_type tinst2) -> @@ -6814,11 +6478,13 @@ struct | _ -> Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = gen.ghandle_cast <- (fun tto tfrom expr -> handle_cast gen expr (gen.greal_type tto) (gen.greal_type tfrom)); - let map e = Some(mapping_func e) in + let map e = match gen.gcurrent_classfield with + | Some(cf) when Meta.has (Meta.Custom ":skipCastDetect") cf.cf_meta -> + None + | _ -> + Some(run e) + in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map; ReturnCast.configure gen @@ -6835,12 +6501,12 @@ end;; of strategies between what should have been different modules, they are all unified in this reflection-enabling class fields. They include: - * Get(isStatic, throwErrors, isCheck) / Set fields . Remember to allow implements Dynamic also. - * Invoke fields(isStatic) -> You need to configure how many invoke_field fields there will be. + invokeDynamic + * Get(throwErrors, isCheck) / Set fields . Remember to allow implements Dynamic also. + * Invoke fields() -> You need to configure how many invoke_field fields there will be. + invokeDynamic * Has field -> parameter in get field that returns __undefined__ if it doesn't exist. * GetType -> return the current Class<> / Enum<> - * Fields(isStatic) -> returns all the fields / static fields. Remember to allow implements Dynamic also + * Fields() -> returns all the fields / static fields. Remember to allow implements Dynamic also * Create(arguments array), CreateEmpty - calls new() or create empty * getInstanceFields / getClassFields -> show even function fields, everything! @@ -6894,30 +6560,23 @@ struct let name = "reflection_cfs" + type rcf_hash_conflict_ctx = { + t : t; + add_names : texpr->texpr->texpr; + get_conflict : texpr->texpr->texpr->texpr; + set : texpr->texpr->texpr->texpr->texpr; + delete : texpr->texpr->texpr->texpr; + } + type rcf_ctx = { rcf_gen : generator_ctx; rcf_ft : ClosuresToClass.closures_ctx; rcf_optimize : bool; - mutable rcf_float_special_case : bool; - mutable rcf_object_iface : tclass; - - mutable rcf_create_getsetinvoke_fields : bool; - (* should we create the get type (get Class)? *) - mutable rcf_create_get_type : bool; - (* should we handle implements dynamic? *) - mutable rcf_handle_impl_dynamic : bool; - (* - create_dyn_overloading_ctor : - when creating the implements dynamic code, we can also create a special constructor for - the actual DynamicObject class, which will receive all its fields from the code outside. - Note that this will only work on targets that support overloading contrstuctors, as any class that extends - our DynamicObject will have an empty super() call - *) - mutable rcf_create_dyn_ctor : bool; + rcf_object_iface : tclass; - mutable rcf_max_func_arity : int; + rcf_max_func_arity : int; (* the hash lookup function. can be an inlined expr or simply a function call. @@ -6926,63 +6585,41 @@ struct hash->hash_array->length->returning expression *) - mutable rcf_hash_function : texpr->texpr->texpr->texpr; + rcf_hash_function : texpr->texpr->texpr->texpr; - mutable rcf_lookup_function : texpr->texpr; + rcf_lookup_function : texpr->texpr; (* hash_array->length->pos->value *) - mutable rcf_insert_function : texpr->texpr->texpr->texpr->texpr; + rcf_insert_function : texpr->texpr->texpr->texpr->texpr; (* hash_array->length->pos->value *) - mutable rcf_remove_function : texpr->texpr->texpr->texpr; - - (* - class_cl is the real class for Class<> instances. - In the current implementation, due to some targets' limitations, (in particular, Java), - we have to use an empty object so we can access its virtual mehtods. - FIXME find a better way to create Class<> objects in a performant way - *) - mutable rcf_class_cl : tclass option; - (* - Also about the Class<> type, should we crate all classes eagerly? - If false, it means that we should have a way at runtime to create the class when needed by - Type.resolveClass/Enum - *) - mutable rcf_class_eager_creation : bool; + rcf_remove_function : texpr->texpr->texpr->texpr; rcf_hash_fields : (int, string) Hashtbl.t; rcf_hash_paths : (path * int, string) Hashtbl.t; + rcf_hash_conflict_ctx : rcf_hash_conflict_ctx option; + (* main expr -> field expr -> field string -> possible hash int (if optimize) -> possible set expr -> should_throw_exceptions -> changed expression Changes a get / set field to the runtime resolution function *) - mutable rcf_on_getset_field : texpr->texpr->string->int32 option->texpr option->bool->texpr; - - mutable rcf_on_call_field : texpr->texpr->string->int32 option->texpr list->texpr; + rcf_on_getset_field : texpr->texpr->string->int32 option->texpr option->bool->texpr; - mutable rcf_handle_statics : bool; + rcf_on_call_field : texpr->texpr->string->int32 option->texpr list->texpr; } - let new_ctx gen ft object_iface optimize dynamic_getset_field dynamic_call_field hash_function lookup_function insert_function remove_function handle_statics = + let new_ctx gen ft object_iface optimize dynamic_getset_field dynamic_call_field hash_function lookup_function insert_function remove_function hash_conflict_ctx = { rcf_gen = gen; rcf_ft = ft; rcf_optimize = optimize; - rcf_float_special_case = true; - rcf_object_iface = object_iface; - rcf_create_getsetinvoke_fields = true; - rcf_create_get_type = true; - - rcf_handle_impl_dynamic = true; - rcf_create_dyn_ctor = true; - rcf_max_func_arity = 10; rcf_hash_function = hash_function; @@ -6991,16 +6628,12 @@ struct rcf_insert_function = insert_function; rcf_remove_function = remove_function; - rcf_class_cl = None; - rcf_class_eager_creation = false; - rcf_hash_fields = Hashtbl.create 100; rcf_hash_paths = Hashtbl.create 100; rcf_on_getset_field = dynamic_getset_field; rcf_on_call_field = dynamic_call_field; - - rcf_handle_statics = handle_statics; + rcf_hash_conflict_ctx = hash_conflict_ctx; } (* @@ -7009,7 +6642,7 @@ struct Some(true) means collect only methods Some(false) means collect only fields (and MethDynamic fields) *) - let collect_fields cl (methods : bool option) (statics : bool option) = + let collect_fields cl (methods : bool option) = let collected = Hashtbl.create 0 in let collect cf acc = if Meta.has Meta.CompilerGenerated cf.cf_meta || Meta.has Meta.SkipReflection cf.cf_meta then @@ -7031,11 +6664,7 @@ struct loop cfs acc in let rec loop cl acc = - let acc = match statics with - | None -> collect_cfs cl.cl_ordered_fields (collect_cfs cl.cl_ordered_statics acc) - | Some true -> collect_cfs cl.cl_ordered_statics acc - | Some false -> collect_cfs cl.cl_ordered_fields acc - in + let acc = collect_cfs cl.cl_ordered_fields acc in match cl.cl_super with | None -> acc | Some(cl,_) -> @@ -7083,51 +6712,9 @@ struct match ctx.rcf_optimize with | true -> let i = hash_field_i32 ctx pos field_name in - { eexpr = TConst(TInt(i)); etype = ctx.rcf_gen.gcon.basic.tint; epos = pos } + mk (TConst (TInt i)) ctx.rcf_gen.gcon.basic.tint pos | false -> - { eexpr = TConst(TString(field_name)); etype = ctx.rcf_gen.gcon.basic.tstring; epos = pos } - - (* - Will implement getField / setField which will follow the following rule: - function getField(field, isStatic, throwErrors, isCheck, handleProperty, isFirst):Dynamic - { - if (isStatic) - { - switch(field) - { - case "aStaticField": return ThisClass.aStaticField; - case "aDynamicField": return ThisClass.aDynamicField; - default: - if (isFirst) return getField_d(field, isStatic, throwErrors, handleProperty, false); - if(throwErrors) throw "Field not found"; else if (isCheck) return __undefined__ else return null; - } - } else { - switch(field) - { - case "aNormalField": return this.aNormalField; - case "aBoolField": return this.aBoolField; - case "aDoubleField": return this.aDoubleField; - default: return getField_d(field, isStatic, throwErrors, isCheck); - } - } - } - - function getField_d(field, isStatic, throwErrors, handleProperty, isFirst):Float - { - if (isStatic) - { - switch(field) - { - case "aDynamicField": return cast ThisClass.aDynamicField; - default: if (throwErrors) throw "Field not found"; else return null; - } - } - etc... - } - - function setField(field, value, isStatic):Dynamic {} - function setField_d(field, value:Float, isStatic):Float {} - *) + ExprBuilder.make_string ctx.rcf_gen.gcon field_name pos let call_super ctx fn_args ret_t cf cl this_t pos = { @@ -7140,18 +6727,10 @@ struct epos = pos; } - let mk_string ctx str pos = - { eexpr = TConst(TString(str)); etype = ctx.rcf_gen.gcon.basic.tstring; epos = pos } - - let mk_int ctx i pos = - { eexpr = TConst(TInt(Int32.of_int i)); etype = ctx.rcf_gen.gcon.basic.tint; epos = pos } - - let mk_bool ctx b pos = - { eexpr = TConst(TBool(b)); etype = ctx.rcf_gen.gcon.basic.tbool; epos = pos } - let mk_throw ctx str pos = { eexpr = TThrow (mk_string ctx str pos); etype = ctx.rcf_gen.gcon.basic.tvoid; epos = pos } + let mk_throw ctx str pos = { eexpr = TThrow (ExprBuilder.make_string ctx.rcf_gen.gcon str pos); etype = ctx.rcf_gen.gcon.basic.tvoid; epos = pos } - let enumerate_dynamic_fields ctx cl when_found = + let enumerate_dynamic_fields ctx cl when_found base_arr = let gen = ctx.rcf_gen in let basic = gen.gcon.basic in let pos = cl.cl_pos in @@ -7162,22 +6741,18 @@ struct let t = if ctx.rcf_optimize then basic.tint else basic.tstring in let convert_str e = if ctx.rcf_optimize then ctx.rcf_lookup_function e else e in let tmpinc = { eexpr = TUnop(Ast.Increment, Ast.Postfix, mk_local vtmp pos); etype = basic.tint; epos = pos } in - { - eexpr = TBlock [ - { eexpr = TBinop(OpAssign, mk_local vtmp pos, mk_int ctx 0 pos); etype = basic.tint; epos = pos }; - { - eexpr = TWhile ( - { eexpr = TBinop(Ast.OpLt, mk_local vtmp pos, len); etype = basic.tbool; epos = pos }, - mk_block (when_found (convert_str { eexpr = TArray (arr, tmpinc); etype = t; epos = pos })), - Ast.NormalWhile - ); - etype = basic.tvoid; - epos = pos - } - ]; - etype = basic.tvoid; - epos = pos; - } + [ + { eexpr = TBinop(OpAssign, mk_local vtmp pos, ExprBuilder.make_int ctx.rcf_gen.gcon 0 pos); etype = basic.tint; epos = pos }; + { + eexpr = TWhile ( + { eexpr = TBinop(Ast.OpLt, mk_local vtmp pos, len); etype = basic.tbool; epos = pos }, + mk_block (when_found (convert_str { eexpr = TArray (arr, tmpinc); etype = t; epos = pos })), + Ast.NormalWhile + ); + etype = basic.tvoid; + epos = pos + } + ] in let this_t = TInst(cl, List.map snd cl.cl_params) in @@ -7187,13 +6762,19 @@ struct { eexpr = TVar (vtmp,None); etype = basic.tvoid; epos = pos } :: if ctx.rcf_optimize then - [ - mk_for (mk_this (gen.gmk_internal_name "hx" "hashes") (gen.gclasses.nativearray basic.tint)) (mk_this (gen.gmk_internal_name "hx" "length") basic.tint); - mk_for (mk_this (gen.gmk_internal_name "hx" "hashes_f") (gen.gclasses.nativearray basic.tint)) (mk_this (gen.gmk_internal_name "hx" "length_f") basic.tint); - ] else [ - mk_for (mk_this (gen.gmk_internal_name "hx" "hashes") (gen.gclasses.nativearray basic.tstring)) (mk_this (gen.gmk_internal_name "hx" "length") basic.tint); - mk_for (mk_this (gen.gmk_internal_name "hx" "hashes_f") (gen.gclasses.nativearray basic.tstring)) (mk_this (gen.gmk_internal_name "hx" "length_f") basic.tint); - ] + mk_for (mk_this (gen.gmk_internal_name "hx" "hashes") (gen.gclasses.nativearray basic.tint)) (mk_this (gen.gmk_internal_name "hx" "length") basic.tint) + @ + mk_for (mk_this (gen.gmk_internal_name "hx" "hashes_f") (gen.gclasses.nativearray basic.tint)) (mk_this (gen.gmk_internal_name "hx" "length_f") basic.tint) + @ + ( + let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in + let ehead = mk_this (gen.gmk_internal_name "hx" "conflicts") conflict_ctx.t in + [conflict_ctx.add_names ehead base_arr] + ) + else + mk_for (mk_this (gen.gmk_internal_name "hx" "hashes") (gen.gclasses.nativearray basic.tstring)) (mk_this (gen.gmk_internal_name "hx" "length") basic.tint) + @ + mk_for (mk_this (gen.gmk_internal_name "hx" "hashes_f") (gen.gclasses.nativearray basic.tstring)) (mk_this (gen.gmk_internal_name "hx" "length_f") basic.tint) (* ********************* Dynamic lookup @@ -7207,7 +6788,7 @@ struct A binary search or linear search algorithm may be implemented. The only need is that if not found, the NegBits of the place where it should be inserted must be returned. *) - let abstract_dyn_lookup_implementation ctx this hash_local may_value is_float pos = + let abstract_dyn_lookup_implementation ctx this field_local hash_local may_value is_float pos = let gen = ctx.rcf_gen in let basic = gen.gcon.basic in let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in @@ -7268,7 +6849,26 @@ struct epos = pos; })); etype = ret_t; epos = pos } ] in - block + + if ctx.rcf_optimize then + let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in + let ehead = mk_this (gen.gmk_internal_name "hx" "conflicts") conflict_ctx.t in + let vconflict = alloc_var "conflict" conflict_ctx.t in + let local_conflict = mk_local vconflict pos in + [mk (TIf ( + mk (TBinop (OpLt, hash_local, ExprBuilder.make_int gen.gcon 0 pos)) basic.tbool pos, + mk (TBlock [ + mk (TVar (vconflict, Some (conflict_ctx.get_conflict ehead hash_local field_local))) basic.tvoid pos; + mk (TIf ( + mk (TBinop (OpNotEq, local_conflict, mk (TConst TNull) local_conflict.etype pos)) basic.tbool pos, + mk_return (Codegen.field local_conflict "value" t_dynamic pos), + None + )) basic.tvoid pos; + ]) basic.tvoid pos, + Some (mk (TBlock block) basic.tvoid pos) + )) basic.tvoid pos] + else + block | Some value_local -> (* //if is not float: @@ -7324,9 +6924,21 @@ struct ctx.rcf_insert_function fst_hash fst_length neg_res hash_local; ctx.rcf_insert_function fst_dynamics fst_length neg_res value_local; mk (TUnop(Increment,Postfix,fst_length)) basic.tint pos; - mk_return value_local ] in - block + + let block = + if ctx.rcf_optimize then + let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in + let ehead = mk_this (gen.gmk_internal_name "hx" "conflicts") conflict_ctx.t in + [mk (TIf ( + mk (TBinop (OpLt, hash_local, ExprBuilder.make_int gen.gcon 0 pos)) basic.tbool pos, + conflict_ctx.set ehead hash_local field_local value_local, + Some (mk (TBlock block) basic.tvoid pos) + )) basic.tvoid pos] + else + block + in + block @ [mk_return value_local] let get_delete_field ctx cl is_dynamic = let pos = cl.cl_pos in @@ -7375,7 +6987,7 @@ struct return false; *) - [ + let common = [ { eexpr = TVar(res,Some(ctx.rcf_hash_function local_switch_var hx_hashes hx_length)); etype = basic.tvoid; epos = pos }; { eexpr = TIf(gte, { eexpr = TBlock([ @@ -7396,7 +7008,20 @@ struct epos = pos; }; mk_return { eexpr = TConst(TBool false); etype = basic.tbool; epos = pos } - ] + ] in + + if ctx.rcf_optimize then + let v_name = match tf_args with (v,_) :: _ -> v | _ -> assert false in + let local_name = mk_local v_name pos in + let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in + let ehead = mk_this (gen.gmk_internal_name "hx" "conflicts") conflict_ctx.t in + (mk (TIf ( + mk (TBinop (OpLt, local_switch_var, ExprBuilder.make_int gen.gcon 0 pos)) basic.tbool pos, + mk (TReturn (Some (conflict_ctx.delete ehead local_switch_var local_name))) basic.tvoid pos, + None + )) basic.tvoid pos) :: common + else + common end else [ mk_return { eexpr = TConst(TBool false); etype = basic.tbool; epos = pos } @@ -7548,10 +7173,9 @@ struct let may_hash_field s = if ctx.rcf_optimize then begin - (* let hash_field ctx f pos = *) - { eexpr = TConst(TInt (hash_field_i32 ctx pos s)); etype = basic.tint; epos = pos } + mk (TConst (TInt (hash_field_i32 ctx pos s))) basic.tint pos end else begin - { eexpr = TConst(TString s); etype = basic.tstring; epos = pos } + ExprBuilder.make_string gen.gcon s pos end in @@ -7627,6 +7251,14 @@ struct List.iter (fun cf -> cf.cf_expr <- Some { eexpr = TCall(mk_local v_nativearray pos, []); etype = cf.cf_type; epos = cf.cf_pos }) new_fields ); + let new_fields = + if ctx.rcf_optimize then + let f = mk_class_field (gen.gmk_internal_name "hx" "conflicts") (Option.get ctx.rcf_hash_conflict_ctx).t false pos (Var { v_read = AccNormal; v_write = AccNormal }) [] in + f :: new_fields + else + new_fields + in + let delete = get_delete_field ctx cl true in let new_fields = new_fields @ [ @@ -7666,101 +7298,24 @@ struct cl.cl_fields <- PMap.add delete.cf_name delete cl.cl_fields end - let implement_create_empty ctx cl = + + (* + Implements: + __hx_lookupField(field:String, throwErrors:Bool, isCheck:Bool, handleProperties:Bool, isFirst:Bool):Dynamic + + __hx_lookupField_f(field:String, throwErrors:Bool, handleProperties:Bool, isFirst:Bool):Float + + __hx_lookupSetField(field:String, value:Dynamic, handleProperties:Bool, isFirst:Bool):Dynamic; + + __hx_lookupSetField(field:String, value:Float, handleProperties:Bool, isFirst:Bool):Float; + *) + let implement_final_lookup ctx cl = let gen = ctx.rcf_gen in let basic = gen.gcon.basic in let pos = cl.cl_pos in let is_override = is_override cl in - let tparams = List.map (fun _ -> t_empty) cl.cl_params in - let create = - let arr = alloc_var "arr" (basic.tarray t_dynamic) in - let tf_args = [ arr, None ] in - let t = TFun(fun_args tf_args, t_dynamic) in - let cf = mk_class_field (gen.gmk_internal_name "hx" "create") t false pos (Method MethNormal) [] in - let i = ref 0 in - - let arr_local = mk_local arr pos in - let ctor = if is_some cl.cl_constructor then cl.cl_constructor else get_last_ctor cl in - let params = match ctor with - | None -> [] - | Some ctor -> - List.map (fun (n,_,t) -> - let old = !i in - incr i; - { - eexpr = TArray(arr_local, { eexpr = TConst(TInt (Int32.of_int old)); etype = basic.tint; epos = pos } ); - etype = t_dynamic; - epos = pos - } - ) ( fst ( get_fun ctor.cf_type ) ) - in - let expr = mk_return { - eexpr = TNew(cl, tparams, params); - etype = TInst(cl, tparams); - epos = pos - } in - let fn = { - eexpr = TFunction({ - tf_args = tf_args; - tf_type = t_dynamic; - tf_expr = mk_block expr - }); - etype = t; - epos = pos - } in - cf.cf_expr <- Some fn; - cf - in - - let create_empty = - let t = TFun([],t_dynamic) in - let cf = mk_class_field (gen.gmk_internal_name "hx" "createEmpty") t false pos (Method MethNormal) [] in - let fn = { - eexpr = TFunction({ - tf_args = []; - tf_type = t_dynamic; - tf_expr = mk_block (mk_return ( gen.gtools.rf_create_empty cl tparams pos )) - }); - etype = t; - epos = pos - } in - cf.cf_expr <- Some fn; - cf - in - - (* if rcf_handle_statics is false, there is no reason to make createEmpty/create not be static *) - if ctx.rcf_handle_statics then begin - cl.cl_ordered_fields <- cl.cl_ordered_fields @ [create_empty; create]; - cl.cl_fields <- PMap.add create_empty.cf_name create_empty cl.cl_fields; - cl.cl_fields <- PMap.add create.cf_name create cl.cl_fields; - if is_override then begin - cl.cl_overrides <- create_empty :: create :: cl.cl_overrides - end - end else begin - cl.cl_ordered_statics <- cl.cl_ordered_statics @ [create_empty; create]; - cl.cl_statics <- PMap.add create_empty.cf_name create_empty cl.cl_statics; - cl.cl_statics <- PMap.add create.cf_name create cl.cl_statics - end - - - (* - Implements: - __hx_lookupField(field:String, throwErrors:Bool, isCheck:Bool, handleProperties:Bool, isFirst:Bool):Dynamic - - __hx_lookupField_f(field:String, throwErrors:Bool, handleProperties:Bool, isFirst:Bool):Float - - __hx_lookupSetField(field:String, value:Dynamic, handleProperties:Bool, isFirst:Bool):Dynamic; - - __hx_lookupSetField(field:String, value:Float, handleProperties:Bool, isFirst:Bool):Float; - *) - let implement_final_lookup ctx cl = - let gen = ctx.rcf_gen in - let basic = gen.gcon.basic in - let pos = cl.cl_pos in - let is_override = is_override cl in - - let this = { eexpr = TConst(TThis); etype = TInst(cl, List.map snd cl.cl_params); epos = pos } in + let this = { eexpr = TConst(TThis); etype = TInst(cl, List.map snd cl.cl_params); epos = pos } in (* this function will create the class fields and call callback for each version @@ -7854,7 +7409,8 @@ struct (* callback : is_float fields_args switch_var throw_errors_option is_check_option value_option : texpr list *) if is_first_dynamic cl then create_cfs true (fun is_float fields_args switch_var _ _ value_opt -> - abstract_dyn_lookup_implementation ctx this (mk_local switch_var pos) (Option.map (fun v -> mk_local v pos) value_opt) is_float pos + let v_name = match fields_args with (v,_) :: _ -> v | _ -> assert false in + abstract_dyn_lookup_implementation ctx this (mk_local v_name pos) (mk_local switch_var pos) (Option.map (fun v -> mk_local v pos) value_opt) is_float pos ) end else if not is_override then begin create_cfs false (fun is_float fields_args switch_var _ _ value_opt -> @@ -7878,8 +7434,6 @@ struct let tf_args, switch_var = field_type_args ctx pos in let field_args = tf_args in let local_switch_var = { eexpr = TLocal(switch_var); etype = switch_var.v_type; epos = pos } in - let is_static = alloc_var "isStatic" basic.tbool in - let is_static_local = { eexpr = TLocal(is_static); etype = basic.tbool; epos = pos } in let handle_prop = alloc_var "handleProperties" basic.tbool in let handle_prop_local = mk_local handle_prop pos in @@ -7889,8 +7443,6 @@ struct { eexpr = TCall( { (mk_field_access gen this name pos) with etype = fun_t; }, params ); etype = snd (get_args fun_t); epos = pos } in - let tf_args = if ctx.rcf_handle_statics then tf_args @ [is_static, None] else tf_args in - let fun_type = ref (TFun([], basic.tvoid)) in let fun_name = ctx.rcf_gen.gmk_internal_name "hx" ( (if is_set then "setField" else "getField") ^ (if is_float then "_f" else "") ) in let cfield = mk_class_field fun_name !fun_type false pos (Method MethNormal) [] in @@ -7917,7 +7469,7 @@ struct in (* if it is set function, there are some different set fields to do *) - let do_default, do_default_static , do_field, tf_args = if is_set then begin + let do_default, do_field, tf_args = if is_set then begin let value_var = alloc_var "value" (if is_float then basic.tfloat else t_dynamic) in let value_local = { eexpr = TLocal(value_var); etype = value_var.v_type; epos = pos } in let tf_args = tf_args @ [value_var,None; handle_prop, None; ] in @@ -7928,9 +7480,9 @@ struct mk_return (mk_this_call_raw lookup_name (TFun(fun_args (field_args @ [value_var,None]),value_var.v_type)) ( List.map (fun (v,_) -> mk_local v pos) field_args @ [ value_local ] )) in - let do_field cf cf_type is_static = - let get_field ethis = { eexpr = TField (ethis, if is_static then FStatic (cl, cf) else FInstance(cl, List.map snd cl.cl_params, cf)); etype = cf_type; epos = pos } in - let this = if is_static then mk_classtype_access cl pos else { eexpr = TConst(TThis); etype = t; epos = pos } in + let do_field cf cf_type = + let get_field ethis = { eexpr = TField (ethis, FInstance(cl, List.map snd cl.cl_params, cf)); etype = cf_type; epos = pos } in + let this = { eexpr = TConst(TThis); etype = t; epos = pos } in let value_local = if is_float then match follow cf_type with | TInst({ cl_kind = KTypeParameter _ }, _) -> mk_cast t_dynamic value_local @@ -7977,9 +7529,8 @@ struct ret in - (mk_do_default tf_args do_default, do_default, do_field, tf_args) + (mk_do_default tf_args do_default, do_field, tf_args) end else begin - (* (field, isStatic, throwErrors, isCheck):Dynamic *) let throw_errors = alloc_var "throwErrors" basic.tbool in let throw_errors_local = mk_local throw_errors pos in let do_default, tf_args = if not is_float then begin @@ -8028,19 +7579,19 @@ struct { eexpr = TField (this, FClosure(Some (cl,[]), cf)); etype = cf_type; epos = pos } (* TODO: FClosure change *) in - let do_field cf cf_type static = - let this = if static then mk_classtype_access cl pos else { eexpr = TConst(TThis); etype = t; epos = pos } in + let do_field cf cf_type = + let this = { eexpr = TConst(TThis); etype = t; epos = pos } in match is_float, follow cf_type with | true, TInst( { cl_kind = KTypeParameter _ }, _ ) -> mk_return (mk_cast basic.tfloat (mk_cast t_dynamic (get_field cf cf_type this cl cf.cf_name))) | _ -> mk_return (maybe_cast (get_field cf cf_type this cl cf.cf_name )) in - (mk_do_default tf_args do_default, do_default, do_field, tf_args) + (mk_do_default tf_args do_default, do_field, tf_args) end in - let get_fields static = - let ret = collect_fields cl ( if is_float || is_set then Some (false) else None ) (Some static) in + let get_fields() = + let ret = collect_fields cl ( if is_float || is_set then Some (false) else None ) in let ret = if is_set then List.filter (fun (_,cf) -> match cf.cf_kind with (* | Var { v_write = AccNever } -> false *) @@ -8068,8 +7619,8 @@ struct fun_type := TFun(List.map (fun (v,_) -> (v.v_name, false, v.v_type)) tf_args, if is_float then basic.tfloat else t_dynamic ); let has_fields = ref false in - let mk_switch static = - let fields = get_fields static in + let content = + let fields = get_fields() in let fields = List.filter (fun (_, cf) -> match is_set, cf.cf_kind with | true, Var { v_write = AccCall } -> true | false, Var { v_read = AccCall } -> true @@ -8078,17 +7629,11 @@ struct (if fields <> [] then has_fields := true); let cases = List.map (fun (names, cf) -> (if names = [] then assert false); - (List.map (switch_case ctx pos) names, do_field cf cf.cf_type static) + (List.map (switch_case ctx pos) names, do_field cf cf.cf_type) ) fields in - let default = Some(if static then do_default_static() else do_default()) in - - { eexpr = TSwitch(local_switch_var, cases, default); etype = basic.tvoid; epos = pos } - in + let default = Some(do_default()) in - let content = if ctx.rcf_handle_statics then - mk_block { eexpr = TIf(is_static_local, mk_switch true, Some(mk_switch false)); etype = basic.tvoid; epos = pos } - else - mk_block (mk_switch false) + mk_block { eexpr = TSwitch(local_switch_var, cases, default); etype = basic.tvoid; epos = pos } in let is_override = match cl.cl_super with @@ -8115,434 +7660,86 @@ struct (if is_override then cl.cl_overrides <- cfield :: cl.cl_overrides) end else () in - (if ctx.rcf_float_special_case then mk_cfield true true); + mk_cfield true true; mk_cfield true false; mk_cfield false false; - (if ctx.rcf_float_special_case then mk_cfield false true) - - let mk_field_access_r ctx pos local field is_float is_static throw_errors set_option = - let is_set = is_some set_option in - let gen = ctx.rcf_gen in - let basic = gen.gcon.basic in - - let fun_name = ctx.rcf_gen.gmk_internal_name "hx" ( (if is_set then "setField" else "getField") ^ (if is_float then "_f" else "") ) in - let tf_args, _ = field_type_args ctx pos in - let tf_args, args = fun_args tf_args, field in - - let rett = if is_float then basic.tfloat else t_dynamic in - let tf_args, args = if ctx.rcf_handle_statics then tf_args @ [ "isStatic", false, basic.tbool ], args @ [is_static] else tf_args, args in - let tf_args, args = if is_set then tf_args @ [ "setVal", false, rett ], args @ [get set_option] else tf_args, args in - let tf_args, args = tf_args @ [ "throwErrors",false,basic.tbool ], args @ [throw_errors] in - let tf_args, args = if is_set || is_float then tf_args, args else tf_args @ [ "isCheck", false, basic.tbool ], args @ [{ eexpr = TConst(TBool false); etype = basic.tbool; epos = pos }] in - let tf_args, args = tf_args @ [ "handleProperties",false,basic.tbool; ], args @ [ mk_bool ctx false pos; ] in - - { - eexpr = TCall( - { (mk_field_access gen local fun_name pos) with etype = TFun(tf_args, rett) }, - args); - etype = rett; - epos = pos; - } + mk_cfield false true - - let implement_fields ctx cl = - (* - implement two kinds of fields get: - classFields - generic 'fields': receives a parameter isInstance - will receive an Array and start pushing the fields into it. - //add all common fields - if(isInstance) - { - //add methods - } else { - super.fields(isInstance, array); - } - *) + let implement_getFields ctx cl = let gen = ctx.rcf_gen in let basic = gen.gcon.basic in let pos = cl.cl_pos in - (* - let rec has_no_dynamic cl = - if is_some cl.cl_dynamic then - false - else match cl.cl_super with - | None -> true - | Some(cl,_) -> has_no_dynamic cl - in - *) - (* Type.getClassFields() *) - if ctx.rcf_handle_statics then begin - let name = gen.gmk_internal_name "hx" "classFields" in - let v_base_arr = alloc_var "baseArr" (basic.tarray basic.tstring) in - let base_arr = mk_local v_base_arr pos in - - let tf_args = [v_base_arr,None] in - let t = TFun(fun_args tf_args, basic.tvoid) in - let cf = mk_class_field name t false pos (Method MethNormal) [] in - cl.cl_ordered_fields <- cl.cl_ordered_fields @ [cf]; - cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields; - (if is_override cl then cl.cl_overrides <- cf :: cl.cl_overrides); - (* - var newarr = ["field1", "field2"] ...; - *) - let fields = collect_fields cl None (Some true) in - let mk_push value = - { eexpr = TCall({ (mk_field_access gen base_arr "push" pos) with etype = TFun(["x", false, basic.tstring], basic.tint) }, [value] ); etype = basic.tint; epos = pos } - in - - let new_arr_contents = - { - eexpr = TBlock( - List.map (fun (_,cf) -> mk_push { eexpr = TConst(TString(cf.cf_name)); etype = basic.tstring; epos = pos }) fields - ); - etype = basic.tvoid; - epos = pos - } in - - let expr = new_arr_contents in - let fn = - { - tf_args = tf_args; - tf_type = basic.tvoid; - tf_expr = mk_block expr - } in - - cf.cf_expr <- Some { eexpr = TFunction(fn); etype = t; epos = pos } - end; - - let fields = - (* - function __hx_fields(baseArr:Array, isInstanceFields:Bool) - { - //add all variable fields - //then: - if (isInstanceFields) - { - //add all method fields as well - } else { - super.__hx_fields(baseArr, isInstanceFields); - } - } - *) - let name = gen.gmk_internal_name "hx" "getFields" in - let v_base_arr, v_is_inst = alloc_var "baseArr" (basic.tarray basic.tstring), alloc_var "isInstanceFields" basic.tbool in - let base_arr, is_inst = mk_local v_base_arr pos, mk_local v_is_inst pos in - - let tf_args = (v_base_arr,None) :: (if ctx.rcf_handle_statics then [v_is_inst, None] else []) in - let t = TFun(fun_args tf_args, basic.tvoid) in - let cf = mk_class_field name t false pos (Method MethNormal) [] in - - let mk_push value = - { eexpr = TCall({ (mk_field_access gen base_arr "push" pos) with etype = TFun(["x", false, basic.tstring], basic.tint); }, [value] ); etype = basic.tint; epos = pos } - in - - let has_value = ref false in - let map_fields = - List.map (fun (_,cf) -> - match cf.cf_kind with - | Var _ - | Method MethDynamic when not (List.memq cf cl.cl_overrides) -> - has_value := true; - mk_push { eexpr = TConst(TString(cf.cf_name)); etype = basic.tstring; epos = pos } - | _ -> null basic.tvoid pos - ) - in - - (* - if it is first_dynamic, then we need to enumerate the dynamic fields - *) - let if_not_inst = if is_some cl.cl_dynamic && is_first_dynamic cl then begin - has_value := true; - Some (enumerate_dynamic_fields ctx cl mk_push) - end else - None - in - - let if_not_inst = if is_override cl then - Some( - { - eexpr = TBlock( - (if is_some if_not_inst then get if_not_inst else []) @ - [{ - eexpr = TCall( - { eexpr = TField({ eexpr = TConst TSuper; etype = TInst(cl, List.map snd cl.cl_params); epos = pos }, FInstance(cl, List.map snd cl.cl_params, cf)); etype = t; epos = pos }, - base_arr :: (if ctx.rcf_handle_statics then [is_inst] else []) - ); - etype = basic.tvoid; - epos = pos - }] - ); - etype = basic.tvoid; - epos = pos - } - ) else if is_some if_not_inst then - Some({ eexpr = TBlock(get if_not_inst); etype = basic.tvoid; epos = pos }) - else - None - in - - let expr_contents = map_fields (collect_fields cl (Some false) (Some false)) in - let expr_contents = if ctx.rcf_handle_statics then - expr_contents @ - [ { - eexpr = TIf(is_inst, - { eexpr = TBlock( map_fields (collect_fields cl (Some true) (Some false)) ); etype = basic.tvoid; epos = pos }, - if_not_inst - ); - etype = basic.tvoid; - epos = pos - } ] - else - expr_contents @ (if is_some if_not_inst then [ get if_not_inst ] else []) - in - - let expr = - { - eexpr = TBlock( expr_contents ); - etype = basic.tvoid; - epos = pos; - } in - - let fn = - { - tf_args = tf_args; - tf_type = basic.tvoid; - tf_expr = expr - } in - - (if !has_value || (not (is_override cl)) then begin - cl.cl_ordered_fields <- cl.cl_ordered_fields @ [cf]; - cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields; - (if is_override cl then cl.cl_overrides <- cf :: cl.cl_overrides) - end); - cf.cf_expr <- Some { eexpr = TFunction(fn); etype = t; epos = pos } - in - ignore fields - let implement_class_methods ctx cl = - ctx.rcf_class_cl <- Some cl; - - let pos = cl.cl_pos in - let gen = ctx.rcf_gen in - let basic = gen.gcon.basic in (* - fields -> redirected to classFields - getField -> redirected to getField with isStatic true - setField -> isStatic true - invokeField -> isStatic true - getClass -> null - create -> proxy - createEmpty -> proxy + function __hx_getFields(baseArr:Array) + { + //add all variable fields + //then: + super.__hx_getFields(baseArr); + } *) - let is_override = is_override cl in - let name = "classProxy" in - let t = (TInst(ctx.rcf_object_iface,[])) in - (* let cf = mk_class_field name t false pos (Var { v_read = AccNormal; v_write = AccNormal }) [] in *) - let register_cf cf override = - cl.cl_ordered_fields <- cf :: cl.cl_ordered_fields; - cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields; - if override then cl.cl_overrides <- cf :: cl.cl_overrides - in - (* register_cf cf false; *) - - let this_t = TInst(cl, List.map snd cl.cl_params) in - let this = { eexpr = TConst(TThis); etype = this_t; epos = pos } in - let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in - let proxy = mk_this name t in - - (*let ctor = - let cls = alloc_var "cls" t in - let tf_args = [cls, None] in - let t = TFun(fun_args tf_args, basic.tvoid) in - let cf = mk_class_field "new" t true pos (Method MethNormal) [] in - cf.cf_expr <- Some({ - eexpr = TFunction({ - tf_args = tf_args; - tf_type = basic.tvoid; - tf_expr = mk_block { - eexpr = TBinop(Ast.OpAssign, proxy, mk_local cls pos); - etype = cls.v_type; - epos = pos; - } - }); - etype = t; - epos = pos; - }); - cf - in - register_cf ctor false;*) - - (* setting it as DynamicObject makes getClass return null *) - let get_class = - cl.cl_meta <- (Meta.DynamicObject, [], pos) :: cl.cl_meta - in - ignore get_class; - - (* fields -> if isInstanceField, redir the method. If not, return classFields *) - let fields = - let name = gen.gmk_internal_name "hx" "getFields" in - let v_base_arr, v_is_inst = alloc_var "baseArr" (basic.tarray basic.tstring), alloc_var "isInstanceFields" basic.tbool in - let base_arr, is_inst = mk_local v_base_arr pos, mk_local v_is_inst pos in - - let tf_args = [ v_base_arr,None; v_is_inst, None ] in - let t = TFun(fun_args tf_args, basic.tvoid) in - let cf = mk_class_field name t false pos (Method MethNormal) [] in - cf.cf_expr <- Some({ - eexpr = TFunction({ - tf_args = tf_args; - tf_type = basic.tvoid; - tf_expr = mk_block { - eexpr = TIf(is_inst, - { eexpr = TCall( { (mk_field_access gen proxy name pos) with etype = t }, [base_arr;is_inst]); etype = basic.tvoid; epos = pos }, - Some { eexpr = TCall(mk_this (gen.gmk_internal_name "hx" "classFields") (TFun(["baseArr",false,basic.tarray basic.tstring], basic.tvoid)), [base_arr]); etype = basic.tvoid; epos = pos }); - etype = basic.tvoid; - epos = pos - } - }); - etype = t; - epos = pos; - }); - cf - in - register_cf fields (is_override); - - let do_proxy field tf_args ret is_static_argnum = - let field = gen.gmk_internal_name "hx" field in - let t = TFun(fun_args tf_args, ret) in - let cf = mk_class_field field t false pos (Method MethNormal) [] in - let is_void = is_void ret in - let may_return e = if is_void then mk_block e else mk_block (mk_return e) in - let i = ref 0 in - cf.cf_expr <- Some({ - eexpr = TFunction({ - tf_args = tf_args; - tf_type = ret; - tf_expr = may_return { - eexpr = TCall( - { (mk_field_access gen proxy field pos) with etype = t }, - List.map (fun (v,_) -> - let lasti = !i in - incr i; - if lasti = is_static_argnum then - { eexpr = TConst(TBool true); etype = basic.tbool; epos = pos } - else - mk_local v pos - ) tf_args); - etype = ret; - epos = pos - } - }); - etype = t; - epos = pos; - }); - cf + let name = gen.gmk_internal_name "hx" "getFields" in + let v_base_arr = alloc_var "baseArr" (basic.tarray basic.tstring) in + let base_arr = mk_local v_base_arr pos in + + let tf_args = [(v_base_arr,None)] in + let t = TFun(fun_args tf_args, basic.tvoid) in + let cf = mk_class_field name t false pos (Method MethNormal) [] in + + let e_pushfield = mk_field_access gen base_arr "push" pos in + let mk_push value = mk (TCall (e_pushfield, [value])) basic.tint pos in + + let has_value = ref false in + let map_fields = + List.map (fun (_,cf) -> + match cf.cf_kind with + | Var _ + | Method MethDynamic when not (List.memq cf cl.cl_overrides) -> + has_value := true; + mk_push (ExprBuilder.make_string gen.gcon cf.cf_name pos) + | _ -> null basic.tvoid pos + ) in - (* getClassFields -> redir *) - register_cf (do_proxy "classFields" [ alloc_var "baseArr" (basic.tarray basic.tstring), None ] basic.tvoid (-1)) true; - - (*register_cf (do_proxy "classFields" [ alloc_var "baseArr" (basic.tarray basic.tstring), None ] basic.tvoid (-1)) true;*) - - let fst_args, _ = field_type_args ctx pos in - let fst_args_len = List.length fst_args in - - (* getField -> redir the method with static = true *) - (* setField -> redir the methods with static = true *) - (if ctx.rcf_float_special_case then - register_cf (do_proxy "getField_f" (fst_args @ [ alloc_var "isStatic" basic.tbool, None; alloc_var "throwErrors" basic.tbool, None ]) basic.tfloat fst_args_len) true; - register_cf (do_proxy "setField_f" (fst_args @ [ alloc_var "isStatic" basic.tbool, None; alloc_var "value" basic.tfloat, None ]) basic.tfloat fst_args_len) true - ); - register_cf (do_proxy "getField" (fst_args @ [ alloc_var "isStatic" basic.tbool, None; alloc_var "throwErrors" basic.tbool, None; alloc_var "isCheck" basic.tbool, None; alloc_var "handleProperties" basic.tbool,None; ]) t_dynamic fst_args_len) true; - register_cf (do_proxy "setField" (fst_args @ [ alloc_var "isStatic" basic.tbool, None; alloc_var "value" t_dynamic, None; alloc_var "handleProperties" basic.tbool,None; ]) t_dynamic fst_args_len) true; - - (* invokeField -> redir the method with static = true *) - register_cf (do_proxy "invokeField" (fst_args @ [ alloc_var "isStatic" basic.tbool, None; alloc_var "dynArgs" (basic.tarray t_dynamic), None ]) t_dynamic fst_args_len) true; - - (* create / createEmpty -> redir the method *) - register_cf (do_proxy "create" [ alloc_var "arr" (basic.tarray t_dynamic), None ] t_dynamic (-1)) true; - register_cf (do_proxy "createEmpty" [ ] t_dynamic (-1)) true - - let implement_get_class ctx cl = (* - if it is DynamicObject, return null; - if it is not, just do the following: - if (typehandle(this.class) == typehandle(MyClass)) - return (MyClass.__hx_class != null ? MyClass.__hx_class : MyClass.__hx_class = create_empty(MyClass)); - return MyClass.__hx_class = haxe.lang.Runtime.getClass(MyClass); - - implement both on static and non-static contexts. This way we can call without references. + if it is first_dynamic, then we need to enumerate the dynamic fields *) - let gen = ctx.rcf_gen in - let basic = gen.gcon.basic in - let pos = cl.cl_pos in - - let tclass = get_cl ( (Hashtbl.find gen.gtypes ([],"Class")) ) in - let cls = TInst(tclass, [ TInst(cl, List.map (fun _ -> t_dynamic) cl.cl_params) ]) in - let cls_dyn = TInst(tclass, [t_dynamic]) in + let exprs = + if is_some cl.cl_dynamic && is_first_dynamic cl then begin + has_value := true; + enumerate_dynamic_fields ctx cl mk_push base_arr + end else + [] + in - let expr, static_cfs = - if Meta.has Meta.DynamicObject cl.cl_meta then - mk_return (null t_dynamic pos), [] + let exprs = + if is_override cl then + let tparams = List.map snd cl.cl_params in + let esuper = mk (TConst TSuper) (TInst(cl, tparams)) pos in + let efield = mk (TField (esuper, FInstance (cl, tparams, cf))) t pos in + exprs @ [mk (TCall (efield, [base_arr])) basic.tvoid pos] else - let cache_name = (gen.gmk_internal_name "hx" "class") in - let cache = mk_class_field cache_name cls false pos (Var { v_read = AccNormal; v_write = AccNormal }) [] in - cl.cl_ordered_statics <- cl.cl_ordered_statics @ [ cache ]; - cl.cl_statics <- PMap.add cache_name cache cl.cl_statics; - - let cache_access = mk_static_field_access cl cache_name cls pos in - - - let create_expr = { - eexpr = TNew(get ctx.rcf_class_cl, [], [gen.gtools.rf_create_empty cl (List.map (fun _ -> t_dynamic) cl.cl_params) pos]); - etype = cls; - epos = pos - } in - - (if ctx.rcf_class_eager_creation then cache.cf_expr <- Some(create_expr)); - - let expr = if ctx.rcf_class_eager_creation then - mk_return cache_access - else - mk_return { - eexpr = TIf( - { eexpr = TBinop(Ast.OpNotEq, cache_access, null cls pos); etype = basic.tbool; epos = pos }, - cache_access, - Some({ eexpr = TBinop(Ast.OpAssign, cache_access, create_expr); etype = cls; epos = pos }) - ); - etype = cls; - epos = pos - } - in - expr, [] + exprs in - let func = - { + let exprs = map_fields (collect_fields cl (Some false)) @ exprs in + + cf.cf_expr <- Some { eexpr = TFunction({ - tf_args = []; - tf_type = cls_dyn; - tf_expr = expr + tf_args = tf_args; + tf_type = basic.tvoid; + tf_expr = mk (TBlock exprs) basic.tvoid pos }); - etype = TFun([],cls_dyn); + etype = t; epos = pos - } in - - let get_cl_static = mk_class_field (gen.gmk_internal_name "hx" "getClassStatic") (TFun([],cls_dyn)) false pos (Method MethNormal) [] in - let get_cl = mk_class_field (gen.gmk_internal_name "hx" "getClass") (TFun([],cls_dyn)) false pos (Method MethNormal) [] in - - get_cl_static.cf_expr <- Some func; - get_cl.cf_expr <- Some func; - - let all_f = [get_cl] in - cl.cl_ordered_fields <- cl.cl_ordered_fields @ all_f; - List.iter (fun cf -> cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields) all_f; + }; - let all_f = get_cl_static :: static_cfs in - cl.cl_ordered_statics <- cl.cl_ordered_statics @ all_f; - List.iter (fun cf -> cl.cl_statics <- PMap.add cf.cf_name cf cl.cl_statics) all_f; + if !has_value || not (is_override cl) then begin + cl.cl_ordered_fields <- cl.cl_ordered_fields @ [cf]; + cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields; + (if is_override cl then cl.cl_overrides <- cf :: cl.cl_overrides) + end - if is_override cl then cl.cl_overrides <- get_cl :: cl.cl_overrides let implement_invokeField ctx ~slow_invoke cl = (* @@ -8576,9 +7773,8 @@ struct let field_args, switch_var = field_type_args ctx cl.cl_pos in let field_args_exprs = List.map (fun (v,_) -> mk_local v pos) field_args in - let is_static = alloc_var "isStatic" basic.tbool in let dynamic_arg = alloc_var "dynargs" (basic.tarray t_dynamic) in - let all_args = field_args @ (if ctx.rcf_handle_statics then [ is_static,None; dynamic_arg,None ] else [ dynamic_arg, None ] ) in + let all_args = field_args @ [ dynamic_arg, None ] in let fun_t = TFun(fun_args all_args, t_dynamic) in let this_t = TInst(cl, List.map snd cl.cl_params) in @@ -8605,39 +7801,32 @@ struct mk_this_call_raw cf.cf_name (TFun(args, ret)) params in - let mk_static_call cf params = - let t = apply_object cf in - let _, ret = get_fun (follow t) in - { eexpr = TCall( mk_static_field_access cl cf.cf_name t pos, params ); etype = ret; epos = pos } - in - let extends_hxobject = extends_hxobject cl in ignore extends_hxobject; - (* creates a dynamicInvoke of the class fields listed here *) + + (* creates a invokeField of the class fields listed here *) (* - function dynamicInvoke(field, isStatic, dynargs) + function invokeField(field, dynargs) { switch(field) { case "a": this.a(dynargs[0], dynargs[1], dynargs[2]...); - default: super.dynamicInvoke //or this.getField(field).invokeField(dynargs) + default: super.invokeField //or this.getField(field).invokeDynamic(dynargs) } } *) let dyn_fun = mk_class_field (ctx.rcf_gen.gmk_internal_name "hx" "invokeField") fun_t false cl.cl_pos (Method MethNormal) [] in - let mk_switch_dyn cfs static old = - (* mk_class_field name t public pos kind params = *) - + let mk_switch_dyn cfs old = let get_case (names,cf) = has_method := true; let i = ref 0 in let dyn_arg_local = mk_local dynamic_arg pos in let cases = List.map (switch_case ctx pos) names in (cases, - { eexpr = TReturn(Some ( (if static then mk_static_call else mk_this_call) cf (List.map (fun (name,_,t) -> - let ret = { eexpr = TArray(dyn_arg_local, mk_int ctx !i pos); etype = t_dynamic; epos = pos } in + { eexpr = TReturn(Some (mk_this_call cf (List.map (fun (name,_,t) -> + let ret = { eexpr = TArray(dyn_arg_local, ExprBuilder.make_int ctx.rcf_gen.gcon !i pos); etype = t_dynamic; epos = pos } in incr i; ret ) (fst (get_args (cf.cf_type))) ) )); @@ -8660,16 +7849,20 @@ struct ( ncases, mk_return ((get slow_invoke) this (mk_local (fst (List.hd field_args)) pos) (mk_local dynamic_arg pos)) ) :: cases in - let default = if !is_override && not(static) then - (* let call_super ctx fn_args ret_t fn_name this_t pos = *) + let default = if !is_override then { eexpr = TReturn(Some (call_super ctx all_args t_dynamic dyn_fun cl this_t pos) ); etype = basic.tvoid; epos = pos } - (*else if ctx.rcf_create_getsetinvoke_fields then (* we always need to run create_getset before *) - let get_field_name = gen.gmk_internal_name "hx" "getField" in - { eexpr = TReturn( Some (mk_this_call (PMap.find get_field_name cl.cl_fields) [mk_local dynamic_arg pos] ) ); etype = basic.tvoid; epos = pos }*) else ( - (*let field = (gen.gtools.r_field false (TInst(ctx.rcf_ft.func_class,[])) this (mk_local (fst (List.hd all_args)) pos)) in*) - (* let mk_field_access ctx pos local field is_float is_static throw_errors set_option = *) - let field = mk_field_access_r ctx pos this field_args_exprs false {eexpr = TConst(TBool static); etype = basic.tbool; epos = pos} { eexpr = TConst(TBool true); etype = basic.tbool; epos = pos } None in + let field = begin + let fun_name = ctx.rcf_gen.gmk_internal_name "hx" "getField" in + let tf_args, _ = field_type_args ctx pos in + let tf_args, args = fun_args tf_args, field_args_exprs in + + let tf_args, args = tf_args @ ["throwErrors",false, basic.tbool], args @ [ExprBuilder.make_bool gen.gcon true pos] in + let tf_args, args = tf_args @ ["isCheck", false, basic.tbool], args @ [ExprBuilder.make_bool gen.gcon false pos] in + let tf_args, args = tf_args @ ["handleProperties", false, basic.tbool], args @ [ExprBuilder.make_bool gen.gcon false pos] in + + mk (TCall ({ (mk_field_access gen this fun_name pos) with etype = TFun(tf_args, t_dynamic) }, args)) t_dynamic pos + end in let field = mk_cast (TInst(ctx.rcf_ft.func_class,[])) field in mk_return { eexpr = TCall( @@ -8688,8 +7881,7 @@ struct in let contents = - let statics = collect_fields cl (Some true) (Some true) in - let nonstatics = collect_fields cl (Some true) (Some false) in + let nonstatics = collect_fields cl (Some true) in let old_nonstatics = ref [] in @@ -8703,13 +7895,7 @@ struct ) nonstatics in - if ctx.rcf_handle_statics then - { - eexpr = TIf(mk_local is_static pos, mk_switch_dyn statics true [], Some(mk_switch_dyn nonstatics false !old_nonstatics)); - etype = basic.tvoid; - epos = pos; - } else - mk_switch_dyn nonstatics false !old_nonstatics + mk_switch_dyn nonstatics !old_nonstatics in dyn_fun.cf_expr <- Some @@ -8771,10 +7957,10 @@ struct let expr = if like_float ret && not (like_int ret) then mk_cast ret expr else expr in - [], mk_return expr + mk_return expr in - let all_cfs = List.filter (fun cf -> cf.cf_name <> "new" && cf.cf_name <> (invokedyn) && match cf.cf_kind with Method _ -> true | _ -> false) (ctx.rcf_ft.map_base_classfields cl true map_fn) in + let all_cfs = List.filter (fun cf -> cf.cf_name <> "new" && cf.cf_name <> (invokedyn) && match cf.cf_kind with Method _ -> true | _ -> false) (ctx.rcf_ft.map_base_classfields cl map_fn) in cl.cl_ordered_fields <- cl.cl_ordered_fields @ all_cfs; List.iter (fun cf -> @@ -8826,12 +8012,7 @@ struct let expr = { eexpr = TCall( mk_field_access gen this_obj (gen.gmk_internal_name "hx" "invokeField") pos, - (List.map (fun (v,_) -> mk_this v.v_name v.v_type) field_args) @ - (if ctx.rcf_handle_statics then - [ { eexpr = TConst(TBool false); etype = basic.tbool; epos = pos }; call_arg ] - else - [ call_arg ] - ) + (List.map (fun (v,_) -> mk_this v.v_name v.v_type) field_args) @ [ call_arg ] ); etype = t_dynamic; epos = pos @@ -8839,10 +8020,10 @@ struct let expr = if like_float ret && not (like_int ret) then mk_cast ret expr else expr in - [], mk_return expr + mk_return expr in - let all_cfs = List.filter (fun cf -> cf.cf_name <> "new" && match cf.cf_kind with Method _ -> true | _ -> false) (ctx.rcf_ft.map_base_classfields cl true map_fn) in + let all_cfs = List.filter (fun cf -> cf.cf_name <> "new" && match cf.cf_kind with Method _ -> true | _ -> false) (ctx.rcf_ft.map_base_classfields cl map_fn) in List.iter (fun cf -> cl.cl_overrides <- cf :: cl.cl_overrides @@ -8861,7 +8042,7 @@ struct tf_args = tf_args; tf_type = basic.tvoid; tf_expr = { eexpr = TBlock({ - eexpr = TCall({ eexpr = TConst(TSuper); etype = TInst(cl,[]); epos = pos }, [mk_int ctx (-1) pos; mk_int ctx (-1) pos]); + eexpr = TCall({ eexpr = TConst(TSuper); etype = TInst(cl,[]); epos = pos }, [ExprBuilder.make_int ctx.rcf_gen.gcon (-1) pos; ExprBuilder.make_int ctx.rcf_gen.gcon (-1) pos]); etype = basic.tvoid; epos = pos } :: ctor_body); etype = basic.tvoid; epos = pos } @@ -8873,7 +8054,7 @@ struct cl.cl_constructor <- Some ctor_cf; let closure_fun eclosure e field is_static = - let f = { eexpr = TConst(TString field); etype = basic.tstring; epos = eclosure.epos } in + let f = ExprBuilder.make_string gen.gcon field eclosure.epos in let args = if ctx.rcf_optimize then [ f; { eexpr = TConst(TInt (hash_field_i32 ctx eclosure.epos field)); etype = basic.tint; epos = eclosure.epos } ] else [ f ] in let args = args @ [ mk_cast (TInst(ctx.rcf_object_iface, [])) e ] in @@ -8888,7 +8069,7 @@ struct mk_cast eclosure.etype { eclosure with eexpr = TNew(closure_cl, [], [ e; - { eexpr = TConst(TString field); etype = basic.tstring; epos = eclosure.epos } + ExprBuilder.make_string gen.gcon field eclosure.epos ] @ ( if ctx.rcf_optimize then [ { eexpr = TConst(TInt (hash_field_i32 ctx eclosure.epos field)); etype = basic.tint; epos = eclosure.epos } ] else [] )); @@ -8904,7 +8085,7 @@ struct * mutable rcf_on_getset_field : texpr->texpr->string->texpr option->bool->texpr;*) - let configure_dynamic_field_access ctx is_synf = + let configure_dynamic_field_access ctx = let gen = ctx.rcf_gen in let is_dynamic expr fexpr field = match (field_access_esp gen (gen.greal_type fexpr.etype) field) with @@ -8913,10 +8094,8 @@ struct | _ -> true in - let configure = if is_synf then DynamicFieldAccess.configure_as_synf else DynamicFieldAccess.configure in let maybe_hash = if ctx.rcf_optimize then fun str pos -> Some (hash_field_i32 ctx pos str) else fun str pos -> None in - configure gen (DynamicFieldAccess.abstract_implementation gen is_dynamic - (* print_endline *) + DynamicFieldAccess.configure gen is_dynamic (fun expr fexpr field set is_unsafe -> let hash = maybe_hash field fexpr.epos in ctx.rcf_on_getset_field expr fexpr field hash set is_unsafe @@ -8924,130 +8103,49 @@ struct (fun ecall fexpr field call_list -> let hash = maybe_hash field fexpr.epos in ctx.rcf_on_call_field ecall fexpr field hash call_list - ) - ); + ); () - let replace_reflection ctx cl = - let gen = ctx.rcf_gen in - let pos = cl.cl_pos in - - let this_t = TInst(cl, List.map snd cl.cl_params) in - let this = { eexpr = TConst(TThis); etype = this_t; epos = pos } in - let last_fields = match cl.cl_super with - | None -> PMap.empty - | Some (super,_) -> super.cl_fields - in - - let new_fields = ref [] in - let process_cf static cf = - match cf.cf_kind with - | Var _ -> () - | _ when Meta.has Meta.ReplaceReflection cf.cf_meta -> - let name = if String.get cf.cf_name 0 = '_' then String.sub cf.cf_name 1 (String.length cf.cf_name - 1) else cf.cf_name in - let new_name = gen.gmk_internal_name "hx" name in - let new_cf = mk_class_field new_name cf.cf_type cf.cf_public cf.cf_pos cf.cf_kind cf.cf_params in - let fn_args, ret = get_fun (follow cf.cf_type) in - - let tf_args = List.map (fun (name,_,t) -> alloc_var name t, None) fn_args in - let is_void = is_void ret in - let expr = { - eexpr = TCall( - { - eexpr = (if static then TField(mk_classtype_access cl pos, FStatic(cl, cf)) else TField(this, FInstance(cl, List.map snd cl.cl_params, cf))); - etype = cf.cf_type; - epos = cf.cf_pos; - }, - List.map (fun (v,_) -> mk_local v cf.cf_pos) tf_args); - etype = ret; - epos = cf.cf_pos - } in - - let new_f = - { - tf_args = tf_args; - tf_type = ret; - tf_expr = { - eexpr = TBlock([if is_void then expr else mk_return expr]); - etype = ret; - epos = pos; - } - } in - - new_cf.cf_expr <- Some({ eexpr = TFunction(new_f); etype = cf.cf_type; epos = cf.cf_pos}); - - new_fields := new_cf :: !new_fields; - - (if static then cl.cl_statics <- PMap.add new_name new_cf cl.cl_statics else cl.cl_fields <- PMap.add new_name new_cf cl.cl_fields); - - if not static && PMap.mem new_name last_fields then cl.cl_overrides <- new_cf :: cl.cl_overrides - | _ -> () - in - - List.iter (process_cf false) cl.cl_ordered_fields; - cl.cl_ordered_fields <- cl.cl_ordered_fields @ !new_fields; - new_fields := []; - List.iter (process_cf true) cl.cl_ordered_statics; - cl.cl_ordered_statics <- cl.cl_ordered_statics @ !new_fields - - (* ******************************************* *) - (* UniversalBaseClass *) - (* ******************************************* *) - - (* - - Sets the universal base class for hxgen types (HxObject / IHxObject) + (* ******************************************* *) + (* UniversalBaseClass *) + (* ******************************************* *) + (* + Sets the universal base class for hxgen types (HxObject / IHxObject) dependencies: As a rule, it should be one of the last module filters to run so any @:hxgen class created in the process - -Should- only run after TypeParams.RealTypeParams.Modf, since - + -Should- only run after TypeParams.RealTypeParams.Modf *) - module UniversalBaseClass = struct - let name = "rcf_universal_base_class" - let priority = min_dep +. 10. - let default_implementation gen baseclass baseinterface basedynamic = - (* baseinterface.cl_meta <- (Meta.BaseInterface, [], baseinterface.cl_pos) :: baseinterface.cl_meta; *) + let configure gen baseclass baseinterface basedynamic = let rec run md = - (if is_hxgen md then + if is_hxgen md then match md with - | TClassDecl ( { cl_interface = true } as cl ) when cl.cl_path <> baseclass.cl_path && cl.cl_path <> baseinterface.cl_path && cl.cl_path <> basedynamic.cl_path -> - cl.cl_implements <- (baseinterface, []) :: cl.cl_implements - | TClassDecl ({ cl_kind = KAbstractImpl _ } as cl) -> - (* - TODO: probably here is not the best place to add @:final to KAbstractImpl, also: - Doesn't it make sense to add @:final to KAbstractImpls on all platforms? - *) - if not (Meta.has Meta.Final cl.cl_meta) then cl.cl_meta <- (Meta.Final, [], cl.cl_pos) :: cl.cl_meta - | TClassDecl ( { cl_super = None } as cl ) when cl.cl_path <> baseclass.cl_path && cl.cl_path <> baseinterface.cl_path && cl.cl_path <> basedynamic.cl_path -> - if is_some cl.cl_dynamic then - cl.cl_super <- Some (basedynamic,[]) - else - cl.cl_super <- Some (baseclass,[]) - | TClassDecl ( { cl_super = Some(super,_) } as cl ) when cl.cl_path <> baseclass.cl_path && cl.cl_path <> baseinterface.cl_path && not ( is_hxgen (TClassDecl super) ) -> - cl.cl_implements <- (baseinterface, []) :: cl.cl_implements - | _ -> () - ); - md + | TClassDecl ({ cl_interface = true } as cl) when cl.cl_path <> baseclass.cl_path && cl.cl_path <> baseinterface.cl_path && cl.cl_path <> basedynamic.cl_path -> + cl.cl_implements <- (baseinterface, []) :: cl.cl_implements + | TClassDecl ({ cl_kind = KAbstractImpl _ }) -> + (* don't add any base classes to abstract implementations *) + () + | TClassDecl ({ cl_super = None } as cl) when cl.cl_path <> baseclass.cl_path && cl.cl_path <> baseinterface.cl_path && cl.cl_path <> basedynamic.cl_path -> + if is_some cl.cl_dynamic then + cl.cl_super <- Some (basedynamic,[]) + else + cl.cl_super <- Some (baseclass,[]) + | TClassDecl ({ cl_super = Some(super,_) } as cl) when cl.cl_path <> baseclass.cl_path && cl.cl_path <> baseinterface.cl_path && not (is_hxgen (TClassDecl super)) -> + cl.cl_implements <- (baseinterface, []) :: cl.cl_implements + | _ -> + () in - run - - let configure gen mapping_func = - let map e = Some(mapping_func e) in + let map md = Some(run md; md) in gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) map - - let default_config gen baseclass baseinterface basedynamic = - let impl = (default_implementation gen baseclass baseinterface basedynamic) in - configure gen impl - end;; + (* Priority: must run AFTER UniversalBaseClass *) @@ -9057,14 +8155,11 @@ struct let gen = ctx.rcf_gen in let run = (fun md -> match md with | TClassDecl cl when is_hxgen md && ( not cl.cl_interface || cl.cl_path = baseinterface.cl_path ) && (match cl.cl_kind with KAbstractImpl _ -> false | _ -> true) -> - (if Meta.has Meta.ReplaceReflection cl.cl_meta then replace_reflection ctx cl); (implement_dynamics ctx cl); (if not (PMap.mem (gen.gmk_internal_name "hx" "lookupField") cl.cl_fields) then implement_final_lookup ctx cl); (if not (PMap.mem (gen.gmk_internal_name "hx" "getField") cl.cl_fields) then implement_get_set ctx cl); (if not (PMap.mem (gen.gmk_internal_name "hx" "invokeField") cl.cl_fields) then implement_invokeField ctx ~slow_invoke:slow_invoke cl); - (if not (PMap.mem (gen.gmk_internal_name "hx" "classFields") cl.cl_fields) then implement_fields ctx cl); - (if ctx.rcf_handle_statics && not (PMap.mem (gen.gmk_internal_name "hx" "getClassStatic") cl.cl_statics) then implement_get_class ctx cl); - (if not cl.cl_interface && not (PMap.mem (gen.gmk_internal_name "hx" "create") cl.cl_fields) then implement_create_empty ctx cl); + (if not (PMap.mem (gen.gmk_internal_name "hx" "getFields") cl.cl_fields) then implement_getFields ctx cl); None | _ -> None) in @@ -9076,86 +8171,56 @@ end;; (* ******************************************* *) (* Object Declaration Mapper *) (* ******************************************* *) - -(* - - A simple Object Declaration Mapper. By default it will be a syntax filter, which only runs - after - - dependencies: - - -*) - module ObjectDeclMap = struct - let name = "object_decl_map" - let priority = solve_deps name [] - let traverse gen map_fn = + let configure gen map_fn = let rec run e = match e.eexpr with - | TObjectDecl odecl -> - let e = Type.map_expr run e in - (match e.eexpr with | TObjectDecl odecl -> map_fn e odecl | _ -> assert false) - | _ -> Type.map_expr run e + | TObjectDecl odecl -> + let e = Type.map_expr run e in + (match e.eexpr with TObjectDecl odecl -> map_fn e odecl | _ -> assert false) + | _ -> + Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map - end;; (* ******************************************* *) (* EnumToClass *) (* ******************************************* *) - (* - For languages that don't support parameterized enums and/or metadata in enums, we need to transform enums into normal classes. This is done at the first module pass by creating new classes with the same path inside the modules, and removing the actual enum module by setting it as en extern. - Later, on the last expression pass, it will transform the TMatch codes into TSwitch. it will introduce a new - dependency, though: - * The target must create its own strategy to deal with reflection. As it is right now, we will have a base class - which the class will extend, create @:$IsEnum metadata for the class, and create @:alias() metadatas for the fields, - with their tag order (as a string) as their alias. If you are using ReflectionCFs, then you don't have to worry - about that, as it's already generating all information needed by the haxe runtime. - so they can be - - dependencies: - The MatchToSwitch part must run after ExprStatementUnwrap as modified expressions might confuse it (not so true anymore) - + * The target must create its own strategy to deal with reflection. As it is right now, we will have a base class + which the class will extend, create @:$IsEnum metadata for the class, and create @:alias() metadatas for the fields, + with their tag order (as a string) as their alias. If you are using ReflectionCFs, then you don't have to worry + about that, as it's already generating all information needed by the haxe runtime. + so they can be *) - module EnumToClass = struct - let name = "enum_to_class" - let priority = solve_deps name [] type t = { ec_tbl : (path, tclass) Hashtbl.t; } - let new_t () = - { + let new_t () = { ec_tbl = Hashtbl.create 10 } (* ******************************************* *) (* EnumToClassModf *) (* ******************************************* *) - (* - The actual Module Filter that will transform the enum into a class dependencies: @@ -9163,12 +8228,9 @@ struct Should run before TypeParams.RealTypeParams.RealTypeParamsModf, since generic enums must be first converted to generic classes It needs that the target platform implements __array__() as a shortcut to declare haxe.ds.Vector *) - module EnumToClassModf = struct - let name = "enum_to_class_mod" - let priority = solve_deps name [DBefore ReflectionCFs.priority; DBefore TypeParams.RealTypeParams.RealTypeParamsModf.priority] let pmap_exists fn pmap = try PMap.iter (fun a b -> if fn a b then raise Exit) pmap; false with | Exit -> true @@ -9177,7 +8239,8 @@ struct let has_meta meta = List.exists (fun (m,_,_) -> match m with Meta.Custom _ -> true | _ -> false) meta in has_meta en.e_meta || pmap_exists (fun _ ef -> has_meta ef.ef_meta) en.e_constrs - let convert gen t base_class base_param_class en should_be_hxgen handle_type_params = + let convert gen t base_class base_param_class en = + let handle_type_params = false in (* TODO: look into this *) let basic = gen.gcon.basic in let pos = en.e_pos in @@ -9249,7 +8312,7 @@ struct eexpr = TFunction({ tf_args = tf_args; tf_type = ret; - tf_expr = mk_block ( mk_return { eexpr = TNew(cl,List.map snd dup_types, [mk_int gen old_i pos; arr_decl] ); etype = TInst(cl, List.map snd dup_types); epos = pos } ); + tf_expr = mk_block ( mk_return { eexpr = TNew(cl,List.map snd dup_types, [ExprBuilder.make_int gen.gcon old_i pos; arr_decl] ); etype = TInst(cl, List.map snd dup_types); epos = pos } ); }); etype = ef_type; epos = pos @@ -9263,9 +8326,9 @@ struct in let cf = mk_class_field name actual_t true pos (Var { v_read = AccNormal; v_write = AccNever }) [] in let args = if has_params then - [mk_int gen old_i pos; null (gen.gclasses.nativearray t_dynamic) pos] + [ExprBuilder.make_int gen.gcon old_i pos; null (gen.gclasses.nativearray t_dynamic) pos] else - [mk_int gen old_i pos] + [ExprBuilder.make_int gen.gcon old_i pos] in cf.cf_meta <- [Meta.ReadOnly,[],pos]; cf.cf_expr <- Some { @@ -9314,11 +8377,7 @@ struct cl.cl_ordered_fields <- getTag_cf :: cl.cl_ordered_fields ; cl.cl_fields <- PMap.add "getTag" getTag_cf cl.cl_fields; cl.cl_overrides <- getTag_cf :: cl.cl_overrides; - - if should_be_hxgen then - cl.cl_meta <- (Meta.HxGen,[],cl.cl_pos) :: cl.cl_meta - else - cl.cl_meta <- (Meta.NativeGen,[],cl.cl_pos) :: cl.cl_meta; + cl.cl_meta <- (Meta.NativeGen,[],cl.cl_pos) :: cl.cl_meta; gen.gadd_to_module (TClassDecl cl) (max_dep); TEnumDecl en @@ -9331,9 +8390,10 @@ struct enum_base_class : tclass - the enum base class. should_be_hxgen : bool - should the created enum be hxgen? *) - let traverse gen t convert_all convert_if_has_meta enum_base_class param_enum_class should_be_hxgen handle_tparams = - let convert e = convert gen t enum_base_class param_enum_class e should_be_hxgen handle_tparams in - let run md = match md with + let configure gen t convert_all convert_if_has_meta enum_base_class param_enum_class = + let convert e = convert gen t enum_base_class param_enum_class e in + let run md = + match md with | TEnumDecl e when is_hxgen md -> if convert_all then convert e @@ -9346,39 +8406,28 @@ struct e.e_meta <- List.filter (fun (n,_,_) -> not (n = Meta.HxGen)) e.e_meta; md end - | _ -> md + | _ -> + md in - run - - let configure gen (mapping_func:module_type->module_type) = - let map md = Some(mapping_func md) in + let map md = Some(run md) in gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) map - end;; (* ******************************************* *) (* EnumToClassExprf *) (* ******************************************* *) - (* - Enum to class Expression Filter - will convert TMatch into TSwitch - dependencies: Should run before TArrayTransform, since it generates array access expressions - *) - module EnumToClassExprf = struct - let name = "enum_to_class_exprf" - let priority = solve_deps name [DBefore TArrayTransform.priority] - let traverse gen t opt_get_native_enum_tag = + let configure gen t opt_get_native_enum_tag = let rec run e = let get_converted_enum_type et = let en, eparams = match follow (gen.gfollow#run_f et) with @@ -9390,39 +8439,35 @@ struct in match e.eexpr with - | TCall (({eexpr = TField(_, FStatic({cl_path=[],"Type"},{cf_name="enumIndex"}))} as left), [f]) -> - let f = run f in - (try - mk_field_access gen {f with etype = get_converted_enum_type f.etype} "index" e.epos - with Not_found -> - { e with eexpr = TCall(left, [f]) }) - | TEnumParameter(f, _,i) -> - let f = run f in - (* check if en was converted to class *) - (* if it was, switch on tag field and change cond type *) - let f = try - { f with etype = get_converted_enum_type f.etype } - with Not_found -> - f - in - let cond_array = { (mk_field_access gen f "params" f.epos) with etype = gen.gclasses.nativearray t_dynamic } in - { e with eexpr = TArray(cond_array, mk_int gen i cond_array.epos); } - | _ -> Type.map_expr run e + | TCall (({eexpr = TField(_, FStatic({cl_path=[],"Type"},{cf_name="enumIndex"}))} as left), [f]) -> + let f = run f in + (try + mk_field_access gen {f with etype = get_converted_enum_type f.etype} "index" e.epos + with Not_found -> + { e with eexpr = TCall(left, [f]) }) + | TEnumParameter(f, _,i) -> + let f = run f in + (* check if en was converted to class *) + (* if it was, switch on tag field and change cond type *) + let f = try + { f with etype = get_converted_enum_type f.etype } + with Not_found -> + f + in + let cond_array = { (mk_field_access gen f "params" f.epos) with etype = gen.gclasses.nativearray t_dynamic } in + Codegen.index gen.gcon cond_array i e.etype e.epos + | _ -> + Type.map_expr run e in - - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gexpr_filters#add ~name:name ~priority:(PCustom priority) map end;; - let configure gen opt_get_native_enum_tag convert_all convert_if_has_meta enum_base_class param_enum_class should_be_hxgen handle_tparams = + let configure gen opt_get_native_enum_tag convert_all convert_if_has_meta enum_base_class param_enum_class = let t = new_t () in - EnumToClassModf.configure gen (EnumToClassModf.traverse gen t convert_all convert_if_has_meta enum_base_class param_enum_class should_be_hxgen handle_tparams); - EnumToClassExprf.configure gen (EnumToClassExprf.traverse gen t opt_get_native_enum_tag) - + EnumToClassModf.configure gen t convert_all convert_if_has_meta enum_base_class param_enum_class; + EnumToClassExprf.configure gen t opt_get_native_enum_tag end;; (* ******************************************* *) @@ -9459,15 +8504,12 @@ end;; module IteratorsInterface = struct - let name = "iterators_interface" (* TODO later (* ******************************************* *) (* IteratorsInterfaceModf *) (* ******************************************* *) - (* - The module filter for Iterators Interface, which will implement the iterator/iterable interface on each class that conforms with the typedefs Iterator<> and Iterable<> @@ -9476,12 +8518,9 @@ struct dependencies: Must run at the Module Filters, so cast detection can detect a cast to the interface and we can - *) - module IteratorsInterfaceModf = struct - let name = "iterators_interface_modf" let conforms_cfs has_next next = @@ -9557,9 +8596,7 @@ struct (* ******************************************* *) (* IteratorsInterfaceExprf *) (* ******************************************* *) - (* - The expression filter for Iterators. Will look for TFor, transform it into { var iterator = // in expression here @@ -9572,17 +8609,14 @@ struct dependencies: Must run before Dynamic fields access is run + TODO: I think TFor is always rewritten to TWhile before getting into the generator nowadays, + so this filter could probably be removed. Gotta ask Simon about it. *) - module IteratorsInterfaceExprf = struct - let name = "iterators_interface_exprf" - let priority = solve_deps name [DBefore DynamicFieldAccess.priority] - let priority_as_synf = solve_deps name [DBefore DynamicFieldAccess.priority_as_synf] - let mk_access gen v name pos = let field_t = try match follow v.v_type with @@ -9597,70 +8631,51 @@ struct in { (mk_field_access gen (mk_local v pos) name pos) with etype = field_t } - let traverse gen change_in_expr = + let configure gen = let basic = gen.gcon.basic in let rec run e = match e.eexpr with - | TFor(var, in_expr, block) -> - let in_expr = change_in_expr (run in_expr) in - let temp = mk_temp gen "iterator" in_expr.etype in - let block = - [ - { eexpr = TVar(temp, Some(in_expr)); etype = basic.tvoid; epos = in_expr.epos }; - { - eexpr = TWhile( - { eexpr = TCall(mk_access gen temp "hasNext" in_expr.epos, []); etype = basic.tbool; epos = in_expr.epos }, - Type.concat ({ - eexpr = TVar(var, Some({ eexpr = TCall(mk_access gen temp "next" in_expr.epos, []); etype = var.v_type; epos = in_expr.epos })); - etype = basic.tvoid; - epos = in_expr.epos - }) ( run block ), - Ast.NormalWhile); - etype = basic.tvoid; - epos = e.epos - } - ] in - { eexpr = TBlock(block); etype = e.etype; epos = e.epos } - | _ -> Type.map_expr run e + | TFor(var, in_expr, block) -> + let in_expr = run in_expr in + let temp = mk_temp gen "iterator" in_expr.etype in + let block = [ + { eexpr = TVar(temp, Some(in_expr)); etype = basic.tvoid; epos = in_expr.epos }; + { + eexpr = TWhile( + { eexpr = TCall(mk_access gen temp "hasNext" in_expr.epos, []); etype = basic.tbool; epos = in_expr.epos }, + Type.concat ({ + eexpr = TVar(var, Some({ eexpr = TCall(mk_access gen temp "next" in_expr.epos, []); etype = var.v_type; epos = in_expr.epos })); + etype = basic.tvoid; + epos = in_expr.epos + }) ( run block ), + Ast.NormalWhile); + etype = basic.tvoid; + epos = e.epos + } + ] in + { eexpr = TBlock(block); etype = e.etype; epos = e.epos } + | _ -> + Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gexpr_filters#add ~name:name ~priority:(PCustom priority) map - - let configure_as_synf gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in - gen.gexpr_filters#add ~name:name ~priority:(PCustom priority_as_synf) map - end;; - let configure gen change_in_expr = - IteratorsInterfaceExprf.configure gen (IteratorsInterfaceExprf.traverse gen change_in_expr) - - let configure_as_synf gen change_in_expr = - IteratorsInterfaceExprf.configure_as_synf gen (IteratorsInterfaceExprf.traverse gen change_in_expr) + let configure gen = + IteratorsInterfaceExprf.configure gen end;; + (* ******************************************* *) (* SwitchToIf *) (* ******************************************* *) - (* - Just a syntax filter which changes switch expressions to if() else if() else if() ... - It can be also an expression filter - dependencies: - - *) - module SwitchToIf = struct - let name = "switch_to_if" - let priority = solve_deps name [] let rec simplify_expr e = match e.eexpr with @@ -9668,20 +8683,20 @@ struct | TMeta(_,e) -> simplify_expr e | _ -> e - let traverse gen (should_convert:texpr->bool) (handle_nullables:bool) = + let configure gen (should_convert:texpr->bool) = let basic = gen.gcon.basic in let rec run e = match e.eexpr with | TSwitch(cond,cases,default) when should_convert e -> - let cond_etype, should_cache = match handle_nullables, gen.gfollow#run_f cond.etype with - | true, TType({ t_path = ([], "Null") }, [t]) -> + let cond_etype, should_cache = match gen.gfollow#run_f cond.etype with + | TType({ t_path = ([], "Null") }, [t]) -> let rec take_off_nullable t = match gen.gfollow#run_f t with | TType({ t_path = ([], "Null") }, [t]) -> take_off_nullable t | _ -> t in take_off_nullable t, true - | _, _ -> cond.etype, false + | _ -> cond.etype, false in if should_cache && not (should_convert { e with eexpr = TSwitch({ cond with etype = cond_etype }, cases, default) }) then begin @@ -9759,20 +8774,15 @@ struct with Not_found -> Type.map_expr run e) | _ -> Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map - end;; + (* ******************************************* *) (* Anonymous Class object handling *) (* ******************************************* *) - (* - (syntax) When we pass a class as an object, in some languages we will need a special construct to be able to access its statics as if they were normal object fields. On C# and Java the way found to do that is @@ -9789,17 +8799,12 @@ end;; This module will of course let the caller choose how this will be implemented. It will just identify all uses of class that will require it to be cast as an object. - - dependencies: - *) - module ClassInstance = struct - let priority = solve_deps "class_instance" [] - let traverse gen (change_expr:texpr->module_type->texpr) = + let configure gen (change_expr:texpr->module_type->texpr) = let rec run e = match e.eexpr with | TCall( ({ eexpr = TLocal({ v_name = ("__is__" | "__as__" | "__typeof__") } as v) } as local), calls ) when Hashtbl.mem gen.gspecial_vars v.v_name -> @@ -9818,20 +8823,14 @@ struct | TTypeExpr(mt) -> change_expr e mt | _ -> Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gsyntax_filters#add ~name:"class_instance" ~priority:(PCustom priority) map - end;; (* ******************************************* *) (* HardNullableSynf *) (* ******************************************* *) - (* - This module will handle Null types for languages that offer a way of dealing with stack-allocated structures or tuples and generics. Essentialy on those targets a Null will be a tuple ( 'a * bool ), where bool is whether the value is null or not. @@ -9847,15 +8846,10 @@ end;; dependencies: Needs to be run after all cast detection modules - - *) - module HardNullableSynf = struct - let name = "hard_nullable" - let priority = solve_deps name [DAfter CastDetect.ReturnCast.priority] let rec is_null_t gen t = match gen.greal_type t with @@ -9886,21 +8880,16 @@ struct Some( TType(tdef, [ strip_off_nullable of_t ]) ) | _ -> None - let traverse gen unwrap_null wrap_val null_to_dynamic has_value opeq_handler handle_opeq handle_cast = - (* let unwrap_null e = *) - (* let ret = unwrap_null e in *) - (* { ret with eexpr = TParenthesis(ret) } *) - (* in *) - (* let wrap_val e t b = *) - (* let ret = wrap_val e t b in *) - (* { ret with eexpr = TParenthesis(ret) } *) - (* in *) + let configure gen unwrap_null wrap_val null_to_dynamic has_value opeq_handler = + gen.gfollow#add ~name:(name ^ "_follow") (follow_addon gen); + + let is_null_t = is_null_t gen in let is_string t = match gen.greal_type t with | TInst({ cl_path=([],"String") },_) -> true | _ -> false in let handle_unwrap to_t e = - let e_null_t = get (is_null_t gen e.etype) in + let e_null_t = get (is_null_t e.etype) in match gen.greal_type to_t with | TDynamic _ | TMono _ | TAnon _ -> (match e_null_t with @@ -9920,7 +8909,6 @@ struct wrap_val e t true in - let is_null_t = is_null_t gen in let cur_block = ref [] in let add_tmp v e p = cur_block := { eexpr = TVar(v,e); etype = gen.gcon.basic.tvoid; epos = p } :: !cur_block @@ -9963,8 +8951,6 @@ struct ) | None, Some(et) -> handle_wrap (run v) et - | Some(vt), Some(et) when handle_cast -> - handle_wrap (gen.ghandle_cast et vt (handle_unwrap vt (run v))) et | Some(vt), Some(et) when not (type_iseq (run_follow gen vt) (run_follow gen et)) -> (* check if has value and convert *) let vlocal_fst, vlocal = get_local (run v) in @@ -10024,8 +9010,6 @@ struct | _ -> Type.map_expr run e (* casts are already dealt with normal CastDetection module *) ) - | Ast.OpEq | Ast.OpNotEq when not handle_opeq -> - Type.map_expr run e | Ast.OpEq | Ast.OpNotEq -> (match e1.eexpr, e2.eexpr with | TConst(TNull), _ when is_some e2_t -> @@ -10101,12 +9085,7 @@ struct | { eexpr = TBlock([e]) } -> e | e -> e in - run - - let configure gen (mapping_func:texpr->texpr) = - gen.gfollow#add ~name:(name ^ "_follow") (follow_addon gen); - - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map end;; @@ -10114,52 +9093,40 @@ end;; (* ******************************************* *) (* ArrayDeclSynf *) (* ******************************************* *) - (* - A syntax filter that will change array declarations to the actual native array declarations plus the haxe array initialization dependencies: Must run after ObjectDeclMap since it can add TArrayDecl expressions - *) - module ArrayDeclSynf = struct - let name = "array_decl_synf" - let priority = solve_deps name [DAfter ObjectDeclMap.priority] - let default_implementation gen native_array_cl = + let configure gen native_array_cl = let rec run e = match e.eexpr with - | TArrayDecl el -> - let cl, params = match follow e.etype with - | TInst(({ cl_path = ([], "Array") } as cl), ( _ :: _ as params)) -> cl, params - | TInst(({ cl_path = ([], "Array") } as cl), []) -> cl, [t_dynamic] - | _ -> assert false - in - - let changed_params = gen.greal_type_param (TClassDecl cl) params in - { e with eexpr = TNew(cl, changed_params, [ { e with eexpr = TArrayDecl(List.map run el); etype = TInst(native_array_cl, changed_params) } ] ); } - | _ -> Type.map_expr run e + | TArrayDecl el -> + let cl, params = match follow e.etype with + | TInst(({ cl_path = ([], "Array") } as cl), ( _ :: _ as params)) -> cl, params + | TInst(({ cl_path = ([], "Array") } as cl), []) -> cl, [t_dynamic] + | _ -> assert false + in + let changed_params = gen.greal_type_param (TClassDecl cl) params in + { e with eexpr = TNew(cl, changed_params, [ { e with eexpr = TArrayDecl(List.map run el); etype = TInst(native_array_cl, changed_params) } ] ); } + | _ -> Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map - end;; + (* ******************************************* *) (* SwitchBreakSynf *) (* ******************************************* *) - (* - In most languages, 'break' is used as a statement also to break from switch statements. This generates an incompatibility with haxe code, as we can use break to break from loops from inside a switch @@ -10175,19 +9142,15 @@ end;; Since UnreachableCodeElimination must run before it, and Unreachable should be one of the very last filters to run, we will make a fixed value which runs after UnreachableCodeElimination (meaning: it's the very last filter) - *) - module SwitchBreakSynf = struct - let name = "switch_break_synf" - let priority = min_dep -. 150.0 type add_to_block_api = texpr->bool->unit - let traverse gen (change_loop:texpr->int->add_to_block_api->texpr) (change_break:texpr->int->add_to_block_api->texpr) = + let configure gen (change_loop:texpr->int->add_to_block_api->texpr) (change_break:texpr->int->add_to_block_api->texpr) = let in_switch = ref false in let cur_block = ref [] in let to_add = ref [] in @@ -10201,73 +9164,68 @@ struct let rec run e = match e.eexpr with - | TFunction _ -> - let old_num = !num in - num := 0; - let ret = Type.map_expr run e in - num := old_num; - ret - | TFor _ - | TWhile _ -> - let last_switch = !in_switch in - let last_found = !did_found in - let last_num = !cur_num in - in_switch := false; - incr num; - cur_num := !num; - did_found := -1; - let new_e = Type.map_expr run e in (* assuming that no loop will be found in the condition *) - let new_e = if !did_found <> -1 then change_loop new_e !did_found api else new_e in - did_found := last_found; - in_switch := last_switch; - cur_num := last_num; - - new_e - | TSwitch _ -> - let last_switch = !in_switch in - in_switch := true; - - let new_e = Type.map_expr run e in - - in_switch := last_switch; - new_e - | TBlock bl -> - let last_block = !cur_block in - let last_toadd = !to_add in - to_add := []; - cur_block := []; + | TFunction _ -> + let old_num = !num in + num := 0; + let ret = Type.map_expr run e in + num := old_num; + ret + | TFor _ + | TWhile _ -> + let last_switch = !in_switch in + let last_found = !did_found in + let last_num = !cur_num in + in_switch := false; + incr num; + cur_num := !num; + did_found := -1; + let new_e = Type.map_expr run e in (* assuming that no loop will be found in the condition *) + let new_e = if !did_found <> -1 then change_loop new_e !did_found api else new_e in + did_found := last_found; + in_switch := last_switch; + cur_num := last_num; + + new_e + | TSwitch _ -> + let last_switch = !in_switch in + in_switch := true; + + let new_e = Type.map_expr run e in + + in_switch := last_switch; + new_e + | TBlock bl -> + let last_block = !cur_block in + let last_toadd = !to_add in + to_add := []; + cur_block := []; - List.iter (fun e -> - let new_e = run e in - cur_block := new_e :: !cur_block; - match !to_add with - | [] -> () - | _ -> cur_block := !to_add @ !cur_block; to_add := [] - ) bl; - - let ret = List.rev !cur_block in - cur_block := last_block; - to_add := last_toadd; - - { e with eexpr = TBlock(ret) } - | TBreak -> - if !in_switch then (did_found := !cur_num; change_break e !cur_num api) else e - | _ -> Type.map_expr run e - in - run + List.iter (fun e -> + let new_e = run e in + cur_block := new_e :: !cur_block; + match !to_add with + | [] -> () + | _ -> cur_block := !to_add @ !cur_block; to_add := [] + ) bl; - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in - gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map + let ret = List.rev !cur_block in + cur_block := last_block; + to_add := last_toadd; + { e with eexpr = TBlock(ret) } + | TBreak -> + if !in_switch then (did_found := !cur_num; change_break e !cur_num api) else e + | _ -> Type.map_expr run e + in + let map e = Some(run e) in + gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map end;; + (* ******************************************* *) (* Unreachable Code Elimination *) (* ******************************************* *) - (* - In some source code platforms, the code won't compile if there is Unreachable code, so this filter will take off any unreachable code. If the parameter "handle_switch_break" is set to true, it will already add a "break" statement on switch cases when suitable; in order to not confuse with while break, it will be a special expression __sbreak__ @@ -10279,9 +9237,7 @@ end;; dependencies: This must run before SwitchBreakSynf (see SwitchBreakSynf dependecy value) This must be the LAST syntax filter to run. It expects ExpressionUnwrap to have run correctly, since this will only work for source-code based targets - *) - module UnreachableCodeEliminationSynf = struct @@ -10318,8 +9274,9 @@ struct | TParenthesis(e) | TMeta(_,e) -> get_constant_expr e | _ -> None - let traverse gen should_warn handle_switch_break handle_not_final_returns java_mode = + let traverse gen java_mode = let basic = gen.gcon.basic in + let should_warn = false in let do_warn = if should_warn then gen.gcon.warning "Unreachable code" else (fun pos -> ()) @@ -10343,15 +9300,11 @@ struct | _ -> false in - let handle_case = if handle_switch_break then - (fun (expr,kind) -> - match kind with - | Normal when has_fallback expr -> expr - | Normal -> Type.concat expr (mk_sbreak expr.epos) - | BreaksLoop | BreaksFunction -> expr - ) - else - fst + let handle_case = fun (expr,kind) -> + match kind with + | Normal when has_fallback expr -> expr + | Normal -> Type.concat expr (mk_sbreak expr.epos) + | BreaksLoop | BreaksFunction -> expr in let has_break = ref false in @@ -10385,7 +9338,7 @@ struct { expr with eexpr = TBlock(List.rev !new_block) }, !ret_kind | TFunction tf -> let changed, kind = process_expr tf.tf_expr in - let changed = if handle_not_final_returns && not (is_void tf.tf_type) && kind <> BreaksFunction then + let changed = if not (ExtType.is_void tf.tf_type) && kind <> BreaksFunction then Type.concat changed { eexpr = TReturn( Some (null tf.tf_type expr.epos) ); etype = basic.tvoid; epos = expr.epos } else changed @@ -10447,18 +9400,6 @@ struct (el, handle_case (e, ek)) ) el_e_l, Some def) } in ret, !k -(* | TMatch(cond, ep, il_vopt_e_l, None) -> - { expr with eexpr = TMatch(cond, ep, List.map (fun (il, vopt, e) -> (il, vopt, handle_case (process_expr e))) il_vopt_e_l, None) }, Normal *) -(* | TMatch(cond, ep, il_vopt_e_l, Some def) -> - let def, k = process_expr def in - let def = handle_case (def, k) in - let k = ref k in - let ret = { expr with eexpr = TMatch(cond, ep, List.map (fun (il, vopt, e) -> - let e, ek = process_expr e in - k := aggregate_kind !k ek; - (il, vopt, handle_case (e, ek)) - ) il_vopt_e_l, Some def) } in - ret, !k *) | TTry (e, catches) -> let e, k = process_expr e in let k = ref k in @@ -10474,32 +9415,27 @@ struct let run e = fst (process_expr e) in run - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let configure gen java_mode = + let run = traverse gen java_mode in + let map e = Some(run e) in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map - end;; + (* ******************************************* *) (* DefaultArguments *) (* ******************************************* *) - (* - This Module Filter will go through all defined functions in all modules and change them so they set all default arguments to be of a Nullable type, and adds the unroll from nullable to the not-nullable type in the beginning of the function. dependencies: - It must run before OverloadingCtors, since OverloadingCtors will change optional structures behavior - + It must run before OverloadingConstructor, since OverloadingConstructor will change optional structures behavior *) - module DefaultArguments = struct - let name = "default_arguments" - let priority = solve_deps name [ DBefore OverloadingConstructor.priority ] let gen_check basic t nullable_var const pos = @@ -10531,24 +9467,21 @@ struct let add_opt gen block pos (var,opt) = match opt with - | None | Some TNull -> (var,opt) - | Some (TString str) -> - block := Codegen.set_default gen.gcon var (TString str) pos :: !block; - (var, opt) - | Some const -> - let basic = gen.gcon.basic in - let nullable_var = mk_temp gen var.v_name (basic.tnull var.v_type) in - let orig_name = var.v_name in - var.v_name <- nullable_var.v_name; - nullable_var.v_name <- orig_name; - (* var v = (temp_var == null) ? const : cast temp_var; *) - block := - { - eexpr = TVar(var, Some(gen_check basic var.v_type nullable_var const pos)); - etype = basic.tvoid; - epos = pos; - } :: !block; - (nullable_var, opt) + | None | Some TNull -> + (var,opt) + | Some (TString str) -> + block := Codegen.set_default gen.gcon var (TString str) pos :: !block; + (var, opt) + | Some const -> + let basic = gen.gcon.basic in + let nullable_var = mk_temp gen var.v_name (basic.tnull var.v_type) in + let orig_name = var.v_name in + var.v_name <- nullable_var.v_name; + nullable_var.v_name <- orig_name; + (* var v = (temp_var == null) ? const : cast temp_var; *) + let evar = mk (TVar(var, Some(gen_check basic var.v_type nullable_var const pos))) basic.tvoid pos in + block := evar :: !block; + (nullable_var, opt) let rec change_func gen cf = List.iter (change_func gen) cf.cf_overloads; @@ -10627,29 +9560,25 @@ struct (if !found then cf.cf_type <- TFun(!args, ret)) | _, _ -> assert false - let traverse gen = - let run md = match md with + let configure gen = + let run md = + (match md with | TClassDecl cl -> List.iter (change_func gen) cl.cl_ordered_fields; List.iter (change_func gen) cl.cl_ordered_statics; - (match cl.cl_constructor with | None -> () | Some cf -> change_func gen cf); - md - | _ -> md + Option.may (change_func gen) cl.cl_constructor; + | _ -> ()); + Some(md); in - run - - let configure gen (mapping_func:module_type->module_type) = - let map md = Some(mapping_func md) in - gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) map + gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) run end;; + (* ******************************************* *) (* Interface Variables Removal Modf *) (* ******************************************* *) - (* - This module filter will take care of sanitizing interfaces for targets that do not support variables declaration in interfaces. By now this will mean that if anything is typed as the interface, and a variable access is made, a FNotFound will be returned for the field_access, so @@ -10657,99 +9586,81 @@ end;; Speed-wise, ideally it would be best to create getProp/setProp functions in this case and change the AST to call them when accessing by interface. (TODO) But right now it will be accessed by reflection. - - dependencies: - - *) - module InterfaceVarsDeleteModf = struct - let name = "interface_vars" - let priority = solve_deps name [] - let run gen = - let run md = match md with - | TClassDecl ( { cl_interface = true } as cl ) -> + let configure gen = + let run md = + match md with + | TClassDecl ({ cl_interface = true } as cl) -> let to_add = ref [] in let fields = List.filter (fun cf -> match cf.cf_kind with - | Var _ when gen.gcon.platform = Cs && Meta.has Meta.Event cf.cf_meta -> - true - | Var vkind when not (Type.is_extern_field cf && Meta.has Meta.Property cf.cf_meta) -> - (match vkind.v_read with - | AccCall -> - let newcf = mk_class_field ("get_" ^ cf.cf_name) (TFun([],cf.cf_type)) true cf.cf_pos (Method MethNormal) [] in - to_add := newcf :: !to_add; - | _ -> () - ); - (match vkind.v_write with - | AccCall -> - let newcf = mk_class_field ("set_" ^ cf.cf_name) (TFun(["val",false,cf.cf_type],cf.cf_type)) true cf.cf_pos (Method MethNormal) [] in - to_add := newcf :: !to_add; - | _ -> () - ); - cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields; - false - | Method MethDynamic -> - (* TODO OPTIMIZATION - add a `_dispatch` method to the interface which will call the dynamic function itself *) - cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields; - false - | _ -> true + | Var _ when gen.gcon.platform = Cs && Meta.has Meta.Event cf.cf_meta -> + true + | Var vkind when not (Type.is_extern_field cf && Meta.has Meta.Property cf.cf_meta) -> + (match vkind.v_read with + | AccCall -> + let newcf = mk_class_field ("get_" ^ cf.cf_name) (TFun([],cf.cf_type)) true cf.cf_pos (Method MethNormal) [] in + to_add := newcf :: !to_add; + | _ -> () + ); + (match vkind.v_write with + | AccCall -> + let newcf = mk_class_field ("set_" ^ cf.cf_name) (TFun(["val",false,cf.cf_type],cf.cf_type)) true cf.cf_pos (Method MethNormal) [] in + to_add := newcf :: !to_add; + | _ -> () + ); + cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields; + false + | Method MethDynamic -> + (* TODO OPTIMIZATION - add a `_dispatch` method to the interface which will call the dynamic function itself *) + cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields; + false + | _ -> + true ) cl.cl_ordered_fields in cl.cl_ordered_fields <- fields; List.iter (fun cf -> match field_access gen (TInst(cl,List.map snd cl.cl_params)) cf.cf_name with - | FNotFound | FDynamicField _ -> - cl.cl_ordered_fields <- cf :: cl.cl_ordered_fields; - cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields - | _ -> () - ) !to_add; - - md - | _ -> md + | FNotFound | FDynamicField _ -> + cl.cl_ordered_fields <- cf :: cl.cl_ordered_fields; + cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields + | _ -> + () + ) !to_add + | _ -> () in - run - - let configure gen = - let run = run gen in - let map md = Some(run md) in + let map md = Some(run md; md) in gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) map - - end;; + (* ******************************************* *) (* InterfaceProps *) (* ******************************************* *) - (* - This module filter will go through all declared properties, and see if they are conforming to a native interface. - If they are, it will add Meta.Property to it - - dependencies: - + If they are, it will add Meta.Property to it. *) - module InterfaceProps = struct let name = "interface_props" - let priority = solve_deps name [] - let run gen = - let run md = match md with - | TClassDecl ( { cl_interface = false; cl_extern = false } as cl ) -> + let configure gen = + let run md = + match md with + | TClassDecl ({ cl_interface = false; cl_extern = false } as cl) -> let vars = List.fold_left (fun acc (iface,_) -> if Meta.has Meta.CsNative iface.cl_meta then List.filter (fun cf -> match cf.cf_kind with - | Var { v_read = AccCall } | Var { v_write = AccCall } -> - true + | Var { v_read = AccCall } | Var { v_write = AccCall } -> true | _ -> false ) iface.cl_ordered_fields @ acc else @@ -10759,235 +9670,153 @@ struct if vars <> [] then List.iter (fun cf -> match cf.cf_kind with | Var { v_read = AccCall } | Var { v_write = AccCall } when List.mem cf.cf_name vars -> - cf.cf_meta <- (Meta.Property, [], Ast.null_pos) :: cf.cf_meta + cf.cf_meta <- (Meta.Property, [], null_pos) :: cf.cf_meta | _ -> () - ) cl.cl_ordered_fields; - - md - | _ -> md + ) cl.cl_ordered_fields + | _ -> + () in - run - - let configure gen = - let run = run gen in - let map md = Some(run md) in + let map md = Some(run md; md) in gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) map end;; + (* ******************************************* *) (* Int Division Synf *) (* ******************************************* *) - (* - - On targets that support int division, this module will force a float division to be performed, - so compatibility with current haxe targets is ensured. - If catch_int_div is set to true, though, it will look for casts to int or use of Std.int() to optimize - this kind of operation. + On targets that support int division, this module will force a float division to be performed. + It will also look for casts to int or use of Std.int() to optimize this kind of operation. dependencies: since it depends on nothing, but many modules might generate division expressions, it will be one of the last modules to run - *) - module IntDivisionSynf = struct - let name = "int_division_synf" - let priority = solve_deps name [ DAfter ExpressionUnwrap.priority; DAfter ObjectDeclMap.priority; DAfter ArrayDeclSynf.priority ] - let is_int = like_int - - let is_exactly_int t = match follow t with - | TAbstract ({ a_path=[],"Int" }, []) -> true - | _ -> false - - let default_implementation gen catch_int_div = + let configure gen = let basic = gen.gcon.basic in + let rec is_int t = match follow t with + | TInst({ cl_path = (["haxe";"lang"],"Null") }, [t]) -> is_int t + | t -> + like_int t && not (like_i64 t) + in + let is_exactly_int t = match follow t with + | TAbstract ({ a_path=[],"Int" }, []) -> true + | _ -> false + in let rec run e = match e.eexpr with - | TBinop((Ast.OpDiv as op), e1, e2) when is_int e1.etype && is_int e2.etype -> - { e with eexpr = TBinop(op, mk_cast basic.tfloat (run e1), run e2) } - | TCall( - { eexpr = TField(_, FStatic({ cl_path = ([], "Std") }, { cf_name = "int" })) }, - [ ({ eexpr = TBinop((Ast.OpDiv as op), e1, e2) } as ebinop ) ] - ) when catch_int_div && is_int e1.etype && is_int e2.etype -> - let e = { ebinop with eexpr = TBinop(op, run e1, run e2); etype = basic.tint } in - if not (is_exactly_int e1.etype && is_exactly_int e2.etype) then - mk_cast basic.tint e - else - e - | TCast( ({ eexpr = TBinop((Ast.OpDiv as op), e1, e2) } as ebinop ), _ ) - | TCast( ({ eexpr = TBinop(( (Ast.OpAssignOp Ast.OpDiv) as op), e1, e2) } as ebinop ), _ ) when catch_int_div && is_int e1.etype && is_int e2.etype && is_int e.etype -> - let ret = { ebinop with eexpr = TBinop(op, run e1, run e2); etype = e.etype } in - if not (is_exactly_int e1.etype && is_exactly_int e2.etype) then - mk_cast e.etype ret - else - e - | _ -> Type.map_expr run e + | TBinop((Ast.OpDiv as op), e1, e2) when is_int e1.etype && is_int e2.etype -> + { e with eexpr = TBinop(op, mk_cast basic.tfloat (run e1), run e2) } + | TCall( + { eexpr = TField(_, FStatic({ cl_path = ([], "Std") }, { cf_name = "int" })) }, + [ ({ eexpr = TBinop((Ast.OpDiv as op), e1, e2) } as ebinop ) ] + ) when is_int e1.etype && is_int e2.etype -> + let e = { ebinop with eexpr = TBinop(op, run e1, run e2); etype = basic.tint } in + if not (is_exactly_int e1.etype && is_exactly_int e2.etype) then + mk_cast basic.tint e + else + e + | TCast( ({ eexpr = TBinop((Ast.OpDiv as op), e1, e2) } as ebinop ), _ ) + | TCast( ({ eexpr = TBinop(( (Ast.OpAssignOp Ast.OpDiv) as op), e1, e2) } as ebinop ), _ ) when is_int e1.etype && is_int e2.etype && is_int e.etype -> + let ret = { ebinop with eexpr = TBinop(op, run e1, run e2); etype = e.etype } in + if not (is_exactly_int e1.etype && is_exactly_int e2.etype) then + mk_cast e.etype ret + else + e + | _ -> + Type.map_expr run e in - run - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map - end;; + (* ******************************************* *) (* UnnecessaryCastsRemoval *) (* ******************************************* *) - (* - This module will take care of simplifying unnecessary casts, specially those made by the compiler when inlining. Right now, it will only take care of casts used as a statement, which are always useless; TODO: Take care of more cases, e.g. when the to and from types are the same dependencies: This must run after CastDetection, but before ExpressionUnwrap - *) - module UnnecessaryCastsRemoval = struct - let name = "casts_removal" - let priority = solve_deps name [DAfter CastDetect.priority; DBefore ExpressionUnwrap.priority] - let rec take_off_cast run e = - match e.eexpr with - | TCast (c, _) -> - take_off_cast run c + let configure gen = + let rec take_off_cast run e = + match e.eexpr with + | TCast (c, _) -> take_off_cast run c | _ -> run e - - let default_implementation gen = + in let rec traverse e = match e.eexpr with - | TBlock bl -> - let bl = List.map (fun e -> - take_off_cast traverse e - ) bl in - { e with eexpr = TBlock bl } - | TTry (block, catches) -> - { e with eexpr = TTry(traverse (mk_block block), List.map (fun (v,block) -> (v, traverse (mk_block block))) catches) } -(* | TMatch (cond,ep,il_vol_e_l,default) -> - { e with eexpr = TMatch(cond,ep,List.map (fun (il,vol,e) -> (il,vol,traverse (mk_block e))) il_vol_e_l, Option.map (fun e -> traverse (mk_block e)) default) } *) - | TSwitch (cond,el_e_l, default) -> - { e with eexpr = TSwitch(cond, List.map (fun (el,e) -> (el, traverse (mk_block e))) el_e_l, Option.map (fun e -> traverse (mk_block e)) default) } - | TWhile (cond,block,flag) -> - {e with eexpr = TWhile(cond,traverse (mk_block block), flag) } - | TIf (cond, eif, eelse) -> - { e with eexpr = TIf(cond, traverse (mk_block eif), Option.map (fun e -> traverse (mk_block e)) eelse) } - | TFor (v,it,block) -> - { e with eexpr = TFor(v,it, traverse (mk_block block)) } - | TFunction (tfunc) -> - { e with eexpr = TFunction({ tfunc with tf_expr = traverse (mk_block tfunc.tf_expr) }) } - | _ -> e (* if expression doesn't have a block, we will exit *) + | TBlock bl -> + let bl = List.map (take_off_cast traverse) bl in + { e with eexpr = TBlock bl } + | TTry (block, catches) -> + { e with eexpr = TTry(traverse (mk_block block), List.map (fun (v,block) -> (v, traverse (mk_block block))) catches) } + | TSwitch (cond,el_e_l, default) -> + { e with eexpr = TSwitch(cond, List.map (fun (el,e) -> (el, traverse (mk_block e))) el_e_l, Option.map (fun e -> traverse (mk_block e)) default) } + | TWhile (cond,block,flag) -> + {e with eexpr = TWhile(cond,traverse (mk_block block), flag) } + | TIf (cond, eif, eelse) -> + { e with eexpr = TIf(cond, traverse (mk_block eif), Option.map (fun e -> traverse (mk_block e)) eelse) } + | TFor (v,it,block) -> + { e with eexpr = TFor(v,it, traverse (mk_block block)) } + | TFunction (tfunc) -> + { e with eexpr = TFunction({ tfunc with tf_expr = traverse (mk_block tfunc.tf_expr) }) } + | _ -> e (* if expression doesn't have a block, we will exit *) in - traverse - - let configure gen = - let map e = Some(default_implementation gen e) in + let map e = Some(traverse e) in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map - end;; -(* ******************************************* *) -(* OverrideFix *) -(* ******************************************* *) - -(* - - When DCE is on, sometimes a field is marked as override when it - really doesn't override anything. This module filter will take care of this. - - dependencies: - No dependencies - -*) - -module OverrideFix = -struct - - let name = "override_fix" - - let priority = solve_deps name [] - - let default_implementation gen = - let rec run e = - match e.eexpr with - | _ -> Type.map_expr run e - in - run - - let configure gen = - let map md = - match md with - | TClassDecl cl -> - cl.cl_overrides <- List.filter (fun s -> - let rec loop cl = - match cl.cl_super with - | Some (cl,_) when PMap.mem s.cf_name cl.cl_fields -> true - | Some (cl,_) -> loop cl - | None -> false - in - loop cl - ) cl.cl_overrides; - Some md - | _ -> Some md - in - gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) map - -end;; (* ******************************************* *) (* AbstractImplementationFix *) (* ******************************************* *) - (* - This module filter will map the compiler created classes from abstract implementations to valid haxe code, as needed by gencommon dependencies: No dependencies - *) - module AbstractImplementationFix = struct - let name = "abstract_implementation_fix" - let priority = solve_deps name [] - let default_implementation gen = - let rec run md = - match md with - | TClassDecl ({ cl_kind = KAbstractImpl a } as c) -> - List.iter (function - | ({ cf_name = "_new" } as cf) -> - cf.cf_params <- cf.cf_params @ a.a_params - | cf when Meta.has Meta.Impl cf.cf_meta -> - (match cf.cf_expr with - | Some({ eexpr = TFunction({ tf_args = (v, _) :: _ }) }) when Meta.has Meta.This v.v_meta -> - cf.cf_params <- cf.cf_params @ a.a_params - | _ -> ()) - | _ -> () - ) c.cl_ordered_statics; - Some md - | _ -> Some md - in - run - let configure gen = - let map = default_implementation gen in - gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) map - + let run md = + (match md with + | TClassDecl ({ cl_kind = KAbstractImpl a } as c) -> + List.iter ( + function + | ({ cf_name = "_new" } as cf) -> + cf.cf_params <- cf.cf_params @ a.a_params + | cf when Meta.has Meta.Impl cf.cf_meta -> + (match cf.cf_expr with + | Some({ eexpr = TFunction({ tf_args = (v, _) :: _ }) }) when Meta.has Meta.This v.v_meta -> + cf.cf_params <- cf.cf_params @ a.a_params + | _ -> ()) + | _ -> () + ) c.cl_ordered_statics + | _ -> ()); + Some md + in + gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) run end;; (* ******************************************* *) @@ -11045,14 +9874,14 @@ struct let ftype = apply_params iface.cl_params itl f.cf_type in let real_ftype = get_real_fun gen (apply_params iface.cl_params real_itl f.cf_type) in replace_mono real_ftype; - let overloads = Typeload.get_overloads c f.cf_name in + let overloads = Overloads.get_overloads c f.cf_name in try let t2, f2 = match overloads with | (_, cf) :: _ when Meta.has Meta.Overload cf.cf_meta -> (* overloaded function *) (* try to find exact function *) List.find (fun (t,f2) -> - Typeload.same_overload_args ~get_vmtype ftype t f f2 + Overloads.same_overload_args ~get_vmtype ftype t f f2 ) overloads | _ :: _ -> (match field_access gen (TInst(c, List.map snd c.cl_params)) f.cf_name with @@ -11068,11 +9897,11 @@ struct if List.length f.cf_params <> List.length f2.cf_params then raise Not_found; replace_mono t2; match follow (apply_params f2.cf_params (List.map snd f.cf_params) t2), follow real_ftype with - | TFun(a1,r1), TFun(a2,r2) when not implement_explicitly && not (type_iseq r1 r2) && Typeload.same_overload_args ~get_vmtype real_ftype t2 f f2 -> + | TFun(a1,r1), TFun(a2,r2) when not implement_explicitly && not (type_iseq r1 r2) && Overloads.same_overload_args ~get_vmtype real_ftype t2 f f2 -> (* different return types are the trickiest cases to deal with *) (* check for covariant return type *) let is_covariant = match follow r1, follow r2 with - | _, TDynamic _ -> true + | _, TDynamic _ -> false | r1, r2 -> try unify r1 r2; true @@ -11094,7 +9923,7 @@ struct | TFun(a1,r1), TFun(a2,r2) -> (* just implement a function that will call the main one *) let name, is_explicit = match explicit_fn_name with - | Some fn when not (type_iseq r1 r2) && Typeload.same_overload_args ~get_vmtype real_ftype t2 f f2 -> + | Some fn when not (type_iseq r1 r2) && Overloads.same_overload_args ~get_vmtype real_ftype t2 f f2 -> fn iface itl f.cf_name, true | _ -> f.cf_name, false in @@ -11106,7 +9935,7 @@ struct let field = { eexpr = TField(this, FInstance(c,List.map snd c.cl_params,f2)); etype = TFun(a1,r1); epos = p } in let call = { eexpr = TCall(field, args); etype = r1; epos = p } in (* let call = gen.gparam_func_call call field (List.map snd f.cf_params) args in *) - let is_void = is_void r2 in + let is_void = ExtType.is_void r2 in newf.cf_expr <- Some { eexpr = TFunction({ @@ -11145,43 +9974,9 @@ struct in match decl with | Some(f2,actual_t,_,t,declared_cl,_,_) - when not (Typeload.same_overload_args ~get_vmtype actual_t (get_real_fun gen f.cf_type) f2 f) -> - if Meta.has Meta.Overload f.cf_meta then begin - (* if it is overload, create another field with the requested type *) - let f3 = mk_class_field f.cf_name t f.cf_public f.cf_pos f.cf_kind f.cf_params in - let p = f.cf_pos in - let old_args, old_ret = get_fun f.cf_type in - let args, ret = get_fun t in - let tf_args = List.map (fun (n,o,t) -> alloc_var n t, None) args in - let f3_mk_return = if is_void ret then (fun e -> e) else (fun e -> mk_return (mk_cast ret e)) in - f3.cf_expr <- Some { - eexpr = TFunction({ - tf_args = tf_args; - tf_type = ret; - tf_expr = mk_block (f3_mk_return { - eexpr = TCall( - { - eexpr = TField( - { eexpr = TConst TThis; etype = TInst(c, List.map snd c.cl_params); epos = p }, - FInstance(c,List.map snd c.cl_params,f)); - etype = f.cf_type; - epos = p - }, - List.map2 (fun (v,_) (_,_,t) -> mk_cast t (mk_local v p)) tf_args old_args); - etype = old_ret; - epos = p - }) - }); - etype = t; - epos = p; - }; - gen.gafter_filters_ended <- ((fun () -> - f.cf_overloads <- f3 :: f.cf_overloads; - ) :: gen.gafter_filters_ended); - f3 - end else begin match f.cf_expr with + when not (Overloads.same_overload_args ~get_vmtype actual_t (get_real_fun gen f.cf_type) f2 f) -> + (match f.cf_expr with | Some({ eexpr = TFunction(tf) } as e) -> - (* if it's not overload, just cast the vars *) let actual_args, _ = get_fun (get_real_fun gen actual_t) in let new_args, vardecl = List.fold_left2 (fun (args,vdecl) (v,_) (_,_,t) -> if not (type_iseq (gen.greal_type v.v_type) (gen.greal_type t)) then begin @@ -11190,17 +9985,62 @@ struct end else (v,None) :: args, vdecl ) ([],[]) tf.tf_args actual_args in - - if vardecl <> [] then - f.cf_expr <- Some({ e with - eexpr = TFunction({ tf with - tf_args = List.rev new_args; - tf_expr = Type.concat { eexpr = TBlock(List.map (fun (v,ve) -> { eexpr = TVar(v,ve); etype = gen.gcon.basic.tvoid; epos = e.epos }) vardecl); etype = gen.gcon.basic.tvoid; epos = e.epos } tf.tf_expr + let block = { eexpr = TBlock(List.map (fun (v,ve) -> + { + eexpr = TVar(v,ve); + etype = gen.gcon.basic.tvoid; + epos = tf.tf_expr.epos + }) vardecl); + etype = gen.gcon.basic.tvoid; + epos = tf.tf_expr.epos + } in + if Meta.has Meta.Overload f.cf_meta then begin + (* if it is overload, create another field with the requested type *) + let f3 = mk_class_field f.cf_name t f.cf_public f.cf_pos f.cf_kind f.cf_params in + let p = f.cf_pos in + let old_args, old_ret = get_fun f.cf_type in + let args, ret = get_fun t in + let tf_args = List.map (fun (n,o,t) -> alloc_var n t, None) args in + let f3_mk_return = if ExtType.is_void ret then (fun e -> e) else (fun e -> mk_return (mk_cast ret e)) in + f3.cf_expr <- Some { + eexpr = TFunction({ + tf_args = List.rev new_args; + tf_type = ret; + tf_expr = Type.concat block (mk_block (f3_mk_return { + eexpr = TCall( + { + eexpr = TField( + { eexpr = TConst TThis; etype = TInst(c, List.map snd c.cl_params); epos = p }, + FInstance(c,List.map snd c.cl_params,f)); + etype = f.cf_type; + epos = p + }, + List.map2 (fun (v,_) (_,_,t) -> mk_cast t (mk_local v p)) tf_args old_args); + etype = old_ret; + epos = p + })) + }); + etype = t; + epos = p; + }; + (* make sure we skip cast detect - otherwise this new function will make the overload detection go crazy *) + f3.cf_meta <- (Meta.Custom(":skipCastDetect"), [], f3.cf_pos) :: f3.cf_meta; + gen.gafter_expr_filters_ended <- ((fun () -> + f.cf_overloads <- f3 :: f.cf_overloads; + ) :: gen.gafter_expr_filters_ended); + f3 + end else begin + (* if it's not overload, just cast the vars *) + if vardecl <> [] then + f.cf_expr <- Some({ e with + eexpr = TFunction({ tf with + tf_args = List.rev new_args; + tf_expr = Type.concat block tf.tf_expr + }); }); - }); - f - | _ -> f - end + f + end + | _ -> f) | _ -> f in if not c.cl_extern then @@ -11220,12 +10060,11 @@ struct gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) map end;; + (* ******************************************* *) (* Normalize *) (* ******************************************* *) - (* - - Filters out enum constructor type parameters from the AST; See Issue #1796 - Filters out monomorphs - Filters out all non-whitelisted AST metadata @@ -11233,51 +10072,59 @@ end;; dependencies: No dependencies; but it still should be one of the first filters to run, as it will help normalize the AST - *) - module Normalize = struct - let name = "normalize_type" - let priority = max_dep - let rec filter_param t = match t with - | TInst({ cl_kind = KTypeParameter _ } as c,_) when Meta.has Meta.EnumConstructorParam c.cl_meta -> - t_dynamic - | TMono r -> (match !r with - | None -> t_dynamic - | Some t -> filter_param t) - | TInst(_,[]) | TEnum(_,[]) | TType(_,[]) | TAbstract(_,[]) -> t - | TType(t,tl) -> TType(t,List.map filter_param tl) - | TInst(c,tl) -> TInst(c,List.map filter_param tl) - | TEnum(e,tl) -> TEnum(e,List.map filter_param tl) - | TAbstract({ a_path = (["haxe";"extern"],"Rest") } as a,tl) -> TAbstract(a, List.map filter_param tl) - | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> - filter_param (Abstract.get_underlying_type a tl) - | TAbstract(a,tl) -> TAbstract(a, List.map filter_param tl) - | TAnon a -> - TAnon { - a_fields = PMap.map (fun f -> { f with cf_type = filter_param f.cf_type }) a.a_fields; - a_status = a.a_status; - } - | TFun(args,ret) -> TFun(List.map (fun (n,o,t) -> (n,o,filter_param t)) args, filter_param ret) - | TDynamic _ -> t - | TLazy f -> filter_param (!f()) + let rec filter_param t = + match t with + | TInst({ cl_kind = KTypeParameter _ } as c,_) when Meta.has Meta.EnumConstructorParam c.cl_meta -> + t_dynamic + | TMono r -> + (match !r with + | None -> t_dynamic + | Some t -> filter_param t) + | TInst(_,[]) | TEnum(_,[]) | TType(_,[]) | TAbstract(_,[]) -> + t + | TType(t,tl) -> + TType(t,List.map filter_param tl) + | TInst(c,tl) -> + TInst(c,List.map filter_param tl) + | TEnum(e,tl) -> + TEnum(e,List.map filter_param tl) + | TAbstract({ a_path = (["haxe";"extern"],"Rest") } as a,tl) -> + TAbstract(a, List.map filter_param tl) + | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> + filter_param (Abstract.get_underlying_type a tl) + | TAbstract(a,tl) -> + TAbstract(a, List.map filter_param tl) + | TAnon a -> + TAnon { + a_fields = PMap.map (fun f -> { f with cf_type = filter_param f.cf_type }) a.a_fields; + a_status = a.a_status; + } + | TFun(args,ret) -> + TFun(List.map (fun (n,o,t) -> (n,o,filter_param t)) args, filter_param ret) + | TDynamic _ -> + t + | TLazy f -> + filter_param (!f()) - let default_implementation gen ~metas = + let configure gen ~metas = let rec run e = match e.eexpr with - | TMeta(entry, e) when not (Hashtbl.mem metas entry) -> + | TMeta (entry, e) when not (Hashtbl.mem metas entry) -> run e | _ -> map_expr_type (fun e -> run e) filter_param (fun v -> v.v_type <- filter_param v.v_type; v) e in - run + let map e = Some (run e) in + gen.gexpr_filters#add ~name:name ~priority:(PCustom priority) map; - let default_implementation_module gen ~metas = - let rec run md = match md with + let run md = + match md with | TClassDecl cl -> let rec map cf = cf.cf_type <- filter_param cf.cf_type; @@ -11285,95 +10132,47 @@ struct in List.iter map cl.cl_ordered_fields; List.iter map cl.cl_ordered_statics; - Option.may map cl.cl_constructor; - md - | _ -> md + Option.may map cl.cl_constructor + | _ -> + () in - run - - let configure gen ~metas = - let map e = Some(default_implementation gen e ~metas:metas) in - gen.gexpr_filters#add ~name:name ~priority:(PCustom priority) map; - let map md = Some(default_implementation_module gen ~metas md) in + let map md = Some (run md; md) in gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) map end;; + (* ******************************************* *) (* InterfaceMetas *) (* ******************************************* *) - (* - Deal with metadata on interfaces by taking it off from interface, and adding a new class with `_HxMeta` suffix dependencies: Must run before InitFunction - *) - module InterfaceMetas = struct - let name = "interface_metas" - let priority = solve_deps name [ DBefore InitFunction.priority ] - let traverse gen = - let run md = match md with + let configure gen = + let run md = + match md with | TClassDecl ({ cl_interface = true; cl_ordered_statics = (_ :: _) } as cl) -> cl.cl_ordered_statics <- []; let path = fst cl.cl_path,snd cl.cl_path ^ "_HxMeta" in (match Codegen.build_metadata gen.gcon (TClassDecl cl) with - | Some expr -> - let ncls = mk_class cl.cl_module path cl.cl_pos in - let cf = mk_class_field "__meta__" expr.etype false expr.epos (Var { v_read = AccNormal; v_write = AccNormal }) [] in - cf.cf_expr <- Some expr; - ncls.cl_statics <- PMap.add "__meta__" cf ncls.cl_statics; - ncls.cl_ordered_statics <- cf :: ncls.cl_ordered_statics; - gen.gadd_to_module (TClassDecl(ncls)) priority; - | _ -> ()) + | Some expr -> + let ncls = mk_class cl.cl_module path cl.cl_pos in + let cf = mk_class_field "__meta__" expr.etype false expr.epos (Var { v_read = AccNormal; v_write = AccNormal }) [] in + cf.cf_expr <- Some expr; + ncls.cl_statics <- PMap.add "__meta__" cf ncls.cl_statics; + ncls.cl_ordered_statics <- cf :: ncls.cl_ordered_statics; + gen.gadd_to_module (TClassDecl(ncls)) priority; + | _ -> ()) | _ -> () in - run - - let configure gen = - let map md = traverse gen md; Some(md) in + let map md = run md; Some(md) in gen.gmodule_filters#add ~name:name ~priority:(PCustom priority) map - end;; - -(* -(* ******************************************* *) -(* Example *) -(* ******************************************* *) - -(* - - description - - dependencies: - - -*) - -module Example = -struct - - let name = "example" - - let priority = solve_deps name [] - - let default_implementation gen = - let rec run e = - match e.eexpr with - | _ -> Type.map_expr run e - in - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in - gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map - -end;; -*) diff --git a/src/generators/gencpp.ml b/src/generators/gencpp.ml new file mode 100644 index 00000000..355fcb41 --- /dev/null +++ b/src/generators/gencpp.ml @@ -0,0 +1,7566 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Ast +open Type +open Common +open Globals + +(* + Generators do not care about non-core-type abstracts, so let us follow them + away by default. +*) +let follow = Abstract.follow_with_abstracts + +(* + Code for generating source files. + It manages creating diretories, indents, blocks and only modifying files + when the content changes. +*) + +(* + A class_path is made from a package (array of strings) and a class name. + Join these together, inclding a separator. eg, "/" for includes : pack1/pack2/Name or "::" + for namespace "pack1::pack2::Name" +*) +let join_class_path path separator = + let result = match fst path, snd path with + | [], s -> s + | el, s -> String.concat separator el ^ separator ^ s in + if (String.contains result '+') then begin + let idx = String.index result '+' in + (String.sub result 0 idx) ^ (String.sub result (idx+1) ((String.length result) - idx -1 ) ) + end else + result;; + +let class_text path = + join_class_path path "::" +;; + +(* The internal classes are implemented by the core hxcpp system, so the cpp + classes should not be generated *) +let is_internal_class = function + | ([],"Int") | ([],"Void") | ([],"String") | ([], "Null") | ([], "Float") + | ([],"Array") | ([], "Class") | ([], "Enum") | ([], "Bool") + | ([], "Dynamic") | ([], "ArrayAccess") | (["cpp"], "FastIterator") + | (["cpp"],"Pointer") | (["cpp"],"ConstPointer") + | (["cpp"],"RawPointer") | (["cpp"],"RawConstPointer") + | (["cpp"],"Function") -> true + | (["cpp"],"VirtualArray") -> true + | ([],"Math") -> true + | (["cpp"],"Int8") | (["cpp"],"UInt8") | (["cpp"],"Char") + | (["cpp"],"Int16") | (["cpp"],"UInt16") + | (["cpp"],"Int32") | (["cpp"],"UInt32") + | (["cpp"],"Int64") | (["cpp"],"UInt64") + | (["cpp"],"Float32") | (["cpp"],"Float64") -> true + | _ -> false;; + +let get_include_prefix common_ctx with_slash = + try + (Common.defined_value common_ctx Define.IncludePrefix) ^ (if with_slash then "/" else "") + with + Not_found -> "" +;; + + +let should_prefix_include = function + | x when is_internal_class x -> false + | ([],"hxMath") -> true + | _ -> false;; + + +let verbatim_include file = + if (String.sub file 0 1)="@" then + ("@import " ^ (String.sub file 1 ((String.length file) - 1 )) ^ ";\n") + else + ("#include \"" ^ file ^ "\"\n") +;; + +let hash64 s = + String.sub (Digest.to_hex (Digest.string s)) 0 16 +;; + + +let guarded_include file = + let guard_name = "INCLUDED_" ^ (hash64 file) in + "#ifndef " ^ guard_name ^ "\n" ^ + "#define " ^ guard_name ^ "\n" ^ + (verbatim_include file) ^ + "#endif\n"; + + + +class source_writer common_ctx write_header_func write_func close_func = + object(this) + val indent_str = "\t" + val mutable indent = "" + val mutable indents = [] + val mutable just_finished_block = false + val mutable headerLines = Hashtbl.create 0 + method close = close_func(); () + method write x = write_func x; just_finished_block <- false + method write_h x = write_header_func x; () + method write_h_unique x = if not (Hashtbl.mem headerLines x) then begin + Hashtbl.add headerLines x (); + this#write_h x; + end + method indent_one = this#write indent_str + + method push_indent = indents <- indent_str::indents; indent <- String.concat "" indents + method pop_indent = match indents with + | h::tail -> indents <- tail; indent <- String.concat "" indents + | [] -> indent <- "/*?*/"; + method write_i x = this#write (indent ^ x) + method get_indent = indent + method begin_block = this#write ("{\n"); this#push_indent + method end_block = this#pop_indent; this#write_i "}\n"; just_finished_block <- true + method end_block_line = this#pop_indent; this#write_i "}"; just_finished_block <- true + method terminate_line = this#write (if just_finished_block then "" else ";\n") + method add_big_closures = this#write_h_unique "#include \n"; + + method add_include class_path = + ( match class_path with + | (["@verbatim"],file) -> this#write_h_unique (guarded_include file) + | _ -> + let prefix = if should_prefix_include class_path then "" else get_include_prefix common_ctx true in + this#write_h ("#ifndef INCLUDED_" ^ (join_class_path class_path "_") ^ "\n"); + this#write_h ("#include <" ^ prefix ^ (join_class_path class_path "/") ^ ".h>\n"); + this#write_h ("#endif\n") + ) +end;; + +let read_whole_file chan = + Std.input_all chan;; + +(* The cached_source_writer will not write to the file if it has not changed, + thus allowing the makefile dependencies to work correctly *) +let cached_source_writer common_ctx filename = + let header = Buffer.create 0 in + let add_header str = Buffer.add_string header str in + let buffer = Buffer.create 0 in + let add_buf str = Buffer.add_string buffer str in + let close = fun() -> + Buffer.add_buffer header buffer; + let contents = Buffer.contents header in + let same = + try + let in_file = open_in filename in + let old_contents = read_whole_file in_file in + close_in in_file; + contents=old_contents + with _ -> + false + in + if not same then begin + let out_file = open_out filename in + output_string out_file contents; + close_out out_file; + end; + in + new source_writer common_ctx (add_header) (add_buf) (close) +;; + +let make_class_directories = Common.mkdir_recursive;; + +let make_base_directory dir = + make_class_directories "" ( ( Str.split_delim (Str.regexp "[\\/]+") dir ) );; + +let new_source_file common_ctx base_dir sub_dir extension class_path = + let include_prefix = get_include_prefix common_ctx true in + let full_dir = + if (sub_dir="include") && (include_prefix<>"") then begin + let dir = match fst class_path with + | [] -> base_dir ^ "/include/" ^ (get_include_prefix common_ctx false) + | path -> base_dir ^ "/include/" ^ include_prefix ^ ( String.concat "/" path ) + in + make_class_directories base_dir (["include";include_prefix]@(fst class_path)); + dir + end else begin + make_class_directories base_dir ( sub_dir :: (fst class_path)); + base_dir ^ "/" ^ sub_dir ^ "/" ^ ( String.concat "/" (fst class_path) ) + end + in + let file = cached_source_writer common_ctx (full_dir ^ "/" ^ ((snd class_path) ^ extension)) in + Codegen.map_source_header common_ctx (fun s -> file#write_h (Printf.sprintf "// %s\n" s)); + file + + + +let source_file_extension common_ctx = + (* no need to -D file_extension if -D objc is defined *) + if Common.defined common_ctx Define.Objc then + ".mm" + else try + "." ^ (Common.defined_value common_ctx Define.FileExtension) + with + Not_found -> ".cpp" +;; + + +let new_cpp_file common_ctx base_dir = new_source_file common_ctx base_dir "src" (source_file_extension common_ctx);; + +let new_header_file common_ctx base_dir = + new_source_file common_ctx base_dir "include" ".h";; + + + +(* CPP code generation context *) +(* + ctx_debug_level + 0 = no debug + 1 = function + line debug via macros, which can be activated at cpp compile-time + 2 = include macros for HXCPP_DEBUGGER + 3 = annotate source with additional info about AST and types + 4 = console output at haxe compile-time + + normal = 1 +*) +type context = +{ + ctx_common : Common.context; + + mutable ctx_debug_level : int; + (* cached as required *) + mutable ctx_file_info : (string,string) PMap.t ref; + + ctx_type_ids : (string,Int32.t) Hashtbl.t; + + (* Per file *) + ctx_output : string -> unit; + ctx_writer : source_writer; + ctx_file_id : int ref; + ctx_is_header : bool; + + ctx_interface_slot : (string,int) Hashtbl.t ref; + ctx_interface_slot_count : int ref; + (* This is for returning from the child nodes of TSwitch && TTry *) + mutable ctx_real_this_ptr : bool; + mutable ctx_class_member_types : (string,string) Hashtbl.t; +} + +let new_context common_ctx debug file_info member_types = +let null_file = new source_writer common_ctx ignore ignore (fun () -> () ) in +let has_def def = Common.defined_value_safe common_ctx def <>"" in +let result = +{ + ctx_common = common_ctx; + ctx_writer = null_file; + ctx_file_id = ref (-1); + ctx_type_ids = Hashtbl.create 0; + ctx_is_header = false; + ctx_output = (null_file#write); + ctx_interface_slot = ref (Hashtbl.create 0); + ctx_interface_slot_count = ref 2; + ctx_debug_level = if has_def Define.AnnotateSource then 3 else + if has_def Define.HxcppDebugger then 2 else + debug; + ctx_real_this_ptr = true; + ctx_class_member_types = member_types; + ctx_file_info = file_info; +} in +result + + +let file_context ctx writer debug header = + { ctx with + ctx_writer = writer; + ctx_output = (writer#write); + ctx_is_header = header; + ctx_file_id = ref (-1); + } +;; + + +(* The internal header files are also defined in the hx/Object.h file, so you do + #include them separately. However, Math classes has its + own header file (under the hxcpp tree) so these should be included *) +let include_class_header = function + | ([],"@Main") -> false + | ([],"Math") -> true + | path -> not ( is_internal_class path ) + + +let is_cpp_class = function + | ("cpp"::_ , _) -> true + | ( [] , "EReg" ) -> true + | ( ["haxe"] , "Log" ) -> true + | _ -> false;; + +let is_block exp = match exp.eexpr with | TBlock _ -> true | _ -> false ;; + +(* todo - is this how it's done? *) +let hash_keys hash = + let key_list = ref [] in + Hashtbl.iter (fun key value -> key_list := key :: !key_list ) hash; + !key_list;; + +let pmap_keys pmap = + let key_list = ref [] in + PMap.iter (fun key _ -> key_list := key :: !key_list ) pmap; + !key_list;; + +let pmap_values pmap = + let value_list = ref [] in + PMap.iter (fun _ value -> value_list := value :: !value_list ) pmap; + !value_list;; + + + +(* The Hashtbl structure seems a little odd - but here is a helper function *) +let hash_iterate hash visitor = + let result = ref [] in + Hashtbl.iter (fun key value -> result := (visitor key value) :: !result ) hash; + !result + + + + + +let is_internal_member member = + member = "toString" || ( + (String.length member > 1) && (String.sub member 0 2 = "__") && + (match member with + | "__ArgCount" | "__ArrayImplRef" | "__CStr" | "__Compare" | "__Create" + | "__CreateEmpty" | "__FieldRef" | "__FindArgCount" + | "__GetFieldMap" | "__GetHandle" | "__GetItem" + | "__GetScriptCallable" | "__GetScriptVTable" + | "__Param" | "__Remove" | "__SGetClass" + | "__Set" | "__SetItem" | "__TArrayImplRef" + | "__ToDouble" | "__ToInt" | "__ToInterface" | "__ToObject" + | "__Visit" | "__WCStr" | "__a" | "__blit" | "__boot" + | "__boot_all" | "__compare" | "__concat" | "__construct" | "__copy" + | "__filter" | "__get_args" | "__hx_dump_stack" | "__hx_field_iter" | "__hxt_gc_new" + | "__indexOf" | "__insert" | "__instanceof" | "__int" | "__iterator" + | "__join" | "__lastIndexOf" | "__loadprim" | "__mClass" | "__mDynamicFields" + | "__map" | "__memcmp" | "__new" | "__pop" | "__prime" + | "__push" | "__qsort" | "__unshift" | "__unsafeStringReference" | "__time_stamp" + | "__superString" | "__splice" | "__shift" | "__slice" | "__sort" + | "__s_id" | "__run" | "__root" | "__register" | "__remove" + | "__removeAt" | "__reverse" | "__zero" + | "__Field" | "__IField" | "__Run" | "__Is" | "__GetClass" | "__GetType" | "__ToString" + | "__s" | "__GetPtr" | "__SetField" | "__length" | "__IsArray" | "__SetThis" | "__Internal" + | "__EnumParams" | "__Index" | "__Tag" | "__GetFields" | "__HasField" + | "__get" | "__set" | "__unsafe_get" | "__unsafe_set" | "__global__" + | "__SetSize" | "__trace" | "__GetRealObject" | "__SetSizeExact" | "__cpp__" + | "__URLEncode" | "__URLDecode" | "__IsEnum" + -> true + | _ -> (String.length member > 4) && (String.sub member 0 4 = "__hx") ) );; + +let is_known_member member = + match member with + | "__meta__" | "__rtti" | "_Compare" + -> true + | _ -> false;; + +(* Convert function names that can't be written in c++ ... *) +let keyword_remap name = + if (is_internal_member name) || (is_known_member name) then + name + else if (String.length name > 1) && (String.sub name 0 2 = "__") then + "_hx_" ^ name + else match name with + | "int" | "Int" | "Bool" | "super" + | "auto" | "char" | "const" | "delete" | "double" | "Float" | "enum" + | "extern" | "float" | "friend" | "goto" | "long" | "operator" | "protected" + | "register" | "short" | "signed" | "sizeof" | "template" | "typedef" + | "union" | "unsigned" | "void" | "volatile" | "or" | "and" | "xor" | "or_eq" | "not" + | "and_eq" | "xor_eq" | "typeof" | "stdin" | "stdout" | "stderr" | "system" + | "BIG_ENDIAN" | "LITTLE_ENDIAN" | "assert" | "NULL" | "wchar_t" | "EOF" + | "bool" | "const_cast" | "dynamic_cast" | "explicit" | "export" | "mutable" | "namespace" + | "reinterpret_cast" | "static_cast" | "typeid" | "typename" | "virtual" + | "_Complex" | "INFINITY" | "NAN" + | "INT_MIN" | "INT_MAX" | "INT8_MIN" | "INT8_MAX" | "UINT8_MAX" | "INT16_MIN" + | "INT16_MAX" | "UINT16_MAX" | "INT32_MIN" | "INT32_MAX" | "UINT32_MAX" + | "asm" | "near" | "far" + | "HX_" | "HXLINE" | "HXDLIN" + | "NO" | "YES" + | "abstract" | "decltype" | "finally" | "nullptr" | "static_assert" + | "struct" -> "_hx_" ^ name + | x -> x +;; + +let remap_class_path class_path = + let path_remap with_keywords name = + let len = String.length name in + if (len > 3) && (String.sub name 0 3 = " ::") then + String.sub name 3 (len-3) + else if (len > 2) && (String.sub name 0 2 = "::") then + String.sub name 2 (len-2) + else if with_keywords then + keyword_remap name + else + name + in + (List.map (path_remap true) (fst class_path)) , path_remap false (snd class_path) +;; + +let join_class_path_remap path separator = + match join_class_path (remap_class_path path) separator with + | "Class" -> "hx::Class" + | x -> x +;; + +let get_meta_string meta key = + let rec loop = function + | [] -> "" + | (k,[Ast.EConst (Ast.String name),_],_) :: _ when k=key-> name + | _ :: l -> loop l + in + loop meta +;; + + + +let get_meta_string_path meta key = + let rec loop = function + | [] -> "" + | (k,[Ast.EConst (Ast.String name),_], pos) :: _ when k=key-> + (try + if (String.sub name 0 2) = "./" then begin + let base = if (Filename.is_relative pos.pfile) then + Filename.concat (Sys.getcwd()) pos.pfile + else + pos.pfile + in + Path.normalize_path (Filename.concat (Filename.dirname base) (String.sub name 2 ((String.length name) -2) )) + end else + name + with Invalid_argument _ -> name) + | _ :: l -> loop l + in + loop meta +;; + + +let get_meta_string_full_filename meta key = + let rec loop = function + | [] -> "" + | (k,_, pos) :: _ when k=key-> + if (Filename.is_relative pos.pfile) then + Path.normalize_path (Filename.concat (Sys.getcwd()) pos.pfile) + else + pos.pfile + | _ :: l -> loop l + in + loop meta +;; + +let get_meta_string_full_dirname meta key = + let name = get_meta_string_full_filename meta key in + try + Path.normalize_path (Filename.dirname name) + with Invalid_argument _ -> "" +;; + + +let get_field_access_meta field_access key = +match field_access with + | FInstance(_,_,class_field) + | FStatic(_,class_field) -> get_meta_string class_field.cf_meta key + | _ -> "" +;; + +let format_code code = + String.concat "\n" (ExtString.String.nsplit code "\r\n") + +let get_code meta key = + let code = get_meta_string meta key in + let magic_var = "${GENCPP_SOURCE_DIRECTORY}" in + let code = if ExtString.String.exists code magic_var then begin + let source_directory = get_meta_string_full_dirname meta key in + let _,code = ExtString.String.replace code magic_var source_directory in + code + end else + code + in + if (code<>"") then format_code code ^ "\n" else code +;; + +let has_meta_key meta key = + List.exists (fun m -> match m with | (k,_,_) when k=key-> true | _ -> false ) meta +;; + +let type_has_meta_key haxe_type key = + match follow haxe_type with + | TInst (klass,_) -> has_meta_key klass.cl_meta key + | TType (type_def,_) -> has_meta_key type_def.t_meta key + | TEnum (enum_def,_) -> has_meta_key enum_def.e_meta key + | _ -> false +;; + + +(* +let dump_meta meta = + List.iter (fun m -> match m with | (k,_,_) -> print_endline ((fst (Meta.to_string k)) ^ "=" ^ (get_meta_string meta k) ) | _ -> () ) meta;; +*) + +let get_class_code class_def key = match class_def.cl_kind with + | KAbstractImpl abstract_def -> + let value = (get_code abstract_def.a_meta key) in + value + | _ -> get_code class_def.cl_meta key +;; + + +(* Add include to source code *) +let add_include writer class_path = + writer#add_include class_path;; + +let list_num l = string_of_int (List.length l);; + + +(* This gets the class include order correct. In the header files, we forward declare + the class types so the header file does not have any undefined variables. + In the cpp files, we include all the required header files, providing the actual + types for everything. This way there is no problem with circular class references. +*) +let gen_forward_decl writer class_path isNative = + begin + let output = writer#write in + match class_path with + | (["@verbatim"],file) -> + writer#write (guarded_include file) + | _ -> + let name = fst (remap_class_path class_path) in + output ((if isNative then "HX_DECLARE_NATIVE" else "HX_DECLARE_CLASS") ^ list_num name ^ "("); + List.iter (fun package_part -> output (package_part ^ ",") ) name; + output ( (snd class_path) ^ ")\n") +end;; + +let real_interfaces = +List.filter (function (t,pl) -> + match t, pl with + | { cl_path = ["cpp";"rtti"],_ },[] -> false + | _ -> true +);; + + +let is_var_field field = + match field.cf_kind with + | Var _ -> true + | Method MethDynamic -> true + | _ -> false +;; + +let rec has_rtti_interface c interface = + List.exists (function (t,pl) -> + (snd t.cl_path) = interface && (match fst t.cl_path with | ["cpp";"rtti"] -> true | _ -> false ) + ) c.cl_implements || + (match c.cl_super with None -> false | Some (c,_) -> has_rtti_interface c interface);; + +let has_field_integer_lookup class_def = + has_rtti_interface class_def "FieldIntegerLookup";; + +let has_field_integer_numeric_lookup class_def = + has_rtti_interface class_def "FieldNumericIntegerLookup";; + +(* Output required code to place contents in required namespace *) +let gen_open_namespace output class_path = + List.iter (fun namespace -> output ("namespace " ^ namespace ^ "{\n")) (List.map keyword_remap (fst class_path));; + +let gen_close_namespace output class_path = + List.iter + (fun namespace -> output ( "}" ^ " // end namespace " ^ namespace ^"\n")) + (fst class_path);; + +(* The basic types can have default values and are passesby value *) +let is_numeric = function + | "Int" | "Bool" | "Float" | "unsigned char" -> true + | "::cpp::UInt8" | "::cpp::Int8" | "::cpp::Char" + | "::cpp::UInt16" | "::cpp::Int16" + | "::cpp::UInt32" | "::cpp::Int32" + | "::cpp::UInt64" | "::cpp::Int64" + | "::cpp::Float32" | "::cpp::Float64" + | "int" | "bool" | "double" | "float" -> true + | _ -> false + + +let rec remove_parens expression = + match expression.eexpr with + | TParenthesis e -> remove_parens e + | TMeta(_,e) -> remove_parens e + | _ -> expression +;; + + +let rec remove_parens_cast expression = + match expression.eexpr with + | TParenthesis e -> remove_parens_cast e + | TMeta(_,e) -> remove_parens_cast e + | TCast ( e,None) -> remove_parens_cast e + | _ -> expression +;; + +let is_interface_type t = + match follow t with + | TInst (klass,params) -> klass.cl_interface + | _ -> false +;; + + +let is_cpp_function_instance haxe_type = + match follow haxe_type with + | TInst (klass,params) -> + (match klass.cl_path with + | ["cpp"] , "Function" -> true + | _ -> false ) + | _ -> false + ;; + + +let is_objc_class klass = + klass.cl_extern && Meta.has Meta.Objc klass.cl_meta +;; + +let rec is_objc_type t = + match t with + | TInst(cl,_) -> cl.cl_extern && Meta.has Meta.Objc cl.cl_meta + | TType(td,_) -> (Meta.has Meta.Objc td.t_meta) + | TAbstract (a,_) -> (Meta.has Meta.Objc a.a_meta) + | TMono r -> (match !r with | Some t -> is_objc_type t | _ -> false) + | TLazy f -> is_objc_type (!f()) + | _ -> false +;; + + +let is_lvalue var = + match (remove_parens var).eexpr with + | TLocal _ -> true + | TField (_,FStatic(_,field) ) | TField (_,FInstance(_,_,field) ) -> is_var_field field + | _ -> false +;; + + + +let is_pointer haxe_type includeRaw = + match follow haxe_type with + | TInst (klass,params) -> + (match klass.cl_path with + | ["cpp"] , "Pointer" + | ["cpp"] , "ConstPointer" + | ["cpp"] , "Function" -> true + | ["cpp"] , "RawPointer" when includeRaw -> true + | ["cpp"] , "RawConstPointer" when includeRaw -> true + | _ -> false ) + | TType (type_def,params) -> + (match type_def.t_path with + | ["cpp"] , "Pointer" + | ["cpp"] , "ConstPointer" + | ["cpp"] , "Function" -> true + | ["cpp"] , "RawPointer" when includeRaw -> true + | ["cpp"] , "RawConstPointer" when includeRaw -> true + | _ -> false ) + | _ -> false + ;; + +let is_dynamic_type_param class_kind = + match class_kind with + | KTypeParameter _ -> true + | _ -> false +;; + + +let is_native_gen_class class_def = + (has_meta_key class_def.cl_meta Meta.NativeGen) || + (match class_def.cl_kind with + | KAbstractImpl abstract_def -> (has_meta_key abstract_def.a_meta Meta.NativeGen) + | _ -> false ); +;; + +let is_native_gen_module = function + | TClassDecl class_def -> is_native_gen_class class_def + | _ -> false +;; + + + +(* Get a string to represent a type. + The "suffix" will be nothing or "_obj", depending if we want the name of the + pointer class or the pointee (_obj class *) +let rec class_string klass suffix params remap = + let type_string = type_string_remap remap in + let join_class_path_remap = if remap then join_class_path_remap else join_class_path in + (match klass.cl_path with + (* Array class *) + | ([],"Array") when is_dynamic_array_param (List.hd params) -> + "cpp::ArrayBase" ^ suffix + (*"cpp::VirtualArray" ^ suffix*) + | ([],"Array") -> (snd klass.cl_path) ^ suffix ^ "< " ^ (String.concat "," + (List.map array_element_type params) ) ^ " >" + (* FastIterator class *) + | (["cpp"],"FastIterator") -> "::cpp::FastIterator" ^ suffix ^ "< " ^ (String.concat "," + (List.map type_string params) ) ^ " >" + | (["cpp"],"Pointer") + | (["cpp"],"ConstPointer") -> + "::cpp::Pointer< " ^ (String.concat "," (List.map type_string params) ) ^ " >" + | (["cpp"],"RawPointer") -> + " " ^ (String.concat "," (List.map type_string params) ) ^ " * " + | (["cpp"],"RawConstPointer") -> + " const " ^ (String.concat "," (List.map type_string params) ) ^ " * " + | (["cpp"],"Function") -> + "::cpp::Function< " ^ (cpp_function_signature_params params) ^ " >" + | _ when is_dynamic_type_param klass.cl_kind -> "Dynamic" + | ([],"#Int") -> "/* # */int" + | (["cpp"],"UInt8") -> "unsigned char" + | ([],"Class") -> "hx::Class" + | ([],"EnumValue") -> "Dynamic" + | ([],"Null") -> (match params with + | [t] -> + (match follow t with + | TAbstract ({ a_path = [],"Int" },_) + | TAbstract ({ a_path = [],"Float" },_) + | TAbstract ({ a_path = [],"Bool" },_) -> "Dynamic" + | TAbstract ({ a_path = ["cpp"],"UInt8" },_) -> "Dynamic" + | t when type_has_meta_key t Meta.NotNull -> "Dynamic" + | _ -> "/*NULL*/" ^ (type_string t) ) + | _ -> assert false); + (* Objective-C class *) + | path when is_objc_type (TInst(klass,[])) -> + let str = join_class_path_remap klass.cl_path "::" in + if suffix = "_obj" then + str + else if klass.cl_interface then + "id < " ^ str ^ ">" + else + str ^ " *" + (* Native interface - use pointer *) + | _ when klass.cl_interface && is_native_gen_class klass -> + (join_class_path_remap klass.cl_path "::") ^ " *" + (* Normal class *) + | path when klass.cl_extern && (not (is_internal_class path) )-> + (join_class_path_remap klass.cl_path "::") ^ suffix + | _ -> "::" ^ (join_class_path_remap klass.cl_path "::") ^ suffix + ) +and type_string_suff suffix haxe_type remap = + let type_string = type_string_remap remap in + let join_class_path_remap = if remap then join_class_path_remap else join_class_path in + (match haxe_type with + | TMono r -> (match !r with None -> "Dynamic" ^ suffix | Some t -> type_string_suff suffix t remap) + | TAbstract ({ a_path = ([],"Void") },[]) -> "Void" + | TAbstract ({ a_path = ([],"Bool") },[]) -> "bool" + | TAbstract ({ a_path = ([],"Float") },[]) -> "Float" + | TAbstract ({ a_path = ([],"Int") },[]) -> "int" + | TAbstract ({ a_path = (["cpp"],"UInt8") },[]) -> "unsigned char" + | TAbstract( { a_path = ([], "EnumValue") }, _ ) -> "Dynamic" + | TEnum (enum,params) -> "::" ^ (join_class_path_remap enum.e_path "::") ^ suffix + | TInst (klass,params) -> (class_string klass suffix params remap) + | TType (type_def,params) -> + (match type_def.t_path with + | [] , "Null" -> + (match params with + | [t] -> + (match follow t with + | TAbstract ({ a_path = [],"Int" },_) + | TAbstract ({ a_path = [],"Float" },_) + | TAbstract ({ a_path = [],"Bool" },_) -> "Dynamic" ^ suffix + | t when type_has_meta_key t Meta.NotNull -> "Dynamic" ^ suffix + | _ -> type_string_suff suffix t remap) + | _ -> assert false); + | [] , "Array" -> + (match params with + | [t] when (type_string (follow t) ) = "Dynamic" -> "Dynamic" + | [t] -> "Array< " ^ (type_string (follow t) ) ^ " >" + | _ -> assert false) + | ["cpp"] , "FastIterator" -> + (match params with + | [t] -> "::cpp::FastIterator< " ^ (type_string (follow t) ) ^ " >" + | _ -> assert false) + | ["cpp"] , "Pointer" + | ["cpp"] , "ConstPointer" -> + (match params with + | [t] -> "::cpp::Pointer< " ^ (type_string (follow t) ) ^ " >" + | _ -> assert false) + | ["cpp"] , "RawPointer" -> + (match params with + | [t] -> " " ^ (type_string (follow t) ) ^ " *" + | _ -> assert false) + | ["cpp"] , "RawConstPointer" -> + (match params with + | [t] -> "const " ^ (type_string (follow t) ) ^ " *" + | _ -> assert false) + | ["cpp"] , "Function" -> + "::cpp::Function< " ^ (cpp_function_signature_params params ) ^ " >" + | _ -> type_string_suff suffix (apply_params type_def.t_params params type_def.t_type) remap + ) + | TFun (args,haxe_type) -> "Dynamic" ^ suffix + | TAnon a -> "Dynamic" + (* + (match !(a.a_status) with + | Statics c -> type_string_suff suffix (TInst (c,List.map snd c.cl_params)) + | EnumStatics e -> type_string_suff suffix (TEnum (e,List.map snd e.e_params)) + | _ -> "Dynamic" ^ suffix ) + *) + | TDynamic haxe_type -> "Dynamic" ^ suffix + | TLazy func -> type_string_suff suffix ((!func)()) remap + | TAbstract (abs,pl) when abs.a_impl <> None -> + type_string_suff suffix (Abstract.get_underlying_type abs pl) remap + | TAbstract (abs,pl) -> + "::" ^ (join_class_path_remap abs.a_path "::") ^ suffix + ) + +and type_string_remap remap haxe_type = + type_string_suff "" haxe_type remap + +and type_string haxe_type = + type_string_suff "" haxe_type true + +and array_element_type haxe_type = + match type_string haxe_type with + | x when cant_be_null haxe_type -> x + | x when is_interface_type (follow haxe_type) -> x + | "::String" -> "::String" + | _ -> "::Dynamic" + +and is_dynamic_array_param haxe_type = + if (type_string (follow haxe_type)) = "Dynamic" then true + else (match follow haxe_type with + | TInst (klass,params) -> + (match klass.cl_path with + | ([],"Array") | ([],"Class") | (["cpp"],"FastIterator") + | (["cpp"],"RawPointer") |(["cpp"],"ConstRawPointer") + | (["cpp"],"Pointer") |(["cpp"],"ConstPointer")|(["cpp"],"Function") -> false + | _ -> (match klass.cl_kind with KTypeParameter _ -> true | _ -> false) + ) + | _ -> false + ) +and cpp_function_signature tfun abi = + match follow tfun with + | TFun(args,ret) -> (type_string ret) ^ " " ^ abi ^ "(" ^ (gen_tfun_interface_arg_list args) ^ ")" + | _ -> "void *" + +and cpp_function_signature_params params = match params with + | [t; abi] -> (match follow abi with + | TInst (klass,_) -> cpp_function_signature t (get_meta_string klass.cl_meta Meta.Abi) + | _ -> print_endline (type_string abi); + assert false ) + | _ -> + print_endline ("Params:" ^ (String.concat "," (List.map type_string params) )); + assert false; + +and gen_interface_arg_type_name name opt typ = + let type_str = (type_string typ) in + (* type_str may have already converted Null to Dynamic because of NotNull tag ... *) + (if (opt && (cant_be_null typ) && type_str<>"Dynamic" ) then + "hx::Null< " ^ type_str ^ " > " + else + type_str ) ^ " " ^ (keyword_remap name) + +and gen_tfun_interface_arg_list args = + String.concat "," (List.map (fun (name,opt,typ) -> gen_interface_arg_type_name name opt typ) args) +and cant_be_null haxe_type = + is_numeric (type_string haxe_type) || (type_has_meta_key haxe_type Meta.NotNull ) +;; + + + +let is_array haxe_type = + match follow haxe_type with + | TInst (klass,params) -> + (match klass.cl_path with + | [] , "Array" -> not (is_dynamic_array_param (List.hd params)) + | _ -> false ) + | TType (type_def,params) -> + (match type_def.t_path with + | [] , "Array" -> not (is_dynamic_array_param (List.hd params)) + | _ -> false ) + | _ -> false + ;; + +let is_array_or_dyn_array haxe_type = + match follow haxe_type with + | TInst (klass,params) -> + (match klass.cl_path with | [] , "Array" -> true | _ -> false ) + | TType (type_def,params) -> + (match type_def.t_path with | [] , "Array" -> true | _ -> false ) + | _ -> false + ;; + + + +let is_array_implementer haxe_type = + match follow haxe_type with + | TInst (klass,params) -> + (match klass.cl_array_access with + | Some _ -> true + | _ -> false ) + | _ -> false + ;; + + + +let is_static_access obj = + match (remove_parens obj).eexpr with + | TTypeExpr _ -> true + | _ -> false +;; + +let is_native_with_space func = + match (remove_parens func).eexpr with + | TField(obj,field) when is_static_access obj -> + String.contains (get_field_access_meta field Meta.Native) ' ' + | _ -> false +;; + + +let is_native_pointer expr = + let t = type_string expr.etype in + let l = String.length t in + l>1 && (String.sub t (l-1) 1) = "*" +;; + + +let rec is_cpp_function_member func = + match (remove_parens func).eexpr with + | TField(obj,field) when is_cpp_function_instance obj.etype -> true + | TCall(obj,_) -> is_cpp_function_member obj + | _ -> false +;; + + + + +(* Get the type and output it to the stream *) +(* +let gen_type ctx haxe_type = + ctx.ctx_output (type_string haxe_type) +;; + +let member_type ctx field_object member = + let name = (if (is_array field_object.etype) then "::Array" + else (type_string field_object.etype)) ^ "." ^ member in + try ( Hashtbl.find ctx.ctx_class_member_types name ) + with Not_found -> "?";; + +*) +let is_interface obj = is_interface_type obj.etype;; + +let should_implement_field x = not (is_extern_field x);; + +let is_extern_class class_def = + class_def.cl_extern || (has_meta_key class_def.cl_meta Meta.Extern) || + (match class_def.cl_kind with + | KAbstractImpl abstract_def -> (has_meta_key abstract_def.a_meta Meta.Extern) + | _ -> false ); +;; + +let is_scalar_abstract abstract_def = + Meta.has Meta.Scalar abstract_def.a_meta && Meta.has Meta.CoreType abstract_def.a_meta +;; + + +let real_non_native_interfaces = +List.filter (function (t,pl) -> + match t, pl with + | { cl_path = ["cpp";"rtti"],_ },[] -> false + | _ -> not (is_native_gen_class t) +);; + + + +let is_extern_class_instance obj = + match follow obj.etype with + | TInst (klass,params) -> klass.cl_extern + | _ -> false +;; + + +let rec is_dynamic_accessor name acc field class_def = + ( ( acc ^ "_" ^ field.cf_name) = name ) && + ( not (List.exists (fun f -> f.cf_name=name) class_def.cl_ordered_fields) ) + && (match class_def.cl_super with None -> true | Some (parent,_) -> is_dynamic_accessor name acc field parent ) +;; + + +(* Check to see if we are the first object in the parent tree to implement a dynamic interface *) +let implement_dynamic_here class_def = + let implements_dynamic c = match c.cl_dynamic with None -> false | _ -> true in + let rec super_implements_dynamic c = match c.cl_super with + | None -> false + | Some (csup, _) -> if (implements_dynamic csup) then true else + super_implements_dynamic csup; + in + ( (implements_dynamic class_def) && (not (super_implements_dynamic class_def) ) );; + + +let gen_hash32 seed str = + let h = ref (Int32.of_int seed) in + let cycle = Int32.of_int 223 in + for i = 0 to String.length str - 1 do + h := Int32.add (Int32.mul !h cycle) (Int32.of_int (int_of_char (String.unsafe_get str i))); + done; + !h +;; + +let gen_hash seed str = + Printf.sprintf "0x%08lx" (gen_hash32 seed str) +;; + +let gen_hash_small seed str = + Printf.sprintf "%08lx" (gen_hash32 seed str) +;; + +let gen_string_hash str = + let h = gen_hash32 0 str in + Printf.sprintf "\"\\x%02lx\",\"\\x%02lx\",\"\\x%02lx\",\"\\x%02lx\"" + (Int32.shift_right_logical (Int32.shift_left h 24) 24) + (Int32.shift_right_logical (Int32.shift_left h 16) 24) + (Int32.shift_right_logical (Int32.shift_left h 8) 24) + (Int32.shift_right_logical h 24) +;; + +let gen_qstring_hash str = + let h = gen_hash32 0 str in + Printf.sprintf "%02lx,%02lx,%02lx,%02lx" + (Int32.shift_right_logical (Int32.shift_left h 24) 24) + (Int32.shift_right_logical (Int32.shift_left h 16) 24) + (Int32.shift_right_logical (Int32.shift_left h 8) 24) + (Int32.shift_right_logical h 24) +;; + + + + + +(* Make string printable for c++ code *) +(* Here we know there are no utf8 characters, so use the L"" notation to avoid conversion *) +let escape_stringw s l = + let b = Buffer.create 0 in + Buffer.add_char b 'L'; + Buffer.add_char b '"'; + let skip = ref 0 in + for i = 0 to String.length s - 1 do + if (!skip>0) then begin + skip := !skip -1; + l := !l-1; + end else + match Char.code (String.unsafe_get s i) with + | c when (c>127) -> + let encoded = ((c land 0x3F) lsl 6) lor ( Char.code ((String.unsafe_get s (i+1))) land 0x7F) in + skip := 1; + Buffer.add_string b (Printf.sprintf "\\x%X\"L\"" encoded) + | c when (c < 32) -> Buffer.add_string b (Printf.sprintf "\\x%X\"L\"" c) + | c -> Buffer.add_char b (Char.chr c) + done; + Buffer.add_char b '"'; + Buffer.contents b;; + +let special_to_hex s = + let l = String.length s in + let b = Buffer.create 0 in + for i = 0 to l - 1 do + match Char.code (String.unsafe_get s i) with + | c when (c>127) || (c<32) -> + Buffer.add_string b (Printf.sprintf "\\x%02x\"\"" c) + | c -> Buffer.add_char b (Char.chr c) + done; + Buffer.contents b;; + +let escape_extern s = + let l = String.length s in + let b = Buffer.create 0 in + for i = 0 to l - 1 do + match Char.code (String.unsafe_get s i) with + | c when (c>127) || (c<32) || (c=34) || (c=92) -> + Buffer.add_string b (Printf.sprintf "\\x%02x" c) + | c -> Buffer.add_char b (Char.chr c) + done; + Buffer.contents b;; + + + +let has_utf8_chars s = + let result = ref false in + for i = 0 to String.length s - 1 do + result := !result || ( Char.code (String.unsafe_get s i) > 127 ) + done; + !result;; + +let escape_command s = + let b = Buffer.create 0 in + String.iter (fun ch -> if (ch=='"' || ch=='\\' ) then Buffer.add_string b "\\"; Buffer.add_char b ch ) s; + Buffer.contents b;; + +let gen_str macro gen s = + let rec split s plus = + let escaped = Ast.s_escape ~hex:false s in + let hexed = (special_to_hex escaped) in + if (String.length hexed <= 16000 ) then + plus ^ " HX_CSTRING(\"" ^ hexed ^ "\")" + else begin + let len = String.length s in + let half = len lsr 1 in + (split (String.sub s 0 half) plus ) ^ (split (String.sub s half (len-half)) "+" ) + end + in + let escaped = Ast.s_escape ~hex:false s in + let hexed = (special_to_hex escaped) in + if (String.length hexed <= 16000 ) then + macro ^ "(\"" ^ hexed ^ "\"," ^ (gen s) ^ ")" + else + "(" ^ (split s "" ) ^ ")" +;; + +let str s = gen_str "HX_HCSTRING" gen_string_hash s;; +let strq s = gen_str "HX_" gen_qstring_hash s;; + + + +let const_char_star s = + let escaped = Ast.s_escape ~hex:false s in + "\"" ^ special_to_hex escaped ^ "\""; +;; + + + + +(* Convert an array to a comma separated list of values *) +let array_arg_list inList = + let i = ref (0-1) in + String.concat "," (List.map (fun _ -> incr i; "inArgs[" ^ (string_of_int !i) ^ "]" ) inList) + + +(* See if there is a haxe break statement that will be swollowed by c++ break *) +exception BreakFound;; + +(* Decide is we should look the field up by name *) +let dynamic_internal = function | "__Is" -> true | _ -> false + + +let rec is_null expr = + match expr.eexpr with + | TConst TNull -> true + | TParenthesis expr | TMeta (_,expr) -> is_null expr + | TCast (e,None) -> is_null e + | _ -> false +;; + + +let is_virtual_array expr = (type_string expr.etype="cpp::VirtualArray") ;; + +let is_real_function field = + match field.cf_kind with + | Method MethNormal | Method MethInline-> true + | _ -> false +;; + + +let is_this expression = + match (remove_parens expression).eexpr with + | TConst TThis -> true + | _ -> false +;; + +let is_super expression = + match (remove_parens expression).eexpr with + | TConst TSuper -> true + | _ -> false +;; + + +let rec is_dynamic_in_cpp ctx expr = + let expr_type = type_string ( match follow expr.etype with TFun (args,ret) -> ret | _ -> expr.etype) in + if ( expr_type="Dynamic" || expr_type="cpp::ArrayBase") then + true + else begin + let result = ( + match expr.eexpr with + | TEnumParameter( obj, _, index ) -> true (* TODO? *) + | TField( obj, field ) -> + (is_dynamic_member_lookup_in_cpp ctx obj field) || + (is_dynamic_member_return_in_cpp ctx obj field) + | TArray (obj,index) -> (is_dynamic_in_cpp ctx obj || is_virtual_array obj) + | TTypeExpr _ -> false + | TCall(func,args) -> + let is_IaCall = + (match (remove_parens_cast func).eexpr with + | TField ( { eexpr = TLocal { v_name = "__global__" }}, field ) -> false + | TField (obj,FStatic (class_def,field) ) when is_real_function field -> false + | TField (obj,FInstance (_,_,field) ) when (is_this obj) && (is_real_function field) -> false + | TField (obj,FInstance (_,_,field) ) when is_super obj -> false + | TField (obj,FInstance (_,_,field) ) when field.cf_name = "_hx_getIndex" -> false + | TField (obj,FInstance (_,_,field) ) when field.cf_name = "__Index" || (not (is_dynamic_in_cppia ctx obj) && is_real_function field) -> false + | TField (obj,FDynamic (name) ) when (is_internal_member name || (type_string obj.etype = "::String" && name="cca") ) -> false + | TConst TSuper -> false + | TField (_,FEnum (enum,field)) -> false + | _ -> true + ) in + if is_IaCall then + true + else + (match follow func.etype with + | TFun (args,ret) -> is_dynamic_in_cpp ctx func + | _ -> true + ); + | TParenthesis(expr) | TMeta(_,expr) -> is_dynamic_in_cpp ctx expr + | TCast (e,None) -> (type_string expr.etype) = "Dynamic" + | TLocal { v_name = "__global__" } -> false + | TConst TNull -> true + | _ -> false (* others ? *) ) + in + result + end + +and is_dynamic_member_lookup_in_cpp ctx field_object field = + let member = field_name field in + if (is_internal_member member) then false else + if (is_native_pointer field_object) then false else + if (is_pointer field_object.etype true) then false else + if (match field_object.eexpr with | TTypeExpr _ -> true | _ -> false) then false else + if (is_dynamic_in_cpp ctx field_object) then true else + if (is_array field_object.etype) then false else ( + let tstr = type_string field_object.etype in + match tstr with + (* Internal classes have no dynamic members *) + | "::String" | "Null" | "::hx::Class" | "::Enum" | "::Math" | "::ArrayAccess" -> false + | "Dynamic" -> true + | name -> + let full_name = name ^ "." ^ member in + if Hashtbl.mem ctx.ctx_class_member_types full_name then + false + else + not (is_extern_class_instance field_object) + ) +and is_dynamic_member_return_in_cpp ctx field_object field = + let member = field_name field in + if (is_array field_object.etype) then false else + if (is_pointer field_object.etype true) then false else + if (is_internal_member member) then false else + match field_object.eexpr with + | TTypeExpr t -> + let full_name = "::" ^ (join_class_path_remap (t_path t) "::" ) ^ "." ^ member in + ( try ( let mem_type = (Hashtbl.find ctx.ctx_class_member_types full_name) in + mem_type="Dynamic" || mem_type="cpp::ArrayBase" || mem_type="cpp::VirtualArray" ) + with Not_found -> true ) + | _ -> + let tstr = type_string field_object.etype in + (match tstr with + (* Internal classes have no dynamic members *) + | "::String" | "Null" | "::hx::Class" | "::Enum" | "::Math" | "::ArrayAccess" -> false + | "Dynamic" | "cpp::ArrayBase" | "cpp::VirtualArray" -> true + | name -> + let full_name = name ^ "." ^ member in + try ( let mem_type = (Hashtbl.find ctx.ctx_class_member_types full_name) in + mem_type="Dynamic" || mem_type="cpp::ArrayBase" || mem_type="cpp::VirtualArray" ) + with Not_found -> true ) +and is_dynamic_in_cppia ctx expr = + match expr.eexpr with + | TCast(_,None) -> true + | _ -> is_dynamic_in_cpp ctx expr +;; + +let cast_if_required ctx expr to_type = + if (is_dynamic_in_cpp ctx expr) then + ctx.ctx_output (".Cast< " ^ to_type ^ " >()" ) +;; + + +let is_matching_interface_type t0 t1 = + (match (follow t0),(follow t1) with + | TInst (k0,_), TInst(k1,_) -> k0==k1 + | _ -> false + ) +;; + + + +let default_value_string = function + | TInt i -> Printf.sprintf "%ld" i + | TFloat float_as_string -> "((Float)" ^ float_as_string ^ ")" + | TString s -> str s + | TBool b -> (if b then "true" else "false") + | TNull -> "null()" + | _ -> "/* Hmmm */" +;; + + + +let get_return_type field = + match follow field.cf_type with + | TFun (_,return_type) -> return_type + | _ -> raise Not_found +;; + + +let get_nth_type field index = + match follow field.ef_type with + | TFun (args,_) -> + let rec nth l index = match l with + | [] -> raise Not_found + | (_,_,t)::rest -> + if index = 0 then t + else nth rest (index-1) + in + nth args index + | _ -> raise Not_found +;; + + + +let has_default_values args = + List.exists ( fun (_,o) -> match o with + | Some TNull -> false + | Some _ -> true + | _ -> false ) args ;; + +exception PathFound of string;; + + +let strip_file ctx file = (match Common.defined ctx Common.Define.AbsolutePath with + | true -> file + | false -> let flen = String.length file in + (* Not quite right - should probably test is file exists *) + try + List.iter (fun path -> + let plen = String.length path in + if (flen>plen && path=(String.sub file 0 plen )) + then raise (PathFound (String.sub file plen (flen-plen)) ) ) + (ctx.class_path @ ctx.std_path); + file; + with PathFound tail -> + tail) +;; + +let hx_stack_push ctx output clazz func_name pos gc_stack = + if ctx.ctx_debug_level > 0 then begin + let stripped_file = strip_file ctx.ctx_common pos.pfile in + let esc_file = (Ast.s_escape stripped_file) in + ctx.ctx_file_info := PMap.add stripped_file pos.pfile !(ctx.ctx_file_info); + let full_name = clazz ^ "." ^ func_name ^ ( + if (clazz="*") then + (" (" ^ esc_file ^ ":" ^ (string_of_int (Lexer.get_error_line pos) ) ^ ")") + else "") in + + let hash_class_func = gen_hash 0 (clazz^"."^func_name) in + let hash_file = gen_hash 0 stripped_file in + + let lineName = (string_of_int (Lexer.get_error_line pos) ) in + incr ctx.ctx_file_id; + let classId = hash64 (clazz ^ "." ^ stripped_file) in + let varName = "_hx_pos_" ^ classId ^ "_" ^ lineName ^ "_" ^func_name in + let decl = ( varName ^ ",\"" ^ clazz ^ "\",\"" ^ func_name ^ "\"," ^ hash_class_func ^ ",\"" ^ + full_name ^ "\",\"" ^ esc_file ^ "\"," ^ lineName ^ "," ^ hash_file ) in + if ctx.ctx_is_header then + ctx.ctx_writer#write_h_unique ("HX_DECLARE_STACK_FRAME" ^ "(" ^ varName ^ ")\n") + else + ctx.ctx_writer#write_h_unique ( (if func_name="new" then "HX_DEFINE_STACK_FRAME" else "HX_LOCAL_STACK_FRAME") ^ "(" ^ decl ^ ")\n"); + output ( (if gc_stack then "HX_GC_STACKFRAME" else "HX_STACKFRAME") ^ "(&" ^ varName ^ ")\n"); + end else if gc_stack then + output ("HX_JUST_GC_STACKFRAME\n") +;; + + + +(* { *) + +type tcpp = + | TCppDynamic + | TCppUnchanged + | TCppObject + | TCppObjectPtr + | TCppVoid + | TCppNull + | TCppEnum of tenum + | TCppScalar of string + | TCppString + | TCppFastIterator of tcpp + | TCppPointer of string * tcpp + | TCppRawPointer of string * tcpp + | TCppFunction of tcpp list * tcpp * string + | TCppObjCBlock of tcpp list * tcpp + | TCppRest of tcpp + | TCppReference of tcpp + | TCppStar of tcpp + | TCppVoidStar + | TCppVarArg + | TCppAutoCast + | TCppDynamicArray + | TCppObjectArray of tcpp + | TCppWrapped of tcpp + | TCppScalarArray of tcpp + | TCppObjC of tclass + | TCppNativePointer of tclass + | TCppVariant + | TCppCode of tcpp + | TCppInst of tclass + | TCppInterface of tclass + | TCppProtocol of tclass + | TCppClass + | TCppGlobal + + +and tcppexpr = { + cppexpr : tcpp_expr_expr; + cpptype : tcpp; + cpppos : pos; +} + + +and tcpp_closure = { + close_type : tcpp; + close_args : (tvar * tconstant option) list; + close_expr : tcppexpr; + close_id : int; + close_undeclared : (string,tvar) Hashtbl.t; + close_this : tcppthis option; +} + + +and tcppcrementop = + | CppIncrement + | CppDecrement + +and tcppunop = + | CppNeg + | CppNegBits + | CppNot + +and tcppthis = + | ThisReal + | ThisFake + | ThisDynamic + +and tcppvarloc = + | VarLocal of tvar + | VarClosure of tvar + | VarThis of tclass_field + | VarInstance of tcppexpr * tclass_field * string * string + | VarInterface of tcppexpr * tclass_field + | VarStatic of tclass * bool * tclass_field + | VarInternal of tcppexpr * string * string + +and tcppinst = + | InstPtr + | InstObjC + | InstStruct + +and tcppfuncloc = + | FuncThis of tclass_field + | FuncInstance of tcppexpr * tcppinst * tclass_field + | FuncStatic of tclass * bool * tclass_field + | FuncTemplate of tclass * tclass_field * path * bool + | FuncInterface of tcppexpr * tclass * tclass_field + | FuncEnumConstruct of tenum * tenum_field + | FuncSuperConstruct + | FuncSuper of tcppthis * tclass_field + | FuncNew of tcpp + | FuncExpression of tcppexpr + | FuncInternal of tcppexpr * string * string + | FuncGlobal of string + | FuncFromStaticFunction + +and tcpparrayloc = + | ArrayTyped of tcppexpr * tcppexpr + | ArrayPointer of tcppexpr * tcppexpr + | ArrayRawPointer of tcppexpr * tcppexpr + | ArrayObject of tcppexpr * tcppexpr * tcpp + | ArrayVirtual of tcppexpr * tcppexpr + | ArrayImplements of tclass * tcppexpr * tcppexpr + | ArrayDynamic of tcppexpr * tcppexpr + +and tcpplvalue = + | CppVarRef of tcppvarloc + | CppArrayRef of tcpparrayloc + | CppDynamicRef of tcppexpr * string + | CppGlobalRef of string + + +and tcpp_expr_expr = + | CppInt of int32 + | CppFloat of string + | CppString of string + | CppBool of bool + | CppNull + | CppNullAccess + | CppNil + | CppThis of tcppthis + | CppSuper of tcppthis + | CppCode of string * tcppexpr list + | CppClosure of tcpp_closure + | CppVar of tcppvarloc + | CppGlobal of string + | CppDynamicField of tcppexpr * string + | CppFunction of tcppfuncloc * tcpp + | CppEnumIndex of tcppexpr + | CppEnumField of tenum * tenum_field + | CppCall of tcppfuncloc * tcppexpr list + | CppFunctionAddress of tclass * tclass_field + | CppAddressOf of tcppexpr + | CppArray of tcpparrayloc + | CppCrement of tcppcrementop * Ast.unop_flag * tcpplvalue + | CppSet of tcpplvalue * tcppexpr + | CppModify of Ast.binop * tcpplvalue * tcppexpr + | CppBinop of Ast.binop * tcppexpr * tcppexpr + | CppCompare of string * tcppexpr * tcppexpr + | CppNullCompare of string * tcppexpr + | CppObjectDecl of (string * tcppexpr) list * bool + | CppPosition of string * int32 * string * string + | CppArrayDecl of tcppexpr list + | CppUnop of tcppunop * tcppexpr + | CppVarDecl of tvar * tcppexpr option + | CppBlock of tcppexpr list * tcpp_closure list * bool + | CppFor of tvar * tcppexpr * tcppexpr + | CppIf of tcppexpr * tcppexpr * tcppexpr option + | CppWhile of tcppexpr * tcppexpr * Ast.while_flag * int + | CppIntSwitch of tcppexpr * (Int32.t list * tcppexpr) list * tcppexpr option + | CppSwitch of tcppexpr * tcpp * (tcppexpr list * tcppexpr) list * tcppexpr option * int + | CppTry of tcppexpr * (tvar * tcppexpr) list + | CppBreak + | CppContinue + | CppClassOf of path * bool + | CppGoto of int + | CppReturn of tcppexpr option + | CppThrow of tcppexpr + | CppEnumParameter of tcppexpr * tenum_field * int + | CppTCast of tcppexpr * tcpp + | CppCast of tcppexpr * tcpp + | CppCastStatic of tcppexpr * tcpp + | CppCastScalar of tcppexpr * string + | CppCastVariant of tcppexpr + | CppCastObjC of tcppexpr * tclass + | CppCastObjCBlock of tcppexpr * tcpp list * tcpp + | CppCastProtocol of tcppexpr * tclass + | CppCastNative of tcppexpr + +let rec s_tcpp = function + | CppInt _ -> "CppInt" + | CppFloat _ -> "CppFloat" + | CppString _ -> "CppString" + | CppBool _ -> "CppBool" + | CppNull -> "CppNull" + | CppNil -> "CppNil" + | CppThis _ -> "CppThis" + | CppSuper _ -> "CppSuper" + | CppCode _ -> "CppCode" + | CppClosure _ -> "CppClosure" + | CppVar VarLocal(_) -> "CppVarLocal" + | CppVar VarClosure(_) -> "CppVarClosure" + | CppVar VarThis(_) -> "CppVarThis" + | CppVar VarInstance(expr,field,clazz,op) -> "CppVarInstance(" ^ clazz ^ "::" ^ op ^ field.cf_name ^ ")" + | CppVar VarInterface(_) -> "CppVarInterface" + | CppVar VarStatic(_,true,_) -> "CppObjcVarStatic" + | CppVar VarStatic(_) -> "CppVarStatic" + | CppVar VarInternal(_) -> "CppVarInternal" + | CppDynamicField _ -> "CppDynamicField" + | CppGlobal _ -> "CppGlobal" + | CppFunction _ -> "CppFunction" + | CppEnumIndex _ -> "CppEnumIndex" + | CppEnumField _ -> "CppEnumField" + | CppNullAccess -> "CppNullAccess" + + | CppCall (FuncThis _,_) -> "CppCallThis" + | CppCall (FuncInstance (obj,inst,field),_) -> + (match inst with InstObjC -> "CppCallObjCInstance(" | InstPtr-> "CppCallInstance(" | _ -> "CppCallStruct(") ^ + tcpp_to_string obj.cpptype ^ "," ^ field.cf_name ^ ")" + | CppCall (FuncInterface _,_) -> "CppCallInterface" + | CppCall (FuncStatic (_,objC,_),_) -> if objC then "CppCallStaticObjC" else "CppCallStatic" + | CppCall (FuncTemplate _,_) -> "CppCallTemplate" + | CppCall (FuncEnumConstruct _,_) -> "CppCallEnumConstruct" + | CppCall (FuncSuperConstruct,_) -> "CppCallSuperConstruct" + | CppCall (FuncSuper _,_) -> "CppCallSuper" + | CppCall (FuncNew _,_) -> "CppCallNew" + | CppCall (FuncExpression _,_) -> "CppCallExpression" + | CppCall (FuncInternal _,_) -> "CppCallInternal" + | CppCall (FuncGlobal _,_) -> "CppCallGlobal" + | CppCall (FuncFromStaticFunction,_) -> "CppCallFromStaticFunction" + | CppAddressOf _ -> "CppAddressOf" + | CppFunctionAddress _ -> "CppFunctionAddress" + | CppArray _ -> "CppArray" + | CppCrement _ -> "CppCrement" + | CppSet _ -> "CppSet" + | CppModify _ -> "CppModify" + | CppBinop _ -> "CppBinop" + | CppCompare _ -> "CppCompare" + | CppNullCompare _ -> "CppNullCompare" + | CppObjectDecl _ -> "CppObjectDecl" + | CppPosition _ -> "CppPosition" + | CppArrayDecl _ -> "CppArrayDecl" + | CppUnop _ -> "CppUnop" + | CppVarDecl _ -> "CppVarDecl" + | CppBlock _ -> "CppBlock" + | CppFor _ -> "CppFor" + | CppIf _ -> "CppIf" + | CppWhile _ -> "CppWhile" + | CppIntSwitch _ -> "CppIntSwitch" + | CppSwitch _ -> "CppSwitch" + | CppTry _ -> "CppTry" + | CppBreak -> "CppBreak" + | CppContinue -> "CppContinue" + | CppClassOf _ -> "CppClassOf" + | CppGoto _ -> "CppGoto" + | CppReturn _ -> "CppReturn" + | CppThrow _ -> "CppThrow" + | CppEnumParameter _ -> "CppEnumParameter" + | CppTCast _ -> "CppTCast" + | CppCast _ -> "CppCast" + | CppCastStatic _ -> "CppCastStatic" + | CppCastScalar _ -> "CppCastScalar" + | CppCastVariant _ -> "CppCastVariant" + | CppCastObjC _ -> "CppCastObjC" + | CppCastObjCBlock _ -> "CppCastObjCBlock" + | CppCastProtocol _ -> "CppCastProtocol" + | CppCastNative _ -> "CppCastNative" + +and tcpp_to_string_suffix suffix tcpp = match tcpp with + | TCppDynamic -> " ::Dynamic" + | TCppUnchanged -> " ::Dynamic/*Unchanged*/" + | TCppObject -> " ::Dynamic" + | TCppObjectPtr -> " ::hx::Object *" + | TCppReference t -> (tcpp_to_string t) ^" &" + | TCppStar t -> (tcpp_to_string t) ^" *" + | TCppVoid -> "void" + | TCppVoidStar -> "void *" + | TCppRest _ -> "vaarg_list" + | TCppVarArg -> "vararg" + | TCppAutoCast -> "::cpp::AutoCast" + | TCppVariant -> "::cpp::Variant" + | TCppEnum(enum) -> " ::" ^ (join_class_path_remap enum.e_path "::") ^ suffix + | TCppScalar(scalar) -> scalar + | TCppString -> "::String" + | TCppFastIterator it -> "::cpp::FastIterator" ^ suffix ^ "< " ^ (tcpp_to_string it) ^ " >"; + | TCppPointer(ptrType,valueType) -> "::cpp::" ^ ptrType ^ "< " ^ (tcpp_to_string valueType) ^ " >" + | TCppRawPointer(constName,valueType) -> constName ^ (tcpp_to_string valueType) ^ "*" + | TCppFunction(argTypes,retType,abi) -> + let args = (String.concat "," (List.map tcpp_to_string argTypes)) in + "::cpp::Function< " ^ (tcpp_to_string retType) ^ " " ^ abi ^ " (" ^ args ^ ") >" + | TCppObjCBlock(argTypes,retType) -> + (tcpp_objc_block_struct argTypes retType) ^ "::t" + | TCppDynamicArray -> "::cpp::VirtualArray" ^ suffix + | TCppObjectArray _ -> "::Array" ^ suffix ^ "< ::Dynamic>" + | TCppWrapped _ -> " ::Dynamic" + | TCppScalarArray(value) -> "::Array" ^ suffix ^ "< " ^ (tcpp_to_string value) ^ " >" + | TCppObjC klass -> + let path = join_class_path_remap klass.cl_path "::" in + if klass.cl_interface then + "id < " ^ path ^ ">" + else + path ^ " *" + | TCppProtocol interface -> + let path = get_meta_string interface.cl_meta Meta.ObjcProtocol in + let path = if path<>"" then path else join_class_path_remap interface.cl_path "::" in + "id < " ^ path ^ ">" + | TCppNativePointer klass -> + let name = (join_class_path_remap klass.cl_path "::") in + if suffix="_obj" then + name + else + "hx::Native< " ^ name ^ "* >"; + | TCppInst klass -> + (cpp_class_path_of klass) ^ suffix + | TCppInterface klass when suffix="_obj" -> + (cpp_class_path_of klass) ^ suffix + | TCppInterface _ -> "::Dynamic" + | TCppClass -> "hx::Class" ^ suffix; + | TCppGlobal -> ""; + | TCppNull -> " ::Dynamic"; + | TCppCode _ -> "Code" + +and tcpp_objc_block_struct argTypes retType = + let args = (String.concat "," (List.map tcpp_to_string argTypes)) in + let ret = tcpp_to_string retType in + let suffix = (string_of_int (List.length argTypes)) in + if (ret="void") then begin + if (List.length argTypes) = 0 then + "hx::TObjcBlockVoidVoid" + else + "hx::TObjcBlockVoidArgs" ^ suffix ^ "< " ^ args ^ " >" + end else begin + if (List.length argTypes) = 0 then + "hx::TObjcBlockRetVoid< " ^ ret ^ " >" + else + "hx::TObjcBlockRetArgs" ^ suffix ^ "< " ^ ret ^ "," ^ args ^ " >" + end + +and tcpp_to_string tcpp = + tcpp_to_string_suffix "" tcpp + +and cpp_class_path_of klass = + " ::" ^ (join_class_path_remap klass.cl_path "::") +;; + + +let cpp_const_type cval = match cval with + | TInt i -> CppInt(i) , TCppScalar("int") + | TBool b -> CppBool(b) , TCppScalar("bool") + | TFloat f -> CppFloat(f) , TCppScalar("Float") + | TString s -> CppString(s) , TCppString + | _ -> (* TNull, TThis & TSuper should already be handled *) + CppNull, TCppNull +;; + + +let is_cpp_scalar cpp_type = + match cpp_type with + | TCppScalar(_) -> true + | _ -> false +;; + + +let is_cpp_array_implementer cppType = + match cppType with + | TCppInst (klass) + | TCppInterface (klass) -> + (match klass.cl_array_access with + | Some _ -> true + | _ -> false ) + | _ -> false +;; + +let rec const_int_of expr = + match expr.eexpr with + | TConst TInt x -> x + | TConst TBool x -> Int32.of_int (if x then 1 else 0) + | TParenthesis e -> const_int_of e + | _ -> raise Not_found +;; + +let rec const_float_of expr = + match expr.eexpr with + | TConst TInt x -> Printf.sprintf "%ld" x + | TConst TFloat x -> x + | TConst TBool x -> if x then "1" else "0" + | TParenthesis e -> const_float_of e + | _ -> raise Not_found +;; + + +let rec const_string_of expr = + match expr.eexpr with + | TConst TString x -> x + | TParenthesis e -> const_string_of e + | _ -> raise Not_found +;; + + +let rec cpp_is_struct_access t = + match t with + | TCppFunction _ -> true + | TCppInst (class_def) -> (has_meta_key class_def.cl_meta Meta.StructAccess) + | TCppReference (r) -> cpp_is_struct_access r + | _ -> false +;; + + +let cpp_is_dynamic_type = function + | TCppDynamic | TCppObject | TCppVariant | TCppWrapped _ | TCppGlobal | TCppNull + | TCppInterface _ + -> true + | _ -> false +;; + + +let rec cpp_type_of ctx haxe_type = + (match haxe_type with + | TMono r -> (match !r with None -> TCppDynamic | Some t -> cpp_type_of ctx t) + + | TEnum (enum,params) -> TCppEnum(enum) + + | TInst ({ cl_path=([],"Array"); cl_kind = KTypeParameter _},_) + -> TCppObject + + | TInst ({ cl_kind = KTypeParameter _},_) + -> TCppDynamic + + | TInst (klass,params) -> + cpp_instance_type ctx klass params + + | TAbstract (abs,pl) when not (Meta.has Meta.CoreType abs.a_meta) -> + cpp_type_from_path ctx abs.a_path pl (fun () -> + cpp_type_of ctx (Abstract.get_underlying_type abs pl) ) + + | TAbstract (a,params) -> + cpp_type_from_path ctx a.a_path params (fun () -> + if is_scalar_abstract a then + TCppScalar(join_class_path a.a_path "::") + else + TCppDynamic) + + | TType (type_def,params) -> + cpp_type_from_path ctx type_def.t_path params (fun () -> + cpp_type_of ctx (apply_params type_def.t_params params type_def.t_type) ) + + | TFun _ -> TCppObject + | TAnon _ -> TCppObject + | TDynamic _ -> TCppDynamic + | TLazy func -> cpp_type_of ctx ((!func)()) + ) + and cpp_type_from_path ctx path params default = + match path,params with + | ([],"Void"),_ -> TCppVoid + | ([],"void"),_ -> TCppVoid (* for old code with @:void *) + | ([],"Bool"),_ -> TCppScalar("bool") + | ([],"Float"),_ -> TCppScalar("Float") + | ([],"Int"),_ -> TCppScalar("int") + | ([], "EnumValue"),_ -> TCppObject + | ([], "Class"),_ -> TCppClass + | ([], "Enum"),_ -> TCppClass + | (["cpp"], "Char"),_ -> TCppScalar("char") + | (["cpp"], "Object"),_ -> TCppObjectPtr + | (["cpp"], "Float32"),_ -> TCppScalar("float") + | (["cpp"], "Float64"),_ -> TCppScalar("double") + | (["cpp"], "Int8"),_ -> TCppScalar("signed char") + | (["cpp"], "Int16"),_ -> TCppScalar("short") + | (["cpp"], "Int32"),_ -> TCppScalar("int") + | (["cpp"], "Int64"),_ -> TCppScalar("::cpp::Int64") + | (["cpp"], "UInt8"),_ -> TCppScalar("unsigned char") + | (["cpp"], "UInt16"),_ -> TCppScalar("unsigned short") + | (["cpp"], "UInt32"),_ -> TCppScalar("unsigned int") + | (["cpp"], "UInt64"),_ -> TCppScalar("::cpp::UInt64") + | (["cpp"], "VarArg"),_ -> TCppVarArg + | (["cpp"], "AutoCast"),_ -> TCppAutoCast + + | ([],"String"), [] -> + TCppString + + (* Things with type parameters hxcpp knows about ... *) + | (["cpp"],"FastIterator"), [p] -> + TCppFastIterator(cpp_type_of ctx p) + | (["cpp"],"Pointer"), [p] -> + TCppPointer("Pointer", cpp_type_of ctx p) + | (["cpp"],"ConstPointer"), [p] -> + TCppPointer("ConstPointer", cpp_type_of ctx p) + | (["cpp"],"RawPointer"), [p] -> + TCppRawPointer("", cpp_type_of ctx p) + | (["cpp"],"RawConstPointer"), [p] -> + TCppRawPointer("const ", cpp_type_of ctx p) + | (["cpp"],"Function"), [function_type; abi] -> + cpp_function_type_of ctx function_type abi; + | (["cpp"],"Callable"), [function_type] + | (["cpp"],"CallableData"), [function_type] -> + cpp_function_type_of_string ctx function_type ""; + | (("cpp"::["objc"]),"ObjcBlock"), [function_type] -> + let args,ret = (cpp_function_type_of_args_ret ctx function_type) in + TCppObjCBlock(args,ret) + | (["haxe";"extern"], "Rest"),[rest] -> + TCppRest(cpp_type_of ctx rest) + | (("cpp"::["objc"]),"Protocol"), [interface_type] -> + (match follow interface_type with + | TInst (klass,[]) when klass.cl_interface -> + TCppProtocol(klass) + (* TODO - get the line number here *) + | _ -> print_endline "cpp.objc.Protocol must refer to an interface"; + assert false; + ) + | (["cpp"],"Reference"), [param] -> + TCppReference(cpp_type_of ctx param) + | (["cpp"],"Star"), [param] -> + TCppStar(cpp_type_of ctx param) + + | ([],"Array"), [p] -> + let arrayOf = cpp_type_of ctx p in + (match arrayOf with + | TCppVoid (* ? *) + | TCppDynamic -> + TCppDynamicArray + + | TCppObject + | TCppObjectPtr + | TCppReference _ + | TCppStar _ + | TCppEnum _ + | TCppInst _ + | TCppInterface _ + | TCppProtocol _ + | TCppClass + | TCppDynamicArray + | TCppObjectArray _ + | TCppScalarArray _ + -> TCppObjectArray(arrayOf) + | _ -> + TCppScalarArray(arrayOf) + ) + + | ([],"Null"), [p] -> + cpp_type_of_null ctx p + + | _ -> default () + + and cpp_type_of_null ctx p = + let baseType = cpp_type_of ctx p in + if (type_has_meta_key p Meta.NotNull) || (is_cpp_scalar baseType) then + TCppObject + else + baseType + + (* Optional types are Dynamic if they norally could not be null *) + and cpp_fun_arg_type_of ctx tvar opt = + match opt with + | Some _ -> cpp_type_of_null ctx tvar.t_type + | _ -> cpp_type_of ctx tvar.t_type + + and cpp_tfun_arg_type_of ctx opt t = + if opt then cpp_type_of_null ctx t else cpp_type_of ctx t + + and cpp_function_type_of ctx function_type abi = + let abi = (match follow abi with + | TInst (klass1,_) -> get_meta_string klass1.cl_meta Meta.Abi + | _ -> assert false ) + in + cpp_function_type_of_string ctx function_type abi + and cpp_function_type_of_string ctx function_type abi_string = + let args,ret = cpp_function_type_of_args_ret ctx function_type in + TCppFunction(args, ret, abi_string) + + and cpp_function_type_of_args_ret ctx function_type = + match follow function_type with + | TFun(args,ret) -> + (* Optional types are Dynamic if they norally could not be null *) + let cpp_arg_type_of = fun(_,optional,haxe_type) -> + if optional then + cpp_type_of_null ctx haxe_type + else + cpp_type_of ctx haxe_type + in + List.map cpp_arg_type_of args, cpp_type_of ctx ret + | _ -> (* ? *) + [TCppVoid], TCppVoid + + and cpp_instance_type ctx klass params = + cpp_type_from_path ctx klass.cl_path params (fun () -> + if is_objc_class klass then + TCppObjC(klass) + else if klass.cl_interface && is_native_gen_class klass then + TCppNativePointer(klass) + else if klass.cl_interface then + TCppInterface(klass) + else if klass.cl_extern && (not (is_internal_class klass.cl_path) ) then + TCppInst(klass) + else + TCppInst(klass) + ) +;; + + +let cpp_return_type ctx haxe_type = + match haxe_type with + | TFun (_,ret) -> cpp_type_of ctx ret + | _ -> TCppDynamic +;; + + +let cpp_member_return_type ctx member = + cpp_return_type ctx member.cf_type +;; + +let is_cpp_objc_type cpptype = match cpptype with + | TCppObjC(_) -> true; + | _ -> false +;; + + +let cpp_enum_path_of enum = + (* + let rename = get_meta_string enum.e_meta Meta.Native in + if rename <> "" then + rename + else + *) + "::" ^ (join_class_path_remap enum.e_path "::") +;; + + + +(* +let rec cpp_object_name = function + | TCppString -> "::String" + | TCppDynamicArray -> "::cpp::VirtualArray_obj" + | TCppObjectArray _ -> "::Array_obj< ::Dynamic>" + | TCppScalarArray(value) -> "::Array_obj< " ^ (tcpp_to_string value) ^ " >" + | TCppObjC klass -> (cpp_class_path_of klass) ^ "_obj" + | TCppInst klass -> (cpp_class_path_of klass) ^ "_obj" + | TCppClass -> "hx::Class_obj"; + | TCppDynamic -> "Dynamic" + | TCppVoid -> "void" + | TCppVoidStar -> "void *" + | TCppEnum(enum) -> "::hx::EnumBase" + | TCppScalar(scalar) -> scalar + | TCppFastIterator it -> "::cpp::FastIterator< " ^ (tcpp_to_string it) ^ " >"; + | TCppPointer(ptrType,valueType) -> "::cpp::" ^ ptrType ^ "< " ^ (tcpp_to_string valueType) ^ " >" + | TCppRawPointer(constName,valueType) -> constName ^ (tcpp_to_string valueType) ^ "*" + | TCppFunction(argTypes,retType,abi) -> + let args = (String.concat "," (List.map tcpp_to_string argTypes)) in + "::cpp::Function< " ^ abi ^ " " ^ (tcpp_to_string retType) ^ "(" ^ args ^ ") >" + | TCppWrapped _ -> "Dynamic" + | TCppNativePointer klass -> (cpp_class_path_of klass) ^ " *" + | TCppGlobal -> ""; + | TCppNull -> "Dynamic"; + | TCppCode -> "/* code */" +;; +*) + +let cpp_class_name klass = + (* + let rename = get_meta_string klass.cl_meta Meta.Native in + if rename <> "" then + rename ^ "_obj" + else + *) + begin + let path = "::" ^ (join_class_path_remap klass.cl_path "::") in + if path="::String" then path else path ^ "_obj" + end +;; + + +let cpp_variant_type_of t = match t with + | TCppDynamic + | TCppUnchanged + | TCppObject + | TCppObjectPtr + | TCppReference _ + | TCppStar _ + | TCppVoid + | TCppFastIterator _ + | TCppDynamicArray + | TCppObjectArray _ + | TCppScalarArray _ + | TCppWrapped _ + | TCppObjC _ + | TCppObjCBlock _ + | TCppRest _ + | TCppInst _ + | TCppInterface _ + | TCppProtocol _ + | TCppCode _ + | TCppClass + | TCppGlobal + | TCppNull + | TCppEnum _ -> TCppDynamic + | TCppString -> TCppString + | TCppFunction _ + | TCppNativePointer _ + | TCppPointer _ + | TCppRawPointer _ + | TCppAutoCast + | TCppVarArg + | TCppVoidStar -> TCppVoidStar + | TCppScalar "Int" + | TCppScalar "bool" + | TCppScalar "Float" -> t + | TCppScalar "double" + | TCppScalar "float" -> TCppScalar("Float") + | TCppScalar _ -> TCppScalar("int") + | TCppVariant -> TCppVariant +;; + +let cpp_cast_variant_type_of t = match t with + | TCppObjectArray _ + | TCppScalarArray _ + | TCppDynamicArray + | TCppClass + | TCppEnum _ + | TCppInst _ -> t + | _ -> cpp_variant_type_of t; +;; + +let cpp_base_type_of t = + match cpp_variant_type_of t with + | TCppDynamic -> "Object" + | TCppString -> "String" + | TCppVoidStar -> "Pointer" + | TCppScalar "int" -> "Int" + | TCppScalar "bool" -> "Bool" + | TCppScalar x -> x + | _ -> "Object" +;; + +let ctx_type_string ctx haxe_type = + tcpp_to_string (cpp_type_of ctx haxe_type) +;; + + +let ctx_cant_be_null ctx haxe_type = + match cpp_type_of ctx haxe_type with + | TCppScalar _ -> true + | _ -> false + +let is_complex_compare = function + | TCppScalar _ -> false + | TCppString -> false + | _ -> true +;; + + + +let ctx_arg_type_name ctx name default_val arg_type prefix = + let remap_name = keyword_remap name in + let type_str = (ctx_type_string ctx arg_type) in + match default_val with + | Some TNull -> (type_str,remap_name) + | Some constant when (ctx_cant_be_null ctx arg_type) -> ("hx::Null< " ^ type_str ^ " > ",prefix ^ remap_name) + | Some constant -> (type_str,prefix ^ remap_name) + | _ -> (type_str,remap_name);; + + + +(* Generate prototype text, including allowing default values to be null *) +let ctx_arg ctx name default_val arg_type prefix = + let pair = ctx_arg_type_name ctx name default_val arg_type prefix in + (fst pair) ^ " " ^ (snd pair);; + + +(* Generate prototype text, including allowing default values to be null *) +let ctx_arg_name ctx name default_val arg_type prefix = + let pair = ctx_arg_type_name ctx name default_val arg_type prefix in + (snd pair);; + + +let ctx_arg_list ctx arg_list prefix = + String.concat "," (List.map (fun (v,o) -> (ctx_arg ctx v.v_name o v.v_type prefix) ) arg_list) + +let ctx_arg_list_name ctx arg_list prefix = + String.concat "," (List.map (fun (v,o) -> (ctx_arg_name ctx v.v_name o v.v_type prefix) ) arg_list) + +let cpp_arg_names args = + String.concat "," (List.map (fun (name,_,_) -> keyword_remap name) args) +;; + +let rec ctx_tfun_arg_list ctx include_names arg_list = + let oType o arg_type = + let type_str = (ctx_type_string ctx arg_type) in + (* type_str may have already converted Null to Dynamic because of NotNull tag ... *) + if o && (ctx_cant_be_null ctx arg_type) && type_str<>"Dynamic" then + "hx::Null< " ^ type_str ^ " > " + else + type_str + in + match arg_list with + | [] -> "" + | [(name,o,arg_type)] -> (oType o arg_type) ^ (if include_names then " " ^ (keyword_remap name) else "") + | (name,o,arg_type) :: remaining -> + (oType o arg_type) ^ (if include_names then " " ^ (keyword_remap name) else "") ^ "," ^ (ctx_tfun_arg_list ctx include_names remaining) + +let cpp_var_type_of ctx var = + tcpp_to_string (cpp_type_of ctx var.v_type) +;; + + +let cpp_macro_var_type_of ctx var = + let t = tcpp_to_string (cpp_type_of ctx var.v_type) in + if String.contains t ',' then + Str.global_replace (Str.regexp ",") " HX_COMMA " t + else + t +;; + + + + +let ctx_function_signature ctx include_names tfun abi = + match follow tfun with + | TFun(args,ret) -> (ctx_type_string ctx ret) ^ " " ^ abi ^ "(" ^ (ctx_tfun_arg_list ctx include_names args) ^ ")" + | _ -> "void *" + + + +let cpp_var_name_of var = + let rename = get_meta_string var.v_meta Meta.Native in + if rename <> "" then + rename + else + keyword_remap var.v_name +;; + +let cpp_var_debug_name_of v = + let rec loop meta = match meta with + | (Meta.RealPath,[EConst (String s),_],_) :: _ -> s + | _ :: meta -> loop meta + | [] -> v.v_name + in + loop v.v_meta +;; + + +let cpp_no_debug_synbol ctx var = + (ctx.ctx_debug_level<=1) || (has_meta_key var.v_meta Meta.CompilerGenerated) || + match cpp_type_of ctx var.v_type with + | TCppStar _ | TCppReference _ -> true + | TCppInst (class_def) when (has_meta_key class_def.cl_meta Meta.StructAccess) -> true + | TCppInst (class_def) when (has_meta_key class_def.cl_meta Meta.Unreflective) -> true + | _-> + let name = cpp_var_debug_name_of var in + (String.length name) >4 && (String.sub name 0 4) = "_hx_" +;; + +let cpp_debug_name_of var = + keyword_remap var.v_name +;; + +let cpp_debug_var_visible ctx var = + not (cpp_no_debug_synbol ctx (fst var)) +;; + + +let only_stack_access ctx haxe_type = + let tcpp = cpp_type_of ctx haxe_type in + match tcpp with + | TCppInst(klass) -> has_meta_key klass.cl_meta Meta.StackOnly + | _ -> false; +;; + +let cpp_is_real_array obj = + match obj.cpptype with + | TCppScalarArray _ + | TCppObjectArray _ -> true + | _ -> false +;; + + +let is_array_splice_call obj member = + match obj.cpptype, member.cf_name with + | TCppScalarArray _, "splice" + | TCppObjectArray _, "splice" -> true + | _,_ -> false +;; + +let cpp_can_static_cast funcType inferredType = + match funcType with + | TCppReference(_) | TCppStar(_) -> false + | _ -> + (match inferredType with + | TCppInst _ + | TCppClass + | TCppEnum _ + -> (tcpp_to_string funcType) <> (tcpp_to_string inferredType) + | _ -> false + ) +;; + +let cpp_member_name_of member = + let rename = get_meta_string member.cf_meta Meta.Native in + if rename <> "" then + rename + else + keyword_remap member.cf_name +;; + +let cpp_is_templated_call ctx member = + has_meta_key member.cf_meta Meta.TemplatedCall +;; + +let cpp_is_static_extension ctx member = + has_meta_key member.cf_meta Meta.NativeStaticExtension +;; + + +let cpp_template_param path native = + let path = "::" ^ (join_class_path_remap (path) "::" ) in + if (native) then + path + else match path with + | "::Array" -> "hx::ArrayBase" + | "::Int" -> "int" + | "::Bool" -> "bool" + | x -> x +;; + + +let cpp_append_block block expr = + match block.cppexpr with + | CppBlock(expr_list, closures, gc_stack) -> + { block with cppexpr = CppBlock( expr_list @ [expr], closures, gc_stack) } + | _ -> abort "Internal error appending expression" block.cpppos +;; + + + +let cpp_enum_name_of field = + let rename = get_meta_string field.ef_meta Meta.Native in + if rename <> "" then + rename + else + keyword_remap field.ef_name +;; + +let is_gc_element ctx member_type = + Common.defined ctx.ctx_common Define.HxcppGcGenerational && + match member_type with + | TCppDynamic + | TCppObject + | TCppObjectPtr + | TCppEnum _ + | TCppString + | TCppFunction _ + | TCppDynamicArray + | TCppObjectArray _ + | TCppWrapped _ + | TCppScalarArray _ + | TCppInst _ + | TCppInterface _ + | TCppClass + -> true + | _ -> false + +;; + + + +let retype_expression ctx request_type function_args expression_tree forInjection = + let rev_closures = ref [] in + let closureId = ref 0 in + let declarations = ref (Hashtbl.create 0) in + let undeclared = ref (Hashtbl.create 0) in + let uses_this = ref None in + let gc_stack = ref false in + let injection = ref forInjection in + let this_real = ref (if ctx.ctx_real_this_ptr then ThisReal else ThisDynamic) in + let file_id = ctx.ctx_file_id in + let loop_stack = ref [] in + let alloc_file_id () = + incr file_id; + !file_id + in + let begin_loop () = + loop_stack := (alloc_file_id (),ref false) :: !loop_stack; + (fun () -> match !loop_stack with + | (label_id,used) :: tl -> + loop_stack := tl; + if !used then label_id else -1 + | [] -> + abort "Invalid inernal loop handling" expression_tree.epos + ) + in + + (* '__trace' is at the top-level *) + Hashtbl.add !declarations "__trace" (); + List.iter (fun arg -> Hashtbl.add !declarations arg.v_name () ) function_args; + + let rec to_lvalue value = + match value.cppexpr with + | CppVar( VarClosure(var) as varloc) when is_gc_element ctx (cpp_type_of ctx var.v_type) -> + CppVarRef(varloc), true + | CppVar( VarThis(member) as varloc) when is_gc_element ctx (cpp_type_of ctx member.cf_type) -> + CppVarRef(varloc), true + | CppVar( VarInstance(obj,member,_,"->") as varloc) when is_gc_element ctx (cpp_type_of ctx member.cf_type) -> + CppVarRef(varloc), true + | CppVar varloc -> CppVarRef(varloc), false + | CppArray arrayloc -> CppArrayRef(arrayloc), false + | CppDynamicField(expr, name) -> CppDynamicRef(expr,name), false + | CppTCast(cppExpr,_) + | CppCast(cppExpr,_) + | CppCastStatic(cppExpr,_) + | CppCastObjC(cppExpr,_) + | CppCastObjCBlock(cppExpr,_,_) + | CppCastScalar(cppExpr,_) -> to_lvalue cppExpr + | CppCastVariant(cppExpr) -> to_lvalue cppExpr + | CppGlobal(name) -> CppGlobalRef(name), false + + | _ -> abort ("Could not convert expression to l-value (" ^ s_tcpp value.cppexpr ^ ")") value.cpppos + in + + let rec retype return_type expr = + let cpp_type_of t = cpp_type_of ctx t in + let mk_cppexpr newExpr newType = { cppexpr = newExpr; cpptype = newType; cpppos = expr.epos } in + let retype_function_args args arg_types = + let rec map_pair args types result= + match args, types with + | args, [TCppRest(rest)] -> (List.rev (List.map (retype rest) args) ) @ result + | [], [] -> result + | a::arest, t::trest -> map_pair arest trest ((retype t a) :: result ) + | _, [] -> abort ("Too many args") expr.epos + | [], _ -> abort ("Too many types") expr.epos + in + List.rev (map_pair args arg_types []) + in + + let retypedExpr, retypedType = + match expr.eexpr with + | TEnumParameter( enumObj, enumField, enumIndex ) -> + let retypedObj = retype TCppDynamic enumObj in + CppEnumParameter( retypedObj, enumField, enumIndex ), cpp_cast_variant_type_of (cpp_type_of (get_nth_type enumField enumIndex)) + + | TConst TThis -> + uses_this := Some !this_real; + CppThis(!this_real), if !this_real=ThisDynamic then TCppDynamic else cpp_type_of expr.etype + + | TConst TSuper -> + uses_this := Some !this_real; + CppSuper(!this_real), if !this_real=ThisDynamic then TCppDynamic else cpp_type_of expr.etype + + | TConst TNull when is_objc_type expr.etype -> + CppNil, TCppNull + + | TConst x -> + cpp_const_type x + + | TLocal { v_name = "__global__" } -> + CppClassOf(([],""),false), TCppGlobal + + | TLocal tvar -> + let name = tvar.v_name in + if (Hashtbl.mem !declarations name) then begin + (*print_endline ("Using existing tvar " ^ tvar.v_name);*) + CppVar(VarLocal(tvar)), cpp_type_of tvar.v_type + end else begin + (*print_endline ("Missing tvar " ^ tvar.v_name);*) + Hashtbl.replace !undeclared name tvar; + if tvar.v_capture then + CppVar(VarClosure(tvar)), cpp_type_of tvar.v_type + else + CppGlobal(name), cpp_type_of tvar.v_type + end + + | TBreak -> + begin match !loop_stack with + | [] -> + CppBreak, TCppVoid + | (label_id,used) :: _ -> + used := true; + (CppGoto label_id),TCppVoid + end + + | TContinue -> + CppContinue, TCppVoid + + | TThrow e1 -> + CppThrow(retype TCppDynamic e1), TCppVoid + + | TMeta( (Meta.Fixed,_,_),e) -> + let cppType = retype return_type e in + (match cppType.cppexpr with + | CppObjectDecl(def,false) -> CppObjectDecl(def,true), cppType.cpptype + | _ -> cppType.cppexpr, cppType.cpptype + ) + + | TMeta(_,e) + | TParenthesis e -> + let cppType = retype return_type e in + cppType.cppexpr, cppType.cpptype + + | TField( obj, field ) -> + (match field with + | FInstance (clazz,params,member) + | FClosure (Some (clazz,params),member) -> + let funcReturn = cpp_member_return_type ctx member in + let clazzType = cpp_instance_type ctx clazz params in + let retypedObj = retype clazzType obj in + let exprType = cpp_type_of member.cf_type in + let is_objc = is_cpp_objc_type retypedObj.cpptype in + + if retypedObj.cpptype=TCppNull then + CppNullAccess, TCppDynamic + else if retypedObj.cpptype=TCppDynamic && not clazz.cl_interface then begin + if is_internal_member member.cf_name then + CppFunction( FuncInstance(retypedObj,InstPtr,member), funcReturn ), exprType + else + CppDynamicField(retypedObj, member.cf_name), TCppVariant + end else if cpp_is_struct_access retypedObj.cpptype then begin + + match retypedObj.cppexpr with + | CppThis ThisReal -> + CppVar(VarThis(member)), exprType + | _ -> if (is_var_field member) then + CppVar( VarInstance(retypedObj,member,tcpp_to_string clazzType, ".") ), exprType + else + CppFunction( FuncInstance(retypedObj,InstStruct,member), funcReturn ), exprType + + end else if is_var_field member then begin + + let exprType = match retypedObj.cpptype, exprType with + | TCppPointer(_,t), TCppDynamic + | TCppRawPointer(_,t), TCppDynamic (* the 'type parameter' will show up as Dynamic *) + -> t + | _ -> exprType + in + + match retypedObj.cppexpr with + | CppThis ThisReal -> + CppVar(VarThis(member) ), exprType + | _ -> + (match retypedObj.cpptype, member.cf_name with + (* Special variable remapping ... *) + | TCppDynamicArray, "length" -> + CppCall(FuncInternal(retypedObj,"get_length","->"),[]), exprType + + | TCppInterface _,_ + | TCppDynamic,_ -> + CppDynamicField(retypedObj, member.cf_name), TCppVariant + | TCppObjC _,_ -> + CppVar(VarInstance(retypedObj,member,tcpp_to_string clazzType, ".") ), exprType + + | _ -> + let operator = if cpp_is_struct_access retypedObj.cpptype || retypedObj.cpptype=TCppString then "." else "->" in + CppVar(VarInstance(retypedObj,member,tcpp_to_string clazzType, operator) ), exprType + ) + end else if (clazz.cl_interface && not is_objc (* Use instance call for objc interfaces *)) then + CppFunction( FuncInterface(retypedObj,clazz,member), funcReturn ), exprType + else begin + let isArrayObj = match retypedObj.cpptype with + | TCppDynamicArray + | TCppObjectArray _ + | TCppScalarArray _ + -> true + | _ -> false in + (* Special array return values *) + let funcReturn = + if isArrayObj then match member.cf_name with + | "map" -> TCppDynamicArray + | "splice" + | "slice" + | "concat" + | "copy" + | "filter" -> retypedObj.cpptype + | _ -> funcReturn + else match retypedObj.cpptype, funcReturn with + | TCppPointer(_,t), TCppDynamic + | TCppRawPointer(_,t), TCppDynamic (* the 'type parameter' will show up as Dynamic *) + -> t + | _ -> funcReturn + in + (match retypedObj.cppexpr with + | CppThis ThisReal -> + CppFunction( FuncThis(member), funcReturn ), exprType + | CppSuper this -> + CppFunction( FuncSuper(this,member), funcReturn ), exprType + | _ -> + CppFunction( FuncInstance(retypedObj,(if is_objc then InstObjC else InstPtr),member), funcReturn ), exprType + ) + end + + | FStatic ( _, ({cf_name="nativeFromStaticFunction"} as member) ) -> + let funcReturn = cpp_member_return_type ctx member in + let exprType = cpp_type_of member.cf_type in + CppFunction( FuncFromStaticFunction, funcReturn ), exprType + + | FStatic (clazz,member) -> + let funcReturn = cpp_member_return_type ctx member in + let exprType = cpp_type_of member.cf_type in + let objC = is_objc_class clazz in + if is_var_field member then + CppVar(VarStatic(clazz, objC, member)), exprType + else + CppFunction( FuncStatic(clazz,objC,member), funcReturn ), exprType + | FClosure (None,field) + | FAnon field -> + let obj = retype TCppDynamic obj in + let fieldName = field.cf_name in + if obj.cpptype=TCppGlobal then + CppGlobal(fieldName), cpp_type_of expr.etype + else if obj.cpptype=TCppNull then + CppNullAccess, TCppDynamic + else if is_internal_member fieldName then begin + let cppType = cpp_return_type ctx expr.etype in + if obj.cpptype=TCppString then + CppFunction( FuncInternal(obj,fieldName,"."), cppType), cppType + else + CppFunction( FuncInternal(obj,fieldName,"->"), cppType), cppType + end else + CppDynamicField(obj, field.cf_name), TCppVariant + + | FDynamic fieldName -> + let obj = retype TCppDynamic obj in + if obj.cpptype=TCppNull then + CppNullAccess, TCppDynamic + else if fieldName="cca" && obj.cpptype=TCppString then + CppFunction( FuncInternal(obj,"cca","."), TCppScalar("int")), TCppDynamic + else if fieldName="__s" && obj.cpptype=TCppString then + CppVar( VarInternal(obj,".","__s")), TCppPointer("ConstPointer", TCppScalar("char")) + else if fieldName="__Index" then + CppEnumIndex(obj), TCppScalar("int") + else if is_internal_member fieldName || cpp_is_real_array obj then begin + let cppType = cpp_return_type ctx expr.etype in + if obj.cpptype=TCppString then + CppFunction( FuncInternal(obj,fieldName,"."), cppType), cppType + else + CppFunction( FuncInternal(obj,fieldName,"->"), cppType), cppType + end else if (obj.cpptype=TCppGlobal) then + CppGlobal(fieldName), cpp_type_of expr.etype + else if (obj.cpptype=TCppClass) then begin + match obj.cppexpr with + | CppClassOf(path,_) -> + CppGlobal ( (join_class_path_remap path "::" ) ^ "_obj::" ^ fieldName ), cpp_type_of expr.etype + | _ -> + CppVar( VarInternal(obj,"->",fieldName)), cpp_type_of expr.etype + end else + CppDynamicField(obj, fieldName), TCppVariant + + | FEnum (enum, enum_field) -> + CppEnumField(enum, enum_field), TCppEnum(enum) + ) + + | TCall( {eexpr = TLocal { v_name = "__cpp__" }}, arg_list ) -> + let cppExpr = match arg_list with + | [{ eexpr = TConst (TString code) }] -> CppCode(code, []) + | ({ eexpr = TConst (TString code) }) :: remaining -> + let retypedArgs = List.map (fun arg -> retype (TCppCode(cpp_type_of arg.etype)) arg) remaining in + CppCode(code, retypedArgs) + | _ -> abort "__cpp__'s first argument must be a string" expr.epos; + in + cppExpr, TCppCode(cpp_type_of expr.etype) + + | TCall( func, args ) -> + let retypedFunc = retype TCppUnchanged func in + (match retypedFunc.cpptype with + | TCppNull -> + CppNullAccess, TCppDynamic + | TCppFunction(argTypes,retType,_) -> + let retypedArgs = retype_function_args args argTypes in + CppCall( FuncExpression(retypedFunc) ,retypedArgs), retType + | TCppObjCBlock(argTypes,retType) -> + let retypedArgs = retype_function_args args argTypes in + CppCall( FuncExpression(retypedFunc) ,retypedArgs), retType + + | _ -> + let cppType = cpp_type_of expr.etype in + (match retypedFunc.cppexpr with + | CppFunction(FuncFromStaticFunction ,returnType) -> + let retypedArgs = List.map (retype TCppDynamic ) args in + ( match retypedArgs with + | [ {cppexpr=CppFunction( FuncStatic(clazz,false,member), funcReturn)} ] -> + CppFunctionAddress(clazz,member), funcReturn + | _ -> abort "cpp.Function.fromStaticFunction must be called on static function" expr.epos; + ) + | CppEnumIndex(_) -> + (* Not actually a TCall...*) + retypedFunc.cppexpr, retypedFunc.cpptype + + | CppFunction( FuncInstance(obj, InstPtr, member), _ ) when return_type=TCppVoid && is_array_splice_call obj member -> + let retypedArgs = List.map (retype TCppDynamic ) args in + CppCall( FuncInstance(obj, InstPtr, {member with cf_name="removeRange"}), retypedArgs), TCppVoid + + | CppFunction( FuncStatic(obj, false, member), _ ) when member.cf_name = "hx::AddressOf" -> + let arg = retype TCppUnchanged (List.hd args) in + CppAddressOf(arg), TCppRawPointer("", arg.cpptype) + + | CppFunction( FuncStatic(obj, false, member), _ ) when member.cf_name = "_hx_create_array_length" -> + let retypedArgs = List.map (retype TCppDynamic ) args in + (* gc_stack - not needed yet *) + (match return_type with + | TCppObjectArray _ + | TCppScalarArray _ -> CppCall( FuncNew(return_type), retypedArgs), return_type + | _ -> CppCall( FuncNew(TCppDynamicArray), retypedArgs), return_type + ) + + | CppFunction( FuncStatic(obj, false, member), returnType ) when cpp_is_templated_call ctx member -> + let retypedArgs = List.map (retype TCppDynamic ) args in + (match retypedArgs with + | {cppexpr = CppClassOf(path,native) }::rest -> + CppCall( FuncTemplate(obj,member,path,native), rest), returnType + | _ -> abort "First parameter of template function must be a Class" retypedFunc.cpppos + ) + + | CppFunction( FuncInstance(obj,InstPtr,member) as func, returnType ) when cpp_can_static_cast returnType cppType -> + let retypedArgs = List.map (retype TCppDynamic ) args in + let call = mk_cppexpr (CppCall(func,retypedArgs)) returnType in + CppCastStatic(call, cppType), cppType + (* + let error_printer file line = Printf.sprintf "%s:%d:" file line in + let epos = Lexer.get_error_pos error_printer expr.epos in + print_endline ( "fixed override " ^ member.cf_name ^ " @ " ^ epos ^ " " ^ (tcpp_to_string returnType) ^ "->" ^ (ctx_type_string ctx expr.etype) ); + CppCall(func,retypedArgs), returnType + *) + + (* Other functions ... *) + | CppFunction( FuncInstance(_,_,{cf_type=TFun(arg_types,_)} ) as func, returnType ) + | CppFunction( FuncStatic(_,_,{cf_type=TFun(arg_types,_)} ) as func, returnType ) + | CppFunction( FuncThis({cf_type=TFun(arg_types,_)} ) as func, returnType ) -> + let arg_types = List.map (fun (_,opt,t) -> cpp_tfun_arg_type_of ctx opt t) arg_types in + (* retype args specifically (not just CppDynamic) *) + let retypedArgs = retype_function_args args arg_types in + CppCall(func,retypedArgs), returnType + + | CppFunction(func,returnType) -> + let retypedArgs = List.map (retype TCppDynamic ) args in + CppCall(func,retypedArgs), returnType + + | CppEnumField(enum, field) -> + (* TODO - proper re-typing *) + let retypedArgs = List.map (retype TCppDynamic ) args in + CppCall( FuncEnumConstruct(enum,field),retypedArgs), cppType + + | CppSuper(_) -> + (* TODO - proper re-typing *) + let retypedArgs = List.map (retype TCppDynamic ) args in + CppCall( FuncSuperConstruct ,retypedArgs), TCppVoid + + | CppDynamicField(expr,name) -> + let retypedArgs = List.map (retype TCppDynamic ) args in + (* Special function calls *) + (match expr.cpptype, name with + | TCppGlobal, _ -> + CppCall( FuncGlobal(name),retypedArgs), cppType + + | TCppString, _ -> + CppCall( FuncInternal(expr,name,"."),retypedArgs), cppType + + | _, "__Tag" -> + CppCall( FuncInternal(expr,"_hx_getTag","->"),retypedArgs), cppType + + | _, name when is_internal_member name -> + CppCall( FuncInternal(expr,name,"->"),retypedArgs), cppType + + | _ -> (* not special *) + CppCall( FuncExpression(retypedFunc), retypedArgs), TCppDynamic + ) + + | CppGlobal(_) -> + let retypedArgs = List.map (retype TCppDynamic ) args in + CppCall( FuncExpression(retypedFunc) ,retypedArgs), cppType + + | _ -> + let retypedArgs = List.map (retype TCppDynamic ) args in + CppCall( FuncExpression(retypedFunc), retypedArgs), TCppDynamic + ) + ) + + | TNew (clazz,params,args) -> + (* New DynamicArray ? *) + let retypedArgs = List.map (retype TCppDynamic ) args in + let created_type = cpp_type_of expr.etype in + gc_stack := !gc_stack || (match created_type with | TCppInst(_) -> true | _ -> false ); + CppCall( FuncNew(created_type), retypedArgs), created_type + + | TFunction func -> + let old_this_real = !this_real in + this_real := ThisFake; + (* TODO - this_dynamic ? *) + let old_undeclared = Hashtbl.copy !undeclared in + let old_declarations = Hashtbl.copy !declarations in + let old_uses_this = !uses_this in + let old_gc_stack = !gc_stack in + uses_this := None; + undeclared := Hashtbl.create 0; + declarations := Hashtbl.create 0; + List.iter ( fun (tvar,_) -> + Hashtbl.add !declarations tvar.v_name () ) func.tf_args; + let cppExpr = retype TCppVoid (mk_block func.tf_expr) in + let result = { close_expr=cppExpr; + close_id= !closureId; + close_undeclared= !undeclared; + close_type= cpp_type_of func.tf_type; + close_args= func.tf_args; + close_this= !uses_this; + } in + incr closureId; + declarations := old_declarations; + undeclared := old_undeclared; + Hashtbl.iter (fun name tvar -> + if not (Hashtbl.mem !declarations name) then + Hashtbl.replace !undeclared name tvar; + ) result.close_undeclared; + this_real := old_this_real; + uses_this := if !uses_this != None then Some old_this_real else old_uses_this; + gc_stack := old_gc_stack; + rev_closures := result:: !rev_closures; + CppClosure(result), TCppDynamic + + | TArray (e1,e2) -> + let retypedObj = retype TCppDynamic e1 in + let retypedIdx = retype (TCppScalar("int")) e2 in + let arrayExpr, elemType = (match retypedObj.cpptype with + | TCppScalarArray scalar -> + CppArray( ArrayTyped(retypedObj,retypedIdx) ), scalar + | TCppPointer (_,elem) -> + CppArray( ArrayPointer(retypedObj, retypedIdx) ), elem + | TCppRawPointer (_,elem) -> + CppArray( ArrayRawPointer(retypedObj, retypedIdx) ), elem + | TCppObjectArray TCppDynamic -> + CppArray( ArrayObject(retypedObj,retypedIdx,TCppDynamic) ), TCppDynamic + | TCppObjectArray elem -> + CppArray( ArrayObject(retypedObj,retypedIdx,elem) ), elem + | TCppInst({cl_array_access = Some _ } as klass) -> + CppArray( ArrayImplements(klass, retypedObj,retypedIdx) ), cpp_type_of expr.etype + | TCppDynamicArray -> + CppArray( ArrayVirtual(retypedObj, retypedIdx) ), TCppDynamic + | _ -> + CppArray( ArrayDynamic(retypedObj, retypedIdx) ), TCppDynamic + ) in + let returnType = cpp_type_of expr.etype in + if cpp_can_static_cast elemType returnType then + CppCastStatic(mk_cppexpr arrayExpr returnType, returnType), returnType + else + arrayExpr, elemType + + | TTypeExpr module_type -> + let path = t_path module_type in + CppClassOf(path, is_native_gen_module module_type), TCppClass + + | TBinop (op,e1,e2) -> + let objC1 = (is_objc_type e1.etype) in + let objC2 = (is_objc_type e2.etype) in + let compareObjC = (objC1<>objC2) && (op=OpEq || op=OpNotEq) in + let e2 = retype (if compareObjC && objC2 then TCppUnchanged + else cpp_type_of (if op=OpAssign then e1 else e2).etype) e2 in + let e1 = retype (if compareObjC && objC1 then TCppUnchanged else cpp_type_of e1.etype) e1 in + let complex = (is_complex_compare e1.cpptype) || (is_complex_compare e2.cpptype) in + let e1_null = e1.cpptype=TCppNull in + let e2_null = e2.cpptype=TCppNull in + let reference = match op with + | OpAssign -> + let lvalue, gc = to_lvalue e1 in + if gc then gc_stack := true; + CppSet(lvalue, e2) + | OpAssignOp op -> + let lvalue, gc = to_lvalue e1 in + if gc then gc_stack := true; + CppModify(op, lvalue, e2) + | OpEq when e1_null && e2_null-> CppBool(true) + | OpGte when e1_null && e2_null-> CppBool(true) + | OpLte when e1_null && e2_null-> CppBool(true) + | OpNotEq when e1_null && e2_null-> CppBool(false) + | _ when e1_null && e2_null-> CppBool(false) + + | OpEq when e1_null -> CppNullCompare("IsNull", e2) + | OpGte when e1_null -> CppNullCompare("IsNull", e2) + | OpLte when e1_null -> CppNullCompare("IsNull", e2) + | OpNotEq when e1_null -> CppNullCompare("IsNotNull", e2) + + | OpEq when e2_null -> CppNullCompare("IsNull", e1) + | OpGte when e2_null -> CppNullCompare("IsNull", e1) + | OpLte when e2_null -> CppNullCompare("IsNull", e1) + | OpNotEq when e2_null -> CppNullCompare("IsNotNull", e1) + + | OpEq when complex -> CppCompare("IsEq", e1, e2) + | OpNotEq when complex -> CppCompare("IsNotEq", e1, e2) + | OpGte when complex -> CppCompare("IsGreaterEq", e1, e2) + | OpLte when complex -> CppCompare("IsLessEq", e1, e2) + | OpGt when complex -> CppCompare("IsGreater", e1, e2) + | OpLt when complex -> CppCompare("IsLess", e1, e2) + + | _ -> CppBinop(op,e1,e2) + in + reference, cpp_type_of expr.etype + + | TUnop (op,pre,e1) -> + let targetType = match op with + | Not -> TCppScalar("bool") + | NegBits -> TCppScalar("int") + | _ -> cpp_type_of e1.etype + in + + let e1 = retype targetType e1 in + let reference = match op with + | Increment -> + let lvalue, gc = to_lvalue e1 in + if gc then gc_stack := true; + CppCrement( CppIncrement, pre, lvalue) + | Decrement -> + let lvalue, gc = to_lvalue e1 in + if gc then gc_stack := true; + CppCrement( CppDecrement, pre, lvalue) + | Neg -> CppUnop(CppNeg,e1) + | Not -> CppUnop(CppNot,e1) + | NegBits -> CppUnop(CppNegBits,e1) + in reference, cpp_type_of expr.etype + + | TFor (v,init,block) -> + let old_declarations = Hashtbl.copy !declarations in + Hashtbl.add !declarations v.v_name (); + let init = retype (cpp_type_of v.v_type) init in + let block = retype TCppVoid (mk_block block) in + declarations := old_declarations; + CppFor(v,init,block), TCppVoid + + | TWhile (e1,e2,flag) -> + let condition = retype (TCppScalar("bool")) e1 in + let close = begin_loop() in + let block = retype TCppVoid (mk_block e2) in + CppWhile(condition, block, flag, close()), TCppVoid + + | TArrayDecl el -> + let retypedEls = List.map (retype TCppDynamic) el in + CppArrayDecl(retypedEls), cpp_type_of expr.etype + + | TBlock expr_list -> + let inject = !injection in + injection := false; + if (return_type<>TCppVoid) then + print_endline ("Value from a block not handled " ^ + (expr.epos.pfile ) ^ " " ^ (string_of_int (Lexer.get_error_line expr.epos) )); + + let old_declarations = Hashtbl.copy !declarations in + let old_closures = !rev_closures in + rev_closures := []; + let local_closures = ref [] in + let remaining = ref (List.length expr_list) in + let cppExprs = List.map ( fun expr -> + let targetType = if inject && (!remaining=1) then cpp_type_of expr.etype else TCppVoid in + decr remaining; + let result = retype targetType expr in + local_closures := !rev_closures @ !local_closures; + rev_closures := []; + result + ) expr_list in + declarations := old_declarations; + rev_closures := old_closures; + + CppBlock(cppExprs, List.rev !local_closures, !gc_stack ), TCppVoid + + | TObjectDecl ( + ("fileName" , { eexpr = (TConst (TString file)) }) :: + ("lineNumber" , { eexpr = (TConst (TInt line)) }) :: + ("className" , { eexpr = (TConst (TString class_name)) }) :: + ("methodName", { eexpr = (TConst (TString meth)) }) :: [] ) -> + CppPosition(file,line,class_name,meth), TCppDynamic + + | TObjectDecl el -> + let retypedEls = List.map ( fun(v,e) -> v, retype TCppDynamic e) el in + (match return_type with + | TCppVoid -> CppObjectDecl(retypedEls,false), TCppVoid + | _ -> CppObjectDecl(retypedEls,false), TCppDynamic + ) + + | TVar (v,eo) -> + let varType = cpp_type_of v.v_type in + let init = match eo with None -> None | Some e -> Some (retype varType e) in + Hashtbl.add !declarations v.v_name (); + CppVarDecl(v, init), varType + + | TIf (ec,e1,e2) -> + let ec = retype (TCppScalar("bool")) ec in + let blockify = if return_type!=TCppVoid then fun e -> e else mk_block in + let e1 = retype return_type (blockify e1) in + let e2 = match e2 with None->None | Some e -> Some (retype return_type (blockify e)) + in + CppIf(ec, e1, e2), if return_type=TCppVoid then TCppVoid else cpp_type_of expr.etype + + (* Switch internal return - wrap whole thing in block *) + | TSwitch (condition,cases,def) -> + if return_type<>TCppVoid then + abort "Value from a switch not handled" expr.epos; + + let conditionType = cpp_type_of condition.etype in + let condition = retype conditionType condition in + let cppDef = match def with None -> None | Some e -> Some (retype TCppVoid (mk_block e)) in + (try + (match conditionType with TCppScalar("int") | TCppScalar("bool") -> () | _ -> raise Not_found ); + let cases = List.map (fun (el,e2) -> + (List.map const_int_of el), (retype TCppVoid (mk_block e2)) ) cases in + CppIntSwitch(condition, cases, cppDef), TCppVoid + with Not_found -> + let label = alloc_file_id () in + (* do something better maybe ... *) + let cases = List.map (fun (el,e2) -> + let cppBlock = retype TCppVoid (mk_block e2) in + let gotoExpr = { cppexpr = CppGoto(label); cpptype = TCppVoid; cpppos = e2.epos } in + let cppBlock = cpp_append_block cppBlock gotoExpr in + (List.map (retype conditionType) el), cppBlock ) cases in + CppSwitch(condition, conditionType, cases, cppDef, label), TCppVoid + ) + + | TTry (try_block,catches) -> + (* TTry internal return - wrap whole thing in block ? *) + if return_type<>TCppVoid then + abort "Value from a try-block not handled" expr.epos; + let cppBlock = retype TCppVoid try_block in + let cppCatches = List.map (fun (tvar,catch_block) -> + let old_declarations = Hashtbl.copy !declarations in + Hashtbl.add !declarations tvar.v_name (); + let cppCatchBlock = retype TCppVoid catch_block in + declarations := old_declarations; + tvar, cppCatchBlock; + ) catches in + CppTry(cppBlock, cppCatches), TCppVoid + + | TReturn eo -> + CppReturn(match eo with None -> None | Some e -> Some (retype (cpp_type_of expr.etype) e)), TCppVoid + + | TCast (base,None) -> (* Use auto-cast rules *) + let return_type = cpp_type_of expr.etype in + let baseCpp = retype (return_type) base in + let baseStr = (tcpp_to_string baseCpp.cpptype) in + let returnStr = (tcpp_to_string return_type) in + if baseStr=returnStr then + baseCpp.cppexpr, baseCpp.cpptype (* nothing to do *) + else (match return_type with + | TCppObjC(k) -> CppCastObjC(baseCpp,k), return_type + | TCppPointer(_,_) + | TCppInst(_) -> CppCast(baseCpp,return_type), return_type + | TCppString -> CppCastScalar(baseCpp,"::String"), return_type + | TCppCode(t) when baseStr <> (tcpp_to_string t) -> + CppCast(baseCpp, t), t + | TCppNativePointer(klass) -> CppCastNative(baseCpp), return_type + | TCppObjCBlock(args,ret) -> CppCastObjCBlock(baseCpp,args,ret), return_type + | TCppProtocol(p) -> CppCastProtocol(baseCpp,p), return_type + | TCppDynamic when baseCpp.cpptype=TCppClass -> CppCast(baseCpp,TCppDynamic), TCppDynamic + | _ -> baseCpp.cppexpr, baseCpp.cpptype (* use autocasting rules *) + ) + + | TCast (base,Some t) -> + let baseCpp = retype (cpp_type_of base.etype) base in + let baseStr = (tcpp_to_string baseCpp.cpptype) in + let returnStr = (tcpp_to_string return_type) in + + if baseStr=returnStr then + baseCpp.cppexpr, baseCpp.cpptype (* nothing to do *) + else (match return_type with + | TCppNativePointer(klass) -> CppCastNative(baseCpp), return_type + | TCppVoid -> baseCpp.cppexpr, TCppVoid + | TCppInterface _ -> + baseCpp.cppexpr, return_type + | TCppDynamic -> + baseCpp.cppexpr, baseCpp.cpptype + | _ -> + CppTCast(baseCpp, return_type), return_type + ) + in + let cppExpr = mk_cppexpr retypedExpr retypedType in + + (* Autocast rules... *) + if return_type=TCppVoid then + mk_cppexpr retypedExpr TCppVoid + else if return_type=TCppVarArg then begin + match cpp_variant_type_of cppExpr.cpptype with + | TCppVoidStar + | TCppScalar _ -> cppExpr + | TCppString -> mk_cppexpr (CppVar(VarInternal(cppExpr,".","__s"))) (TCppPointer("ConstPointer", TCppScalar("char"))) + | TCppDynamic -> mk_cppexpr (CppCastNative(cppExpr)) TCppVoidStar + | _ -> let toDynamic = mk_cppexpr (CppCast(cppExpr, TCppDynamic)) TCppDynamic in + mk_cppexpr (CppCastNative(toDynamic)) TCppVoidStar + end else if (cppExpr.cpptype=TCppVariant || cppExpr.cpptype=TCppDynamic) then begin + match return_type with + | TCppObjectArray _ + | TCppScalarArray _ + | TCppNativePointer _ + | TCppDynamicArray + | TCppObjectPtr + | TCppVarArg + | TCppInst _ + -> mk_cppexpr (CppCast(cppExpr,return_type)) return_type + + | TCppObjC k + -> mk_cppexpr (CppCastObjC(cppExpr,k)) return_type + + | TCppObjCBlock(ret,args) + -> mk_cppexpr (CppCastObjCBlock(cppExpr,ret,args)) return_type + + | TCppScalar(scalar) + -> mk_cppexpr (CppCastScalar(cppExpr,scalar)) return_type + + | TCppString + -> mk_cppexpr (CppCastScalar(cppExpr,"::String")) return_type + + | TCppInterface _ when cppExpr.cpptype=TCppVariant + -> mk_cppexpr (CppCastVariant(cppExpr)) return_type + + | TCppDynamic when cppExpr.cpptype=TCppVariant + -> mk_cppexpr (CppCastVariant(cppExpr)) return_type + + | _ -> cppExpr + end else match cppExpr.cpptype, return_type with + | _, TCppUnchanged -> cppExpr + | TCppAutoCast, _ + | TCppObjC(_), TCppDynamic + | TCppObjCBlock(_), TCppDynamic + -> mk_cppexpr (CppCast(cppExpr,return_type)) return_type + | TCppReference(TCppDynamic), TCppReference(_) -> cppExpr + | TCppReference(TCppDynamic), t -> + mk_cppexpr retypedExpr (TCppReference(t)) + | TCppStar(TCppDynamic), TCppStar(_) -> cppExpr + | TCppStar(TCppDynamic), t -> + mk_cppexpr retypedExpr (TCppStar(t)) + | TCppObjectPtr, TCppObjectPtr -> cppExpr + | TCppObjectPtr, _ -> + mk_cppexpr (CppCast(cppExpr,TCppDynamic)) TCppDynamic + + | TCppProtocol _, TCppProtocol _ -> cppExpr + | t, TCppProtocol protocol -> + mk_cppexpr (CppCastProtocol(cppExpr,protocol)) return_type + + | _, TCppObjectPtr -> + mk_cppexpr (CppCast(cppExpr,TCppObjectPtr)) TCppObjectPtr + | _ -> cppExpr + in + retype request_type expression_tree +;; + +type tinject = { + inj_prologue : bool -> unit; + inj_setvar : string; + inj_tail : string; +} + +let mk_injection prologue set_var tail = + Some { inj_prologue=prologue; inj_setvar=set_var; inj_tail=tail } +;; + + +let cpp_arg_type_name ctx tvar default_val prefix = + let remap_name = (cpp_var_name_of tvar) in + let type_str = (cpp_var_type_of ctx tvar) in + match default_val with + | Some TNull -> (tcpp_to_string (cpp_type_of_null ctx tvar.v_type)),remap_name + | Some constant -> (tcpp_to_string (cpp_type_of_null ctx tvar.v_type)),prefix ^ remap_name + | _ -> type_str,remap_name +;; + + +let cpp_gen_default_values ctx args prefix = + List.iter ( fun (tvar,o) -> + match o with + | Some TNull -> () + | Some const -> + let name = cpp_var_name_of tvar in + ctx.ctx_output ((cpp_var_type_of ctx tvar) ^ " " ^ name ^ " = " ^ prefix ^ name ^ ".Default(" ^ + (default_value_string const) ^ ");\n") + | _ -> () + ) args; +;; + +let is_constant_zero expr = + match expr.cppexpr with + | CppFloat x when (float_of_string x) = 0.0 -> true + | CppInt i when i = Int32.of_int 0 -> true + | _ -> false +;; + +let cpp_is_const_scalar_array arrayType expressions = + List.length expressions>0 && (match arrayType with + | TCppScalarArray _ -> + List.for_all (fun expr -> match expr.cppexpr with + | CppInt _ | CppFloat _ | CppString _ | CppBool _ -> true + | _ -> false + ) expressions + | _ -> false) +;; + + + +(* Generate prototype text, including allowing default values to be null *) +let cpp_arg_string ctx tvar default_val prefix = + let t,n = cpp_arg_type_name ctx tvar default_val prefix in + t ^ " " ^ n +;; + +let cpp_arg_list ctx args prefix = + String.concat "," (List.map (fun (v,o) -> (cpp_arg_string ctx v o prefix) ) args) +;; + + +let ctx_default_values ctx args prefix = + cpp_gen_default_values ctx args prefix +;; + + +let gen_type ctx haxe_type = + ctx.ctx_output (ctx_type_string ctx haxe_type) +;; + + +let gen_cpp_ast_expression_tree ctx class_name func_name function_args injection tree = + let writer = ctx.ctx_writer in + let out = ctx.ctx_output in + let lastLine = ref (-1) in + let tempId = ref 0 in + + let spacer = if (ctx.ctx_debug_level>0) then " \t" else "" in + let output_i value = out spacer; writer#write_i value in + + let output_p expr value = + if (ctx.ctx_debug_level>0) then begin + let line = Lexer.get_error_line expr.cpppos in + let lineName = Printf.sprintf "%4d" line in + let macro = if (line != !lastLine) then "HXLINE" else "HXDLIN" in + out (macro ^ "(" ^ lineName ^ ")\t" ); + lastLine := line; + end; + writer#write_i value + in + + let forInjection = match injection with Some inject -> inject.inj_setvar<>"" | _ -> false in + + let cppTree = retype_expression ctx TCppVoid function_args tree forInjection in + let label_name i = Printf.sprintf "_hx_goto_%i" i in + let class_hash = gen_hash_small 0 class_name in + + let rec gen_with_injection injection expr = + (match expr.cppexpr with + | CppBlock(exprs,closures,gc_stack) -> + writer#begin_block; + List.iter gen_closure closures; + (match injection with Some inject -> inject.inj_prologue gc_stack | _ -> () ); + let remaining = ref (List.length exprs) in + lastLine := -1; + List.iter (fun e -> + output_p e ""; + if (!remaining=1) then + (match injection with Some inject -> out inject.inj_setvar | _ -> () ); + gen e; + decr remaining; + writer#terminate_line; + ) exprs; + (match injection with Some inject -> out inject.inj_tail | _ -> () ); + out spacer; + writer#end_block; + + | CppInt i -> out (Printf.sprintf "(int)%ld" i) + | CppFloat float_as_string -> out ("((Float)" ^ float_as_string ^")") + | CppString s -> out (strq s) + | CppBool b -> out (if b then "true" else "false") + | CppNull -> out "null()" + | CppNil -> out "nil" + + | CppThis ThisReal -> out "hx::ObjectPtr(this)" + | CppThis _ -> out "__this" + + | CppSuper thiscall -> + out ("hx::ObjectPtr(" ^ (if thiscall=ThisReal then "this" else "__this.mPtr") ^ ")") + + | CppBreak -> out "break" + | CppContinue -> out "continue" + | CppGoto label -> out ("goto " ^ (label_name label)); + + | CppVarDecl(var,init) -> + let name = cpp_var_name_of var in + if cpp_no_debug_synbol ctx var then + out ( (cpp_var_type_of ctx var) ^ " " ^ name ) + else begin + let dbgName = cpp_var_debug_name_of var in + let macro = if init=None then "HX_VAR" else "HX_VARI" in + let varType = cpp_macro_var_type_of ctx var in + if name<>dbgName then + out ( macro ^ "_NAME( " ^ varType ^ "," ^ name ^ ",\"" ^ dbgName ^ "\")" ) + else + out ( macro ^ "( " ^ varType ^ "," ^ name ^ ")"); + end; + (match init with Some init -> out " = "; gen init | _ -> () ); + + | CppEnumIndex(obj) -> + gen obj; + (*if cpp_is_dynamic_type obj.cpptype then*) + out ".StaticCast< ::hx::EnumBase >()"; + out "->getIndex()" + + | CppNullAccess -> out ("hx::Throw(" ^ strq "Null access" ^ ")") + | CppFunction(func,_) -> + (match func with + | FuncThis(field) -> + out ("this->" ^ (cpp_member_name_of field) ^ "_dyn()"); + | FuncInstance(expr,inst,field) -> + gen expr; out ((if expr.cpptype=TCppString || inst=InstStruct then "." else "->") ^ (cpp_member_name_of field) ^ "_dyn()"); + | FuncInterface(expr,_,field) -> + gen expr; + out ("->__Field(" ^ strq field.cf_name ^ ", hx::paccDynamic)") + | FuncStatic(clazz,_,field) -> + let rename = get_meta_string field.cf_meta Meta.Native in + if rename<>"" then + out rename + else + (out (cpp_class_name clazz); out ("::" ^ (cpp_member_name_of field) ^ "_dyn()")) + | FuncExpression(expr) -> + gen expr; + | FuncGlobal(name) -> + out ("::" ^ name); + | FuncInternal(expr,name,_) -> + gen expr; out ("->__Field(" ^ (strq name) ^ ",hx::paccDynamic)") + | FuncSuper _ | FuncSuperConstruct -> abort "Can't create super closure" expr.cpppos + | FuncNew _ -> abort "Can't create new closure" expr.cpppos + | FuncEnumConstruct _ -> abort "Enum constructor outside of CppCall" expr.cpppos + | FuncFromStaticFunction -> abort "Can't create cpp.Function.fromStaticFunction closure" expr.cpppos + | FuncTemplate _ -> abort "Can't create template function closure" expr.cpppos + ); + | CppCall( FuncInterface(expr,clazz,field), args) when not (is_native_gen_class clazz)-> + out ( cpp_class_name clazz ^ "::" ^ cpp_member_name_of field ^ "("); + gen expr; + List.iter (fun arg -> out ","; gen arg ) args; + out ")"; + + | CppCall(FuncStatic(_,true,field) as func, arg_list) + | CppCall(FuncInstance(_,InstObjC,field) as func, arg_list) -> + out "[ "; + (match func with + | FuncStatic(cl,_,_) -> out (join_class_path_remap cl.cl_path "::") + | FuncInstance(expr,_,_) -> gen expr + | _ ->() ); + + let names = ExtString.String.nsplit field.cf_name ":" in + let field_name, arg_names = match names with + | name :: args -> name, args + | _ -> assert false (* per nsplit specs, this should never happen *) + in + out (" " ^ field_name); + (try match arg_list, arg_names with + | [], _ -> () + | [single_arg], _ -> out ": "; gen single_arg + | first_arg :: args, arg_names -> + out ": "; + gen first_arg; + List.iter2 (fun arg arg_name -> + out (" " ^ arg_name ^ ": "); + gen arg) args arg_names + with | Invalid_argument _ -> (* not all arguments names are known *) + abort ( + "The function called here with name " ^ (String.concat ":" names) ^ + " does not contain the right amount of arguments' names as required" ^ + " by the objective-c calling / naming convention:" ^ + " expected " ^ (string_of_int (List.length arg_list)) ^ + " and found " ^ (string_of_int (List.length arg_names))) + expr.cpppos); + out " ]" + + | CppCall(FuncNew( TCppInst klass), args) -> + out ((cpp_class_path_of klass) ^ "_obj::__alloc( HX_CTX "); + List.iter (fun arg -> out ","; gen arg ) args; + out (")") + + | CppCall(func, args) -> + let closeCall = ref "" in + let argsRef = ref args in + (match func with + | FuncThis(field) -> + out ("this->" ^ (cpp_member_name_of field) ); + | FuncInstance(expr,inst,field) -> + let operator = if (expr.cpptype = TCppString || inst=InstStruct) then "." else "->" in + gen expr; out (operator ^ (cpp_member_name_of field) ); + | FuncInterface(expr,_,field) -> + gen expr; out ("->" ^ (cpp_member_name_of field) ); + | FuncStatic(clazz,false,field) when cpp_is_static_extension ctx field -> + (match args with + | fst :: remaining -> + argsRef := remaining; + gen fst; out ("->" ^ (cpp_member_name_of field) ); + | _ -> abort "Native static extensions must have at least 1 argument" expr.cpppos + ); + + | FuncStatic(clazz,_,field) -> + let rename = get_meta_string field.cf_meta Meta.Native in + if rename<>"" then begin + (* This is the case if you use @:native('new foo'). c++ wil group the space undesirably *) + if String.contains rename ' ' then begin + out "("; + closeCall := ")" + end; + out rename + end else + (out (cpp_class_name clazz); out ("::" ^ (cpp_member_name_of field) )) + + | FuncTemplate(clazz,field,tpath,native) -> + let rename = get_meta_string field.cf_meta Meta.Native in + if rename<>"" then begin + (* This is the case if you use @:native('new foo'). c++ wil group the space undesirably *) + if String.contains rename ' ' then begin + out "("; + closeCall := ")" + end; + out rename + end else + (out (cpp_class_name clazz); out ("::" ^ (cpp_member_name_of field) )); + out ("< " ^ (cpp_template_param tpath native) ^ " >") + + | FuncFromStaticFunction -> + abort "Unexpected FuncFromStaticFunction" expr.cpppos + | FuncEnumConstruct(enum,field) -> + out ((string_of_path enum.e_path) ^ "::" ^ (cpp_enum_name_of field)); + + | FuncSuperConstruct -> out ((if not ctx.ctx_real_this_ptr then "__this->" else "") ^ "super::__construct") + + | FuncSuper(this,field) -> + out ( (if this==ThisReal then "this->" else "__->") ^ "super::" ^ (cpp_member_name_of field) ) + + | FuncNew(newType) -> + let objName = match newType with + | TCppString -> "::String" + | TCppDynamicArray -> "::cpp::VirtualArray_obj::__new" + | TCppObjectArray _ -> "::Array_obj< ::Dynamic>::__new" + | TCppScalarArray(value) -> "::Array_obj< " ^ (tcpp_to_string value) ^ " >::__new" + | TCppObjC klass -> (cpp_class_path_of klass) ^ "_obj::__new" + | TCppNativePointer klass -> "new " ^ (cpp_class_path_of klass); + | TCppInst klass -> (cpp_class_path_of klass) ^ "_obj::__new" + | TCppClass -> "hx::Class_obj::__new"; + | TCppFunction _ -> tcpp_to_string newType + | _ -> abort ("Unknown 'new' target " ^ (tcpp_to_string newType)) expr.cpppos + in + out objName + + | FuncInternal(func,name,join) -> + gen func; out (join ^ name); + + | FuncGlobal(name) -> + out ("::" ^ name); + | FuncExpression(expr) -> + gen expr; + ); + let sep = ref "" in + out "("; + List.iter (fun arg -> + out !sep; sep := ","; + gen arg; + ) !argsRef; + out (")" ^ !closeCall); + | CppAddressOf(e) -> + out ("&("); gen e; out ")"; + | CppFunctionAddress(klass, member) -> + let signature = ctx_function_signature ctx false member.cf_type "" in + let name = cpp_member_name_of member in + (*let void_cast = has_meta_key field.cf_meta Meta.Void in*) + out ("::cpp::Function< " ^ signature ^">(hx::AnyCast("); + out ("&::" ^(join_class_path_remap klass.cl_path "::")^ "_obj::" ^ name ); + out " ))" + + | CppGlobal(name) -> + out ("::" ^ name) + + | CppDynamicField(obj,name) -> + gen obj; + out ("->__Field(" ^ (strq name) ^ ",hx::paccDynamic)"); + + | CppArray(arrayLoc) -> (match arrayLoc with + | ArrayTyped(arrayObj,index) -> + gen arrayObj; out "->__get("; gen index; out ")" + + | ArrayPointer(arrayObj,index) -> + gen arrayObj; out ".ptr["; gen index; out "]" + + | ArrayRawPointer(arrayObj,index) -> + gen arrayObj; out "["; gen index; out "]" + + | ArrayObject(arrayObj,index,elem) -> + let close = if cpp_is_dynamic_type elem then + "" + else if elem=TCppDynamicArray then begin + out (tcpp_to_string elem ^ "( "); ")" + end else + ".StaticCast< " ^ tcpp_to_string elem ^ " >()" + in + gen arrayObj; out "->__get("; gen index; out (")" ^ close); + + | ArrayVirtual(arrayObj,index) -> + gen arrayObj; out "->__get("; gen index; out ")"; + + | ArrayDynamic(arrayObj,index) -> + gen arrayObj; out "->__GetItem("; gen index; out ")" + + | ArrayImplements(_,arrayObj,index) -> + gen arrayObj; out "->__get("; gen index; out ")"; + ) + + + | CppSet(lvalue,rvalue) -> + let close = if expr.cpptype=TCppVoid then "" else (out "("; ")" ) in + (match lvalue with + | CppVarRef( VarClosure(var)) when is_gc_element ctx (cpp_type_of ctx var.v_type) -> + out ("this->_hx_set_" ^ (cpp_var_name_of var) ^ "(HX_CTX, "); gen rvalue; out ")" + + | CppVarRef( VarThis(member)) when is_gc_element ctx (cpp_type_of ctx member.cf_type) -> + out ("this->_hx_set_" ^ (cpp_member_name_of member) ^ "(HX_CTX, "); gen rvalue; out ")" + + | CppVarRef( VarInstance(obj,member,_,"->")) when is_gc_element ctx (cpp_type_of ctx member.cf_type) -> + gen obj; out ("->_hx_set_" ^ (cpp_member_name_of member) ^ "(HX_CTX, "); gen rvalue; out ")" + | CppVarRef( VarInternal(obj,operator,member) ) -> + gen obj; out (operator ^ member) + + | CppVarRef varLoc -> + gen_val_loc varLoc true; out " = "; gen rvalue; + + + | CppArrayRef arrayLoc -> (match arrayLoc with + | ArrayObject(arrayObj, index, _) when (is_gc_element ctx TCppDynamic) -> + gen arrayObj; out "->setCtx( HX_CTX, "; gen index; out ","; gen rvalue; out ")" + | ArrayObject(arrayObj, index, _) + | ArrayTyped(arrayObj, index) + | ArrayRawPointer(arrayObj, index) -> + gen arrayObj; out "["; gen index; out "] = "; gen rvalue + | ArrayPointer(arrayObj, index) -> + gen arrayObj; out ".ptr["; gen index; out "] = "; gen rvalue + | ArrayVirtual(arrayObj, index) -> + gen arrayObj; out "->set("; gen index; out ","; gen rvalue; out ")" + + | ArrayDynamic(arrayObj, index) -> + gen arrayObj; out "->__SetItem("; gen index; out ","; gen rvalue; out ")" + + | ArrayImplements(_,arrayObj,index) -> + gen arrayObj; out "->__set("; gen index; out ","; gen rvalue; out ")" + ) + | CppDynamicRef(expr,name) -> + gen expr; out ("->__SetField(" ^ (strq name) ^ ","); gen rvalue; out ",hx::paccDynamic)" + | CppGlobalRef(name) -> out ("::" ^ name ^ " = "); + ); + out close; + + | CppCrement(incFlag,preFlag, lvalue) -> + let op = if incFlag==CppIncrement then "++" else "--" in + if (preFlag==Prefix) then out op; + gen_lvalue lvalue; + if (preFlag==Postfix) then out op + + | CppModify(op,lvalue,rvalue) -> + out (string_of_op_eq op expr.cpppos); + out "("; gen_lvalue lvalue; out ","; gen rvalue; out ")" + + | CppPosition(name,line,clazz,func) -> + out ("hx::SourceInfo(" ^ strq name ^ "," ^ string_of_int(Int32.to_int line) ^ "," ^ strq clazz ^ "," ^ strq func ^ ")") + + | CppClassOf (path,native) -> + let path = "::" ^ (join_class_path_remap (path) "::" ) in + let path = match path with + | "::Int" -> "int" + | "::Bool" -> "bool" + | x -> x in + if (native) then + out "null()" + else if (path="::Array") then + out "hx::ArrayBase::__mClass" + else + out ("hx::ClassOf< " ^ path ^ " >()") + + | CppVar(loc) -> + gen_val_loc loc false; + + + | CppClosure closure -> + out (" ::Dynamic(new _hx_Closure_" ^ (string_of_int(closure.close_id)) ^ "("); + let separator = ref "" in + (match closure.close_this with + | Some this -> + out (if this=ThisReal then "this" else "__this"); + separator := ","; + | _ -> () ); + + Hashtbl.iter (fun name value -> + out !separator; separator := ","; + out (keyword_remap name) + ) closure.close_undeclared; + out "))"; + + | CppObjectDecl (values,isStruct) -> + let length = List.length values in + let lengthStr = string_of_int length in + if (expr.cpptype!=TCppVoid) then out " ::Dynamic("; + if (isStruct) && length>0 && length<=5 then begin + out ("hx::AnonStruct" ^ lengthStr ^"_obj< " ^ + (String.concat "," (List.map (fun (_,value) -> tcpp_to_string value.cpptype) values) ) ^ + " >::Create(" ); + let sep = ref "" in + List.iter (fun (name,value) -> out (!sep ^ (strq name) ^ "," ); sep:=","; gen value ) values; + out ")"; + end else begin + out ("hx::Anon_obj::Create(" ^ lengthStr ^")"); + let sorted = List.sort (fun (_,_,h0) (_,_,h1) -> Int32.compare h0 h1 ) + (List.map (fun (name,value) -> name,value,(gen_hash32 0 name ) ) values) in + writer#push_indent; + ExtList.List.iteri (fun idx (name,value,_) -> + out ("\n" ^ spacer); writer#write_i ("->setFixed(" ^ (string_of_int idx) ^ "," ^ (strq name) ^ ","); gen value; out ")"; + ) sorted; + end; + if (expr.cpptype!=TCppVoid) then out ")"; + writer#pop_indent; + + | CppArrayDecl(exprList) when cpp_is_const_scalar_array expr.cpptype exprList -> + let arrayType = match expr.cpptype with TCppScalarArray(value) -> value | _ -> assert false in + let typeName = tcpp_to_string arrayType in + incr ctx.ctx_file_id; + + let id = "_hx_array_data_" ^ class_hash ^ "_" ^ string_of_int( !(ctx.ctx_file_id) ) in + + let out_top = ctx.ctx_writer#write_h in + out_top ("static const " ^ typeName ^ " " ^ id ^ "[] = {\n\t"); + List.iter (fun expr -> match expr.cppexpr with + | CppInt i -> out_top (Printf.sprintf "(%s)%ld," typeName i) + | CppFloat f -> out_top ( f ^ "," ) + | CppString s -> out_top ( (strq s) ^ "," ) + | CppBool b -> out_top (if b then "1," else "0,") + | _ -> assert false + ) exprList; + out_top ("\n};\n"); + out ("::Array_obj< " ^ typeName ^ " >::fromData( " ^ id ^ "," ^ list_num exprList ^ ")"); + + | CppArrayDecl(exprList) -> + let count = List.length exprList in + let countStr = string_of_int count in + let arrayType,close = match expr.cpptype with + | TCppObjectArray _ -> "::Array_obj< ::Dynamic>","" + | TCppScalarArray(value) -> "::Array_obj< " ^ (tcpp_to_string value) ^ " >","" + | TCppDynamicArray -> "::cpp::VirtualArray_obj","" + | _ -> " ::Dynamic( ::cpp::VirtualArray_obj",")" + in + out (arrayType ^ "::__new(" ^ countStr ^ ")" ); + ExtList.List.iteri ( fun idx elem -> out ("->init(" ^ (string_of_int idx) ^ ","); + gen elem; out ")" ) exprList; + out close; + + + | CppBinop( Ast.OpUShr, left, right) -> + out "hx::UShr("; gen left; out ","; gen right; out ")"; + + | CppBinop( Ast.OpMod, left, right) -> + if is_constant_zero right then begin + out "hx::Mod("; gen left; out ",(double)( "; gen right; out " ))"; + end else begin + out "hx::Mod("; gen left; out ","; gen right; out ")"; + end + + | CppBinop( Ast.OpDiv, left, right) when is_constant_zero right -> + out "hx::DivByZero("; gen left; out ")"; + + | CppBinop(op, left, right) -> + let op = string_of_op op expr.cpppos in + let castOpen, castClose = (match op with + | ">>" | "<<" | "&" | "|" | "^" -> "(int)", "" + | "&&" | "||" -> "(bool)", "" + | "/" -> "(Float)", "" + | _ -> "","") in + out "("; + out castOpen; gen left; out castClose; + out (" " ^ op ^ " "); + out castOpen; gen right; out castClose; + out ")"; + | CppCompare(op, left, right) -> + out ("hx::" ^ op ^ "( "); + gen left; + out (","); + gen right; + out (" )"); + | CppNullCompare(op, left) -> + out ("hx::" ^ op ^ "( "); gen left; out (" )"); + + | CppThrow(value) -> + out "HX_STACK_DO_THROW("; gen value; out ")"; + + | CppReturn None -> out "return"; + | CppReturn Some value -> out "return "; gen value; + + | CppEnumField(enum,field) -> + out ((string_of_path enum.e_path) ^ "::" ^ (cpp_enum_name_of field) ^ "_dyn()" ); + + | CppEnumParameter(obj,field,index) -> + let valueType = cpp_type_of ctx (get_nth_type field index) in + let baseType = cpp_base_type_of valueType in + gen obj; + if cpp_is_dynamic_type obj.cpptype then + out ".StaticCast< ::hx::EnumBase >()"; + out ( "->_hx_get" ^ baseType ^ "(" ^ (string_of_int index) ^ ")"); + (match valueType with + | TCppObjectArray _ + | TCppScalarArray _ + | TCppDynamicArray + | TCppClass + | TCppEnum _ + | TCppInst _ -> out (".StaticCast< " ^ (tcpp_to_string valueType ) ^ " >()") + | _ ->() + ) + + | CppIntSwitch(condition, cases, defVal) -> + out "switch((int)("; gen condition; out "))"; + writer#begin_block; + List.iter (fun (values,expr) -> + out spacer; writer#write_i ""; + List.iter (fun value -> out ("case (int)" ^ (Printf.sprintf "%ld" value) ^ ": " ) ) values; + gen expr; + out spacer; writer#write_i "break;\n"; + ) cases; + (match defVal with + | Some expr -> output_i "default:"; gen expr; | _ -> () ); + out spacer; + writer#end_block; + | CppSwitch(condition, conditionType, cases, optional_default, label) -> + let tmp_name = "_hx_switch_" ^ (string_of_int !tempId) in + incr tempId; + out ( (tcpp_to_string conditionType) ^ " " ^ tmp_name ^ " = " ); + gen condition; + out ";\n"; + List.iter (fun (cases,expression) -> + output_i "if ( "; + let or_str = ref "" in + List.iter (fun value -> + out (!or_str ^ " (" ^ tmp_name ^ "=="); gen value; out ")"; + or_str := " || "; + ) cases; + out (" )"); + gen expression; + ) cases; + (match optional_default with | None -> () + | Some default -> + output_i "/* default */"; + gen default; + ); + output_i ((label_name label) ^ ":") + + | CppUnop(unop,value) -> + out (match unop with + | CppNot -> "!" + | CppNeg -> "-" + | CppNegBits -> "~" + ); + out "("; gen value; out ")" + + | CppWhile(condition, block, while_flag, loop_id) -> + (match while_flag with + | NormalWhile -> + out "while("; gen condition; out (")"); + gen block; + | DoWhile -> + out ("do "); + gen block; + out "while("; gen condition; out ")" + ); + if loop_id > -1 then output_i ((label_name loop_id) ^ ":"); + + | CppIf (condition,block,None) -> + out "if ("; gen condition; out (") "); + gen block; + + | CppIf (condition,block,Some elze) when expr.cpptype = TCppVoid -> + out "if ("; gen condition; out (") "); + gen block; + output_i ("else "); + gen elze; + + | CppIf (condition,block,Some elze) -> + gen condition; out " ? "; gen block; out " : "; gen elze; + + | CppFor (tvar, init, loop) -> + let varType = cpp_var_type_of ctx tvar in + out ("for(::cpp::FastIterator_obj< " ^ varType ^ + " > *__it = ::cpp::CreateFastIterator< "^ varType ^ " >("); + gen init; + out ("); __it->hasNext(); )"); + let prologue = fun _ -> + output_i ( varType ^ " " ^ (cpp_var_name_of tvar) ^ " = __it->next();\n" ); + in + gen_with_injection (mk_injection prologue "" "") loop; + + + | CppTry(block,catches) -> + let prologue = function _ -> + ExtList.List.iteri (fun idx (v,_) -> + output_i ("HX_STACK_CATCHABLE(" ^ cpp_macro_var_type_of ctx v ^ ", " ^ string_of_int idx ^ ");\n") + ) catches + in + out ("try "); + gen_with_injection (mk_injection prologue "" "" ) block; + if (List.length catches > 0 ) then begin + output_i "catch( ::Dynamic _hx_e)"; + writer#begin_block; + + let seen_dynamic = ref false in + let else_str = ref "" in + List.iter (fun (v,catch) -> + let type_name = cpp_var_type_of ctx v in + if (type_name="Dynamic") then begin + seen_dynamic := true; + output_i !else_str; + end else + output_i (!else_str ^ "if (_hx_e.IsClass< " ^ type_name ^ " >() )"); + let prologue = function _ -> + output_i "HX_STACK_BEGIN_CATCH\n"; + output_i (type_name ^ " " ^ (cpp_var_name_of v) ^ " = _hx_e;\n"); + in + gen_with_injection (mk_injection prologue "" "") catch; + else_str := "else "; + ) catches; + + if (not !seen_dynamic) then begin + output_i "else {\n"; + output_i "\tHX_STACK_DO_THROW(_hx_e);\n"; + output_i "}\n"; + end; + out spacer; + writer#end_block; + end + + | CppCode(value, exprs) -> + Codegen.interpolate_code ctx.ctx_common (format_code value) exprs out (fun e -> gen e) expr.cpppos + | CppTCast(expr,cppType) -> + let toType = tcpp_to_string cppType in + if toType="Dynamic" then + (out " ::Dynamic("; gen expr; out ")") + else + (out ("hx::TCast< " ^ toType ^ " >::cast("); gen expr; out ")") + + | CppCastStatic(expr,toType) -> + let close = match expr.cpptype with + | TCppDynamic -> "" + | _ -> out "Dynamic( "; ")" + in + gen expr; out (close ^ ".StaticCast< " ^ tcpp_to_string toType ^" >()") + + | CppCast(expr,toType) -> + (match expr.cppexpr, expr.cpptype with + | CppCall( FuncInternal _, _), _ -> + gen expr; out (".StaticCast< " ^ tcpp_to_string toType ^" >()") + | _, TCppObjC(_) + | _, TCppObjCBlock(_) -> + out ("( ("^ tcpp_to_string toType ^")((id) ( "); gen expr; out (") ))") + | _,_ -> + (match toType with + | TCppObjectPtr -> out ("hx::DynamicPtr("); gen expr; out (")") + | t -> out ("( ("^ tcpp_to_string t ^")("); gen expr; out (") )") + ) + ) + + | CppCastScalar(expr,scalar) -> + out ("( ("^scalar^")("); gen expr; out (") )"); + + | CppCastVariant(expr) -> + out " ::Dynamic("; gen expr; out ")"; + + | CppCastObjC(expr,klass) -> + let path = join_class_path_remap klass.cl_path "::" in + let toType = if klass.cl_interface then "id < " ^ path ^ ">" else path ^ " *" in + out ("( (" ^ toType ^ ") (id) ("); gen expr; out ") )" + + | CppCastObjCBlock(expr,args,ret) -> + out (tcpp_objc_block_struct args ret ^ "::create( "); + gen expr; + out ")" + + | CppCastProtocol(expr,klass) -> + out ( (join_class_path_remap klass.cl_path "::" ) ^ "_obj::_hx_toProtocol( "); + gen expr; + out ")" + + | CppCastNative(expr) -> + out "("; gen expr; out ").mPtr" + ); + if (ctx.ctx_debug_level >= 3) then + out ("/* " ^ (s_tcpp expr.cppexpr) ^ ":" ^ tcpp_to_string expr.cpptype ^ " */") + + and gen expr = + gen_with_injection None expr + + and gen_lvalue lvalue = + match lvalue with + | CppVarRef varLoc -> + gen_val_loc varLoc true + | CppArrayRef arrayLoc -> (match arrayLoc with + | ArrayObject(arrayObj, index, _) -> + out "hx::IndexRef("; gen arrayObj; out ".mPtr,"; gen index; out ")"; + | ArrayTyped(arrayObj, index) -> + gen arrayObj; out "["; gen index; out "]"; + | ArrayPointer(arrayObj, index) -> + gen arrayObj; out ".ptr["; gen index; out "]"; + | ArrayRawPointer(arrayObj, index) -> + gen arrayObj; out "["; gen index; out "]"; + | ArrayVirtual(arrayObj, index) + | ArrayDynamic(arrayObj, index) -> + out "hx::IndexRef("; gen arrayObj; out ".mPtr,"; gen index; out ")"; + | ArrayImplements(_,arrayObj,index) -> + out "hx::__ArrayImplRef("; gen arrayObj; out ","; gen index; out ")"; + ) + | CppGlobalRef(name) -> out ("::" ^ name) + | CppDynamicRef(expr,name) -> + let objPtr = match expr.cpptype with + | TCppVariant -> "getObject()" + | _ -> ".mPtr" + in + out "hx::FieldRef(("; gen expr ; out (")" ^ objPtr ^ "," ^ strq name ^ ")") + + and gen_val_loc loc lvalue = + match loc with + | VarClosure(var) -> + out (cpp_var_name_of var) + | VarLocal(local) -> out (cpp_var_name_of local) + | VarStatic(clazz,objc,member) -> + let rename = get_meta_string member.cf_meta Meta.Native in + if rename <> "" then + out rename + else if objc then + (out ( (join_class_path_remap clazz.cl_path "::") ); out ("." ^ (cpp_member_name_of member))) + else + (out (cpp_class_name clazz ); out ("::" ^ (cpp_member_name_of member))) + | VarThis(member) -> + out ("this->" ^ (cpp_member_name_of member)) + | VarInstance(obj,member,_,operator) -> + gen obj; out (operator ^ (cpp_member_name_of member)) + | VarInternal(obj,operator,member) -> + gen obj; out (operator ^ member) + | VarInterface(obj,member) -> + gen obj; out ("->" ^ (cpp_member_name_of member) ^ "_get()" ) + + and string_of_op_eq op pos = match op with + | OpAdd -> "hx::AddEq" + | OpMult -> "hx::MultEq" + | OpDiv -> "hx::DivEq" + | OpSub -> "hx::SubEq" + | OpAnd -> "hx::AndEq" + | OpOr -> "hx::OrEq" + | OpXor -> "hx::XorEq" + | OpShl -> "hx::ShlEq" + | OpShr -> "hx::ShrEq" + | OpUShr -> "hx::UShrEq" + | OpMod -> "hx::ModEq" + | _ -> abort "Bad assign op" pos + and string_of_op op pos = match op with + | OpAdd -> "+" + | OpMult -> "*" + | OpDiv -> "/" + | OpSub -> "-" + | OpEq -> "==" + | OpNotEq -> "!=" + | OpGt -> ">" + | OpGte -> ">=" + | OpLt -> "<" + | OpLte -> "<=" + | OpAnd -> "&" + | OpOr -> "|" + | OpXor -> "^" + | OpBoolAnd -> "&&" + | OpBoolOr -> "||" + | OpShl -> "<<" + | OpShr -> ">>" + | OpUShr -> "<<<" + | OpMod -> "%" + | OpInterval -> "..." + | OpArrow -> "->" + | OpAssign | OpAssignOp _ -> abort "Unprocessed OpAssign" pos + and string_of_path path = + "::" ^ (join_class_path_remap path "::") ^ "_obj" + + and gen_closure closure = + let argc = Hashtbl.length closure.close_undeclared in + let size = string_of_int argc in + if argc >= 62 then (* Limited by c++ macro size of 128 args *) + abort "Too many capture variables" closure.close_expr.cpppos; + if argc >= 20 || (List.length closure.close_args) >= 20 then + writer#add_big_closures; + let argsCount = list_num closure.close_args in + output_i ("HX_BEGIN_LOCAL_FUNC_S" ^ size ^ "("); + out (if closure.close_this != None then "hx::LocalThisFunc," else "hx::LocalFunc,"); + out ("_hx_Closure_" ^ (string_of_int closure.close_id) ); + Hashtbl.iter (fun name var -> + out ("," ^ (cpp_macro_var_type_of ctx var) ^ "," ^ (keyword_remap name)); + ) closure.close_undeclared; + out (") HXARGC(" ^ argsCount ^")\n"); + + let func_type = tcpp_to_string closure.close_type in + output_i (func_type ^ " _hx_run(" ^ (cpp_arg_list ctx closure.close_args "__o_") ^ ")"); + + let prologue = function gc_stack -> + cpp_gen_default_values ctx closure.close_args "__o_"; + hx_stack_push ctx output_i class_name func_name closure.close_expr.cpppos gc_stack; + if (ctx.ctx_debug_level>=2) then begin + if (closure.close_this != None) then + output_i ("HX_STACK_THIS(__this.mPtr)\n"); + List.iter (fun (v,_) -> output_i ("HX_STACK_ARG(" ^ (cpp_var_name_of v) ^ ",\"" ^ (cpp_debug_name_of v) ^"\")\n") ) + (List.filter (cpp_debug_var_visible ctx) closure.close_args); + end + in + + gen_with_injection (mk_injection prologue "" "") closure.close_expr; + + let return = match closure.close_type with TCppVoid -> "(void)" | _ -> "return" in + + output_i ("HX_END_LOCAL_FUNC" ^ argsCount ^ "(" ^ return ^ ")\n\n"); + in + + + (*out "\t";*) + + gen_with_injection injection cppTree; + +;; + +(* } *) + + +let gen_cpp_function_body ctx clazz is_static func_name function_def head_code tail_code no_debug = + let output = ctx.ctx_output in + let dot_name = join_class_path clazz.cl_path "." in + if no_debug then ctx.ctx_debug_level <- 0; + let prologue = function gc_stack -> + let spacer = if no_debug then "\t" else " \t" in + let output_i = fun s -> output (spacer ^ s) in + ctx_default_values ctx function_def.tf_args "__o_"; + hx_stack_push ctx output_i dot_name func_name function_def.tf_expr.epos gc_stack; + if ctx.ctx_debug_level >= 2 then begin + if (not is_static) + then output_i ("HX_STACK_THIS(" ^ (if ctx.ctx_real_this_ptr then "this" else "__this") ^")\n"); + List.iter (fun (v,_) -> if not (cpp_no_debug_synbol ctx v) then + output_i ("HX_STACK_ARG(" ^ (cpp_var_name_of v) ^ ",\"" ^ v.v_name ^"\")\n") ) function_def.tf_args; + end; + if (head_code<>"") then + output_i (head_code ^ "\n"); + in + let args = List.map fst function_def.tf_args in + + let injection = mk_injection prologue "" tail_code in + gen_cpp_ast_expression_tree ctx dot_name func_name args injection (mk_block function_def.tf_expr); +;; + +let gen_cpp_init ctx dot_name func_name var_name expr = + let output = ctx.ctx_output in + let prologue = function gc_stack -> + let spacer = if ctx.ctx_debug_level > 0 then " \t" else "\t" in + let output_i = fun s -> output (spacer ^ s) in + hx_stack_push ctx output_i dot_name func_name expr.epos gc_stack; + in + let injection = mk_injection prologue var_name "" in + gen_cpp_ast_expression_tree ctx dot_name func_name [] injection (mk_block expr); +;; + + +(* +let is_dynamic_haxe_method f = + match follow f.cf_type with + | TFun _ when f.cf_expr = None -> true + | _ -> + (match f.cf_expr with + | Some { eexpr = TFunction fd } when f.cf_set = MethodAccess true -> true + | Some { eexpr = TFunction fd } when f.cf_set = NormalAccess -> true + | _ -> false);; +*) + +let is_dynamic_haxe_method f = + (match f.cf_expr, f.cf_kind with + | Some { eexpr = TFunction _ }, (Var _ | Method MethDynamic) -> true + | _ -> false);; + + +let is_data_member field = + match field.cf_expr with + | Some { eexpr = TFunction function_def } -> is_dynamic_haxe_method field + | _ -> true;; + + +let is_override class_def field = + List.exists (fun f -> f.cf_name = field) class_def.cl_overrides +;; + +let current_virtual_functions clazz = + List.rev (List.fold_left (fun result elem -> match follow elem.cf_type, elem.cf_kind with + | _, Method MethDynamic -> result + | TFun (args,return_type), Method _ when not (is_override clazz elem.cf_name ) -> (elem,args,return_type) :: result + | _,_ -> result ) [] clazz.cl_ordered_fields) +;; + +let all_virtual_functions clazz = + let rec all_virtual_functions clazz = + (match clazz.cl_super with + | Some def -> all_virtual_functions (fst def) + | _ -> [] ) @ current_virtual_functions clazz + in + all_virtual_functions clazz +;; + + +let rec unreflective_type t = + match follow t with + | TInst (klass,_) -> Meta.has Meta.Unreflective klass.cl_meta + | TFun (args,ret) -> + List.fold_left (fun result (_,_,t) -> result || (unreflective_type t)) (unreflective_type ret) args; + | _ -> false +;; + +let reflective class_def field = not ( + (Meta.has Meta.NativeGen class_def.cl_meta) || + (Meta.has Meta.Unreflective class_def.cl_meta) || + (Meta.has Meta.Unreflective field.cf_meta) || + unreflective_type field.cf_type + ) +;; + + + + + +let field_arg_count field = + match follow field.cf_type, field.cf_kind with + | _, Method MethDynamic -> -1 + | TFun (args,return_type), Method _ -> List.length args + | _,_ -> -1 +;; + +let native_field_name_remap is_static field = + let remap_name = keyword_remap field.cf_name in + if not is_static then + remap_name + else begin + let nativeImpl = get_meta_string field.cf_meta Meta.Native in + if nativeImpl<>"" then begin + let r = Str.regexp "^[a-zA-Z_0-9]+$" in + if Str.string_match r remap_name 0 then + "_hx_" ^ remap_name + else + "_hx_f" ^ (gen_hash 0 remap_name) + end else + remap_name + end +;; + + +let gen_field ctx class_def class_name ptr_name dot_name is_static is_interface field = + let output = ctx.ctx_output in + ctx.ctx_real_this_ptr <- not is_static; + let remap_name = keyword_remap field.cf_name in + let decl = get_meta_string field.cf_meta Meta.Decl in + let has_decl = decl <> "" in + if (is_interface) then begin + (* Just the dynamic glue - not even that ... *) + () + end else (match field.cf_expr with + (* Function field *) + | Some { eexpr = TFunction function_def } -> + let return_type = (ctx_type_string ctx function_def.tf_type) in + let nargs = string_of_int (List.length function_def.tf_args) in + let is_void = (cpp_type_of ctx function_def.tf_type ) = TCppVoid in + let ret = if is_void then "(void)" else "return " in + let orig_debug = ctx.ctx_debug_level in + let no_debug = has_meta_key field.cf_meta Meta.NoDebug in + + if (not (is_dynamic_haxe_method field)) then begin + (* The actual function definition *) + let nativeImpl = get_meta_string field.cf_meta Meta.Native in + let remap_name = native_field_name_remap is_static field in + output (if is_void then "void" else return_type ); + output (" " ^ class_name ^ "::" ^ remap_name ^ "(" ); + output (ctx_arg_list ctx function_def.tf_args "__o_"); + output ")"; + ctx.ctx_real_this_ptr <- true; + let code = (get_code field.cf_meta Meta.FunctionCode) in + let tail_code = (get_code field.cf_meta Meta.FunctionTailCode) in + + if nativeImpl<>"" && is_static then begin + output " {\n"; + output ("\t" ^ ret ^ "::" ^ nativeImpl ^ "(" ^ (ctx_arg_list_name ctx function_def.tf_args "__o_") ^ ");\n"); + output "}\n\n"; + end else + gen_cpp_function_body ctx class_def is_static field.cf_name function_def code tail_code no_debug; + + output "\n\n"; + let nonVirtual = has_meta_key field.cf_meta Meta.NonVirtual in + let doDynamic = (nonVirtual || not (is_override class_def field.cf_name ) ) && (reflective class_def field ) in + (* generate dynamic version too ... *) + if ( doDynamic ) then begin + if (is_static) then output "STATIC_"; + output ("HX_DEFINE_DYNAMIC_FUNC" ^ nargs ^ "(" ^ class_name ^ "," ^ + remap_name ^ "," ^ ret ^ ")\n\n"); + end; + + end else begin + ctx.ctx_real_this_ptr <- false; + let func_name = "__default_" ^ (remap_name) in + output ("HX_BEGIN_DEFAULT_FUNC(" ^ func_name ^ "," ^ class_name ^ ")\n"); + output return_type; + output (" _hx_run(" ^ (ctx_arg_list ctx function_def.tf_args "__o_") ^ ")"); + gen_cpp_function_body ctx class_def is_static func_name function_def "" "" no_debug; + + output ("HX_END_LOCAL_FUNC" ^ nargs ^ "(" ^ ret ^ ")\n"); + output ("HX_END_DEFAULT_FUNC\n\n"); + + if (is_static) then + output ( "::Dynamic " ^ class_name ^ "::" ^ remap_name ^ ";\n\n"); + end; + ctx.ctx_debug_level <- orig_debug + + (* Data field *) + | _ when has_decl -> + if is_static then begin + output ( class_name ^ "::" ^ remap_name ^ "_decl "); + output ( " " ^ class_name ^ "::" ^ remap_name ^ ";\n\n"); + end + | _ -> + if is_static && (not (is_extern_field field)) then begin + gen_type ctx field.cf_type; + output ( " " ^ class_name ^ "::" ^ remap_name ^ ";\n\n"); + end + ) + ;; + + + + + +let gen_field_init ctx class_def field = + let dot_name = join_class_path class_def.cl_path "." in + let output = ctx.ctx_output in + let remap_name = keyword_remap field.cf_name in + match field.cf_expr with + (* Function field *) + | Some { eexpr = TFunction function_def } -> + if (is_dynamic_haxe_method field) then begin + let func_name = "__default_" ^ (remap_name) in + output ( "\t" ^ remap_name ^ " = new " ^ func_name ^ ";\n\n" ); + end + + (* Data field *) + | Some expr -> + let var_name = ( match remap_name with + | "__meta__" -> "__mClass->__meta__" + | "__rtti" -> "__mClass->__rtti__" + | _ -> remap_name ) in + + gen_cpp_init ctx dot_name "boot" (var_name ^ " = ") expr + | _ -> () +;; + + +let cpp_interface_impl_name ctx interface = + "_hx_" ^ (join_class_path interface.cl_path "_" ) +;; + + +let cpp_class_hash interface = + gen_hash 0 (join_class_path interface.cl_path "::" ) +;; + + + +let has_field_init field = + match field.cf_expr with + (* Function field *) + | Some { eexpr = TFunction function_def } -> is_dynamic_haxe_method field + (* Data field *) + | Some _ -> true + | _ -> false +;; + + +let gen_member_def ctx class_def is_static is_interface field = + let output = ctx.ctx_output in + let remap_name = keyword_remap field.cf_name in + let nativeGen = has_meta_key class_def.cl_meta Meta.NativeGen in + + if (is_interface) then begin + match follow field.cf_type, field.cf_kind with + | _, Method MethDynamic -> () + | TFun (args,return_type), Method _ -> + let gen_args = ctx_tfun_arg_list ctx true in + if is_static || nativeGen then begin + output ( (if (not is_static) then " virtual " else " " ) ^ (ctx_type_string ctx return_type) ); + output (" " ^ remap_name ^ "( " ); + output (gen_args args); + output (if (not is_static) then ")=0;\n" else ");\n"); + if (reflective class_def field) then begin + if (Common.defined ctx.ctx_common Define.DynamicInterfaceClosures) then + output (" inline ::Dynamic " ^ remap_name ^ "_dyn() { return __Field( " ^ (str field.cf_name) ^ ", hx::paccDynamic); }\n" ) + else + output (" virtual ::Dynamic " ^ remap_name ^ "_dyn()=0;\n" ); + end + end else begin + let argList = gen_args args in + let returnType = ctx_type_string ctx return_type in + let returnStr = if returnType = "void" then "" else "return " in + let commaArgList = if argList="" then argList else "," ^ argList in + let cast = "static_cast< ::" ^ join_class_path_remap class_def.cl_path "::" ^ "_obj *>" in + output (" " ^ returnType ^ " (hx::Object :: *_hx_" ^ remap_name ^ ")(" ^ argList ^ "); \n"); + output (" static inline " ^ returnType ^ " " ^ remap_name ^ "( ::Dynamic _hx_" ^ commaArgList ^ ") {\n"); + output (" " ^ returnStr ^ "(_hx_.mPtr->*( " ^ cast ^ "(_hx_.mPtr->_hx_getInterface(" ^ (cpp_class_hash class_def) ^ ")))->_hx_" ^ remap_name ^ ")(" ^ cpp_arg_names args ^ ");\n }\n" ); + end + | _ -> ( ) + end else begin + let decl = get_meta_string field.cf_meta Meta.Decl in + let has_decl = decl <> "" in + if (has_decl) then + output ( " typedef " ^ decl ^ ";\n" ); + output (if is_static then "\t\tstatic " else "\t\t"); + (match field.cf_expr with + | Some { eexpr = TFunction function_def } -> + let nonVirtual = has_meta_key field.cf_meta Meta.NonVirtual in + let doDynamic = (nonVirtual || not (is_override class_def field.cf_name ) ) && (reflective class_def field ) in + if ( is_dynamic_haxe_method field ) then begin + if ( doDynamic ) then begin + output ("::Dynamic " ^ remap_name ^ ";\n"); + if (not is_static) && (is_gc_element ctx TCppDynamic) then + output ("\t\tinline ::Dynamic _hx_set_" ^ remap_name ^ "(hx::Ctx *_hx_ctx,::Dynamic _hx_v) { HX_OBJ_WB(this,_hx_v) return " ^ remap_name ^ "=_hx_v; }\n"); + output (if is_static then "\t\tstatic " else "\t\t"); + output ("inline ::Dynamic &" ^ remap_name ^ "_dyn() " ^ "{return " ^ remap_name^ "; }\n") + end + end else begin + let return_type = (ctx_type_string ctx function_def.tf_type) in + if ( not is_static && not nonVirtual ) then begin + let scriptable = Common.defined ctx.ctx_common Define.Scriptable in + if (not (is_internal_member field.cf_name) && not scriptable ) then begin + let key = (join_class_path class_def.cl_path ".") ^ "." ^ field.cf_name in + try output (Hashtbl.find ctx.ctx_class_member_types key) with Not_found -> () + end else + output "virtual "; + end; + output (if return_type="Void" then "void" else return_type ); + + let remap_name = native_field_name_remap is_static field in + output (" " ^ remap_name ^ "(" ); + output (ctx_arg_list ctx function_def.tf_args "" ); + output ");\n"; + if ( doDynamic ) then begin + output (if is_static then "\t\tstatic " else "\t\t"); + output ("::Dynamic " ^ remap_name ^ "_dyn();\n" ) + end; + end; + output "\n"; + | _ when has_decl -> + output ( remap_name ^ "_decl " ^ remap_name ^ ";\n" ); + (* Variable access *) + | _ -> + (* Variable access *) + let tcpp = cpp_type_of ctx field.cf_type in + let tcppStr = tcpp_to_string tcpp in + if not is_static && only_stack_access ctx field.cf_type then + abort ("Variables of type " ^ tcppStr ^ " may not be used as members") field.cf_pos; + + output (tcppStr ^ " " ^ remap_name ^ ";\n" ); + if not is_static && (is_gc_element ctx tcpp) then + output ("\t\tinline " ^ tcppStr ^ " _hx_set_" ^ remap_name ^ "(hx::Ctx *_hx_ctx," ^ tcppStr ^ " _hx_v) { HX_OBJ_WB(this,_hx_v) return " ^ remap_name ^ "=_hx_v; }\n"); + + (* Add a "dyn" function for variable to unify variable/function access *) + (match follow field.cf_type with + | _ when nativeGen -> () + | TFun (_,_) -> + output (if is_static then "\t\tstatic " else "\t\t"); + output ("Dynamic " ^ remap_name ^ "_dyn() { return " ^ remap_name ^ ";}\n" ) + | _ -> (match field.cf_kind with + | Var { v_read = AccCall } when (not is_static) && (is_dynamic_accessor ("get_" ^ field.cf_name) "get" field class_def) -> + output ("\t\tDynamic get_" ^ field.cf_name ^ ";\n" ) + | _ -> () + ); + (match field.cf_kind with + | Var { v_write = AccCall } when (not is_static) && (is_dynamic_accessor ("set_" ^ field.cf_name) "set" field class_def) -> + output ("\t\tDynamic set_" ^ field.cf_name ^ ";\n" ) + | _ -> () + ) + ) + ); + end + ;; + +let path_of_string path = + ["@verbatim"], path +;; + + +(* + Get a list of all classes referred to by the class/enum definition + These are used for "#include"ing the appropriate header files, + or for building the dependencies in the Build.xml file +*) +let find_referenced_types_flags ctx obj field_name super_deps constructor_deps header_only for_depends include_super_args = + let types = ref PMap.empty in + let rec add_type_flag isNative in_path = + if ( not (PMap.mem in_path !types)) then begin + types := (PMap.add in_path isNative !types); + try + List.iter (add_type_flag isNative) (Hashtbl.find super_deps in_path); + with Not_found -> () + end + and add_type in_path = + add_type_flag false in_path + in + let add_extern_type decl = + let tinfo = t_infos decl in + let include_file = get_meta_string_path tinfo.mt_meta (if for_depends then Meta.Depend else Meta.Include) in + if (include_file<>"") then + add_type ( path_of_string include_file ) + else if (not for_depends) && (has_meta_key tinfo.mt_meta Meta.Include) then + add_type tinfo.mt_path + in + + let add_extern_class klass = + add_extern_type (TClassDecl klass) + in + let add_native_gen_class klass = + let include_file = get_meta_string_path klass.cl_meta (if for_depends then Meta.Depend else Meta.Include) in + if (include_file<>"") then + add_type ( path_of_string include_file ) + else if for_depends then + add_type klass.cl_path + else begin + let path = klass.cl_path in + if not klass.cl_interface then + (* Always include native struct headers directly ... *) + add_type ( path_of_string ( (join_class_path path "/") ^ ".h") ) + else begin + add_type_flag true klass.cl_path + end + end + in + let visited = ref [] in + let rec visit_type in_type = + if not (List.exists (fun t2 -> Type.fast_eq in_type t2) !visited) then begin + visited := in_type :: !visited; + begin match follow in_type with + | TMono r -> (match !r with None -> () | Some t -> visit_type t) + | TEnum (enum,params) -> add_type enum.e_path + (* If a class has a template parameter, then we treat it as dynamic - except + for the Array, Class, FastIterator or Pointer classes, for which we do a fully typed object *) + | TInst (klass,params) -> + (match klass.cl_path with + | ([],"Array") | ([],"Class") | (["cpp"],"FastIterator") + | (["cpp"],"Pointer") | (["cpp"],"ConstPointer") | (["cpp"],"Function") + | (["cpp"],"RawPointer") | (["cpp"],"RawConstPointer") -> List.iter visit_type params + | _ when is_native_gen_class klass -> add_native_gen_class klass + | _ when is_extern_class klass -> add_extern_class klass + | _ -> (match klass.cl_kind with KTypeParameter _ -> () | _ -> add_type klass.cl_path); + ) + | TAbstract (a,params) when is_scalar_abstract a -> + add_extern_type (TAbstractDecl a) + | TFun (args,haxe_type) -> visit_type haxe_type; + List.iter (fun (_,_,t) -> visit_type t; ) args; + | _ -> () + end; + visited := List.tl !visited; + end + in + let rec visit_params expression = + begin + let rec visit_expression = fun expression -> + (* Expand out TTypeExpr (ie, the name of a class, as used for static access etc ... *) + (match expression.eexpr with + | TTypeExpr type_def -> ( match type_def with + | TClassDecl class_def when is_native_gen_class class_def -> add_native_gen_class class_def + | TClassDecl class_def when is_extern_class class_def -> add_extern_class class_def + | _ -> add_type (t_path type_def) + ) + + (* Must visit the types, Type.iter will visit the expressions ... *) + | TTry (e,catches) -> + List.iter (fun (v,_) -> visit_type v.v_type) catches + (* Must visit type too, Type.iter will visit the expressions ... *) + | TNew (klass,params,_) -> begin + visit_type (TInst (klass,params)); + try + let construct_type = Hashtbl.find constructor_deps klass.cl_path in + visit_type construct_type.cf_type + with Not_found -> (); + end + (* Must visit type too, Type.iter will visit the expressions ... *) + | TVar (v,_) -> + visit_type v.v_type + (* Must visit enum type too, Type.iter will visit the expressions ... *) + | TEnumParameter (_,ef,_) -> visit_type (follow ef.ef_type) + (* Must visit args too, Type.iter will visit the expressions ... *) + | TFunction func_def -> + List.iter (fun (v,_) -> visit_type v.v_type) func_def.tf_args; + + | TField( obj, field ) -> + (match field with + | FInstance (clazz,params,_) + | FClosure (Some (clazz,params),_) -> + visit_type (TInst (clazz,params)) + | _ -> () + ) + | TConst TSuper -> + (match follow expression.etype with + | TInst (klass,params) -> + (try let construct_type = Hashtbl.find constructor_deps klass.cl_path in + visit_type construct_type.cf_type + with Not_found -> () ) + | _ -> print_endline ("TSuper : Odd etype ?" ^ ( (ctx_type_string ctx expression.etype)) ) + ) + | _ -> () + ); + Type.iter visit_expression expression; + visit_type (follow expression.etype) + in + visit_expression expression + end + in + let visit_field field = + (* Add the type of the expression ... *) + visit_type field.cf_type; + if (not header_only) then + (match field.cf_expr with + | Some expression -> visit_params expression | _ -> ()); + in + let visit_class class_def = + let fields = List.append class_def.cl_ordered_fields class_def.cl_ordered_statics in + let fields_and_constructor = List.append fields + (match class_def.cl_constructor with | Some expr -> [expr] | _ -> [] ) in + let fields_and_constructor = + if field_name="*" then + fields_and_constructor + else + List.filter (fun f -> f.cf_name=field_name) fields_and_constructor in + List.iter visit_field fields_and_constructor; + if (include_super_args) then + List.iter visit_field (List.map (fun (a,_,_) -> a ) (all_virtual_functions class_def )); + + (* Add super & interfaces *) + if is_native_gen_class class_def then + add_native_gen_class class_def + else + add_type class_def.cl_path; + in + let visit_enum enum_def = + add_type enum_def.e_path; + PMap.iter (fun _ constructor -> + (match constructor.ef_type with + | TFun (args,_) -> + List.iter (fun (_,_,t) -> visit_type t; ) args; + | _ -> () ); + ) enum_def.e_constrs; + if (not header_only) then begin + let meta = Codegen.build_metadata ctx.ctx_common (TEnumDecl enum_def) in + match meta with Some expr -> visit_params expr | _ -> (); + end; + in + let inc_cmp i1 i2 = + String.compare (join_class_path i1 ".") (join_class_path i2 ".") + in + + (* Body of main function *) + (match obj with + | TClassDecl class_def -> visit_class class_def; + (match class_def.cl_init with Some expression -> visit_params expression | _ -> ()) + | TEnumDecl enum_def -> visit_enum enum_def + | TTypeDecl _ | TAbstractDecl _ -> (* These are expanded *) ()); + + let deps = List.sort inc_cmp (List.filter (fun path -> (include_class_header path) ) (pmap_keys !types)) in + let flags = List.map (fun dep -> PMap.find dep !types) deps in + deps, flags +;; + +let find_referenced_types ctx obj super_deps constructor_deps header_only for_depends include_super_args = + let deps,_ = find_referenced_types_flags ctx obj "*" super_deps constructor_deps header_only for_depends include_super_args in + deps +;; + + +let generate_main_header output_main = + output_main "#include \n\n"; + output_main "#include \n\n"; + output_main "extern \"C\" void __hxcpp_main();\n\n"; + output_main "extern \"C\" void __hxcpp_lib_main();\n\n" +;; + +let generate_main_footer1 output_main = + output_main "void __hxcpp_main() {\n";; + +let generate_main_footer2 output_main = + output_main " }\n\n"; + output_main "void __hxcpp_lib_main() {\n"; + output_main " HX_TOP_OF_STACK\n"; + output_main " hx::Boot();\n"; + output_main " __boot_all();\n"; + output_main " __hxcpp_main();\n"; + output_main " }\n" +;; + + +let generate_main ctx super_deps class_def = + let common_ctx = ctx.ctx_common in + (* main routine should be a single static function *) + let main_expression = + (match class_def.cl_ordered_statics with + | [{ cf_expr = Some expression }] -> expression; + | _ -> assert false ) in + ignore(find_referenced_types ctx (TClassDecl class_def) super_deps (Hashtbl.create 0) false false false); + let depend_referenced = find_referenced_types ctx (TClassDecl class_def) super_deps (Hashtbl.create 0) false true false in + let generate_startup filename is_main = + (*make_class_directories base_dir ( "src" :: []);*) + let cpp_file = new_cpp_file common_ctx common_ctx.file ([],filename) in + let output_main = (cpp_file#write) in + + generate_main_header (cpp_file#write_h); + + List.iter ( add_include cpp_file ) depend_referenced; + output_main "\n\n"; + + if is_main then output_main "\n#include \n\n"; + + generate_main_footer1 output_main; + + let ctx = file_context ctx cpp_file 1 false in + gen_cpp_init ctx "hxcpp" "__hxcpp_main" "" main_expression; + + + generate_main_footer2 output_main; + cpp_file#close; + in + generate_startup "__main__" true; + generate_startup "__lib__" false + ;; + +let generate_dummy_main common_ctx = + let generate_startup filename is_main = + let main_file = new_cpp_file common_ctx common_ctx.file ([],filename) in + let output_main = (main_file#write) in + generate_main_header (main_file#write_h); + if is_main then output_main "\n#include \n\n"; + generate_main_footer1 output_main; + generate_main_footer2 output_main; + main_file#close; + in + generate_startup "__main__" true; + generate_startup "__lib__" false + ;; + +let generate_boot ctx boot_enums boot_classes nonboot_classes init_classes = + let common_ctx = ctx.ctx_common in + (* Write boot class too ... *) + let base_dir = common_ctx.file in + let boot_file = new_cpp_file common_ctx base_dir ([],"__boot__") in + let output_boot = (boot_file#write) in + boot_file#write_h "#include \n\n"; + + List.iter ( fun class_path -> boot_file#add_include class_path ) + (boot_enums @ boot_classes @ nonboot_classes); + + let newScriptable = (Common.defined common_ctx Define.Scriptable) in + if newScriptable then begin + output_boot "#include \n"; + let funcs = hash_iterate !(ctx.ctx_interface_slot) (fun name id -> (name,id) ) in + let sorted = List.sort (fun (_,id1) (_,id2) -> id1-id2 ) funcs in + output_boot "static const char *scriptableInterfaceFuncs[] = {\n\t0,\n\t0,\n"; + List.iter (fun (name,id) -> output_boot ("\t\"" ^ name ^ "\", //" ^ (string_of_int (-id) ) ^ "\n")) sorted; + output_boot "};\n"; + end; + + + output_boot "\nvoid __files__boot();\n"; + output_boot "\nvoid __boot_all()\n{\n"; + output_boot "__files__boot();\n"; + output_boot "hx::RegisterResources( hx::GetResources() );\n"; + if newScriptable then + output_boot ("hx::ScriptableRegisterNameSlots(scriptableInterfaceFuncs," ^ (string_of_int !(ctx.ctx_interface_slot_count) ) ^ ");\n"); + + List.iter ( fun class_path -> + output_boot ("::" ^ ( join_class_path_remap class_path "::" ) ^ "_obj::__register();\n") ) + (boot_enums @ boot_classes @ nonboot_classes); + + let dump_boot = + List.iter ( fun class_path -> + output_boot ("::" ^ ( join_class_path_remap class_path "::" ) ^ "_obj::__boot();\n") ) in + + dump_boot boot_enums; + + List.iter ( fun class_path -> + output_boot ("::" ^ ( join_class_path_remap class_path "::" ) ^ "_obj::__init__();\n") ) (List.rev init_classes); + + dump_boot (List.filter (fun path -> is_cpp_class path ) (List.rev boot_classes)); + dump_boot (List.filter (fun path -> not (is_cpp_class path) ) (List.rev boot_classes)); + + output_boot "}\n\n"; + boot_file#close;; + + +let generate_files common_ctx file_info = + (* Write __files__ class too ... *) + let base_dir = common_ctx.file in + let files_file = new_cpp_file common_ctx base_dir ([],"__files__") in + let output_files = (files_file#write) in + let types = common_ctx.types in + files_file#write_h "#include \n\n"; + output_files "namespace hx {\n"; + output_files "const char *__hxcpp_all_files[] = {\n"; + output_files "#ifdef HXCPP_DEBUGGER\n"; + List.iter ( fun file -> output_files ((const_char_star file)^",\n" ) ) + ( List.sort String.compare ( pmap_keys !file_info) ); + output_files "#endif\n"; + output_files " 0 };\n"; + output_files "\n"; + + output_files "const char *__hxcpp_all_files_fullpath[] = {\n"; + output_files "#ifdef HXCPP_DEBUGGER\n"; + List.iter ( fun file -> output_files ((const_char_star ( + Path.get_full_path (try Common.find_file common_ctx file with Not_found -> file) + ))^",\n" ) ) + ( List.sort String.compare ( pmap_keys !file_info) ); + output_files "#endif\n"; + output_files " 0 };\n"; + output_files "\n"; + + + output_files "const char *__hxcpp_all_classes[] = {\n"; + output_files "#ifdef HXCPP_DEBUGGER\n"; + List.iter ( fun object_def -> + (match object_def with + | TClassDecl class_def when is_extern_class class_def -> ( ) + | TClassDecl class_def when class_def.cl_interface -> ( ) + | TClassDecl class_def -> + output_files ((const_char_star (join_class_path class_def.cl_path "." )) ^ ",\n") + | _ -> ( ) + ) + ) types; + output_files "#endif\n"; + output_files " 0 };\n"; + + output_files "} // namespace hx\n"; + output_files "void __files__boot() { __hxcpp_set_debugger_info(hx::__hxcpp_all_classes, hx::__hxcpp_all_files_fullpath); }\n"; + + files_file#close;; + + +let begin_header_file output_h def_string nativeGen = + output_h ("#ifndef INCLUDED_" ^ def_string ^ "\n"); + output_h ("#define INCLUDED_" ^ def_string ^ "\n\n"); + output_h "#ifndef HXCPP_H\n"; + if nativeGen then begin + output_h "#ifdef HXCPP_API_LEVEL\n"; + output_h "#include \n"; + output_h "#else\n"; + output_h "#include \n"; + output_h "#endif\n" + end else begin + output_h "#include \n" + end; + output_h "#endif\n\n";; + +let end_header_file output_h def_string = + output_h ("\n#endif /* INCLUDED_" ^ def_string ^ " */ \n");; + +let new_placed_cpp_file common_ctx class_path = + let base_dir = common_ctx.file in + + if (Common.defined common_ctx Define.Vcproj ) then begin + make_class_directories base_dir ("src"::[]); + cached_source_writer common_ctx + ( base_dir ^ "/src/" ^ ( String.concat "-" (fst class_path) ) ^ "-" ^ + (snd class_path) ^ (source_file_extension common_ctx) ) + end else + new_cpp_file common_ctx common_ctx.file class_path;; + + + +let generate_enum_files baseCtx enum_def super_deps meta = + let common_ctx = baseCtx.ctx_common in + let class_path = enum_def.e_path in + let just_class_name = (snd class_path) in + let class_name = just_class_name ^ "_obj" in + let remap_class_name = ("::" ^ (join_class_path_remap class_path "::") ) in + (*let cpp_file = new_cpp_file common_ctx.file class_path in*) + let cpp_file = new_placed_cpp_file common_ctx class_path in + let output_cpp = (cpp_file#write) in + let debug = if (has_meta_key enum_def.e_meta Meta.NoDebug) || ( Common.defined common_ctx Define.NoDebug) + then 0 else 1 in + + let ctx = file_context baseCtx cpp_file debug false in + + if (debug>1) then + print_endline ("Found enum definition:" ^ (join_class_path class_path "::" )); + + cpp_file#write_h "#include \n\n"; + + let referenced,flags = find_referenced_types_flags ctx (TEnumDecl enum_def) "*" super_deps (Hashtbl.create 0) false false false in + List.iter (add_include cpp_file) referenced; + + gen_open_namespace output_cpp class_path; + output_cpp "\n"; + + PMap.iter (fun _ constructor -> + let name = keyword_remap constructor.ef_name in + match constructor.ef_type with + | TFun (args,_) -> + output_cpp (remap_class_name ^ " " ^ class_name ^ "::" ^ name ^ "(" ^ + (ctx_tfun_arg_list ctx true args) ^")\n"); + + output_cpp ("{\n\treturn hx::CreateEnum< " ^ class_name ^ " >(" ^ (strq name) ^ "," ^ + (string_of_int constructor.ef_index) ^ "," ^ (string_of_int (List.length args)) ^ ")" ); + ExtList.List.iteri (fun i (arg,_,_) -> output_cpp ("->_hx_init(" ^ (string_of_int i) ^ "," ^ (keyword_remap arg) ^ ")")) args; + output_cpp ";\n}\n\n" + | _ -> + output_cpp ( remap_class_name ^ " " ^ class_name ^ "::" ^ name ^ ";\n\n" ) + ) enum_def.e_constrs; + + + let constructor_arg_count constructor = + (match constructor.ef_type with | TFun(args,_) -> List.length args | _ -> 0 ) + in + + output_cpp ("bool " ^ class_name ^ "::__GetStatic(const ::String &inName, ::Dynamic &outValue, hx::PropertyAccess inCallProp)\n{\n"); + PMap.iter (fun _ constructor -> + let name = constructor.ef_name in + let dyn = if constructor_arg_count constructor > 0 then "_dyn()" else "" in + output_cpp ("\tif (inName==" ^ strq name ^ ") { outValue = " ^ class_name ^ "::" ^ keyword_remap name ^ dyn ^ "; return true; }\n" ); + ) enum_def.e_constrs; + output_cpp ("\treturn super::__GetStatic(inName, outValue, inCallProp);\n}\n\n"); + + output_cpp ("HX_DEFINE_CREATE_ENUM(" ^ class_name ^ ")\n\n"); + + output_cpp ("int " ^ class_name ^ "::__FindIndex(::String inName)\n{\n"); + PMap.iter (fun _ constructor -> + let name = constructor.ef_name in + let idx = string_of_int constructor.ef_index in + output_cpp ("\tif (inName==" ^ (strq name) ^ ") return " ^ idx ^ ";\n") ) enum_def.e_constrs; + output_cpp ("\treturn super::__FindIndex(inName);\n"); + output_cpp ("}\n\n"); + + (* Dynamic versions of constructors *) + let dump_dynamic_constructor _ constr = + let count = constructor_arg_count constr in + if (count>0) then begin + let nargs = string_of_int count in + output_cpp ("STATIC_HX_DEFINE_DYNAMIC_FUNC" ^ nargs ^ "(" ^ class_name ^ "," ^ + (keyword_remap constr.ef_name) ^ ",return)\n\n"); + end + in + PMap.iter dump_dynamic_constructor enum_def.e_constrs; + + + output_cpp ("int " ^ class_name ^ "::__FindArgCount(::String inName)\n{\n"); + PMap.iter (fun _ constructor -> + let name = constructor.ef_name in + let count = string_of_int (constructor_arg_count constructor) in + output_cpp ("\tif (inName==" ^ (strq name) ^ ") return " ^ count ^ ";\n") ) enum_def.e_constrs; + output_cpp ("\treturn super::__FindArgCount(inName);\n"); + output_cpp ("}\n\n"); + + (* Dynamic "Get" Field function - string version *) + output_cpp ("hx::Val " ^ class_name ^ "::__Field(const ::String &inName,hx::PropertyAccess inCallProp)\n{\n"); + let dump_constructor_test _ constr = + output_cpp ("\tif (inName==" ^ (strq constr.ef_name) ^ ") return " ^ + (keyword_remap constr.ef_name) ); + if ( (constructor_arg_count constr) > 0 ) then output_cpp "_dyn()"; + output_cpp (";\n") + in + PMap.iter dump_constructor_test enum_def.e_constrs; + output_cpp ("\treturn super::__Field(inName,inCallProp);\n}\n\n"); + + output_cpp ("static ::String " ^ class_name ^ "_sStaticFields[] = {\n"); + let sorted = + List.sort (fun f1 f2 -> (PMap.find f1 enum_def.e_constrs ).ef_index - + (PMap.find f2 enum_def.e_constrs ).ef_index ) + (pmap_keys enum_def.e_constrs) in + + List.iter (fun name -> output_cpp ("\t" ^ (strq name) ^ ",\n") ) sorted; + + output_cpp "\t::String(null())\n};\n\n"; + + (* ENUM - Mark static as used by GC *) + output_cpp ("static void " ^ class_name ^ "_sMarkStatics(HX_MARK_PARAMS) {\n"); + PMap.iter (fun _ constructor -> + let name = keyword_remap constructor.ef_name in + match constructor.ef_type with + | TFun (_,_) -> () + | _ -> output_cpp ("\tHX_MARK_MEMBER_NAME(" ^ class_name ^ "::" ^ name ^ ",\"" ^ name ^ "\");\n") ) + enum_def.e_constrs; + output_cpp "};\n\n"; + + (* ENUM - Visit static as used by GC *) + output_cpp "#ifdef HXCPP_VISIT_ALLOCS\n"; + output_cpp ("static void " ^ class_name ^ "_sVisitStatic(HX_VISIT_PARAMS) {\n"); + output_cpp ("\tHX_VISIT_MEMBER_NAME(" ^ class_name ^ "::__mClass,\"__mClass\");\n"); + PMap.iter (fun _ constructor -> + let name = keyword_remap constructor.ef_name in + match constructor.ef_type with + | TFun (_,_) -> () + | _ -> output_cpp ("\tHX_VISIT_MEMBER_NAME(" ^ class_name ^ "::" ^ name ^ ",\"" ^ name ^ "\");\n") ) + enum_def.e_constrs; + output_cpp "};\n"; + output_cpp "#endif\n\n"; + + output_cpp ("hx::Class " ^ class_name ^ "::__mClass;\n\n"); + + output_cpp ("Dynamic __Create_" ^ class_name ^ "() { return new " ^ class_name ^ "; }\n\n"); + + output_cpp ("void " ^ class_name ^ "::__register()\n{\n"); + let text_name = str (join_class_path class_path ".") in + output_cpp ("\nhx::Static(__mClass) = hx::_hx_RegisterClass(" ^ text_name ^ + ", hx::TCanCast< " ^ class_name ^ " >," ^ class_name ^ "_sStaticFields,0,\n"); + output_cpp ("\t&__Create_" ^ class_name ^ ", &__Create,\n"); + output_cpp ("\t&super::__SGetClass(), &Create" ^ class_name ^ ", " ^ class_name ^ "_sMarkStatics\n"); + output_cpp("#ifdef HXCPP_VISIT_ALLOCS\n , " ^ class_name ^ "_sVisitStatic\n#endif\n"); + output_cpp ("#ifdef HXCPP_SCRIPTABLE\n , 0\n#endif\n"); + output_cpp (");\n"); + output_cpp ("\t__mClass->mGetStaticField = &" ^ class_name ^"::__GetStatic;\n"); + output_cpp "}\n\n"; + + output_cpp ("void " ^ class_name ^ "::__boot()\n{\n"); + (match meta with + | Some expr -> + let ctx = file_context ctx cpp_file 1 false in + gen_cpp_init ctx class_name "boot" "__mClass->__meta__ = " expr + | _ -> () ); + PMap.iter (fun _ constructor -> + let name = constructor.ef_name in + match constructor.ef_type with + | TFun (_,_) -> () + | _ -> + output_cpp ( (keyword_remap name) ^ " = hx::CreateEnum< " ^ class_name ^ " >(" ^ (str name) ^ "," ^ + (string_of_int constructor.ef_index) ^ ",0);\n" ) + ) enum_def.e_constrs; + output_cpp ("}\n\n"); + + + + + output_cpp "\n"; + gen_close_namespace output_cpp class_path; + cpp_file#close; + + let h_file = new_header_file common_ctx common_ctx.file class_path in + let super = "hx::EnumBase_obj" in + let output_h = (h_file#write) in + let def_string = join_class_path class_path "_" in + + let ctx = file_context baseCtx h_file debug true in + + begin_header_file (h_file#write_h) def_string false; + + List.iter2 (fun r f -> gen_forward_decl h_file r f) referenced flags; + + gen_open_namespace output_h class_path; + + output_h "\n\n"; + output_h ("class " ^ class_name ^ " : public " ^ super ^ "\n"); + output_h ("{\n\ttypedef " ^ super ^ " super;\n"); + output_h ("\t\ttypedef " ^ class_name ^ " OBJ_;\n"); + output_h "\n\tpublic:\n"; + output_h ("\t\t" ^ class_name ^ "() {};\n"); + output_h ("\t\tHX_DO_ENUM_RTTI;\n"); + output_h ("\t\tstatic void __boot();\n"); + output_h ("\t\tstatic void __register();\n"); + output_h ("\t\tstatic bool __GetStatic(const ::String &inName, Dynamic &outValue, hx::PropertyAccess inCallProp);\n"); + output_h ("\t\t::String GetEnumName( ) const { return " ^ (str (join_class_path class_path ".")) ^ "; }\n" ); + output_h ("\t\t::String __ToString() const { return " ^ (str (just_class_name ^ ".") )^ " + _hx_tag; }\n\n"); + + + PMap.iter (fun _ constructor -> + let name = keyword_remap constructor.ef_name in + output_h ( "\t\tstatic " ^ remap_class_name ^ " " ^ name ); + match constructor.ef_type with + | TFun (args,_) -> + output_h ( "(" ^ (ctx_tfun_arg_list ctx true args) ^");\n"); + output_h ( "\t\tstatic ::Dynamic " ^ name ^ "_dyn();\n"); + | _ -> + output_h ";\n"; + output_h ( "\t\tstatic inline " ^ remap_class_name ^ " " ^ name ^ + "_dyn() { return " ^name ^ "; }\n" ); + ) enum_def.e_constrs; + + output_h "};\n\n"; + + gen_close_namespace output_h class_path; + + end_header_file output_h def_string; + h_file#close +;; + +let generate_enum_deps ctx enum_def super_deps = + find_referenced_types ctx (TEnumDecl enum_def) super_deps (Hashtbl.create 0) false true false +;; + +let list_iteri func in_list = + let idx = ref 0 in + List.iter (fun elem -> func !idx elem; idx := !idx + 1 ) in_list +;; + +let has_new_gc_references ctx class_def = + match class_def.cl_dynamic with + | Some _ -> true + | _ -> ( + let is_gc_reference field = + (should_implement_field field) && (is_data_member field) && not (ctx_cant_be_null ctx field.cf_type) + in + List.exists is_gc_reference class_def.cl_ordered_fields + ) +;; + + +let rec has_gc_references ctx class_def = + ( match class_def.cl_super with + | Some def when has_gc_references ctx (fst def) -> true + | _ -> false ) + || has_new_gc_references ctx class_def +;; + +let rec find_next_super_iteration ctx class_def = + match class_def.cl_super with + | Some (klass,params) when has_new_gc_references ctx klass -> + tcpp_to_string_suffix "_obj" (cpp_instance_type ctx klass params) + | Some (klass,_) -> find_next_super_iteration ctx klass + | _ -> ""; +;; + +let has_init_field class_def = + match class_def.cl_init with + | Some _ -> true + | _ -> false;; + + +let is_abstract_impl class_def = match class_def.cl_kind with + | KAbstractImpl _ -> true + | _ -> false +;; + +let variable_field field = + (match field.cf_expr with + | Some { eexpr = TFunction function_def } -> is_dynamic_haxe_method field + | _ -> true) +;; + +let is_readable class_def field = + (match field.cf_kind with + | Var { v_read = AccNever } when (is_extern_field field) -> false + | Var { v_read = AccInline } -> false + | Var _ when is_abstract_impl class_def -> false + | _ -> true) +;; + +let is_writable class_def field = + (match field.cf_kind with + | Var { v_write = AccNever } when (is_extern_field field) -> false + | Var { v_read = AccInline } -> false + | Var _ when is_abstract_impl class_def -> false + | _ -> true) +;; + + +let statics_except_meta class_def = (List.filter (fun static -> static.cf_name <> "__meta__" && static.cf_name <> "__rtti") class_def.cl_ordered_statics);; + +let has_set_member_field class_def = + implement_dynamic_here class_def || ( + let reflect_fields = List.filter (reflective class_def) (class_def.cl_ordered_fields) in + let reflect_writable = List.filter (is_writable class_def) reflect_fields in + List.exists variable_field reflect_writable + ) +;; + + +let has_set_static_field class_def = + let reflect_fields = List.filter (reflective class_def) (statics_except_meta class_def) in + let reflect_writable = List.filter (is_writable class_def) reflect_fields in + List.exists variable_field reflect_writable +;; + + +let has_get_fields class_def = + implement_dynamic_here class_def || ( + let is_data_field field = (match follow field.cf_type with | TFun _ -> false | _ -> true) in + List.exists is_data_field class_def.cl_ordered_fields + ) +;; + +let has_get_member_field class_def = + implement_dynamic_here class_def || ( + let reflect_fields = List.filter (reflective class_def) (class_def.cl_ordered_fields) in + List.exists (is_readable class_def) reflect_fields + ) +;; + + +let has_get_static_field class_def = + let reflect_fields = List.filter (reflective class_def) (statics_except_meta class_def) in + List.exists (is_readable class_def) reflect_fields +;; + + + +let has_boot_field class_def = + match class_def.cl_init with + | None -> List.exists has_field_init (List.filter should_implement_field class_def.cl_ordered_statics) + | _ -> true +;; + +let cpp_tfun_signature ctx include_names args return_type = + let argList = ctx_tfun_arg_list ctx include_names args in + let returnType = ctx_type_string ctx return_type in + ("( " ^ returnType ^ " (hx::Object::*)(" ^ argList ^ "))") +;; + +exception FieldFound of tclass_field;; + +let find_class_implementation ctx class_def name interface = + let rec find def = + List.iter (fun f -> if f.cf_name=name then raise (FieldFound f) ) def.cl_ordered_fields; + match def.cl_super with + | Some (def,_) -> find def + | _ -> () + in + try + find class_def; + abort ("Could not find implementation of " ^ name ^ " in " ^ + (join_class_path class_def.cl_path ".") ^ " required by " ^ (join_class_path interface.cl_path ".")) class_def.cl_pos + with FieldFound field -> + match follow field.cf_type, field.cf_kind with + | _, Method MethDynamic -> "" + | TFun (args,return_type), Method _ -> + cpp_tfun_signature ctx false args return_type + | _,_ -> "" +;; + + +let is_macro meta = + Meta.has Meta.Macro meta +;; + + +let cpp_get_interface_slot ctx name = + try Hashtbl.find !(ctx.ctx_interface_slot) name + with Not_found -> begin + let result = !(ctx.ctx_interface_slot_count) in + Hashtbl.replace !(ctx.ctx_interface_slot) name result; + ctx.ctx_interface_slot_count := !(ctx.ctx_interface_slot_count) + 1; + result + end +;; + +let access_str a = match a with + | AccNormal -> "AccNormal" + | AccNo -> "AccNo" + | AccNever -> "AccNever" + | AccResolve -> "AccResolve" + | AccCall -> "AccCall" + | AccInline -> "AccInline" + | AccRequire(_,_) -> "AccRequire" ;; + + +let script_type t optional = if optional then begin + match type_string t with + | "::String" -> "String" + | _ -> "Object" + end else match type_string t with + | "bool" -> "Int" + | "int" -> "Int" + | "Float" -> "Float" + | "::String" -> "String" + | "Null" -> "Void" + | "Void" -> "Void" + | _ -> "Object" +;; + +let script_signature t optional = match script_type t optional with + | "Bool" -> "b" + | "Int" -> "i" + | "Float" -> "f" + | "String" -> "s" + | "Void" -> "v" + | "void" -> "v" + | _ -> "o" +;; + +let script_size_type t optional = match script_type t optional with + | "Object" -> "void *" + | "Int" -> "int" + | "Bool" -> "bool" + | x -> x +;; + + + +let constructor_arg_var_list class_def ctx = + match class_def.cl_constructor with + | Some definition -> + (match definition.cf_expr with + | Some { eexpr = TFunction function_def } -> + List.map (fun (v,o) -> (v.v_name, ctx_arg_type_name ctx v.v_name o v.v_type "__o_")) + function_def.tf_args; + | _ -> + (match follow definition.cf_type with + | TFun (args,_) -> List.map (fun (a,_,t) -> (a, (ctx_type_string ctx t, a)) ) args + | _ -> []) + ) + | _ -> [] +;; + +let can_inline_constructor ctx class_def super_deps constructor_deps = + match class_def.cl_constructor with + | Some { cf_expr= Some super_func } -> + let is_simple = ref true in + let rec check_simple e = + (match e.eexpr with + | TReturn _ -> is_simple := false + | TArrayDecl e when List.length e > 0 -> is_simple := false + | _ -> () + ); + if !is_simple then Type.iter check_simple e + in + check_simple super_func; + !is_simple && ( + let rec known_classes class_def so_far = match class_def.cl_super with + | Some super -> known_classes (fst super) ((fst super).cl_path :: so_far) + | _ -> so_far in + let allowed = known_classes class_def [class_def.cl_path] in + (* Check to see if all the types required by the constructor are already in the header *) + (* This is quite restrictive, since most classes are forward-declared *) + let deps,_ = find_referenced_types_flags ctx (TClassDecl class_def) "new" super_deps constructor_deps false false true in + List.for_all (fun dep -> List.mem dep allowed ) deps + ) + | _ -> true +;; + +let has_dynamic_member_functions class_def = +List.fold_left (fun result field -> + match field.cf_expr with + | Some { eexpr = TFunction function_def } when is_dynamic_haxe_method field -> true + | _ -> result ) false class_def.cl_ordered_fields +;; + + +let generate_protocol_delegate ctx class_def output = + let protocol = get_meta_string class_def.cl_meta Meta.ObjcProtocol in + let full_class_name = ("::" ^ (join_class_path_remap class_def.cl_path "::") ) ^ "_obj" in + let name = "_hx_" ^ protocol ^ "_delegate" in + output ("@interface " ^ name ^ " : NSObject<" ^ protocol ^ "> {\n"); + output ("\t::hx::Object *haxeObj;\n"); + output ("}\n"); + output ("@end\n\n"); + output ("@implementation " ^ name ^ "\n"); + output ("- (id)initWithImplementation:( ::hx::Object *)inInplemnetation {\n"); + output (" if (self = [super init]) {\n"); + output (" self->haxeObj = inInplemnetation;\n"); + output (" GCAddRoot(&self->haxeObj);\n"); + output (" }\n"); + output (" return self;\n"); + output ("}\n"); + output ("- (void)dealloc {\n"); + output (" GCRemoveRoot(&self->haxeObj);\n"); + output (" #ifndef OBJC_ARC\n"); + output (" [super dealloc];\n"); + output (" #endif\n"); + output ("}\n\n"); + + let dump_delegate field = + match field.cf_type with + | TFun(args,ret) -> + let retStr = ctx_type_string ctx ret in + let nativeName = get_meta_string field.cf_meta Meta.ObjcProtocol in + let fieldName,argNames = if nativeName<>"" then begin + let parts = ExtString.String.nsplit nativeName ":" in + List.hd parts, parts + end else + field.cf_name, List.map (fun (n,_,_) -> n ) args + in + output ("- (" ^ retStr ^ ") " ^ fieldName ); + + let first = ref true in + (try + List.iter2 (fun (name,_,argType) signature_name -> + if !first then + output (" :(" ^ (ctx_type_string ctx argType) ^ ")" ^ name ) + else + output (" " ^ signature_name ^ ":(" ^ (ctx_type_string ctx argType) ^ ")" ^ name ); + first := false; + ) args argNames; + with Invalid_argument _ -> begin + abort ( + let argString = String.concat "," (List.map (fun (name,_,_) -> name) args) in + "Invalid arg count in delegate in " ^ field.cf_name ^ " '" ^ field.cf_name ^ "," ^ + (argString) ^ "' != '" ^ (String.concat "," argNames) ^ "'" ) field.cf_pos + end); + output (" {\n"); + output ("\thx::NativeAttach _hx_attach;\n"); + output ( (if retStr="void" then "\t" else "\treturn ") ^ full_class_name ^ "::" ^ (keyword_remap field.cf_name) ^ "(haxeObj"); + List.iter (fun (name,_,_) -> output ("," ^ name)) args; + output (");\n}\n\n"); + | _ -> () + in + List.iter dump_delegate class_def.cl_ordered_fields; + + output ("@end\n\n"); +;; + + +(* + Generate class header and cpp files + +*) + + +let generate_class_files baseCtx super_deps constructor_deps class_def inScriptable = + + (* Shorcuts *) + let common_ctx = baseCtx.ctx_common in + let class_path = class_def.cl_path in + let nativeGen = has_meta_key class_def.cl_meta Meta.NativeGen in + let class_name = (snd class_path) ^ (if nativeGen then "" else "_obj") in + let dot_name = join_class_path class_path "." in + let smart_class_name = (snd class_path) in + let class_name_text = join_class_path class_path "." in + let gcName = const_char_star class_name_text in + let ptr_name = "hx::ObjectPtr< " ^ class_name ^ " >" in + let debug = if (has_meta_key class_def.cl_meta Meta.NoDebug) || ( Common.defined baseCtx.ctx_common Define.NoDebug) + then 0 else 1 in + let scriptable = inScriptable && not class_def.cl_private in + + let classId = try Hashtbl.find baseCtx.ctx_type_ids (class_text class_def.cl_path) with Not_found -> Int32.of_int 0 in + let classIdTxt = Printf.sprintf "0x%08lx" classId in + + (* Config *) + let implement_dynamic = implement_dynamic_here class_def in + let override_iteration = (not nativeGen) && (has_new_gc_references baseCtx class_def) in + let dynamic_interface_closures = (Common.defined baseCtx.ctx_common Define.DynamicInterfaceClosures) in + + (* All interfaces (and sub-interfaces) implemented *) + let implemented_hash = Hashtbl.create 0 in + let native_implemented = Hashtbl.create 0 in + List.iter (fun imp -> + let rec descend_interface interface = + let intf_def = (fst interface) in + let interface_name = cpp_interface_impl_name baseCtx intf_def in + let hash = if is_native_gen_class intf_def then native_implemented else implemented_hash in + if ( not (Hashtbl.mem hash interface_name) ) then begin + Hashtbl.replace hash interface_name intf_def; + List.iter descend_interface intf_def.cl_implements; + end; + match intf_def.cl_super with + | Some (interface,params) -> descend_interface (interface,params) + | _ -> () + in descend_interface imp + ) (real_interfaces class_def.cl_implements); + let implemented = hash_keys implemented_hash in + let implementsNative = (Hashtbl.length native_implemented) > 0 in + + let dynamic_functions = List.fold_left (fun result field -> + match field.cf_expr with + | Some { eexpr = TFunction function_def } when is_dynamic_haxe_method field -> + (keyword_remap field.cf_name) :: result + | _ -> result ) [] class_def.cl_ordered_fields + in + + + (* Field groups *) + let statics_except_meta = statics_except_meta class_def in + let implemented_fields = List.filter should_implement_field statics_except_meta in + let implemented_instance_fields = List.filter should_implement_field class_def.cl_ordered_fields in + + let reflect_member_fields = List.filter (reflective class_def) class_def.cl_ordered_fields in + let reflect_member_readable = List.filter (is_readable class_def) reflect_member_fields in + let reflect_member_writable = List.filter (is_writable class_def) reflect_member_fields in + let reflect_write_member_variables = List.filter variable_field reflect_member_writable in + + let reflect_static_fields = List.filter (reflective class_def) (statics_except_meta) in + let reflect_static_readable = List.filter (is_readable class_def) reflect_static_fields in + let reflect_static_writable = List.filter (is_writable class_def) reflect_static_fields in + let reflect_write_static_variables = List.filter variable_field reflect_static_writable in + + let reflective_members = List.filter (reflective class_def) implemented_instance_fields in + + (* native interface glue *) + let neededInterfaceFunctions = if not implementsNative then [] + else begin + let have = Hashtbl.create 0 in + List.iter (fun field -> Hashtbl.replace have field.cf_name () ) implemented_instance_fields; + let want = ref [] in + Hashtbl.iter (fun _ intf_def -> + List.iter (fun field -> + if not (Hashtbl.mem have field.cf_name) then begin + Hashtbl.replace have field.cf_name (); + want := field :: !want; + end + ) intf_def.cl_ordered_fields; + ) native_implemented; + !want; + end + in + + let not_toString = fun (field,args,_) -> field.cf_name<>"toString" || class_def.cl_interface in + let functions = List.filter not_toString (all_virtual_functions class_def) in + + (* Constructor definition *) + let cargs = (constructor_arg_var_list class_def baseCtx) in + let constructor_type_var_list = List.map snd cargs in + let constructor_var_list = List.map snd constructor_type_var_list in + let constructor_type_args = String.concat "," + (List.map (fun (t,a) -> t ^ " " ^ a) constructor_type_var_list) in + let constructor_args = String.concat "," constructor_var_list in + + let isContainer = if (has_gc_references common_ctx class_def) then "true" else "false" in + + let outputConstructor ctx out isHeader = + let classScope = if isHeader then "" else class_name ^ "::" in + out (ptr_name ^ " " ^ classScope ^ "__new(" ^constructor_type_args ^") {\n"); + out ("\t" ^ ptr_name ^ " __this = new " ^ class_name ^ "();\n"); + out ("\t__this->__construct(" ^ constructor_args ^ ");\n"); + out ("\treturn __this;\n"); + out ("}\n\n"); + + out ((if isHeader then "static " else "") ^ ptr_name ^ " " ^ classScope ^ "__alloc(hx::Ctx *_hx_ctx" ^ (if constructor_type_args="" then "" else "," ^constructor_type_args) ^") {\n"); + out ("\t" ^ class_name ^ " *__this = (" ^ class_name ^ "*)(hx::Ctx::alloc(_hx_ctx, sizeof(" ^ class_name ^ "), " ^ isContainer ^", " ^ gcName ^ "));\n"); + out ("\t*(void **)__this = " ^ class_name ^ "::_hx_vtable;\n"); + let rec dump_dynamic class_def = + if has_dynamic_member_functions class_def then + out ("\t" ^ (join_class_path_remap class_def.cl_path "::") ^ "_obj::__alloc_dynamic_functions(_hx_ctx,__this);\n") + else match class_def.cl_super with + | Some super -> dump_dynamic (fst super) + | _ -> () + in + dump_dynamic class_def; + + if isHeader then begin + match class_def.cl_constructor with + | Some ( { cf_expr = Some ( { eexpr = TFunction(function_def) } ) } as definition ) -> + let old_debug = ctx.ctx_debug_level in + if has_meta_key definition.cf_meta Meta.NoDebug then + ctx.ctx_debug_level <- 0; + ctx.ctx_real_this_ptr <- false; + gen_cpp_function_body ctx class_def false "new" function_def "" "" (has_meta_key definition.cf_meta Meta.NoDebug); + out "\n"; + + ctx.ctx_debug_level <- old_debug; + | _ -> () + end else + out ("\t__this->__construct(" ^ constructor_args ^ ");\n"); + + out ("\treturn __this;\n"); + out ("}\n\n"); + in + + (* State *) + let header_glue = ref [] in + + + let cpp_file = new_placed_cpp_file baseCtx.ctx_common class_path in + let cpp_ctx = file_context baseCtx cpp_file debug false in + + let inlineContructor = can_inline_constructor cpp_ctx class_def super_deps constructor_deps in + + (* + Generate cpp code + *) + let generate_class_cpp () = + (*let cpp_file = new_cpp_file common_ctx.file class_path in*) + let ctx = cpp_ctx in + let output_cpp = (cpp_file#write) in + + let class_super_name = (match class_def.cl_super with + | Some (klass, params) -> (tcpp_to_string_suffix "_obj" (cpp_instance_type ctx klass params) ) + | _ -> "") in + if (debug>1) then print_endline ("Found class definition:" ^ (join_class_path class_def.cl_path "::")); + + + cpp_file#write_h "#include \n\n"; + + let all_referenced = find_referenced_types ctx (TClassDecl class_def) super_deps constructor_deps false false scriptable in + List.iter ( add_include cpp_file ) all_referenced; + + + if (scriptable) then + cpp_file#write_h "#include \n"; + + cpp_file#write_h "\n"; + + output_cpp ( get_class_code class_def Meta.CppFileCode ); + let inc = get_meta_string_path class_def.cl_meta Meta.CppInclude in + if (inc<>"") then + output_cpp ("#include \"" ^ inc ^ "\"\n"); + + gen_open_namespace output_cpp class_path; + output_cpp "\n"; + + output_cpp ( get_class_code class_def Meta.CppNamespaceCode ); + + if (not class_def.cl_interface) && not nativeGen then begin + output_cpp ("void " ^ class_name ^ "::__construct(" ^ constructor_type_args ^ ")"); + (match class_def.cl_constructor with + | Some ( { cf_expr = Some ( { eexpr = TFunction(function_def) } ) } as definition ) -> + let old_debug = ctx.ctx_debug_level in + if has_meta_key definition.cf_meta Meta.NoDebug then + ctx.ctx_debug_level <- 0; + + gen_cpp_function_body ctx class_def false "new" function_def "" "" (has_meta_key definition.cf_meta Meta.NoDebug); + output_cpp "\n"; + + ctx.ctx_debug_level <- old_debug; + | _ -> output_cpp " { }\n\n" + ); + + (* Destructor goes in the cpp file so we can "see" the full definition of the member vars *) + output_cpp ("Dynamic " ^ class_name ^ "::__CreateEmpty() { return new " ^ class_name ^ "; }\n\n"); + output_cpp ("void *" ^ class_name ^ "::_hx_vtable = 0;\n\n"); + + output_cpp ("Dynamic " ^ class_name ^ "::__Create(hx::DynamicArray inArgs)\n"); + output_cpp ("{\n\t" ^ ptr_name ^ " _hx_result = new " ^ class_name ^ "();\n"); + output_cpp ("\t_hx_result->__construct(" ^ (array_arg_list constructor_var_list) ^ ");\n"); + output_cpp ("\treturn _hx_result;\n}\n\n"); + + let rec addParent cls others = match cls.cl_super with + | Some (super,_) -> ( try ( + let parentId = Hashtbl.find ctx.ctx_type_ids (class_text super.cl_path) in + addParent super (parentId :: others); + ) with Not_found -> others ) + | _ -> others + in + let implemented_classes = addParent class_def [classId ; (Int32.of_int 1)] in + let implemented_classes = List.sort compare implemented_classes in + + output_cpp ("bool " ^ class_name ^ "::_hx_isInstanceOf(int inClassId) {\n"); + let txt cId = Printf.sprintf "0x%08lx" cId in + let rec dump_classes indent classes = match classes with + | [] -> () + | [c] -> output_cpp (indent ^ "return inClassId==(int)" ^ (txt c) ^ ";\n" ) + | [c;c1] -> output_cpp (indent ^ "return inClassId==(int)" ^ (txt c) ^ " || inClassId==(int)" ^ (txt c1) ^ ";\n" ) + | _ -> + let len = List.length classes in + let mid = List.nth classes (len / 2) in + let low,high = List.partition (fun e -> e<=mid) classes in + output_cpp (indent ^ "if (inClassId<=(int)" ^ (txt mid) ^ ") {\n"); + dump_classes (indent ^ "\t") low; + output_cpp (indent ^ "} else {\n"); + dump_classes (indent ^ "\t") high; + output_cpp (indent ^ "}\n"); + in + dump_classes "\t" implemented_classes; + output_cpp ("}\n\n"); + + if ( List.length implemented) > 0 then begin + let alreadyGlued = Hashtbl.create 0 in + let cname = "_hx_" ^ (join_class_path class_def.cl_path "_") in + let implname = (cpp_class_name class_def) in + let cpp_glue = ref [] in + List.iter (fun interface_name -> + (try let interface = Hashtbl.find implemented_hash interface_name in + output_cpp ("static " ^ cpp_class_name interface ^ " " ^ cname ^ "_" ^ interface_name ^ "= {\n" ); + let rec gen_interface_funcs interface = + let gen_field field = (match follow field.cf_type, field.cf_kind with + | _, Method MethDynamic -> () + | TFun (args,return_type), Method _ -> + let cast = cpp_tfun_signature ctx false args return_type in + let class_implementation = find_class_implementation ctx class_def field.cf_name interface in + let realName= cpp_member_name_of field in + let castKey = realName ^ "::" ^ cast in + (* C++ can't work out which function it needs to take the addrss of + when the implementation is overloaded - currently the map-set functions. + Change the castKey to force a glue function in this case (could double-cast the pointer, but it is ugly) + *) + let castKey = if interface_name="_hx_haxe_IMap" && realName="set" then castKey ^ "*" else castKey in + let implementationKey = realName ^ "::" ^ class_implementation in + if castKey <> implementationKey && not (Hashtbl.mem alreadyGlued castKey) then begin + Hashtbl.replace alreadyGlued castKey (); + let glue = Printf.sprintf "%s_%08lx" field.cf_name (gen_hash32 0 cast) in + let argList = ctx_tfun_arg_list ctx true args in + let returnType = ctx_type_string ctx return_type in + let returnStr = if returnType="void" then "" else "return " in + let cppCode = returnType ^ " " ^ class_name ^ "::" ^ glue ^ "(" ^ argList ^ ") {\n" ^ + "\t\t\t" ^ returnStr ^ realName ^ "(" ^ cpp_arg_names args ^ ");\n}\n" in + let headerCode = "\t\t" ^ returnType ^ " " ^ glue ^ "(" ^ argList ^ ");\n" in + header_glue := headerCode :: !header_glue; + cpp_glue := cppCode :: !cpp_glue; + output_cpp (" " ^ cast ^ "&" ^ implname ^ "::" ^ glue ^ ",\n"); + end else + output_cpp (" " ^ cast ^ "&" ^ implname ^ "::" ^ realName ^ ",\n"); + | _ -> () ) + in + (match interface.cl_super with + | Some super -> gen_interface_funcs (fst super) + | _ -> ()); + List.iter gen_field interface.cl_ordered_fields; + in + gen_interface_funcs interface; + output_cpp "};\n\n"; + with Not_found -> () ) + ) implemented; + + output_cpp (String.concat "\n" !cpp_glue); + + output_cpp ("void *" ^ class_name ^ "::_hx_getInterface(int inHash) {\n"); + output_cpp "\tswitch(inHash) {\n"; + List.iter (fun interface_name -> + try let interface = Hashtbl.find implemented_hash interface_name in + output_cpp ("\t\tcase (int)" ^ (cpp_class_hash interface) ^ ": return &" ^ cname ^ "_" ^ interface_name ^ ";\n") + with Not_found -> () + ) implemented; + + output_cpp "\t}\n"; + + if class_super_name="" then begin + output_cpp ("\t#ifdef HXCPP_SCRIPTABLE\n"); + output_cpp ("\treturn super::_hx_getInterface(inHash);\n"); + output_cpp ("\t#else\n"); + output_cpp ("\treturn 0;\n"); + output_cpp ("\t#endif\n") + end else + output_cpp ("\treturn super::_hx_getInterface(inHash);\n"); + output_cpp ("}\n\n"); + end; + end; + + (match class_def.cl_init with + | Some expression -> + let ctx = file_context baseCtx cpp_file debug false in + output_cpp ("void " ^ class_name^ "::__init__()"); + gen_cpp_init ctx (cpp_class_name class_def) "__init__" "" (mk_block expression); + output_cpp "\n\n"; + | _ -> ()); + + + let dump_field_name = (fun field -> output_cpp ("\t" ^ (str field.cf_name) ^ ",\n")) in + + List.iter + (gen_field ctx class_def class_name smart_class_name dot_name false class_def.cl_interface) + class_def.cl_ordered_fields; + List.iter + (gen_field ctx class_def class_name smart_class_name dot_name true class_def.cl_interface) statics_except_meta; + output_cpp "\n"; + + if (List.length dynamic_functions > 0) then begin + output_cpp ("void " ^ class_name ^ "::__alloc_dynamic_functions(hx::Ctx *_hx_ctx," ^ class_name ^ " *_hx_obj) {\n"); + List.iter (fun name -> + output_cpp ("\tif (!_hx_obj->" ^ name ^".mPtr) _hx_obj->" ^ name ^ " = new __default_" ^ name ^ "(_hx_obj);\n") + ) dynamic_functions; + (match class_def.cl_super with + | Some super -> + let rec find_super class_def = + if has_dynamic_member_functions class_def then begin + let super_name = (join_class_path_remap class_def.cl_path "::" ) ^ "_obj" in + output_cpp ("\t" ^ super_name ^ "::__alloc_dynamic_functions(_hx_ctx,_hx_obj);\n") + end else + match class_def.cl_super with + | Some super -> find_super (fst super) + | _ -> () + in + find_super (fst super); + | _ -> () + ); + output_cpp ("}\n"); + end; + + if (not class_def.cl_interface) && not nativeGen && not inlineContructor then + outputConstructor ctx output_cpp false; + + + (* Initialise non-static variables *) + if ( (not class_def.cl_interface) && (not nativeGen) ) then begin + output_cpp (class_name ^ "::" ^ class_name ^ "()\n{\n"); + List.iter (fun name -> + output_cpp ("\t" ^ name ^ " = new __default_" ^ name ^ "(this);\n") + ) dynamic_functions; + output_cpp "}\n\n"; + + + let dump_field_iterator macro field = + if (is_data_member field) then begin + let remap_name = keyword_remap field.cf_name in + output_cpp ("\t" ^ macro ^ "(" ^ remap_name ^ ",\"" ^ field.cf_name^ "\");\n"); + + (match field.cf_kind with Var { v_read = AccCall } when (is_dynamic_accessor ("get_" ^ field.cf_name) "get" field class_def) -> + let name = "get_" ^ field.cf_name in + output_cpp ("\t" ^ macro ^ "(" ^ name ^ "," ^ "\"" ^ name ^ "\");\n" ) | _ -> ()); + (match field.cf_kind with Var { v_write = AccCall } when (is_dynamic_accessor ("set_" ^ field.cf_name) "set" field class_def) -> + let name = "set_" ^ field.cf_name in + output_cpp ("\t" ^ macro ^ "(" ^ name ^ "," ^ "\"" ^ name ^ "\");\n" ) | _ -> ()); + end + in + + + if (override_iteration) then begin + let super_needs_iteration = find_next_super_iteration ctx class_def in + (* MARK function - explicitly mark all child pointers *) + output_cpp ("void " ^ class_name ^ "::__Mark(HX_MARK_PARAMS)\n{\n"); + output_cpp ("\tHX_MARK_BEGIN_CLASS(" ^ smart_class_name ^ ");\n"); + if (implement_dynamic) then + output_cpp "\tHX_MARK_DYNAMIC;\n"; + List.iter (dump_field_iterator "HX_MARK_MEMBER_NAME") implemented_instance_fields; + (match super_needs_iteration with + | "" -> () + | super -> output_cpp ("\t" ^ super^"::__Mark(HX_MARK_ARG);\n" ) ); + output_cpp "\tHX_MARK_END_CLASS();\n"; + output_cpp "}\n\n"; + + (* Visit function - explicitly visit all child pointers *) + output_cpp ("void " ^ class_name ^ "::__Visit(HX_VISIT_PARAMS)\n{\n"); + if (implement_dynamic) then + output_cpp "\tHX_VISIT_DYNAMIC;\n"; + List.iter (dump_field_iterator "HX_VISIT_MEMBER_NAME") implemented_instance_fields; + (match super_needs_iteration with + | "" -> () + | super -> output_cpp ("\t" ^ super ^ "::__Visit(HX_VISIT_ARG);\n") ); + output_cpp "}\n\n"; + end; + + + let dump_quick_field_test fields = + if ( (List.length fields) > 0) then begin + let len = function (_,l,_) -> l in + let sfields = List.sort (fun f1 f2 -> (len f1)-(len f2)) fields in + let len_case = ref (-1) in + output_cpp "\tswitch(inName.length) {\n"; + List.iter (fun (field,l,result) -> + if (l <> !len_case) then begin + if (!len_case>=0) then output_cpp "\t\tbreak;\n"; + output_cpp ("\tcase " ^ (string_of_int l) ^ ":\n"); + len_case := l; + end; + output_cpp ("\t\tif (HX_FIELD_EQ(inName,\"" ^ (Ast.s_escape field) ^ "\") ) { " ^ result ^ " }\n"); + ) sfields; + output_cpp "\t}\n"; + end; + in + + let checkPropCall field = if ( (has_meta_key class_def.cl_meta Meta.NativeProperty) || + (has_meta_key field.cf_meta Meta.NativeProperty) || + (Common.defined common_ctx Define.ForceNativeProperty) ) + then + "inCallProp != hx::paccNever" + else + "inCallProp == hx::paccAlways" + in + + + + if (has_get_member_field class_def) then begin + (* Dynamic "Get" Field function - string version *) + output_cpp ("hx::Val " ^ class_name ^ "::__Field(const ::String &inName,hx::PropertyAccess inCallProp)\n{\n"); + let get_field_dat = List.map (fun f -> + (f.cf_name, String.length f.cf_name, + (match f.cf_kind with + | Var { v_read = AccCall } when is_extern_field f -> "if (" ^ (checkPropCall f) ^ ") return hx::Val(" ^(keyword_remap ("get_" ^ f.cf_name)) ^ "());" + | Var { v_read = AccCall } -> "return hx::Val( " ^ (checkPropCall f) ^ " ? " ^ (keyword_remap ("get_" ^ f.cf_name)) ^ "() : " ^ + ((keyword_remap f.cf_name) ^ (if (variable_field f) then "" else "_dyn()")) ^ ");" + | _ -> "return hx::Val( " ^ ((keyword_remap f.cf_name) ^ if (variable_field f) then "" else "_dyn()") ^ ");" + ) ) ) + in + dump_quick_field_test (get_field_dat reflect_member_readable); + if (implement_dynamic) then + output_cpp "\tHX_CHECK_DYNAMIC_GET_FIELD(inName);\n"; + output_cpp ("\treturn super::__Field(inName,inCallProp);\n}\n\n"); + + end; + + if (has_get_static_field class_def) then begin + output_cpp ("bool " ^ class_name ^ "::__GetStatic(const ::String &inName, Dynamic &outValue, hx::PropertyAccess inCallProp)\n{\n"); + let get_field_dat = List.map (fun f -> + (f.cf_name, String.length f.cf_name, + (match f.cf_kind with + | Var { v_read = AccCall } when is_extern_field f -> "if (" ^ (checkPropCall f) ^ ") { outValue = " ^(keyword_remap ("get_" ^ f.cf_name)) ^ "(); return true; }" + | Var { v_read = AccCall } -> "outValue = " ^ (checkPropCall f) ^ " ? " ^ (keyword_remap ("get_" ^ f.cf_name)) ^ "() : " ^ + ((keyword_remap f.cf_name) ^ if (variable_field f) then "" else "_dyn()") ^ "; return true;"; + | _ when variable_field f -> "outValue = " ^ (keyword_remap f.cf_name) ^ "; return true;" + | _ -> "outValue = " ^ ((native_field_name_remap true f) ^ "_dyn(); return true;") + ) + ) ) + in + dump_quick_field_test (get_field_dat reflect_static_readable); + output_cpp ("\treturn false;\n}\n\n"); + end; + + (* Dynamic "Set" Field function *) + if (has_set_member_field class_def) then begin + + output_cpp ("hx::Val " ^ class_name ^ "::__SetField(const ::String &inName,const hx::Val &inValue,hx::PropertyAccess inCallProp)\n{\n"); + + let set_field_dat = List.map (fun f -> + let default_action = if is_gc_element ctx (cpp_type_of ctx f.cf_type) then + "_hx_set_" ^ (keyword_remap f.cf_name) ^ "(HX_CTX_GET,inValue.Cast< " ^ (ctx_type_string ctx f.cf_type) ^ " >());" ^ " return inValue;" + else + (keyword_remap f.cf_name) ^ "=inValue.Cast< " ^ (ctx_type_string ctx f.cf_type) ^ " >();" ^ " return inValue;" + in + (f.cf_name, String.length f.cf_name, + (match f.cf_kind with + | Var { v_write = AccCall } -> "if (" ^ (checkPropCall f) ^ ") return hx::Val( " ^ (keyword_remap ("set_" ^ f.cf_name)) ^ "(inValue) );" + ^ ( if is_extern_field f then "" else default_action ) + | _ -> default_action + ) + ) + ) in + + dump_quick_field_test (set_field_dat reflect_write_member_variables); + if (implement_dynamic) then begin + output_cpp ("\ttry { return super::__SetField(inName,inValue,inCallProp); }\n"); + output_cpp ("\tcatch(Dynamic e) { HX_DYNAMIC_SET_FIELD(inName,inValue); }\n"); + output_cpp "\treturn inValue;\n}\n\n"; + end else + output_cpp ("\treturn super::__SetField(inName,inValue,inCallProp);\n}\n\n"); + end; + + if (has_set_static_field class_def) then begin + + output_cpp ("bool " ^ class_name ^ "::__SetStatic(const ::String &inName,Dynamic &ioValue,hx::PropertyAccess inCallProp)\n{\n"); + + let set_field_dat = List.map (fun f -> + let default_action = + (keyword_remap f.cf_name) ^ "=ioValue.Cast< " ^ (ctx_type_string ctx f.cf_type) ^ " >(); return true;" in + (f.cf_name, String.length f.cf_name, + (match f.cf_kind with + | Var { v_write = AccCall } -> "if (" ^ (checkPropCall f) ^ ") ioValue = " ^ (keyword_remap ("set_" ^ f.cf_name)) ^ "(ioValue);" + ^ ( if is_extern_field f then "" else " else " ^ default_action ) + | _ -> default_action + ) + ) + ) in + + dump_quick_field_test (set_field_dat reflect_write_static_variables); + output_cpp ("\treturn false;\n}\n\n"); + end; + + + + + (* For getting a list of data members (eg, for serialization) *) + if (has_get_fields class_def) then begin + let append_field = + (fun field -> output_cpp ("\toutFields->push(" ^( str field.cf_name )^ ");\n")) in + let is_data_field field = (match follow field.cf_type with | TFun _ -> false | _ -> true) in + + output_cpp ("void " ^ class_name ^ "::__GetFields(Array< ::String> &outFields)\n{\n"); + List.iter append_field (List.filter is_data_field class_def.cl_ordered_fields); + if (implement_dynamic) then + output_cpp "\tHX_APPEND_DYNAMIC_FIELDS(outFields);\n"; + output_cpp "\tsuper::__GetFields(outFields);\n"; + output_cpp "};\n\n"; + end; + + let storage field = match type_string field.cf_type with + | "bool" -> "hx::fsBool" + | "int" -> "hx::fsInt" + | "Float" -> "hx::fsFloat" + | "::String" -> "hx::fsString" + | str -> "hx::fsObject" ^ " /*" ^ str ^ "*/ " + in + let dump_member_storage = (fun field -> + output_cpp ("\t{" ^ (storage field) ^ ",(int)offsetof(" ^ class_name ^"," ^ (keyword_remap field.cf_name) ^")," ^ + (str field.cf_name) ^ "},\n") + ) + in + let dump_static_storage = (fun field -> + output_cpp ("\t{" ^ (storage field) ^ ",(void *) &" ^ class_name ^"::" ^ (keyword_remap field.cf_name) ^"," ^ + (str field.cf_name) ^ "},\n") + ) + in + + output_cpp "#if HXCPP_SCRIPTABLE\n"; + + let stored_fields = List.filter is_data_member implemented_instance_fields in + if ( (List.length stored_fields) > 0) then begin + output_cpp ("static hx::StorageInfo " ^ class_name ^ "_sMemberStorageInfo[] = {\n"); + List.iter dump_member_storage stored_fields; + output_cpp "\t{ hx::fsUnknown, 0, null()}\n};\n"; + end else + output_cpp ("static hx::StorageInfo *" ^ class_name ^ "_sMemberStorageInfo = 0;\n"); + + let stored_statics = List.filter is_data_member implemented_fields in + if ( (List.length stored_statics) > 0) then begin + output_cpp ("static hx::StaticInfo " ^ class_name ^ "_sStaticStorageInfo[] = {\n"); + List.iter dump_static_storage stored_statics; + output_cpp "\t{ hx::fsUnknown, 0, null()}\n};\n"; + end else + output_cpp ("static hx::StaticInfo *" ^ class_name ^ "_sStaticStorageInfo = 0;\n"); + + output_cpp "#endif\n\n"; + end; (* cl_interface *) + + let sMemberFields = if List.length reflective_members>0 then begin + let memberFields = class_name ^ "_sMemberFields" in + output_cpp ("static ::String " ^ memberFields ^ "[] = {\n"); + List.iter dump_field_name reflective_members; + output_cpp "\t::String(null()) };\n\n"; + memberFields + end else + "0 /* sMemberFields */"; + in + + if (not nativeGen) then begin + (* Mark static variables as used *) + output_cpp ("static void " ^ class_name ^ "_sMarkStatics(HX_MARK_PARAMS) {\n"); + output_cpp ("\tHX_MARK_MEMBER_NAME(" ^ class_name ^ "::__mClass,\"__mClass\");\n"); + List.iter (fun field -> + if (is_data_member field) then + output_cpp ("\tHX_MARK_MEMBER_NAME(" ^ class_name ^ "::" ^ (keyword_remap field.cf_name) ^ ",\"" ^ field.cf_name ^ "\");\n") ) + implemented_fields; + output_cpp "};\n\n"; + + (* Visit static variables *) + output_cpp "#ifdef HXCPP_VISIT_ALLOCS\n"; + output_cpp ("static void " ^ class_name ^ "_sVisitStatics(HX_VISIT_PARAMS) {\n"); + output_cpp ("\tHX_VISIT_MEMBER_NAME(" ^ class_name ^ "::__mClass,\"__mClass\");\n"); + List.iter (fun field -> + if (is_data_member field) then + output_cpp ("\tHX_VISIT_MEMBER_NAME(" ^ class_name ^ "::" ^ (keyword_remap field.cf_name) ^ ",\"" ^ field.cf_name ^ "\");\n") ) + implemented_fields; + output_cpp "};\n\n"; + output_cpp "#endif\n\n"; + end; + + let generate_script_function isStatic field scriptName callName = + match follow field.cf_type with + | TFun (args,return_type) -> + output_cpp ("\nstatic void CPPIA_CALL " ^ scriptName ^ "(hx::CppiaCtx *ctx) {\n"); + let ret = script_signature return_type false in + if (ret<>"v") then output_cpp ("ctx->return" ^ (script_type return_type false) ^ "("); + if class_def.cl_interface then begin + output_cpp (class_name ^ "::" ^ callName ^ "(ctx->getThis()" ^ (if (List.length args) > 0 then "," else "")); + end else if isStatic then + output_cpp (class_name ^ "::" ^ callName ^ "(") + else + output_cpp ("((" ^ class_name ^ "*)ctx->getThis())->" ^ callName ^ "("); + + let (signature,_,_) = List.fold_left (fun (signature,sep,size) (_,opt,t) -> + output_cpp (sep ^ "ctx->get" ^ (script_type t opt) ^ "(" ^ size ^ ")"); + (signature ^ (script_signature t opt ), ",", (size^"+sizeof(" ^ (script_size_type t opt) ^ ")") ) ) (ret,"","sizeof(void*)") args + in + + output_cpp ")"; + if (ret<>"v") then output_cpp (")"); + output_cpp (";\n}\n"); + signature; + | _ -> "" + in + + + let newInteface = class_def.cl_interface in + + if (scriptable && not nativeGen) then begin + let delegate = "this->" in + let dump_script_field idx (field,f_args,return_t) = + let args = ctx_tfun_arg_list ctx true f_args in + let names = List.map (fun (n,_,_) -> keyword_remap n) f_args in + let return_type = ctx_type_string ctx return_t in + let ret = if (return_type="Void" || return_type="void") then " " else "return " in + let name = keyword_remap field.cf_name in + let vtable = "__scriptVTable[" ^ (string_of_int (idx+1) ) ^ "] " in + let args_varray = (List.fold_left (fun l n -> l ^ ".Add(" ^ n ^ ")") "Array()" names) in + + output_cpp (" " ^ return_type ^ " " ^ name ^ "( " ^ args ^ " ) {\n"); + if newInteface then begin + output_cpp ("\t\thx::CppiaCtx *__ctx = hx::CppiaCtx::getCurrent();\n" ); + output_cpp ("\t\thx::AutoStack __as(__ctx);\n" ); + output_cpp ("\t\t__ctx->pushObject(this);\n" ); + List.iter (fun (name,opt, t ) -> + output_cpp ("\t\t__ctx->push" ^ (script_type t opt) ^ "(" ^ (keyword_remap name) ^ ");\n" ); + ) f_args; + let interfaceSlot = string_of_int( -(cpp_get_interface_slot ctx name) ) in + output_cpp ("\t\t" ^ ret ^ "__ctx->run" ^ (script_type return_t false) ^ "(__GetScriptVTable()[" ^ interfaceSlot ^ "]);\n" ); + output_cpp "\t}\n"; + end else begin + output_cpp ("\tif (" ^ vtable ^ ") {\n" ); + output_cpp ("\t\thx::CppiaCtx *__ctx = hx::CppiaCtx::getCurrent();\n" ); + output_cpp ("\t\thx::AutoStack __as(__ctx);\n" ); + output_cpp ("\t\t__ctx->pushObject(" ^ (if class_def.cl_interface then "mDelegate.mPtr" else "this" ) ^");\n" ); + List.iter (fun (name,opt, t ) -> + output_cpp ("\t\t__ctx->push" ^ (script_type t opt) ^ "(" ^ (keyword_remap name) ^ ");\n" ); + ) f_args; + output_cpp ("\t\t" ^ ret ^ "__ctx->run" ^ (script_type return_t false) ^ "(" ^ vtable ^ ");\n" ); + output_cpp ("\t} else " ^ ret ); + + + if (class_def.cl_interface) then begin + output_cpp (" " ^ delegate ^ "__Field(HX_CSTRING(\"" ^ field.cf_name ^ "\"), hx::paccNever)"); + if (List.length names <= 5) then + output_cpp ("->__run(" ^ (String.concat "," names) ^ ");") + else + output_cpp ("->__Run(" ^ args_varray ^ ");"); + end else + output_cpp (class_name ^ "::" ^ name ^ "(" ^ (String.concat "," names)^ ");"); + if (return_type<>"void") then + output_cpp "return null();"; + output_cpp "}\n"; + if (class_def.cl_interface) && not dynamic_interface_closures then begin + output_cpp (" Dynamic " ^ name ^ "_dyn() { return mDelegate->__Field(HX_CSTRING(\"" ^ field.cf_name ^ "\"), hx::paccNever); }\n\n"); + + end + end + in + + let new_sctipt_functions = if newInteface then + all_virtual_functions class_def + else + current_virtual_functions class_def + in + let sctipt_name = class_name ^ "__scriptable" in + + if newInteface then begin + output_cpp ("class " ^ sctipt_name ^ " : public hx::Object {\n" ); + output_cpp "public:\n"; + end else begin + output_cpp ("class " ^ sctipt_name ^ " : public " ^ class_name ^ " {\n" ); + output_cpp (" typedef "^sctipt_name ^" __ME;\n"); + output_cpp (" typedef "^class_name ^" super;\n"); + let has_funky_toString = List.exists (fun f -> f.cf_name="toString") class_def.cl_ordered_statics || + List.exists (fun f -> f.cf_name="toString" && field_arg_count f <> 0) class_def.cl_ordered_fields in + let super_string = if has_funky_toString then class_name ^ "::super" else class_name in + output_cpp (" typedef "^ super_string ^" __superString;\n"); + if (class_def.cl_interface) then + output_cpp (" HX_DEFINE_SCRIPTABLE_INTERFACE\n") + else begin + output_cpp (" HX_DEFINE_SCRIPTABLE(HX_ARR_LIST" ^ (string_of_int (List.length constructor_var_list) ) ^ ")\n"); + if (not implement_dynamic) then + output_cpp "\tHX_DEFINE_SCRIPTABLE_DYNAMIC;\n"; + end; + end; + + list_iteri dump_script_field functions; + output_cpp ("};\n\n"); + + let sigs = Hashtbl.create 0 in + + let static_functions = (List.filter (fun f-> not (is_data_member f) ) reflect_static_fields) in + let all_script_functions = (List.map (fun (f,_,_)->f) new_sctipt_functions) @ static_functions in + + if (List.length all_script_functions) > 0 then begin + List.iter (fun (f,_,_) -> + let s = generate_script_function false f ("__s_" ^f.cf_name) (keyword_remap f.cf_name) in + Hashtbl.add sigs f.cf_name s + ) new_sctipt_functions; + + let dump_script_static f = + let s = generate_script_function true f ("__s_" ^f.cf_name) (keyword_remap f.cf_name) in + Hashtbl.add sigs f.cf_name s + in + List.iter dump_script_static class_def.cl_ordered_statics; + + output_cpp "static hx::ScriptNamedFunction __scriptableFunctions[] = {\n"; + let dump_func f isStaticFlag = + let s = try Hashtbl.find sigs f.cf_name with Not_found -> "v" in + output_cpp (" hx::ScriptNamedFunction(\"" ^ f.cf_name ^ "\",__s_" ^ f.cf_name ^ ",\"" ^ s ^ "\", " ^ isStaticFlag ^ " ),\n" ) + in + List.iter (fun (f,_,_) -> dump_func f "false") new_sctipt_functions; + List.iter (fun f -> dump_func f "true") static_functions; + output_cpp " hx::ScriptNamedFunction(0,0,0) };\n"; + end else + output_cpp "static hx::ScriptNamedFunction *__scriptableFunctions = 0;\n"; + + if newInteface then begin + output_cpp ("\n\n" ^ class_name ^ " " ^ class_name ^ "_scriptable = {\n"); + List.iter (fun (f,args,return_type) -> + let cast = cpp_tfun_signature ctx true args return_type in + output_cpp ("\t" ^ cast ^ "&" ^ sctipt_name ^ "::" ^ (keyword_remap f.cf_name) ^ ",\n") + ) new_sctipt_functions; + output_cpp ("};\n"); + end; + + end; + + + let class_name_text = join_class_path class_path "." in + + (* Initialise static in boot function ... *) + if (not class_def.cl_interface && not nativeGen) then begin + (* Remap the specialised "extern" classes back to the generic names *) + output_cpp ("hx::Class " ^ class_name ^ "::__mClass;\n\n"); + if (scriptable) then begin + (match class_def.cl_constructor with + | Some field -> + let signature = generate_script_function false field "__script_construct_func" "__construct" in + output_cpp ("hx::ScriptFunction " ^ class_name ^ "::__script_construct(__script_construct_func,\"" ^ signature ^ "\");\n"); + | _ -> + output_cpp ("hx::ScriptFunction " ^ class_name ^ "::__script_construct(0,0);\n"); + ); + end; + + let reflective_statics = List.filter (reflective class_def) implemented_fields in + let sStaticFields = if List.length reflective_statics > 0 then begin + output_cpp ("static ::String " ^ class_name ^ "_sStaticFields[] = {\n"); + List.iter dump_field_name reflective_statics; + output_cpp "\t::String(null())\n};\n\n"; + class_name ^ "_sStaticFields"; + end else + "0 /* sStaticFields */" + in + + output_cpp ("void " ^ class_name ^ "::__register()\n{\n"); + output_cpp ("\thx::Object *dummy = new " ^ class_name ^ ";\n"); + output_cpp ("\t" ^ class_name ^ "::_hx_vtable = *(void **)dummy;\n"); + output_cpp ("\thx::Static(__mClass) = new hx::Class_obj();\n"); + output_cpp ("\t__mClass->mName = " ^ (str class_name_text) ^ ";\n"); + output_cpp ("\t__mClass->mSuper = &super::__SGetClass();\n"); + output_cpp ("\t__mClass->mConstructEmpty = &__CreateEmpty;\n"); + output_cpp ("\t__mClass->mConstructArgs = &__Create;\n"); + output_cpp ("\t__mClass->mGetStaticField = &" ^ ( + if (has_get_static_field class_def) then class_name ^ "::__GetStatic;\n" else "hx::Class_obj::GetNoStaticField;\n" )); + output_cpp ("\t__mClass->mSetStaticField = &" ^ ( + if (has_set_static_field class_def) then class_name ^ "::__SetStatic;\n" else "hx::Class_obj::SetNoStaticField;\n" )); + output_cpp ("\t__mClass->mMarkFunc = " ^ class_name ^ "_sMarkStatics;\n"); + output_cpp ("\t__mClass->mStatics = hx::Class_obj::dupFunctions(" ^ sStaticFields ^ ");\n"); + output_cpp ("\t__mClass->mMembers = hx::Class_obj::dupFunctions(" ^ sMemberFields ^ ");\n"); + output_cpp ("\t__mClass->mCanCast = hx::TCanCast< " ^ class_name ^ " >;\n"); + output_cpp ("#ifdef HXCPP_VISIT_ALLOCS\n\t__mClass->mVisitFunc = " ^ class_name ^ "_sVisitStatics;\n#endif\n"); + output_cpp ("#ifdef HXCPP_SCRIPTABLE\n\t__mClass->mMemberStorageInfo = " ^ class_name ^ "_sMemberStorageInfo;\n#endif\n"); + output_cpp ("#ifdef HXCPP_SCRIPTABLE\n\t__mClass->mStaticStorageInfo = " ^ class_name ^ "_sStaticStorageInfo;\n#endif\n"); + output_cpp ("\thx::_hx_RegisterClass(__mClass->mName, __mClass);\n"); + if (scriptable) then + output_cpp (" HX_SCRIPTABLE_REGISTER_CLASS(\""^class_name_text^"\"," ^ class_name ^ ");\n"); + Hashtbl.iter (fun _ intf_def -> + output_cpp ("\tHX_REGISTER_VTABLE_OFFSET( " ^ class_name ^ "," ^ (join_class_path_remap intf_def.cl_path "::")^ ");\n"); + ) native_implemented; + output_cpp ("}\n\n"); + end else if not nativeGen then begin + output_cpp ("hx::Class " ^ class_name ^ "::__mClass;\n\n"); + + output_cpp ("void " ^ class_name ^ "::__register()\n{\n"); + + output_cpp ("\thx::Static(__mClass) = new hx::Class_obj();\n"); + output_cpp ("\t__mClass->mName = " ^ (str class_name_text) ^ ";\n"); + output_cpp ("\t__mClass->mSuper = &super::__SGetClass();\n"); + output_cpp ("\t__mClass->mMarkFunc = " ^ class_name ^ "_sMarkStatics;\n"); + (*output_cpp ("\t__mClass->mStatics = hx::Class_obj::dupFunctions(" ^ sStaticFields ^ ");\n");*) + output_cpp ("\t__mClass->mMembers = hx::Class_obj::dupFunctions(" ^ sMemberFields ^ ");\n"); + output_cpp ("\t__mClass->mCanCast = hx::TIsInterface< (int)" ^ (cpp_class_hash class_def) ^ " >;\n"); + output_cpp ("#ifdef HXCPP_VISIT_ALLOCS\n\t__mClass->mVisitFunc = " ^ class_name ^ "_sVisitStatics;\n#endif\n"); + output_cpp ("\thx::_hx_RegisterClass(__mClass->mName, __mClass);\n"); + if (scriptable) then + output_cpp (" HX_SCRIPTABLE_REGISTER_INTERFACE(\""^class_name_text^"\"," ^ class_name ^ ");\n"); + output_cpp ("}\n\n"); + end; + + if (has_boot_field class_def) then begin + output_cpp ("void " ^ class_name ^ "::__boot()\n{\n"); + + List.iter (gen_field_init ctx class_def ) (List.filter should_implement_field class_def.cl_ordered_statics); + + output_cpp ("}\n\n"); + end; + + + gen_close_namespace output_cpp class_path; + + if class_def.cl_interface && has_meta_key class_def.cl_meta Meta.ObjcProtocol then begin + let full_class_name = ("::" ^ (join_class_path_remap class_path "::") ) ^ "_obj" in + let protocol = get_meta_string class_def.cl_meta Meta.ObjcProtocol in + generate_protocol_delegate ctx class_def output_cpp; + output_cpp ("id<" ^ protocol ^ "> " ^ full_class_name ^ "::_hx_toProtocol(Dynamic inImplementation) {\n"); + output_cpp ("\treturn [ [_hx_" ^ protocol ^ "_delegate alloc] initWithImplementation:inImplementation.mPtr];\n"); + output_cpp ("}\n\n"); + end; + + + cpp_file#close; + in + (* + Header code + *) + let generate_class_header () = + let common_ctx = baseCtx.ctx_common in + let class_path = class_def.cl_path in + let nativeGen = has_meta_key class_def.cl_meta Meta.NativeGen in + let class_name = (snd class_path) ^ (if nativeGen then "" else "_obj") in + let smart_class_name = (snd class_path) in + let scriptable = inScriptable && not class_def.cl_private in + (*let cpp_file = new_cpp_file common_ctx.file class_path in*) + let debug = if (has_meta_key class_def.cl_meta Meta.NoDebug) || ( Common.defined baseCtx.ctx_common Define.NoDebug) + then 0 else 1 in + + let h_file = new_header_file common_ctx common_ctx.file class_path in + let ctx = file_context baseCtx h_file debug true in + + + let parent,super = match class_def.cl_super with + | Some (klass,params) -> + let name = (tcpp_to_string_suffix "_obj" (cpp_instance_type ctx klass params) ) in + (if class_def.cl_interface && nativeGen then "virtual " else "" ) ^ name, name + | None when nativeGen && class_def.cl_interface -> "virtual hx::NativeInterface", "hx::NativeInterface" + | None when class_def.cl_interface -> "", "hx::Object" + | None when nativeGen -> "", "" + | None -> "hx::Object", "hx::Object" + in + let output_h = (h_file#write) in + let def_string = join_class_path class_path "_" in + + + begin_header_file (h_file#write_h) def_string nativeGen; + + (* Include the real header file for the super class *) + (match class_def.cl_super with + | Some super -> + let super_path = (fst super).cl_path in + h_file#add_include super_path + | _ -> () ); + + (* And any interfaces ... *) + List.iter (fun imp-> + let interface = fst imp in + let include_file = get_meta_string_path interface.cl_meta Meta.Include in + h_file#add_include (if include_file="" then interface.cl_path else path_of_string include_file) ) + (real_interfaces class_def.cl_implements); + + (* Only need to forward-declare classes that are mentioned in the header file + (ie, not the implementation) *) + let header_referenced,header_flags = find_referenced_types_flags ctx (TClassDecl class_def) "*" super_deps (Hashtbl.create 0) true false scriptable in + List.iter2 ( fun r f -> gen_forward_decl h_file r f ) header_referenced header_flags; + output_h "\n"; + + output_h ( get_class_code class_def Meta.HeaderCode ); + let inc = get_meta_string_path class_def.cl_meta Meta.HeaderInclude in + if (inc<>"") then + output_h ("#include \"" ^ inc ^ "\"\n"); + + gen_open_namespace output_h class_path; + output_h "\n\n"; + output_h ( get_class_code class_def Meta.HeaderNamespaceCode ); + + let extern_class = Common.defined common_ctx Define.DllExport in + let attribs = "HXCPP_" ^ (if extern_class then "EXTERN_" else "") ^ "CLASS_ATTRIBUTES" in + + let dump_native_interfaces () = + List.iter ( fun(c,params) -> + output_h (" , public virtual " ^ (join_class_path c.cl_path "::") ) + ) (List.filter (fun (t,_) -> is_native_gen_class t) class_def.cl_implements); + in + + if (class_def.cl_interface && not nativeGen) then begin + output_h ("class " ^ attribs ^ " " ^ class_name ^ " {\n"); + output_h "\tpublic:\n"; + output_h ("\t\ttypedef " ^ super ^ " super;\n"); + end else if (super="") then begin + output_h ("class " ^ attribs ^ " " ^ class_name); + dump_native_interfaces(); + output_h "\n{\n\tpublic:\n"; + end else begin + output_h ("class " ^ attribs ^ " " ^ class_name ^ " : public " ^ parent ); + dump_native_interfaces(); + output_h "\n{\n\tpublic:\n"; + if not nativeGen then begin + output_h ("\t\ttypedef " ^ super ^ " super;\n"); + output_h ("\t\ttypedef " ^ class_name ^ " OBJ_;\n"); + end + end; + + + + if (not class_def.cl_interface && not nativeGen) then begin + output_h ("\t\t" ^ class_name ^ "();\n"); + output_h "\n\tpublic:\n"; + output_h ("\t\tenum { _hx_ClassId = " ^ classIdTxt ^ " };\n\n"); + output_h ("\t\tvoid __construct(" ^ constructor_type_args ^ ");\n"); + output_h ("\t\tinline void *operator new(size_t inSize, bool inContainer=" ^ isContainer ^",const char *inName=" ^ gcName ^ ")\n" ); + output_h ("\t\t\t{ return hx::Object::operator new(inSize,inContainer,inName); }\n" ); + output_h ("\t\tinline void *operator new(size_t inSize, int extra)\n" ); + output_h ("\t\t\t{ return hx::Object::operator new(inSize+extra," ^ isContainer ^ "," ^ gcName ^ "); }\n" ); + if inlineContructor then begin + output_h "\n"; + outputConstructor ctx (fun str -> output_h ("\t\t" ^ str) ) true + end else begin + output_h ("\t\tstatic " ^ptr_name^ " __new(" ^constructor_type_args ^");\n"); + output_h ("\t\tstatic " ^ptr_name^ " __alloc(hx::Ctx *_hx_ctx" ^ (if constructor_type_args="" then "" else "," ^constructor_type_args) ^");\n"); + end; + output_h ("\t\tstatic void * _hx_vtable;\n"); + output_h ("\t\tstatic Dynamic __CreateEmpty();\n"); + output_h ("\t\tstatic Dynamic __Create(hx::DynamicArray inArgs);\n"); + if (List.length dynamic_functions > 0) then + output_h ("\t\tstatic void __alloc_dynamic_functions(hx::Ctx *_hx_alloc," ^ class_name ^ " *_hx_obj);\n"); + if (scriptable) then + output_h ("\t\tstatic hx::ScriptFunction __script_construct;\n"); + output_h ("\t\t//~" ^ class_name ^ "();\n\n"); + output_h ("\t\tHX_DO_RTTI_ALL;\n"); + if (has_get_member_field class_def) then + output_h ("\t\thx::Val __Field(const ::String &inString, hx::PropertyAccess inCallProp);\n"); + if (has_get_static_field class_def) then + output_h ("\t\tstatic bool __GetStatic(const ::String &inString, Dynamic &outValue, hx::PropertyAccess inCallProp);\n"); + if (has_set_member_field class_def) then + output_h ("\t\thx::Val __SetField(const ::String &inString,const hx::Val &inValue, hx::PropertyAccess inCallProp);\n"); + if (has_set_static_field class_def) then + output_h ("\t\tstatic bool __SetStatic(const ::String &inString, Dynamic &ioValue, hx::PropertyAccess inCallProp);\n"); + if (has_get_fields class_def) then + output_h ("\t\tvoid __GetFields(Array< ::String> &outFields);\n"); + + if (implement_dynamic) then + output_h ("\t\tHX_DECLARE_IMPLEMENT_DYNAMIC;\n"); + output_h ("\t\tstatic void __register();\n"); + if (override_iteration) then begin + output_h ("\t\tvoid __Mark(HX_MARK_PARAMS);\n"); + output_h ("\t\tvoid __Visit(HX_VISIT_PARAMS);\n"); + end; + + if (implementsNative) then begin + output_h ("\n\t\tHX_NATIVE_IMPLEMENTATION\n"); + List.iter (fun field -> + match follow field.cf_type, field.cf_kind with + | _, Method MethDynamic -> () + | TFun (args,return_type), _ -> + let retVal = ctx_type_string ctx return_type in + let ret = if retVal="void" then "" else "return " in + let name = keyword_remap field.cf_name in + let argNames = List.map (fun (name,_,_) -> keyword_remap name ) args in + output_h ( "\t\t" ^ retVal ^" " ^ name ^ "( " ^ ctx_tfun_arg_list ctx true args ^ ") {\n"); + output_h ( "\t\t\t" ^ ret ^ "super::" ^ name ^ "( " ^ (String.concat "," argNames) ^ ");\n\t\t}\n"); + | _ -> () + ) neededInterfaceFunctions; + output_h ("\n"); + end; + + output_h ("\t\tbool _hx_isInstanceOf(int inClassId);\n"); + if ( (List.length implemented) > 0 ) then begin + output_h "\t\tvoid *_hx_getInterface(int inHash);\n"; + output_h (String.concat "\n" !header_glue); + end; + + + if (has_init_field class_def) then + output_h "\t\tstatic void __init__();\n\n"; + output_h ("\t\t::String __ToString() const { return " ^ (str smart_class_name) ^ "; }\n\n"); + end else if not nativeGen then begin + output_h ("\t\tHX_DO_INTERFACE_RTTI;\n\n"); + end else begin + (* native interface *) ( ) + end; + + if (has_boot_field class_def) then + output_h ("\t\tstatic void __boot();\n"); + + + (match class_def.cl_array_access with + | Some t -> output_h ("\t\ttypedef " ^ (type_string t) ^ " __array_access;\n") + | _ -> ()); + + + List.iter (gen_member_def ctx class_def true class_def.cl_interface) (List.filter should_implement_field class_def.cl_ordered_statics); + + if class_def.cl_interface then begin + List.iter (fun (field,_,_) -> gen_member_def ctx class_def false true field) functions; + end else begin + List.iter (gen_member_def ctx class_def false false) (List.filter should_implement_field class_def.cl_ordered_fields); + end; + + if class_def.cl_interface && has_meta_key class_def.cl_meta Meta.ObjcProtocol then begin + let protocol = get_meta_string class_def.cl_meta Meta.ObjcProtocol in + output_h ("\t\tstatic id<" ^ protocol ^ "> _hx_toProtocol(Dynamic inImplementation);\n"); + end; + + + output_h ( get_class_code class_def Meta.HeaderClassCode ); + output_h "};\n\n"; + + gen_close_namespace output_h class_path; + + end_header_file output_h def_string; + h_file#close; + + in + + (* create header and cpp files *) + if not (nativeGen && class_def.cl_interface) then + generate_class_cpp (); + generate_class_header () +;; + +let generate_class_deps ctx class_def super_deps constructor_deps = + find_referenced_types ctx (TClassDecl class_def) super_deps constructor_deps false true false +;; + + + + +let write_resources common_ctx = + + let idx = ref 0 in + + Hashtbl.iter (fun _ data -> + let id = "__res_" ^ (string_of_int !idx) in + let resource_file = new_cpp_file common_ctx common_ctx.file (["resources"],id) in + resource_file#write "namespace hx {\n"; + resource_file#write_i ("unsigned char " ^ id ^ "[] = {\n"); + resource_file#write_i "0xff, 0xff, 0xff, 0xff,\n"; + for i = 0 to String.length data - 1 do + let code = Char.code (String.unsafe_get data i) in + resource_file#write (Printf.sprintf "%d," code); + if ( (i mod 10) = 9) then resource_file#write "\n"; + done; + resource_file#write ("0x00 };\n"); + incr idx; + resource_file#write ("}\n"); + resource_file#close; + ) common_ctx.resources; + + + let resource_file = new_cpp_file common_ctx common_ctx.file ([],"__resources__") in + resource_file#write_h "#include \n\n"; + resource_file#write "namespace hx {\n"; + + idx := 0; + Hashtbl.iter (fun _ data -> + let id = "__res_" ^ (string_of_int !idx) in + resource_file#write_i ("extern unsigned char " ^ id ^ "[];\n"); + incr idx; + ) common_ctx.resources; + + resource_file#write "}\n\n"; + + idx := 0; + resource_file#write "hx::Resource __Resources[] = "; + resource_file#begin_block; + Hashtbl.iter (fun name data -> + let id = "__res_" ^ (string_of_int !idx) in + resource_file#write_i + ("{ " ^ (str name) ^ "," ^ (string_of_int (String.length data)) ^ "," ^ + "hx::" ^ id ^ " + 4 },\n"); + incr idx; + ) common_ctx.resources; + + resource_file#write_i "{ ::String(null()),0,0 }\n"; + resource_file#end_block_line; + resource_file#write ";\n\n"; + resource_file#write "namespace hx { Resource *GetResources() { return __Resources; } }\n"; + resource_file#close;; + + + +let write_build_data common_ctx filename classes main_deps boot_deps build_extra extern_src exe_name = + let buildfile = open_out filename in + let include_prefix = get_include_prefix common_ctx true in + let add_class_to_buildfile class_path deps fileXml = + let cpp = (join_class_path class_path "/") ^ (source_file_extension common_ctx) in + output_string buildfile ( " "" then output_string buildfile fileXml; + output_string buildfile (">\n" ); + let project_deps = List.filter (fun path -> not (is_internal_class path) ) deps in + List.iter (fun path-> output_string buildfile (" file + | _ -> "include/" ^ include_prefix ^ (join_class_path path "/") ^ ".h" ) + ^ "\"/>\n") ) project_deps; + output_string buildfile ( " \n" ) + in + let add_classdef_to_buildfile (class_path, deps, object_def ) = + let fileXml = match object_def with + | TClassDecl class_def -> get_meta_string class_def.cl_meta Meta.FileXml + | TEnumDecl enum_def -> get_meta_string enum_def.e_meta Meta.FileXml + | _ -> "" + in + add_class_to_buildfile class_path deps fileXml + in + + output_string buildfile "\n"; + output_string buildfile ("\n"); + output_string buildfile "\n"; + output_string buildfile "\n"; + List.iter add_classdef_to_buildfile classes; + add_class_to_buildfile ( [] , "__boot__") boot_deps ""; + add_class_to_buildfile ( [] , "__files__") [] "if='HXCPP_DEBUGGER'"; + output_string buildfile (" \n"); + add_class_to_buildfile ( [] , "__resources__") [] ""; + output_string buildfile "\n"; + output_string buildfile "\n"; + output_string buildfile "\n"; + add_class_to_buildfile ( [] , "__lib__") main_deps ""; + output_string buildfile "\n"; + output_string buildfile "\n"; + output_string buildfile "\n"; + add_class_to_buildfile ( [] , "__main__") main_deps ""; + output_string buildfile "\n"; + output_string buildfile "\n"; + let idx = ref 0 in + let ext = source_file_extension common_ctx in + Hashtbl.iter (fun _ data -> + let id = "__res_" ^ (string_of_int !idx) in + output_string buildfile ("\n"); + incr idx; + ) common_ctx.resources; + output_string buildfile "\n"; + output_string buildfile "\n"; + List.iter (fun src -> output_string buildfile ("\n") ) extern_src; + output_string buildfile "\n"; + output_string buildfile ("\n"); + output_string buildfile "\n"; + output_string buildfile build_extra; + output_string buildfile "\n"; + close_out buildfile;; + +let write_build_options common_ctx filename defines = + let writer = cached_source_writer common_ctx filename in + PMap.iter ( fun name value -> match name with + | "true" | "sys" | "dce" | "cpp" | "debug" -> () + | _ -> writer#write (name ^ "="^(escape_command value)^ "\n" ) ) defines; + let cmd = Unix.open_process_in "haxelib path hxcpp" in + writer#write ("hxcpp=" ^ (Pervasives.input_line cmd)); + Pervasives.ignore (Unix.close_process_in cmd); + writer#close;; + +let create_member_types common_ctx = + let result = Hashtbl.create 0 in + List.iter (fun object_def -> + (match object_def with + | TClassDecl class_def when not class_def.cl_interface -> + let rec add_override to_super = + let class_name = (join_class_path to_super.cl_path ".") in + List.iter (fun member -> Hashtbl.add result (class_name ^ "." ^ member.cf_name) "virtual " ) class_def.cl_ordered_fields; + match to_super.cl_super with + | Some super -> add_override (fst super) + | _ -> () + in + (match class_def.cl_super with Some super -> add_override (fst super) | _->()) + | _ -> () + ) ) common_ctx.types; + result;; + +(* Builds inheritance tree, so header files can include parents defs. *) +let create_super_dependencies common_ctx = + let result = Hashtbl.create 0 in + List.iter (fun object_def -> + (match object_def with + | TClassDecl class_def when not class_def.cl_extern -> + let deps = ref [] in + (match class_def.cl_super with Some super -> + if not (fst super).cl_extern then + deps := ((fst super).cl_path) :: !deps + | _ ->() ); + List.iter (fun imp -> if not (fst imp).cl_extern then deps := (fst imp).cl_path :: !deps) (real_non_native_interfaces class_def.cl_implements); + Hashtbl.add result class_def.cl_path !deps; + | TEnumDecl enum_def when not enum_def.e_extern -> + Hashtbl.add result enum_def.e_path []; + | _ -> () ); + ) common_ctx.types; + result;; + +let create_constructor_dependencies common_ctx = + let result = Hashtbl.create 0 in + List.iter (fun object_def -> + (match object_def with + | TClassDecl class_def when not class_def.cl_extern -> + (match class_def.cl_constructor with + | Some func_def -> Hashtbl.add result class_def.cl_path func_def + | _ -> () ) + | _ -> () ); + ) common_ctx.types; + result;; + + +let is_assign_op op = + match op with + | OpAssign + | OpAssignOp _ -> true + | _ -> false +;; + +let rec script_type_string haxe_type = + match haxe_type with + | TType ({ t_path = ([],"Null") },[t]) -> + (match follow t with + | TAbstract ({ a_path = [],"Int" },_) + | TAbstract ({ a_path = [],"Float" },_) + | TAbstract ({ a_path = [],"Bool" },_) -> "Dynamic" + | _ -> script_type_string t) + | TInst ({cl_path=[],"Null"},[t]) -> + (match follow t with + | TAbstract ({ a_path = [],"Int" },_) + | TAbstract ({ a_path = [],"Float" },_) + | TAbstract ({ a_path = [],"Bool" },_) -> "Dynamic" + | _ -> script_type_string t ) + | _ -> + match follow haxe_type with + | TType ({t_path = [],"Array"},params) -> "Array" + | TInst ({cl_path=[],"Array"},params) -> + (match params with + | [t] -> + (match type_string_suff "" t false with + | "int" -> "Array.int" + | "Float" -> "Array.Float" + | "bool" -> "Array.bool" + | "::String" -> "Array.String" + | "unsigned char" -> "Array.unsigned char" + | "::cpp::UInt8" -> "Array.unsigned char" + | "Dynamic" -> "Array.Any" + | _ -> "Array.Object" + ) + | _ -> "Array.Object" + ) + | TAbstract (abs,pl) when abs.a_impl <> None -> + script_type_string (Abstract.get_underlying_type abs pl); + | _ -> + type_string_suff "" haxe_type false +;; + +type array_of = + | ArrayInterface of int + | ArrayData of string + | ArrayObject + | ArrayAny + | ArrayNone +;; + +let is_template_type t = + false +;; + +type cppia_op = + | IaFunction + | IaVar + | IaToInterface + | IaToDynArray + | IaToDataArray + | IaToInterfaceArray + | IaFun + | IaCast + | IaTCast + | IaBlock + | IaBreak + | IaContinue + | IaIsNull + | IaNotNull + | IaSet + | IaCall + | IaCallGlobal + | IaCallStatic + | IaCallMember + | IaCallSuper + | IaCallThis + | IaCallSuperNew + | IaCreateEnum + | IaADef + | IaIf + | IaIfElse + | IaFStatic + | IaFName + | IaFThisInst + | IaFLink + | IaFThisName + | IaFEnum + | IaThrow + | IaArrayI + | IaPlusPlus + | IaPlusPlusPost + | IaMinusMinus + | IaMinusMinusPost + | IaNeg + | IaBitNot + | IaLogicNot + | IaTVars + | IaVarDecl + | IaVarDeclI + | IaNew + | IaReturn + | IaRetVal + | IaPosInfo + | IaObjDef + | IaClassOf + | IaWhile + | IaFor + | IaEnumI + | IaSwitch + | IaTry + | IaImplDynamic + | IaConstInt + | IaConstFloat + | IaConstString + | IaConstFalse + | IaConstTrue + | IaConstNull + | IaConsThis + | IaConstSuper + | IaCastInt + | IaCastBool + | IaInterface + | IaClass + | IaAccessNormal + | IaAccessNot + | IaAccessResolve + | IaAccessCall + | IaEnum + | IaInline + | IaMain + | IaNoMain + | IaResources + | IaReso + | IaNoCast + | IaAccessCallNative + + | IaBinOp of Ast.binop +;; + +let cppia_op_info = function + | IaFunction -> ("FUNCTION", 1) + | IaVar -> ("VAR", 2) + | IaToInterface -> ("TOINTERFACE", 3) + | IaToDynArray -> ("TODYNARRAY", 4) + | IaToDataArray -> ("TODATAARRAY", 5) + | IaToInterfaceArray -> ("TOINTERFACEARRAY", 6) + | IaFun -> ("FUN", 7) + | IaCast -> ("CAST", 8) + | IaBlock -> ("BLOCK", 9) + | IaBreak -> ("BREAK", 10) + | IaContinue -> ("CONTINUE", 11) + | IaIsNull -> ("ISNULL", 12) + | IaNotNull -> ("NOTNULL", 13) + | IaSet -> ("SET", 14) + | IaCall -> ("CALL", 15) + | IaCallGlobal -> ("CALLGLOBAL", 16) + | IaCallStatic -> ("CALLSTATIC", 17) + | IaCallMember -> ("CALLMEMBER", 18) + | IaCallSuper -> ("CALLSUPER", 19) + | IaCallThis -> ("CALLTHIS", 20) + | IaCallSuperNew -> ("CALLSUPERNEW", 21) + | IaCreateEnum -> ("CREATEENUM", 22) + | IaADef -> ("ADEF", 23) + | IaIf -> ("IF", 24) + | IaIfElse -> ("IFELSE", 25) + | IaFName -> ("FNAME", 27) + | IaFStatic -> ("FSTATIC", 28) + | IaFThisInst -> ("FTHISINST", 29) + | IaFLink -> ("FLINK", 30) + | IaFThisName -> ("FTHISNAME", 31) + | IaFEnum -> ("FENUM", 32) + | IaThrow -> ("THROW", 33) + | IaArrayI -> ("ARRAYI", 34) + | IaPlusPlus -> ("++", 35) + | IaPlusPlusPost -> ("+++", 36) + | IaMinusMinus -> ("--", 37) + | IaMinusMinusPost -> ("---", 38) + | IaNeg -> ("NEG", 39) + | IaBitNot -> ("~", 40) + | IaLogicNot -> ("!", 41) + | IaTVars -> ("TVARS", 42) + | IaVarDecl -> ("VARDECL", 43) + | IaVarDeclI -> ("VARDECLI", 44) + | IaNew -> ("NEW", 45) + | IaReturn -> ("RETURN", 46) + | IaRetVal -> ("RETVAL", 47) + | IaPosInfo -> ("POSINFO", 48) + | IaObjDef -> ("OBJDEF", 49) + | IaClassOf -> ("CLASSOF", 50) + | IaWhile -> ("WHILE", 51) + | IaFor -> ("FOR", 52) + | IaEnumI -> ("ENUMI", 53) + | IaSwitch -> ("SWITCH", 54) + | IaTry -> ("TRY", 55) + | IaImplDynamic -> ("IMPLDYNAMIC", 56) + | IaConstInt -> ("i", 57) + | IaConstFloat -> ("f", 58) + | IaConstString -> ("s", 59) + | IaConstFalse -> ("false", 60) + | IaConstTrue -> ("true", 61) + | IaConstNull -> ("NULL", 62) + | IaConsThis -> ("THIS", 63) + | IaConstSuper -> ("SUPER", 64) + | IaCastInt -> ("CASTINT", 65) + | IaCastBool -> ("CASTBOOL", 66) + | IaInterface -> ("INTERFACE", 67) + | IaClass -> ("CLASS", 68) + | IaAccessNormal -> ("N", 69) + | IaAccessNot -> ("n", 70) + | IaAccessResolve -> ("R", 71) + | IaAccessCall -> ("C", 72) + | IaEnum -> ("ENUM", 73) + | IaInline -> ("INLINE", 74) + | IaMain -> ("MAIN", 75) + | IaNoMain -> ("NOMAIN", 76) + | IaResources -> ("RESOURCES", 77) + | IaReso -> ("RESO", 78) + | IaNoCast -> ("NOCAST", 79) + | IaAccessCallNative -> ("V", 80) + + | IaBinOp OpAdd -> ("+", 101) + | IaBinOp OpMult -> ("*", 102) + | IaBinOp OpDiv -> ("/", 103) + | IaBinOp OpSub -> ("-", 104) + | IaBinOp OpAssign -> ("=", 105) + | IaBinOp OpEq -> ("==", 106) + | IaBinOp OpNotEq -> ("!=", 107) + | IaBinOp OpGte -> (">=", 108) + | IaBinOp OpLte -> ("<=", 109) + | IaBinOp OpGt -> (">", 110) + | IaBinOp OpLt -> ("<", 111) + | IaBinOp OpAnd -> ("&", 112) + | IaBinOp OpOr -> ("|", 113) + | IaBinOp OpXor -> ("^", 114) + | IaBinOp OpBoolAnd -> ("&&", 115) + | IaBinOp OpBoolOr -> ("||", 116) + | IaBinOp OpShr -> (">>", 117) + | IaBinOp OpUShr -> (">>>", 118) + | IaBinOp OpShl -> ("<<", 119) + | IaBinOp OpMod -> ("%", 120) + | IaBinOp OpInterval -> ("...", 121) + | IaBinOp OpArrow -> ("=>", 122) + | IaBinOp OpAssignOp OpAdd -> ("+=", 201) + | IaBinOp OpAssignOp OpMult -> ("*=", 202) + | IaBinOp OpAssignOp OpDiv -> ("/=", 203) + | IaBinOp OpAssignOp OpSub -> ("-=", 204) + + + | IaBinOp OpAssignOp OpAnd -> ("&=", 212) + | IaBinOp OpAssignOp OpOr -> ("|=", 213) + | IaBinOp OpAssignOp OpXor -> ("^=", 214) + | IaBinOp OpAssignOp OpBoolAnd -> ("&&=", 215) + | IaBinOp OpAssignOp OpBoolOr -> ("||=", 216) + | IaBinOp OpAssignOp OpShr -> (">>=", 217) + | IaBinOp OpAssignOp OpUShr -> (">>>=", 218) + | IaBinOp OpAssignOp OpShl -> ("<<=", 219) + | IaBinOp OpAssignOp OpMod -> ("%=", 220) + + | IaBinOp OpAssignOp OpInterval + | IaBinOp OpAssignOp OpAssign + | IaBinOp OpAssignOp OpEq + | IaBinOp OpAssignOp OpNotEq + | IaBinOp OpAssignOp OpGte + | IaBinOp OpAssignOp OpLte + | IaBinOp OpAssignOp OpGt + | IaBinOp OpAssignOp OpLt + | IaBinOp OpAssignOp OpAssignOp _ + | IaBinOp OpAssignOp OpArrow -> assert false + | IaTCast -> ("TCAST", 221) +;; + +class script_writer ctx filename asciiOut = + object(this) + val debug = asciiOut + val doComment = asciiOut && (Common.defined ctx.ctx_common Define.AnnotateSource) + val indent_str = if asciiOut then "\t" else "" + val mutable indent = "" + val mutable indents = [] + val mutable just_finished_block = false + val mutable classCount = 0 + val mutable return_type = TMono(ref None) + val buffer = Buffer.create 0 + val identTable = Hashtbl.create 0 + val fileTable = Hashtbl.create 0 + val identBuffer = Buffer.create 0 + + method stringId name = + try ( Hashtbl.find identTable name ) + with Not_found -> begin + let size = Hashtbl.length identTable in + Hashtbl.add identTable name size; + Buffer.add_string identBuffer ((string_of_int (String.length name)) ^ " " ^ name ^ "\n"); + size; + end + method incClasses = classCount <- classCount +1 + + method stringText name = (string_of_int (this#stringId name)) ^ " " + val typeTable = Hashtbl.create 0 + val typeBuffer = Buffer.create 0 + method typeId name = + let name = if name="::hx::Class" then "::Class" else name in + try ( Hashtbl.find typeTable name ) + with Not_found -> begin + let size = Hashtbl.length typeTable in + Hashtbl.add typeTable name size; + Buffer.add_string typeBuffer ((string_of_int (String.length name)) ^ " " ^ name ^ "\n"); + size; + end + method write str = if asciiOut then + Buffer.add_string buffer str + else begin + let push i = Buffer.add_char buffer (Char.chr i) in + let pushI32 i = push (Int32.to_int (Int32.logand i (Int32.of_int 255))) in + List.iter (fun i -> + if ((Int32.compare i Int32.zero) >= 0) && ((Int32.compare i (Int32.of_int 254)) < 0) then + pushI32 i + else if ((Int32.compare i Int32.zero) >= 0) && ((Int32.compare i (Int32.of_int 65536)) < 0) then begin + push 254; + pushI32 i; + pushI32 (Int32.shift_right i 8); + end else begin + push 255; + pushI32 i; + pushI32 (Int32.shift_right i 8); + pushI32 (Int32.shift_right i 16); + pushI32 (Int32.shift_right i 24); + end + ) (List.map Int32.of_string (Str.split (Str.regexp "[\n\t ]+") str) ); + end; + just_finished_block <- false + method comment text = if doComment then this#write ("# " ^ text ^ "\n") + method commentOf text = if doComment then " # " ^ text else "" + method typeTextString typeName = (string_of_int (this#typeId typeName)) ^ " " + method typeText typeT = (string_of_int (this#typeId (script_type_string typeT))) ^ " " + method writeType typeT = this#write (this#typeText typeT) + method boolText value = if value then "1" else "0" + method writeBool value = this#write (if value then "1 " else "0 ") + method staticText value = if value then "1" else "0" + method writeData str = Buffer.add_string buffer str; + method wint ival = this#write ((string_of_int ival)^" ") + method ident name = this#wint (this#stringId name) + method instText clazz = match clazz.cl_path with + | ([],"Array") -> string_of_int (this#typeId "Array< ::Dynamic >") ^ " " + | _ -> this#typeText (TInst(clazz,[])) + method instName clazz = this#write (this#instText clazz) + method enumText e = this#typeText (TEnum(e,[])) + method enumName e = this#write (this#enumText e) + method close = + let out_file = open_out_bin filename in + output_string out_file (if asciiOut then "CPPIA\n" else "CPPIB\n"); + let idents = Buffer.contents identBuffer in + output_string out_file ((string_of_int (Hashtbl.length identTable)) ^ "\n"); + output_string out_file idents; + let types = Buffer.contents typeBuffer in + output_string out_file ((string_of_int (Hashtbl.length typeTable)) ^ "\n"); + output_string out_file types; + output_string out_file ( (string_of_int classCount) ^ "\n" ); + let contents = Buffer.contents buffer in + output_string out_file contents; + close_out out_file + method fileId file = + try ( Hashtbl.find fileTable file ) + with Not_found -> begin + let stripped_file = strip_file ctx.ctx_common file in + let result = this#stringId stripped_file in + Hashtbl.add fileTable file result; + result; + end + method constText c = match c with + | TInt i -> (this#op IaConstInt) ^ (Printf.sprintf "%ld " i) + | TFloat f -> (this#op IaConstFloat) ^ (this#stringText f) + | TString s -> (this#op IaConstString) ^ (this#stringText s) + | TBool true -> (this#op IaConstTrue) + | TBool false -> (this#op IaConstFalse) + | TNull -> (this#op IaConstNull) + | TThis -> (this#op IaConsThis) + | TSuper -> (this#op IaConstSuper) + + method get_array_type t = + match follow t with + | TInst ({cl_path=[],"Array"},[param]) -> + let typeName = type_string_suff "" param false in + (match typeName with + | "::String" -> ArrayData "String" + | "int" | "Float" | "bool" | "String" | "unsigned char" | "::cpp::UInt8" -> + ArrayData typeName + | "cpp::ArrayBase" | "cpp::VirtualArray" | "Dynamic" -> ArrayAny + | _ when is_interface_type param -> ArrayInterface (this#typeId (script_type_string param)) + | _ -> ArrayObject + ) + | TAbstract (abs,pl) when abs.a_impl <> None -> + this#get_array_type (Abstract.get_underlying_type abs pl); + | _ -> ArrayNone; + + method pushReturn inType = + let oldReturnType = return_type in + return_type <- inType; + fun () -> return_type <- oldReturnType; + method fileText file = string_of_int (this#fileId file) + method indent_one = this#write indent_str + method push_indent = indents <- indent_str::indents; indent <- String.concat "" indents + method pop_indent = match indents with + | h::tail -> indents <- tail; indent <- String.concat "" indents + | [] -> indent <- "/*?*/"; + method write_i x = this#write (indent ^ x) + method get_indent = indent + method begin_expr = this#push_indent + method end_expr = if not just_finished_block then this#write "\n"; this#pop_indent; just_finished_block <- true + method op x = match cppia_op_info x with + | (name,index) -> (if debug then name else string_of_int index) ^ " " + method writeOp o = this#write (this#op o) + method writeOpLine o = this#write ((this#op o) ^ "\n") + method voidFunc isStatic isDynamic funcName fieldExpression = + this#comment funcName; + this#write ( (this#op IaFunction) ^ (this#staticText isStatic) ^ " " ^(this#boolText isDynamic) ^ " " ^(this#stringText funcName) ^ " "); + this#write ((this#typeTextString "Void") ^ "0\n"); + this#gen_expression fieldExpression + method func isStatic isDynamic funcName ret args isInterface fieldExpression = + this#comment funcName; + this#write ( (this#op IaFunction) ^ (this#staticText isStatic) ^ " " ^(this#boolText isDynamic) ^ " " ^(this#stringText funcName) ^ " "); + this#write ((this#typeText ret) ^ (string_of_int (List.length args)) ^ " "); + List.iter (fun (name,opt,typ) -> this#write ( (this#stringText name) ^ (this#boolText opt) ^ " " ^ (this#typeText typ) ^ " " )) args; + this#write "\n"; + if (not isInterface) then begin + match fieldExpression with + | Some ({ eexpr = TFunction function_def } as e) -> this#gen_expression e + | _ -> print_endline ("Missing function body for " ^ funcName ); + end + method var readAcc writeAcc isExtern isStatic name varType varExpr = + this#write ( (this#op IaVar) ^ (this#staticText isStatic) ^ " " ^ (this#op readAcc) ^ (this#op writeAcc) ^ + (this#boolText isExtern) ^ " " ^ (this#stringText name)^ (this#typeText varType) ^ + (match varExpr with Some _ -> "1" | _ -> "0" ) ^ + (if doComment then (" # " ^ name ^ "\n") else "\n") ); + match varExpr with + | Some expression -> this#gen_expression expression + | _ -> () + method implDynamic = this#writeOpLine IaImplDynamic; + method writeVar v = + this#ident v.v_name; + this#wint v.v_id; + this#writeBool v.v_capture; + this#writeType v.v_type; + method writeList prefix len = this#write (prefix ^" " ^ (string_of_int (len)) ^ "\n"); + method writePos expr = if debug then + this#write ( (this#fileText expr.epos.pfile) ^ "\t" ^ (string_of_int (Lexer.get_error_line expr.epos) ) ^ indent); + method checkCast toType expr forceCast fromGenExpression= + let write_cast text = + if (not fromGenExpression) then + this#writePos expr; + this#write (text ^"\n" ); + this#begin_expr; + this#gen_expression expr; + this#end_expr; + true; + in + let was_cast = + if (is_interface_type toType) then begin + if (is_dynamic_in_cppia ctx expr) then begin + write_cast ( (this#op IaToInterface) ^ (this#typeText toType) ^ " " ^ (this#typeTextString "Dynamic") ) + end else if (not (is_matching_interface_type toType expr.etype)) then begin + write_cast ( (this#op IaToInterface) ^ (this#typeText toType) ^ " " ^ (this#typeText expr.etype) ) + end else + false + end else begin + let get_array_expr_type expr = + if is_dynamic_in_cppia ctx expr then + ArrayNone + else + this#get_array_type expr.etype + in + match (this#get_array_type toType), (get_array_expr_type expr) with + | ArrayAny, _ -> false + | ArrayObject, ArrayData _ -> write_cast (this#op IaToDynArray) + | ArrayObject, ArrayObject -> false + | ArrayObject, ArrayNone + | ArrayObject, ArrayAny -> write_cast ((this#op IaToDataArray) ^ (this#typeTextString ("Array.Object"))) + | ArrayData t, ArrayNone + | ArrayData t, ArrayObject + | ArrayData t, ArrayAny -> write_cast ((this#op IaToDataArray) ^ (this#typeTextString ("Array." ^ t))) + | ArrayInterface t, ArrayNone + | ArrayInterface t, ArrayAny -> write_cast ((this#op IaToInterfaceArray) ^ (string_of_int t)) + | _,_ -> (* a0,a1 -> + let arrayString a = + match a with + | ArrayNone -> "ArrayNone" + | ArrayAny -> "ArrayAny" + | ArrayObject -> "ArrayObject" + | ArrayData _ -> "ArrayData" + | ArrayInterface _ -> "ArrayInterface" + in + this#write ("NOCAST " ^ (arrayString a0) ^ "=" ^ (arrayString a1)); *) + false + end + in + + if (not was_cast) then begin + if (forceCast) then begin + let op =match (type_string expr.etype) with + | "int" -> IaCastInt + | "bool" -> IaCastBool + | _ when is_interface_type toType -> IaNoCast + | _ -> IaCast + in + this#writeOpLine op; + end; + this#gen_expression expr; + end + method gen_expression expr = + let expression = remove_parens expr in + this#begin_expr; + (*this#write ( (this#fileText expression.epos.pfile) ^ "\t" ^ (string_of_int (Lexer.get_error_line expression.epos) ) ^ indent);*) + this#writePos expression; + (match expression.eexpr with + | TFunction function_def -> this#write ( (this#op IaFun) ^ (this#typeText function_def.tf_type) ^ (string_of_int (List.length function_def.tf_args)) ^ "\n" ); + List.iter (fun(arg,init) -> + this#write (indent ^ indent_str ); + this#writeVar arg; + match init with + | Some const -> this#write ("1 " ^ (this#constText const) ^ "\n") + | _ -> this#write "0\n"; + ) function_def.tf_args; + let pop = this#pushReturn function_def.tf_type in + this#gen_expression function_def.tf_expr; + pop (); + | TBlock expr_list -> this#writeList (this#op IaBlock) (List.length expr_list); + List.iter this#gen_expression expr_list; + | TConst const -> this#write (this#constText const) + | TBreak -> this#writeOp IaBreak + | TContinue -> this#writeOp IaContinue + + | TBinop (op,e1,e2) when op=OpAssign -> + this#writeOpLine IaSet; + this#gen_expression e1; + this#checkCast e1.etype e2 false false; + | TBinop (OpEq ,e1, { eexpr = TConst TNull } ) -> this#writeOpLine IaIsNull; + this#gen_expression e1; + | TBinop (OpNotEq ,e1, { eexpr = TConst TNull }) -> this#writeOpLine IaNotNull; + this#gen_expression e1; + | TBinop (OpEq , { eexpr = TConst TNull }, e1) -> this#writeOpLine IaIsNull; + this#gen_expression e1; + | TBinop (OpNotEq, { eexpr = TConst TNull }, e1) -> this#writeOpLine IaNotNull; + this#gen_expression e1; + | TBinop (op,e1,e2) -> this#writeOpLine (IaBinOp op); + this#gen_expression e1; + this#gen_expression e2; + | TThrow e -> this#writeOpLine IaThrow; + this#gen_expression e; + | TArrayDecl expr_list -> + this#write ( (this#op IaADef) ^ (this#typeText expression.etype) ^ " " ^(string_of_int (List.length expr_list))^"\n"); + List.iter this#gen_expression expr_list; + | TIf (e,e1,e2) -> + (match e2 with + | None -> + this#writeOpLine IaIf; + this#gen_expression e; + this#gen_expression e1; + | Some elze -> + this#writeOpLine IaIfElse; + this#gen_expression e; + this#gen_expression e1; + this#gen_expression elze; ) + | TCall (func, arg_list) -> + let argN = (string_of_int (List.length arg_list)) ^ " " in + let gen_call () = + (match (remove_parens_cast func).eexpr with + | TField ( { eexpr = TLocal { v_name = "__global__" }}, field ) -> + this#write ( (this#op IaCallGlobal) ^ (this#stringText (field_name field)) ^ argN ^ (this#commentOf (field_name field)) ^ "\n"); + | TField (obj,FStatic (class_def,field) ) when is_real_function field -> + this#write ( (this#op IaCallStatic) ^ (this#instText class_def) ^ " " ^ (this#stringText field.cf_name) ^ + argN ^ (this#commentOf ( join_class_path class_def.cl_path "." ^ "." ^ field.cf_name) ) ^ "\n"); + | TField (obj,FInstance (_,_,field) ) when (is_this obj) && (is_real_function field) -> + this#write ( (this#op IaCallThis) ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^ + argN ^ (this#commentOf field.cf_name) ^ "\n"); + | TField (obj,FInstance (_,_,field) ) when is_super obj -> + this#write ( (this#op IaCallSuper) ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^ + argN ^ (this#commentOf field.cf_name) ^ "\n"); + (* Cppia does not have a "GetEnumIndex" op code - must use IaCallMember hx::EnumBase.__Index *) + | TField (obj,FInstance (_,_,field) ) when field.cf_name = "_hx_getIndex" && (script_type_string obj.etype)="hx::EnumBase" -> + this#write ( (this#op IaCallMember) ^ (this#typeTextString "hx::EnumBase") ^ " " ^ (this#stringText "__Index") ^ + argN ^ (this#commentOf ("Enum index") ) ^ "\n"); + this#gen_expression obj; + | TField (obj,FInstance (_,_,field) ) when field.cf_name = "__Index" || (not (is_dynamic_in_cppia ctx obj) && is_real_function field) -> + this#write ( (this#op IaCallMember) ^ (this#typeText obj.etype) ^ " " ^ (this#stringText field.cf_name) ^ + argN ^ (this#commentOf field.cf_name) ^ "\n"); + this#gen_expression obj; + | TField (obj,FDynamic (name) ) when (is_internal_member name || (type_string obj.etype = "::String" && name="cca") ) -> + this#write ( (this#op IaCallMember) ^ (this#typeText obj.etype) ^ " " ^ (this#stringText name) ^ + argN ^ (this#commentOf name) ^ "\n"); + this#gen_expression obj; + | TConst TSuper -> this#write ((this#op IaCallSuperNew) ^ (this#typeText func.etype) ^ " " ^ argN ^ "\n"); + | TField (_,FEnum (enum,field)) -> this#write ((this#op IaCreateEnum) ^ (this#enumText enum) ^ " " ^ (this#stringText field.ef_name) ^ argN ^ + (this#commentOf field.ef_name) ^ "\n"); + | _ -> this#write ( (this#op IaCall) ^ argN ^ "\n"); + this#gen_expression func; + ); + let matched_args = match func.etype with + | TFun (args,_) -> + ( try ( + List.iter2 (fun (_,_,protoT) arg -> this#checkCast protoT arg false false) args arg_list; + true; ) + with Invalid_argument _ -> (*print_endline "Bad count?";*) false ) + | _ -> false + in + if not matched_args then + List.iter this#gen_expression arg_list; + in + (match (remove_parens_cast func).eexpr with + | TField(obj,field) when is_array_or_dyn_array obj.etype && (field_name field)="map" -> + (match this#get_array_type expression.etype with + | ArrayData t -> + this#write ( (this#op IaToDataArray) ^ (this#typeTextString ("Array." ^ t)) ^ "\n"); + this#begin_expr; + this#writePos func; + gen_call(); + this#end_expr; + | ArrayInterface t -> + this#write ( (this#op IaToInterfaceArray) ^ (string_of_int t) ^ "\n"); + this#begin_expr; + this#writePos func; + gen_call(); + this#end_expr; + | _ -> gen_call(); + ) + | _ -> gen_call(); + ); + | TField (obj, acc) -> + let objType = if is_dynamic_in_cppia ctx obj then "Dynamic" else script_type_string obj.etype in + let typeText = if is_dynamic_in_cppia ctx obj then this#typeTextString "Dynamic" else this#typeText obj.etype in + (match acc with + | FDynamic name -> this#write ( (this#op IaFName) ^ typeText ^ " " ^ (this#stringText name) ^ (this#commentOf name) ^ "\n"); + this#gen_expression obj; + | FStatic (class_def,field) -> this#write ( (this#op IaFStatic) ^ (this#instText class_def) ^ " " ^ + (this#stringText field.cf_name) ^ (this#commentOf field.cf_name) ); + | FInstance (_,_,field) when is_this obj -> this#write ( (this#op IaFThisInst) ^ typeText ^ " " ^ (this#stringText field.cf_name) + ^ (this#commentOf field.cf_name) ); + | FInstance (_,_,field) -> this#write ( (this#op IaFLink) ^ typeText ^ " " ^ (this#stringText field.cf_name) ^ (this#commentOf ( objType ^ "." ^ field.cf_name)) ^ "\n"); + this#gen_expression obj; + + | FClosure (_,field) when is_this obj -> this#write ( (this#op IaFThisName) ^typeText ^ " " ^ (this#stringText field.cf_name) ^ "\n") + | FAnon (field) when is_this obj -> this#write ( (this#op IaFThisName) ^typeText ^ " " ^ (this#stringText field.cf_name) ^ (this#commentOf field.cf_name) ^ "\n") + + | FClosure (_,field) + | FAnon (field) -> this#write ( (this#op IaFName) ^typeText ^ " " ^ (this#stringText field.cf_name) ^ (this#commentOf field.cf_name) ^ "\n"); + this#gen_expression obj; + + | FEnum (enum,field) -> this#write ( (this#op IaFEnum) ^ (this#enumText enum) ^ " " ^ (this#stringText field.ef_name) ^ (this#commentOf field.ef_name) ); + ) + | TArray (e1, e2) -> this#write ((this#op IaArrayI) ^ (this#typeText e1.etype) ^ "\n"); + this#gen_expression e1; + this#gen_expression e2; + | TUnop (op, flag, e) -> + this#writeOpLine (match op,flag with + | Increment, Prefix -> IaPlusPlus + | Increment, _ -> IaPlusPlusPost + | Decrement, Prefix -> IaMinusMinus + | Decrement, _ -> IaMinusMinusPost + | Not, _ -> IaLogicNot + | Neg, _ -> IaNeg + | NegBits, _ -> IaBitNot ); + this#gen_expression e; + (* TODO - lval op-assign local/member/array *) + | TLocal var -> this#write ((this#op IaVar) ^ (string_of_int var.v_id) ^ (this#commentOf var.v_name) ); + + | TVar (tvar,optional_init) -> + this#write ( (this#op IaTVars) ^ (string_of_int (1)) ^ (this#commentOf (tvar.v_name ^ ":" ^ (script_type_string tvar.v_type)) ) ^ "\n"); + this#write ("\t\t" ^ indent); + (match optional_init with + | None -> this#writeOp IaVarDecl; + this#writeVar tvar; + | Some init ->this#writeOp IaVarDeclI; + let init = remove_parens init in + this#writeVar tvar; + this#write (" " ^ (this#typeText init.etype)); + this#write "\n"; + this#checkCast tvar.v_type init false false); + | TNew (clazz,params,arg_list) -> + this#write ((this#op IaNew) ^ (this#typeText (TInst(clazz,params))) ^ (string_of_int (List.length arg_list)) ^ "\n"); + let rec matched_args clazz = match clazz.cl_constructor, clazz.cl_super with + | None, Some super -> matched_args (fst super) + | None, _ -> false + | Some ctr, _ -> + (match ctr.cf_type with + | TFun(args,_) -> + ( try ( + List.iter2 (fun (_,_,protoT) arg -> this#checkCast protoT arg false false) args arg_list; + true; ) + with Invalid_argument _ -> (*print_endline "Bad count?";*) false ) + | _ -> false + ) + in + if not (matched_args clazz) then + List.iter this#gen_expression arg_list; + + | TReturn optval -> (match optval with + | None -> this#writeOpLine IaReturn; + | Some value -> this#write ( (this#op IaRetVal) ^ (this#typeText value.etype) ^ "\n"); + this#checkCast return_type value false false; + ) + | TObjectDecl ( + ("fileName" , { eexpr = (TConst (TString file)) }) :: + ("lineNumber" , { eexpr = (TConst (TInt line)) }) :: + ("className" , { eexpr = (TConst (TString class_name)) }) :: + ("methodName", { eexpr = (TConst (TString meth)) }) :: [] ) -> + this#write ( (this#op IaPosInfo) ^ (this#stringText file) ^ (Printf.sprintf "%ld" line) ^ " " ^ + (this#stringText class_name) ^ " " ^ (this#stringText meth)) + + | TObjectDecl values ->this#write ( (this#op IaObjDef) ^ (string_of_int (List.length values))); + this#write " "; + List.iter (fun (name,_) -> this#write (this#stringText name) ) values; + this#write "\n"; + List.iter (fun (_,e) -> this#gen_expression e ) values; + | TTypeExpr type_expr -> + let klass = "::" ^ (join_class_path (t_path type_expr) "::" ) in + this#write ((this#op IaClassOf) ^ (string_of_int (this#typeId klass))) + | TWhile (e1,e2,flag) -> this#write ( (this#op IaWhile) ^ (if flag=NormalWhile then "1" else "0" ) ^ "\n"); + this#gen_expression e1; + this#gen_expression e2; + | TFor (tvar,init,loop) -> this#writeOp IaFor; + this#writeVar tvar; + this#write "\n"; + this#gen_expression init; + this#gen_expression loop; + | TEnumParameter (expr,ef,i) -> + let enum = match follow ef.ef_type with + | TEnum(en,_) | TFun(_,TEnum(en,_)) -> en + | _ -> assert false + in + this#write ( (this#op IaEnumI) ^ (this#typeText (TEnum(enum,[])) ) ^ (string_of_int i) ^ "\n"); + this#gen_expression expr; + | TSwitch (condition,cases,optional_default) -> + this#write ( (this#op IaSwitch) ^ (string_of_int (List.length cases)) ^ " " ^ + (match optional_default with None -> "0" | Some _ -> "1") ^ "\n"); + this#gen_expression condition; + List.iter (fun (cases_list,expression) -> + this#writeList ("\t\t\t"^indent) (List.length cases_list); + List.iter (fun value -> this#gen_expression value ) cases_list; + this#gen_expression expression; + ) cases; + (match optional_default with None -> () | Some expr -> this#gen_expression expr); + | TTry (e,catches) -> + this#writeList (this#op IaTry) (List.length catches); + this#gen_expression e; + List.iter ( fun (tvar,catch_expr) -> + this#write ("\t\t\t"^indent); + this#writeVar tvar; + this#write "\n"; + this#gen_expression catch_expr; + ) catches; + | TCast (cast,Some (TClassDecl t)) -> + this#write ((this#op IaTCast) ^ (this#typeText (TInst(t,[])) ) ^ "\n"); + this#gen_expression cast; + | TCast (cast,_) -> this#checkCast expression.etype cast true true; + | TParenthesis _ -> abort "Unexpected parens" expression.epos + | TMeta(_,_) -> abort "Unexpected meta" expression.epos + ); + this#end_expr; +end;; + +let generate_script_class common_ctx script class_def = + script#incClasses; + let classText = (join_class_path class_def.cl_path ".") in + script#comment ("Class " ^ classText); + script#writeOp (if class_def.cl_interface then IaInterface else IaClass ); + script#instName class_def; + (match class_def.cl_super with + | None -> script#ident "" + | Some (c,_) -> script#instName c); + script#wint (List.length class_def.cl_implements); + List.iter (fun(c,_) -> script#instName c) class_def.cl_implements; + script#write "\n"; + (* Looks like some map impl classes have their bodies discarded - not sure best way to filter *) + let non_dodgy_function field = + class_def.cl_interface || + match field.cf_kind, field.cf_expr with + | Var _, _ -> true + | Method MethDynamic, _ -> true + | Method _, Some _ -> true + | _ -> false + in + let ordered_statics = List.filter non_dodgy_function class_def.cl_ordered_statics in + let ordered_fields = List.filter non_dodgy_function class_def.cl_ordered_fields in + script#write ((string_of_int ( (List.length ordered_fields) + + (List.length ordered_statics) + + (match class_def.cl_constructor with Some _ -> 1 | _ -> 0 ) + + (if (implement_dynamic_here class_def) then 1 else 0) + + (match class_def.cl_init with Some _ -> 1 | _ -> 0 ) ) ) + ^ "\n"); + + let generate_field isStatic field = + match field.cf_kind, follow field.cf_type with + | Var { v_read = AccInline; v_write = AccNever },_ -> + script#writeOpLine IaInline; + | Var v,_ -> + let mode_code mode = match mode with + | AccNormal -> IaAccessNormal + | AccNo -> IaAccessNot + | AccNever -> IaAccessNot + | AccResolve -> IaAccessResolve + | AccCall -> if ( (has_meta_key class_def.cl_meta Meta.NativeProperty) || + (has_meta_key field.cf_meta Meta.NativeProperty) || + (Common.defined common_ctx Define.ForceNativeProperty) ) + then IaAccessCallNative else IaAccessCall; + | AccInline -> IaAccessNormal + | AccRequire (_,_) -> IaAccessNormal + in + let isExtern = is_extern_field field in + script#var (mode_code v.v_read) (mode_code v.v_write) isExtern isStatic field.cf_name field.cf_type field.cf_expr + | Method MethDynamic, TFun(args,ret) -> + script#func isStatic true field.cf_name ret args class_def.cl_interface field.cf_expr + | Method _, TFun(args,ret) when field.cf_name="new" -> + script#func true false "new" (TInst(class_def,[])) args false field.cf_expr + | Method _, TFun (args,ret) -> + script#func isStatic false field.cf_name ret args class_def.cl_interface field.cf_expr + | Method _, _ -> print_endline ("Unknown method type " ^ (join_class_path class_def.cl_path "." ) + ^ "." ^field.cf_name ) + in + (match class_def.cl_constructor with + | Some field -> generate_field true field + | _ -> () ); + (match class_def.cl_init with + | Some expression -> script#voidFunc true false "__init__" expression + | _ -> () ); + + List.iter (generate_field false) ordered_fields; + List.iter (generate_field true) ordered_statics; + if (implement_dynamic_here class_def) then + script#implDynamic; + script#write "\n"; +;; + +let generate_script_enum common_ctx script enum_def meta = + script#incClasses; + let sorted_items = List.sort (fun f1 f2 -> (f1.ef_index - f2.ef_index ) ) (pmap_values enum_def.e_constrs) in + script#writeList ((script#op IaEnum) ^ (script#enumText enum_def)) (List.length sorted_items); + + List.iter (fun constructor -> + let name = script#stringText constructor.ef_name in + match constructor.ef_type with + | TFun (args,_) -> + script#write ( name ^ " " ^ (string_of_int (List.length args)) ); + List.iter (fun (arg,_,t) -> script#write ( " " ^ (script#stringText arg) ^ " " ^ (script#typeText t) ) ) args; + script#write "\n"; + | _ -> script#write ( name ^ " 0\n" ) + ) sorted_items; + + match meta with + | Some expr -> script#write "1\n"; + script#gen_expression expr + | _ -> script#write "0\n"; + script#write "\n" +;; + + +let generate_cppia ctx = + let common_ctx = ctx.ctx_common in + let debug = ctx.ctx_debug_level in + let script = new script_writer ctx common_ctx.file common_ctx.debug in + ignore (script#stringId ""); + ignore (script#typeId ""); + + List.iter (fun object_def -> + (match object_def with + | TClassDecl class_def when class_def.cl_extern -> + () (*if (gen_externs) then gen_extern_class common_ctx class_def;*) + | TClassDecl class_def -> + let is_internal = is_internal_class class_def.cl_path in + if (is_internal || (is_macro class_def.cl_meta)) then + ( if (debug>=4) then print_endline (" internal class " ^ (join_class_path class_def.cl_path ".") )) + else begin + generate_script_class common_ctx script class_def + end + | TEnumDecl enum_def when enum_def.e_extern -> () + | TEnumDecl enum_def -> + let is_internal = is_internal_class enum_def.e_path in + if (is_internal) then + (if (debug>=4) then print_endline (" internal enum " ^ (join_class_path enum_def.e_path ".") )) + else begin + let meta = Codegen.build_metadata common_ctx object_def in + if (enum_def.e_extern) then + (if (debug>=4) then print_endline ("external enum " ^ (join_class_path enum_def.e_path ".") )); + generate_script_enum common_ctx script enum_def meta + end + | TTypeDecl _ | TAbstractDecl _ -> (* already done *) () + ); + ) common_ctx.types; + + (match common_ctx.main with + | None -> script#writeOpLine IaNoMain; + | Some e -> script#writeOpLine IaMain; + script#gen_expression e + ); + + script#write ( (script#op IaResources) ^ (string_of_int (Hashtbl.length common_ctx.resources)) ^ "\n"); + Hashtbl.iter (fun name data -> + script#write ((script#op IaReso) ^ (script#stringText name) ^ (string_of_int (String.length data)) ^ "\n"); + ) common_ctx.resources; + Hashtbl.iter (fun _ data -> script#writeData data) common_ctx.resources; + + script#close +;; + + +(* + The common_ctx contains the haxe AST in the "types" field and the resources +*) +let generate_source ctx = + let common_ctx = ctx.ctx_common in + let debug = ctx.ctx_debug_level in + make_base_directory common_ctx.file; + let exe_classes = ref [] in + let boot_classes = ref [] in + let boot_enums = ref [] in + let nonboot_classes = ref [] in + let init_classes = ref [] in + let super_deps = create_super_dependencies common_ctx in + let constructor_deps = create_constructor_dependencies common_ctx in + let main_deps = ref [] in + let extern_src = ref [] in + let jobs = ref [] in + let build_xml = ref "" in + let scriptable = (Common.defined common_ctx Define.Scriptable) in + let existingIds = Hashtbl.create 0 in + + List.iter (fun object_def -> + (* check if any @:objc class is referenced while '-D objc' is not defined + This will guard all code changes to this flag *) + (if not (Common.defined common_ctx Define.Objc) then match object_def with + | TClassDecl class_def when Meta.has Meta.Objc class_def.cl_meta -> + abort "In order to compile '@:objc' classes, please define '-D objc'" class_def.cl_pos + | _ -> ()); + (match object_def with + | TClassDecl class_def when is_extern_class class_def -> + build_xml := !build_xml ^ (get_class_code class_def Meta.BuildXml); + let source = get_meta_string_path class_def.cl_meta Meta.SourceFile in + if (source<>"") then + extern_src := source :: !extern_src; + | TClassDecl class_def -> + let name = class_text class_def.cl_path in + let is_internal = is_internal_class class_def.cl_path in + if (is_internal || (is_macro class_def.cl_meta)) then + ( if (debug>=4) then print_endline (" internal class " ^ name )) + else begin + let rec makeId class_name seed = + let id = gen_hash32 seed class_name in + (* reserve first 100 ids for runtime *) + if id < Int32.of_int 100 || Hashtbl.mem existingIds id then + makeId class_name (seed+100) + else begin + Hashtbl.add existingIds id true; + Hashtbl.add ctx.ctx_type_ids class_name id; + end in + makeId name 0; + + build_xml := !build_xml ^ (get_class_code class_def Meta.BuildXml); + if (has_init_field class_def) then + init_classes := class_def.cl_path :: !init_classes; + if (has_boot_field class_def) then + boot_classes := class_def.cl_path :: !boot_classes + else if not (has_meta_key class_def.cl_meta Meta.NativeGen) then + nonboot_classes := class_def.cl_path :: !nonboot_classes; + jobs := (fun () -> generate_class_files ctx super_deps constructor_deps class_def scriptable ) :: !jobs; + let deps = generate_class_deps ctx class_def super_deps constructor_deps in + if not (class_def.cl_interface && (is_native_gen_class class_def)) then + exe_classes := (class_def.cl_path, deps, object_def) :: !exe_classes; + end + | TEnumDecl enum_def when enum_def.e_extern -> () + | TEnumDecl enum_def -> + let name = class_text enum_def.e_path in + let is_internal = is_internal_class enum_def.e_path in + if (is_internal) then + (if (debug>1) then print_endline (" internal enum " ^ name )) + else begin + let meta = Codegen.build_metadata common_ctx object_def in + if (enum_def.e_extern) then + (if (debug>1) then print_endline ("external enum " ^ name )); + boot_enums := enum_def.e_path :: !boot_enums; + jobs := (fun () -> generate_enum_files ctx enum_def super_deps meta ) :: !jobs; + let deps = generate_enum_deps ctx enum_def super_deps in + exe_classes := (enum_def.e_path, deps, object_def) :: !exe_classes; + end + | TTypeDecl _ | TAbstractDecl _ -> (* already done *) () + ); + ) common_ctx.types; + + List.iter (fun job -> job () ) !jobs; + + + (match common_ctx.main with + | None -> generate_dummy_main common_ctx + | Some e -> + let main_field = { cf_name = "__main__"; cf_type = t_dynamic; cf_expr = Some e; cf_expr_unoptimized = None; cf_pos = e.epos; cf_name_pos = null_pos; cf_public = true; cf_meta = []; cf_overloads = []; cf_doc = None; cf_kind = Var { v_read = AccNormal; v_write = AccNormal; }; cf_params = [] } in + let class_def = { null_class with cl_path = ([],"@Main"); cl_ordered_statics = [main_field] } in + main_deps := find_referenced_types ctx (TClassDecl class_def) super_deps constructor_deps false true false; + generate_main ctx super_deps class_def + ); + + generate_boot ctx !boot_enums !boot_classes !nonboot_classes !init_classes; + + generate_files common_ctx ctx.ctx_file_info; + + write_resources common_ctx; + + (* Output class info if requested *) + if (scriptable || (Common.defined common_ctx Define.DllExport) ) then begin + let filename = + try + let value = Common.defined_value common_ctx Define.DllExport in + if value="1" then raise Not_found; + value + with Not_found -> "export_classes.info" + in + if (filename <> "") then begin + let escape s = + let b = Buffer.create 0 in + for i = 0 to String.length s - 1 do + let c = String.unsafe_get s i in + match c with + | '\\' -> Buffer.add_char b c; Buffer.add_char b c; + | ' ' -> Buffer.add_char b '\\'; Buffer.add_char b 's'; + | '\n' -> Buffer.add_char b '\\'; Buffer.add_char b 'n'; + | _ -> Buffer.add_char b c; + done; + Buffer.contents b; + in + + let exeClasses = open_out filename in + let out = output_string exeClasses in + let outline str = output_string exeClasses (str ^ "\n") in + let spath path = (join_class_path path ".") in + List.iter (fun (name,_,def) -> + match def with + | TClassDecl class_def -> + outline ((if class_def.cl_interface then "interface " else "class ") ^ (spath name) ); + | TEnumDecl enum_def -> + out ("enum " ^ (spath name) ^ "\n"); + | _ -> () + ) !exe_classes; + + (* Output file info too *) + List.iter ( fun file -> + let full_path = Path.get_full_path (try Common.find_file common_ctx file with Not_found -> file) in + if file <> "?" then + out ("file " ^ (escape file) ^ " " ^ (escape full_path) ^"\n") ) + ( List.sort String.compare ( pmap_keys !(ctx.ctx_file_info) ) ); + close_out exeClasses; + end; + end; + + let output_name = match common_ctx.main_class with + | Some path -> (snd path) + | _ -> "output" in + + write_build_data common_ctx (common_ctx.file ^ "/Build.xml") !exe_classes !main_deps (!boot_enums@ !boot_classes) !build_xml !extern_src output_name; + let cmd_defines = ref "" in + PMap.iter ( fun name value -> match name with + | "true" | "sys" | "dce" | "cpp" | "debug" -> () + | _ -> cmd_defines := !cmd_defines ^ " -D" ^ name ^ "=\"" ^ (escape_command value) ^ "\"" ) common_ctx.defines; + write_build_options common_ctx (common_ctx.file ^ "/Options.txt") common_ctx.defines; + if ( not (Common.defined common_ctx Define.NoCompilation) ) then begin + let t = Common.timer ["generate";"cpp";"native compilation"] in + let old_dir = Sys.getcwd() in + Sys.chdir common_ctx.file; + let cmd = ref "haxelib run hxcpp Build.xml haxe" in + if (common_ctx.debug) then cmd := !cmd ^ " -Ddebug"; + cmd := !cmd ^ !cmd_defines; + cmd := List.fold_left (fun cmd path -> cmd ^ " -I\"" ^ (escape_command path) ^ "\"" ) !cmd common_ctx.class_path; + common_ctx.print (!cmd ^ "\n"); + if common_ctx.run_command !cmd <> 0 then failwith "Build failed"; + Sys.chdir old_dir; + t() + end + ;; + +let generate common_ctx = + if (Common.defined common_ctx Define.Cppia) then begin + let ctx = new_context common_ctx 1 (ref PMap.empty) (Hashtbl.create 0) in + generate_cppia ctx + end else begin + let ctx = new_context common_ctx 1 (ref PMap.empty) (create_member_types common_ctx) in + generate_source ctx + end +;; + + diff --git a/gencs.ml b/src/generators/gencs.ml similarity index 90% rename from gencs.ml rename to src/generators/gencs.ml index 3c80a34a..3f695b2e 100644 --- a/gencs.ml +++ b/src/generators/gencs.ml @@ -1,31 +1,30 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) +open Globals open Gencommon.ReflectionCFs open Ast open Common open Type open Gencommon open Gencommon.SourceWriter +open Codegen open Printf open Option open ExtString @@ -184,26 +183,29 @@ let rec change_md = function change_md (t_to_md a.a_this) | TClassDecl( { cl_kind = KAbstractImpl ({ a_this = TInst(impl,_) } as a) }) when Meta.has Meta.Delegate a.a_meta -> TClassDecl impl + | TClassDecl( { cl_kind = KAbstractImpl (a) }) when Meta.has Meta.CoreType a.a_meta -> + TAbstractDecl a | md -> md +(* used in c#-specific filters to skip some of them for the special haxe.lang.Runtime class *) +let in_runtime_class gen = + match gen.gcurrent_class with + | Some { cl_path = ["haxe";"lang"],"Runtime"} -> true + | _ -> false + (* ******************************************* *) (* CSharpSpecificESynf *) (* ******************************************* *) - (* - Some CSharp-specific syntax filters that must run before ExpressionUnwrap dependencies: It must run before ExprUnwrap, as it may not return valid Expr/Statement expressions It must run before ClassInstance, as it will detect expressions that need unchanged TTypeExpr - *) module CSharpSpecificESynf = struct - let name = "csharp_specific_e" - let priority = solve_deps name [DBefore ExpressionUnwrap.priority; DBefore ClassInstance.priority; DAfter TryCatchWrapper.priority] let get_cl_from_t t = @@ -216,15 +218,11 @@ struct | TAbstract(ab,_) -> ab | _ -> assert false - let traverse gen runtime_cl = + let configure gen runtime_cl = let basic = gen.gcon.basic in let uint = match get_type gen ([], "UInt") with | TTypeDecl t -> TType(t, []) | TAbstractDecl a -> TAbstract(a, []) | _ -> assert false in let is_var = alloc_var "__is__" t_dynamic in - let name () = match gen.gcurrent_class with - | Some cl -> path_s cl.cl_path - | _ -> "" - in let rec run e = match e.eexpr with @@ -271,7 +269,7 @@ struct let obj = run obj in (match follow_module follow md with - | TAbstractDecl{ a_path = ([], "Float") } when name() <> "haxe.lang.Runtime" -> + | TAbstractDecl{ a_path = ([], "Float") } when not (in_runtime_class gen) -> (* on the special case of seeing if it is a Float, we need to test if both it is a float and if it is an Int *) let mk_is local = (* we check if it float or int or uint *) @@ -282,7 +280,7 @@ struct in wrap_if_needed obj mk_is - | TAbstractDecl{ a_path = ([], "Int") } when name() <> "haxe.lang.Runtime" -> + | TAbstractDecl{ a_path = ([], "Int") } when not (in_runtime_class gen) -> (* int can be stored in double variable because of anonymous functions, check that case *) let mk_isint_call local = { @@ -301,7 +299,7 @@ struct in wrap_if_needed obj mk_is - | TAbstractDecl{ a_path = ([], "UInt") } when name() <> "haxe.lang.Runtime" -> + | TAbstractDecl{ a_path = ([], "UInt") } when not (in_runtime_class gen) -> (* uint can be stored in double variable because of anonymous functions, check that case *) let mk_isuint_call local = { @@ -361,12 +359,8 @@ struct | _ -> Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map - end;; (* ******************************************* *) @@ -384,9 +378,7 @@ end;; module CSharpSpecificSynf = struct - let name = "csharp_specific" - let priority = solve_deps name [ DAfter ExpressionUnwrap.priority; DAfter ObjectDeclMap.priority; DAfter ArrayDeclSynf.priority; DAfter HardNullableSynf.priority ] let get_cl_from_t t = @@ -399,7 +391,7 @@ struct | TInst( { cl_kind = KTypeParameter _ }, _ ) -> true | _ -> false - let traverse gen runtime_cl = + let configure gen runtime_cl = let basic = gen.gcon.basic in let tchar = match ( get_type gen (["cs"], "Char16") ) with | TTypeDecl t -> TType(t,[]) @@ -407,7 +399,6 @@ struct | _ -> assert false in let string_ext = get_cl ( get_type gen (["haxe";"lang"], "StringExt")) in - let is_string t = match follow t with | TInst({ cl_path = ([], "String") }, []) -> true | _ -> false in let clstring = match basic.tstring with | TInst(cl,_) -> cl | _ -> assert false in let ti64 = match ( get_type gen (["cs"], "Int64") ) with | TTypeDecl t -> TType(t,[]) | TAbstractDecl a -> TAbstract(a,[]) | _ -> assert false in let boxed_ptr = @@ -425,10 +416,9 @@ struct in let is_cl t = match gen.greal_type t with | TInst ( { cl_path = (["System"], "Type") }, [] ) -> true | _ -> false in - let name () = match gen.gcurrent_class with - | Some cl -> path_s cl.cl_path - | _ -> "" - in + + let as_var = alloc_var "__as__" t_dynamic in + let fast_cast = Common.defined gen.gcon Define.FastCast in let rec run e = match e.eexpr with @@ -450,7 +440,7 @@ struct { e with eexpr = TField(run ef, FDynamic "ToUpperInvariant") } | TCall( { eexpr = TField(_, FStatic({ cl_path = [], "String" }, { cf_name = "fromCharCode" })) }, [cc] ) -> - { e with eexpr = TNew(get_cl_from_t basic.tstring, [], [mk_cast tchar (run cc); mk_int gen 1 cc.epos]) } + { e with eexpr = TNew(get_cl_from_t basic.tstring, [], [mk_cast tchar (run cc); ExprBuilder.make_int gen.gcon 1 cc.epos]) } | TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("charAt" as field) })) }, args ) | TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("charCodeAt" as field) })) }, args ) | TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("indexOf" as field) })) }, args ) @@ -482,7 +472,7 @@ struct { e with eexpr = TNew(boxed_ptr,[],[expr]) } | Some e -> run e) - | TCast(expr, _) when is_bool e.etype && not (is_exactly_bool gen expr.etype) -> + | TCast(expr, _) when is_bool e.etype && is_dynamic gen expr.etype -> { eexpr = TCall( mk_static_field_access_infer runtime_cl "toBool" expr.epos [], @@ -491,7 +481,7 @@ struct etype = basic.tbool; epos = e.epos } - | TCast(expr, _) when is_int_float gen e.etype && not (is_cs_basic_type (gen.greal_type expr.etype)) && ( Common.defined gen.gcon Define.EraseGenerics || not (is_null e.etype) ) && name() <> "haxe.lang.Runtime" -> + | TCast(expr, _) when is_int_float gen e.etype && is_dynamic gen expr.etype && ( Common.defined gen.gcon Define.EraseGenerics || not (is_null e.etype) ) && not (in_runtime_class gen) -> let needs_cast = match gen.gfollow#run_f e.etype with | TInst _ -> false | _ -> true @@ -509,20 +499,37 @@ struct } in if needs_cast then mk_cast e.etype ret else ret - | TCast(expr, _) when (is_string e.etype) && (not (is_string expr.etype)) && name() <> "haxe.lang.Runtime" -> + + | TCast(expr, _) when Common.defined gen.gcon Define.EraseGenerics && like_i64 e.etype && is_dynamic gen expr.etype && not (in_runtime_class gen) -> + { + eexpr = TCall( + mk_static_field_access_infer runtime_cl "toLong" expr.epos [], + [ run expr ] + ); + etype = ti64; + epos = expr.epos + } + + | TCast(expr, Some(TClassDecl cls)) when fast_cast && cls == null_class -> + if is_cs_basic_type (gen.greal_type e.etype) || is_tparam (gen.greal_type e.etype) then + { e with eexpr = TCast(run expr, Some(TClassDecl null_class)) } + else + { e with eexpr = TCall(mk_local as_var e.epos, [run expr]) } + + | TCast(expr, _) when (is_string e.etype) && (not (is_string expr.etype)) && not (in_runtime_class gen) -> { e with eexpr = TCall( mk_static_field_access_infer runtime_cl "toString" expr.epos [], [run expr] ) } | TBinop( (Ast.OpNotEq as op), e1, e2) | TBinop( (Ast.OpEq as op), e1, e2) when is_string e1.etype || is_string e2.etype -> let mk_ret e = match op with | Ast.OpNotEq -> { e with eexpr = TUnop(Ast.Not, Ast.Prefix, e) } | _ -> e in mk_ret { e with eexpr = TCall({ - eexpr = TField(mk_classtype_access clstring e.epos, FDynamic "Equals"); + eexpr = TField(ExprBuilder.make_static_this clstring e.epos, FDynamic "Equals"); etype = TFun(["obj1",false,basic.tstring; "obj2",false,basic.tstring], basic.tbool); epos = e1.epos }, [ run e1; run e2 ]) } - | TCast(expr, _) when is_tparam e.etype && name() <> "haxe.lang.Runtime" && not (Common.defined gen.gcon Define.EraseGenerics) -> + | TCast(expr, _) when is_tparam e.etype && not (in_runtime_class gen) && not (Common.defined gen.gcon Define.EraseGenerics) -> let static = mk_static_field_access_infer (runtime_cl) "genericCast" e.epos [e.etype] in { e with eexpr = TCall(static, [mk_local (alloc_var "$type_param" e.etype) expr.epos; run expr]); } @@ -538,7 +545,7 @@ struct } | TBinop ( (Ast.OpEq as op), e1, e2 ) - | TBinop ( (Ast.OpNotEq as op), e1, e2 ) when is_cl e1.etype && name() <> "haxe.lang.Runtime" -> + | TBinop ( (Ast.OpNotEq as op), e1, e2 ) when is_cl e1.etype && not (in_runtime_class gen) -> let static = mk_static_field_access_infer (runtime_cl) "typeEq" e.epos [] in let ret = { e with eexpr = TCall(static, [run e1; run e2]); } in if op = Ast.OpNotEq then @@ -548,12 +555,8 @@ struct | _ -> Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map - end;; let add_cast_handler gen = @@ -602,7 +605,7 @@ let add_cast_handler gen = epos = e.epos }; { - eexpr = TVar(i, Some( mk_int gen (-1) e.epos )); + eexpr = TVar(i, Some( ExprBuilder.make_int gen.gcon (-1) e.epos )); etype = basic.tvoid; epos = e.epos }; @@ -668,12 +671,6 @@ let add_cast_handler gen = Hashtbl.add gen.gtparam_cast (["cs"], "NativeArray") gtparam_cast_native_array (* end set gtparam_cast *) - -(* Type Parameters Handling *) -let handle_type_params gen ifaces base_generic = - add_cast_handler gen; - TypeParams.RealTypeParams.default_config gen (fun e t -> gen.gcon.warning ("Cannot cast to " ^ (debug_type t)) e.epos; mk_cast t e) ifaces base_generic - let connecting_string = "?" (* ? see list here http://www.fileformat.info/info/unicode/category/index.htm and here for C# http://msdn.microsoft.com/en-us/library/aa664670.aspx *) let default_package = "cs" (* I'm having this separated as I'm still not happy with having a cs package. Maybe dotnet would be better? *) let strict_mode = ref false (* strict mode is so we can check for unexpected information *) @@ -713,7 +710,7 @@ let rec get_fun_modifiers meta access modifiers = | (Meta.ReadOnly,[],_) :: meta -> get_fun_modifiers meta access ("readonly" :: modifiers) | (Meta.Unsafe,[],_) :: meta -> get_fun_modifiers meta access ("unsafe" :: modifiers) | (Meta.Volatile,[],_) :: meta -> get_fun_modifiers meta access ("volatile" :: modifiers) - | (Meta.Custom ("?prop_impl" | "?event_impl"),[],_) :: meta -> get_fun_modifiers meta "private" modifiers + | (Meta.Custom ("?prop_impl" | ":cs_event_impl"),[],_) :: meta -> get_fun_modifiers meta "private" modifiers | _ :: meta -> get_fun_modifiers meta access modifiers (* this was the way I found to pass the generator context to be accessible across all functions here *) @@ -762,6 +759,7 @@ let configure gen = let change_ns_params md params ns = if no_root then match ns with | [] when is_hxgen md -> ["haxe";"root"], params + | [s] when (t_infos md).mt_private && is_hxgen md -> ["haxe";"root";s], params | [] -> (match md with | TClassDecl { cl_path = ([],"Std" | [],"Math") } -> ["haxe";"root"], params | TClassDecl { cl_meta = m } when Meta.has Meta.Enum m -> ["haxe";"root"], params @@ -798,7 +796,7 @@ let configure gen = let rec field_is_hxgeneric e = match e.eexpr with | TParenthesis e | TMeta(_,e) -> field_is_hxgeneric e | TField(_, (FStatic(cl,_) | FInstance(cl,_,_)) ) -> - (* print_endline ("is_hxgeneric " ^ path_s cl.cl_path ^ " : " ^ string_of_bool (is_hxgeneric (TClassDecl cl))); *) + (* print_endline ("is_hxgeneric " ^ s_type_path cl.cl_path ^ " : " ^ string_of_bool (is_hxgeneric (TClassDecl cl))); *) is_hxgeneric (TClassDecl cl) | _ -> true in @@ -844,10 +842,10 @@ let configure gen = let path = (t_infos md).mt_path in match path with | ([], "String") -> "string", params - | ([], "Null") -> path_s (change_ns md ["haxe"; "lang"], change_clname "Null"), params + | ([], "Null") -> s_type_path (change_ns md ["haxe"; "lang"], change_clname "Null"), params | (ns,clname) -> let ns, params = change_ns_params md params ns in - path_s (ns, change_clname clname), params + s_type_path (ns, change_clname clname), params in let module_s md = @@ -912,7 +910,7 @@ let configure gen = else (match real_type t with | TInst( { cl_kind = KTypeParameter _ }, _ ) -> TInst(null_t, [t]) - | _ when is_cs_basic_type t -> TInst(null_t, [t]) + | t when is_cs_basic_type t -> TInst(null_t, [t]) | _ -> real_type t) | TAbstract _ | TType _ -> t @@ -1137,9 +1135,9 @@ let configure gen = if skip_line_directives then fun w p -> () else fun w p -> - if p.pfile <> Ast.null_pos.pfile then (* Compiler Error CS1560 https://msdn.microsoft.com/en-us/library/z3t5e5sw(v=vs.90).aspx *) + if p.pfile <> null_pos.pfile then (* Compiler Error CS1560 https://msdn.microsoft.com/en-us/library/z3t5e5sw(v=vs.90).aspx *) let cur_line = Lexer.get_error_line p in - let file = Common.get_full_path p.pfile in + let file = Path.get_full_path p.pfile in if cur_line <> ((!last_line)+1) then let line = Ast.s_escape file in if String.length line <= 256 then @@ -1301,6 +1299,7 @@ let configure gen = (match c with | TInt i32 -> write w (Int32.to_string i32); + (* these suffixes won't work because of the cast detector which will set each constant to its expected type *) (*match real_type e.etype with | TType( { t_path = (["haxe";"_Int64"], "NativeInt64") }, [] ) -> write w "L"; | _ -> () @@ -1324,6 +1323,10 @@ let configure gen = | TNull -> write w "null" | TThis -> write w "this" | TSuper -> write w "base") + | TCast({ eexpr = TConst(TNull) }, _) -> + write w "default("; + write w (t_s e.etype); + write w ")" | TLocal { v_name = "__sbreak__" } -> write w "break" | TLocal { v_name = "__undefined__" } -> write w (t_s (TInst(runtime_cl, List.map (fun _ -> t_dynamic) runtime_cl.cl_params))); @@ -1361,7 +1364,7 @@ let configure gen = | TField (e, s) when is_pointer gen e.etype -> (* take off the extra cast if possible *) let e = match e.eexpr with - | TCast(e1,_) when Gencommon.CastDetect.type_iseq gen e.etype e1.etype -> + | TCast(e1,_) when CastDetect.type_iseq gen e.etype e1.etype -> e1 | _ -> e in @@ -1369,7 +1372,7 @@ let configure gen = | TField (e, s) -> expr_s w e; write w "."; write_field w (field_name s) | TTypeExpr mt -> - (match mt with + (match change_md mt with | TClassDecl { cl_path = (["haxe"], "Int64") } -> write w ("global::" ^ module_s mt) | TClassDecl { cl_path = (["haxe"], "Int32") } -> write w ("global::" ^ module_s mt) | TClassDecl cl -> write w (t_s (TInst(cl, List.map (fun _ -> t_empty) cl.cl_params))); @@ -1577,12 +1580,20 @@ let configure gen = ) el; end_block w | TIf (econd, e1, Some(eelse)) when was_in_value -> + let base = t_s e.etype in write w "( "; expr_s w (mk_paren econd); write w " ? "; - expr_s w (mk_paren e1); + if t_s e1.etype <> base then + expr_s w (mk_cast e.etype e1) + else + expr_s w (mk_paren e1); + write w " : "; - expr_s w (mk_paren eelse); + if t_s eelse.etype <> base then + expr_s w (mk_cast e.etype eelse) + else + expr_s w (mk_paren eelse); write w " )"; | TIf (econd, e1, eelse) -> write w "if "; @@ -1985,6 +1996,34 @@ let configure gen = end; in + let needs_unchecked e = + let rec loop e = match e.eexpr with + (* a non-zero integer constant means that we want unchecked context *) + | TConst (TInt i) when i <> Int32.zero -> + raise Exit + + (* don't recurse into explicit checked blocks *) + | TCall ({ eexpr = TLocal({ v_name = "__checked__" }) }, _) -> + () + + (* skip reflection field hashes as they are safe *) + | TNew ({ cl_path = (["haxe"; "lang"],"DynamicObject") }, [], [_; e1; _; e2]) -> + loop e1; + loop e2 + | TNew ({ cl_path = (["haxe"; "lang"],"Closure") }, [], [eo; _; _]) -> + loop eo + | TCall ({ eexpr = TField (_, FStatic ({ cl_path = ["haxe"; "lang"],"Runtime" }, + { cf_name = "getField" | "setField" | "getField_f" | "setField_f" | "callField" })) }, + eo :: _ :: _ :: rest) -> + loop eo; + List.iter loop rest + + | _ -> + Type.iter loop e + in + try (loop e; false) with Exit -> true + in + let rec gen_class_field w ?(is_overload=false) is_static cl is_final cf = gen_attributes w cf.cf_meta; let is_interface = cl.cl_interface in @@ -1992,7 +2031,7 @@ let configure gen = | "new" -> snd cl.cl_path, true, false | name when String.contains name '.' -> let fn_name, path = parse_explicit_iface name in - (path_s path) ^ "." ^ fn_name, false, true + (s_type_path path) ^ "." ^ fn_name, false, true | name -> try let binop = PMap.find name binops_names in "operator " ^ s_binop binop, false, false @@ -2000,7 +2039,7 @@ let configure gen = let unop = PMap.find name unops_names in "operator " ^ s_unop unop, false, false with | Not_found -> - if Meta.has (Meta.Custom "?prop_impl") cf.cf_meta || Meta.has (Meta.Custom "?event_impl") cf.cf_meta then + if Meta.has (Meta.Custom "?prop_impl") cf.cf_meta || Meta.has (Meta.Custom ":cs_event_impl") cf.cf_meta then "_" ^ name, false, false else name, false, false @@ -2012,7 +2051,7 @@ let configure gen = | true, Some(cl,_) -> (try let cf2 = PMap.find cf.cf_name cl.cl_statics in - Gencommon.CastDetect.type_eq gen EqStrict cf.cf_type cf2.cf_type; + CastDetect.type_eq gen EqStrict cf.cf_type cf2.cf_type; ["new"] with | Not_found | Unify_error _ -> @@ -2092,7 +2131,7 @@ let configure gen = match meta with | [] -> let expr = match cf.cf_expr with - | None -> mk (TBlock([])) t_dynamic Ast.null_pos + | None -> mk (TBlock([])) t_dynamic null_pos | Some s -> match s.eexpr with | TFunction tf -> @@ -2100,33 +2139,6 @@ let configure gen = | _ -> assert false (* FIXME *) in - let needs_unchecked e = - let rec loop e = match e.eexpr with - (* a non-zero integer constant means that we want unchecked context *) - | TConst (TInt i) when i <> Int32.zero -> - raise Exit - - (* don't recurse into explicit checked blocks *) - | TCall ({ eexpr = TLocal({ v_name = "__checked__" }) }, _) -> - () - - (* skip reflection field hashes as they are safe *) - | TNew ({ cl_path = (["haxe"; "lang"],"DynamicObject") }, [], [_; e1; _; e2]) -> - loop e1; - loop e2 - | TNew ({ cl_path = (["haxe"; "lang"],"Closure") }, [], [eo; _; _]) -> - loop eo - | TCall ({ eexpr = TField (_, FStatic ({ cl_path = ["haxe"; "lang"],"Runtime" }, - { cf_name = "getField" | "setField" | "getField_f" | "setField_f" | "callField" })) }, - eo :: _ :: _ :: rest) -> - loop eo; - List.iter loop rest - - | _ -> - Type.iter loop e - in - try (loop e; false) with Exit -> true - in let write_method_expr e = match e.eexpr with | TBlock [] -> @@ -2135,7 +2147,7 @@ let configure gen = | TBlock _ -> let unchecked = needs_unchecked e in if unchecked then (begin_block w; write w "unchecked "); - let t = Common.timer "expression to string" in + let t = Common.timer ["expression to string"] in expr_s w e; t(); line_reset_directive w; @@ -2162,7 +2174,7 @@ let configure gen = | None -> () | Some sc -> write w ": "; - let t = Common.timer "expression to string" in + let t = Common.timer ["expression to string"] in expr_s w sc; write w " "; t() @@ -2327,7 +2339,7 @@ let configure gen = in if prop v.v_read && prop v.v_write && (v.v_read = AccCall || v.v_write = AccCall) then begin let this = if static then - mk_classtype_access cl f.cf_pos + ExprBuilder.make_static_this cl f.cf_pos else { eexpr = TConst TThis; etype = TInst(cl,List.map snd cl.cl_params); epos = f.cf_pos } in @@ -2399,8 +2411,12 @@ let configure gen = write w "public static void Main() "; begin_block w; (if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "global::cs.Boot.init();"; newline w); - expr_s w { eexpr = TTypeExpr(TClassDecl cl); etype = t_dynamic; epos = Ast.null_pos }; - write w ".main();"; + (match gen.gcon.main with + | None -> + expr_s w { eexpr = TTypeExpr(TClassDecl cl); etype = t_dynamic; epos = null_pos }; + write w ".main();" + | Some expr -> + expr_s w (mk_block expr)); end_block w; end_block w; newline w; @@ -2440,7 +2456,11 @@ let configure gen = write w "public static void Main()"; begin_block w; (if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "global::cs.Boot.init();"; newline w); - write w "main();"; + (match gen.gcon.main with + | None -> + write w "main();"; + | Some expr -> + expr_s w (mk_block expr)); end_block w end; @@ -2448,7 +2468,13 @@ let configure gen = | None -> () | Some init -> print w "static %s() " (snd cl.cl_path); - expr_s w (mk_block init); + if needs_unchecked init then begin + begin_block w; + write w "unchecked "; + expr_s w (mk_block init); + end_block w; + end else + expr_s w (mk_block init); line_reset_directive w; newline w; newline w @@ -2462,8 +2488,6 @@ let configure gen = | Var { v_read = AccCall } | Var { v_write = AccCall } when Type.is_extern_field v && Meta.has Meta.Property v.cf_meta -> props := (v.cf_name, ref (v, v.cf_type, None, None)) :: !props; | Var { v_read = AccNormal; v_write = AccNormal } when Meta.has Meta.Event v.cf_meta -> - if v.cf_public then gen.gcon.error "@:event fields must be private" v.cf_pos; - v.cf_meta <- (Meta.SkipReflection, [], null_pos) :: v.cf_meta; events := (v.cf_name, ref (v, v.cf_type, false, None, None)) :: !events; | _ -> nonprops := v :: !nonprops; @@ -2512,7 +2536,6 @@ let configure gen = let event = find_event (String.sub cf.cf_name 4 (String.length cf.cf_name - 4)) in let v, t, _, add, remove = !event in assert (add = None); - cf.cf_meta <- (Meta.Custom "?event_impl", [], null_pos) :: cf.cf_meta; let custom = not (is_empty_function cf) in event := (v, t, custom, Some cf, remove); false @@ -2521,7 +2544,6 @@ let configure gen = let event = find_event (String.sub cf.cf_name 7 (String.length cf.cf_name - 7)) in let v, t, _, add, remove = !event in assert (remove = None); - cf.cf_meta <- (Meta.Custom "?event_impl", [], null_pos) :: cf.cf_meta; let custom = not (is_empty_function cf) in event := (v, t, custom, add, Some cf); false @@ -2532,25 +2554,11 @@ let configure gen = let nonprops = ref nonprops in List.iter (fun (n,r) -> let ev, t, custom, add, remove = !r in - let tmeth = (tfun [t] basic.tvoid) in match add, remove with - | None, _ -> - gen.gcon.error ("Missing event method add_" ^ n) ev.cf_pos; - failwith "Build failed" - | _, None -> - gen.gcon.error ("Missing event method remove_" ^ n) ev.cf_pos; - failwith "Build failed" | Some add, Some remove -> - let check cf = try - type_eq EqStrict cf.cf_type tmeth - with Unify_error el -> - List.iter (fun e -> gen.gcon.error (Typecore.unify_error_msg (print_context()) e) cf.cf_pos) el; - failwith "Build failed"; - in - check add; - check remove; if custom && not cl.cl_interface then nonprops := add :: remove :: !nonprops + | _ -> assert false (* shouldn't happen because Filters.check_cs_events makes sure methods are present *) ) events; let evts = List.map (fun(_,v) -> !v) events in @@ -2602,11 +2610,15 @@ let configure gen = in let module_type_gen w md_tp = + let file_start = len w = 0 in + let requires_root = no_root && file_start in + if file_start then + Codegen.map_source_header gen.gcon (fun s -> print w "// %s\n" s); reset_temps(); match md_tp with | TClassDecl cl -> if not cl.cl_extern then begin - (if no_root && len w = 0 then write w "using haxe.root;\n"; newline w;); + (if requires_root then write w "using haxe.root;\n"; newline w;); gen_class w cl; newline w; newline w @@ -2614,7 +2626,7 @@ let configure gen = (not cl.cl_extern) | TEnumDecl e -> if not e.e_extern && not (Meta.has Meta.Class e.e_meta) then begin - (if no_root && len w = 0 then write w "using haxe.root;\n"; newline w;); + (if requires_root then write w "using haxe.root;\n"; newline w;); gen_enum w e; newline w; newline w @@ -2625,10 +2637,6 @@ let configure gen = false in - let module_gen w md_def = - List.fold_left (fun should md -> module_type_gen w md || should) false md_def.m_types - in - (* generate source code *) init_ctx gen; @@ -2664,7 +2672,7 @@ let configure gen = gen.greal_type <- real_type; gen.greal_type_param <- change_param_type; - SetHXGen.run_filter gen SetHXGen.default_hxgen_func; + SetHXGen.run_filter gen; (* before running the filters, follow all possible types *) (* this is needed so our module transformations don't break some core features *) @@ -2694,32 +2702,22 @@ let configure gen = | _ -> () ) gen.gtypes_list; - let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen 6 in - - (*let closure_t = ClosuresToClass.create gen 10 float_cl - (fun l -> l) - (fun l -> l) - (fun args -> args) - (fun args -> []) - in - ClosuresToClass.configure gen (ClosuresToClass.default_implementation closure_t (fun e _ _ -> e)); - - StubClosureImpl.configure gen (StubClosureImpl.default_implementation gen float_cl 10 (fun e _ _ -> e));*) - let tp_v = alloc_var "$type_param" t_dynamic in let mk_tp t pos = { eexpr = TLocal(tp_v); etype = t; epos = pos } in - TypeParams.configure gen (fun ecall efield params elist -> + gen.gparam_func_call <- (fun ecall efield params elist -> match efield.eexpr with | TField(_, FEnum _) -> - { ecall with eexpr = TCall(efield, elist) } + { ecall with eexpr = TCall(efield, elist) } | _ -> - { ecall with eexpr = TCall(efield, (List.map (fun t -> mk_tp t ecall.epos ) params) @ elist) } + { ecall with eexpr = TCall(efield, (List.map (fun t -> mk_tp t ecall.epos) params) @ elist) } ); - if not erase_generics then HardNullableSynf.configure gen (HardNullableSynf.traverse gen + if not erase_generics then HardNullableSynf.configure gen (fun e -> - match real_type e.etype with - | TInst({ cl_path = (["haxe";"lang"], "Null") }, [t]) -> + match e.eexpr, real_type e.etype with + | TConst TThis, _ when gen.gcurrent_path = (["haxe";"lang"], "Null") -> + e + | _, TInst({ cl_path = (["haxe";"lang"], "Null") }, [t]) -> let e = { e with eexpr = TParenthesis(e) } in { (mk_field_access gen e "value" e.epos) with etype = t } | _ -> @@ -2749,17 +2747,8 @@ let configure gen = mk_field_access gen { e with etype = real_type e.etype } "hasValue" e.epos ) (fun e1 e2 -> - { - eexpr = TCall( - mk_field_access gen e1 "Equals" e1.epos, - [e2]); - etype = basic.tbool; - epos = e1.epos; - } - ) - true - false - ); + mk (TCall(mk_field_access gen e1 "Equals" e1.epos, [e2])) basic.tbool e1.epos + ); let explicit_fn_name c tl fname = @@ -2771,15 +2760,14 @@ let configure gen = AbstractImplementationFix.configure gen; - IteratorsInterface.configure gen (fun e -> e); + IteratorsInterface.configure gen; - OverrideFix.configure gen; - - ClosuresToClass.configure gen (ClosuresToClass.default_implementation closure_t (get_cl (get_type gen (["haxe";"lang"],"Function")) )); + let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen (get_cl (get_type gen (["haxe";"lang"],"Function"))) 6 in + ClosuresToClass.configure gen closure_t; let enum_base = (get_cl (get_type gen (["haxe";"lang"],"Enum")) ) in let param_enum_base = (get_cl (get_type gen (["haxe";"lang"],"ParamEnum")) ) in - EnumToClass.configure gen (Some (fun e -> mk_cast gen.gcon.basic.tint e)) true true enum_base param_enum_base false false; + EnumToClass.configure gen (Some (fun e -> mk_cast gen.gcon.basic.tint e)) true true enum_base param_enum_base; InterfaceVarsDeleteModf.configure gen; InterfaceProps.configure gen; @@ -2788,20 +2776,14 @@ let configure gen = let object_iface = get_cl (get_type gen (["haxe";"lang"],"IHxObject")) in - (*fixme: THIS IS A HACK. take this off *) - let empty_e = match (get_type gen (["haxe";"lang"], "EmptyObject")) with | TEnumDecl e -> e | _ -> assert false in - (*OverloadingCtor.set_new_create_empty gen ({eexpr=TEnumField(empty_e, "EMPTY"); etype=TEnum(empty_e,[]); epos=null_pos;});*) - - let empty_expr = { eexpr = (TTypeExpr (TEnumDecl empty_e)); etype = (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics empty_e) }); epos = null_pos } in - let empty_ef = - try - PMap.find "EMPTY" empty_e.e_constrs - with Not_found -> gen.gcon.error "Required enum field EMPTY was not found" empty_e.e_pos; assert false - in - OverloadingConstructor.configure ~empty_ctor_type:(TEnum(empty_e, [])) ~empty_ctor_expr:({ eexpr=TField(empty_expr, FEnum(empty_e, empty_ef)); etype=TEnum(empty_e,[]); epos=null_pos; }) ~supports_ctor_inheritance:false gen; + let empty_en = match get_type gen (["haxe";"lang"], "EmptyObject") with TEnumDecl e -> e | _ -> assert false in + let empty_ctor_type = TEnum(empty_en, []) in + let empty_en_expr = mk (TTypeExpr (TEnumDecl empty_en)) (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics empty_en) }) null_pos in + let empty_ctor_expr = mk (TField (empty_en_expr, FEnum(empty_en, PMap.find "EMPTY" empty_en.e_constrs))) empty_ctor_type null_pos in + OverloadingConstructor.configure ~empty_ctor_type:empty_ctor_type ~empty_ctor_expr:empty_ctor_expr gen; - let rcf_static_find = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "findHash" Ast.null_pos [] in - let rcf_static_lookup = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "lookupHash" Ast.null_pos [] in + let rcf_static_find = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "findHash" null_pos [] in + let rcf_static_lookup = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "lookupHash" null_pos [] in let rcf_static_insert, rcf_static_remove = if erase_generics then begin @@ -2810,11 +2792,11 @@ let configure gen = | TAnon _ | TDynamic _ -> "Dynamic" | _ -> print_endline (debug_type t); assert false in - (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("insert" ^ get_specialized_postfix t) Ast.null_pos []), - (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("remove" ^ get_specialized_postfix t) Ast.null_pos []) + (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("insert" ^ get_specialized_postfix t) null_pos []), + (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("remove" ^ get_specialized_postfix t) null_pos []) end else - (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "insert" Ast.null_pos [t]), - (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "remove" Ast.null_pos [t]) + (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "insert" null_pos [t]), + (fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "remove" null_pos [t]) in let can_be_float = like_float in @@ -2870,12 +2852,13 @@ let configure gen = mk_cast ecall.etype { ecall with eexpr = TCall(infer, call_args) } in + add_cast_handler gen; if not erase_generics then - handle_type_params gen ifaces (get_cl (get_type gen (["haxe";"lang"], "IGenericObject"))) - else begin - add_cast_handler gen; - TypeParams.RealTypeParams.RealTypeParamsModf.configure gen (TypeParams.RealTypeParams.RealTypeParamsModf.set_only_hxgeneric gen) - end; + TypeParams.RealTypeParams.configure gen (fun e t -> gen.gcon.warning ("Cannot cast to " ^ (debug_type t)) e.epos; mk_cast t e) ifaces (get_cl (get_type gen (["haxe";"lang"], "IGenericObject"))) + else + TypeParams.RealTypeParams.RealTypeParamsModf.configure gen (TypeParams.RealTypeParams.RealTypeParamsModf.set_only_hxgeneric gen); + + let flookup_cl = get_cl (get_type gen (["haxe";"lang"], "FieldLookup")) in let rcf_ctx = ReflectionCFs.new_ctx @@ -2895,14 +2878,26 @@ let configure gen = let t = gen.gclasses.nativearray_type hash_array.etype in { hash_array with eexpr = TCall(rcf_static_remove t, [hash_array; length; pos]); etype = gen.gcon.basic.tvoid } ) - false + ( + let delete = mk_static_field_access_infer flookup_cl "deleteHashConflict" null_pos [] in + let get = mk_static_field_access_infer flookup_cl "getHashConflict" null_pos [] in + let set = mk_static_field_access_infer flookup_cl "setHashConflict" null_pos [] in + let add = mk_static_field_access_infer flookup_cl "addHashConflictNames" null_pos [] in + let conflict_t = TInst (get_cl (get_type gen (["haxe"; "lang"], "FieldHashConflict")), []) in + Some { + t = conflict_t; + get_conflict = (fun ehead ehash ename -> mk (TCall (get, [ehead; ehash; ename])) conflict_t ehead.epos); + set = (fun ehead ehash ename evalue -> mk (TCall (set, [ehead; ehash; ename; evalue])) basic.tvoid ehead.epos); + delete = (fun ehead ehash ename -> mk (TCall (delete, [ehead; ehash; ename])) basic.tbool ehead.epos); + add_names = (fun ehead earr -> mk (TCall (add, [ehead; earr])) basic.tvoid ehead.epos); + } + ) in - ReflectionCFs.UniversalBaseClass.default_config gen (get_cl (get_type gen (["haxe";"lang"],"HxObject")) ) object_iface dynamic_object; + ReflectionCFs.UniversalBaseClass.configure gen (get_cl (get_type gen (["haxe";"lang"],"HxObject")) ) object_iface dynamic_object; - ReflectionCFs.configure_dynamic_field_access rcf_ctx false; + ReflectionCFs.configure_dynamic_field_access rcf_ctx; - (* let closure_func = ReflectionCFs.implement_closure_cl rcf_ctx ( get_cl (get_type gen (["haxe";"lang"],"Closure")) ) in *) let closure_cl = get_cl (get_type gen (["haxe";"lang"],"Closure")) in let varargs_cl = get_cl (get_type gen (["haxe";"lang"],"VarArgsFunction")) in let dynamic_name = gen.gmk_internal_name "hx" "invokeDynamic" in @@ -2913,23 +2908,19 @@ let configure gen = ) cl.cl_ordered_fields ) [closure_cl; varargs_cl]; - let closure_func = ReflectionCFs.get_closure_func rcf_ctx closure_cl in - ReflectionCFs.implement_varargs_cl rcf_ctx ( get_cl (get_type gen (["haxe";"lang"], "VarArgsBase")) ); - let slow_invoke = mk_static_field_access_infer (runtime_cl) "slowCallField" Ast.null_pos [] in + let slow_invoke = mk_static_field_access_infer (runtime_cl) "slowCallField" null_pos [] in ReflectionCFs.configure rcf_ctx ~slow_invoke:(fun ethis efield eargs -> { eexpr = TCall(slow_invoke, [ethis; efield; eargs]); etype = t_dynamic; epos = ethis.epos; } ) object_iface; - let objdecl_fn = ReflectionCFs.implement_dynamic_object_ctor rcf_ctx dynamic_object in - - ObjectDeclMap.configure gen (ObjectDeclMap.traverse gen objdecl_fn); + ObjectDeclMap.configure gen (ReflectionCFs.implement_dynamic_object_ctor rcf_ctx dynamic_object); - InitFunction.configure gen true true; - TArrayTransform.configure gen (TArrayTransform.default_implementation gen ( + InitFunction.configure gen; + TArrayTransform.configure gen ( fun e binop -> match e.eexpr with | TArray(e1, e2) -> @@ -2946,7 +2937,7 @@ let configure gen = true | _ -> false) | _ -> assert false - ) "__get" "__set" ); + ) "__get" "__set"; let field_is_dynamic t field = match field_access_esp gen (gen.greal_type t) field with @@ -3014,7 +3005,7 @@ let configure gen = in DynamicOperators.configure gen - (DynamicOperators.abstract_implementation gen (fun e -> match e.eexpr with + (fun e -> match e.eexpr with | TBinop (Ast.OpEq, e1, e2) | TBinop (Ast.OpNotEq, e1, e2) -> ( @@ -3083,9 +3074,10 @@ let configure gen = end else begin let static = mk_static_field_access_infer (runtime_cl) "compare" e1.epos [] in { eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos } - end) ~handle_strings:false); + end) + ~handle_strings:false; - FilterClosures.configure gen (FilterClosures.traverse gen (fun e1 s -> true) closure_func); + FilterClosures.configure gen (fun e1 s -> true) (ReflectionCFs.get_closure_func rcf_ctx closure_cl); let base_exception = get_cl (get_type gen (["System"], "Exception")) in let base_exception_t = TInst(base_exception, []) in @@ -3104,45 +3096,34 @@ let configure gen = in TryCatchWrapper.configure gen - ( - TryCatchWrapper.traverse gen - (fun t -> not (is_exception (real_type t))) - (fun throwexpr expr -> - let wrap_static = mk_static_field_access (hx_exception) "wrap" (TFun([("obj",false,t_dynamic)], base_exception_t)) expr.epos in - { throwexpr with eexpr = TThrow { expr with eexpr = TCall(wrap_static, [expr]); etype = hx_exception_t }; etype = gen.gcon.basic.tvoid } - ) - (fun v_to_unwrap pos -> - let local = mk_cast hx_exception_t { eexpr = TLocal(v_to_unwrap); etype = v_to_unwrap.v_type; epos = pos } in - mk_field_access gen local "obj" pos - ) - (fun rethrow -> - { rethrow with eexpr = TCall(mk_local (alloc_var "__rethrow__" t_dynamic) rethrow.epos, [rethrow]); etype = gen.gcon.basic.tvoid } - ) - (base_exception_t) - (hx_exception_t) - (fun v e -> - - let exc_cl = get_cl (get_type gen (["haxe";"lang"],"Exceptions")) in - let exc_field = mk_static_field_access_infer exc_cl "exception" e.epos [] in - let esetstack = mk (TBinop(Ast.OpAssign, exc_field, mk_local v e.epos)) v.v_type e.epos in - - Type.concat esetstack e; - ) - ); + (fun t -> not (is_exception (real_type t))) + (fun throwexpr expr -> + let wrap_static = mk_static_field_access (hx_exception) "wrap" (TFun([("obj",false,t_dynamic)], base_exception_t)) expr.epos in + { throwexpr with eexpr = TThrow { expr with eexpr = TCall(wrap_static, [expr]); etype = hx_exception_t }; etype = gen.gcon.basic.tvoid } + ) + (fun v_to_unwrap pos -> + let local = mk_cast hx_exception_t { eexpr = TLocal(v_to_unwrap); etype = v_to_unwrap.v_type; epos = pos } in + mk_field_access gen local "obj" pos + ) + (fun rethrow -> + { rethrow with eexpr = TCall(mk_local (alloc_var "__rethrow__" t_dynamic) rethrow.epos, [rethrow]); etype = gen.gcon.basic.tvoid } + ) + (base_exception_t) + (hx_exception_t) + (fun v e -> - let get_typeof e = - { e with eexpr = TCall( { eexpr = TLocal( alloc_var "__typeof__" t_dynamic ); etype = t_dynamic; epos = e.epos }, [e] ) } - in + let exc_cl = get_cl (get_type gen (["haxe";"lang"],"Exceptions")) in + let exc_field = mk_static_field_access_infer exc_cl "exception" e.epos [] in + let esetstack = mk (TBinop(Ast.OpAssign, exc_field, mk_local v e.epos)) v.v_type e.epos in - ClassInstance.configure gen (ClassInstance.traverse gen (fun e mt -> - get_typeof e - )); + Type.concat esetstack e; + ); - CastDetect.configure gen (CastDetect.default_implementation gen (Some (TEnum(empty_e, []))) (not erase_generics) ~native_string_cast:false ~overloads_cast_to_base:true); + ClassInstance.configure gen (fun e _ -> { e with eexpr = TCall({ eexpr = TLocal(alloc_var "__typeof__" t_dynamic); etype = t_dynamic; epos = e.epos }, [e]) }); - (*FollowAll.configure gen;*) + CastDetect.configure gen (Some empty_ctor_type) (not erase_generics) ~overloads_cast_to_base:true; - SwitchToIf.configure gen (SwitchToIf.traverse gen (fun e -> + SwitchToIf.configure gen (fun e -> match e.eexpr with | TSwitch(cond, cases, def) -> (match gen.gfollow#run_f cond.etype with @@ -3154,35 +3135,34 @@ let configure gen = | _ -> true ) | _ -> assert false - ) true ) ; + ); - ExpressionUnwrap.configure gen (ExpressionUnwrap.traverse gen (fun e -> Some { eexpr = TVar(mk_temp gen "expr" e.etype, Some e); etype = gen.gcon.basic.tvoid; epos = e.epos })); + ExpressionUnwrap.configure gen (fun e -> Some { eexpr = TVar(mk_temp gen "expr" e.etype, Some e); etype = gen.gcon.basic.tvoid; epos = e.epos }); UnnecessaryCastsRemoval.configure gen; - IntDivisionSynf.configure gen (IntDivisionSynf.default_implementation gen true); + IntDivisionSynf.configure gen; - UnreachableCodeEliminationSynf.configure gen (UnreachableCodeEliminationSynf.traverse gen false true true false); + UnreachableCodeEliminationSynf.configure gen false; - ArrayDeclSynf.configure gen (ArrayDeclSynf.default_implementation gen native_arr_cl); + ArrayDeclSynf.configure gen native_arr_cl; let goto_special = alloc_var "__goto__" t_dynamic in let label_special = alloc_var "__label__" t_dynamic in - SwitchBreakSynf.configure gen (SwitchBreakSynf.traverse gen + SwitchBreakSynf.configure gen (fun e_loop n api -> - api ({ eexpr = TCall( mk_local label_special e_loop.epos, [ mk_int gen n e_loop.epos ] ); etype = t_dynamic; epos = e_loop.epos }) false; + api ({ eexpr = TCall( mk_local label_special e_loop.epos, [ ExprBuilder.make_int gen.gcon n e_loop.epos ] ); etype = t_dynamic; epos = e_loop.epos }) false; e_loop ) (fun e_break n api -> - { eexpr = TCall( mk_local goto_special e_break.epos, [ mk_int gen n e_break.epos ] ); etype = t_dynamic; epos = e_break.epos } - ) - ); + { eexpr = TCall( mk_local goto_special e_break.epos, [ ExprBuilder.make_int gen.gcon n e_break.epos ] ); etype = t_dynamic; epos = e_break.epos } + ); - DefaultArguments.configure gen (DefaultArguments.traverse gen); + DefaultArguments.configure gen; InterfaceMetas.configure gen; - CSharpSpecificSynf.configure gen (CSharpSpecificSynf.traverse gen runtime_cl); - CSharpSpecificESynf.configure gen (CSharpSpecificESynf.traverse gen runtime_cl); + CSharpSpecificSynf.configure gen runtime_cl; + CSharpSpecificESynf.configure gen runtime_cl; let out_files = ref [] in @@ -3200,7 +3180,7 @@ let configure gen = output_string f v; close_out f; - out_files := (unique_full_path full_path) :: !out_files + out_files := (Path.unique_full_path full_path) :: !out_files ) gen.gcon.resources; end; (* add resources array *) @@ -3209,9 +3189,9 @@ let configure gen = let cf = PMap.find "content" res.cl_statics in let res = ref [] in Hashtbl.iter (fun name v -> - res := { eexpr = TConst(TString name); etype = gen.gcon.basic.tstring; epos = Ast.null_pos } :: !res; + res := { eexpr = TConst(TString name); etype = gen.gcon.basic.tstring; epos = null_pos } :: !res; ) gen.gcon.resources; - cf.cf_expr <- Some ({ eexpr = TArrayDecl(!res); etype = gen.gcon.basic.tarray gen.gcon.basic.tstring; epos = Ast.null_pos }) + cf.cf_expr <- Some ({ eexpr = TArrayDecl(!res); etype = gen.gcon.basic.tarray gen.gcon.basic.tstring; epos = null_pos }) with | Not_found -> ()); run_filters gen; @@ -3228,7 +3208,6 @@ let configure gen = let hashes = Hashtbl.fold (fun i s acc -> incr nhash; (normalize_i i,s) :: acc) rcf_ctx.rcf_hash_fields [] in let hashes = List.sort (fun (i,s) (i2,s2) -> compare i i2) hashes in - let flookup_cl = get_cl (get_type gen (["haxe";"lang"], "FieldLookup")) in let haxe_libs = List.filter (function (_,_,_,lookup) -> is_some (lookup (["haxe";"lang"], "DceNo"))) gen.gcon.net_libs in (try (* first let's see if we're adding a -net-lib that has already a haxe.lang.FieldLookup *) @@ -3298,16 +3277,23 @@ let configure gen = TypeParams.RenameTypeParameters.run gen; - let t = Common.timer "code generation" in - let parts = Str.split_delim (Str.regexp "[\\/]+") gen.gcon.file in mkdir_recursive "" parts; - generate_modules gen "cs" "src" module_gen out_files; + + List.iter (fun md_def -> + let source_dir = gen.gcon.file ^ "/src/" ^ (String.concat "/" (fst (path_of_md_def md_def))) in + let w = SourceWriter.new_source_writer() in + let should_write = List.fold_left (fun should md -> module_type_gen w md || should) false md_def.m_types in + if should_write then begin + let path = path_of_md_def md_def in + write_file gen w source_dir path "cs" out_files + end + ) gen.gmodules; if not (Common.defined gen.gcon Define.KeepOldOutput) then clean_files (gen.gcon.file ^ "/src") !out_files gen.gcon.verbose; - dump_descriptor gen ("hxcs_build.txt") path_s module_s; + dump_descriptor gen ("hxcs_build.txt") s_type_path module_s; if ( not (Common.defined gen.gcon Define.NoCompilation) ) then begin let old_dir = Sys.getcwd() in Sys.chdir gen.gcon.file; @@ -3315,9 +3301,7 @@ let configure gen = print_endline cmd; if gen.gcon.run_command cmd <> 0 then failwith "Build failed"; Sys.chdir old_dir; - end; - - t() + end (* end of configure function *) @@ -3338,15 +3322,15 @@ let generate con = let type_cl = get_cl ( get_type gen (["System"], "Type")) in let basic_fns = [ - mk_class_field "Equals" (TFun(["obj",false,t_dynamic], basic.tbool)) true Ast.null_pos (Method MethNormal) []; - mk_class_field "ToString" (TFun([], basic.tstring)) true Ast.null_pos (Method MethNormal) []; - mk_class_field "GetHashCode" (TFun([], basic.tint)) true Ast.null_pos (Method MethNormal) []; - mk_class_field "GetType" (TFun([], TInst(type_cl, []))) true Ast.null_pos (Method MethNormal) []; + mk_class_field "Equals" (TFun(["obj",false,t_dynamic], basic.tbool)) true null_pos (Method MethNormal) []; + mk_class_field "ToString" (TFun([], basic.tstring)) true null_pos (Method MethNormal) []; + mk_class_field "GetHashCode" (TFun([], basic.tint)) true null_pos (Method MethNormal) []; + mk_class_field "GetType" (TFun([], TInst(type_cl, []))) true null_pos (Method MethNormal) []; ] in List.iter (fun cf -> gen.gbase_class_fields <- PMap.add cf.cf_name cf gen.gbase_class_fields) basic_fns; configure gen with | TypeNotFound path -> - con.error ("Error. Module '" ^ (path_s path) ^ "' is required and was not included in build.") Ast.null_pos); + con.error ("Error. Module '" ^ (s_type_path path) ^ "' is required and was not included in build.") null_pos); debug_mode := false (* -net-lib implementation *) @@ -3473,7 +3457,7 @@ let rec convert_signature ctx p = function | LObject -> mk_type_path ctx ([],[],"Dynamic") [] | LPointer s | LManagedPointer s -> - mk_type_path ctx (["cs"],[],"Pointer") [ TPType (convert_signature ctx p s) ] + mk_type_path ctx (["cs"],[],"Pointer") [ TPType (convert_signature ctx p s,null_pos) ] | LTypedReference -> mk_type_path ctx (["cs";"system"],[],"TypedReference") [] | LIntPtr -> @@ -3481,20 +3465,20 @@ let rec convert_signature ctx p = function | LUIntPtr -> mk_type_path ctx (["cs";"system"],[],"UIntPtr") [] | LValueType (s,args) | LClass (s,args) -> - mk_type_path ctx s (List.map (fun s -> TPType (convert_signature ctx p s)) args) + mk_type_path ctx s (List.map (fun s -> TPType (convert_signature ctx p s,null_pos)) args) | LTypeParam i -> mk_type_path ctx ([],[],"T" ^ string_of_int i) [] | LMethodTypeParam i -> mk_type_path ctx ([],[],"M" ^ string_of_int i) [] | LVector s -> - mk_type_path ctx (["cs"],[],"NativeArray") [TPType (convert_signature ctx p s)] + mk_type_path ctx (["cs"],[],"NativeArray") [TPType (convert_signature ctx p s,null_pos)] (* | LArray of ilsig_norm * (int option * int option) array *) | LMethod (_,ret,args) -> - CTFunction (List.map (convert_signature ctx p) args, convert_signature ctx p ret) + CTFunction (List.map (fun v -> convert_signature ctx p v,null_pos) args, (convert_signature ctx p ret,null_pos)) | _ -> mk_type_path ctx ([],[], "Dynamic") [] let ilpath_s = function - | ns,[], name -> path_s (ns,name) + | ns,[], name -> s_type_path (ns,name) | [],nested,name -> String.concat "." nested ^ "." ^ name | ns, nested, name -> String.concat "." ns ^ "." ^ String.concat "." nested ^ "." ^ name @@ -3552,14 +3536,14 @@ let convert_ilenum ctx p ?(is_flag=false) ilcls = | _ -> [], Int64.zero in - data := ( { ec_name = f.fname; ec_doc = None; ec_meta = meta; ec_args = []; ec_pos = p; ec_params = []; ec_type = None; }, const) :: !data; + data := ( { ec_name = f.fname,null_pos; ec_doc = None; ec_meta = meta; ec_args = []; ec_pos = p; ec_params = []; ec_type = None; }, const) :: !data; ) ilcls.cfields; let data = List.stable_sort (fun (_,i1) (_,i2) -> Int64.compare i1 i2) (List.rev !data) in let _, c = netpath_to_hx ctx.nstd ilcls.cpath in let name = netname_to_hx c in EEnum { - d_name = if is_flag then name ^ "_FlagsEnum" else name; + d_name = (if is_flag then name ^ "_FlagsEnum" else name),null_pos; d_doc = None; d_params = []; (* enums never have type parameters *) d_meta = !meta; @@ -3604,9 +3588,10 @@ let convert_ilfield ctx p field = Printf.printf "\t%sfield %s : %s\n" (if List.mem AStatic acc then "static " else "") cff_name (IlMetaDebug.ilsig_s field.fsig.ssig); let kind = match readonly with | true -> - FProp ("default", "never", Some (convert_signature ctx p field.fsig.snorm), None) + cff_meta := (Meta.ReadOnly, [], cff_pos) :: !cff_meta; + FProp (("default",null_pos), ("never",null_pos), Some (convert_signature ctx p field.fsig.snorm,null_pos), None) | false -> - FVar (Some (convert_signature ctx p field.fsig.snorm), None) + FVar (Some (convert_signature ctx p field.fsig.snorm,null_pos), None) in let cff_name, cff_meta = if String.get cff_name 0 = '%' then @@ -3617,7 +3602,7 @@ let convert_ilfield ctx p field = cff_name, !cff_meta in { - cff_name = cff_name; + cff_name = cff_name,null_pos; cff_doc = cff_doc; cff_pos = cff_pos; cff_meta = cff_meta; @@ -3628,7 +3613,7 @@ let convert_ilfield ctx p field = let convert_ilevent ctx p ev = let p = { p with pfile = p.pfile ^" (" ^ev.ename ^")" } in let name = ev.ename in - let kind = FVar (Some (convert_signature ctx p ev.esig.snorm), None) in + let kind = FVar (Some (convert_signature ctx p ev.esig.snorm,null_pos), None) in let meta = [Meta.Event, [], p; Meta.Keep,[],p; Meta.SkipReflection,[],p] in let acc = [APrivate] in let add_m acc m = match m with @@ -3645,7 +3630,7 @@ let convert_ilevent ctx p ev = let acc = add_m acc ev.eremove in let acc = add_m acc ev.eraise in { - cff_name = name; + cff_name = name,null_pos; cff_doc = None; cff_pos = p; cff_meta = meta; @@ -3737,24 +3722,25 @@ let convert_ilmethod ctx p m is_explicit_impl = | LManagedPointer s -> let is_out = List.mem POut flag.pf_io && not (List.mem PIn flag.pf_io) in let name = if is_out then "Out" else "Ref" in - mk_type_path ctx (["cs"],[],name) [ TPType (convert_signature ctx p s) ] + mk_type_path ctx (["cs"],[],name) [ TPType (convert_signature ctx p s,null_pos) ] | _ -> convert_signature ctx p (change_sig s.snorm) in - name,false,Some t,None) m.margs + (name,null_pos),false,[],Some (t,null_pos),None) m.margs in let ret = convert_signature ctx p (change_sig ret) in let types = List.map (fun t -> { - tp_name = "M" ^ string_of_int t.tnumber; + tp_name = "M" ^ string_of_int t.tnumber,null_pos; tp_params = []; tp_constraints = []; + tp_meta = []; } ) m.mtypes in FFun { f_params = types; f_args = args; - f_type = Some ret; + f_type = Some (ret,null_pos); f_expr = None; } in @@ -3778,7 +3764,7 @@ let convert_ilmethod ctx p m is_explicit_impl = | _ -> acc in { - cff_name = cff_name; + cff_name = cff_name,null_pos; cff_doc = cff_doc; cff_pos = cff_pos; cff_meta = cff_meta; @@ -3821,7 +3807,7 @@ let convert_ilprop ctx p prop is_explicit_impl = raise Exit (* special (?) getter; not used *) | Some(_,m) when access m <> FAPublic -> (match access m with | FAFamily - | FAFamOrAssem -> "null" + | FAFamOrAssem -> "never" | _ -> "never"); | Some _ -> "set" in @@ -3839,10 +3825,10 @@ let convert_ilprop ctx p prop is_explicit_impl = in let kind = - FProp (get, set, Some(convert_signature ctx p ilsig), None) + FProp ((get,null_pos), (set,null_pos), Some(convert_signature ctx p ilsig,null_pos), None) in { - cff_name = prop.pname; + cff_name = prop.pname,null_pos; cff_doc = None; cff_pos = p; cff_meta = meta; @@ -3876,7 +3862,7 @@ let mk_metas metas p = let mk_abstract_fun name p kind metas acc = let metas = mk_metas metas p in { - cff_name = name; + cff_name = name,null_pos; cff_doc = None; cff_pos = p; cff_meta = metas; @@ -3886,13 +3872,13 @@ let mk_abstract_fun name p kind metas acc = let convert_fun_arg ctx p = function | LManagedPointer s -> - mk_type_path ctx (["cs"],[],"Ref") [ TPType (convert_signature ctx p s) ] + mk_type_path ctx (["cs"],[],"Ref") [ TPType (convert_signature ctx p s,null_pos) ],p | s -> - convert_signature ctx p s + convert_signature ctx p s,p let convert_fun ctx p ret args = let args = List.map (convert_fun_arg ctx p) args in - CTFunction(args, convert_signature ctx p ret) + CTFunction(args, (convert_signature ctx p ret,null_pos)) let get_clsname ctx cpath = match netpath_to_hx ctx.nstd cpath with @@ -3907,16 +3893,17 @@ let convert_delegate ctx p ilcls = (* - AsDelegate():Super *) (* - @:op(A+B) Add(d:absType) *) (* - @:op(A-B) Remove(d:absType) *) - let abs_type = mk_type_path ctx (ilcls.cpath) (List.map (fun t -> TPType (mk_type_path ctx ([],[],"T" ^ string_of_int t.tnumber) [])) ilcls.ctypes) in + let abs_type = mk_type_path ctx (ilcls.cpath) (List.map (fun t -> TPType (mk_type_path ctx ([],[],"T" ^ string_of_int t.tnumber) [],null_pos)) ilcls.ctypes) in let invoke = List.find (fun m -> m.mname = "Invoke") ilcls.cmethods in let ret = invoke.mret.snorm in let args = List.map (fun (_,_,s) -> s.snorm) invoke.margs in let haxe_type = convert_fun ctx p ret args in let types = List.map (fun t -> { - tp_name = "T" ^ string_of_int t.tnumber; + tp_name = ("T" ^ string_of_int t.tnumber),null_pos; tp_params = []; tp_constraints = []; + tp_meta = []; } ) ilcls.ctypes in let mk_op_fn op name p = @@ -3927,15 +3914,15 @@ let convert_delegate ctx p ilcls = let expr = (ECall( (EField( (EConst(Ident (clsname)),p), fn_name ),p), [(EConst(Ident"arg1"),p);(EConst(Ident"arg2"),p)]),p) in FFun { f_params = types; - f_args = ["arg1",false,Some abs_type,None;"arg2",false,Some abs_type,None]; - f_type = Some abs_type; + f_args = [("arg1",null_pos),false,[],Some (abs_type,null_pos),None;("arg2",null_pos),false,[],Some (abs_type,null_pos),None]; + f_type = Some (abs_type,null_pos); f_expr = Some ( (EReturn (Some expr), p) ); } in let mk_op op name = let p = { p with pfile = p.pfile ^" (op " ^ name ^ ")" } in { - cff_name = name; + cff_name = name,null_pos; cff_doc = None; cff_pos = p; cff_meta = [ Meta.Extern,[],p ; Meta.Op, [ (EBinop(op, (EConst(Ident"A"),p), (EConst(Ident"B"),p)),p) ], p ]; @@ -3944,7 +3931,7 @@ let convert_delegate ctx p ilcls = } in let params = (List.map (fun s -> - TPType (mk_type_path ctx ([],[],s.tp_name) []) + TPType (mk_type_path ctx ([],[],fst s.tp_name) [],null_pos) ) types) in let underlying_type = match ilcls.cpath with | ns,inner,name -> @@ -3953,33 +3940,16 @@ let convert_delegate ctx p ilcls = let fn_new = FFun { f_params = []; - f_args = ["hxfunc",false,Some haxe_type,None]; + f_args = [("hxfunc",null_pos),false,[],Some (haxe_type,null_pos),None]; f_type = None; f_expr = Some ( EBinop(Ast.OpAssign, (EConst(Ident "this"),p), (mk_special_call "__delegate__" p [EConst(Ident "hxfunc"),p]) ), p ); } in let fn_from_hx = FFun { f_params = types; - f_args = ["hxfunc",false,Some haxe_type,None]; - f_type = Some( mk_type_path ctx ilcls.cpath params ); + f_args = [("hxfunc",null_pos),false,[],Some (haxe_type,null_pos),None]; + f_type = Some( mk_type_path ctx ilcls.cpath params,null_pos ); f_expr = Some( EReturn( Some (mk_special_call "__delegate__" p [EConst(Ident "hxfunc"),p] )), p); } in - let i = ref 0 in - let j = ref 0 in - let fn_invoke = FFun { - f_params = []; - f_args = List.map (fun arg -> - incr i; - "arg" ^ string_of_int !i, false, Some (convert_fun_arg ctx p arg), None - ) args; - f_type = Some(convert_signature ctx p ret); - f_expr = Some( - EReturn( Some ( - mk_this_call "Invoke" p (List.map (fun arg -> - incr j; (EConst( Ident ("arg" ^ string_of_int !j) ), p) - ) args ) - )), p - ); - } in let fn_asdel = FFun { f_params = []; f_args = []; @@ -3990,16 +3960,15 @@ let convert_delegate ctx p ilcls = } in let fn_new = mk_abstract_fun "new" p fn_new [Meta.Extern] [APublic;AInline] in let fn_from_hx = mk_abstract_fun "FromHaxeFunction" p fn_from_hx [Meta.Extern;Meta.From] [APublic;AInline;AStatic] in - let fn_invoke = mk_abstract_fun "Invoke" p fn_invoke [Meta.Extern] [APublic;AInline] in let fn_asdel = mk_abstract_fun "AsDelegate" p fn_asdel [Meta.Extern] [APublic;AInline] in let _, c = netpath_to_hx ctx.nstd ilcls.cpath in EAbstract { - d_name = netname_to_hx c; + d_name = netname_to_hx c,null_pos; d_doc = None; d_params = types; - d_meta = mk_metas [Meta.Delegate] p; - d_flags = [AIsType underlying_type]; - d_data = [fn_new;fn_from_hx;fn_invoke;fn_asdel;mk_op Ast.OpAdd "Add";mk_op Ast.OpSub "Remove"]; + d_meta = mk_metas [Meta.Delegate; Meta.Forward] p; + d_flags = [AIsType (underlying_type,null_pos)]; + d_data = [fn_new;fn_from_hx;fn_asdel;mk_op Ast.OpAdd "Add";mk_op Ast.OpSub "Remove"]; } let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with @@ -4034,12 +4003,12 @@ let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with (match ilcls.csuper with | Some { snorm = LClass ( (["System"],[],"Object"), [] ) } -> () | Some ({ snorm = LClass ( (["System"],[],"ValueType"), [] ) } as s) -> - flags := HExtends (get_type_path ctx (convert_signature ctx p s.snorm)) :: !flags; + flags := HExtends (get_type_path ctx (convert_signature ctx p s.snorm),null_pos) :: !flags; meta := (Meta.Struct,[],p) :: !meta | Some { snorm = LClass ( (["haxe";"lang"],[],"HxObject"), [] ) } -> meta := (Meta.HxGen,[],p) :: !meta | Some s -> - flags := HExtends (get_type_path ctx (convert_signature ctx p s.snorm)) :: !flags + flags := HExtends (get_type_path ctx (convert_signature ctx p s.snorm),null_pos) :: !flags | _ -> ()); let has_explicit_ifaces = ref false in @@ -4051,9 +4020,9 @@ let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with | i -> if is_explicit ctx ilcls i then has_explicit_ifaces := true; flags := if !is_interface then - HExtends (get_type_path ctx (convert_signature ctx p i)) :: !flags + HExtends (get_type_path ctx (convert_signature ctx p i),null_pos) :: !flags else - HImplements (get_type_path ctx (convert_signature ctx p i)) :: !flags + HImplements (get_type_path ctx (convert_signature ctx p i),null_pos) :: !flags ) ilcls.cimplements; (* this is needed because of explicit interfaces. see http://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx *) (* explicit interfaces can't be mapped into Haxe in any way - since their fields can't be accessed directly, but they still implement that interface *) @@ -4064,9 +4033,9 @@ let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with ignore (List.exists (function | { psig = { snorm = LMethod(_,ret,[v]) } } -> flags := if !is_interface then - (HExtends( raw_type_path ctx ([],"ArrayAccess") [ TPType (convert_signature ctx p ret) ]) :: !flags) + (HExtends( raw_type_path ctx ([],"ArrayAccess") [ TPType (convert_signature ctx p ret,null_pos) ],null_pos) :: !flags) else - (HImplements( raw_type_path ctx ([],"ArrayAccess") [ TPType (convert_signature ctx p ret) ]) :: !flags); + (HImplements( raw_type_path ctx ([],"ArrayAccess") [ TPType (convert_signature ctx p ret,null_pos) ],null_pos) :: !flags); true | _ -> false) ilcls.cprops); @@ -4095,27 +4064,28 @@ let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with let params = List.map (fun p -> { - tp_name = "T" ^ string_of_int p.tnumber; + tp_name = "T" ^ string_of_int p.tnumber,null_pos; tp_params = []; tp_constraints = []; + tp_meta = []; }) ilcls.ctypes in if delegate then begin (* add op_Addition and op_Subtraction *) let path = ilcls.cpath in - let thist = mk_type_path ctx path (List.map (fun t -> TPType (mk_type_path ctx ([],[],"T" ^ string_of_int t.tnumber) [])) ilcls.ctypes) in + let thist = mk_type_path ctx path (List.map (fun t -> TPType (mk_type_path ctx ([],[],"T" ^ string_of_int t.tnumber) [],null_pos)) ilcls.ctypes) in let op name = { - cff_name = name; + cff_name = name,null_pos; cff_doc = None; cff_pos = p; cff_meta = []; cff_access = [APublic;AStatic]; cff_kind = FFun { f_params = params; - f_args = ["arg1",false,Some thist,None;"arg2",false,Some thist,None]; - f_type = Some thist; + f_args = [("arg1",null_pos),false,[],Some (thist,null_pos),None;("arg2",null_pos),false,[],Some (thist,null_pos),None]; + f_type = Some (thist,null_pos); f_expr = None; }; } @@ -4129,7 +4099,7 @@ let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with in let _, c = netpath_to_hx ctx.nstd path in EClass { - d_name = netname_to_hx c; + d_name = netname_to_hx c,null_pos; d_doc = None; d_params = params; d_meta = !meta; @@ -4238,10 +4208,7 @@ let compatible_field f1 f2 = match f1, f2 with let get_all_fields cls = let all_fields = List.map (fun f -> IlField f, cls.cpath, f.fname, List.mem CStatic f.fflags.ff_contract) cls.cfields in let all_fields = all_fields @ List.map (fun m -> IlMethod m, cls.cpath, m.mname, List.mem CMStatic m.mflags.mf_contract) cls.cmethods in - let all_fields = all_fields @ List.map (function - | p -> - IlProp p, cls.cpath, p.pname, is_static (IlProp p) - ) cls.cprops in + let all_fields = all_fields @ List.map (fun p -> IlProp p, cls.cpath, p.pname, is_static (IlProp p)) cls.cprops in all_fields let normalize_ilcls ctx cls = @@ -4436,7 +4403,7 @@ let add_net_lib com file std = Hashtbl.iter (fun _ td -> let path = IlMetaTools.get_path (TypeDef td) in if PMap.mem "net_loader_debug" com.defines then - Printf.printf "found %s\n" (path_s (netpath_to_hx path)); + Printf.printf "found %s\n" (s_type_path (netpath_to_hx path)); Hashtbl.replace com.net_path_map (netpath_to_hx path) path; Hashtbl.replace meta.il_typedefs path td ) il_typedefs; @@ -4468,12 +4435,12 @@ let add_net_lib com file std = in let build path = - let p = { pfile = !real_file ^ " @ " ^ path_s path; pmin = 0; pmax = 0; } in + let p = { pfile = !real_file ^ " @ " ^ s_type_path path; pmin = 0; pmax = 0; } in let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in let cp = ref [] in let rec build path = try if PMap.mem "net_loader_debug" com.defines then - Printf.printf "looking up %s\n" (path_s path); + Printf.printf "looking up %s\n" (s_type_path path); match lookup path with | Some({csuper = Some{snorm = LClass( (["System"],[],("Delegate"|"MulticastDelegate")),_)}} as cls) when List.mem SSealed cls.cflags.tdf_semantics -> diff --git a/src/generators/genhl.ml b/src/generators/genhl.ml new file mode 100644 index 00000000..2e3fc191 --- /dev/null +++ b/src/generators/genhl.ml @@ -0,0 +1,3719 @@ +(* + * Copyright (C)2005-2015 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. + *) +open Unix +open Globals +open Ast +open Type +open Common +open Hlcode + +(* compiler *) + +type ('a,'b) lookup = { + arr : 'b DynArray.t; + mutable map : ('a, int) PMap.t; +} + +(* not mutable, might be be shared *) +type method_capture = { + c_map : (int, int) PMap.t; + c_vars : tvar array; + c_type : ttype; + c_group : bool; +} + +type allocator = { + mutable a_all : int list; + mutable a_hold : int list; +} + +type lassign = (string index * int * int) + +type method_context = { + mid : int; + mregs : (int, ttype) lookup; + mops : opcode DynArray.t; + mret : ttype; + mdebug : Globals.pos DynArray.t; + mvars : (int, int) Hashtbl.t; + mhasthis : bool; + mutable mdeclared : int list; + mutable mallocs : (ttype, allocator) PMap.t; + mutable mcaptured : method_capture; + mutable mcontinues : (int -> unit) list; + mutable mbreaks : (int -> unit) list; + mutable mtrys : int; + mutable mloop_trys : int; + mutable mcaptreg : int; + mutable mcurpos : Globals.pos; + mutable massign : lassign list; +} + +type array_impl = { + aall : tclass; + abase : tclass; + adyn : tclass; + aobj : tclass; + aui16 : tclass; + ai32 : tclass; + af32 : tclass; + af64 : tclass; +} + +type context = { + com : Common.context; + cglobals : (string, ttype) lookup; + cstrings : (string, string) lookup; + cfloats : (float, float) lookup; + cints : (int32, int32) lookup; + cnatives : (string, (string index * string index * ttype * functable index)) lookup; + cfids : (string * path, unit) lookup; + cfunctions : fundecl DynArray.t; + optimize : bool; + overrides : (string * path, bool) Hashtbl.t; + defined_funs : (int,unit) Hashtbl.t; + is_macro : bool; + mutable dump_out : (unit IO.output) option; + mutable cached_types : (path, ttype) PMap.t; + mutable m : method_context; + mutable anons_cache : (tanon * ttype) list; + mutable method_wrappers : ((ttype * ttype), int) PMap.t; + mutable rec_cache : (Type.t * ttype option ref) list; + mutable cached_tuples : (ttype list, ttype) PMap.t; + macro_typedefs : (string, ttype) Hashtbl.t; + array_impl : array_impl; + base_class : tclass; + base_type : tclass; + base_enum : tclass; + core_type : tclass; + core_enum : tclass; + ref_abstract : tabstract; + cdebug_files : (string, string) lookup; + cdebug_locals : (string, string ) lookup; + cdebug_assigns : (lassign array) DynArray.t; +} + +(* --- *) + +type access = + | ANone + | AGlobal of global + | ALocal of tvar * reg + | AStaticVar of global * ttype * field index + | AStaticFun of fundecl index + | AInstanceFun of texpr * fundecl index + | AInstanceProto of texpr * field index + | AInstanceField of texpr * field index + | AArray of reg * (ttype * ttype) * reg + | AVirtualMethod of texpr * field index + | ADynamic of texpr * string index + | AEnum of tenum * field index + | ACaptured of field index + +let is_to_string t = + match follow t with + | TFun([],r) -> (match follow r with TInst({ cl_path=[],"String" },[]) -> true | _ -> false) + | _ -> false + +let is_extern_field f = + Type.is_extern_field f || (match f.cf_kind with Method MethNormal -> List.exists (fun (m,_,_) -> m = Meta.Custom ":hlNative") f.cf_meta | _ -> false) || Meta.has Meta.Extern f.cf_meta + +let is_array_class name = + match name with + | "hl.types.ArrayDyn" | "hl.types.ArrayBytes_Int" | "hl.types.ArrayBytes_Float" | "hl.types.ArrayObj" | "hl.types.ArrayBytes_Single" | "hl.types.ArrayBytes_hl_UI16" -> true + | _ -> false + +let is_array_type t = + match t with + | HObj p -> is_array_class p.pname + | _ -> false + +let to_utf8 str p = + let u8 = try + UTF8.validate str; + str; + with + UTF8.Malformed_code -> + (* ISO to utf8 *) + let b = UTF8.Buf.create 0 in + String.iter (fun c -> UTF8.Buf.add_char b (UChar.of_char c)) str; + UTF8.Buf.contents b + in + let ccount = ref 0 in + UTF8.iter (fun c -> + let c = UChar.code c in + if (c >= 0xD800 && c <= 0xDFFF) || c >= 0x110000 then abort "Invalid unicode char" p; + incr ccount; + if c > 0x10000 then incr ccount; + ) u8; + u8, !ccount + +let tuple_type ctx tl = + try + PMap.find tl ctx.cached_tuples + with Not_found -> + let ct = HEnum { + eglobal = None; + ename = ""; + eid = 0; + efields = [|"",0,Array.of_list tl|]; + } in + ctx.cached_tuples <- PMap.add tl ct ctx.cached_tuples; + ct + +let type_size_bits = function + | HUI8 | HBool -> 0 + | HUI16 -> 1 + | HI32 | HF32 -> 2 + | HF64 -> 3 + | _ -> assert false + +let new_lookup() = + { + arr = DynArray.create(); + map = PMap.empty; + } + +let null_capture = + { + c_vars = [||]; + c_map = PMap.empty; + c_type = HVoid; + c_group = false; + } + +let lookup l v fb = + try + PMap.find v l.map + with Not_found -> + let id = DynArray.length l.arr in + DynArray.add l.arr (Obj.magic 0); + l.map <- PMap.add v id l.map; + DynArray.set l.arr id (fb()); + id + +let lookup_alloc l v = + let id = DynArray.length l.arr in + DynArray.add l.arr v; + id + +let method_context id t captured hasthis = + { + mid = id; + mregs = new_lookup(); + mops = DynArray.create(); + mvars = Hashtbl.create 0; + mallocs = PMap.empty; + mret = t; + mbreaks = []; + mdeclared = []; + mcontinues = []; + mhasthis = hasthis; + mcaptured = captured; + mtrys = 0; + mloop_trys = 0; + mcaptreg = 0; + mdebug = DynArray.create(); + mcurpos = Globals.null_pos; + massign = []; + } + +let field_name c f = + s_type_path c.cl_path ^ ":" ^ f.cf_name + +let efield_name e f = + s_type_path e.e_path ^ ":" ^ f.ef_name + +let global_type ctx g = + DynArray.get ctx.cglobals.arr g + +let is_overriden ctx c f = + ctx.is_macro || Hashtbl.mem ctx.overrides (f.cf_name,c.cl_path) + +let alloc_float ctx f = + lookup ctx.cfloats f (fun() -> f) + +let alloc_i32 ctx i = + lookup ctx.cints i (fun() -> i) + +let alloc_string ctx s = + lookup ctx.cstrings s (fun() -> s) + +let array_class ctx t = + match t with + | HI32 -> + ctx.array_impl.ai32 + | HUI16 -> + ctx.array_impl.aui16 + | HF32 -> + ctx.array_impl.af32 + | HF64 -> + ctx.array_impl.af64 + | HDyn -> + ctx.array_impl.adyn + | _ -> + ctx.array_impl.aobj + +let member_fun c t = + match follow t with + | TFun (args, ret) -> TFun (("this",false,TInst(c,[])) :: args, ret) + | _ -> assert false + +let rec unsigned t = + match follow t with + | TAbstract ({ a_path = [],"UInt" },_) -> true + | TAbstract (a,pl) -> unsigned (Abstract.get_underlying_type a pl) + | _ -> false + +let unsigned_op e1 e2 = + let is_unsigned e = + match e.eexpr with + | TConst (TInt _) -> true + | _ -> unsigned e.etype + in + is_unsigned e1 && is_unsigned e2 + +let set_curpos ctx p = + ctx.m.mcurpos <- p + +let make_debug ctx arr = + let get_relative_path p = + match Common.defined ctx.com Common.Define.AbsolutePath with + | true -> if (Filename.is_relative p.pfile) + then Filename.concat (Sys.getcwd()) p.pfile + else p.pfile + | false -> try + (* lookup relative path *) + let len = String.length p.pfile in + let base = List.find (fun path -> + let l = String.length path in + len > l && String.sub p.pfile 0 l = path + ) ctx.com.Common.class_path in + let l = String.length base in + String.sub p.pfile l (len - l) + with Not_found -> + p.pfile + in + let pos = ref (0,0) in + let cur_file = ref 0 in + let cur_line = ref 0 in + let cur = ref Globals.null_pos in + let out = Array.make (DynArray.length arr) !pos in + for i = 0 to DynArray.length arr - 1 do + let p = DynArray.unsafe_get arr i in + if p != !cur then begin + let file = if p.pfile == (!cur).pfile then !cur_file else lookup ctx.cdebug_files p.pfile (fun() -> if ctx.is_macro then p.pfile else get_relative_path p) in + let line = if ctx.is_macro then p.pmin lor ((p.pmax - p.pmin) lsl 20) else Lexer.get_error_line p in + if line <> !cur_line || file <> !cur_file then begin + cur_file := file; + cur_line := line; + pos := (file,line); + end; + cur := p; + end; + Array.unsafe_set out i !pos + done; + out + +let rec to_type ?tref ctx t = + match t with + | TMono r -> + (match !r with + | None -> HDyn + | Some t -> to_type ?tref ctx t) + | TType (td,tl) -> + let t = (try + match !(List.assq t ctx.rec_cache) with + | None -> abort "Unsupported recursive type" td.t_pos + | Some t -> t + with Not_found -> + let tref = ref None in + ctx.rec_cache <- (t,tref) :: ctx.rec_cache; + let t = to_type ~tref ctx (apply_params td.t_params tl td.t_type) in + ctx.rec_cache <- List.tl ctx.rec_cache; + t + ) in + (match td.t_path with + | [], "Null" when not (is_nullable t) -> HNull t + | ["haxe";"macro"], name -> Hashtbl.replace ctx.macro_typedefs name t; t + | _ -> t) + | TLazy f -> + to_type ?tref ctx (!f()) + | TFun (args, ret) -> + HFun (List.map (fun (_,o,t) -> + let pt = to_type ctx t in + if o && not (is_nullable pt) then HRef pt else pt + ) args, to_type ctx ret) + | TAnon a when (match !(a.a_status) with Statics _ | EnumStatics _ -> true | _ -> false) -> + (match !(a.a_status) with + | Statics c -> + class_type ctx c (List.map snd c.cl_params) true + | EnumStatics e -> + enum_class ctx e + | _ -> assert false) + | TAnon a -> + (try + (* can't use physical comparison in PMap since addresses might change in GC compact, + maybe add an uid to tanon if too slow ? *) + List.assq a ctx.anons_cache + with Not_found -> + let vp = { + vfields = [||]; + vindex = PMap.empty; + } in + let t = HVirtual vp in + (match tref with + | None -> () + | Some r -> r := Some t); + ctx.anons_cache <- (a,t) :: ctx.anons_cache; + let fields = PMap.fold (fun cf acc -> + match cf.cf_kind with + | Var _ when (match follow cf.cf_type with TAnon _ | TFun _ -> true | _ -> false) -> + (* + if it's another virtual or a method, it might not match our own (might be larger, or class) + *) + acc + | Method _ -> + acc + | _ -> + (cf.cf_name,alloc_string ctx cf.cf_name,to_type ctx cf.cf_type) :: acc + ) a.a_fields [] in + if fields = [] then + let t = HDyn in + ctx.anons_cache <- (a,t) :: List.tl ctx.anons_cache; + t + else + let fields = List.sort (fun (n1,_,_) (n2,_,_) -> compare n1 n2) fields in + vp.vfields <- Array.of_list fields; + Array.iteri (fun i (n,_,_) -> vp.vindex <- PMap.add n i vp.vindex) vp.vfields; + t + ) + | TDynamic _ -> + HDyn + | TEnum (e,_) -> + enum_type ~tref ctx e + | TInst ({ cl_path = ["hl"],"Abstract" },[TInst({ cl_kind = KExpr (EConst (String name),_) },_)]) -> + HAbstract (name, alloc_string ctx name) + | TInst (c,pl) -> + (match c.cl_kind with + | KTypeParameter tl -> + let rec loop = function + | [] -> HDyn + | t :: tl -> + match follow (apply_params c.cl_params pl t) with + | TInst ({cl_interface=false},_) as t -> to_type ?tref ctx t + | _ -> loop tl + in + loop tl + | _ -> class_type ~tref ctx c pl false) + | TAbstract (a,pl) -> + if Meta.has Meta.CoreType a.a_meta then + (match a.a_path with + | [], "Void" -> HVoid + | [], "Int" | [], "UInt" -> HI32 + | [], "Float" -> HF64 + | [], "Single" -> HF32 + | [], "Bool" -> HBool + | [], "Dynamic" -> HDyn + | [], "Class" -> + class_type ctx ctx.base_class [] false + | [], "Enum" -> + class_type ctx ctx.base_type [] false + | [], "EnumValue" -> HDyn + | ["hl"], "Ref" -> HRef (to_type ctx (List.hd pl)) + | ["hl"], ("Bytes" | "BytesAccess") -> HBytes + | ["hl"], "Type" -> HType + | ["hl"], "UI16" -> HUI16 + | ["hl"], "UI8" -> HUI8 + | ["hl"], "NativeArray" -> HArray + | ["haxe";"macro"], "Position" -> HAbstract ("macro_pos", alloc_string ctx "macro_pos") + | _ -> failwith ("Unknown core type " ^ s_type_path a.a_path)) + else + to_type ?tref ctx (Abstract.get_underlying_type a pl) + +and resolve_class ctx c pl statics = + let not_supported() = + failwith ("Extern type not supported : " ^ s_type (print_context()) (TInst (c,pl))) + in + match c.cl_path, pl with + | ([],"Array"), [t] -> + if statics then ctx.array_impl.abase else array_class ctx (to_type ctx t) + | ([],"Array"), [] -> + assert false + | _, _ when c.cl_extern -> + not_supported() + | _ -> + c + +and field_type ctx f p = + match f with + | FInstance (c,pl,f) | FClosure (Some (c,pl),f) -> + let creal = resolve_class ctx c pl false in + let rec loop c = + try + PMap.find f.cf_name c.cl_fields + with Not_found -> + match c.cl_super with + | Some (csup,_) -> loop csup + | None -> abort (s_type_path creal.cl_path ^ " is missing field " ^ f.cf_name) p + in + (loop creal).cf_type + | FStatic (_,f) | FAnon f | FClosure (_,f) -> f.cf_type + | FDynamic _ -> t_dynamic + | FEnum (_,f) -> f.ef_type + +and real_type ctx e = + let rec loop e = + match e.eexpr with + | TField (_,f) -> + let ft = field_type ctx f e.epos in + (* + Handle function variance: + If we have type parameters which are function types, we need to keep the functions + because we might need to insert a cast to coerce Void->Bool to Void->Dynamic for instance. + *) + (match ft, e.etype with + | TFun (args,ret), TFun (args2,_) -> + TFun (List.map2 (fun ((_,_,t) as a) ((_,_,t2) as a2) -> match t, t2 with TInst ({cl_kind=KTypeParameter _},_), TFun _ -> a2 | _ -> a) args args2, ret) + | _ -> ft) + | TLocal v -> v.v_type + | TParenthesis e -> loop e + | _ -> e.etype + in + to_type ctx (loop e) + +and class_type ?(tref=None) ctx c pl statics = + let c = if c.cl_extern then resolve_class ctx c pl statics else c in + let key_path = (if statics then fst c.cl_path, "$" ^ snd c.cl_path else c.cl_path) in + try + PMap.find key_path ctx.cached_types + with Not_found when c.cl_interface && not statics -> + let vp = { + vfields = [||]; + vindex = PMap.empty; + } in + let t = HVirtual vp in + ctx.cached_types <- PMap.add c.cl_path t ctx.cached_types; + let rec loop c = + let fields = List.fold_left (fun acc (i,_) -> loop i @ acc) [] c.cl_implements in + PMap.fold (fun cf acc -> (cf.cf_name,alloc_string ctx cf.cf_name,to_type ctx cf.cf_type) :: acc) c.cl_fields fields + in + let fields = loop c in + vp.vfields <- Array.of_list fields; + Array.iteri (fun i (n,_,_) -> vp.vindex <- PMap.add n i vp.vindex) vp.vfields; + t + | Not_found -> + let pname = s_type_path key_path in + let p = { + pname = pname; + pid = alloc_string ctx pname; + psuper = None; + pclassglobal = None; + pproto = [||]; + pfields = [||]; + pindex = PMap.empty; + pvirtuals = [||]; + pfunctions = PMap.empty; + pnfields = -1; + pinterfaces = PMap.empty; + pbindings = []; + } in + let t = HObj p in + (match tref with + | None -> () + | Some r -> r := Some t); + ctx.cached_types <- PMap.add key_path t ctx.cached_types; + if c.cl_path = ([],"Array") then assert false; + if c == ctx.base_class then begin + if statics then assert false; + p.pnfields <- 1; + end; + let tsup = (match c.cl_super with + | Some (csup,pl) when not statics -> Some (class_type ctx csup [] statics) + | _ -> if statics then Some (class_type ctx ctx.base_class [] false) else None + ) in + let start_field, virtuals = (match tsup with + | None -> 0, [||] + | Some (HObj psup) -> + if psup.pnfields < 0 then assert false; + p.psuper <- Some psup; + p.pfunctions <- psup.pfunctions; + p.pinterfaces <- psup.pinterfaces; + psup.pnfields, psup.pvirtuals + | _ -> assert false + ) in + let fa = DynArray.create() and pa = DynArray.create() and virtuals = DynArray.of_array virtuals in + let todo = ref [] in + List.iter (fun f -> + if is_extern_field f || (statics && f.cf_name = "__meta__") then () else + let fid = (match f.cf_kind with + | Method m when m <> MethDynamic && not statics -> + let g = alloc_fid ctx c f in + p.pfunctions <- PMap.add f.cf_name g p.pfunctions; + let virt = if List.exists (fun ff -> ff.cf_name = f.cf_name) c.cl_overrides then + let vid = (try -(fst (get_index f.cf_name p))-1 with Not_found -> assert false) in + DynArray.set virtuals vid g; + Some vid + else if is_overriden ctx c f then begin + let vid = DynArray.length virtuals in + DynArray.add virtuals g; + p.pindex <- PMap.add f.cf_name (-vid-1,HVoid) p.pindex; + Some vid + end else + None + in + DynArray.add pa { fname = f.cf_name; fid = alloc_string ctx f.cf_name; fmethod = g; fvirtual = virt; }; + None + | Method MethDynamic when List.exists (fun ff -> ff.cf_name = f.cf_name) c.cl_overrides -> + Some (try fst (get_index f.cf_name p) with Not_found -> assert false) + | _ -> + let fid = DynArray.length fa in + p.pindex <- PMap.add f.cf_name (fid + start_field, t) p.pindex; + DynArray.add fa (f.cf_name, alloc_string ctx f.cf_name, HVoid); + todo := (fun() -> + let t = to_type ctx f.cf_type in + p.pindex <- PMap.add f.cf_name (fid + start_field, t) p.pindex; + Array.set p.pfields fid (f.cf_name, alloc_string ctx f.cf_name, t) + ) :: !todo; + Some (fid + start_field) + ) in + match f.cf_kind, fid with + | Method _, Some fid -> p.pbindings <- (fid, alloc_fun_path ctx c.cl_path f.cf_name) :: p.pbindings + | _ -> () + ) (if statics then c.cl_ordered_statics else c.cl_ordered_fields); + if not statics then begin + (* add interfaces *) + List.iter (fun (i,pl) -> + let fid = DynArray.length fa in + let t = to_type ctx (TInst (i,pl)) in + p.pinterfaces <- PMap.add t (fid + start_field) p.pinterfaces; + DynArray.add fa ("", 0, t); + ) c.cl_implements; + (* check toString *) + (try + let cf = PMap.find "toString" c.cl_fields in + if List.memq cf c.cl_overrides || PMap.mem "__string" c.cl_fields || not (is_to_string cf.cf_type) then raise Not_found; + DynArray.add pa { fname = "__string"; fid = alloc_string ctx "__string"; fmethod = alloc_fun_path ctx c.cl_path "__string"; fvirtual = None; } + with Not_found -> + ()); + end else begin + (match c.cl_constructor with + | Some f when not (is_extern_field f) -> + p.pbindings <- ((try fst (get_index "__constructor__" p) with Not_found -> assert false),alloc_fid ctx c f) :: p.pbindings + | _ -> ()); + end; + p.pnfields <- DynArray.length fa + start_field; + p.pfields <- DynArray.to_array fa; + p.pproto <- DynArray.to_array pa; + p.pvirtuals <- DynArray.to_array virtuals; + List.iter (fun f -> f()) !todo; + if not statics && c != ctx.core_type && c != ctx.core_enum then p.pclassglobal <- Some (fst (class_global ctx (if statics then ctx.base_class else c))); + t + +and enum_type ?(tref=None) ctx e = + try + PMap.find e.e_path ctx.cached_types + with Not_found -> + let ename = s_type_path e.e_path in + let et = { + eglobal = None; + ename = ename; + eid = alloc_string ctx ename; + efields = [||]; + } in + let t = HEnum et in + (match tref with + | None -> () + | Some r -> r := Some t); + ctx.cached_types <- PMap.add e.e_path t ctx.cached_types; + et.efields <- Array.of_list (List.map (fun f -> + let f = PMap.find f e.e_constrs in + let args = (match f.ef_type with + | TFun (args,_) -> Array.of_list (List.map (fun (_,_,t) -> to_type ctx t) args) + | _ -> [||] + ) in + (f.ef_name, alloc_string ctx f.ef_name, args) + ) e.e_names); + let ct = enum_class ctx e in + et.eglobal <- Some (alloc_global ctx (match ct with HObj o -> o.pname | _ -> assert false) ct); + t + +and enum_class ctx e = + let cpath = (fst e.e_path,"$" ^ snd e.e_path) in + try + PMap.find cpath ctx.cached_types + with Not_found -> + let pname = s_type_path cpath in + let p = { + pname = pname; + pid = alloc_string ctx pname; + psuper = None; + pclassglobal = None; + pproto = [||]; + pfields = [||]; + pindex = PMap.empty; + pvirtuals = [||]; + pfunctions = PMap.empty; + pnfields = -1; + pinterfaces = PMap.empty; + pbindings = []; + } in + let t = HObj p in + ctx.cached_types <- PMap.add cpath t ctx.cached_types; + p.psuper <- Some (match class_type ctx ctx.base_enum [] false with HObj o -> o | _ -> assert false); + t + +and alloc_fun_path ctx path name = + lookup ctx.cfids (name, path) (fun() -> ()) + +and alloc_fid ctx c f = + match f.cf_kind with + | Var _ -> assert false + | _ -> alloc_fun_path ctx c.cl_path f.cf_name + +and alloc_eid ctx e f = + alloc_fun_path ctx e.e_path f.ef_name + +and alloc_function_name ctx f = + alloc_fun_path ctx ([],"") f + +and alloc_global ctx name t = + lookup ctx.cglobals name (fun() -> t) + +and class_global ?(resolve=true) ctx c = + let static = c != ctx.base_class in + let c = if resolve && is_array_type (HObj { null_proto with pname = s_type_path c.cl_path }) then ctx.array_impl.abase else c in + let c = resolve_class ctx c (List.map snd c.cl_params) static in + let t = class_type ctx c [] static in + alloc_global ctx ("$" ^ s_type_path c.cl_path) t, t + +let resolve_class_global ctx cpath = + lookup ctx.cglobals ("$" ^ cpath) (fun() -> assert false) + +let resolve_type ctx path = + PMap.find path ctx.cached_types + +let alloc_std ctx name args ret = + let lib = "std" in + (* different from :hlNative to prevent mismatch *) + let nid = lookup ctx.cnatives ("$" ^ name ^ "@" ^ lib) (fun() -> + let fid = alloc_fun_path ctx ([],"std") name in + Hashtbl.add ctx.defined_funs fid (); + (alloc_string ctx lib, alloc_string ctx name,HFun (args,ret),fid) + ) in + let _,_,_,fid = DynArray.get ctx.cnatives.arr nid in + fid + +let alloc_fresh ctx t = + let rid = DynArray.length ctx.m.mregs.arr in + DynArray.add ctx.m.mregs.arr t; + rid + +let alloc_tmp ctx t = + if not ctx.optimize then alloc_fresh ctx t else + let a = try PMap.find t ctx.m.mallocs with Not_found -> + let a = { + a_all = []; + a_hold = []; + } in + ctx.m.mallocs <- PMap.add t a ctx.m.mallocs; + a + in + match a.a_all with + | [] -> + let r = alloc_fresh ctx t in + a.a_all <- [r]; + r + | r :: _ -> + r + +let current_pos ctx = + DynArray.length ctx.m.mops + +let rtype ctx r = + DynArray.get ctx.m.mregs.arr r + +let hold ctx r = + if not ctx.optimize || Hashtbl.mem ctx.m.mvars r then () else + let t = rtype ctx r in + let a = PMap.find t ctx.m.mallocs in + let rec loop l = + match l with + | [] -> if List.mem r a.a_hold then [] else assert false + | n :: l when n = r -> l + | n :: l -> n :: loop l + in + a.a_all <- loop a.a_all; + a.a_hold <- r :: a.a_hold + +let free ctx r = + if not ctx.optimize || Hashtbl.mem ctx.m.mvars r then () else + let t = rtype ctx r in + let a = PMap.find t ctx.m.mallocs in + let last = ref true in + let rec loop l = + match l with + | [] -> assert false + | n :: l when n = r -> + if List.mem r l then last := false; + l + | n :: l -> n :: loop l + in + a.a_hold <- loop a.a_hold; + (* insert sorted *) + let rec loop l = + match l with + | [] -> [r] + | n :: _ when n > r -> r :: l + | n :: l -> n :: loop l + in + if !last then a.a_all <- loop a.a_all + +let decl_var ctx v = + ctx.m.mdeclared <- v.v_id :: ctx.m.mdeclared + +let alloc_var ctx v new_var = + if new_var then decl_var ctx v; + try + Hashtbl.find ctx.m.mvars v.v_id + with Not_found -> + let r = alloc_tmp ctx (to_type ctx v.v_type) in + hold ctx r; + Hashtbl.add ctx.m.mvars v.v_id r; + r + +let op ctx o = + match o with + | OMov (a,b) when a = b -> () + | _ -> + DynArray.add ctx.m.mdebug ctx.m.mcurpos; + DynArray.add ctx.m.mops o + +let jump ctx f = + let pos = current_pos ctx in + op ctx (OJAlways (-1)); (* loop *) + (fun() -> DynArray.set ctx.m.mops pos (f (current_pos ctx - pos - 1))) + +let jump_back ctx = + let pos = current_pos ctx in + op ctx (OLabel 0); + (fun() -> op ctx (OJAlways (pos - current_pos ctx - 1))) + +let reg_int ctx v = + let r = alloc_tmp ctx HI32 in + op ctx (OInt (r,alloc_i32 ctx (Int32.of_int v))); + r + +let shl ctx idx v = + if v = 0 then + idx + else begin + hold ctx idx; + let rv = reg_int ctx v in + let idx2 = alloc_tmp ctx HI32 in + op ctx (OShl (idx2, idx, rv)); + free ctx idx; + idx2; + end + +let set_default ctx r = + match rtype ctx r with + | HUI8 | HUI16 | HI32 -> + op ctx (OInt (r,alloc_i32 ctx 0l)) + | HF32 | HF64 -> + op ctx (OFloat (r,alloc_float ctx 0.)) + | HBool -> + op ctx (OBool (r, false)) + | HType -> + op ctx (OType (r, HVoid)) + | _ -> + op ctx (ONull r) + +let read_mem ctx rdst bytes index t = + match t with + | HUI8 -> + op ctx (OGetUI8 (rdst,bytes,index)) + | HUI16 -> + op ctx (OGetUI16 (rdst,bytes,index)) + | HI32 -> + op ctx (OGetI32 (rdst,bytes,index)) + | HF32 -> + op ctx (OGetF32 (rdst,bytes,index)) + | HF64 -> + op ctx (OGetF64 (rdst,bytes,index)) + | _ -> + assert false + +let write_mem ctx bytes index t r = + match t with + | HUI8 -> + op ctx (OSetUI8 (bytes,index,r)) + | HUI16 -> + op ctx (OSetUI16 (bytes,index,r)) + | HI32 -> + op ctx (OSetI32 (bytes,index,r)) + | HF32 -> + op ctx (OSetF32 (bytes,index,r)) + | HF64 -> + op ctx (OSetF64 (bytes,index,r)) + | _ -> + assert false + +let common_type ctx e1 e2 for_eq p = + let t1 = to_type ctx e1.etype in + let t2 = to_type ctx e2.etype in + let rec loop t1 t2 = + if t1 == t2 then t1 else + match t1, t2 with + | HUI8, (HUI16 | HI32 | HF32 | HF64) -> t2 + | HUI16, (HI32 | HF32 | HF64) -> t2 + | HI32, HF32 -> t2 (* possible loss of precision *) + | (HI32 | HF32), HF64 -> t2 + | (HUI8|HUI16|HI32|HF32|HF64), (HUI8|HUI16|HI32|HF32|HF64) -> t1 + | (HUI8|HUI16|HI32|HF32|HF64), (HNull t2) -> if for_eq then HNull (loop t1 t2) else loop t1 t2 + | (HNull t1), (HUI8|HUI16|HI32|HF32|HF64) -> if for_eq then HNull (loop t1 t2) else loop t1 t2 + | (HNull t1), (HNull t2) -> if for_eq then HNull (loop t1 t2) else loop t1 t2 + | HDyn, (HUI8|HUI16|HI32|HF32|HF64) -> HF64 + | (HUI8|HUI16|HI32|HF32|HF64), HDyn -> HF64 + | HDyn, _ -> HDyn + | _, HDyn -> HDyn + | _ when for_eq && safe_cast t1 t2 -> t2 + | _ when for_eq && safe_cast t2 t1 -> t1 + | HBool, HNull HBool when for_eq -> t2 + | HNull HBool, HBool when for_eq -> t1 + | HObj _, HVirtual _ | HVirtual _, HObj _ -> HDyn + | _ -> + abort ("Don't know how to compare " ^ tstr t1 ^ " and " ^ tstr t2) p + in + loop t1 t2 + +let captured_index ctx v = + if not v.v_capture then None else try Some (PMap.find v.v_id ctx.m.mcaptured.c_map) with Not_found -> None + +let real_name v = + let rec loop = function + | [] -> v.v_name + | (Meta.RealPath,[EConst (String name),_],_) :: _ -> name + | _ :: l -> loop l + in + loop v.v_meta + +let add_assign ctx v r = + let name = real_name v in + ctx.m.massign <- (lookup ctx.cdebug_locals name (fun() -> name), DynArray.length ctx.m.mops, r) :: ctx.m.massign + +let add_capture ctx r = + Array.iter (fun v -> + let name = real_name v in + ctx.m.massign <- (lookup ctx.cdebug_locals name (fun() -> name), -1, r) :: ctx.m.massign + ) ctx.m.mcaptured.c_vars + +let before_return ctx = + let rec loop i = + if i > 0 then begin + op ctx (OEndTrap false); + loop (i - 1) + end + in + loop ctx.m.mtrys + +let before_break_continue ctx = + let rec loop i = + if i > 0 then begin + op ctx (OEndTrap false); + loop (i - 1) + end + in + loop (ctx.m.mtrys - ctx.m.mloop_trys) + +let type_value ctx t p = + match t with + | TClassDecl c -> + let g, t = class_global ctx c in + let r = alloc_tmp ctx t in + op ctx (OGetGlobal (r, g)); + r + | TAbstractDecl a -> + let r = alloc_tmp ctx (class_type ctx ctx.base_type [] false) in + (match a.a_path with + | [], "Int" -> op ctx (OGetGlobal (r, alloc_global ctx "$Int" (rtype ctx r))) + | [], "Float" -> op ctx (OGetGlobal (r, alloc_global ctx "$Float" (rtype ctx r))) + | [], "Bool" -> op ctx (OGetGlobal (r, alloc_global ctx "$Bool" (rtype ctx r))) + | [], "Class" -> op ctx (OGetGlobal (r, fst (class_global ctx ctx.base_class))) + | [], "Enum" -> op ctx (OGetGlobal (r, fst (class_global ctx ctx.base_enum))) + | [], "Dynamic" -> op ctx (OGetGlobal (r, alloc_global ctx "$Dynamic" (rtype ctx r))) + | _ -> abort ("Unsupported type value " ^ s_type_path (t_path t)) p); + r + | TEnumDecl e -> + let r = alloc_tmp ctx (enum_class ctx e) in + let rt = rtype ctx r in + op ctx (OGetGlobal (r, alloc_global ctx (match rt with HObj o -> o.pname | _ -> assert false) rt)); + r + | TTypeDecl _ -> + assert false + +let rec eval_to ctx e (t:ttype) = + let r = eval_expr ctx e in + cast_to ctx r t e.epos + +and cast_to ?(force=false) ctx (r:reg) (t:ttype) p = + let rt = rtype ctx r in + if safe_cast rt t then r else + match rt, t with + | _, HVoid -> + alloc_tmp ctx HVoid + | HVirtual _, HVirtual _ -> + let tmp = alloc_tmp ctx HDyn in + op ctx (OMov (tmp,r)); + cast_to ctx tmp t p + | (HUI8 | HUI16 | HI32 | HF32 | HF64), (HF32 | HF64) -> + let tmp = alloc_tmp ctx t in + op ctx (OToSFloat (tmp, r)); + tmp + | (HUI8 | HUI16 | HI32 | HF32 | HF64), (HUI8 | HUI16 | HI32) -> + let tmp = alloc_tmp ctx t in + op ctx (OToInt (tmp, r)); + tmp + | (HUI8 | HUI16 | HI32), HObj { pname = "String" } -> + let len = alloc_tmp ctx HI32 in + hold ctx len; + let lref = alloc_tmp ctx (HRef HI32) in + let bytes = alloc_tmp ctx HBytes in + op ctx (ORef (lref,len)); + op ctx (OCall2 (bytes,alloc_std ctx "itos" [HI32;HRef HI32] HBytes,cast_to ctx r HI32 p,lref)); + let out = alloc_tmp ctx t in + op ctx (OCall2 (out,alloc_fun_path ctx ([],"String") "__alloc__",bytes,len)); + free ctx len; + out + | (HF32 | HF64), HObj { pname = "String" } -> + let len = alloc_tmp ctx HI32 in + let lref = alloc_tmp ctx (HRef HI32) in + let bytes = alloc_tmp ctx HBytes in + op ctx (ORef (lref,len)); + op ctx (OCall2 (bytes,alloc_std ctx "ftos" [HF64;HRef HI32] HBytes,cast_to ctx r HF64 p,lref)); + let out = alloc_tmp ctx t in + op ctx (OCall2 (out,alloc_fun_path ctx ([],"String") "__alloc__",bytes,len)); + out + | _, HObj { pname = "String" } -> + let r = cast_to ctx r HDyn p in + let out = alloc_tmp ctx t in + op ctx (OJNotNull (r,2)); + op ctx (ONull out); + op ctx (OJAlways 1); + op ctx (OCall1 (out,alloc_fun_path ctx ([],"Std") "string",r)); + out + | HObj o, HVirtual _ -> + let out = alloc_tmp ctx t in + (try + let fid = PMap.find t o.pinterfaces in + (* memoisation *) + let need_null_check r = + not (r = 0 && ctx.m.mhasthis) + in + let jend = if need_null_check r then + let jnull = jump ctx (fun d -> OJNotNull (r,d)) in + op ctx (ONull out); + let jend = jump ctx (fun d -> OJAlways d) in + jnull(); + jend + else + (fun() -> ()) + in + op ctx (OField (out, r, fid)); + let j = jump ctx (fun d -> OJNotNull (out,d)) in + op ctx (OToVirtual (out,r)); + op ctx (OSetField (r, fid, out)); + jend(); + j(); + with Not_found -> + (* not an interface *) + op ctx (OToVirtual (out,r))); + out + | (HDynObj | HDyn) , HVirtual _ -> + let out = alloc_tmp ctx t in + op ctx (OToVirtual (out,r)); + out + | HDyn, _ -> + let out = alloc_tmp ctx t in + op ctx (OSafeCast (out, r)); + out + | HNull rt, _ when t = rt -> + let out = alloc_tmp ctx t in + op ctx (OSafeCast (out, r)); + out + | HVoid, HDyn -> + let tmp = alloc_tmp ctx HDyn in + op ctx (ONull tmp); + tmp + | _ , HDyn -> + let tmp = alloc_tmp ctx HDyn in + op ctx (OToDyn (tmp, r)); + tmp + | _, HNull t when rt == t -> + let tmp = alloc_tmp ctx (HNull t) in + op ctx (OToDyn (tmp, r)); + tmp + | HNull t1, HNull t2 -> + let j = jump ctx (fun n -> OJNull (r,n)) in + let rtmp = alloc_tmp ctx t1 in + op ctx (OSafeCast (rtmp,r)); + let out = cast_to ctx rtmp t p in + op ctx (OJAlways 1); + j(); + op ctx (ONull out); + out + | (HUI8 | HUI16 | HI32 | HF32 | HF64), HNull ((HF32 | HF64) as t) -> + let tmp = alloc_tmp ctx t in + op ctx (OToSFloat (tmp, r)); + let r = alloc_tmp ctx (HNull t) in + op ctx (OToDyn (r,tmp)); + r + | (HUI8 | HUI16 | HI32 | HF32 | HF64), HNull ((HUI8 | HUI16 | HI32) as t) -> + let tmp = alloc_tmp ctx t in + op ctx (OToInt (tmp, r)); + let r = alloc_tmp ctx (HNull t) in + op ctx (OToDyn (r,tmp)); + r + | HNull ((HUI8 | HUI16 | HI32) as it), (HF32 | HF64) -> + let i = alloc_tmp ctx it in + op ctx (OSafeCast (i,r)); + let tmp = alloc_tmp ctx t in + op ctx (OToSFloat (tmp, i)); + tmp + | HNull ((HF32 | HF64) as it), (HUI8 | HUI16 | HI32) -> + let i = alloc_tmp ctx it in + op ctx (OSafeCast (i,r)); + let tmp = alloc_tmp ctx t in + op ctx (OToInt (tmp, i)); + tmp + | HFun (args1,ret1), HFun (args2, ret2) when List.length args1 = List.length args2 -> + let fid = gen_method_wrapper ctx rt t p in + let fr = alloc_tmp ctx t in + op ctx (OJNotNull (r,2)); + op ctx (ONull fr); + op ctx (OJAlways 1); + op ctx (OInstanceClosure (fr,fid,r)); + fr + | HObj _, HObj _ when is_array_type rt && is_array_type t -> + let out = alloc_tmp ctx t in + op ctx (OSafeCast (out, r)); + out + | _, HRef t2 -> + let r = cast_to ctx r t2 p in + let r2 = alloc_tmp ctx t2 in + op ctx (OMov (r2, r)); + hold ctx r2; (* retain *) + let out = alloc_tmp ctx t in + op ctx (ORef (out,r2)); + out + | _ -> + if force then + let out = alloc_tmp ctx t in + op ctx (OSafeCast (out, r)); + out + else + abort ("Don't know how to cast " ^ tstr rt ^ " to " ^ tstr t) p + +and unsafe_cast_to ctx (r:reg) (t:ttype) p = + let rt = rtype ctx r in + if safe_cast rt t then + r + else + match rt with + | HFun _ -> + cast_to ctx r t p + | HDyn when is_array_type t -> + cast_to ctx r t p + | (HDyn | HObj _) when (match t with HVirtual _ -> true | _ -> false) -> + cast_to ctx r t p + | HObj _ when is_array_type rt && is_array_type t -> + cast_to ctx r t p + | HVirtual _ when (match t with HObj _ | HVirtual _ -> true | _ -> false) -> + cast_to ~force:true ctx r t p + | _ -> + if is_dynamic (rtype ctx r) && is_dynamic t then + let r2 = alloc_tmp ctx t in + op ctx (OUnsafeCast (r2,r)); + r2 + else + cast_to ~force:true ctx r t p + +and object_access ctx eobj t f = + match t with + | HObj p -> + (try + let fid = fst (get_index f.cf_name p) in + if f.cf_kind = Method MethNormal then + AInstanceProto (eobj, -fid-1) + else + AInstanceField (eobj, fid) + with Not_found -> + ADynamic (eobj, alloc_string ctx f.cf_name)) + | HVirtual v -> + (try + let fid = PMap.find f.cf_name v.vindex in + if f.cf_kind = Method MethNormal then + AVirtualMethod (eobj, fid) + else + AInstanceField (eobj, fid) + with Not_found -> + ADynamic (eobj, alloc_string ctx f.cf_name)) + | HDyn -> + ADynamic (eobj, alloc_string ctx f.cf_name) + | _ -> + abort ("Unsupported field access " ^ tstr t) eobj.epos + +and direct_method_call ctx c f ethis = + if (match f.cf_kind with Method m -> m = MethDynamic | Var _ -> true) then + false + else if c.cl_interface then + false + else if (match c.cl_kind with KTypeParameter _ -> true | _ -> false) then + false + else if is_overriden ctx c f && ethis.eexpr <> TConst(TSuper) then + false + else + true + +and get_access ctx e = + match e.eexpr with + | TField (ethis, a) -> + (match a, follow ethis.etype with + | FStatic (c,({ cf_kind = Var _ | Method MethDynamic } as f)), _ -> + let g, t = class_global ctx c in + AStaticVar (g, t, (match t with HObj o -> (try fst (get_index f.cf_name o) with Not_found -> assert false) | _ -> assert false)) + | FStatic (c,({ cf_kind = Method _ } as f)), _ -> + AStaticFun (alloc_fid ctx c f) + | FClosure (Some (cdef,pl), f), TInst (c,_) + | FInstance (cdef,pl,f), TInst (c,_) when direct_method_call ctx c f ethis -> + (* cdef is the original definition, we want the last redefinition *) + let rec loop c = + if PMap.mem f.cf_name c.cl_fields then c else (match c.cl_super with None -> cdef | Some (c,_) -> loop c) + in + let last_def = loop c in + AInstanceFun (ethis, alloc_fid ctx (resolve_class ctx last_def pl false) f) + | (FInstance (cdef,pl,f) | FClosure (Some (cdef,pl), f)), _ -> + let rec loop t = + match follow t with + | TInst (c,pl) -> c, pl + | TAbstract (a,pl) -> loop (Abstract.get_underlying_type a pl) + | _ -> abort (s_type (print_context()) ethis.etype ^ " hl type should be interface") ethis.epos + in + let cdef, pl = if cdef.cl_interface then loop ethis.etype else cdef,pl in + object_access ctx ethis (class_type ctx cdef pl false) f + | (FAnon f | FClosure(None,f)), _ -> + object_access ctx ethis (to_type ctx ethis.etype) f + | FDynamic name, _ -> + ADynamic (ethis, alloc_string ctx name) + | FEnum (e,ef), _ -> + (match follow ef.ef_type with + | TFun _ -> AEnum (e,ef.ef_index) + | t -> AGlobal (alloc_global ctx (efield_name e ef) (to_type ctx t)))) + | TLocal v -> + (match captured_index ctx v with + | None -> ALocal (v, alloc_var ctx v false) + | Some idx -> ACaptured idx) + | TParenthesis e -> + get_access ctx e + | TArray (a,i) -> + let rec loop t = + match follow t with + | TInst({ cl_path = [],"Array" },[t]) -> + let a = eval_null_check ctx a in + hold ctx a; + let i = eval_to ctx i HI32 in + free ctx a; + let t = to_type ctx t in + AArray (a,(t,t),i) + | TAbstract (a,pl) -> + loop (Abstract.get_underlying_type a pl) + | _ -> + let a = eval_to ctx a (class_type ctx ctx.array_impl.adyn [] false) in + op ctx (ONullCheck a); + hold ctx a; + let i = eval_to ctx i HI32 in + free ctx a; + AArray (a,(HDyn,to_type ctx e.etype),i) + in + loop a.etype + | _ -> + ANone + +and array_read ctx ra (at,vt) ridx p = + match at with + | HUI8 | HUI16 | HI32 | HF32 | HF64 -> + (* check bounds *) + hold ctx ridx; + let length = alloc_tmp ctx HI32 in + free ctx ridx; + op ctx (OField (length, ra, 0)); + let j = jump ctx (fun i -> OJULt (ridx,length,i)) in + let r = alloc_tmp ctx (match at with HUI8 | HUI16 -> HI32 | _ -> at) in + (match at with + | HUI8 | HUI16 | HI32 -> + op ctx (OInt (r,alloc_i32 ctx 0l)); + | HF32 | HF64 -> + op ctx (OFloat (r,alloc_float ctx 0.)); + | _ -> + assert false); + let jend = jump ctx (fun i -> OJAlways i) in + j(); + let hbytes = alloc_tmp ctx HBytes in + op ctx (OField (hbytes, ra, 1)); + read_mem ctx r hbytes (shl ctx ridx (type_size_bits at)) at; + jend(); + cast_to ctx r vt p + | HDyn -> + (* call getDyn *) + let r = alloc_tmp ctx HDyn in + op ctx (OCallMethod (r,0,[ra;ridx])); + unsafe_cast_to ctx r vt p + | _ -> + (* check bounds *) + hold ctx ridx; + let length = alloc_tmp ctx HI32 in + free ctx ridx; + op ctx (OField (length,ra,0)); + let j = jump ctx (fun i -> OJULt (ridx,length,i)) in + let r = alloc_tmp ctx vt in + set_default ctx r; + let jend = jump ctx (fun i -> OJAlways i) in + j(); + let tmp = alloc_tmp ctx HDyn in + let harr = alloc_tmp ctx HArray in + op ctx (OField (harr,ra,1)); + op ctx (OGetArray (tmp,harr,ridx)); + op ctx (OMov (r,unsafe_cast_to ctx tmp vt p)); + jend(); + r + +and jump_expr ctx e jcond = + match e.eexpr with + | TParenthesis e -> + jump_expr ctx e jcond + | TUnop (Not,_,e) -> + jump_expr ctx e (not jcond) + | TBinop (OpEq,{ eexpr = TConst(TNull) },e) | TBinop (OpEq,e,{ eexpr = TConst(TNull) }) -> + let r = eval_expr ctx e in + jump ctx (fun i -> if jcond then OJNull (r,i) else OJNotNull (r,i)) + | TBinop (OpNotEq,{ eexpr = TConst(TNull) },e) | TBinop (OpNotEq,e,{ eexpr = TConst(TNull) }) -> + let r = eval_expr ctx e in + jump ctx (fun i -> if jcond then OJNotNull (r,i) else OJNull (r,i)) + | TBinop (OpEq | OpNotEq | OpGt | OpGte | OpLt | OpLte as jop, e1, e2) -> + let t = common_type ctx e1 e2 (match jop with OpEq | OpNotEq -> true | _ -> false) e.epos in + let r1 = eval_to ctx e1 t in + hold ctx r1; + let r2 = eval_to ctx e2 t in + free ctx r1; + let unsigned = unsigned_op e1 e2 in + jump ctx (fun i -> + let lt a b = if unsigned then OJULt (a,b,i) else OJSLt (a,b,i) in + let gte a b = if unsigned then OJUGte (a,b,i) else OJSGte (a,b,i) in + match jop with + | OpEq -> if jcond then OJEq (r1,r2,i) else OJNotEq (r1,r2,i) + | OpNotEq -> if jcond then OJNotEq (r1,r2,i) else OJEq (r1,r2,i) + | OpGt -> if jcond then lt r2 r1 else gte r2 r1 + | OpGte -> if jcond then gte r1 r2 else lt r1 r2 + | OpLt -> if jcond then lt r1 r2 else gte r1 r2 + | OpLte -> if jcond then gte r2 r1 else lt r2 r1 + | _ -> assert false + ) + | TBinop (OpBoolAnd, e1, e2) -> + let j = jump_expr ctx e1 false in + let j2 = jump_expr ctx e2 jcond in + if jcond then j(); + (fun() -> if not jcond then j(); j2()); + | TBinop (OpBoolOr, e1, e2) -> + let j = jump_expr ctx e1 true in + let j2 = jump_expr ctx e2 jcond in + if not jcond then j(); + (fun() -> if jcond then j(); j2()); + | _ -> + let r = eval_to ctx e HBool in + jump ctx (fun i -> if jcond then OJTrue (r,i) else OJFalse (r,i)) + +and eval_args ctx el t p = + let rl = List.map2 (fun e t -> + let r = (match e.eexpr, t with + | TConst TNull, HRef _ -> + let r = alloc_tmp ctx t in + op ctx (ONull r); + r + | _ -> + eval_to ctx e t + ) in + hold ctx r; + r + ) el (match t with HFun (args,_) -> args | HDyn -> List.map (fun _ -> HDyn) el | _ -> assert false) in + List.iter (free ctx) rl; + set_curpos ctx p; + rl + +and eval_null_check ctx e = + let r = eval_expr ctx e in + (match e.eexpr with + | TConst TThis | TConst TSuper -> () + | _ -> op ctx (ONullCheck r)); + r + +and make_string ctx s p = + let str, len = to_utf8 s p in + let r = alloc_tmp ctx HBytes in + let s = alloc_tmp ctx (to_type ctx ctx.com.basic.tstring) in + op ctx (ONew s); + op ctx (OString (r,alloc_string ctx str)); + op ctx (OSetField (s,0,r)); + op ctx (OSetField (s,1,reg_int ctx len)); + s + +and eval_var ctx v = + match captured_index ctx v with + | None -> alloc_var ctx v false + | Some idx -> + let r = alloc_tmp ctx (to_type ctx v.v_type) in + op ctx (OEnumField (r,ctx.m.mcaptreg,0,idx)); + r + +and eval_expr ctx e = + set_curpos ctx e.epos; + match e.eexpr with + | TConst c -> + (match c with + | TInt i -> + let r = alloc_tmp ctx HI32 in + op ctx (OInt (r,alloc_i32 ctx i)); + r + | TFloat f -> + let r = alloc_tmp ctx HF64 in + op ctx (OFloat (r,alloc_float ctx (float_of_string f))); + r + | TBool b -> + let r = alloc_tmp ctx HBool in + op ctx (OBool (r,b)); + r + | TString s -> + make_string ctx s e.epos + | TThis | TSuper -> + 0 (* first reg *) + | TNull -> + let r = alloc_tmp ctx (to_type ctx e.etype) in + op ctx (ONull r); + r) + | TVar (v,e) -> + (match e with + | None -> + if captured_index ctx v = None then decl_var ctx v + | Some e -> + let ri = eval_to ctx e (to_type ctx v.v_type) in + match captured_index ctx v with + | None -> + let r = alloc_var ctx v true in + op ctx (OMov (r,ri)); + add_assign ctx v r; + | Some idx -> + op ctx (OSetEnumField (ctx.m.mcaptreg, idx, ri)); + ); + alloc_tmp ctx HVoid + | TLocal v -> + cast_to ctx (match captured_index ctx v with + | None -> + (* we need to make a copy for cases such as (a - a++) *) + let r = alloc_var ctx v false in + let r2 = alloc_tmp ctx (rtype ctx r) in + op ctx (OMov (r2, r)); + r2 + | Some idx -> + let r = alloc_tmp ctx (to_type ctx v.v_type) in + op ctx (OEnumField (r, ctx.m.mcaptreg, 0, idx)); + r) (to_type ctx e.etype) e.epos + | TReturn None -> + before_return ctx; + let r = alloc_tmp ctx HVoid in + op ctx (ORet r); + alloc_tmp ctx HDyn + | TReturn (Some e) -> + let r = eval_to ctx e ctx.m.mret in + before_return ctx; + op ctx (ORet r); + alloc_tmp ctx HDyn + | TParenthesis e -> + eval_expr ctx e + | TBlock el -> + let rec loop = function + | [e] -> eval_expr ctx e + | [] -> alloc_tmp ctx HVoid + | e :: l -> + ignore(eval_expr ctx e); + loop l + in + let old = ctx.m.mdeclared in + ctx.m.mdeclared <- []; + let r = loop el in + List.iter (fun vid -> + let r = try Hashtbl.find ctx.m.mvars vid with Not_found -> -1 in + if r >= 0 then begin + Hashtbl.remove ctx.m.mvars vid; + free ctx r; + end + ) ctx.m.mdeclared; + ctx.m.mdeclared <- old; + r + | TCall ({ eexpr = TConst TSuper } as s, el) -> + (match follow s.etype with + | TInst (csup,_) -> + (match csup.cl_constructor with + | None -> assert false + | Some f -> + let r = alloc_tmp ctx HVoid in + let el = eval_args ctx el (to_type ctx f.cf_type) e.epos in + op ctx (OCallN (r, alloc_fid ctx csup f, 0 :: el)); + r + ) + | _ -> assert false); + | TCall ({ eexpr = TLocal v }, el) when v.v_name.[0] = '$' -> + let invalid() = abort "Invalid native call" e.epos in + (match v.v_name, el with + | "$new", [{ eexpr = TTypeExpr (TClassDecl _) }] -> + (match follow e.etype with + | TInst (c,pl) -> + let r = alloc_tmp ctx (class_type ctx c pl false) in + op ctx (ONew r); + r + | _ -> + invalid()) + | "$int", [{ eexpr = TBinop (OpDiv, e1, e2) }] when is_int (to_type ctx e1.etype) && is_int (to_type ctx e2.etype) -> + let tmp = alloc_tmp ctx HI32 in + let r1 = eval_to ctx e1 HI32 in + hold ctx r1; + let r2 = eval_to ctx e2 HI32 in + free ctx r1; + op ctx (if unsigned_op e1 e2 then OUDiv (tmp,r1,r2) else OSDiv (tmp, r1, r2)); + tmp + | "$int", [e] -> + let tmp = alloc_tmp ctx HI32 in + op ctx (OToInt (tmp, eval_expr ctx e)); + tmp + | "$bsetui8", [b;pos;v] -> + let b = eval_to ctx b HBytes in + hold ctx b; + let pos = eval_to ctx pos HI32 in + hold ctx pos; + let r = eval_to ctx v HI32 in + free ctx pos; + free ctx b; + op ctx (OSetUI8 (b, pos, r)); + r + | "$bsetui16", [b;pos;v] -> + let b = eval_to ctx b HBytes in + hold ctx b; + let pos = eval_to ctx pos HI32 in + hold ctx pos; + let r = eval_to ctx v HI32 in + free ctx pos; + free ctx b; + op ctx (OSetUI16 (b, pos, r)); + r + | "$bseti32", [b;pos;v] -> + let b = eval_to ctx b HBytes in + hold ctx b; + let pos = eval_to ctx pos HI32 in + hold ctx pos; + let r = eval_to ctx v HI32 in + free ctx pos; + free ctx b; + op ctx (OSetI32 (b, pos, r)); + r + | "$bsetf32", [b;pos;v] -> + let b = eval_to ctx b HBytes in + hold ctx b; + let pos = eval_to ctx pos HI32 in + hold ctx pos; + let r = eval_to ctx v HF32 in + free ctx pos; + free ctx b; + op ctx (OSetF32 (b, pos, r)); + r + | "$bsetf64", [b;pos;v] -> + let b = eval_to ctx b HBytes in + hold ctx b; + let pos = eval_to ctx pos HI32 in + hold ctx pos; + let r = eval_to ctx v HF64 in + free ctx pos; + free ctx b; + op ctx (OSetF64 (b, pos, r)); + r + | "$bytes_sizebits", [eb] -> + (match follow eb.etype with + | TAbstract({a_path = ["hl"],"BytesAccess"},[t]) -> + reg_int ctx (match to_type ctx t with + | HUI8 -> 0 + | HUI16 -> 1 + | HI32 -> 2 + | HF32 -> 2 + | HF64 -> 3 + | t -> abort ("Unsupported basic type " ^ tstr t) e.epos) + | _ -> + abort "Invalid BytesAccess" eb.epos); + | "$bytes_nullvalue", [eb] -> + (match follow eb.etype with + | TAbstract({a_path = ["hl"],"BytesAccess"},[t]) -> + let t = to_type ctx t in + let r = alloc_tmp ctx t in + (match t with + | HUI8 | HUI16 | HI32 -> + op ctx (OInt (r,alloc_i32 ctx 0l)) + | HF32 | HF64 -> + op ctx (OFloat (r, alloc_float ctx 0.)) + | t -> + abort ("Unsupported basic type " ^ tstr t) e.epos); + r + | _ -> + abort "Invalid BytesAccess" eb.epos); + | "$bget", [eb;pos] -> + (match follow eb.etype with + | TAbstract({a_path = ["hl"],"BytesAccess"},[t]) -> + let b = eval_to ctx eb HBytes in + hold ctx b; + let pos = eval_to ctx pos HI32 in + free ctx b; + let t = to_type ctx t in + (match t with + | HUI8 -> + let r = alloc_tmp ctx HI32 in + op ctx (OGetUI8 (r, b, pos)); + r + | HUI16 -> + let r = alloc_tmp ctx HI32 in + op ctx (OGetUI16 (r, b, shl ctx pos 1)); + r + | HI32 -> + let r = alloc_tmp ctx HI32 in + op ctx (OGetI32 (r, b, shl ctx pos 2)); + r + | HF32 -> + let r = alloc_tmp ctx HF32 in + op ctx (OGetF32 (r, b, shl ctx pos 2)); + r + | HF64 -> + let r = alloc_tmp ctx HF64 in + op ctx (OGetF64 (r, b, shl ctx pos 3)); + r + | _ -> + abort ("Unsupported basic type " ^ tstr t) e.epos) + | _ -> + abort "Invalid BytesAccess" eb.epos); + | "$bset", [eb;pos;value] -> + (match follow eb.etype with + | TAbstract({a_path = ["hl"],"BytesAccess"},[t]) -> + let b = eval_to ctx eb HBytes in + hold ctx b; + let pos = eval_to ctx pos HI32 in + hold ctx pos; + let t = to_type ctx t in + let v = (match t with + | HUI8 -> + let v = eval_to ctx value HI32 in + op ctx (OSetUI8 (b, pos, v)); + v + | HUI16 -> + let v = eval_to ctx value HI32 in + hold ctx v; + op ctx (OSetUI16 (b, shl ctx pos 1, v)); + free ctx v; + v + | HI32 -> + let v = eval_to ctx value HI32 in + hold ctx v; + op ctx (OSetI32 (b, shl ctx pos 2, v)); + free ctx v; + v + | HF32 -> + let v = eval_to ctx value HF32 in + hold ctx v; + op ctx (OSetF32 (b, shl ctx pos 2, v)); + free ctx v; + v + | HF64 -> + let v = eval_to ctx value HF64 in + hold ctx v; + op ctx (OSetF64 (b, shl ctx pos 3, v)); + free ctx v; + v + | _ -> + abort ("Unsupported basic type " ^ tstr t) e.epos + ) in + free ctx b; + free ctx pos; + v + | _ -> + abort "Invalid BytesAccess" eb.epos); + | "$bgetui8", [b;pos] -> + let b = eval_to ctx b HBytes in + hold ctx b; + let pos = eval_to ctx pos HI32 in + free ctx b; + let r = alloc_tmp ctx HI32 in + op ctx (OGetUI8 (r, b, pos)); + r + | "$bgetui16", [b;pos] -> + let b = eval_to ctx b HBytes in + hold ctx b; + let pos = eval_to ctx pos HI32 in + free ctx b; + let r = alloc_tmp ctx HI32 in + op ctx (OGetUI16 (r, b, pos)); + r + | "$bgeti32", [b;pos] -> + let b = eval_to ctx b HBytes in + hold ctx b; + let pos = eval_to ctx pos HI32 in + free ctx b; + let r = alloc_tmp ctx HI32 in + op ctx (OGetI32 (r, b, pos)); + r + | "$bgetf32", [b;pos] -> + let b = eval_to ctx b HBytes in + hold ctx b; + let pos = eval_to ctx pos HI32 in + free ctx b; + let r = alloc_tmp ctx HF32 in + op ctx (OGetF32 (r, b, pos)); + r + | "$bgetf64", [b;pos] -> + let b = eval_to ctx b HBytes in + hold ctx b; + let pos = eval_to ctx pos HI32 in + free ctx b; + let r = alloc_tmp ctx HF64 in + op ctx (OGetF64 (r, b, pos)); + r + | "$asize", [e] -> + let r = alloc_tmp ctx HI32 in + op ctx (OArraySize (r, eval_to ctx e HArray)); + r + | "$aalloc", [esize] -> + let et = (match follow e.etype with TAbstract ({ a_path = ["hl"],"NativeArray" },[t]) -> to_type ctx t | _ -> invalid()) in + let size = eval_to ctx esize HI32 in + let a = alloc_tmp ctx HArray in + let rt = alloc_tmp ctx HType in + op ctx (OType (rt,et)); + op ctx (OCall2 (a,alloc_std ctx "alloc_array" [HType;HI32] HArray,rt,size)); + a + | "$aget", [a; pos] -> + (* + read/write on arrays are unsafe : the type of NativeArray needs to be correcly set. + *) + let at = (match follow a.etype with TAbstract ({ a_path = ["hl"],"NativeArray" },[t]) -> to_type ctx t | _ -> invalid()) in + let arr = eval_to ctx a HArray in + hold ctx arr; + let pos = eval_to ctx pos HI32 in + free ctx arr; + let r = alloc_tmp ctx at in + op ctx (OGetArray (r, arr, pos)); + cast_to ctx r (to_type ctx e.etype) e.epos + | "$aset", [a; pos; value] -> + let et = (match follow a.etype with TAbstract ({ a_path = ["hl"],"NativeArray" },[t]) -> to_type ctx t | _ -> invalid()) in + let arr = eval_to ctx a HArray in + let pos = eval_to ctx pos HI32 in + let r = eval_to ctx value et in + op ctx (OSetArray (arr, pos, r)); + r + | "$abytes", [a] -> + (match follow a.etype with + | TInst ({ cl_path = [], "Array" },[t]) when is_number (to_type ctx t) -> + let a = eval_expr ctx a in + let r = alloc_tmp ctx HBytes in + op ctx (ONullCheck a); + op ctx (OField (r,a,1)); + r + | t -> + abort ("Invalid array type " ^ s_type (print_context()) t) a.epos) + | "$ref", [v] -> + (match v.eexpr with + | TLocal v -> + let r = alloc_tmp ctx (to_type ctx e.etype) in + let rv = (match rtype ctx r with HRef t -> alloc_var ctx v false | _ -> invalid()) in + hold ctx rv; (* infinite hold *) + op ctx (ORef (r,rv)); + r + | _ -> + abort "Ref should be a local variable" v.epos) + | "$setref", [e1;e2] -> + let rec loop e = match e.eexpr with + | TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) -> loop e1 + | TLocal v -> v + | _ -> invalid() + in + let v = loop e1 in + let r = alloc_var ctx v false in + let rv = eval_to ctx e2 (match rtype ctx r with HRef t -> t | _ -> invalid()) in + op ctx (OSetref (r,rv)); + r + | "$unref", [e1] -> + let rec loop e = match e.eexpr with + | TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) -> loop e1 + | TLocal v -> v + | _ -> invalid() + in + let v = loop e1 in + let r = alloc_var ctx v false in + let out = alloc_tmp ctx (match rtype ctx r with HRef t -> t | _ -> invalid()) in + op ctx (OUnref (out,r)); + out + | "$ttype", [v] -> + let r = alloc_tmp ctx HType in + op ctx (OType (r,to_type ctx v.etype)); + r + | "$tdyntype", [v] -> + let r = alloc_tmp ctx HType in + op ctx (OGetType (r,eval_to ctx v HDyn)); + r + | "$tkind", [v] -> + let r = alloc_tmp ctx HI32 in + op ctx (OGetTID (r,eval_to ctx v HType)); + r + | "$resources", [] -> + let tdef = (try List.find (fun t -> (t_infos t).mt_path = (["haxe";"_Resource"],"ResourceContent")) ctx.com.types with Not_found -> assert false) in + let t = class_type ctx (match tdef with TClassDecl c -> c | _ -> assert false) [] false in + let arr = alloc_tmp ctx HArray in + let rt = alloc_tmp ctx HType in + op ctx (OType (rt,t)); + let res = Hashtbl.fold (fun k v acc -> (k,v) :: acc) ctx.com.resources [] in + let size = reg_int ctx (List.length res) in + op ctx (OCall2 (arr,alloc_std ctx "alloc_array" [HType;HI32] HArray,rt,size)); + let ro = alloc_tmp ctx t in + let rb = alloc_tmp ctx HBytes in + let ridx = reg_int ctx 0 in + hold ctx ridx; + let has_len = (match t with HObj p -> PMap.mem "dataLen" p.pindex | _ -> assert false) in + list_iteri (fun i (k,v) -> + op ctx (ONew ro); + op ctx (OString (rb,alloc_string ctx k)); + op ctx (OSetField (ro,0,rb)); + op ctx (OBytes (rb,alloc_string ctx (v ^ "\x00"))); (* add a \x00 to prevent clashing with existing string *) + op ctx (OSetField (ro,1,rb)); + if has_len then op ctx (OSetField (ro,2,reg_int ctx (String.length v))); + op ctx (OSetArray (arr,ridx,ro)); + op ctx (OIncr ridx); + ) res; + free ctx ridx; + arr + | "$rethrow", [v] -> + let r = alloc_tmp ctx HVoid in + op ctx (ORethrow (eval_to ctx v HDyn)); + r + | "$allTypes", [] -> + let r = alloc_tmp ctx (to_type ctx e.etype) in + op ctx (OGetGlobal (r, alloc_global ctx "__types__" (rtype ctx r))); + r + | "$allTypes", [v] -> + let v = eval_expr ctx v in + op ctx (OSetGlobal (alloc_global ctx "__types__" (rtype ctx v), v)); + v + | "$hash", [v] -> + (match v.eexpr with + | TConst (TString str) -> + let r = alloc_tmp ctx HI32 in + op ctx (OInt (r,alloc_i32 ctx (hl_hash str))); + r + | _ -> abort "Constant string required" v.epos) + | "$enumIndex", [v] -> + let r = alloc_tmp ctx HI32 in + let re = eval_expr ctx v in + op ctx (ONullCheck re); + op ctx (OEnumIndex (r,re)); + r + | "$__mk_pos__", [{ eexpr = TConst (TString file) };min;max] -> + (* macros only - generated by reification *) + let rt = HAbstract ("macro_pos",alloc_string ctx "macro_pos") in + let r = alloc_tmp ctx rt in + let rfile = alloc_tmp ctx HBytes in + op ctx (OBytes (rfile, alloc_string ctx file)); + hold ctx rfile; + let min = eval_expr ctx min in hold ctx min; + let max = eval_expr ctx max in + op ctx (OCall3 (r,alloc_std ctx "make_macro_pos" [HBytes;HI32;HI32] rt,rfile,min,max)); + free ctx rfile; + free ctx min; + r + | _ -> + abort ("Unknown native call " ^ v.v_name) e.epos) + | TCall (ec,args) -> + let tfun = real_type ctx ec in + let el() = eval_args ctx args tfun e.epos in + let ret = alloc_tmp ctx (match tfun with HFun (_,r) -> r | _ -> HDyn) in + let def_ret = ref None in + (match get_access ctx ec with + | AStaticFun f -> + (match el() with + | [] -> op ctx (OCall0 (ret, f)) + | [a] -> op ctx (OCall1 (ret, f, a)) + | [a;b] -> op ctx (OCall2 (ret, f, a, b)) + | [a;b;c] -> op ctx (OCall3 (ret, f, a, b, c)) + | [a;b;c;d] -> op ctx (OCall4 (ret, f, a, b, c, d)) + | el -> op ctx (OCallN (ret, f, el))); + | AInstanceFun (ethis, f) -> + let r = eval_null_check ctx ethis in + hold ctx r; + let el = r :: el() in + free ctx r; + (match el with + | [a] -> op ctx (OCall1 (ret, f, a)) + | [a;b] -> op ctx (OCall2 (ret, f, a, b)) + | [a;b;c] -> op ctx (OCall3 (ret, f, a, b, c)) + | [a;b;c;d] -> op ctx (OCall4 (ret, f, a, b, c, d)) + | _ -> op ctx (OCallN (ret, f, el))); + | AInstanceProto ({ eexpr = TConst TThis }, fid) -> + op ctx (OCallThis (ret, fid, el())) + | AInstanceProto (ethis, fid) | AVirtualMethod (ethis, fid) -> + let r = eval_null_check ctx ethis in + hold ctx r; + let el = r :: el() in + free ctx r; + op ctx (OCallMethod (ret, fid, el)) + | AEnum (_,index) -> + op ctx (OMakeEnum (ret, index, el())) + | AArray (a,t,idx) -> + let r = array_read ctx a t idx ec.epos in + hold ctx r; + op ctx (ONullCheck r); + op ctx (OCallClosure (ret, r, el())); (* if it's a value, it's a closure *) + free ctx r; + | _ -> + (* don't use real_type here *) + let tfun = to_type ctx ec.etype in + let r = eval_null_check ctx ec in + hold ctx r; + let el = eval_args ctx args tfun e.epos in + free ctx r; + let ret = alloc_tmp ctx (match tfun with HFun (_,r) -> r | _ -> HDyn) in + op ctx (OCallClosure (ret, r, el)); (* if it's a value, it's a closure *) + def_ret := Some (cast_to ~force:true ctx ret (to_type ctx e.etype) e.epos); + ); + (match !def_ret with None -> cast_to ~force:true ctx ret (to_type ctx e.etype) e.epos | Some r -> r) + | TField (ec,FInstance({ cl_path = [],"Array" },[t],{ cf_name = "length" })) when to_type ctx t = HDyn -> + let r = alloc_tmp ctx HI32 in + op ctx (OCall1 (r,alloc_fun_path ctx (["hl";"types"],"ArrayDyn") "get_length", eval_null_check ctx ec)); + r + | TField (ec,a) -> + let r = alloc_tmp ctx (to_type ctx (field_type ctx a e.epos)) in + (match get_access ctx e with + | AGlobal g -> + op ctx (OGetGlobal (r,g)); + | AStaticVar (g,t,fid) -> + let o = alloc_tmp ctx t in + op ctx (OGetGlobal (o,g)); + op ctx (OField (r,o,fid)); + | AStaticFun f -> + op ctx (OStaticClosure (r,f)); + | AInstanceFun (ethis, f) -> + op ctx (OInstanceClosure (r, f, eval_null_check ctx ethis)) + | AInstanceField (ethis,fid) -> + let robj = eval_null_check ctx ethis in + op ctx (match ethis.eexpr with TConst TThis -> OGetThis (r,fid) | _ -> OField (r,robj,fid)); + | AInstanceProto (ethis,fid) | AVirtualMethod (ethis, fid) -> + let robj = eval_null_check ctx ethis in + op ctx (OVirtualClosure (r,robj,fid)); + | ADynamic (ethis, f) -> + let robj = eval_null_check ctx ethis in + op ctx (ODynGet (r,robj,f)) + | AEnum (en,index) -> + let cur_fid = DynArray.length ctx.cfids.arr in + let name = List.nth en.e_names index in + let fid = alloc_fun_path ctx en.e_path name in + if fid = cur_fid then begin + let ef = PMap.find name en.e_constrs in + let eargs, et = (match follow ef.ef_type with TFun (args,ret) -> args, ret | _ -> assert false) in + let ct = ctx.com.basic in + let p = ef.ef_pos in + let eargs = List.map (fun (n,o,t) -> Type.alloc_var n t en.e_pos, if o then Some TNull else None) eargs in + let ecall = mk (TCall (e,List.map (fun (v,_) -> mk (TLocal v) v.v_type p) eargs)) et p in + let f = { + tf_args = eargs; + tf_type = et; + tf_expr = mk (TReturn (Some ecall)) ct.tvoid p; + } in + ignore(make_fun ctx ("","") fid f None None); + end; + op ctx (OStaticClosure (r,fid)); + | ANone | ALocal _ | AArray _ | ACaptured _ -> + abort "Invalid access" e.epos); + unsafe_cast_to ctx r (to_type ctx e.etype) e.epos + | TObjectDecl fl -> + (match to_type ctx e.etype with + | HVirtual vp as t when Array.length vp.vfields = List.length fl && not (List.exists (fun (s,e) -> s = "toString" && is_to_string e.etype) fl) -> + let r = alloc_tmp ctx t in + op ctx (ONew r); + hold ctx r; + List.iter (fun (s,ev) -> + let fidx = (try PMap.find s vp.vindex with Not_found -> assert false) in + let _, _, ft = vp.vfields.(fidx) in + let v = eval_to ctx ev ft in + op ctx (OSetField (r,fidx,v)); + ) fl; + free ctx r; + r + | _ -> + let r = alloc_tmp ctx HDynObj in + op ctx (ONew r); + hold ctx r; + let a = (match follow e.etype with TAnon a -> Some a | t -> if t == t_dynamic then None else assert false) in + List.iter (fun (s,ev) -> + let ft = (try (match a with None -> raise Not_found | Some a -> PMap.find s a.a_fields).cf_type with Not_found -> ev.etype) in + let v = eval_to ctx ev (to_type ctx ft) in + op ctx (ODynSet (r,alloc_string ctx s,v)); + if s = "toString" && is_to_string ev.etype then begin + let f = alloc_tmp ctx (HFun ([],HBytes)) in + op ctx (OInstanceClosure (f, alloc_fun_path ctx ([],"String") "call_toString", r)); + op ctx (ODynSet (r,alloc_string ctx "__string",f)); + end; + ) fl; + free ctx r; + cast_to ctx r (to_type ctx e.etype) e.epos) + | TNew (c,pl,el) -> + let c = resolve_class ctx c pl false in + let r = alloc_tmp ctx (class_type ctx c pl false) in + op ctx (ONew r); + hold ctx r; + (match c.cl_constructor with + | None -> if c.cl_implements <> [] then assert false + | Some { cf_expr = None } -> abort (s_type_path c.cl_path ^ " does not have a constructor") e.epos + | Some ({ cf_expr = Some cexpr } as constr) -> + let rl = eval_args ctx el (to_type ctx cexpr.etype) e.epos in + let ret = alloc_tmp ctx HVoid in + let g = alloc_fid ctx c constr in + op ctx (match rl with + | [] -> OCall1 (ret,g,r) + | [a] -> OCall2 (ret,g,r,a) + | [a;b] -> OCall3 (ret,g,r,a,b) + | [a;b;c] -> OCall4 (ret,g,r,a,b,c) + | _ -> OCallN (ret,g,r :: rl)); + ); + free ctx r; + r + | TIf (cond,eif,eelse) -> + let t = to_type ctx e.etype in + let out = alloc_tmp ctx t in + let j = jump_expr ctx cond false in + if t = HVoid then ignore(eval_expr ctx eif) else op ctx (OMov (out,eval_to ctx eif t)); + (match eelse with + | None -> j() + | Some e -> + let jexit = jump ctx (fun i -> OJAlways i) in + j(); + if t = HVoid then ignore(eval_expr ctx e) else op ctx (OMov (out,eval_to ctx e t)); + jexit()); + out + | TBinop (bop, e1, e2) -> + let is_unsigned() = unsigned_op e1 e2 in + let boolop r f = + let j = jump ctx f in + op ctx (OBool (r,false)); + op ctx (OJAlways 1); + j(); + op ctx (OBool (r, true)); + in + let binop r a b = + let rec loop bop = + match bop with + | OpLte -> boolop r (fun d -> if is_unsigned() then OJUGte (b,a,d) else OJSLte (a,b,d)) + | OpGt -> boolop r (fun d -> if is_unsigned() then OJULt (b,a,d) else OJSGt (a,b,d)) + | OpGte -> boolop r (fun d -> if is_unsigned() then OJUGte (a,b,d) else OJSGte (a,b,d)) + | OpLt -> boolop r (fun d -> if is_unsigned() then OJULt (a,b,d) else OJSLt (a,b,d)) + | OpEq -> boolop r (fun d -> OJEq (a,b,d)) + | OpNotEq -> boolop r (fun d -> OJNotEq (a,b,d)) + | OpAdd -> + (match rtype ctx r with + | HUI8 | HUI16 | HI32 | HF32 | HF64 -> + op ctx (OAdd (r,a,b)) + | HObj { pname = "String" } -> + op ctx (OCall2 (r,alloc_fun_path ctx ([],"String") "__add__",a,b)) + | HDyn -> + op ctx (OCall2 (r,alloc_fun_path ctx ([],"Std") "__add__",a,b)) + | t -> + abort ("Cannot add " ^ tstr t) e.epos) + | OpSub | OpMult | OpMod | OpDiv -> + (match rtype ctx r with + | HUI8 | HUI16 | HI32 | HF32 | HF64 -> + (match bop with + | OpSub -> op ctx (OSub (r,a,b)) + | OpMult -> op ctx (OMul (r,a,b)) + | OpMod -> op ctx (if unsigned e1.etype then OUMod (r,a,b) else OSMod (r,a,b)) + | OpDiv -> op ctx (OSDiv (r,a,b)) (* don't use UDiv since both operands are float already *) + | _ -> assert false) + | _ -> + assert false) + | OpShl | OpShr | OpUShr | OpAnd | OpOr | OpXor -> + (match rtype ctx r with + | HUI8 | HUI16 | HI32 -> + (match bop with + | OpShl -> op ctx (OShl (r,a,b)) + | OpShr -> op ctx (if unsigned e1.etype then OUShr (r,a,b) else OSShr (r,a,b)) + | OpUShr -> op ctx (OUShr (r,a,b)) + | OpAnd -> op ctx (OAnd (r,a,b)) + | OpOr -> op ctx (OOr (r,a,b)) + | OpXor -> op ctx (OXor (r,a,b)) + | _ -> ()) + | _ -> + assert false) + | OpAssignOp bop -> + loop bop + | _ -> + assert false + in + loop bop + in + (match bop with + | OpLte | OpGt | OpGte | OpLt -> + let r = alloc_tmp ctx HBool in + let t = common_type ctx e1 e2 false e.epos in + let a = eval_to ctx e1 t in + hold ctx a; + let b = eval_to ctx e2 t in + free ctx a; + binop r a b; + r + | OpEq | OpNotEq -> + let r = alloc_tmp ctx HBool in + let t = common_type ctx e1 e2 true e.epos in + let a = eval_to ctx e1 t in + hold ctx a; + let b = eval_to ctx e2 t in + free ctx a; + binop r a b; + r + | OpAdd | OpSub | OpMult | OpDiv | OpMod | OpShl | OpShr | OpUShr | OpAnd | OpOr | OpXor -> + let t = (match to_type ctx e.etype with HNull t -> t | t -> t) in + let r = alloc_tmp ctx t in + let a = eval_to ctx e1 t in + hold ctx a; + let b = eval_to ctx e2 t in + free ctx a; + binop r a b; + r + | OpAssign -> + let value() = eval_to ctx e2 (real_type ctx e1) in + (match get_access ctx e1 with + | AGlobal g -> + let r = value() in + op ctx (OSetGlobal (g,r)); + r + | AStaticVar (g,t,fid) -> + let r = value() in + hold ctx r; + let o = alloc_tmp ctx t in + free ctx r; + op ctx (OGetGlobal (o, g)); + op ctx (OSetField (o, fid, r)); + r + | AInstanceField ({ eexpr = TConst TThis }, fid) -> + let r = value() in + op ctx (OSetThis (fid,r)); + r + | AInstanceField (ethis, fid) -> + let rthis = eval_null_check ctx ethis in + hold ctx rthis; + let r = value() in + free ctx rthis; + op ctx (OSetField (rthis, fid, r)); + r + | ALocal (v,l) -> + let r = value() in + op ctx (OMov (l, r)); + add_assign ctx v l; + r + | AArray (ra,(at,vt),ridx) -> + hold ctx ra; + hold ctx ridx; + let v = cast_to ctx (value()) (match at with HUI16 | HUI8 -> HI32 | _ -> at) e.epos in + hold ctx v; + (* bounds check against length *) + (match at with + | HDyn -> + (* call setDyn() *) + op ctx (OCallMethod (alloc_tmp ctx HVoid,1,[ra;ridx;cast_to ctx v (if is_dynamic at then at else HDyn) e.epos])); + | _ -> + let len = alloc_tmp ctx HI32 in + op ctx (OField (len,ra,0)); (* length *) + let j = jump ctx (fun i -> OJULt (ridx,len,i)) in + op ctx (OCall2 (alloc_tmp ctx HVoid, alloc_fun_path ctx (array_class ctx at).cl_path "__expand", ra, ridx)); + j(); + match at with + | HI32 | HF64 | HUI16 | HF32 -> + let b = alloc_tmp ctx HBytes in + op ctx (OField (b,ra,1)); + write_mem ctx b (shl ctx ridx (type_size_bits at)) at v + | _ -> + let arr = alloc_tmp ctx HArray in + op ctx (OField (arr,ra,1)); + op ctx (OSetArray (arr,ridx,cast_to ctx v (if is_dynamic at then at else HDyn) e.epos)) + ); + free ctx v; + free ctx ra; + free ctx ridx; + v + | ADynamic (ethis,f) -> + let obj = eval_null_check ctx ethis in + hold ctx obj; + let r = eval_expr ctx e2 in + free ctx obj; + op ctx (ODynSet (obj,f,r)); + r + | ACaptured index -> + let r = value() in + op ctx (OSetEnumField (ctx.m.mcaptreg,index,r)); + r + | AEnum _ | ANone | AInstanceFun _ | AInstanceProto _ | AStaticFun _ | AVirtualMethod _ -> + assert false) + | OpBoolOr -> + let r = alloc_tmp ctx HBool in + let j = jump_expr ctx e1 true in + let j2 = jump_expr ctx e2 true in + op ctx (OBool (r,false)); + let jend = jump ctx (fun b -> OJAlways b) in + j(); + j2(); + op ctx (OBool (r,true)); + jend(); + r + | OpBoolAnd -> + let r = alloc_tmp ctx HBool in + let j = jump_expr ctx e1 false in + let j2 = jump_expr ctx e2 false in + op ctx (OBool (r,true)); + let jend = jump ctx (fun b -> OJAlways b) in + j(); + j2(); + op ctx (OBool (r,false)); + jend(); + r + | OpAssignOp bop -> + (match get_access ctx e1 with + | ALocal (v,l) -> + let r = eval_to ctx { e with eexpr = TBinop (bop,e1,e2) } (to_type ctx e1.etype) in + op ctx (OMov (l, r)); + add_assign ctx v l; + r + | acc -> + gen_assign_op ctx acc e1 (fun r -> + hold ctx r; + let b = eval_to ctx e2 (rtype ctx r) in + free ctx r; + binop r r b; + r)) + | OpInterval | OpArrow -> + assert false) + | TUnop (Not,_,v) -> + let tmp = alloc_tmp ctx HBool in + let r = eval_to ctx v HBool in + op ctx (ONot (tmp,r)); + tmp + | TUnop (Neg,_,v) -> + let t = to_type ctx e.etype in + let tmp = alloc_tmp ctx t in + let r = eval_to ctx v t in + op ctx (ONeg (tmp,r)); + tmp + | TUnop (NegBits,_,v) -> + let t = to_type ctx e.etype in + let tmp = alloc_tmp ctx t in + let r = eval_to ctx v t in + let mask = (match t with + | HUI8 -> 0xFFl + | HUI16 -> 0xFFFFl + | HI32 -> 0xFFFFFFFFl + | _ -> abort (tstr t) e.epos + ) in + hold ctx r; + let r2 = alloc_tmp ctx t in + free ctx r; + op ctx (OInt (r2,alloc_i32 ctx mask)); + op ctx (OXor (tmp,r,r2)); + tmp + | TUnop (Increment|Decrement as uop,fix,v) -> + let rec unop r = + match rtype ctx r with + | HUI8 | HUI16 | HI32 -> + if uop = Increment then op ctx (OIncr r) else op ctx (ODecr r) + | HF32 | HF64 as t -> + hold ctx r; + let tmp = alloc_tmp ctx t in + free ctx r; + op ctx (OFloat (tmp,alloc_float ctx 1.)); + if uop = Increment then op ctx (OAdd (r,r,tmp)) else op ctx (OSub (r,r,tmp)) + | HNull (HUI8 | HUI16 | HI32 | HF32 | HF64 as t) -> + hold ctx r; + let tmp = alloc_tmp ctx t in + free ctx r; + op ctx (OSafeCast (tmp,r)); + unop tmp; + op ctx (OToDyn (r,tmp)); + | _ -> + assert false + in + (match get_access ctx v, fix with + | ALocal (v,r), Prefix -> + unop r; + add_assign ctx v r; + r + | ALocal (v,r), Postfix -> + let r2 = alloc_tmp ctx (rtype ctx r) in + op ctx (OMov (r2,r)); + unop r; + add_assign ctx v r; + r2 + | acc, _ -> + let ret = ref 0 in + (match acc with AArray (a,_,idx) -> hold ctx a; hold ctx idx | _ -> ()); + ignore(gen_assign_op ctx acc v (fun r -> + if fix = Prefix then ret := r else begin + hold ctx r; + let tmp = alloc_tmp ctx (rtype ctx r) in + free ctx r; + op ctx (OMov (tmp, r)); + ret := tmp; + end; + hold ctx !ret; + unop r; + r) + ); + free ctx !ret; + (match acc with AArray (a,_,idx) -> free ctx a; free ctx idx | _ -> ()); + !ret) + | TFunction f -> + let fid = alloc_function_name ctx ("function#" ^ string_of_int (DynArray.length ctx.cfids.arr)) in + let capt = make_fun ctx ("","") fid f None (Some ctx.m.mcaptured) in + let r = alloc_tmp ctx (to_type ctx e.etype) in + if capt == ctx.m.mcaptured then + op ctx (OInstanceClosure (r, fid, ctx.m.mcaptreg)) + else (match Array.length capt.c_vars with + | 0 -> + op ctx (OStaticClosure (r, fid)) + | 1 when not capt.c_group -> + op ctx (OInstanceClosure (r, fid, eval_var ctx capt.c_vars.(0))) + | _ -> + let env = alloc_tmp ctx capt.c_type in + op ctx (OEnumAlloc (env,0)); + hold ctx env; + Array.iteri (fun i v -> op ctx (OSetEnumField (env,i,eval_var ctx v))) capt.c_vars; + free ctx env; + op ctx (OInstanceClosure (r, fid, env))); + r + | TThrow v -> + op ctx (OThrow (eval_to ctx v HDyn)); + alloc_tmp ctx HDyn + | TWhile (cond,eloop,NormalWhile) -> + let oldb = ctx.m.mbreaks and oldc = ctx.m.mcontinues and oldtrys = ctx.m.mloop_trys in + ctx.m.mbreaks <- []; + ctx.m.mcontinues <- []; + ctx.m.mloop_trys <- ctx.m.mtrys; + let continue_pos = current_pos ctx in + let ret = jump_back ctx in + let j = jump_expr ctx cond false in + ignore(eval_expr ctx eloop); + ret(); + j(); + List.iter (fun f -> f (current_pos ctx)) ctx.m.mbreaks; + List.iter (fun f -> f continue_pos) ctx.m.mcontinues; + ctx.m.mbreaks <- oldb; + ctx.m.mcontinues <- oldc; + ctx.m.mloop_trys <- oldtrys; + alloc_tmp ctx HVoid + | TWhile (cond,eloop,DoWhile) -> + let oldb = ctx.m.mbreaks and oldc = ctx.m.mcontinues and oldtrys = ctx.m.mloop_trys in + ctx.m.mbreaks <- []; + ctx.m.mcontinues <- []; + ctx.m.mloop_trys <- ctx.m.mtrys; + let start = jump ctx (fun p -> OJAlways p) in + let continue_pos = current_pos ctx in + let ret = jump_back ctx in + let j = jump_expr ctx cond false in + start(); + ignore(eval_expr ctx eloop); + ret(); + j(); + List.iter (fun f -> f (current_pos ctx)) ctx.m.mbreaks; + List.iter (fun f -> f continue_pos) ctx.m.mcontinues; + ctx.m.mbreaks <- oldb; + ctx.m.mcontinues <- oldc; + ctx.m.mloop_trys <- oldtrys; + alloc_tmp ctx HVoid + | TCast (v,None) -> + let t = to_type ctx e.etype in + let rv = eval_expr ctx v in + (match t with + | HF32 | HF64 when unsigned v.etype -> + let r = alloc_tmp ctx t in + op ctx (OToUFloat (r,rv)); + r + | HDyn when (match rtype ctx rv with HFun _ -> true | _ -> false) -> + (* if called, a HDyn method will return HDyn, not its usual return type *) + let r = alloc_tmp ctx t in + op ctx (OMov (r,rv)); + r + | _ -> + cast_to ~force:true ctx rv t e.epos) + | TArrayDecl el -> + let r = alloc_tmp ctx (to_type ctx e.etype) in + let et = (match follow e.etype with TInst (_,[t]) -> to_type ctx t | _ -> assert false) in + let array_bytes bits t tname get_op = + let b = alloc_tmp ctx HBytes in + let size = reg_int ctx ((List.length el) lsl bits) in + op ctx (OCall1 (b,alloc_std ctx "alloc_bytes" [HI32] HBytes,size)); + let idx = reg_int ctx 0 in + hold ctx idx; + hold ctx b; + list_iteri (fun i e -> + let r = eval_to ctx e t in + hold ctx r; + op ctx (get_op b (shl ctx idx bits) r); + free ctx r; + op ctx (OIncr idx); + ) el; + free ctx b; + free ctx idx; + op ctx (OCall2 (r, alloc_fun_path ctx (["hl";"types"],"ArrayBase") ("alloc" ^ tname), b, reg_int ctx (List.length el))); + in + (match et with + | HI32 -> + array_bytes 2 HI32 "I32" (fun b i r -> OSetI32 (b,i,r)) + | HUI16 -> + array_bytes 1 HI32 "UI16" (fun b i r -> OSetUI16 (b,i,r)) + | HF32 -> + array_bytes 2 HF32 "F32" (fun b i r -> OSetF32 (b,i,r)) + | HF64 -> + array_bytes 3 HF64 "F64" (fun b i r -> OSetF64 (b,i,r)) + | _ -> + let at = if is_dynamic et then et else HDyn in + let a = alloc_tmp ctx HArray in + let rt = alloc_tmp ctx HType in + op ctx (OType (rt,at)); + let size = reg_int ctx (List.length el) in + op ctx (OCall2 (a,alloc_std ctx "alloc_array" [HType;HI32] HArray,rt,size)); + hold ctx a; + list_iteri (fun i e -> + let r = eval_to ctx e at in + op ctx (OSetArray (a,reg_int ctx i,r)); + ) el; + free ctx a; + let tmp = if et = HDyn then alloc_tmp ctx (class_type ctx ctx.array_impl.aobj [] false) else r in + op ctx (OCall1 (tmp, alloc_fun_path ctx (["hl";"types"],"ArrayObj") "alloc", a)); + if tmp <> r then begin + let re = alloc_tmp ctx HBool in + op ctx (OBool (re,true)); + let ren = alloc_tmp ctx (HRef HBool) in + op ctx (ORef (ren, re)); + op ctx (OCall2 (r, alloc_fun_path ctx (["hl";"types"],"ArrayDyn") "alloc", tmp, ren)); + end; + ); + r + | TArray _ -> + (match get_access ctx e with + | AArray (a,at,idx) -> + array_read ctx a at idx e.epos + | _ -> + assert false) + | TMeta (_,e) -> + eval_expr ctx e + | TFor (v,it,loop) -> + eval_expr ctx (Codegen.for_remap ctx.com v it loop e.epos) + | TSwitch (en,cases,def) -> + let rt = to_type ctx e.etype in + let r = alloc_tmp ctx rt in + (try + let max = ref (-1) in + let rec get_int e = + match e.eexpr with + | TConst (TInt i) -> + let v = Int32.to_int i in + if Int32.of_int v <> i then raise Exit; + v + | _ -> + raise Exit + in + List.iter (fun (values,_) -> + List.iter (fun v -> + let i = get_int v in + if i < 0 then raise Exit; + if i > !max then max := i; + ) values; + ) cases; + if !max > 255 || cases = [] then raise Exit; + let ridx = eval_to ctx en HI32 in + let indexes = Array.make (!max + 1) 0 in + op ctx (OSwitch (ridx,indexes,0)); + let switch_pos = current_pos ctx in + (match def with + | None -> + if rt <> HVoid then set_default ctx r; + | Some e -> + let re = eval_to ctx e rt in + if rt <> HVoid then op ctx (OMov (r,re))); + let jends = ref [jump ctx (fun i -> OJAlways i)] in + List.iter (fun (values,ecase) -> + List.iter (fun v -> + Array.set indexes (get_int v) (current_pos ctx - switch_pos) + ) values; + let re = eval_to ctx ecase rt in + if rt <> HVoid then op ctx (OMov (r,re)); + jends := jump ctx (fun i -> OJAlways i) :: !jends + ) cases; + DynArray.set ctx.m.mops (switch_pos - 1) (OSwitch (ridx,indexes,current_pos ctx - switch_pos)); + List.iter (fun j -> j()) (!jends); + with Exit -> + let jends = ref [] in + let rvalue = eval_expr ctx en in + let loop (cases,e) = + let ok = List.map (fun c -> + hold ctx rvalue; + let r = eval_to ctx c (common_type ctx en c true c.epos) in + free ctx rvalue; + jump ctx (fun n -> OJEq (r,rvalue,n)) + ) cases in + (fun() -> + List.iter (fun f -> f()) ok; + let re = eval_to ctx e rt in + if rt <> HVoid then op ctx (OMov (r,re)); + jends := jump ctx (fun n -> OJAlways n) :: !jends) + in + let all = List.map loop cases in + (match def with + | None -> + if rt <> HVoid then op ctx (ONull r) + | Some e -> + let rdef = eval_to ctx e rt in + if rt <> HVoid then op ctx (OMov (r,rdef))); + jends := jump ctx (fun n -> OJAlways n) :: !jends; + List.iter (fun f -> f()) all; + List.iter (fun j -> j()) (!jends); + ); + r + | TEnumParameter (ec,f,index) -> + let r = alloc_tmp ctx (match to_type ctx ec.etype with HEnum e -> let _,_,args = e.efields.(f.ef_index) in args.(index) | _ -> assert false) in + op ctx (OEnumField (r,eval_expr ctx ec,f.ef_index,index)); + cast_to ctx r (to_type ctx e.etype) e.epos + | TContinue -> + before_break_continue ctx; + let pos = current_pos ctx in + op ctx (OJAlways (-1)); (* loop *) + ctx.m.mcontinues <- (fun target -> DynArray.set ctx.m.mops pos (OJAlways (target - (pos + 1)))) :: ctx.m.mcontinues; + alloc_tmp ctx HVoid + | TBreak -> + before_break_continue ctx; + let pos = current_pos ctx in + op ctx (OJAlways (-1)); (* loop *) + ctx.m.mbreaks <- (fun target -> DynArray.set ctx.m.mops pos (OJAlways (target - (pos + 1)))) :: ctx.m.mbreaks; + alloc_tmp ctx HVoid + | TTry (etry,catches) -> + let pos = current_pos ctx in + let rtrap = alloc_tmp ctx HDyn in + op ctx (OTrap (rtrap,-1)); (* loop *) + ctx.m.mtrys <- ctx.m.mtrys + 1; + let tret = to_type ctx e.etype in + let result = alloc_tmp ctx tret in + let r = eval_expr ctx etry in + if tret <> HVoid then op ctx (OMov (result,cast_to ctx r tret etry.epos)); + ctx.m.mtrys <- ctx.m.mtrys - 1; + op ctx (OEndTrap true); + let j = jump ctx (fun n -> OJAlways n) in + DynArray.set ctx.m.mops pos (OTrap (rtrap, current_pos ctx - (pos + 1))); + let rec loop l = + match l with + | [] -> + op ctx (ORethrow rtrap); + [] + | (v,ec) :: next -> + let rv = alloc_var ctx v true in + let jnext = if v.v_type == t_dynamic then begin + op ctx (OMov (rv, rtrap)); + (fun() -> ()) + end else + let ct = (match follow v.v_type with + | TInst (c,_) -> TClassDecl c + | TAbstract (a,_) -> TAbstractDecl a + | TEnum (e,_) -> TEnumDecl e + | _ -> assert false + ) in + hold ctx rtrap; + let r = type_value ctx ct ec.epos in + free ctx rtrap; + let rb = alloc_tmp ctx HBool in + op ctx (OCall2 (rb, alloc_fun_path ctx (["hl"],"BaseType") "check",r,rtrap)); + let jnext = jump ctx (fun n -> OJFalse (rb,n)) in + op ctx (OMov (rv, unsafe_cast_to ctx rtrap (to_type ctx v.v_type) ec.epos)); + jnext + in + let r = eval_expr ctx ec in + if tret <> HVoid then op ctx (OMov (result,cast_to ctx r tret ec.epos)); + if v.v_type == t_dynamic then [] else + let jend = jump ctx (fun n -> OJAlways n) in + jnext(); + jend :: loop next + in + List.iter (fun j -> j()) (loop catches); + j(); + result + | TTypeExpr t -> + type_value ctx t e.epos + | TCast (ev,Some _) -> + let t = to_type ctx e.etype in + let re = eval_expr ctx ev in + let r = alloc_tmp ctx t in + if safe_cast (rtype ctx re) t then + op ctx (OMov (r,re)) + else + op ctx (OSafeCast (r,re)); + r + +and gen_assign_op ctx acc e1 f = + let f r = + match rtype ctx r with + | HNull t -> + let r2 = alloc_tmp ctx t in + op ctx (OSafeCast (r2,r)); + let r3 = alloc_tmp ctx (HNull t) in + op ctx (OToDyn (r3,f r2)); + r3 + | _ -> + f r + in + match acc with + | AInstanceField (eobj, findex) -> + let robj = eval_null_check ctx eobj in + hold ctx robj; + let t = real_type ctx e1 in + let r = alloc_tmp ctx t in + op ctx (OField (r,robj,findex)); + let r = cast_to ctx r (to_type ctx e1.etype) e1.epos in + let r = f r in + free ctx robj; + op ctx (OSetField (robj,findex,cast_to ctx r t e1.epos)); + r + | AStaticVar (g,t,fid) -> + let o = alloc_tmp ctx t in + op ctx (OGetGlobal (o,g)); + let r = alloc_tmp ctx (to_type ctx e1.etype) in + op ctx (OField (r,o,fid)); + hold ctx o; + let r = f r in + free ctx o; + op ctx (OSetField (o,fid,r)); + r + | AGlobal g -> + let r = alloc_tmp ctx (to_type ctx e1.etype) in + op ctx (OGetGlobal (r,g)); + let r = f r in + op ctx (OSetGlobal (g,r)); + r + | ACaptured idx -> + let r = alloc_tmp ctx (to_type ctx e1.etype) in + op ctx (OEnumField (r, ctx.m.mcaptreg, 0, idx)); + let r = f r in + op ctx (OSetEnumField (ctx.m.mcaptreg,idx,r)); + r + | AArray (ra,(at,_),ridx) -> + hold ctx ra; + hold ctx ridx; + let r = (match at with + | HDyn -> + (* call getDyn() *) + let r = alloc_tmp ctx HDyn in + op ctx (OCallMethod (r,0,[ra;ridx])); + let r = f r in + (* call setDyn() *) + op ctx (OCallMethod (alloc_tmp ctx HVoid,1,[ra;ridx;r])); + r + | _ -> + (* bounds check against length *) + let len = alloc_tmp ctx HI32 in + op ctx (OField (len,ra,0)); (* length *) + let j = jump ctx (fun i -> OJULt (ridx,len,i)) in + op ctx (OCall2 (alloc_tmp ctx HVoid, alloc_fun_path ctx (array_class ctx at).cl_path "__expand", ra, ridx)); + j(); + match at with + | HI32 | HF64 -> + let hbytes = alloc_tmp ctx HBytes in + op ctx (OField (hbytes, ra, 1)); + let ridx = shl ctx ridx (type_size_bits at) in + hold ctx ridx; + hold ctx hbytes; + let r = alloc_tmp ctx at in + read_mem ctx r hbytes ridx at; + let r = f r in + write_mem ctx hbytes ridx at r; + free ctx ridx; + free ctx hbytes; + r + | _ -> + let arr = alloc_tmp ctx HArray in + op ctx (OField (arr,ra,1)); + let r = alloc_tmp ctx at in + op ctx (OGetArray (r,arr,ridx)); + hold ctx arr; + let r = f r in + free ctx arr; + op ctx (OSetArray (arr,ridx,r)); + r + ) in + free ctx ra; + free ctx ridx; + r + | ADynamic (eobj, fid) -> + let robj = eval_null_check ctx eobj in + let t = real_type ctx e1 in + let r = alloc_tmp ctx t in + op ctx (ODynGet (r,robj,fid)); + hold ctx robj; + let r = cast_to ctx r (to_type ctx e1.etype) e1.epos in + let r = f r in + free ctx robj; + op ctx (ODynSet (robj,fid,cast_to ctx r t e1.epos)); + r + | ANone | ALocal _ | AStaticFun _ | AInstanceFun _ | AInstanceProto _ | AVirtualMethod _ | AEnum _ -> + assert false + +and build_capture_vars ctx f = + let ignored_vars = ref PMap.empty in + let used_vars = ref PMap.empty in + (* get all captured vars in scope, ignore vars that are declared *) + let decl_var v = + if v.v_capture then ignored_vars := PMap.add v.v_id () !ignored_vars + in + let use_var v = + if v.v_capture then used_vars := PMap.add v.v_id v !used_vars + in + let rec loop e = + (match e.eexpr with + | TLocal v -> + use_var v; + | TVar (v,_) -> + decl_var v + | TTry (_,catches) -> + List.iter (fun (v,_) -> decl_var v) catches + | TFunction f -> + List.iter (fun (v,_) -> decl_var v) f.tf_args; + | _ -> + () + ); + Type.iter loop e + in + List.iter (fun (v,_) -> decl_var v) f.tf_args; + loop f.tf_expr; + let cvars = Array.of_list (PMap.fold (fun v acc -> if PMap.mem v.v_id !ignored_vars then acc else v :: acc) !used_vars []) in + Array.sort (fun v1 v2 -> v1.v_id - v2.v_id) cvars; + let indexes = ref PMap.empty in + let v0t = (if Array.length cvars = 1 then to_type ctx cvars.(0).v_type else HDyn) in + let ct, group = (match Array.length cvars with + | 0 -> HVoid, false + | 1 when is_nullable v0t -> v0t, false + | _ -> + Array.iteri (fun i v -> indexes := PMap.add v.v_id i !indexes) cvars; + let ctypes = Array.map (fun v -> to_type ctx v.v_type) cvars in + let ct = tuple_type ctx (Array.to_list ctypes) in + ct, true + ) in + { + c_map = !indexes; + c_vars = cvars; + c_type = ct; + c_group = group; + } + +and gen_method_wrapper ctx rt t p = + try + PMap.find (rt,t) ctx.method_wrappers + with Not_found -> + let fid = lookup_alloc ctx.cfids () in + ctx.method_wrappers <- PMap.add (rt,t) fid ctx.method_wrappers; + let old = ctx.m in + let targs, tret = (match t with HFun (args, ret) -> args, ret | _ -> assert false) in + let iargs, iret = (match rt with HFun (args, ret) -> args, ret | _ -> assert false) in + ctx.m <- method_context fid HDyn null_capture false; + let rfun = alloc_tmp ctx rt in + let rargs = List.map (fun t -> + let r = alloc_tmp ctx t in + hold ctx r; + r + ) targs in + let casts = List.map2 (fun r t -> let r2 = cast_to ctx r t p in hold ctx r2; free ctx r; r2) rargs iargs in + List.iter (free ctx) casts; + let rret = alloc_tmp ctx iret in + op ctx (OCallClosure (rret,rfun,casts)); + op ctx (ORet (cast_to ctx rret tret p)); + let f = { + fpath = "",""; + findex = fid; + ftype = HFun (rt :: targs, tret); + regs = DynArray.to_array ctx.m.mregs.arr; + code = DynArray.to_array ctx.m.mops; + debug = make_debug ctx ctx.m.mdebug; + } in + ctx.m <- old; + DynArray.add ctx.cfunctions f; + DynArray.add ctx.cdebug_assigns [||]; + fid + +and make_fun ?gen_content ctx name fidx f cthis cparent = + let old = ctx.m in + let capt = build_capture_vars ctx f in + let has_captured_vars = Array.length capt.c_vars > 0 in + let capt, use_parent_capture = (match cparent with + | Some cparent when has_captured_vars && List.for_all (fun v -> PMap.mem v.v_id cparent.c_map) (Array.to_list capt.c_vars) -> cparent, true + | _ -> capt, false + ) in + + ctx.m <- method_context fidx (to_type ctx f.tf_type) capt (cthis <> None); + + set_curpos ctx f.tf_expr.epos; + + let tthis = (match cthis with + | None -> None + | Some c -> + let t = to_type ctx (TInst (c,[])) in + hold ctx (alloc_tmp ctx t); (* index 0 *) + Some t + ) in + + let rcapt = match has_captured_vars && cparent <> None with + | true when capt.c_group -> + let r = alloc_tmp ctx capt.c_type in + hold ctx r; + Some r + | true -> + Some (alloc_var ctx capt.c_vars.(0) true) + | false -> + None + in + + let args = List.map (fun (v,o) -> + let t = to_type ctx v.v_type in + let r = alloc_var ctx (if o = None then v else { v with v_type = if not (is_nullable t) then TAbstract(ctx.ref_abstract,[v.v_type]) else v.v_type }) true in + add_assign ctx v r; + rtype ctx r + ) f.tf_args in + + if has_captured_vars then ctx.m.mcaptreg <- (match rcapt with + | None when not capt.c_group -> + -1 + | None -> + let r = alloc_tmp ctx capt.c_type in + hold ctx r; + op ctx (OEnumAlloc (r,0)); + add_capture ctx r; + r + | Some r -> + add_capture ctx r; + r + ); + + List.iter (fun (v, o) -> + let r = alloc_var ctx v false in + let vt = to_type ctx v.v_type in + let capt = captured_index ctx v in + (match o with + | None | Some TNull -> () + | Some c when not (is_nullable vt) -> + (* if optional but not null, turn into a not nullable here *) + let j = jump ctx (fun n -> OJNotNull (r,n)) in + let t = alloc_tmp ctx vt in + (match vt with + | HUI8 | HUI16 | HI32 -> + (match c with + | TInt i -> op ctx (OInt (t,alloc_i32 ctx i)) + | TFloat s -> op ctx (OInt (t,alloc_i32 ctx (Int32.of_float (float_of_string s)))) + | _ -> assert false) + | HF32 | HF64 -> + (match c with + | TInt i -> op ctx (OFloat (t,alloc_float ctx (Int32.to_float i))) + | TFloat s -> op ctx (OFloat (t,alloc_float ctx (float_of_string s))) + | _ -> assert false) + | HBool -> + (match c with + | TBool b -> op ctx (OBool (t,b)) + | _ -> assert false) + | _ -> + assert false); + if capt = None then add_assign ctx v t; + let jend = jump ctx (fun n -> OJAlways n) in + j(); + op ctx (OUnref (t,r)); + if capt = None then add_assign ctx v t; + jend(); + Hashtbl.replace ctx.m.mvars v.v_id t; + free ctx r; + hold ctx t + | Some c -> + let j = jump ctx (fun n -> OJNotNull (r,n)) in + (match c with + | TNull | TThis | TSuper -> assert false + | TInt i when (match to_type ctx (follow v.v_type) with HUI8 | HUI16 | HI32 | HDyn -> true | _ -> false) -> + let tmp = alloc_tmp ctx HI32 in + op ctx (OInt (tmp, alloc_i32 ctx i)); + op ctx (OToDyn (r, tmp)); + | TFloat s when (match to_type ctx (follow v.v_type) with HUI8 | HUI16 | HI32 -> true | _ -> false) -> + let tmp = alloc_tmp ctx HI32 in + op ctx (OInt (tmp, alloc_i32 ctx (Int32.of_float (float_of_string s)))); + op ctx (OToDyn (r, tmp)); + | TInt i -> + let tmp = alloc_tmp ctx HF64 in + op ctx (OFloat (tmp, alloc_float ctx (Int32.to_float i))); + op ctx (OToDyn (r, tmp)); + | TFloat s -> + let tmp = alloc_tmp ctx HF64 in + op ctx (OFloat (tmp, alloc_float ctx (float_of_string s))); + op ctx (OToDyn (r, tmp)); + | TBool b -> + let tmp = alloc_tmp ctx HBool in + op ctx (OBool (tmp, b)); + op ctx (OToDyn (r, tmp)); + | TString s -> + op ctx (OMov (r, make_string ctx s f.tf_expr.epos)) + ); + if capt = None then add_assign ctx v r; + j(); + ); + (match capt with + | None -> () + | Some index -> + op ctx (OSetEnumField (ctx.m.mcaptreg, index, alloc_var ctx v false))); + ) f.tf_args; + + (match gen_content with + | None -> () + | Some f -> f()); + + ignore(eval_expr ctx f.tf_expr); + let tret = to_type ctx f.tf_type in + let rec has_final_jump e = + (* prevents a jump outside function bounds error *) + match e.eexpr with + | TBlock el -> (match List.rev el with e :: _ -> has_final_jump e | [] -> false) + | TParenthesis e -> has_final_jump e + | TReturn _ -> false + | _ -> true + in + if tret = HVoid then + op ctx (ORet (alloc_tmp ctx HVoid)) + else if has_final_jump f.tf_expr then begin + let r = alloc_tmp ctx tret in + (match tret with + | HI32 | HUI8 | HUI16 -> op ctx (OInt (r,alloc_i32 ctx 0l)) + | HF32 | HF64 -> op ctx (OFloat (r,alloc_float ctx 0.)) + | HBool -> op ctx (OBool (r,false)) + | _ -> op ctx (ONull r)); + op ctx (ORet r) + end; + let fargs = (match tthis with None -> [] | Some t -> [t]) @ (match rcapt with None -> [] | Some r -> [rtype ctx r]) @ args in + let f = { + fpath = name; + findex = fidx; + ftype = HFun (fargs, tret); + regs = DynArray.to_array ctx.m.mregs.arr; + code = DynArray.to_array ctx.m.mops; + debug = make_debug ctx ctx.m.mdebug; + } in + let assigns = Array.of_list (List.rev ctx.m.massign) in + ctx.m <- old; + Hashtbl.add ctx.defined_funs fidx (); + let f = if ctx.optimize then Hlopt.optimize ctx.dump_out f else f in + DynArray.add ctx.cfunctions f; + DynArray.add ctx.cdebug_assigns assigns; + capt + +let generate_static ctx c f = + match f.cf_kind with + | Var _ -> + () + | Method _ when Meta.has Meta.Extern f.cf_meta -> + () + | Method m -> + let add_native lib name = + ignore(lookup ctx.cnatives (name ^ "@" ^ lib) (fun() -> + let fid = alloc_fid ctx c f in + Hashtbl.add ctx.defined_funs fid (); + (alloc_string ctx lib, alloc_string ctx name,to_type ctx f.cf_type,fid) + )); + in + let rec loop = function + | (Meta.Custom ":hlNative",[(EConst(String(lib)),_);(EConst(String(name)),_)] ,_ ) :: _ -> + add_native lib name + | (Meta.Custom ":hlNative",[(EConst(String(lib)),_)] ,_ ) :: _ -> + add_native lib f.cf_name + | (Meta.Custom ":hlNative",[] ,_ ) :: _ -> + add_native "std" f.cf_name + | (Meta.Custom ":hlNative",_ ,p) :: _ -> + abort "Invalid @:hlNative decl" p + | [] -> + ignore(make_fun ctx (s_type_path c.cl_path,f.cf_name) (alloc_fid ctx c f) (match f.cf_expr with Some { eexpr = TFunction f } -> f | _ -> abort "Missing function body" f.cf_pos) None None) + | _ :: l -> + loop l + in + loop f.cf_meta + + +let rec generate_member ctx c f = + match f.cf_kind with + | Var _ -> () + | _ when is_extern_field f -> () + | Method m -> + let gen_content = if f.cf_name <> "new" then None else Some (fun() -> + + let o = (match class_type ctx c (List.map snd c.cl_params) false with + | HObj o -> o + | _ -> assert false + ) in + + (* + init dynamic functions + *) + List.iter (fun f -> + match f.cf_kind with + | Method MethDynamic -> + let r = alloc_tmp ctx (to_type ctx f.cf_type) in + let fid = (try fst (get_index f.cf_name o) with Not_found -> assert false) in + op ctx (OGetThis (r,fid)); + op ctx (OJNotNull (r,2)); + op ctx (OInstanceClosure (r,alloc_fid ctx c f,0)); + op ctx (OSetThis (fid,r)); + | _ -> () + ) c.cl_ordered_fields; + ) in + ignore(make_fun ?gen_content ctx (s_type_path c.cl_path,f.cf_name) (alloc_fid ctx c f) (match f.cf_expr with Some { eexpr = TFunction f } -> f | _ -> abort "Missing function body" f.cf_pos) (Some c) None); + if f.cf_name = "toString" && not (List.memq f c.cl_overrides) && not (PMap.mem "__string" c.cl_fields) && is_to_string f.cf_type then begin + let p = f.cf_pos in + (* function __string() return this.toString().bytes *) + let ethis = mk (TConst TThis) (TInst (c,List.map snd c.cl_params)) p in + let tstr = mk (TCall (mk (TField (ethis,FInstance(c,List.map snd c.cl_params,f))) f.cf_type p,[])) ctx.com.basic.tstring p in + let cstr, cf_bytes = (try (match ctx.com.basic.tstring with TInst(c,_) -> c, PMap.find "bytes" c.cl_fields | _ -> assert false) with Not_found -> assert false) in + let estr = mk (TReturn (Some (mk (TField (tstr,FInstance (cstr,[],cf_bytes))) cf_bytes.cf_type p))) ctx.com.basic.tvoid p in + ignore(make_fun ctx (s_type_path c.cl_path,"__string") (alloc_fun_path ctx c.cl_path "__string") { tf_expr = estr; tf_args = []; tf_type = cf_bytes.cf_type; } (Some c) None) + end + +let generate_type ctx t = + match t with + | TClassDecl { cl_interface = true }-> + () + | TClassDecl c when c.cl_extern -> + List.iter (fun f -> + List.iter (fun (name,args,pos) -> + match name with + | Meta.Custom ":hlNative" -> generate_static ctx c f + | _ -> () + ) f.cf_meta + ) c.cl_ordered_statics + | TClassDecl c -> + List.iter (generate_static ctx c) c.cl_ordered_statics; + (match c.cl_constructor with + | None -> () + | Some f -> generate_member ctx c f); + List.iter (generate_member ctx c) c.cl_ordered_fields; + | TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ -> + () + +let generate_static_init ctx types main = + let exprs = ref [] in + let t_void = ctx.com.basic.tvoid in + + let gen_content() = + + op ctx (OCall0 (alloc_tmp ctx HVoid, alloc_fun_path ctx ([],"Type") "init")); + + (* init class values *) + List.iter (fun t -> + match t with + | TClassDecl c when not c.cl_extern && not (is_array_class (s_type_path c.cl_path) && snd c.cl_path <> "ArrayDyn") && c != ctx.core_type && c != ctx.core_enum -> + + let path = if c == ctx.array_impl.abase then [],"Array" else if c == ctx.base_class then [],"Class" else c.cl_path in + + let g, ct = class_global ~resolve:false ctx c in + let ctype = if c == ctx.array_impl.abase then ctx.array_impl.aall else c in + let t = class_type ctx ctype (List.map snd ctype.cl_params) false in + + let index name = + match ct with + | HObj o -> + fst (try get_index name o with Not_found -> assert false) + | _ -> + assert false + in + + let rc = (match t with + | HObj o when (match o.pclassglobal with None -> -1 | Some i -> i) <> g -> + (* manual registration for objects with prototype tricks (Array) *) + + let rc = alloc_tmp ctx ct in + op ctx (ONew rc); + op ctx (OSetGlobal (g,rc)); + hold ctx rc; + + let rt = alloc_tmp ctx HType in + op ctx (OType (rt, t)); + op ctx (OSetField (rc,index "__type__",rt)); + op ctx (OSetField (rc,index "__name__",eval_expr ctx { eexpr = TConst (TString (s_type_path path)); epos = c.cl_pos; etype = ctx.com.basic.tstring })); + + let rname = alloc_tmp ctx HBytes in + op ctx (OString (rname, alloc_string ctx (s_type_path path))); + op ctx (OCall2 (alloc_tmp ctx HVoid, alloc_fun_path ctx ([],"Type") "register",rname,rc)); + rc + + | _ -> + + let rct = alloc_tmp ctx HType in + op ctx (OType (rct, ct)); + hold ctx rct; + + let rt = alloc_tmp ctx HType in + op ctx (OType (rt, t)); + + let rname = alloc_tmp ctx HBytes in + op ctx (OString (rname, alloc_string ctx (s_type_path path))); + + let rc = alloc_tmp ctx (class_type ctx ctx.base_class [] false) in + op ctx (OCall3 (rc, alloc_fun_path ctx ([],"Type") "initClass", rct, rt, rname)); + hold ctx rc; + free ctx rct; + rc + ) in + + let gather_implements() = + let classes = ref [] in + let rec lookup cv = + List.exists (fun (i,_) -> i == c || lookup i) cv.cl_implements + in + let check = function + | TClassDecl c when c.cl_interface = false && not c.cl_extern -> if lookup c then classes := c :: !classes + | _ -> () + in + List.iter check ctx.com.types; + !classes + in + if c.cl_interface then begin + let l = gather_implements() in + let ra = alloc_tmp ctx HArray in + let rt = alloc_tmp ctx HType in + op ctx (OType (rt, HType)); + op ctx (OCall2 (ra, alloc_std ctx "alloc_array" [HType;HI32] HArray, rt, reg_int ctx (List.length l))); + list_iteri (fun i intf -> + op ctx (OType (rt, to_type ctx (TInst (intf,[])))); + op ctx (OSetArray (ra, reg_int ctx i, rt)); + ) l; + op ctx (OSetField (rc,index "__implementedBy__",ra)); + + (* TODO : use a plain class for interface object since we don't allow statics *) + let rt = alloc_tmp ctx ct in + op ctx (OSafeCast (rt, rc)); + op ctx (OSetGlobal (g, rt)); + end; + + (match Codegen.build_metadata ctx.com (TClassDecl c) with + | None -> () + | Some e -> + let r = eval_to ctx e HDyn in + op ctx (OSetField (rc,index "__meta__",r))); + + free ctx rc; + + | TEnumDecl e when not e.e_extern -> + + let et = enum_class ctx e in + let t = enum_type ctx e in + + let ret = alloc_tmp ctx HType in + op ctx (OType (ret, et)); + hold ctx ret; + let rt = alloc_tmp ctx HType in + op ctx (OType (rt, t)); + let r = alloc_tmp ctx (class_type ctx ctx.base_enum [] false) in + op ctx (OCall2 (r, alloc_fun_path ctx ([],"Type") "initEnum", ret, rt)); + free ctx ret; + + let index name = + match et with + | HObj o -> + fst (try get_index name o with Not_found -> assert false) + | _ -> + assert false + in + + let avalues = alloc_tmp ctx HArray in + op ctx (OField (avalues, r, index "__evalues__")); + + List.iter (fun n -> + let f = PMap.find n e.e_constrs in + match follow f.ef_type with + | TFun _ -> () + | _ -> + let g = alloc_global ctx (efield_name e f) t in + let r = alloc_tmp ctx t in + let rd = alloc_tmp ctx HDyn in + op ctx (OGetArray (rd,avalues, reg_int ctx f.ef_index)); + op ctx (OSafeCast (r, rd)); + op ctx (OSetGlobal (g,r)); + ) e.e_names; + + (match Codegen.build_metadata ctx.com (TEnumDecl e) with + | None -> () + | Some e -> op ctx (OSetField (r,index "__meta__",eval_to ctx e HDyn))); + + + | TAbstractDecl { a_path = [], name; a_pos = pos } -> + (match name with + | "Int" | "Float" | "Dynamic" | "Bool" -> + let is_bool = name = "Bool" in + let t = class_type ctx (if is_bool then ctx.core_enum else ctx.core_type) [] false in + + let index name = + match t with + | HObj o -> + fst (try get_index name o with Not_found -> assert false) + | _ -> + assert false + in + + let g = alloc_global ctx ("$" ^ name) t in + let r = alloc_tmp ctx t in + let rt = alloc_tmp ctx HType in + op ctx (ONew r); + op ctx (OType (rt,(match name with "Int" -> HI32 | "Float" -> HF64 | "Dynamic" -> HDyn | "Bool" -> HBool | _ -> assert false))); + op ctx (OSetField (r,index "__type__",rt)); + op ctx (OSetField (r,index (if is_bool then "__ename__" else "__name__"),make_string ctx name pos)); + op ctx (OSetGlobal (g,r)); + + let bytes = alloc_tmp ctx HBytes in + op ctx (OString (bytes, alloc_string ctx name)); + op ctx (OCall2 (alloc_tmp ctx HVoid, alloc_fun_path ctx ([],"Type") "register",bytes,r)); + | _ -> + ()) + | _ -> + () + + ) types; + in + (* init class statics *) + List.iter (fun t -> + match t with + | TClassDecl c when not c.cl_extern -> + (match c.cl_init with None -> () | Some e -> exprs := e :: !exprs); + List.iter (fun f -> + match f.cf_kind, f.cf_expr with + | Var _, Some e -> + let p = e.epos in + let e = mk (TBinop (OpAssign,(mk (TField (mk (TTypeExpr t) t_dynamic p,FStatic (c,f))) f.cf_type p), e)) f.cf_type p in + exprs := e :: !exprs; + | _ -> + () + ) c.cl_ordered_statics; + | _ -> () + ) types; + (* call main() *) + (match main with + | None -> () + | Some e -> exprs := e :: !exprs); + let fid = lookup_alloc ctx.cfids () in + ignore(make_fun ~gen_content ctx ("","") fid { tf_expr = mk (TBlock (List.rev !exprs)) t_void null_pos; tf_args = []; tf_type = t_void } None None); + fid + +(* --------------------------------------------------------------------------------------------------------------------- *) +(* WRITE *) + + +(* from -500M to +500M + 0[7] = 0-127 + 10[+/-][5] [8] = -x2000/+x2000 + 11[+/-][5] [24] = -x20000000/+x20000000 +*) +let write_index_gen b i = + if i < 0 then + let i = -i in + if i < 0x2000 then begin + b ((i lsr 8) lor 0xA0); + b (i land 0xFF); + end else if i >= 0x20000000 then assert false else begin + b ((i lsr 24) lor 0xE0); + b ((i lsr 16) land 0xFF); + b ((i lsr 8) land 0xFF); + b (i land 0xFF); + end + else if i < 0x80 then + b i + else if i < 0x2000 then begin + b ((i lsr 8) lor 0x80); + b (i land 0xFF); + end else if i >= 0x20000000 then assert false else begin + b ((i lsr 24) lor 0xC0); + b ((i lsr 16) land 0xFF); + b ((i lsr 8) land 0xFF); + b (i land 0xFF); + end + +let write_code ch code debug = + + let all_types, htypes = gather_types code in + let byte = IO.write_byte ch in + let write_index = write_index_gen byte in + + let rec write_type t = + write_index (try PMap.find t htypes with Not_found -> assert false) + in + + let write_op op = + + let o = Obj.repr op in + let oid = Obj.tag o in + + match op with + | OLabel _ | ONop _ -> + byte oid + | OCall2 (r,g,a,b) -> + byte oid; + write_index r; + write_index g; + write_index a; + write_index b; + | OCall3 (r,g,a,b,c) -> + byte oid; + write_index r; + write_index g; + write_index a; + write_index b; + write_index c; + | OCall4 (r,g,a,b,c,d) -> + byte oid; + write_index r; + write_index g; + write_index a; + write_index b; + write_index c; + write_index d; + | OCallN (r,f,rl) | OCallClosure (r,f,rl) | OCallMethod (r,f,rl) | OCallThis (r,f,rl) | OMakeEnum (r,f,rl) -> + byte oid; + write_index r; + write_index f; + let n = List.length rl in + if n > 0xFF then assert false; + byte n; + List.iter write_index rl + | OType (r,t) -> + byte oid; + write_index r; + write_type t + | OSwitch (r,pl,eend) -> + byte oid; + write_index r; + write_index (Array.length pl); + Array.iter write_index pl; + write_index eend + | OEnumField (r,e,i,idx) -> + byte oid; + write_index r; + write_index e; + write_index i; + write_index idx; + | _ -> + let field n = (Obj.magic (Obj.field o n) : int) in + match Obj.size o with + | 1 -> + let a = field 0 in + byte oid; + write_index a; + | 2 -> + let a = field 0 in + let b = field 1 in + byte oid; + write_index a; + write_index b; + | 3 -> + let a = field 0 in + let b = field 1 in + let c = field 2 in + byte oid; + write_index a; + write_index b; + write_index c; + | _ -> + assert false + in + + IO.nwrite ch "HLB"; + byte code.version; + + let flags = ref 0 in + if debug then flags := !flags lor 1; + byte !flags; + + write_index (Array.length code.ints); + write_index (Array.length code.floats); + write_index (Array.length code.strings); + write_index (Array.length all_types); + write_index (Array.length code.globals); + write_index (Array.length code.natives); + write_index (Array.length code.functions); + write_index code.entrypoint; + + Array.iter (IO.write_real_i32 ch) code.ints; + Array.iter (IO.write_double ch) code.floats; + + let write_strings strings = + let str_length = ref 0 in + Array.iter (fun str -> str_length := !str_length + String.length str + 1) strings; + IO.write_i32 ch !str_length; + Array.iter (IO.write_string ch) strings; + Array.iter (fun str -> write_index (String.length str)) strings; + in + write_strings code.strings; + + if debug then begin + write_index (Array.length code.debugfiles); + write_strings code.debugfiles; + end; + + Array.iter (fun t -> + match t with + | HVoid -> byte 0 + | HUI8 -> byte 1 + | HUI16 -> byte 2 + | HI32 -> byte 3 + | HF32 -> byte 4 + | HF64 -> byte 5 + | HBool -> byte 6 + | HBytes -> byte 7 + | HDyn -> byte 8 + | HFun (args,ret) -> + let n = List.length args in + if n > 0xFF then assert false; + byte 9; + byte n; + List.iter write_type args; + write_type ret + | HObj p -> + byte 10; + write_index p.pid; + (match p.psuper with + | None -> write_index (-1) + | Some t -> write_type (HObj t)); + (match p.pclassglobal with + | None -> write_index 0 + | Some g -> write_index (g + 1)); + write_index (Array.length p.pfields); + write_index (Array.length p.pproto); + write_index (List.length p.pbindings); + Array.iter (fun (_,n,t) -> write_index n; write_type t) p.pfields; + Array.iter (fun f -> write_index f.fid; write_index f.fmethod; write_index (match f.fvirtual with None -> -1 | Some i -> i)) p.pproto; + List.iter (fun (fid,fidx) -> write_index fid; write_index fidx) p.pbindings; + | HArray -> + byte 11 + | HType -> + byte 12 + | HRef t -> + byte 13; + write_type t + | HVirtual v -> + byte 14; + write_index (Array.length v.vfields); + Array.iter (fun (_,sid,t) -> write_index sid; write_type t) v.vfields + | HDynObj -> + byte 15 + | HAbstract (_,i) -> + byte 16; + write_index i + | HEnum e -> + byte 17; + write_index e.eid; + (match e.eglobal with + | None -> write_index 0 + | Some g -> write_index (g + 1)); + write_index (Array.length e.efields); + Array.iter (fun (_,nid,tl) -> + write_index nid; + if Array.length tl > 0xFF then assert false; + byte (Array.length tl); + Array.iter write_type tl; + ) e.efields + | HNull t -> + byte 18; + write_type t + ) all_types; + + let write_debug_infos debug = + let curfile = ref (-1) in + let curpos = ref 0 in + let rcount = ref 0 in + let rec flush_repeat p = + if !rcount > 0 then begin + if !rcount > 15 then begin + byte ((15 lsl 2) lor 2); + rcount := !rcount - 15; + flush_repeat(p) + end else begin + let delta = p - !curpos in + let delta = (if delta > 0 && delta < 4 then delta else 0) in + byte ((delta lsl 6) lor (!rcount lsl 2) lor 2); + rcount := 0; + curpos := !curpos + delta; + end + end + in + Array.iter (fun (f,p) -> + if f <> !curfile then begin + flush_repeat(p); + curfile := f; + byte ((f lsr 7) lor 1); + byte (f land 0xFF); + end; + if p <> !curpos then flush_repeat(p); + if p = !curpos then + rcount := !rcount + 1 + else + let delta = p - !curpos in + if delta > 0 && delta < 32 then + byte ((delta lsl 3) lor 4) + else begin + byte (p lsl 3); + byte (p lsr 5); + byte (p lsr 13); + end; + curpos := p; + ) debug; + flush_repeat(!curpos) + in + + Array.iter write_type code.globals; + Array.iter (fun (lib_index, name_index,ttype,findex) -> + write_index lib_index; + write_index name_index; + write_type ttype; + write_index findex; + ) code.natives; + Array.iter (fun f -> + write_type f.ftype; + write_index f.findex; + write_index (Array.length f.regs); + write_index (Array.length f.code); + Array.iter write_type f.regs; + Array.iter write_op f.code; + if debug then write_debug_infos f.debug; + ) code.functions + +(* --------------------------------------------------------------------------------------------------------------------- *) + +let create_context com is_macro dump = + let get_type name = + try + List.find (fun t -> (t_infos t).mt_path = (["hl"],name)) com.types + with Not_found -> try + List.find (fun t -> (t_infos t).mt_path = (["hl";"types"],name)) com.types + with Not_found -> + failwith ("hl type " ^ name ^ " not found") + in + let get_class name = + match get_type name with + | TClassDecl c -> c + | _ -> assert false + in + let get_abstract name = + match get_type name with + | TAbstractDecl a -> a + | _ -> assert false + in + let ctx = { + com = com; + is_macro = is_macro; + optimize = not (Common.raw_defined com "hl-no-opt"); + dump_out = if dump then Some (IO.output_channel (open_out_bin "dump/hlopt.txt")) else None; + m = method_context 0 HVoid null_capture false; + cints = new_lookup(); + cstrings = new_lookup(); + cfloats = new_lookup(); + cglobals = new_lookup(); + cnatives = new_lookup(); + cfunctions = DynArray.create(); + overrides = Hashtbl.create 0; + cached_types = PMap.empty; + cached_tuples = PMap.empty; + cfids = new_lookup(); + defined_funs = Hashtbl.create 0; + array_impl = { + aall = get_class "ArrayAccess"; + abase = get_class "ArrayBase"; + adyn = get_class "ArrayDyn"; + aobj = get_class "ArrayObj"; + aui16 = get_class "ArrayBytes_hl_UI16"; + ai32 = get_class "ArrayBytes_Int"; + af32 = get_class "ArrayBytes_Single"; + af64 = get_class "ArrayBytes_Float"; + }; + base_class = get_class "Class"; + base_enum = get_class "Enum"; + base_type = get_class "BaseType"; + core_type = get_class "CoreType"; + core_enum = get_class "CoreEnum"; + ref_abstract = get_abstract "Ref"; + anons_cache = []; + rec_cache = []; + method_wrappers = PMap.empty; + cdebug_files = new_lookup(); + macro_typedefs = Hashtbl.create 0; + cdebug_locals = new_lookup(); + cdebug_assigns = DynArray.create(); + } in + ignore(alloc_string ctx ""); + ignore(class_type ctx ctx.base_class [] false); + ctx + +let add_types ctx types = + List.iter (fun t -> + match t with + | TClassDecl ({ cl_path = ["hl";"types"], ("BytesIterator"|"ArrayBytes") } as c) -> + c.cl_extern <- true + | TClassDecl c -> + let rec loop p f = + match p with + | Some (p,_) when PMap.mem f.cf_name p.cl_fields || loop p.cl_super f -> + Hashtbl.replace ctx.overrides (f.cf_name,p.cl_path) true; + true + | _ -> + false + in + if not ctx.is_macro then List.iter (fun f -> ignore(loop c.cl_super f)) c.cl_overrides; + List.iter (fun (m,args,p) -> + if m = Meta.Custom ":hlNative" then + let lib, prefix = (match args with + | [(EConst (String lib),_)] -> lib, "" + | [(EConst (String lib),_);(EConst (String p),_)] -> lib, p + | _ -> abort "hlNative on class requires library name" p + ) in + (* adds :hlNative for all empty methods *) + List.iter (fun f -> + match f.cf_kind with + | Method MethNormal when not (List.exists (fun (m,_,_) -> m = Meta.Custom ":hlNative") f.cf_meta) -> + (match f.cf_expr with + | Some { eexpr = TFunction { tf_expr = { eexpr = TBlock ([] | [{ eexpr = TReturn (Some { eexpr = TConst _ })}]) } } } | None -> + let name = prefix ^ String.lowercase (Str.global_replace (Str.regexp "[A-Z]+") "_\\0" f.cf_name) in + f.cf_meta <- (Meta.Custom ":hlNative", [(EConst (String lib),p);(EConst (String name),p)], p) :: f.cf_meta; + | _ -> ()) + | _ -> () + ) c.cl_ordered_statics + ) c.cl_meta; + | _ -> () + ) types; + List.iter (generate_type ctx) types + +let build_code ctx types main = + let ep = generate_static_init ctx types main in + { + version = 1; + entrypoint = ep; + strings = DynArray.to_array ctx.cstrings.arr; + ints = DynArray.to_array ctx.cints.arr; + floats = DynArray.to_array ctx.cfloats.arr; + globals = DynArray.to_array ctx.cglobals.arr; + natives = DynArray.to_array ctx.cnatives.arr; + functions = DynArray.to_array ctx.cfunctions; + debugfiles = DynArray.to_array ctx.cdebug_files.arr; + } + +let check ctx = + PMap.iter (fun (s,p) fid -> + if not (Hashtbl.mem ctx.defined_funs fid) then failwith (Printf.sprintf "Unresolved method %s:%s(@%d)" (s_type_path p) s fid) + ) ctx.cfids.map + +let generate com = + let dump = Common.defined com Define.Dump in + let ctx = create_context com false dump in + add_types ctx com.types; + let code = build_code ctx com.types com.main in + Array.sort (fun (lib1,_,_,_) (lib2,_,_,_) -> lib1 - lib2) code.natives; + if dump then begin + (match ctx.dump_out with None -> () | Some ch -> IO.close_out ch); + let ch = open_out_bin "dump/hlcode.txt" in + Hlcode.dump (fun s -> output_string ch (s ^ "\n")) code; + close_out ch; + end; + if Common.raw_defined com "hl-dump-spec" then begin + let ch = open_out_bin "dump/hlspec.txt" in + let write s = output_string ch (s ^ "\n") in + Array.iter (fun f -> + write (fundecl_name f); + let spec = Hlinterp.make_spec code f in + List.iter (fun s -> write ("\t" ^ Hlinterp.spec_string s)) spec; + write ""; + ) code.functions; + close_out ch; + end; + if Common.raw_defined com "hl-check" then begin + check ctx; + Hlinterp.check code false; + end; + let t = Common.timer ["write";"hl"] in + + let escape_command s = + let b = Buffer.create 0 in + String.iter (fun ch -> if (ch=='"' || ch=='\\' ) then Buffer.add_string b "\\"; Buffer.add_char b ch) s; + "\"" ^ Buffer.contents b ^ "\"" + in + + if file_extension com.file = "c" then begin + Hl2c.write_c com com.file code; + let t = Common.timer ["nativecompile";"hl"] in + if not (Common.defined com Define.NoCompilation) && com.run_command ("haxelib run hashlink build " ^ escape_command com.file) <> 0 then failwith "Build failed"; + t(); + end else begin + let ch = IO.output_string() in + write_code ch code true; + let str = IO.close_out ch in + let ch = open_out_bin com.file in + output_string ch str; + close_out ch; +(* + let ch = IO.output_string() in + let byte = IO.write_byte ch in + let write_index = write_index_gen byte in + write_index (DynArray.length ctx.cdebug_locals.arr); + DynArray.iter (fun s -> + write_index (String.length s); + IO.write_string ch s; + ) ctx.cdebug_locals.arr; + write_index (DynArray.length ctx.cdebug_assigns); + DynArray.iter (fun a -> + write_index (Array.length a); + Array.iter (fun (i,p,r) -> + write_index i; + write_index p; + write_index r; + ) a; + ) ctx.cdebug_assigns; + let str = IO.close_out ch in + let dbg = open_out_bin (com.file ^ "d") in + output_string dbg str; + close_out dbg; *) + end; + t(); + if Common.raw_defined com "run" then begin + if com.run_command ("haxelib run hashlink run " ^ escape_command com.file) <> 0 then failwith "Failed to run HL"; + end; + if Common.defined com Define.Interp then + try + let ctx = Hlinterp.create true in + Hlinterp.add_code ctx code; + with + Failure msg -> abort msg null_pos diff --git a/genjava.ml b/src/generators/genjava.ml similarity index 92% rename from genjava.ml rename to src/generators/genjava.ml index 92fd9547..65905d58 100644 --- a/genjava.ml +++ b/src/generators/genjava.ml @@ -1,25 +1,23 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) +open Globals open JData open Unix open Ast @@ -30,6 +28,7 @@ open Gencommon.SourceWriter open Printf open Option open ExtString + module SS = Set.Make(String) let is_boxed_type t = match follow t with @@ -74,6 +73,11 @@ let rec t_has_type_param t = match follow t with | TFun(f,ret) -> t_has_type_param ret || List.exists (fun (_,_,t) -> t_has_type_param t) f | _ -> false +let is_dynamic gen t = + match follow (gen.greal_type t) with + | TDynamic _ -> true + | _ -> false + let is_type_param t = match follow t with | TInst({ cl_kind = KTypeParameter _ }, _) -> true | _ -> false @@ -152,12 +156,11 @@ let is_cl t = match follow t with | TAnon(a) when is_some (anon_class t) -> true | _ -> false + (* ******************************************* *) (* JavaSpecificESynf *) (* ******************************************* *) - (* - Some Java-specific syntax filters that must run before ExpressionUnwrap dependencies: @@ -165,13 +168,10 @@ let is_cl t = match follow t with It must run before ClassInstance, as it will detect expressions that need unchanged TTypeExpr It must run after CastDetect, as it changes casts It must run after TryCatchWrapper, to change Std.is() calls inside there - *) module JavaSpecificESynf = struct - let name = "java_specific_e" - let priority = solve_deps name [ DBefore ExpressionUnwrap.priority; DBefore ClassInstance.priority; DAfter CastDetect.priority; DAfter TryCatchWrapper.priority ] let get_cl_from_t t = @@ -179,7 +179,7 @@ struct | TInst(cl,_) -> cl | _ -> assert false - let traverse gen runtime_cl = + let configure gen runtime_cl = let basic = gen.gcon.basic in let float_cl = get_cl ( get_type gen (["java";"lang"], "Double")) in let i8_md = ( get_type gen (["java";"lang"], "Byte")) in @@ -270,40 +270,49 @@ struct (* end Std.is() *) | _ -> Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map end;; + (* ******************************************* *) (* JavaSpecificSynf *) (* ******************************************* *) - (* - Some Java-specific syntax filters that can run after ExprUnwrap dependencies: Runs after ExprUnwarp - *) - module JavaSpecificSynf = struct - let name = "java_specific" - let priority = solve_deps name [ DAfter ExpressionUnwrap.priority; DAfter ObjectDeclMap.priority; DAfter ArrayDeclSynf.priority; DBefore IntDivisionSynf.priority ] let java_hash s = + let high_surrogate c = (c lsr 10) + 0xD7C0 in + let low_surrogate c = (c land 0x3FF) lor 0xDC00 in let h = ref Int32.zero in let thirtyone = Int32.of_int 31 in - for i = 0 to String.length s - 1 do - h := Int32.add (Int32.mul thirtyone !h) (Int32.of_int (int_of_char (String.unsafe_get s i))); - done; + (try + UTF8.validate s; + UTF8.iter (fun c -> + let c = (UChar.code c) in + if c > 0xFFFF then + (h := Int32.add (Int32.mul thirtyone !h) + (Int32.of_int (high_surrogate c)); + h := Int32.add (Int32.mul thirtyone !h) + (Int32.of_int (low_surrogate c))) + else + h := Int32.add (Int32.mul thirtyone !h) + (Int32.of_int c) + ) s + with UTF8.Malformed_code -> + String.iter (fun c -> + h := Int32.add (Int32.mul thirtyone !h) + (Int32.of_int (Char.code c))) s + ); !h let rec is_final_return_expr is_switch e = @@ -318,8 +327,6 @@ struct | TBlock bl -> is_final_return_block is_switch bl | TSwitch (_, el_e_l, edef) -> List.for_all (fun (_,e) -> is_final_return_expr e) el_e_l && Option.map_default is_final_return_expr false edef -(* | TMatch (_, _, il_vl_e_l, edef) -> - List.for_all (fun (_,_,e) -> is_final_return_expr e)il_vl_e_l && Option.map_default is_final_return_expr false edef *) | TIf (_,eif, Some eelse) -> is_final_return_expr eif && is_final_return_expr eelse | TFor (_,_,e) -> @@ -545,16 +552,19 @@ struct let get_cl_from_t t = match follow t with - | TInst(cl,_) -> cl - | _ -> assert false + | TInst(cl,_) -> cl + | _ -> assert false - let traverse gen runtime_cl = + let configure gen runtime_cl = + (if java_hash "Testing string hashCode implementation from haXe" <> (Int32.of_int 545883604) then assert false); let basic = gen.gcon.basic in (* let tchar = mt_to_t_dyn ( get_type gen (["java"], "Char16") ) in *) (* let tbyte = mt_to_t_dyn ( get_type gen (["java"], "Int8") ) in *) (* let tshort = mt_to_t_dyn ( get_type gen (["java"], "Int16") ) in *) (* let tsingle = mt_to_t_dyn ( get_type gen ([], "Single") ) in *) + let ti64 = mt_to_t_dyn ( get_type gen (["java"], "Int64") ) in let string_ext = get_cl ( get_type gen (["haxe";"lang"], "StringExt")) in + let fast_cast = Common.defined gen.gcon Define.FastCast in let is_string t = match follow t with | TInst({ cl_path = ([], "String") }, []) -> true | _ -> false in @@ -595,7 +605,7 @@ struct (* (* let unboxed_type gen t tbyte tshort tchar tfloat = match follow t with *) *) (* run { e with etype = unboxed_type gen e.etype tbyte tshort tchar tsingle } *) - | TCast(expr, _) when is_bool e.etype -> + | TCast(expr, _) when is_bool e.etype && is_dynamic gen expr.etype -> { eexpr = TCall( mk_static_field_access_infer runtime_cl "toBool" expr.epos [], @@ -605,7 +615,7 @@ struct epos = e.epos } - | TCast(expr, _) when is_int_float gen e.etype && not (is_int_float gen expr.etype) -> + | TCast(expr, _) when is_int_float gen e.etype && is_dynamic gen expr.etype -> let needs_cast = match gen.gfollow#run_f e.etype with | TInst _ -> false | _ -> true @@ -632,8 +642,21 @@ struct | _ -> true in if need_second_cast then { e with eexpr = TCast(mk_cast (follow e.etype) (run expr), c) } else Type.map_expr run e*) + | TCast(expr, _) when like_i64 e.etype && is_dynamic gen expr.etype -> + { + eexpr = TCall( + mk_static_field_access_infer runtime_cl "toLong" expr.epos [], + [ run expr ] + ); + etype = ti64; + epos = expr.epos + } + + | TCast(expr, Some(TClassDecl cls)) when fast_cast && cls == null_class -> + { e with eexpr = TCast(run expr, Some(TClassDecl null_class)) } + | TBinop( (Ast.OpAssignOp OpAdd as op), e1, e2) - | TBinop( (Ast.OpAdd as op), e1, e2) when is_string e.etype || is_string e1.etype || is_string e2.etype -> + | TBinop( (Ast.OpAdd as op), e1, e2) when not fast_cast && (is_string e.etype || is_string e1.etype || is_string e2.etype) -> let is_assign = match op with Ast.OpAssignOp _ -> true | _ -> false in let mk_to_string e = { e with eexpr = TCall( mk_static_field_access_infer runtime_cl "toString" e.epos [], [run e] ); etype = gen.gcon.basic.tstring } in let check_cast e = match gen.greal_type e.etype with @@ -662,11 +685,7 @@ struct { e with eexpr = TBinop(op, mk_cast t_empty (run e1), mk_cast t_empty (run e2)) } | _ -> Type.map_expr run e in - run - - let configure gen (mapping_func:texpr->texpr) = - (if java_hash "Testing string hashCode implementation from haXe" <> (Int32.of_int 545883604) then assert false); - let map e = Some(mapping_func e) in + let map e = Some(run e) in gen.gsyntax_filters#add ~name:name ~priority:(PCustom priority) map end;; @@ -911,7 +930,7 @@ let configure gen = pack ^ "." ^ name | _ -> raise Not_found with Not_found -> match path with - | (ns,clname) -> path_s (change_ns ns, change_clname clname) + | (ns,clname) -> s_type_path (change_ns ns, change_clname clname) in let cl_cl = get_cl (get_type gen (["java";"lang"],"Class")) in @@ -1186,7 +1205,7 @@ let configure gen = fun w p -> () else fun w p -> let cur_line = Lexer.get_error_line p in - let file = Common.get_full_path p.pfile in + let file = Path.get_full_path p.pfile in print w "//line %d \"%s\"" cur_line (Ast.s_escape file); newline w in @@ -1239,18 +1258,10 @@ let configure gen = (match c with | TInt i32 -> print w "%ld" i32; - (match real_type e.etype with - | TType( { t_path = (["java"], "Int64") }, [] ) -> write w "L"; - | _ -> () - ) | TFloat s -> write w s; (* fix for Int notation, which only fit in a Float *) (if not (String.contains s '.' || String.contains s 'e' || String.contains s 'E') then write w ".0"); - (match real_type e.etype with - | TType( { t_path = ([], "Single") }, [] ) -> write w "f" - | _ -> () - ) | TString s -> print w "\"%s\"" (escape s) | TBool b -> write w (if b then "true" else "false") | TNull -> @@ -1526,8 +1537,9 @@ let configure gen = write w "case "; in_value := true; (match e.eexpr with - | TField(_,FEnum(e,ef)) -> - write w ef.ef_name + | TField(_, FEnum(e, ef)) -> + let changed_name = change_id ef.ef_name in + write w changed_name | _ -> expr_s w e); write w ":"; @@ -1685,7 +1697,7 @@ let configure gen = | [] -> acc | _ -> acc) (* TODO | _ -> (sprintf " where %s : %s" name (String.concat ", " (List.map (fun (cl,p) -> path_param_s (TClassDecl cl) cl.cl_path p) cl.cl_implements))) :: acc ) *) - | _ -> trace (t_s Ast.null_pos t); assert false (* FIXME it seems that a cl_params will never be anything other than cl.cl_params. I'll take the risk and fail if not, just to see if that confirms *) + | _ -> trace (t_s null_pos t); assert false (* FIXME it seems that a cl_params will never be anything other than cl.cl_params. I'll take the risk and fail if not, just to see if that confirms *) ) [] cl_params in (params, String.concat " " params_extends) in @@ -1797,7 +1809,7 @@ let configure gen = match meta with | [] -> let expr = match cf.cf_expr with - | None -> mk (TBlock([])) t_dynamic Ast.null_pos + | None -> mk (TBlock([])) t_dynamic null_pos | Some s -> match s.eexpr with | TFunction tf -> @@ -1941,7 +1953,11 @@ let configure gen = | _ -> () with | Not_found -> () ); - write w "main();"; + (match gen.gcon.main with + | Some(expr) -> + expr_s w (mk_block expr) + | None -> + write w "main();"); end_block w; newline w | _ -> () @@ -1994,6 +2010,7 @@ let configure gen = in let module_type_gen w md_tp = + Codegen.map_source_header gen.gcon (fun s -> print w "// %s\n" s); match md_tp with | TClassDecl cl -> if not cl.cl_extern then begin @@ -2015,10 +2032,6 @@ let configure gen = false in - let module_gen w md = - module_type_gen w md - in - (* generate source code *) init_ctx gen; @@ -2033,7 +2046,7 @@ let configure gen = gen.greal_type <- real_type; gen.greal_type_param <- change_param_type; - SetHXGen.run_filter gen SetHXGen.default_hxgen_func; + SetHXGen.run_filter gen; (* before running the filters, follow all possible types *) (* this is needed so our module transformations don't break some core features *) @@ -2056,18 +2069,6 @@ let configure gen = | _ -> () ) gen.gtypes_list; - let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen 6 in - - (*let closure_t = ClosuresToClass.create gen 10 float_cl - (fun l -> l) - (fun l -> l) - (fun args -> args) - (fun args -> []) - in - ClosuresToClass.configure gen (ClosuresToClass.default_implementation closure_t (fun e _ _ -> e)); - - StubClosureImpl.configure gen (StubClosureImpl.default_implementation gen float_cl 10 (fun e _ _ -> e));*) - let get_vmtype t = match real_type t with | TInst({ cl_path = ["java"],"NativeArray" }, tl) -> t | TInst(c,tl) -> TInst(c,List.map (fun _ -> t_dynamic) tl) @@ -2081,13 +2082,14 @@ let configure gen = Normalize.configure gen ~metas:(Hashtbl.create 0); AbstractImplementationFix.configure gen; - IteratorsInterface.configure gen (fun e -> e); + IteratorsInterface.configure gen; - ClosuresToClass.configure gen (ClosuresToClass.default_implementation closure_t (get_cl (get_type gen (["haxe";"lang"],"Function")) )); + let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen (get_cl (get_type gen (["haxe";"lang"],"Function"))) 6 in + ClosuresToClass.configure gen closure_t; let enum_base = (get_cl (get_type gen (["haxe";"lang"],"Enum")) ) in let param_enum_base = (get_cl (get_type gen (["haxe";"lang"],"ParamEnum")) ) in - EnumToClass.configure gen (None) false true enum_base param_enum_base false false; + EnumToClass.configure gen (None) false true enum_base param_enum_base; InterfaceVarsDeleteModf.configure gen; @@ -2095,28 +2097,22 @@ let configure gen = let object_iface = get_cl (get_type gen (["haxe";"lang"],"IHxObject")) in - (*fixme: THIS IS A HACK. take this off *) - let empty_e = match (get_type gen (["haxe";"lang"], "EmptyObject")) with | TEnumDecl e -> e | _ -> assert false in - (*OverloadingCtor.set_new_create_empty gen ({eexpr=TEnumField(empty_e, "EMPTY"); etype=TEnum(empty_e,[]); epos=null_pos;});*) - - let empty_expr = { eexpr = (TTypeExpr (TEnumDecl empty_e)); etype = (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics empty_e) }); epos = null_pos } in - let empty_ef = - try - PMap.find "EMPTY" empty_e.e_constrs - with Not_found -> gen.gcon.error "Required enum field EMPTY was not found" empty_e.e_pos; assert false - in - OverloadingConstructor.configure ~empty_ctor_type:(TEnum(empty_e, [])) ~empty_ctor_expr:({ eexpr=TField(empty_expr, FEnum(empty_e, empty_ef)); etype=TEnum(empty_e,[]); epos=null_pos; }) ~supports_ctor_inheritance:false gen; + let empty_en = match get_type gen (["haxe";"lang"], "EmptyObject") with TEnumDecl e -> e | _ -> assert false in + let empty_ctor_type = TEnum(empty_en, []) in + let empty_en_expr = mk (TTypeExpr (TEnumDecl empty_en)) (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics empty_en) }) null_pos in + let empty_ctor_expr = mk (TField (empty_en_expr, FEnum(empty_en, PMap.find "EMPTY" empty_en.e_constrs))) empty_ctor_type null_pos in + OverloadingConstructor.configure ~empty_ctor_type:empty_ctor_type ~empty_ctor_expr:empty_ctor_expr gen; - let rcf_static_find = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "findHash" Ast.null_pos [] in - (*let rcf_static_lookup = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "lookupHash" Ast.null_pos [] in*) + let rcf_static_find = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "findHash" null_pos [] in + (*let rcf_static_lookup = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "lookupHash" null_pos [] in*) let get_specialized_postfix t = match t with | TAbstract({a_path = [],"Float"}, _) -> "Float" | TInst({cl_path = [],"String"},_) -> "String" | TAnon _ | TDynamic _ -> "Dynamic" | _ -> print_endline (debug_type t); assert false in - let rcf_static_insert t = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("insert" ^ get_specialized_postfix t) Ast.null_pos [] in - let rcf_static_remove t = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("remove" ^ get_specialized_postfix t) Ast.null_pos [] in + let rcf_static_insert t = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("insert" ^ get_specialized_postfix t) null_pos [] in + let rcf_static_remove t = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("remove" ^ get_specialized_postfix t) null_pos [] in let can_be_float t = like_float (real_type t) in @@ -2192,33 +2188,26 @@ let configure gen = let t = gen.gclasses.nativearray_type hash_array.etype in { hash_array with eexpr = TCall(rcf_static_remove t, [hash_array; length; pos]); etype = gen.gcon.basic.tvoid } ) - false + None in - ReflectionCFs.UniversalBaseClass.default_config gen (get_cl (get_type gen (["haxe";"lang"],"HxObject")) ) object_iface dynamic_object; - - ReflectionCFs.configure_dynamic_field_access rcf_ctx false; - - (* let closure_func = ReflectionCFs.implement_closure_cl rcf_ctx ( get_cl (get_type gen (["haxe";"lang"],"Closure")) ) in *) - let closure_cl = get_cl (get_type gen (["haxe";"lang"],"Closure")) in + ReflectionCFs.UniversalBaseClass.configure gen (get_cl (get_type gen (["haxe";"lang"],"HxObject")) ) object_iface dynamic_object; - let closure_func = ReflectionCFs.get_closure_func rcf_ctx closure_cl in + ReflectionCFs.configure_dynamic_field_access rcf_ctx; ReflectionCFs.implement_varargs_cl rcf_ctx ( get_cl (get_type gen (["haxe";"lang"], "VarArgsBase")) ); - let slow_invoke = mk_static_field_access_infer (runtime_cl) "slowCallField" Ast.null_pos [] in + let slow_invoke = mk_static_field_access_infer (runtime_cl) "slowCallField" null_pos [] in ReflectionCFs.configure rcf_ctx ~slow_invoke:(fun ethis efield eargs -> { eexpr = TCall(slow_invoke, [ethis; efield; eargs]); etype = t_dynamic; epos = ethis.epos; } ) object_iface; - let objdecl_fn = ReflectionCFs.implement_dynamic_object_ctor rcf_ctx dynamic_object in + ObjectDeclMap.configure gen (ReflectionCFs.implement_dynamic_object_ctor rcf_ctx dynamic_object); - ObjectDeclMap.configure gen (ObjectDeclMap.traverse gen objdecl_fn); - - InitFunction.configure gen true true; - TArrayTransform.configure gen (TArrayTransform.default_implementation gen ( + InitFunction.configure gen; + TArrayTransform.configure gen ( fun e _ -> match e.eexpr with | TArray ({ eexpr = TLocal { v_extra = Some( _ :: _, _) } }, _) -> (* captured transformation *) @@ -2228,7 +2217,7 @@ let configure gen = | TInst({ cl_path = (["java"], "NativeArray") }, _) -> false | _ -> true ) | _ -> assert false - ) "__get" "__set" ); + ) "__get" "__set"; let field_is_dynamic t field = match field_access_esp gen (gen.greal_type t) field with @@ -2270,7 +2259,7 @@ let configure gen = let is_int t = like_int t in DynamicOperators.configure gen - (DynamicOperators.abstract_implementation gen (fun e -> match e.eexpr with + (fun e -> match e.eexpr with | TBinop (Ast.OpEq, e1, e2) -> is_dynamic e1.etype || is_dynamic e2.etype || is_type_param e1.etype || is_type_param e2.etype | TBinop (Ast.OpAdd, e1, e2) @@ -2333,9 +2322,10 @@ let configure gen = end else begin let static = mk_static_field_access_infer (runtime_cl) "compare" e1.epos [] in { eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos } - end)); + end); - FilterClosures.configure gen (FilterClosures.traverse gen (fun e1 s -> true) closure_func); + let closure_cl = get_cl (get_type gen (["haxe";"lang"],"Closure")) in + FilterClosures.configure gen (fun e1 s -> true) (ReflectionCFs.get_closure_func rcf_ctx closure_cl); let base_exception = get_cl (get_type gen (["java"; "lang"], "Throwable")) in let base_exception_t = TInst(base_exception, []) in @@ -2354,49 +2344,35 @@ let configure gen = in TryCatchWrapper.configure gen - ( - TryCatchWrapper.traverse gen - (fun t -> not (is_exception (real_type t))) - (fun throwexpr expr -> - let wrap_static = mk_static_field_access (hx_exception) "wrap" (TFun([("obj",false,t_dynamic)], hx_exception_t)) expr.epos in - { throwexpr with eexpr = TThrow { expr with eexpr = TCall(wrap_static, [expr]); etype = hx_exception_t }; etype = gen.gcon.basic.tvoid } - ) - (fun v_to_unwrap pos -> - let local = mk_cast hx_exception_t { eexpr = TLocal(v_to_unwrap); etype = v_to_unwrap.v_type; epos = pos } in - mk_field_access gen local "obj" pos - ) - (fun rethrow -> - let wrap_static = mk_static_field_access (hx_exception) "wrap" (TFun([("obj",false,t_dynamic)], hx_exception_t)) rethrow.epos in - { rethrow with eexpr = TThrow { rethrow with eexpr = TCall(wrap_static, [rethrow]); etype = hx_exception_t }; } - ) - (base_exception_t) - (hx_exception_t) - (fun v e -> - - let exc_cl = get_cl (get_type gen (["haxe";"lang"],"Exceptions")) in - let exc_field = mk_static_field_access_infer exc_cl "setException" e.epos [] in - let esetstack = { eexpr = TCall(exc_field,[mk_local v e.epos]); etype = gen.gcon.basic.tvoid; epos = e.epos } in - - Type.concat esetstack e; - ) - ); - - let get_typeof e = - { e with eexpr = TCall( { eexpr = TLocal( alloc_var "__typeof__" t_dynamic ); etype = t_dynamic; epos = e.epos }, [e] ) } - in + (fun t -> not (is_exception (real_type t))) + (fun throwexpr expr -> + let wrap_static = mk_static_field_access (hx_exception) "wrap" (TFun([("obj",false,t_dynamic)], hx_exception_t)) expr.epos in + { throwexpr with eexpr = TThrow { expr with eexpr = TCall(wrap_static, [expr]); etype = hx_exception_t }; etype = gen.gcon.basic.tvoid } + ) + (fun v_to_unwrap pos -> + let local = mk_cast hx_exception_t { eexpr = TLocal(v_to_unwrap); etype = v_to_unwrap.v_type; epos = pos } in + mk_field_access gen local "obj" pos + ) + (fun rethrow -> + let wrap_static = mk_static_field_access (hx_exception) "wrap" (TFun([("obj",false,t_dynamic)], hx_exception_t)) rethrow.epos in + { rethrow with eexpr = TThrow { rethrow with eexpr = TCall(wrap_static, [rethrow]); etype = hx_exception_t }; } + ) + (base_exception_t) + (hx_exception_t) + (fun v e -> - ClassInstance.configure gen (ClassInstance.traverse gen (fun e mt -> get_typeof e)); + let exc_cl = get_cl (get_type gen (["haxe";"lang"],"Exceptions")) in + let exc_field = mk_static_field_access_infer exc_cl "setException" e.epos [] in + let esetstack = { eexpr = TCall(exc_field,[mk_local v e.epos]); etype = gen.gcon.basic.tvoid; epos = e.epos } in - (*let v = alloc_var "$type_param" t_dynamic in*) - TypeParams.configure gen (fun ecall efield params elist -> - { ecall with eexpr = TCall(efield, elist) } - ); + Type.concat esetstack e; + ); - CastDetect.configure gen (CastDetect.default_implementation gen ~native_string_cast:false (Some (TEnum(empty_e, []))) false); + ClassInstance.configure gen (fun e _ -> { e with eexpr = TCall({ eexpr = TLocal(alloc_var "__typeof__" t_dynamic); etype = t_dynamic; epos = e.epos }, [e]) }); - (*FollowAll.configure gen;*) + CastDetect.configure gen (Some empty_ctor_type) false; - SwitchToIf.configure gen (SwitchToIf.traverse gen (fun e -> + SwitchToIf.configure gen (fun e -> match e.eexpr with | TSwitch(cond, cases, def) -> (match gen.gfollow#run_f cond.etype with @@ -2409,34 +2385,33 @@ let configure gen = | _ -> true ) | _ -> assert false - ) true ); + ); - ExpressionUnwrap.configure gen (ExpressionUnwrap.traverse gen (fun e -> Some { eexpr = TVar(mk_temp gen "expr" e.etype, Some e); etype = gen.gcon.basic.tvoid; epos = e.epos })); + ExpressionUnwrap.configure gen (fun e -> Some { eexpr = TVar(mk_temp gen "expr" e.etype, Some e); etype = gen.gcon.basic.tvoid; epos = e.epos }); UnnecessaryCastsRemoval.configure gen; - IntDivisionSynf.configure gen (IntDivisionSynf.default_implementation gen true); + IntDivisionSynf.configure gen; - UnreachableCodeEliminationSynf.configure gen (UnreachableCodeEliminationSynf.traverse gen false true true true); + UnreachableCodeEliminationSynf.configure gen true; - ArrayDeclSynf.configure gen (ArrayDeclSynf.default_implementation gen native_arr_cl); + ArrayDeclSynf.configure gen native_arr_cl; let goto_special = alloc_var "__goto__" t_dynamic in let label_special = alloc_var "__label__" t_dynamic in - SwitchBreakSynf.configure gen (SwitchBreakSynf.traverse gen + SwitchBreakSynf.configure gen (fun e_loop n api -> - { e_loop with eexpr = TBlock( { eexpr = TCall( mk_local label_special e_loop.epos, [ mk_int gen n e_loop.epos ] ); etype = t_dynamic; epos = e_loop.epos } :: [e_loop] ) }; + { e_loop with eexpr = TBlock( { eexpr = TCall( mk_local label_special e_loop.epos, [ Codegen.ExprBuilder.make_int gen.gcon n e_loop.epos ] ); etype = t_dynamic; epos = e_loop.epos } :: [e_loop] ) }; ) (fun e_break n api -> - { eexpr = TCall( mk_local goto_special e_break.epos, [ mk_int gen n e_break.epos ] ); etype = t_dynamic; epos = e_break.epos } - ) - ); + { eexpr = TCall( mk_local goto_special e_break.epos, [ Codegen.ExprBuilder.make_int gen.gcon n e_break.epos ] ); etype = t_dynamic; epos = e_break.epos } + ); - DefaultArguments.configure gen (DefaultArguments.traverse gen); + DefaultArguments.configure gen; InterfaceMetas.configure gen; - JavaSpecificSynf.configure gen (JavaSpecificSynf.traverse gen runtime_cl); - JavaSpecificESynf.configure gen (JavaSpecificESynf.traverse gen runtime_cl); + JavaSpecificSynf.configure gen runtime_cl; + JavaSpecificESynf.configure gen runtime_cl; (* add native String as a String superclass *) let str_cl = match gen.gcon.basic.tstring with | TInst(cl,_) -> cl | _ -> assert false in @@ -2451,7 +2426,7 @@ let configure gen = (* add resources array *) let res = ref [] in Hashtbl.iter (fun name v -> - res := { eexpr = TConst(TString name); etype = gen.gcon.basic.tstring; epos = Ast.null_pos } :: !res; + res := { eexpr = TConst(TString name); etype = gen.gcon.basic.tstring; epos = null_pos } :: !res; let name = Codegen.escape_res_name name true in let full_path = gen.gcon.file ^ "/src/" ^ name in mkdir_from_path full_path; @@ -2460,23 +2435,30 @@ let configure gen = output_string f v; close_out f; - out_files := (unique_full_path full_path) :: !out_files + out_files := (Path.unique_full_path full_path) :: !out_files ) gen.gcon.resources; (try let c = get_cl (Hashtbl.find gen.gtypes (["haxe"], "Resource")) in let cf = PMap.find "content" c.cl_statics in - cf.cf_expr <- Some ({ eexpr = TArrayDecl(!res); etype = gen.gcon.basic.tarray gen.gcon.basic.tstring; epos = Ast.null_pos }) + cf.cf_expr <- Some ({ eexpr = TArrayDecl(!res); etype = gen.gcon.basic.tarray gen.gcon.basic.tstring; epos = null_pos }) with | Not_found -> ()); run_filters gen; TypeParams.RenameTypeParameters.run gen; - let t = Common.timer "code generation" in - let parts = Str.split_delim (Str.regexp "[\\/]+") gen.gcon.file in mkdir_recursive "" parts; - generate_modules_t gen "java" "src" change_path module_gen out_files; + + let source_dir = gen.gcon.file ^ "/src" in + List.iter (fun md -> + let w = SourceWriter.new_source_writer () in + let should_write = module_type_gen w md in + if should_write then begin + let path = change_path (t_path md) in + write_file gen w (source_dir ^ "/" ^ (String.concat "/" (fst path))) path "java" out_files; + end + ) gen.gtypes_list; if not (Common.defined gen.gcon Define.KeepOldOutput) then clean_files (gen.gcon.file ^ "/src") !out_files gen.gcon.verbose; @@ -2490,9 +2472,7 @@ let configure gen = print_endline cmd; if gen.gcon.run_command cmd <> 0 then failwith "Build failed"; Sys.chdir old_dir; - end; - - t() + end (* end of configure function *) @@ -2529,19 +2509,19 @@ let generate con = let cl_cl = get_cl (get_type gen (["java";"lang"],"Class")) in let basic_fns = [ - mk_class_field "equals" (TFun(["obj",false,t_dynamic], basic.tbool)) true Ast.null_pos (Method MethNormal) []; - mk_class_field "toString" (TFun([], basic.tstring)) true Ast.null_pos (Method MethNormal) []; - mk_class_field "hashCode" (TFun([], basic.tint)) true Ast.null_pos (Method MethNormal) []; - mk_class_field "getClass" (TFun([], (TInst(cl_cl,[t_dynamic])))) true Ast.null_pos (Method MethNormal) []; - mk_class_field "wait" (TFun([], basic.tvoid)) true Ast.null_pos (Method MethNormal) []; - mk_class_field "notify" (TFun([], basic.tvoid)) true Ast.null_pos (Method MethNormal) []; - mk_class_field "notifyAll" (TFun([], basic.tvoid)) true Ast.null_pos (Method MethNormal) []; + mk_class_field "equals" (TFun(["obj",false,t_dynamic], basic.tbool)) true null_pos (Method MethNormal) []; + mk_class_field "toString" (TFun([], basic.tstring)) true null_pos (Method MethNormal) []; + mk_class_field "hashCode" (TFun([], basic.tint)) true null_pos (Method MethNormal) []; + mk_class_field "getClass" (TFun([], (TInst(cl_cl,[t_dynamic])))) true null_pos (Method MethNormal) []; + mk_class_field "wait" (TFun([], basic.tvoid)) true null_pos (Method MethNormal) []; + mk_class_field "notify" (TFun([], basic.tvoid)) true null_pos (Method MethNormal) []; + mk_class_field "notifyAll" (TFun([], basic.tvoid)) true null_pos (Method MethNormal) []; ] in List.iter (fun cf -> gen.gbase_class_fields <- PMap.add cf.cf_name cf gen.gbase_class_fields) basic_fns; (try configure gen - with | TypeNotFound path -> con.error ("Error. Module '" ^ (path_s path) ^ "' is required and was not included in build.") Ast.null_pos); + with | TypeNotFound path -> con.error ("Error. Module '" ^ (s_type_path path) ^ "' is required and was not included in build.") null_pos); debug_mode := false (** Java lib *) @@ -2590,7 +2570,7 @@ let jpath_to_hx (pack,name) = match pack, name with | pack, name -> normalize_pack pack, jname_to_hx name let real_java_path ctx (pack,name) = - path_s (pack, name) + s_type_path (pack, name) let lookup_jclass com path = let path = jpath_to_hx path in @@ -2634,8 +2614,8 @@ let has_tparam name params = List.exists(fun (n,_,_) -> n = name) params let rec convert_arg ctx p arg = match arg with - | TAny | TType (WSuper, _) -> TPType (mk_type_path ctx ([], "Dynamic") []) - | TType (_, jsig) -> TPType (convert_signature ctx p jsig) + | TAny | TType (WSuper, _) -> TPType (mk_type_path ctx ([], "Dynamic") [],null_pos) + | TType (_, jsig) -> TPType (convert_signature ctx p jsig,null_pos) and convert_signature ctx p jsig = match jsig with @@ -2674,7 +2654,7 @@ and convert_signature ctx p jsig = | _ -> assert false in mk_type_path ctx (pack, name ^ "$" ^ String.concat "$" (List.map fst inners)) (List.map (fun param -> convert_arg ctx p param) actual_param) | TObjectInner (pack, inners) -> assert false - | TArray (jsig, _) -> mk_type_path ctx (["java"], "NativeArray") [ TPType (convert_signature ctx p jsig) ] + | TArray (jsig, _) -> mk_type_path ctx (["java"], "NativeArray") [ TPType (convert_signature ctx p jsig,null_pos) ] | TMethod _ -> JReader.error "TMethod cannot be converted directly into Complex Type" | TTypeParameter s -> (match ctx.jtparams with | cur :: others -> @@ -2713,9 +2693,10 @@ let convert_param ctx p parent param = in let constraints = List.map (fun s -> if same_sig parent s then (TObject( (["java";"lang"], "Object"), [])) else s) constraints in { - tp_name = name; + tp_name = name,null_pos; tp_params = []; - tp_constraints = List.map (convert_signature ctx p) constraints; + tp_constraints = List.map (fun t -> convert_signature ctx p t,null_pos) constraints; + tp_meta = []; } let get_type_path ctx ct = match ct with | CTPath p -> p | _ -> assert false @@ -2739,12 +2720,12 @@ let convert_java_enum ctx p pe = (* if List.mem JEnum f.jf_flags then *) match f.jf_vmsignature with | TObject( path, [] ) when path = pe.cpath && List.mem JStatic f.jf_flags && List.mem JFinal f.jf_flags -> - data := { ec_name = f.jf_name; ec_doc = None; ec_meta = []; ec_args = []; ec_pos = p; ec_params = []; ec_type = None; } :: !data; + data := { ec_name = f.jf_name,null_pos; ec_doc = None; ec_meta = []; ec_args = []; ec_pos = p; ec_params = []; ec_type = None; } :: !data; | _ -> () ) pe.cfields; EEnum { - d_name = jname_to_hx (snd pe.cpath); + d_name = jname_to_hx (snd pe.cpath),null_pos; d_doc = None; d_params = []; (* enums never have type parameters *) d_meta = !meta; @@ -2806,15 +2787,15 @@ let convert_java_enum ctx p pe = List.iter (fun jsig -> match convert_signature ctx p jsig with | CTPath path -> - cff_meta := (Meta.Throws, [Ast.EConst (Ast.String (path_s (path.tpackage,path.tname))), p],p) :: !cff_meta + cff_meta := (Meta.Throws, [Ast.EConst (Ast.String (s_type_path (path.tpackage,path.tname))), p],p) :: !cff_meta | _ -> () ) field.jf_throws; let kind = match field.jf_kind with | JKField when !readonly -> - FProp ("default", "null", Some (convert_signature ctx p field.jf_signature), None) + FProp (("default",null_pos), ("null",null_pos), Some (convert_signature ctx p field.jf_signature,null_pos), None) | JKField -> - FVar (Some (convert_signature ctx p field.jf_signature), None) + FVar (Some (convert_signature ctx p field.jf_signature,null_pos), None) | JKMethod -> match field.jf_signature with | TMethod (args, ret) -> @@ -2825,7 +2806,7 @@ let convert_java_enum ctx p pe = let i = ref 0 in let args = List.map (fun s -> incr i; - "param" ^ string_of_int !i, false, Some(convert_signature ctx p s), None + ("param" ^ string_of_int !i,null_pos), false, [], Some(convert_signature ctx p s,null_pos), None ) args in let t = Option.map_default (convert_signature ctx p) (mk_type_path ctx ([], "Void") []) ret in cff_meta := (Meta.Overload, [], p) :: !cff_meta; @@ -2833,15 +2814,17 @@ let convert_java_enum ctx p pe = let types = List.map (function | (name, Some ext, impl) -> { - tp_name = name; + tp_name = name,null_pos; tp_params = []; - tp_constraints = List.map (convert_signature ctx p) (ext :: impl); + tp_constraints = List.map (fun t -> convert_signature ctx p t,null_pos) (ext :: impl); + tp_meta = []; } | (name, None, impl) -> { - tp_name = name; + tp_name = name,null_pos; tp_params = []; - tp_constraints = List.map (convert_signature ctx p) (impl); + tp_constraints = List.map (fun t -> convert_signature ctx p t,null_pos) (impl); + tp_meta = []; } ) field.jf_types in ctx.jtparams <- old_types; @@ -2849,7 +2832,7 @@ let convert_java_enum ctx p pe = FFun ({ f_params = types; f_args = args; - f_type = Some t; + f_type = Some (t,null_pos); f_expr = None }) | _ -> error "Method signature was expected" p @@ -2876,7 +2859,7 @@ let convert_java_enum ctx p pe = Printf.printf "\t%s%sfield %s : %s\n" (if List.mem AStatic !cff_access then "static " else "") (if List.mem AOverride !cff_access then "override " else "") cff_name (s_sig field.jf_signature); { - cff_name = cff_name; + cff_name = cff_name,null_pos; cff_doc = cff_doc; cff_pos = cff_pos; cff_meta = cff_meta; @@ -2938,7 +2921,7 @@ let convert_java_enum ctx p pe = (match jc.csuper with | TObject( (["java";"lang"], "Object"), _ ) -> () | TObject( (["haxe";"lang"], "HxObject"), _ ) -> meta := (Meta.HxGen,[],p) :: !meta - | _ -> flags := HExtends (get_type_path ctx (convert_signature ctx p jc.csuper)) :: !flags + | _ -> flags := HExtends (get_type_path ctx (convert_signature ctx p jc.csuper),null_pos) :: !flags ); List.iter (fun i -> @@ -2946,9 +2929,9 @@ let convert_java_enum ctx p pe = | TObject ( (["haxe";"lang"], "IHxObject"), _ ) -> meta := (Meta.HxGen,[],p) :: !meta | _ -> flags := if !is_interface then - HExtends (get_type_path ctx (convert_signature ctx p i)) :: !flags + HExtends (get_type_path ctx (convert_signature ctx p i),null_pos) :: !flags else - HImplements (get_type_path ctx (convert_signature ctx p i)) :: !flags + HImplements (get_type_path ctx (convert_signature ctx p i),null_pos) :: !flags ) jc.cinterfaces; let fields = ref [] in @@ -2979,7 +2962,7 @@ let convert_java_enum ctx p pe = ) jc.cmethods) in (EClass { - d_name = jname_to_hx (snd jc.cpath); + d_name = jname_to_hx (snd jc.cpath),null_pos; d_doc = None; d_params = List.map (convert_param ctx p jc.cpath) jc.ctypes; d_meta = !meta; @@ -3105,7 +3088,7 @@ let jclass_with_params com cls params = try cinterfaces = List.map (japply_params jparams) cls.cinterfaces; } with Invalid_argument("List.map2") -> - if com.verbose then prerr_endline ("Differing parameters for class: " ^ path_s cls.cpath); + if com.verbose then prerr_endline ("Differing parameters for class: " ^ s_type_path cls.cpath); cls let is_object = function | TObject( (["java";"lang"], "Object"), [] ) -> true | _ -> false @@ -3512,11 +3495,11 @@ let add_java_lib com file std = in match decl with | EClass c -> - EClass { c with d_meta = add_meta c.d_name c.d_meta } + EClass { c with d_meta = add_meta (fst c.d_name) c.d_meta } | EEnum e -> - EEnum { e with d_meta = add_meta e.d_name e.d_meta } + EEnum { e with d_meta = add_meta (fst e.d_name) e.d_meta } | EAbstract a -> - EAbstract { a with d_meta = add_meta a.d_name a.d_meta } + EAbstract { a with d_meta = add_meta (fst a.d_name) a.d_meta } | d -> d in let rec build ctx path p types = @@ -3546,7 +3529,7 @@ let add_java_lib com file std = if is_disallowed_inner then None else begin - if com.verbose then print_endline ("Parsed Java class " ^ (path_s cls.cpath)); + if com.verbose then print_endline ("Parsed Java class " ^ (s_type_path cls.cpath)); let old_types = ctx.jtparams in ctx.jtparams <- cls.ctypes :: ctx.jtparams; @@ -3577,7 +3560,7 @@ let add_java_lib com file std = let ncls = convert_java_class ctx pos { cls with cmethods = smethods; cfields = sfields; cflags = []; csuper = obj; cinterfaces = []; cinner_types = []; ctypes = [] } in match ncls with | EClass c :: imports -> - (EClass { c with d_name = c.d_name ^ "_Statics" }, pos) :: inner @ List.map (fun i -> i,pos) imports + (EClass { c with d_name = (fst c.d_name ^ "_Statics"),snd c.d_name }, pos) :: inner @ List.map (fun i -> i,pos) imports | _ -> assert false with | Not_found -> inner @@ -3586,20 +3569,20 @@ let add_java_lib com file std = List.iter (fun x -> match fst x with | EClass c -> - inner_alias := SS.add c.d_name !inner_alias; + inner_alias := SS.add (fst c.d_name) !inner_alias; | _ -> () ) inner; let alias_list = ref [] in List.iter (fun x -> match x with | (EClass c, pos) -> begin - let parts = String.nsplit c.d_name "_24" in + let parts = String.nsplit (fst c.d_name) "_24" in match parts with | _ :: _ -> let alias_name = String.concat "_" parts in if (not (SS.mem alias_name !inner_alias)) && (not (String.exists (snd path) "_24")) then begin let alias_def = ETypedef { - d_name = alias_name; + d_name = alias_name,null_pos; d_doc = None; d_params = c.d_params; d_meta = []; @@ -3610,13 +3593,13 @@ let add_java_lib com file std = tparams = List.map (fun tp -> TPType (CTPath { tpackage = []; - tname = tp.tp_name; + tname = fst tp.tp_name; tparams = []; tsub = None; - }) + },null_pos) ) c.d_params; - tsub = Some(c.d_name); - }; + tsub = Some(fst c.d_name); + },null_pos; } in inner_alias := SS.add alias_name !inner_alias; alias_list := (alias_def, pos) :: !alias_list; diff --git a/genjs.ml b/src/generators/genjs.ml similarity index 80% rename from genjs.ml rename to src/generators/genjs.ml index 2a23015e..d094edc2 100644 --- a/genjs.ml +++ b/src/generators/genjs.ml @@ -1,31 +1,27 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) +open Globals open Ast open Type open Common -type pos = Ast.pos - type sourcemap = { sources : (string) DynArray.t; sources_hash : (string, int) Hashtbl.t; @@ -37,15 +33,19 @@ type sourcemap = { mutable print_comma : bool; mutable output_last_col : int; mutable output_current_col : int; + mutable current_expr : texpr option; } type ctx = { com : Common.context; buf : Rbuffer.t; + chan : out_channel; packages : (string list,unit) Hashtbl.t; - smap : sourcemap; + smap : sourcemap option; js_modern : bool; js_flatten : bool; + es_version : int; + store_exception_stack : bool; mutable current : tclass; mutable statics : (tclass * string * texpr) list; mutable inits : texpr list; @@ -65,16 +65,15 @@ type object_store = { } let get_exposed ctx path meta = - if not ctx.js_modern then [] - else try + try let (_, args, pos) = Meta.get Meta.Expose meta in (match args with | [ EConst (String s), _ ] -> [s] | [] -> [path] - | _ -> error "Invalid @:expose parameters" pos) + | _ -> abort "Invalid @:expose parameters" pos) with Not_found -> [] -let dot_path = Ast.s_type_path +let dot_path = s_type_path let flat_path (p,s) = (* Replace _ with _$ in paths to prevent name collisions. *) @@ -128,47 +127,20 @@ let ident s = if Hashtbl.mem kwds s then "$" ^ s else s let check_var_declaration v = if Hashtbl.mem kwds2 v.v_name then v.v_name <- "$" ^ v.v_name let anon_field s = if Hashtbl.mem kwds s || not (valid_js_ident s) then "'" ^ s ^ "'" else s -let static_field s = +let static_field c s = match s with - | "length" | "name" -> ".$" ^ s + | "length" | "name" when not c.cl_extern || Meta.has Meta.HxGen c.cl_meta-> ".$" ^ s | s -> field s let has_feature ctx = Common.has_feature ctx.com let add_feature ctx = Common.add_feature ctx.com -let handle_newlines ctx str = - if ctx.com.debug then - let rec loop from = - try begin - let next = String.index_from str from '\n' + 1 in - Rbuffer.add_char ctx.smap.mappings ';'; - ctx.smap.output_last_col <- 0; - ctx.smap.print_comma <- false; - loop next - end with Not_found -> - ctx.smap.output_current_col <- String.length str - from - in - loop 0 - else () +let unsupported p = abort "This expression cannot be compiled to Javascript" p -let spr ctx s = - ctx.separator <- false; - handle_newlines ctx s; - Rbuffer.add_string ctx.buf s -let print ctx = - ctx.separator <- false; - Printf.kprintf (fun s -> begin - handle_newlines ctx s; - Rbuffer.add_string ctx.buf s - end) - -let unsupported p = error "This expression cannot be compiled to Javascript" p - -let add_mapping ctx e = - if not ctx.com.debug || e.epos.pmin < 0 then () else +let add_mapping smap force e = + if e.epos.pmin < 0 then () else let pos = e.epos in - let smap = ctx.smap in let file = try Hashtbl.find smap.sources_hash pos.pfile with Not_found -> @@ -179,8 +151,8 @@ let add_mapping ctx e = in let line, col = Lexer.find_pos pos in let line = line - 1 in - let col = col - 1 in - if smap.source_last_file != file || smap.source_last_line != line || smap.source_last_col != col then begin + if force || smap.source_last_file != file || smap.source_last_line != line || smap.source_last_col != col then begin + smap.current_expr <- Some e; if smap.print_comma then Rbuffer.add_char smap.mappings ',' else @@ -227,13 +199,46 @@ let add_mapping ctx e = smap.output_last_col <- smap.output_current_col end -let write_mappings ctx = +let handle_newlines ctx str = + Option.may (fun smap -> + let rec loop from = + try begin + let next = String.index_from str from '\n' + 1 in + Rbuffer.add_char smap.mappings ';'; + smap.output_last_col <- 0; + smap.output_current_col <- 0; + smap.print_comma <- false; + Option.may (fun e -> add_mapping smap true e) smap.current_expr; + loop next + end with Not_found -> + smap.output_current_col <- smap.output_current_col + (String.length str - from); + in + loop 0 + ) ctx.smap + +let flush ctx = + Rbuffer.output_buffer ctx.chan ctx.buf; + Rbuffer.clear ctx.buf + +let spr ctx s = + ctx.separator <- false; + handle_newlines ctx s; + Rbuffer.add_string ctx.buf s + +let print ctx = + ctx.separator <- false; + Printf.kprintf (fun s -> begin + handle_newlines ctx s; + Rbuffer.add_string ctx.buf s + end) + +let write_mappings ctx smap = let basefile = Filename.basename ctx.com.file in print ctx "\n//# sourceMappingURL=%s.map" basefile; let channel = open_out_bin (ctx.com.file ^ ".map") in - let sources = DynArray.to_list ctx.smap.sources in + let sources = DynArray.to_list smap.sources in let to_url file = - ExtString.String.map (fun c -> if c == '\\' then '/' else c) (Common.get_full_path file) + ExtString.String.map (fun c -> if c == '\\' then '/' else c) (Path.get_full_path file) in output_string channel "{\n"; output_string channel "\"version\":3,\n"; @@ -249,14 +254,14 @@ let write_mappings ctx = end; output_string channel "\"names\":[],\n"; output_string channel "\"mappings\":\""; - Rbuffer.output_buffer channel ctx.smap.mappings; + Rbuffer.output_buffer channel smap.mappings; output_string channel "\"\n"; output_string channel "}"; close_out channel let newline ctx = match Rbuffer.nth ctx.buf (Rbuffer.length ctx.buf - 1) with - | '}' | '{' | ':' when not ctx.separator -> print ctx "\n%s" ctx.tabs + | '}' | '{' | ':' | ';' when not ctx.separator -> print ctx "\n%s" ctx.tabs | _ -> print ctx ";\n%s" ctx.tabs let newprop ctx = @@ -332,15 +337,18 @@ let this ctx = match ctx.in_value with None -> "this" | Some _ -> "$this" let is_dynamic_iterator ctx e = let check x = - has_feature ctx "HxOverrides.iter" && (match follow x.etype with + let rec loop t = match follow t with | TInst ({ cl_path = [],"Array" },_) | TInst ({ cl_kind = KTypeParameter _}, _) | TAnon _ | TDynamic _ | TMono _ -> true + | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> + loop (Abstract.get_underlying_type a tl) | _ -> false - ) + in + has_feature ctx "HxOverrides.iter" && loop x.etype in match e.eexpr with | TField (x,f) when field_name f = "iterator" -> check x @@ -360,7 +368,7 @@ let rec gen_call ctx e el in_value = match e.eexpr , el with | TConst TSuper , params -> (match ctx.current.cl_super with - | None -> error "Missing api.setCurrentClass" e.epos + | None -> abort "Missing api.setCurrentClass" e.epos | Some (c,_) -> print ctx "%s.call(%s" (ctx.type_accessor (TClassDecl c)) (this ctx); List.iter (fun p -> print ctx ","; gen_value ctx p) params; @@ -368,7 +376,7 @@ let rec gen_call ctx e el in_value = ); | TField ({ eexpr = TConst TSuper },f) , params -> (match ctx.current.cl_super with - | None -> error "Missing api.setCurrentClass" e.epos + | None -> abort "Missing api.setCurrentClass" e.epos | Some (c,_) -> let name = field_name f in print ctx "%s.prototype%s.call(%s" (ctx.type_accessor (TClassDecl c)) (field name) (this ctx); @@ -430,6 +438,8 @@ let rec gen_call ctx e el in_value = else match eelse with | [] -> () | e :: _ -> gen_value ctx e) + | TLocal { v_name = "__rethrow__" }, [] -> + spr ctx "throw $hx_rethrow"; | TLocal { v_name = "__resources__" }, [] -> spr ctx "["; concat ctx "," (fun (name,data) -> @@ -461,16 +471,29 @@ let rec gen_call ctx e el in_value = concat ctx "," (gen_value ctx) el; spr ctx ")" +(* + this wraps {} in parenthesis which is required to produce valid js code for field and array access to it. + the case itself is very rare and most probably comes from redundant code fused by the analyzer, + but we still have to support it. +*) +and add_objectdecl_parens e = + let rec loop e = match e.eexpr with + | TCast(e1,None) | TMeta(_,e1) -> loop e1 (* TODO: do we really want to lose these? *) + | TObjectDecl _ -> {e with eexpr = TParenthesis e} + | _ -> e + in + loop e + and gen_expr ctx e = - add_mapping ctx e; - match e.eexpr with + Option.may (fun smap -> add_mapping smap false e) ctx.smap; + (match e.eexpr with | TConst c -> gen_constant ctx e.epos c | TLocal v -> spr ctx (ident v.v_name) - | TArray (e1,{ eexpr = TConst (TString s) }) when valid_js_ident s && (match e1.eexpr with TConst (TInt _|TFloat _) -> false | _ -> true) -> - gen_value ctx e1; - spr ctx (field s) + (*| TArray (e1,{ eexpr = TConst (TString s) }) when valid_js_ident s && (match e1.eexpr with TConst (TInt _|TFloat _) -> false | _ -> true) -> + gen_value ctx (add_objectdecl_parens e1); + spr ctx (field s)*) | TArray (e1,e2) -> - gen_value ctx e1; + gen_value ctx (add_objectdecl_parens e1); spr ctx "["; gen_value ctx e2; spr ctx "]"; @@ -490,10 +513,11 @@ and gen_expr ctx e = print ctx ")"; | TField (x,FClosure (Some ({cl_path=[],"Array"},_), {cf_name="push"})) -> (* see https://github.com/HaxeFoundation/haxe/issues/1997 *) - add_feature ctx "use.$arrayPushClosure"; - print ctx "$arrayPushClosure("; + add_feature ctx "use.$arrayPush"; + add_feature ctx "use.$bind"; + print ctx "$bind("; gen_value ctx x; - print ctx ")" + print ctx ",$arrayPush)" | TField (x,FClosure (_,f)) -> add_feature ctx "use.$bind"; (match x.eexpr with @@ -502,22 +526,26 @@ and gen_expr ctx e = gen_value ctx x; print ctx ","; gen_value ctx x; - print ctx "%s)" (field f.cf_name) + print ctx "%s)" (if Meta.has Meta.SelfCall f.cf_meta then "" else (field f.cf_name)) | _ -> print ctx "($_="; gen_value ctx x; - print ctx ",$bind($_,$_%s))" (field f.cf_name)) + print ctx ",$bind($_,$_%s))" (if Meta.has Meta.SelfCall f.cf_meta then "" else (field f.cf_name))) | TEnumParameter (x,_,i) -> gen_value ctx x; print ctx "[%i]" (i + 2) - | TField ({ eexpr = TConst (TInt _ | TFloat _) } as x,f) -> - gen_expr ctx { e with eexpr = TField(mk (TParenthesis x) x.etype x.epos,f) } | TField (x, (FInstance(_,_,f) | FStatic(_,f) | FAnon(f))) when Meta.has Meta.SelfCall f.cf_meta -> gen_value ctx x; | TField (x,f) -> + let rec skip e = match e.eexpr with + | TCast(e1,None) | TMeta(_,e1) -> skip e1 + | TConst(TInt _ | TFloat _) | TObjectDecl _ -> {e with eexpr = TParenthesis e} + | _ -> e + in + let x = skip x in gen_value ctx x; let name = field_name f in - spr ctx (match f with FStatic _ -> static_field name | FEnum _ | FInstance _ | FAnon _ | FDynamic _ | FClosure _ -> field name) + spr ctx (match f with FStatic(c,_) -> static_field c name | FEnum _ | FInstance _ | FAnon _ | FDynamic _ | FClosure _ -> field name) | TTypeExpr t -> spr ctx (ctx.type_accessor t) | TParenthesis e -> @@ -588,7 +616,7 @@ and gen_expr ctx e = spr ctx "if"; gen_value ctx cond; spr ctx " "; - gen_expr ctx e; + gen_expr ctx (mk_block e); (match eelse with | None -> () | Some e2 -> @@ -597,7 +625,7 @@ and gen_expr ctx e = | _ -> ()); semicolon ctx; spr ctx " else "; - gen_expr ctx e2); + gen_expr ctx (match e2.eexpr with | TIf _ -> e2 | _ -> mk_block e2)); | TUnop (op,Ast.Prefix,e) -> spr ctx (Ast.s_unop op); gen_value ctx e @@ -622,7 +650,7 @@ and gen_expr ctx e = | TObjectDecl fields -> spr ctx "{ "; concat ctx ", " (fun (f,e) -> (match e.eexpr with - | TMeta((Meta.QuotedField,_,_),e) -> print ctx "'%s' : " f; + | TMeta((Meta.QuotedField,_,_),e) -> print ctx "\"%s\" : " (Ast.s_escape f); | _ -> print ctx "%s : " (anon_field f)); gen_value ctx e ) fields; @@ -664,14 +692,47 @@ and gen_expr ctx e = let last = ref false in let else_block = ref false in - if (has_feature ctx "haxe.CallStack.exceptionStack") then begin + if ctx.store_exception_stack then begin newline ctx; print ctx "%s.lastException = %s" (ctx.type_accessor (TClassDecl { null_class with cl_path = ["haxe"],"CallStack" })) vname end; + if (has_feature ctx "js.Lib.rethrow") then begin + let has_rethrow (_,e) = + let rec loop e = match e.eexpr with + | TCall({eexpr = TLocal {v_name = "__rethrow__"}}, []) -> raise Exit + | _ -> Type.iter loop e + in + try (loop e; false) with Exit -> true + in + if List.exists has_rethrow catchs then begin + newline ctx; + print ctx "var $hx_rethrow = %s" vname; + end + end; + if (has_feature ctx "js.Boot.HaxeError") then begin - newline ctx; - print ctx "if (%s instanceof %s) %s = %s.val" vname (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js";"_Boot"],"HaxeError" })) vname vname; + let catch_var_used = + try + List.iter (fun (v,e) -> + match follow v.v_type with + | TDynamic _ -> (* Dynamic catch - unrap if the catch value is used *) + let rec loop e = match e.eexpr with + | TLocal v2 when v2 == v -> raise Exit + | _ -> Type.iter loop e + in + loop e + | _ -> (* not a Dynamic catch - we need to unwrap the error for type-checking *) + raise Exit + ) catchs; + false + with Exit -> + true + in + if catch_var_used then begin + newline ctx; + print ctx "if (%s instanceof %s) %s = %s.val" vname (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js";"_Boot"],"HaxeError" })) vname vname; + end; end; List.iter (fun (v,e) -> @@ -763,7 +824,8 @@ and gen_expr ctx e = gen_expr ctx e1; spr ctx " , "; spr ctx (ctx.type_accessor t); - spr ctx ")" + spr ctx ")"); + Option.may (fun smap -> smap.current_expr <- None) ctx.smap and gen_block_element ?(after=false) ctx e = @@ -787,7 +849,7 @@ and gen_block_element ?(after=false) ctx e = if after then newline ctx and gen_value ctx e = - add_mapping ctx e; + Option.may (fun smap -> add_mapping smap false e) ctx.smap; let assign e = mk (TBinop (Ast.OpAssign, mk (TLocal (match ctx.in_value with None -> assert false | Some v -> v)) t_dynamic e.epos, @@ -796,7 +858,7 @@ and gen_value ctx e = in let value() = let old = ctx.in_value, ctx.in_loop in - let r = alloc_var "$r" t_dynamic in + let r = alloc_var "$r" t_dynamic e.epos in ctx.in_value <- Some r; ctx.in_loop <- false; spr ctx "(function($this) "; @@ -816,7 +878,7 @@ and gen_value ctx e = print ctx "(%s))" (this ctx) ) in - match e.eexpr with + (match e.eexpr with | TConst _ | TLocal _ | TArray _ @@ -879,9 +941,9 @@ and gen_value ctx e = | _ -> cond ) in gen_value ctx cond; - spr ctx "?"; + spr ctx " ? "; gen_value ctx e; - spr ctx ":"; + spr ctx " : "; (match eo with | None -> spr ctx "null" | Some e -> gen_value ctx e); @@ -898,7 +960,9 @@ and gen_value ctx e = gen_expr ctx (mk (TTry (block (assign b), List.map (fun (v,e) -> v, block (assign e)) catchs )) e.etype e.epos); - v() + v()); + Option.may (fun smap -> smap.current_expr <- None) ctx.smap + let generate_package_create ctx (p,_) = let rec loop acc = function @@ -930,9 +994,14 @@ let generate_package_create ctx (p,_) = let check_field_name c f = match f.cf_name with | "prototype" | "__proto__" | "constructor" -> - error ("The field name '" ^ f.cf_name ^ "' is not allowed in JS") (match f.cf_expr with None -> c.cl_pos | Some e -> e.epos); + abort ("The field name '" ^ f.cf_name ^ "' is not allowed in JS") (match f.cf_expr with None -> c.cl_pos | Some e -> e.epos); | _ -> () +(* convert a.b.c to ["a"]["b"]["c"] *) +let path_to_brackets path = + let parts = ExtString.String.nsplit path "." in + "[\"" ^ (String.concat "\"][\"" parts) ^ "\"]" + let gen_class_static_field ctx c f = match f.cf_expr with | None | Some { eexpr = TConst TNull } when not (has_feature ctx "Type.getClassFields") -> @@ -940,16 +1009,16 @@ let gen_class_static_field ctx c f = | None when is_extern_field f -> () | None -> - print ctx "%s%s = null" (s_path ctx c.cl_path) (static_field f.cf_name); + print ctx "%s%s = null" (s_path ctx c.cl_path) (static_field c f.cf_name); newline ctx | Some e -> match e.eexpr with | TFunction _ -> - let path = (s_path ctx c.cl_path) ^ (static_field f.cf_name) in - let dot_path = (dot_path c.cl_path) ^ (static_field f.cf_name) in + let path = (s_path ctx c.cl_path) ^ (static_field c f.cf_name) in + let dot_path = (dot_path c.cl_path) ^ (static_field c f.cf_name) in ctx.id_counter <- 0; print ctx "%s = " path; - (match (get_exposed ctx dot_path f.cf_meta) with [s] -> print ctx "$hx_exports.%s = " s | _ -> ()); + (match (get_exposed ctx dot_path f.cf_meta) with [s] -> print ctx "$hx_exports%s = " (path_to_brackets s) | _ -> ()); gen_value ctx e; newline ctx; | _ -> @@ -990,7 +1059,7 @@ let generate_class ctx c = ctx.current <- c; ctx.id_counter <- 0; (match c.cl_path with - | [],"Function" -> error "This class redefine a native one" c.cl_pos + | [],"Function" -> abort "This class redefine a native one" c.cl_pos | _ -> ()); let p = s_path ctx c.cl_path in let hxClasses = has_feature ctx "Type.resolveClass" in @@ -1002,7 +1071,7 @@ let generate_class ctx c = print ctx "%s = " p else print ctx "%s = $hxClasses[\"%s\"] = " p (dot_path c.cl_path); - (match (get_exposed ctx (dot_path c.cl_path) c.cl_meta) with [s] -> print ctx "$hx_exports.%s = " s | _ -> ()); + (match (get_exposed ctx (dot_path c.cl_path) c.cl_meta) with [s] -> print ctx "$hx_exports%s = " (path_to_brackets s) | _ -> ()); (match c.cl_kind with | KAbstractImpl _ -> (* abstract implementations only contain static members and don't need to have constructor functions *) @@ -1065,7 +1134,7 @@ let generate_class ctx c = | _ when props = [] -> () | Some (csup,_) when Codegen.has_properties csup -> newprop ctx; - let psup = s_path ctx csup.cl_path in + let psup = ctx.type_accessor (TClassDecl csup) in print ctx "__properties__: $extend(%s.prototype.__properties__,{%s})" psup (gen_props props) | _ -> newprop ctx; @@ -1076,7 +1145,8 @@ let generate_class ctx c = print ctx "\n}"; (match c.cl_super with None -> ctx.separator <- true | _ -> print ctx ")"); newline ctx - end + end; + flush ctx let generate_enum ctx e = let p = s_path ctx e.e_path in @@ -1124,15 +1194,17 @@ let generate_enum ctx e = print ctx "%s.__empty_constructs__ = [%s]" p (String.concat "," (List.map (fun s -> Printf.sprintf "%s.%s" p s) ctors_without_args)); newline ctx end; - match Codegen.build_metadata ctx.com (TEnumDecl e) with + begin match Codegen.build_metadata ctx.com (TEnumDecl e) with | None -> () | Some e -> print ctx "%s.__meta__ = " p; gen_expr ctx e; newline ctx + end; + flush ctx let generate_static ctx (c,f,e) = - print ctx "%s%s = " (s_path ctx c.cl_path) (static_field f); + print ctx "%s%s = " (s_path ctx c.cl_path) (static_field c f); gen_value ctx e; newline ctx @@ -1151,7 +1223,7 @@ let generate_require ctx path meta = | [(EConst(String(module_name)),_) ; (EConst(String(object_path)),_)] -> print ctx "%s = require(\"%s\").%s" p module_name object_path | _ -> - error "Unsupported @:jsRequire format" mp); + abort "Unsupported @:jsRequire format" mp); newline ctx @@ -1185,23 +1257,33 @@ let set_current_class ctx c = ctx.current <- c let alloc_ctx com = + let smap = + if com.debug || Common.defined com Define.JsSourceMap then + Some { + source_last_line = 0; + source_last_col = 0; + source_last_file = 0; + print_comma = false; + output_last_col = 0; + output_current_col = 0; + sources = DynArray.create(); + sources_hash = Hashtbl.create 0; + mappings = Rbuffer.create 16; + current_expr = None; + } + else + None + in let ctx = { com = com; buf = Rbuffer.create 16000; + chan = open_out_bin com.file; packages = Hashtbl.create 0; - smap = { - source_last_line = 0; - source_last_col = 0; - source_last_file = 0; - print_comma = false; - output_last_col = 0; - output_current_col = 0; - sources = DynArray.create(); - sources_hash = Hashtbl.create 0; - mappings = Rbuffer.create 16; - }; + smap = smap; js_modern = not (Common.defined com Define.JsClassic); js_flatten = not (Common.defined com Define.JsUnflatten); + es_version = (try int_of_string (Common.defined_value com Define.JsEs) with _ -> 0); + store_exception_stack = if Common.has_dce com then (Common.has_feature com "haxe.CallStack.exceptionStack") else List.exists (function TClassDecl { cl_path=["haxe"],"CallStack" } -> true | _ -> false) com.types; statics = []; inits = []; current = null_class; @@ -1232,22 +1314,23 @@ let gen_single_expr ctx e expr = str let generate com = - let t = Common.timer "generate js" in (match com.js_gen with | Some g -> g() | None -> let ctx = alloc_ctx com in - + Codegen.map_source_header com (fun s -> print ctx "// %s\n" s); if has_feature ctx "Class" || has_feature ctx "Type.getClassName" then add_feature ctx "js.Boot.isClass"; if has_feature ctx "Enum" || has_feature ctx "Type.getEnumName" then add_feature ctx "js.Boot.isEnum"; + let nodejs = Common.raw_defined com "nodejs" in + let exposed = List.concat (List.map (fun t -> match t with | TClassDecl c -> let path = dot_path c.cl_path in let class_exposed = get_exposed ctx path c.cl_meta in let static_exposed = List.map (fun f -> - get_exposed ctx (path ^ static_field f.cf_name) f.cf_meta + get_exposed ctx (path ^ static_field c f.cf_name) f.cf_meta ) c.cl_ordered_statics in List.concat (class_exposed :: static_exposed) | _ -> [] @@ -1274,6 +1357,26 @@ let generate com = in loop parts ""; )) exposed; + let include_files = List.rev com.include_files in + + List.iter (fun file -> + match file with + | path, "top" -> + let file_content = Std.input_file ~bin:true (fst file) in + print ctx "%s\n" file_content; + () + | _ -> () + ) include_files; + + let var_console = ( + "console", + "typeof console != \"undefined\" ? console : {log:function(){}}" + ) in + + let var_exports = ( + "$hx_exports", + "typeof exports != \"undefined\" ? exports : typeof window != \"undefined\" ? window : typeof self != \"undefined\" ? self : this" + ) in let var_global = ( "$global", @@ -1287,59 +1390,63 @@ let generate com = closureArgs in let closureArgs = if (anyExposed && not (Common.defined com Define.ShallowExpose)) then - ( - "$hx_exports", - (* TODO(bruno): Remove runtime branching when standard node haxelib is available *) - "typeof window != \"undefined\" ? window : exports" - ) :: closureArgs + var_exports :: closureArgs else closureArgs in (* Provide console for environments that may not have it. *) - let closureArgs = if (not (Common.defined com Define.JsEs5)) then - ( - "console", - "typeof console != \"undefined\" ? console : {log:function(){}}" - ) :: closureArgs + let closureArgs = if ctx.es_version < 5 then + var_console :: closureArgs else closureArgs in - if Common.raw_defined com "nodejs" then + if nodejs then (* Add node globals to pseudo-keywords, so they are not shadowed by local vars *) List.iter (fun s -> Hashtbl.replace kwds2 s ()) [ "global"; "process"; "__filename"; "__dirname"; "module" ]; + if (anyExposed && ((Common.defined com Define.ShallowExpose) || not ctx.js_modern)) then ( + print ctx "var %s = %s" (fst var_exports) (snd var_exports); + ctx.separator <- true; + newline ctx + ); + if ctx.js_modern then begin (* Additional ES5 strict mode keywords. *) List.iter (fun s -> Hashtbl.replace kwds s ()) [ "arguments"; "eval" ]; (* Wrap output in a closure *) - if (anyExposed && (Common.defined com Define.ShallowExpose)) then ( - print ctx "var $hx_exports = $hx_exports || {}"; - ctx.separator <- true; - newline ctx - ); print ctx "(function (%s) { \"use strict\"" (String.concat ", " (List.map fst closureArgs)); newline ctx; - let rec print_obj f root = ( - let path = root ^ "." ^ f.os_name in - print ctx "%s = %s || {}" path path; - ctx.separator <- true; - newline ctx; - concat ctx ";" (fun g -> print_obj g path) f.os_fields - ) - in - List.iter (fun f -> print_obj f "$hx_exports") exposedObject.os_fields; end; + let rec print_obj f root = ( + let path = root ^ (path_to_brackets f.os_name) in + print ctx "%s = %s || {}" path path; + ctx.separator <- true; + newline ctx; + concat ctx ";" (fun g -> print_obj g path) f.os_fields + ) + in + List.iter (fun f -> print_obj f "$hx_exports") exposedObject.os_fields; + + List.iter (fun file -> + match file with + | path, "closure" -> + let file_content = Std.input_file ~bin:true (fst file) in + print ctx "%s\n" file_content; + () + | _ -> () + ) include_files; + (* If ctx.js_modern, console is defined in closureArgs. *) - if (not ctx.js_modern) && (not (Common.defined com Define.JsEs5)) then + if (not ctx.js_modern) && (ctx.es_version < 5) then add_feature ctx "js.Lib.global"; (* console polyfill will check console from $global *) if (not ctx.js_modern) && (has_feature ctx "js.Lib.global") then print ctx "var %s = %s;\n" (fst var_global) (snd var_global); - if (not ctx.js_modern) && (not (Common.defined com Define.JsEs5)) then + if (not ctx.js_modern) && (ctx.es_version < 5) then spr ctx "var console = $global.console || {log:function(){}};\n"; (* TODO: fix $estr *) @@ -1386,10 +1493,8 @@ let generate com = print ctx "function $bind(o,m) { if( m == null ) return null; if( m.__id__ == null ) m.__id__ = $fid++; var f; if( o.hx__closures__ == null ) o.hx__closures__ = {}; else f = o.hx__closures__[m.__id__]; if( f == null ) { f = function(){ return f.method.apply(f.scope, arguments); }; f.scope = o; f.method = m; o.hx__closures__[m.__id__] = f; } return f; }"; newline ctx; end; - if has_feature ctx "use.$arrayPushClosure" then begin - print ctx "function $arrayPushClosure(a) {"; - print ctx " return function(x) { a.push(x); }; "; - print ctx "}"; + if has_feature ctx "use.$arrayPush" then begin + print ctx "function $arrayPush(x) { this.push(x); }"; newline ctx end; List.iter (gen_block_element ~after:true ctx) (List.rev ctx.inits); @@ -1400,22 +1505,24 @@ let generate com = if ctx.js_modern then begin print ctx "})(%s)" (String.concat ", " (List.map snd closureArgs)); newline ctx; - if (anyExposed && (Common.defined com Define.ShallowExpose)) then ( - List.iter (fun f -> - print ctx "var %s = $hx_exports.%s" f.os_name f.os_name; - ctx.separator <- true; - newline ctx - ) exposedObject.os_fields; - List.iter (fun f -> - print ctx "var %s = $hx_exports.%s" f f; - ctx.separator <- true; - newline ctx - ) !toplevelExposed - ); end; - if com.debug then write_mappings ctx else (try Sys.remove (com.file ^ ".map") with _ -> ()); - let ch = open_out_bin com.file in - Rbuffer.output_buffer ch ctx.buf; - close_out ch); - t() + + if (anyExposed && (Common.defined com Define.ShallowExpose)) then ( + List.iter (fun f -> + print ctx "var %s = $hx_exports%s" f.os_name (path_to_brackets f.os_name); + ctx.separator <- true; + newline ctx + ) exposedObject.os_fields; + List.iter (fun f -> + print ctx "var %s = $hx_exports%s" f (path_to_brackets f); + ctx.separator <- true; + newline ctx + ) !toplevelExposed + ); + + (match ctx.smap with + | Some smap -> write_mappings ctx smap + | None -> try Sys.remove (com.file ^ ".map") with _ -> ()); + flush ctx; + close_out ctx.chan) diff --git a/src/generators/genlua.ml b/src/generators/genlua.ml new file mode 100644 index 00000000..4daebe0f --- /dev/null +++ b/src/generators/genlua.ml @@ -0,0 +1,2108 @@ +(* + * Copyright (C)2005-2013 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. + *) + +open Ast +open Type +open Common +open ExtList + +type pos = Globals.pos + +type ctx = { + com : Common.context; + buf : Buffer.t; + packages : (string list,unit) Hashtbl.t; + mutable current : tclass; + mutable statics : (tclass * string * texpr) list; + mutable inits : texpr list; + mutable tabs : string; + mutable in_value : tvar option; + mutable in_loop : bool; + mutable iife_assign : bool; + mutable handle_break : bool; + mutable break_depth : int; + mutable handle_continue : bool; + mutable id_counter : int; + mutable type_accessor : module_type -> string; + mutable separator : bool; + mutable found_expose : bool; + mutable lua_jit : bool; + mutable lua_ver : float; +} + +type object_store = { + os_name : string; + mutable os_fields : object_store list; +} + +let debug_expression expression = + " --[[ " ^ Type.s_expr_kind expression ^ " --]] " + +let debug_type t = + " --[[ " ^ Type.s_type_kind t ^ " --]] ";; + +let get_exposed ctx path meta = try + let (_, args, pos) = Meta.get Meta.Expose meta in + (match args with + | [ EConst (String s), _ ] -> [s] + | [] -> [path] + | _ -> abort "Invalid @:expose parameters" pos) + with Not_found -> [] + +let dot_path = Globals.s_type_path + +let s_path ctx = dot_path + +(* Lua requires decimal encoding for characters, rather than the hex *) +(* provided by Ast.s_escape *) +let s_escape_lua ?(dec=true) s = + let b = Buffer.create (String.length s) in + for i = 0 to (String.length s) - 1 do + match s.[i] with + | '\n' -> Buffer.add_string b "\\n" + | '\t' -> Buffer.add_string b "\\t" + | '\r' -> Buffer.add_string b "\\r" + | '"' -> Buffer.add_string b "\\\"" + | '\\' -> Buffer.add_string b "\\\\" + | c when int_of_char c < 32 && dec -> + Buffer.add_string b (Printf.sprintf "\\%.3d" (int_of_char c)) + | c -> Buffer.add_char b c + done; + Buffer.contents b + +(* TODO: are all these kwds necessary for field quotes *and* id escapes? *) +let kwds = + let h = Hashtbl.create 0 in + List.iter (fun s -> Hashtbl.add h s ()) [ + "_G"; ""; "and"; "break"; "do"; "else"; "elseif"; + "end"; "false"; "for"; "function"; "if"; + "in"; "local"; "nil"; "not"; "or"; "repeat"; + "return"; "then"; "true"; "until"; "while"; + "goto"; "self"; + ]; + h + +let valid_lua_ident s = + try + for i = 0 to String.length s - 1 do + match String.unsafe_get s i with + | 'a'..'z' | 'A'..'Z' | '_' -> () + | '0'..'9' when i > 0 -> () + | _ -> raise Exit + done; + true + with Exit -> + false + +let field s = if Hashtbl.mem kwds s || not (valid_lua_ident s) then "[\"" ^ s ^ "\"]" else "." ^ s +let ident s = if Hashtbl.mem kwds s then "_" ^ s else s + +let anon_field s = if Hashtbl.mem kwds s || not (valid_lua_ident s) then "['" ^ (s_escape_lua s) ^ "']" else s +let static_field c s = + match s with + | "length" | "name" when not c.cl_extern || Meta.has Meta.HxGen c.cl_meta-> "._hx" ^ s + | s -> field s + +let has_feature ctx = Common.has_feature ctx.com +let add_feature ctx = Common.add_feature ctx.com + +let temp ctx = + ctx.id_counter <- ctx.id_counter + 1; + "_hx_" ^ string_of_int (ctx.id_counter) + +let spr ctx s = + ctx.separator <- false; + Buffer.add_string ctx.buf s + +let print ctx = + ctx.separator <- false; + Printf.kprintf (fun s -> begin + Buffer.add_string ctx.buf s + end) + +let newline ctx = print ctx "\n%s" ctx.tabs + +(* print with newline *) +let println ctx = + ctx.separator <- false; + Printf.kprintf (fun s -> begin + Buffer.add_string ctx.buf s; + newline ctx + end) + +let unsupported p = abort "This expression cannot be compiled to Lua" p + +let basename path = + try + let idx = String.rindex path '/' in + String.sub path (idx + 1) (String.length path - idx - 1) + with Not_found -> path + +(* TODO : is this necessary any more?*) +let newprop ctx = + match Buffer.nth ctx.buf (Buffer.length ctx.buf - 1) with + | '{' -> print ctx "\n%s" ctx.tabs + | _ -> print ctx "\n%s" ctx.tabs + +let semicolon ctx = + match Buffer.nth ctx.buf (Buffer.length ctx.buf - 1) with + | '}' when not ctx.separator -> () + | _ -> spr ctx ";" + +let rec concat ctx s f = function + | [] -> () + | [x] -> f x + | x :: l -> + f x; + spr ctx s; + concat ctx s f l + +let fun_block ctx f p = + let e = List.fold_left (fun e (a,c) -> + match c with + | None | Some TNull -> e + | Some c -> Type.concat (Codegen.set_default ctx.com a c p) e + ) f.tf_expr f.tf_args in + e + +let open_block ctx = + let oldt = ctx.tabs in + ctx.tabs <- " " ^ ctx.tabs; + (fun() -> ctx.tabs <- oldt) + +let rec iter_switch_break in_switch e = + match e.eexpr with + | TFunction _ | TWhile _ | TFor _ -> () + | TSwitch _ when not in_switch -> iter_switch_break true e + | TBreak when in_switch -> raise Exit + | _ -> iter (iter_switch_break in_switch) e + +let handle_break ctx e = + (* TODO: This got messy. Find a way to unify the implementation with a try/catch helper at least *) + let old = ctx.in_loop, ctx.handle_break in + ctx.in_loop <- true; + try + iter_switch_break false e; + ctx.handle_break <- false; + (fun() -> + ctx.in_loop <- fst old; + ctx.handle_break <- snd old; + ) + with + Exit -> + println ctx "local _hx_expected_result = {}"; + println ctx "local _hx_status, _hx_result = pcall(function() "; + let b = open_block ctx in + newline ctx; + ctx.handle_break <- true; + (fun() -> + b(); + ctx.in_loop <- fst old; + ctx.handle_break <- snd old; + newline ctx; + println ctx "end"; + println ctx " return _hx_expected_result end)"; + spr ctx " if not _hx_status then "; + newline ctx; + println ctx " elseif _hx_result ~= _hx_expected_result then return _hx_result"; + ) + +let this ctx = match ctx.in_value with None -> "self" | Some _ -> "self" + +let is_dynamic_iterator ctx e = + let check x = + has_feature ctx "HxOverrides.iter" && (match follow x.etype with + | TInst ({ cl_path = [],"Array" },_) + | TInst ({ cl_kind = KTypeParameter _}, _) + | TAnon _ + | TDynamic _ + | TMono _ -> + true + | _ -> false + ) + in + match e.eexpr with + | TField (x,f) when field_name f = "iterator" -> check x + | _ -> + false + +(* + return index of a first element in the list for which `f` returns true + TODO: is there some standard function to do that? + *) +let index_of f l = + let rec find lst idx = + match lst with + | [] -> raise Not_found + | el :: rest -> + if f el then + idx + else + find rest (idx + 1) + in + find l 0 + +(* create a __lua__ call *) +let mk_lua_code com code args t pos = + let lua_local = Codegen.ExprBuilder.make_local (alloc_var "__lua__" t_dynamic pos) pos in + let code_const = Codegen.ExprBuilder.make_string com code pos in + mk (TCall (lua_local, code_const :: args)) t pos + +(* create a multi-return boxing call for given expr *) +let mk_mr_box ctx e = + let s_fields = + match follow e.etype with + | TInst (c,_) -> + String.concat ", " (List.map (fun f -> "\"" ^ f.cf_name ^ "\"") c.cl_ordered_fields) + | _ -> assert false + in + add_feature ctx "use._hx_box_mr"; + add_feature ctx "use._hx_table"; + let code = Printf.sprintf "_hx_box_mr(_hx_table.pack({0}), {%s})" s_fields in + mk_lua_code ctx.com code [e] e.etype e.epos + +(* create a multi-return select call for given expr and field name *) +let mk_mr_select com e name = + let i = + match follow e.etype with + | TInst (c,_) -> + index_of (fun f -> f.cf_name = name) c.cl_ordered_fields + | _ -> + assert false + in + if i == 0 then + e + else + let code = Printf.sprintf "_G.select(%i, {0})" (i + 1) in + mk_lua_code com code [e] e.etype e.epos + +(* from genphp *) +let rec is_string_type t = + match follow t with + | TInst ({cl_path = ([], "String")}, _) -> true + | TAnon a -> + (match !(a.a_status) with + | Statics ({cl_path = ([], "String")}) -> true + | _ -> false) + | TAbstract (a,pl) -> is_string_type (Abstract.get_underlying_type a pl) + | _ -> false + +let is_string_expr e = is_string_type e.etype +(* /from genphp *) + +let rec is_int_type ctx t = + match follow t with + | TInst ({cl_path = ([], "Int")}, _) -> true + | TAnon a -> + (match !(a.a_status) with + | Statics ({cl_path = ([], "Int")}) -> true + | _ -> false) + | TAbstract ({a_path = ([],"Float")}, pl) -> false + | TAbstract ({a_path = ([],"Int")}, pl) -> true + | TAbstract (a,pl) -> is_int_type ctx (Abstract.get_underlying_type a pl) + | _ -> false + +let rec extract_expr e = match e.eexpr with + | TParenthesis e + | TMeta (_,e) + | TCast(e,_) -> extract_expr e + | _ -> e + +let gen_constant ctx p = function + | TInt i -> print ctx "%ld" i + | TFloat s -> spr ctx s + | TString s -> begin + add_feature ctx "use.string"; + print ctx "\"%s\"" (s_escape_lua s) + end + | TBool b -> spr ctx (if b then "true" else "false") + | TNull -> spr ctx "nil" + | TThis -> spr ctx (this ctx) + | TSuper -> assert false + +let rec gen_call ctx e el in_value = + ctx.iife_assign <- true; + (match e.eexpr , el with + | TConst TSuper , params -> + (match ctx.current.cl_super with + | None -> abort "Missing api.setCurrentClass" e.epos + | Some (c,_) -> + print ctx "%s.super(%s" (ctx.type_accessor (TClassDecl c)) (this ctx); + List.iter (fun p -> print ctx ","; gen_value ctx p) params; + spr ctx ")"; + ); + | TField ({ eexpr = TConst TSuper },f) , params -> + (match ctx.current.cl_super with + | None -> abort "Missing api.setCurrentClass" e.epos + | Some (c,_) -> + let name = field_name f in + print ctx "%s.prototype%s(%s" (ctx.type_accessor (TClassDecl c)) (field name) (this ctx); + List.iter (fun p -> print ctx ","; gen_value ctx p) params; + spr ctx ")"; + ); + | TCall (x,_) , el when (match x.eexpr with TLocal { v_name = "__lua__" } -> false | _ -> true) -> + spr ctx "("; + gen_value ctx e; + spr ctx ")"; + spr ctx "("; + concat ctx "," (gen_value ctx) el; + spr ctx ")"; + | TLocal { v_name = "__new__" }, { eexpr = TConst (TString cl) } :: params -> + print ctx "%s.new(" cl; + concat ctx "," (gen_value ctx) params; + spr ctx ")"; + | TLocal { v_name = "__new__" }, e :: params -> + gen_value ctx e; + spr ctx ".new("; + concat ctx "," (gen_value ctx) params; + spr ctx ")"; + | TLocal { v_name = "__callself__" }, { eexpr = TConst (TString head) } :: { eexpr = TConst (TString tail) } :: el -> + print ctx "%s:%s" head tail; + spr ctx "("; + concat ctx ", " (gen_value ctx) el; + spr ctx ")"; + | TLocal { v_name = "__call__" }, { eexpr = TConst (TString code) } :: el -> + spr ctx code; + spr ctx "("; + concat ctx ", " (gen_value ctx) el; + spr ctx ")"; + | TLocal { v_name = "__lua_length__" }, [e]-> + spr ctx "#"; gen_value ctx e; + | TLocal { v_name = "__lua_table__" }, el -> + let count = ref 0 in + spr ctx "({"; + List.iter (fun e -> + (match e with + | { eexpr = TArrayDecl arr } -> + if (!count > 0 && List.length(arr) > 0) then spr ctx ","; + concat ctx "," (gen_value ctx) arr; + if List.length(arr) > 0 then incr count; + | { eexpr = TObjectDecl fields } -> + if (!count > 0 && List.length(fields) > 0) then spr ctx ","; + concat ctx ", " (fun (f,e) -> + print ctx "%s = " (anon_field f); + gen_value ctx e + ) fields; + if List.length(fields) > 0 then incr count; + | { eexpr = TConst(TNull)} -> () + | _ -> + abort "__lua_table__ only accepts array or anonymous object arguments" e.epos; + )) el; + spr ctx "})"; + | TLocal { v_name = "__lua__" }, [{ eexpr = TConst (TString code) }] -> + spr ctx (String.concat "\n" (ExtString.String.nsplit code "\r\n")) + | TLocal { v_name = "__lua__" }, { eexpr = TConst (TString code); epos = p } :: tl -> + Codegen.interpolate_code ctx.com code tl (spr ctx) (gen_expr ctx) p + | TLocal { v_name = "__type__" }, [o] -> + spr ctx "type("; + gen_value ctx o; + spr ctx ")"; + | TLocal ({v_name = "__define_feature__"}), [_;e] -> + gen_expr ctx e + | TLocal { v_name = "__feature__" }, { eexpr = TConst (TString f) } :: eif :: eelse -> + (if has_feature ctx f then + gen_value ctx eif + else match eelse with + | [] -> () + | e :: _ -> gen_value ctx e) + | TLocal { v_name = "__resources__" }, [] -> + (* TODO: Array declaration helper *) + spr ctx "_hx_tab_array({"; + let count = ref 0 in + concat ctx "," (fun (name,data) -> + if (!count == 0) then spr ctx "[0]="; + spr ctx "{ "; + spr ctx "name = "; + gen_constant ctx e.epos (TString name); + spr ctx ", data = "; + gen_constant ctx e.epos (TString (Codegen.bytes_serialize data)); + spr ctx "}"; + incr count + ) (Hashtbl.fold (fun name data acc -> (name,data) :: acc) ctx.com.resources []); + print ctx "}, %i)" !count; + | TLocal { v_name = "`trace" }, [e;infos] -> + if has_feature ctx "haxe.Log.trace" then begin + let t = (try List.find (fun t -> t_path t = (["haxe"],"Log")) ctx.com.types with _ -> assert false) in + spr ctx (ctx.type_accessor t); + spr ctx ".trace("; + gen_value ctx e; + spr ctx ","; + gen_value ctx infos; + spr ctx ")"; + end else begin + spr ctx "_hx_print("; + gen_value ctx e; + spr ctx ")"; + end + | TField ( { eexpr = TConst(TInt _ | TFloat _| TString _| TBool _) } as e , ((FInstance _ | FAnon _) as ef)), el -> + spr ctx ("("); + gen_value ctx e; + print ctx ("):%s(") (field_name ef); + concat ctx "," (gen_value ctx) el; + spr ctx ")"; + | TField (e, ((FInstance _ | FAnon _ | FDynamic _) as ef)), el -> + let s = (field_name ef) in + if Hashtbl.mem kwds s || not (valid_lua_ident s) then begin + match e.eexpr with + |TNew _-> ( + add_feature ctx "use._hx_apply_self"; + spr ctx "_hx_apply_self("; + gen_value ctx e; + print ctx ",\"%s\"" (field_name ef); + if List.length(el) > 0 then spr ctx ","; + concat ctx "," (gen_value ctx) el; + spr ctx ")"; + ); + |_ -> ( + gen_value ctx e; + print ctx "%s(" (anon_field s); + concat ctx "," (gen_value ctx) (e::el); + spr ctx ")" + ) + end else begin + gen_value ctx e; + print ctx ":%s(" (field_name ef); + concat ctx "," (gen_value ctx) el; + spr ctx ")" + end; + | _ -> + gen_value ctx e; + spr ctx "("; + concat ctx "," (gen_value ctx) el; + spr ctx ")"); + ctx.iife_assign <- false; + +and gen_expr ?(local=true) ctx e = begin + match e.eexpr with + TConst c -> + gen_constant ctx e.epos c; + | TLocal v when v.v_name = "this" -> + spr ctx "self"; + | TLocal v -> spr ctx (ident v.v_name) + | TArray (e1,{ eexpr = TConst (TString s) }) when valid_lua_ident s && (match e1.eexpr with TConst (TInt _|TFloat _) -> false | _ -> true) -> + gen_value ctx e1; + spr ctx (field s) + | TArray (e1,e2) -> + gen_value ctx e1; + spr ctx "["; + gen_value ctx e2; + spr ctx "]"; + | TBinop (op,e1,e2) -> + gen_tbinop ctx op e1 e2; + | TField (x,f) when field_name f = "iterator" && is_dynamic_iterator ctx e -> + add_feature ctx "use._iterator"; + print ctx "_iterator("; + gen_value ctx x; + print ctx ")"; + | TField (x,FClosure (_,f)) -> + add_feature ctx "use._hx_bind"; + (match x.eexpr with + | TConst _ | TLocal _ -> + print ctx "_hx_bind("; + gen_value ctx x; + print ctx ","; + gen_value ctx x; + print ctx "%s)" (if Meta.has Meta.SelfCall f.cf_meta then "" else (field f.cf_name)) + | _ -> + print ctx "(function() local __="; + gen_value ctx x; + print ctx "; return _hx_bind(__,__%s) end)()" (if Meta.has Meta.SelfCall f.cf_meta then "" else (field f.cf_name))) + | TEnumParameter (x,_,i) -> + gen_value ctx x; + print ctx "[%i]" (i + 2) + | TField (x, (FInstance(_,_,f) | FStatic(_,f) | FAnon(f))) when Meta.has Meta.SelfCall f.cf_meta -> + gen_value ctx x; + | TField ({ eexpr = TConst(TInt _ | TFloat _| TString _| TBool _) } as e , ((FInstance _ | FAnon _) as ef)) -> + spr ctx ("("); + gen_value ctx e; + print ctx (").%s") (field_name ef); + | TField ({ eexpr = TConst (TInt _ | TFloat _) } as x,f) -> + gen_expr ctx { e with eexpr = TField(mk (TParenthesis x) x.etype x.epos,f) } + | TField ({ eexpr = TObjectDecl fields }, ef ) -> + spr ctx "(function(x) return x."; + print ctx "%s" (field_name ef); + spr ctx " end )({"; + concat ctx ", " (fun (f,e) -> print ctx "%s = " (anon_field f); gen_value ctx e) fields; + spr ctx "})"; + | TField ({eexpr = TLocal v}, f) when Meta.has Meta.MultiReturn v.v_meta -> + (* field of a multireturn local var is actually just a local var *) + let (_, args, pos) = Meta.get (Meta.Custom ":lua_mr_id") v.v_meta in + (match args with + | [(EConst(String(id)), _)] -> + spr ctx (id ^ "_" ^ (ident v.v_name) ^ "_" ^ (field_name f)); + | _ -> + assert false); + | TField (x,f) -> + gen_value ctx x; + let name = field_name f in + spr ctx (match f with FStatic _ | FEnum _ | FInstance _ | FAnon _ | FDynamic _ | FClosure _ -> field name) + | TTypeExpr t -> + spr ctx (ctx.type_accessor t) + | TParenthesis e -> + spr ctx "("; + gen_value ctx e; + spr ctx ")"; + | TMeta (_,e) -> + gen_expr ctx e + | TReturn eo -> gen_return ctx e eo; + | TBreak -> + if not ctx.in_loop then unsupported e.epos; + if ctx.handle_break then + spr ctx "_G.error(\"_hx__break__\")" + else if ctx.handle_continue then + print ctx "_hx_break_%i = true; break" ctx.break_depth + else + spr ctx "break" (*todo*) + | TContinue -> + if not ctx.in_loop then unsupported e.epos; + spr ctx "break"; + | TBlock el -> + let bend = open_block ctx in + List.iter (gen_block_element ctx) el; + bend(); + newline ctx; + | TFunction f -> + let old = ctx.in_value, ctx.in_loop in + ctx.in_value <- None; + ctx.in_loop <- false; + print ctx "function(%s) " (String.concat "," (List.map ident (List.map arg_name f.tf_args))); + let fblock = fun_block ctx f e.epos in + (match fblock.eexpr with + | TBlock el -> + let bend = open_block ctx in + List.iter (gen_block_element ctx) el; + bend(); + newline ctx; + |_ -> ()); + spr ctx "end"; + ctx.in_value <- fst old; + ctx.in_loop <- snd old; + ctx.separator <- true + | TCall (e,el) -> + gen_call ctx e el false; + | TArrayDecl el -> + spr ctx "_hx_tab_array({"; + let count = ref 0 in + List.iteri (fun i e -> + incr count; + if (i == 0) then spr ctx "[0]=" + else spr ctx ", "; + gen_value ctx e) el; + print ctx " }, %i)" !count; + | TThrow e -> + spr ctx "_G.error("; + gen_value ctx e; + spr ctx ",0)"; + | TVar (v,eo) -> + begin match eo with + | None -> + if local then + spr ctx "local "; + spr ctx (ident v.v_name); + | Some e -> + match e.eexpr with + | TBinop(OpAssign, e1, e2) -> + gen_tbinop ctx OpAssign e1 e2; + if local then + spr ctx " local "; + spr ctx (ident v.v_name); + spr ctx " = "; + gen_value ctx e1; + + | _ when Meta.has Meta.MultiReturn v.v_meta -> + (* multi-return var is generated as several vars for unpacking *) + let id = temp ctx in + let temp_expr = (EConst(String(id)), Globals.null_pos) in + v.v_meta <- (Meta.Custom ":lua_mr_id", [temp_expr], v.v_pos) :: v.v_meta; + let name = ident v.v_name in + let names = + match follow v.v_type with + | TInst (c, _) -> + List.map (fun f -> id ^ "_" ^name ^ "_" ^ f.cf_name) c.cl_ordered_fields + | _ -> + assert false + in + spr ctx "local "; + spr ctx (String.concat ", " names); + spr ctx " = "; + gen_value ctx e; + + | _ -> + if local then + spr ctx "local "; + spr ctx (ident v.v_name); + spr ctx " = "; + + (* + if it was a multi-return var but it was used as a value itself, + we have to box it in an object conforming to a multi-return extern class + *) + let is_boxed_multireturn = Meta.has (Meta.Custom ":lua_mr_box") v.v_meta in + let e = if is_boxed_multireturn then mk_mr_box ctx e else e in + gen_value ctx e; + end + | TNew (c,_,el) -> + (match c.cl_constructor with + | Some cf when Meta.has Meta.SelfCall cf.cf_meta -> + print ctx "%s" (ctx.type_accessor (TClassDecl c)); + | Some cf when Meta.has Meta.Native cf.cf_meta -> + let _, args, mp = Meta.get Meta.Native cf.cf_meta in + (match args with + | [( EConst(String s),_)] -> + print ctx "%s.%s" (ctx.type_accessor (TClassDecl c)) s; + | _ -> + print ctx "%s.new" (ctx.type_accessor (TClassDecl c))); + | _ -> print ctx "%s.new" (ctx.type_accessor (TClassDecl c))); + spr ctx "("; + concat ctx "," (gen_value ctx) el; + spr ctx ")" + | TIf (cond,e,eelse) -> + ctx.iife_assign <- true; + spr ctx "if "; + gen_cond ctx cond; + spr ctx " then "; + let bend = open_block ctx in + gen_block_element ctx e; + bend(); + newline ctx; + (match eelse with + | None -> (); + | Some e2 -> + (match e.eexpr with + | TObjectDecl _ -> ctx.separator <- false + | _ ->()); + spr ctx "else"; + let bend = open_block ctx in + gen_block_element ctx e2; + bend(); + newline ctx); + spr ctx "end"; + ctx.iife_assign <- false; + | TUnop ((Increment|Decrement) as op,unop_flag, e) -> + (* TODO: Refactor this mess *) + println ctx "(function() "; + (match e.eexpr, unop_flag with + | TArray(e1,e2), _ -> + spr ctx "local _hx_idx = "; gen_value ctx e2; semicolon ctx; newline ctx; + spr ctx "local _hx_arr ="; gen_value ctx e1; semicolon ctx; newline ctx; + (match unop_flag with + | Ast.Postfix -> + spr ctx "local _ = _hx_arr[_hx_idx]"; semicolon ctx; newline ctx; + | _ -> ()); + spr ctx "_hx_arr[_hx_idx] = _hx_arr[_hx_idx]"; + | TField(e1,e2), _ -> + spr ctx "local _hx_obj = "; gen_value ctx e1; semicolon ctx; newline ctx; + spr ctx "local _hx_fld = "; + (match e2 with + | FInstance(_,_,fld) + | FStatic(_,fld) + | FAnon fld + | FClosure(_,fld) -> + print ctx "'%s'" fld.cf_name; + | FDynamic name -> + print ctx "'%s'" name; + | FEnum(_,efld) -> + print ctx "'%s'" efld.ef_name); + semicolon ctx; newline ctx; + (match unop_flag with + | Ast.Postfix -> + spr ctx "local _ = _hx_obj[_hx_fld]"; semicolon ctx; newline ctx; + | _ -> ()); + spr ctx "_hx_obj[_hx_fld] = _hx_obj[_hx_fld] "; + | _, Ast.Prefix -> + gen_value ctx e; + spr ctx " = "; + gen_value ctx e; + | _, Ast.Postfix -> + spr ctx "local _ = "; + gen_value ctx e; semicolon ctx; + gen_value ctx e; + spr ctx " = "; + gen_value ctx e); + (match op with + |Increment -> spr ctx " + 1;" + |Decrement -> spr ctx " - 1;" + |_-> print ctx " %s 1;" (Ast.s_unop op)); + newline ctx; + spr ctx " return "; + (match unop_flag, e.eexpr with + | Ast.Postfix, _ -> + spr ctx "_"; + | _, TArray(e1,e2) -> + spr ctx "_hx_arr[_hx_idx]"; + | _, TField(e1,e2) -> + spr ctx "_hx_obj[_hx_fld]"; + | _, _ -> + gen_value ctx e; + ); + semicolon ctx; newline ctx; + spr ctx " end)()"; + | TUnop (Not,unop_flag,e) -> + spr ctx "not "; + gen_value ctx e; + | TUnop (NegBits,unop_flag,e) -> + add_feature ctx "use._bitop"; + spr ctx "_hx_bit.bnot("; + gen_value ctx e; + spr ctx ")"; + | TUnop (op,Ast.Prefix,e) -> + spr ctx (Ast.s_unop op); + gen_value ctx e + | TUnop (op,Ast.Postfix,e) -> + gen_value ctx e; + spr ctx (Ast.s_unop op) + | TWhile (cond,e,Ast.NormalWhile) -> + let handle_break = handle_break ctx e in + let has_continue = has_continue e in + let old_ctx_continue = ctx.handle_continue in + ctx.handle_continue <- has_continue; + if has_continue then + println ctx "local _hx_break_%i = false;" ctx.break_depth; + spr ctx "while "; + gen_cond ctx cond; + let b = open_block ctx in + print ctx " do "; + if has_continue then begin + newline ctx; + (open_block ctx)(); + spr ctx "repeat " + end; + ctx.break_depth <- ctx.break_depth + 1; + gen_block_element ctx e; + newline ctx; + handle_break(); + if has_continue then begin + b(); + newline ctx; + println ctx "until true"; + println ctx "if _hx_break_%i then _hx_break_%i = false; break; end" ctx.break_depth ctx.break_depth; + end; + b(); + spr ctx "end"; + ctx.break_depth <- ctx.break_depth-1; + ctx.handle_continue <- old_ctx_continue; + | TWhile (cond,e,Ast.DoWhile) -> + let handle_break = handle_break ctx e in + let has_continue = has_continue e in + let old_ctx_continue = ctx.handle_continue in + ctx.handle_continue <- has_continue; + println ctx "while true do "; + gen_block_element ctx e; + newline ctx; + if has_continue then + println ctx "local _hx_break_%i = false;" ctx.break_depth; + spr ctx " while "; + gen_cond ctx cond; + let b = open_block ctx in + println ctx " do "; + let b2 = open_block ctx in + if has_continue then begin + newline ctx; + (open_block ctx)(); + spr ctx "repeat " + end; + ctx.break_depth <- ctx.break_depth + 1; + gen_block_element ctx e; + handle_break(); + if has_continue then begin + b2(); + newline ctx; + println ctx "until true"; + println ctx "if _hx_break_%i then _hx_break_%i = false; break; end" ctx.break_depth ctx.break_depth; + end; + b(); + spr ctx "end"; + ctx.break_depth <- ctx.break_depth-1; + ctx.handle_continue <- old_ctx_continue; + | TObjectDecl [] -> + spr ctx "_hx_e()"; + ctx.separator <- true + | TObjectDecl fields -> + spr ctx "_hx_o({__fields__={"; + concat ctx "," (fun (f,e) -> print ctx "%s=" (anon_field f); spr ctx "true") fields; + spr ctx "},"; + concat ctx "," (fun (f,e) -> print ctx "%s=" (anon_field f); gen_value ctx e) fields; + spr ctx "})"; + ctx.separator <- true + | TFor (v,it,e) -> + let handle_break = handle_break ctx e in + let it = ident (match it.eexpr with + | TLocal v -> v.v_name + | _ -> + let name = temp ctx in + print ctx "local %s = " name; + gen_value ctx it; + newline ctx; + name + ) in + print ctx "while( %s:hasNext() ) do" it; + let bend = open_block ctx in + newline ctx; + print ctx "local %s = %s:next();" (ident v.v_name) it; + gen_block_element ctx e; + bend(); + newline ctx; + spr ctx "end"; + handle_break(); + newline ctx; + | TTry (e,catchs) -> + (* TODO: add temp variables *) + println ctx "local _hx_expected_result = {}"; + println ctx "local _hx_status, _hx_result = pcall(function() "; + let b = open_block ctx in + gen_expr ctx e; + let vname = temp ctx in + b(); + println ctx " return _hx_expected_result end)"; + spr ctx " if not _hx_status then "; + let bend = open_block ctx in + newline ctx; + print ctx "local %s = _hx_result" vname; + let last = ref false in + let else_block = ref false in + List.iter (fun (v,e) -> + if !last then () else + let t = (match follow v.v_type with + | TEnum (e,_) -> Some (TEnumDecl e) + | TInst (c,_) -> Some (TClassDecl c) + | TAbstract (a,_) -> Some (TAbstractDecl a) + | TFun _ + | TLazy _ + | TType _ + | TAnon _ -> + assert false + | TMono _ + | TDynamic _ -> + None + ) in + match t with + | None -> + last := true; + if !else_block then print ctx ""; + if vname <> v.v_name then begin + newline ctx; + print ctx "local %s = %s" v.v_name vname; + end; + gen_block_element ctx e; + if !else_block then begin + newline ctx; + print ctx " end "; + end + | Some t -> + if not !else_block then newline ctx; + print ctx "if( %s.__instanceof(%s," (ctx.type_accessor (TClassDecl { null_class with cl_path = ["lua"],"Boot" })) vname; + gen_value ctx (mk (TTypeExpr t) (mk_mono()) e.epos); + spr ctx ") ) then "; + let bend = open_block ctx in + if vname <> v.v_name then begin + newline ctx; + print ctx "local %s = %s" v.v_name vname; + end; + gen_block_element ctx e; + bend(); + newline ctx; + spr ctx "else"; + else_block := true + ) catchs; + if not !last then begin + println ctx " _G.error(%s)" vname; + spr ctx "end"; + end; + bend(); + newline ctx; + print ctx " elseif _hx_result ~= _hx_expected_result then return _hx_result end"; + | TSwitch (e,cases,def) -> + List.iteri (fun cnt (el,e2) -> + if cnt == 0 then spr ctx "if " + else (newline ctx; spr ctx "elseif "); + List.iteri (fun ccnt e3 -> + if ccnt > 0 then spr ctx " or "; + gen_value ctx e; + spr ctx " == "; + gen_value ctx e3; + ) el; + print ctx " then "; + let bend = open_block ctx in + gen_block_element ctx e2; + bend(); + ) cases; + (match def with + | None -> spr ctx " end" + | Some e -> + begin + if (List.length(cases) > 0) then + spr ctx "else"; + let bend = open_block ctx in + bend(); + gen_block_element ctx e; + if (List.length(cases) > 0) then + spr ctx " end"; + end;); + | TCast (e1,Some t) -> + print ctx "%s.__cast(" (ctx.type_accessor (TClassDecl { null_class with cl_path = ["lua"],"Boot" })); + gen_expr ctx e1; + spr ctx " , "; + spr ctx (ctx.type_accessor t); + spr ctx ")" + | TCast (e1,None) -> + gen_value ctx e1; +end; + +(* gen_block_element handles expressions that map to "statements" in lua. *) +(* It handles no-op situations, and ensures that expressions are formatted with newlines *) +and gen_block_element ctx e = + ctx.iife_assign <- false; + begin match e.eexpr with + | TTypeExpr _ | TConst _ | TLocal _ | TFunction _ -> + () + | TCast (e',_) | TParenthesis e' | TMeta (_,e') -> + gen_block_element ctx e' + | TArray (e1,e2) -> + gen_block_element ctx e1; + gen_block_element ctx e2; + | TArrayDecl el | TBlock el -> + List.iter (gen_block_element ctx) el; + (* For plain lua table instantiations, just capture argument operations *) + | TCall({ eexpr = TLocal { v_name = "__lua_table__" }} , el) -> + List.iter(fun x -> gen_block_element ctx x) el + (* make a no-op __define_feature__ expression possible *) + | TCall({eexpr = TLocal ({v_name = "__define_feature__"})}, [_;e]) -> + gen_block_element ctx e + | TObjectDecl fl -> + List.iter (fun (_,e) -> gen_block_element ctx e) fl + | TBinop (op,e1,e2) when op <> Ast.OpAssign -> + newline ctx; + let f () = gen_tbinop ctx op e1 e2 in + gen_iife_assign ctx f; + | TUnop ((Increment|Decrement) as op,_,e) -> + newline ctx; + gen_expr ctx e; + print ctx " = "; + gen_expr ctx e; + (match op with + | Increment -> print ctx " + 1;" + | _ -> print ctx " - 1;" + ) + | TSwitch (e,[],def) -> + (match def with + | None -> () + | Some e -> gen_block_element ctx e) + | TField _ -> + newline ctx; + let f () = gen_expr ctx e in + gen_iife_assign ctx f; + semicolon ctx; + | TCall ({ eexpr = TLocal { v_name = "__feature__" } }, { eexpr = TConst (TString f) } :: eif :: eelse) -> + if has_feature ctx f then + gen_block_element ctx eif + else (match eelse with + | [] -> () + | [e] -> gen_block_element ctx e + | _ -> assert false) + | _ -> + newline ctx; + gen_expr ctx e; + semicolon ctx; + end; + +and gen_value ctx e = + let assign e = + mk (TBinop (Ast.OpAssign, + mk (TLocal (match ctx.in_value with None -> assert false | Some v -> v)) t_dynamic e.epos, + e + )) e.etype e.epos + in + let value() = + let old = ctx.in_value, ctx.in_loop in + let r_id = temp ctx in + let r = alloc_var r_id t_dynamic e.epos in + ctx.in_value <- Some r; + ctx.in_loop <- false; + spr ctx "(function() "; + let b = open_block ctx in + newline ctx; + println ctx "local %s" r_id; + (fun() -> + newline ctx; + spr ctx ("return " ^ r_id); + b(); + newline ctx; + ctx.in_value <- fst old; + ctx.in_loop <- snd old; + spr ctx "end )()" + ) + in + match e.eexpr with + | TBinop (OpAssign, e1, e2) -> + spr ctx "(function() "; + gen_block_element ctx e; + spr ctx " return "; + gen_value ctx e1; + spr ctx " end)()"; + | TConst _ + | TLocal _ + | TArray _ + | TBinop _ + | TField _ + | TEnumParameter _ + | TTypeExpr _ + | TParenthesis _ + | TObjectDecl _ + | TArrayDecl _ + | TNew _ + | TUnop _ + | TFunction _ -> + gen_expr ctx e + | TMeta (_,e1) -> + gen_value ctx e1 + | TCall (e,el) -> + gen_call ctx e el true + | TReturn _ + | TBreak + | TContinue -> + unsupported e.epos + (* TODO: this is just a hack because this specific case is a TestReflect unit test. I don't know how to address this properly + at the moment. - Simon *) + | TCast ({ eexpr = TTypeExpr mt } as e1, None) when (match mt with TClassDecl {cl_path = ([],"Array")} -> false | _ -> true) -> + add_feature ctx "use._hx_staticToInstance"; + spr ctx "_hx_staticToInstance("; + gen_expr ctx e1; + spr ctx ")"; + | TCast (e1, Some t) -> + print ctx "%s.__cast(" (ctx.type_accessor (TClassDecl { null_class with cl_path = ["lua"],"Boot" })); + gen_value ctx e1; + spr ctx " , "; + spr ctx (ctx.type_accessor t); + spr ctx ")" + | TCast (e1, _) -> + gen_value ctx e1 + | TVar _ + | TFor _ + | TWhile _ + | TThrow _ -> + (* value is discarded anyway *) + let v = value() in + gen_expr ctx e; + v() + | TBlock [e] -> + gen_value ctx e + | TBlock el -> + let v = value() in + let rec loop = function + | [] -> + spr ctx "return nil"; + | [e] -> + gen_block_element ctx (assign e); + | e :: l -> + gen_block_element ctx e; + newline ctx; + loop l + in + loop el; + v(); + | TIf (cond,e,eo) -> + let v = value() in + spr ctx "if "; + gen_cond ctx cond; + spr ctx " then "; + gen_block_element ctx (assign e); + let rec gen_elseif ctx e = + (match e with + | None->(); + | Some e2-> + (match e2.eexpr with + | TIf(cond3, e3, eo3) -> + spr ctx " elseif "; + gen_cond ctx cond3; + spr ctx " then "; + gen_block_element ctx (assign e3); + gen_elseif ctx eo3; + | _ -> + spr ctx " else "; + gen_block_element ctx (assign e2); + )); + in + gen_elseif ctx eo; + spr ctx " end"; + v() + | TSwitch (cond,cases,def) -> + let v = value() in + gen_expr ctx (mk (TSwitch (cond, + List.map (fun (e1,e2) -> (e1,assign e2)) cases, + match def with None -> None | Some e -> Some (assign e) + )) e.etype e.epos); + v() + | TTry (b,catchs) -> + let v = value() in + let block e = mk (TBlock [e]) e.etype e.epos in + gen_block_element ctx (mk (TTry (block (assign b), + List.map (fun (v,e) -> v, block (assign e)) catchs + )) e.etype e.epos); + v() + +and is_function_type ctx t = + match t with + | TFun _ -> true + | TMono r -> (match !r with | Some (TFun _) -> true | _ -> false) + | _ -> false; + +and gen_tbinop ctx op e1 e2 = + (match op, e1.eexpr, e2.eexpr with + | Ast.OpAssign, TField(e3, FInstance _), TFunction f -> + gen_expr ctx e1; + spr ctx " = " ; + print ctx "function(%s) " (String.concat "," ("self" :: List.map ident (List.map arg_name f.tf_args))); + let fblock = fun_block ctx f e1.epos in + (match fblock.eexpr with + | TBlock el -> + let rec loop ctx el = (match el with + | [hd] -> (match hd.eexpr with + | TReturn eo -> begin + newline ctx; + gen_return ctx e1 eo; + end; + | _ -> gen_block_element ctx hd); + | hd :: tl -> + gen_block_element ctx hd; + loop ctx tl + |[] ->() + ) in + let bend = open_block ctx in + loop ctx el; + bend(); + newline ctx; + | _ -> gen_value ctx e2); + spr ctx " end" + | Ast.OpAssign, _, _ -> + let iife_assign = ctx.iife_assign in + if iife_assign then spr ctx "(function() "; + (match e1.eexpr, e2.eexpr with + | _, TBinop(OpAssign as op, e3, e4) -> + gen_tbinop ctx op e3 e4; + newline ctx; + gen_value ctx e1; + spr ctx " = "; + gen_value ctx e3; + | TField(e3, FInstance _ ), TField(e4, FClosure _ ) -> + gen_value ctx e1; + print ctx " %s " (Ast.s_binop op); + add_feature ctx "use._hx_funcToField"; + spr ctx "_hx_funcToField("; + gen_value ctx e2; + spr ctx ")"; + | TField(_, FInstance _ ), TLocal t when (is_function_type ctx t.v_type) -> + gen_value ctx e1; + print ctx " %s " (Ast.s_binop op); + add_feature ctx "use._hx_funcToField"; + spr ctx "_hx_funcToField("; + gen_value ctx e2; + spr ctx ")"; + | _ -> + gen_value ctx e1; + print ctx " %s " (Ast.s_binop op); + gen_value ctx e2); + if iife_assign then begin + spr ctx " return "; + gen_value ctx e1; + spr ctx " end)()"; + end; + | Ast.OpAssignOp(op2), TArray(e3,e4), _ -> + (* TODO: Figure out how to rewrite this expression more cleanly *) + println ctx "(function() "; + let idx = alloc_var "idx" e4.etype e4.epos in + let idx_var = mk (TVar( idx , Some(e4))) e4.etype e4.epos in + gen_expr ctx idx_var; + let arr = alloc_var "arr" e3.etype e3.epos in + let arr_var = mk (TVar(arr, Some(e3))) e3.etype e3.epos in + gen_expr ctx arr_var; + newline ctx; + let arr_expr = (mk (TArray( + (mk ( TLocal(arr)) e3.etype e3.epos), + (mk ( TLocal(idx)) e4.etype e4.epos) + )) e3.etype e3.epos) in + spr ctx "arr[idx] = "; + gen_tbinop ctx op2 arr_expr e2; semicolon ctx; newline ctx; + spr ctx "return arr[idx]"; + spr ctx " end)()"; + | Ast.OpAssignOp(op2), TField(e3,e4), _ -> + (* TODO: Figure out how to rewrite this expression more cleanly *) + println ctx "(function() "; + let obj = alloc_var "obj" e3.etype e3.epos in + spr ctx "local fld = "; + (match e4 with + | FInstance(_,_,fld) + | FStatic(_,fld) + | FAnon fld + | FClosure(_,fld) -> + print ctx "'%s'" fld.cf_name; + | FDynamic name -> + print ctx "'%s'" name; + | FEnum(_,efld) -> + print ctx "'%s'" efld.ef_name); + semicolon ctx; newline ctx; + let obj_var = mk (TVar(obj, Some(e3))) e3.etype e3.epos in + gen_expr ctx obj_var; + newline ctx; + let obj_expr = (mk (TField( + (mk ( TLocal(obj)) e3.etype e3.epos), + e4 + )) e3.etype e3.epos) in + spr ctx "obj[fld] = "; + gen_tbinop ctx op2 obj_expr e2; semicolon ctx; newline ctx; + spr ctx "return obj[fld]"; + spr ctx " end)()"; + | Ast.OpAssignOp(op2),_,_ -> + (* TODO: Rewrite expression *) + spr ctx "(function() "; gen_value ctx e1; + spr ctx " = "; gen_tbinop ctx op2 e1 e2; + spr ctx " return "; gen_value ctx e1; + spr ctx " end)()"; + | Ast.OpXor,_,_ | Ast.OpAnd,_,_ | Ast.OpShl,_,_ | Ast.OpShr,_,_ | Ast.OpUShr,_,_ | Ast.OpOr,_,_ -> + gen_bitop ctx op e1 e2; + | Ast.OpMod,_,_ -> + spr ctx "_G.math.fmod("; + gen_expr ctx e1; + spr ctx ", "; + gen_expr ctx e2; + spr ctx ")"; + | Ast.OpAdd,_,_ when (is_string_expr e1 || is_string_expr e2) -> + gen_value ctx e1; + print ctx " .. "; + gen_value ctx e2; + | _ -> begin + (* wrap expressions used in comparisons for lua *) + gen_paren_tbinop ctx e1; + (match op with + | Ast.OpNotEq -> print ctx " ~= "; + | Ast.OpBoolAnd -> print ctx " and "; + | Ast.OpBoolOr -> print ctx " or "; + | _ -> print ctx " %s " (Ast.s_binop op)); + gen_paren_tbinop ctx e2; + end; + ); + +and gen_paren_tbinop ctx e = + let ee = extract_expr e in + match ee.eexpr with + | TBinop _ -> + spr ctx "("; + gen_value ctx ee; + spr ctx ")"; + | _ -> + gen_value ctx ee + +and gen_bitop ctx op e1 e2 = + add_feature ctx "use._bitop"; + print ctx "_hx_bit.%s(" (match op with + | Ast.OpXor -> "bxor" + | Ast.OpAnd -> "band" + | Ast.OpShl -> "lshift" + | Ast.OpShr -> "arshift" + | Ast.OpUShr -> "rshift" + | Ast.OpOr -> "bor" + | _ -> ""); + gen_value ctx e1; + spr ctx ","; + gen_value ctx e2; + spr ctx ")" + +and gen_return ctx e eo = + if ctx.in_value <> None then unsupported e.epos; + (match eo with + | None -> + spr ctx "do return end" + | Some e -> + (match e.eexpr with + | TBinop(OpAssign, e1, e2) -> + gen_expr ctx e; + spr ctx " do return "; + gen_value ctx e1; + spr ctx " end"; + | _ -> + spr ctx "do return "; + gen_value ctx e; + spr ctx " end"); + ) + +and gen_iife_assign ctx f = + spr ctx "(function() return "; + f(); + spr ctx " end)()"; + +and gen_cond ctx cond = + ctx.iife_assign <- true; + gen_value ctx cond; + ctx.iife_assign <- false; + +and has_class ctx c = + has_feature ctx "lua.Boot.getClass" && (c.cl_super <> None || c.cl_ordered_fields <> [] || c.cl_constructor <> None) + +and has_prototype ctx c = + c.cl_super <> None || (has_class ctx c) || List.exists (can_gen_class_field ctx) c.cl_ordered_fields + +and can_gen_class_field ctx = function + | { cf_expr = (None | Some { eexpr = TConst TNull }) } when not (has_feature ctx "Type.getInstanceFields") -> + false + | f -> + not (is_extern_field f) + +and has_continue e = + let rec loop e = match e.eexpr with + | TContinue -> raise Exit + | TWhile(e1,_,_) | TFor(_,e1,_) -> loop e1 (* in theory there could be a continue there. Note that we don't want to recurse into the loop body because we do not care about inner continue expressions *) + | _ -> Type.iter loop e + in + try + loop e; + false; + with Exit -> + true + +let check_multireturn ctx c = + match c with + | _ when Meta.has Meta.MultiReturn c.cl_meta -> + if not c.cl_extern then + abort "MultiReturns must be externs" c.cl_pos + else if List.length c.cl_ordered_statics > 0 then + abort "MultiReturns must not contain static fields" c.cl_pos + else if (List.exists (fun cf -> match cf.cf_kind with Method _ -> true | _-> false) c.cl_ordered_fields) then + abort "MultiReturns must not contain methods" c.cl_pos; + | {cl_super = Some(csup,_)} when Meta.has Meta.MultiReturn csup.cl_meta -> + abort "Cannot extend a MultiReturn" c.cl_pos + | _ -> () + + +let generate_package_create ctx (p,_) = + let rec loop acc = function + | [] -> () + | p :: l when Hashtbl.mem ctx.packages (p :: acc) -> loop (p :: acc) l + | p :: l -> + Hashtbl.add ctx.packages (p :: acc) (); + (match acc with + | [] -> print ctx "local %s = {}" p + | _ -> + let p = String.concat "." (List.rev acc) ^ (field p) in + print ctx "%s = {}" p + ); + ctx.separator <- true; + newline ctx; + loop (p :: acc) l + in + match p with + | [] -> print ctx "local " + | _ -> loop [] p + +let check_field_name c f = + match f.cf_name with + | "prototype" | "__proto__" | "constructor" -> + abort ("The field name '" ^ f.cf_name ^ "' is not allowed in Lua") (match f.cf_expr with None -> c.cl_pos | Some e -> e.epos); + | _ -> () + +(* convert a.b.c to ["a"]["b"]["c"] *) +let path_to_brackets path = + let parts = ExtString.String.nsplit path "." in + "[\"" ^ (String.concat "\"][\"" parts) ^ "\"]" + +let gen_class_static_field ctx c f = + match f.cf_expr with + | None | Some { eexpr = TConst TNull } when not (has_feature ctx "Type.getClassFields") -> + () + | None when is_extern_field f -> + () + | None -> + println ctx "%s%s = nil" (s_path ctx c.cl_path) (field f.cf_name); + | Some e -> + match e.eexpr with + | TFunction _ -> + let path = (s_path ctx c.cl_path) ^ (field f.cf_name) in + let dot_path = (dot_path c.cl_path) ^ (static_field c f.cf_name) in + ctx.id_counter <- 0; + print ctx "%s = " path; + gen_value ctx e; + newline ctx; + (match (get_exposed ctx dot_path f.cf_meta) with [s] -> (print ctx "_hx_exports%s = %s" (path_to_brackets s) path; newline ctx) | _ -> ()); + | _ -> + ctx.statics <- (c,f.cf_name,e) :: ctx.statics + +let gen_class_field ctx c f predelimit = + check_field_name c f; + if predelimit then println ctx ","; + match f.cf_expr with + | None -> + print ctx "'%s', nil" f.cf_name; + | Some e -> + ctx.id_counter <- 0; + (match e.eexpr with + | TFunction f2 -> + let old = ctx.in_value, ctx.in_loop in + ctx.in_value <- None; + ctx.in_loop <- false; + print ctx "'%s', function" f.cf_name; + print ctx "(%s) " (String.concat "," ("self" :: List.map ident (List.map arg_name f2.tf_args))); + let fblock = fun_block ctx f2 e.epos in + (match fblock.eexpr with + | TBlock el -> + let rec loop ctx el = (match el with + | [hd] -> (match hd.eexpr with + | TReturn eo -> begin + newline ctx; + gen_return ctx e eo; + end; + | _ -> gen_block_element ctx hd); + | hd :: tl -> + gen_block_element ctx hd; + loop ctx tl + |[] ->() + ) in + let bend = open_block ctx in + loop ctx el; + bend(); + newline ctx; + |_ -> ()); + spr ctx "end"; + ctx.in_value <- fst old; + ctx.in_loop <- snd old; + ctx.separator <- true; + | _ -> gen_value ctx e) + +let generate_class___name__ ctx c = + if has_feature ctx "lua.Boot.isClass" then begin + let p = s_path ctx c.cl_path in + print ctx "%s.__name__ = " p; + if has_feature ctx "Type.getClassName" then + println ctx "{%s}" (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" (s_escape_lua s)) (fst c.cl_path @ [snd c.cl_path]))) + else + println ctx "true"; + end + +let generate_class ctx c = + ctx.current <- c; + ctx.id_counter <- 0; + (match c.cl_path with + | [],"Function" -> abort "This class redefines a native one" c.cl_pos + | _ -> ()); + let p = s_path ctx c.cl_path in + let hxClasses = has_feature ctx "Type.resolveClass" in + newline ctx; + print ctx "%s.new = " p; + (match c.cl_kind with + | KAbstractImpl _ -> + (* abstract implementations only contain static members and don't need to have constructor functions *) + print ctx "{}"; ctx.separator <- true + | _ -> + (match c.cl_constructor with + | Some { cf_expr = Some e } -> + (match e.eexpr with + | TFunction f -> + let old = ctx.in_value, ctx.in_loop in + ctx.in_value <- None; + ctx.in_loop <- false; + print ctx "function(%s) " (String.concat "," (List.map ident (List.map arg_name f.tf_args))); + let fblock = fun_block ctx f e.epos in + (match fblock.eexpr with + | TBlock el -> + let bend = open_block ctx in + newline ctx; + if not (has_prototype ctx c) then println ctx "local self = _hx_new()" else + println ctx "local self = _hx_new(%s.prototype)" p; + println ctx "%s.super(%s)" p (String.concat "," ("self" :: (List.map ident (List.map arg_name f.tf_args)))); + if p = "String" then println ctx "self = string"; + spr ctx "return self"; + bend(); newline ctx; + spr ctx "end"; newline ctx; + let bend = open_block ctx in + print ctx "%s.super = function(%s) " p (String.concat "," ("self" :: (List.map ident (List.map arg_name f.tf_args)))); + List.iter (gen_block_element ctx) el; + bend(); + newline ctx; + spr ctx "end"; + |_ -> ()); + ctx.in_value <- fst old; + ctx.in_loop <- snd old; + ctx.separator <- true + | _ -> gen_expr ctx e); + | _ -> (print ctx "{}"); ctx.separator <- true) + ); + newline ctx; + + (match (get_exposed ctx (dot_path c.cl_path) c.cl_meta) with [s] -> (print ctx "_hx_exports%s = %s" (path_to_brackets s) p; newline ctx) | _ -> ()); + + if hxClasses then println ctx "_hxClasses[\"%s\"] = %s" (dot_path c.cl_path) p; + generate_class___name__ ctx c; + (match c.cl_implements with + | [] -> () + | l -> + println ctx "%s.__interfaces__ = {%s}" p (String.concat "," (List.map (fun (i,_) -> ctx.type_accessor (TClassDecl i)) l)); + ); + + let gen_props props = + String.concat "," (List.map (fun (p,v) -> p ^"=\""^v^"\"") props) in + let has_property_reflection = + (has_feature ctx "Reflect.getProperty") || (has_feature ctx "Reflect.setProperty") in + + if has_property_reflection then begin + (match Codegen.get_properties c.cl_ordered_statics with + | [] -> () + | props -> println ctx "%s.__properties__ = {%s}" p (gen_props props); + ); + end; + + List.iter (gen_class_static_field ctx c) c.cl_ordered_statics; + + if (has_prototype ctx c) then begin + print ctx "%s.prototype = _hx_a(" p; + let bend = open_block ctx in + newline ctx; + let count = ref 0 in + List.iter (fun f -> if can_gen_class_field ctx f then (gen_class_field ctx c f (!count > 0); incr count;) ) c.cl_ordered_fields; + if (has_class ctx c) then begin + newprop ctx; + if !count > 0 then spr ctx ","; + print ctx "'__class__', %s" p; + incr count; + end; + + if has_property_reflection then begin + let props = Codegen.get_properties c.cl_ordered_fields in + (match c.cl_super with + | _ when props = [] -> () + | _ -> + if !count > 0 then spr ctx ","; + newprop ctx; + print ctx "'__properties__', {%s}" (gen_props props)); + end; + + bend(); newline ctx; + println ctx ")"; + (match c.cl_super with + | None -> () + | Some (csup,_) -> + let psup = ctx.type_accessor (TClassDecl csup) in + println ctx "%s.__super__ = %s" p psup; + println ctx "setmetatable(%s.prototype,{__index=%s.prototype})" p psup; + (* Also use the __properties__ from the super class as the __index metatable *) + if has_property_reflection && Codegen.has_properties csup then + println ctx "setmetatable(%s.prototype.__properties__,{__index=%s.prototype.__properties__})" p psup; + ); + end + +let generate_enum ctx e = + let p = s_path ctx e.e_path in + let ename = List.map (fun s -> Printf.sprintf "\"%s\"" (s_escape_lua s)) (fst e.e_path @ [snd e.e_path]) in + + (* TODO: Unify the _hxClasses declaration *) + if has_feature ctx "Type.resolveEnum" then begin + print ctx "_hxClasses[\"%s\"] = %s" (dot_path e.e_path) p; semicolon ctx; newline ctx; + end; + if has_feature ctx "lua.Boot.isEnum" then begin + print ctx "_hxClasses[\"%s\"] = {" (dot_path e.e_path); + if has_feature ctx "lua.Boot.isEnum" then begin + print ctx " __ename__ = %s," (if has_feature ctx "Type.getEnumName" then "{" ^ String.concat "," ename ^ "}" else "true"); + end; + (* TODO : Come up with a helper function for _hx_tab_array declarations *) + spr ctx " __constructs__ = _hx_tab_array({"; + if ((List.length e.e_names) > 0) then begin + spr ctx "[0]="; + spr ctx (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" s) e.e_names)); + end; + print ctx "},%i)}" (List.length e.e_names); + ctx.separator <- true; + newline ctx; + end; + + if has_feature ctx "Type.resolveEnum" || has_feature ctx "lua.Boot.isEnum" then + print ctx "%s = _hxClasses[\"%s\"];" p (dot_path e.e_path); + + newline ctx; + List.iter (fun n -> + let f = PMap.find n e.e_constrs in + print ctx "%s%s = " p (field f.ef_name); + (match f.ef_type with + | TFun (args,_) -> + let count = List.length args in + let sargs = String.concat "," (List.map (fun (n,_,_) -> ident n) args) in + print ctx "function(%s) local _x = _hx_tab_array({[0]=\"%s\",%d,%s,__enum__=%s}, %i);" sargs f.ef_name f.ef_index sargs p (count + 2); + if has_feature ctx "may_print_enum" then + (* TODO: better namespacing for _estr *) + spr ctx " rawset(_x, 'toString', _estr);"; + spr ctx " return _x; end "; + ctx.separator <- true; + | _ -> + println ctx "_hx_tab_array({[0]=\"%s\",%d,__enum__ = %s},2)" f.ef_name f.ef_index p; + if has_feature ctx "may_print_enum" then begin + println ctx "rawset(%s%s, 'toString', _estr)" p (field f.ef_name); + end; + ); + newline ctx + ) e.e_names; + if has_feature ctx "Type.allEnums" then begin + let ctors_without_args = List.filter (fun s -> + let ef = PMap.find s e.e_constrs in + match follow ef.ef_type with + | TFun _ -> false + | _ -> true + ) e.e_names in + print ctx "%s.__empty_constructs__ = " p; + spr ctx "_hx_tab_array({"; + if (List.length ctors_without_args) > 0 then + begin + spr ctx "[0] = "; + print ctx "%s" (String.concat "," (List.map (fun s -> Printf.sprintf "%s.%s" p s) ctors_without_args)); + end; + println ctx "}, %i)" (List.length ctors_without_args); + end + +let generate_static ctx (c,f,e) = + print ctx "%s%s = " (s_path ctx c.cl_path) (field f); + gen_value ctx e; + newline ctx + +let generate_enumMeta_fields ctx = function + | TEnumDecl e -> begin + let p = s_path ctx e.e_path in + match Codegen.build_metadata ctx.com (TEnumDecl e) with + | None -> () + | Some e -> + print ctx "%s.__meta__ = " p; + gen_expr ctx e; + newline ctx + end + | _ -> () + +let generate_require ctx path meta = + let _, args, mp = Meta.get Meta.LuaRequire meta in + let p = (s_path ctx path) in + + generate_package_create ctx path; + + (match args with + | [(EConst(String(module_name)),_)] -> + print ctx "%s = _G.require(\"%s\")" p module_name + | [(EConst(String(module_name)),_) ; (EConst(String(object_path)),_)] -> + print ctx "%s = _G.require(\"%s\").%s" p module_name object_path + | _ -> + abort "Unsupported @:luaRequire format" mp); + + newline ctx + +let generate_type ctx = function + | TClassDecl c -> + (match c.cl_init with + | None -> () + | Some e -> + ctx.inits <- e :: ctx.inits); + let p = s_path ctx c.cl_path in + (* A special case for Std because we do not want to generate it if it's empty. *) + if p = "Std" && c.cl_ordered_statics = [] then + () + else if not c.cl_extern then + generate_class ctx c + else if Meta.has Meta.LuaRequire c.cl_meta && is_directly_used ctx.com c.cl_meta then + generate_require ctx c.cl_path c.cl_meta + else if Meta.has Meta.InitPackage c.cl_meta then + (match c.cl_path with + | ([],_) -> () + | _ -> generate_package_create ctx c.cl_path); + check_multireturn ctx c; + | TEnumDecl e when e.e_extern -> + if Meta.has Meta.LuaRequire e.e_meta && is_directly_used ctx.com e.e_meta then + generate_require ctx e.e_path e.e_meta; + | TEnumDecl e -> generate_enum ctx e + | TTypeDecl _ | TAbstractDecl _ -> () + +let generate_type_forward ctx = function + | TClassDecl c -> + (match c.cl_init with + | None -> () + | Some e -> + ctx.inits <- e :: ctx.inits); + if not c.cl_extern then begin + generate_package_create ctx c.cl_path; + let p = s_path ctx c.cl_path in + println ctx "%s = _hx_e()" p; + end + | TEnumDecl e when e.e_extern -> + () + | TEnumDecl e -> + generate_package_create ctx e.e_path; + let p = s_path ctx e.e_path in + println ctx "%s = _hx_e()" p; + | TTypeDecl _ | TAbstractDecl _ -> () + +let alloc_ctx com = + let ctx = { + com = com; + buf = Buffer.create 16000; + packages = Hashtbl.create 0; + statics = []; + inits = []; + current = null_class; + tabs = ""; + in_value = None; + iife_assign = false; + in_loop = false; + handle_break = false; + break_depth = 0; + handle_continue = false; + id_counter = 0; + type_accessor = (fun _ -> assert false); + separator = false; + found_expose = false; + lua_jit = Common.defined com Define.LuaJit; + lua_ver = try + float_of_string (PMap.find "lua_ver" com.defines) + with | Not_found -> 5.2; + } in + ctx.type_accessor <- (fun t -> + let p = t_path t in + match t with + | TClassDecl ({ cl_extern = true } as c) when not (Meta.has Meta.LuaRequire c.cl_meta) + -> dot_path p + | TEnumDecl { e_extern = true } + -> dot_path p + | _ -> s_path ctx p); + ctx + + +let transform_multireturn ctx = function + | TClassDecl c -> + let transform_field f = + match f.cf_expr with + | Some e -> + let rec loop e = + let is_multireturn t = + match follow t with + | TInst (c, _) when Meta.has Meta.MultiReturn c.cl_meta -> true + | _ -> false + in + match e.eexpr with + (* + if we found a var declaration initialized by a multi-return call, mark it with @:multiReturn meta, + so it will later be generated as multiple locals unpacking the value + *) + | TVar (v, Some ({ eexpr = TCall _ } as ecall)) when is_multireturn v.v_type -> + v.v_meta <- (Meta.MultiReturn,[],v.v_pos) :: v.v_meta; + let ecall = Type.map_expr loop ecall in + { e with eexpr = TVar (v, Some ecall) } + + (* if we found a field access for the multi-return call, generate select call *) + | TField ({ eexpr = TCall _ } as ecall, f) when is_multireturn ecall.etype -> + let ecall = Type.map_expr loop ecall in + mk_mr_select ctx.com ecall (field_name f) + + (* if we found a multi-return call used as a value, box it *) + | TCall _ when is_multireturn e.etype -> + let e = Type.map_expr loop e in + mk_mr_box ctx e + + (* Don't bother wrapping multireturn function results if we don't use the return values *) + | TBlock el -> + let el2 = List.map (fun x -> + match x.eexpr with + | TCall (e2, el) when is_multireturn x.etype -> + mk (TCall (e2, List.map(fun x-> Type.map_expr loop x) el)) x.etype x.epos + | _ -> loop x) el in + mk (TBlock el2) e.etype e.epos; + + + (* if we found a field access for a multi-return local - that's fine, because it'll be generated as a local var *) + | TField ({ eexpr = TLocal v}, _) when Meta.has Meta.MultiReturn v.v_meta -> + e + | TReturn Some(e2) -> + if is_multireturn e2.etype then + failwith "You cannot return a multireturn type from a haxe function" + else + Type.map_expr loop e; + (* + if we found usage of local var we previously marked with @:multiReturn as a value itself, + remove the @:multiReturn meta and add "box me" meta so it'll be boxed on var initialization + *) + | TLocal v when Meta.has Meta.MultiReturn v.v_meta -> + v.v_meta <- List.filter (fun (m,_,_) -> m <> Meta.MultiReturn) v.v_meta; + v.v_meta <- (Meta.Custom ":lua_mr_box", [], v.v_pos) :: v.v_meta; + e + + | _ -> + Type.map_expr loop e + in + f.cf_expr <- Some (loop e); + | _ -> () + in + List.iter transform_field c.cl_ordered_fields; + List.iter transform_field c.cl_ordered_statics; + Option.may transform_field c.cl_constructor; + | _ -> () + +let generate com = + let ctx = alloc_ctx com in + + Codegen.map_source_header com (fun s -> print ctx "-- %s\n" s); + + if has_feature ctx "Class" || has_feature ctx "Type.getClassName" then add_feature ctx "lua.Boot.isClass"; + if has_feature ctx "Enum" || has_feature ctx "Type.getEnumName" then add_feature ctx "lua.Boot.isEnum"; + + let include_files = List.rev com.include_files in + List.iter (fun file -> + match file with + | path, "top" -> + let file_content = Std.input_file ~bin:true (fst file) in + print ctx "%s\n" file_content; + () + | _ -> () + ) include_files; + + let var_exports = ( + "_hx_exports", + "_hx_exports or {}" + ) in + + let exposed = List.concat (List.map (fun t -> + match t with + | TClassDecl c -> + let path = dot_path c.cl_path in + let class_exposed = get_exposed ctx path c.cl_meta in + let static_exposed = List.map (fun f -> + get_exposed ctx (path ^ static_field c f.cf_name) f.cf_meta + ) c.cl_ordered_statics in + List.concat (class_exposed :: static_exposed) + | _ -> [] + ) com.types) in + let anyExposed = exposed <> [] in + let exportMap = ref (PMap.create String.compare) in + let exposedObject = { os_name = ""; os_fields = [] } in + let toplevelExposed = ref [] in + List.iter (fun path -> ( + let parts = ExtString.String.nsplit path "." in + let rec loop p pre = match p with + | f :: g :: ls -> + let path = match pre with "" -> f | pre -> (pre ^ "." ^ f) in + if not (PMap.exists path !exportMap) then ( + let elts = { os_name = f; os_fields = [] } in + exportMap := PMap.add path elts !exportMap; + let cobject = match pre with "" -> exposedObject | pre -> PMap.find pre !exportMap in + cobject.os_fields <- elts :: cobject.os_fields + ); + loop (g :: ls) path; + | f :: [] when pre = "" -> + toplevelExposed := f :: !toplevelExposed; + | _ -> () + in loop parts ""; + )) exposed; + + + if (anyExposed) then ( + print ctx "local %s = %s" (fst var_exports) (snd var_exports); + ctx.separator <- true; + newline ctx + ); + + let rec print_obj f root = ( + let path = root ^ (path_to_brackets f.os_name) in + print ctx "%s = %s or _hx_e()" path path; + ctx.separator <- true; + newline ctx; + concat ctx ";" (fun g -> print_obj g path) f.os_fields + ) + in + List.iter (fun f -> print_obj f "_hx_exports") exposedObject.os_fields; + + + let vars = [] in + (* let vars = (if has_feature ctx "Type.resolveClass" || has_feature ctx "Type.resolveEnum" then ("_hxClasses = " ^ "{}") :: vars else vars) in *) + let vars = if has_feature ctx "may_print_enum" + then ("_estr = function(self) return " ^ (ctx.type_accessor (TClassDecl { null_class with cl_path = ["lua"],"Boot" })) ^ ".__string_rec(self,''); end") :: vars + else vars in + (match List.rev vars with + | [] -> () + | vl -> + print ctx "local %s" (String.concat ";" vl); + ctx.separator <- true; + newline ctx + ); + + List.iter (generate_type_forward ctx) com.types; newline ctx; + + (* Generate some dummy placeholders for utility libs that may be required*) + println ctx "local _hx_bind, _hx_bit, _hx_staticToInstance, _hx_funcToField, _hx_maxn, _hx_print, _hx_apply_self, _hx_box_mr, _hx_bit_clamp, _hx_table, _hx_bit_raw"; + + List.iter (transform_multireturn ctx) com.types; + List.iter (generate_type ctx) com.types; + + if has_feature ctx "use._bitop" || has_feature ctx "lua.Boot.clamp" then begin + println ctx "_hx_bit_clamp = function(v) "; + println ctx " if v <= 2147483647 and v >= -2147483648 then"; + println ctx " if v > 0 then return _G.math.floor(v)"; + println ctx " else return _G.math.ceil(v)"; + println ctx " end"; + println ctx " end"; + println ctx " if v > 2251798999999999 then v = v*2 end;"; + println ctx " if (v ~= v or math.abs(v) == _G.math.huge) then return nil end"; + println ctx " return _hx_bit.band(v, 2147483647 ) - math.abs(_hx_bit.band(v, 2147483648))"; + println ctx "end"; + println ctx "pcall(require, 'bit')"; (* require this for lua 5.1 *) + println ctx "if bit then"; + println ctx " _hx_bit = bit"; + println ctx "elseif bit32 then"; + println ctx " local _hx_bit_raw = bit32"; + println ctx " _hx_bit = setmetatable({}, { __index = _hx_bit_raw });"; + println ctx " _hx_bit.bnot = function(...) return _hx_bit_clamp(_hx_bit_raw.bnot(...)) end;"; (* lua 5.2 weirdness *) + println ctx " _hx_bit.bxor = function(...) return _hx_bit_clamp(_hx_bit_raw.bxor(...)) end;"; (* lua 5.2 weirdness *) + println ctx "end"; + end; + + (* If we use haxe Strings, patch Lua's string *) + if has_feature ctx "use.string" then begin + println ctx "local _hx_string_mt = _G.getmetatable('');"; + println ctx "String.__oldindex = _hx_string_mt.__index;"; + println ctx "_hx_string_mt.__index = String.__index;"; + println ctx "_hx_string_mt.__add = function(a,b) return Std.string(a)..Std.string(b) end;"; + println ctx "_hx_string_mt.__concat = _hx_string_mt.__add"; + end; + + (* Array is required, always patch it *) + println ctx "_hx_array_mt.__index = Array.prototype"; + newline ctx; + + (* Generate statics *) + List.iter (generate_static ctx) (List.rev ctx.statics); + + (* Localize init variables inside a do-block *) + (* Note: __init__ logic can modify static variables. *) + println ctx "do"; + List.iter (gen_block_element ctx) (List.rev ctx.inits); + newline ctx; + println ctx "end"; + + let rec chk_features e = + if is_dynamic_iterator ctx e then add_feature ctx "use._iterator"; + match e.eexpr with + | TField (_,FClosure _) -> + add_feature ctx "use._hx_bind" + | _ -> + Type.iter chk_features e + in + + List.iter chk_features ctx.inits; + + List.iter (fun (_,_,e) -> chk_features e) ctx.statics; + if has_feature ctx "use._iterator" then begin + add_feature ctx "use._hx_bind"; + println ctx "function _hx_iterator(o) if ( lua.Boot.__instanceof(o, Array) ) then return function() return HxOverrides.iter(o) end elseif (typeof(o.iterator) == 'function') then return _hx_bind(o,o.iterator) else return o.iterator end end"; + end; + + if has_feature ctx "use._hx_bind" then begin + println ctx "_hx_bind = function(o,m)"; + println ctx " if m == nil then return nil end;"; + println ctx " local f;"; + println ctx " if o._hx__closures == nil then"; + println ctx " _G.rawset(o, '_hx__closures', {});"; + println ctx " else "; + println ctx " f = o._hx__closures[m];"; + println ctx " end"; + println ctx " if (f == nil) then"; + println ctx " f = function(...) return m(o, ...) end;"; + println ctx " o._hx__closures[m] = f;"; + println ctx " end"; + println ctx " return f;"; + println ctx "end"; + end; + + if has_feature ctx "use._hx_staticToInstance" then begin + println ctx "_hx_staticToInstance = function (tab)"; + println ctx " return setmetatable({}, {"; + println ctx " __index = function(t,k)"; + println ctx " if type(rawget(tab,k)) == 'function' then "; + println ctx " return function(self,...)"; + println ctx " return rawget(tab,k)(...)"; + println ctx " end"; + println ctx " else"; + println ctx " return rawget(tab,k)"; + println ctx " end"; + println ctx " end"; + println ctx " })"; + println ctx "end"; + end; + + if has_feature ctx "use._hx_funcToField" then begin + println ctx "_hx_funcToField = function(f)"; + println ctx " if type(f) == 'function' then "; + println ctx " return function(self,...) "; + println ctx " return f(...) "; + println ctx " end"; + println ctx " else "; + println ctx " return f"; + println ctx " end"; + println ctx "end"; + end; + + if has_feature ctx "Math.random" then begin + println ctx "_G.math.randomseed(_G.os.time());" + end; + + if has_feature ctx "use._hx_print" then + println ctx "_hx_print = print or (function() end)"; + + if has_feature ctx "use._hx_apply_self" then begin + println ctx "_hx_apply_self = function(self, f, ...)"; + println ctx " return self[f](self,...)"; + println ctx "end"; + end; + + if has_feature ctx "use._hx_box_mr" then begin + println ctx "_hx_box_mr = function(x,nt)"; + println ctx " res = _hx_o({__fields__={}})"; + println ctx " for i,v in ipairs(nt) do"; + println ctx " res[v] = x[i]"; + println ctx " end"; + println ctx " return res"; + println ctx "end"; + end; + + if has_feature ctx "use._hx_table" then begin + println ctx "_hx_table = {}"; + println ctx "_hx_table.pack = _G.table.pack or function(...)"; + println ctx " return {...}"; + println ctx "end"; + println ctx "_hx_table.unpack = _G.table.unpack or _G.unpack"; + println ctx "_hx_table.maxn = _G.table.maxn or function(t)"; + println ctx " local maxn=0;"; + println ctx " for i in pairs(t) do"; + println ctx " maxn=type(i)=='number'and i>maxn and i or maxn"; + println ctx " end"; + println ctx " return maxn"; + println ctx "end;"; + end; + + + List.iter (generate_enumMeta_fields ctx) com.types; + + (match com.main with + | None -> () + | Some e -> gen_expr ctx e; newline ctx); + + println ctx "return _hx_exports"; + + let ch = open_out_bin com.file in + output_string ch (Buffer.contents ctx.buf); + close_out ch + + diff --git a/genneko.ml b/src/generators/genneko.ml similarity index 95% rename from genneko.ml rename to src/generators/genneko.ml index d64ec879..326a3280 100644 --- a/genneko.ml +++ b/src/generators/genneko.ml @@ -1,26 +1,24 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Ast +open Globals open Type open Nast open Common @@ -172,7 +170,7 @@ let gen_constant ctx pe c = if (h land 128 = 0) <> (h land 64 = 0) then raise Exit; int p (Int32.to_int i) with _ -> - if ctx.version < 2 then error "This integer is too big to be compiled to a Neko 31-bit integer. Please use a Float instead" pe; + if ctx.version < 2 then abort "This integer is too big to be compiled to a Neko 31-bit integer. Please use a Float instead" pe; (EConst (Int32 i),p)) | TFloat f -> (EConst (Float f),p) | TString s -> call p (field p (ident p "String") "new") [gen_big_string ctx p s] @@ -238,7 +236,7 @@ and gen_expr ctx e = (match follow e.etype with | TFun (args,_) -> let n = List.length args in - if n > 5 then error "Cannot create closure with more than 5 arguments" e.epos; + if n > 5 then abort "Cannot create closure with more than 5 arguments" e.epos; let tmp = ident p "@tmp" in EBlock [ (EVars ["@tmp", Some (gen_expr ctx e2); "@fun", Some (field p tmp f.cf_name)] , p); @@ -782,8 +780,8 @@ let build ctx types = packs @ methods @ boot :: names @ inits @ vars let generate com = + Hashtbl.clear files; let ctx = new_context com (if Common.defined com Define.NekoV1 then 1 else 2) false in - let t = Common.timer "neko generation" in let libs = (EBlock (generate_libs_init com.neko_libs) , { psource = "
"; pline = 1; }) in let el = build ctx com.types in let emain = (match com.main with None -> [] | Some e -> [gen_expr ctx e]) in @@ -805,7 +803,7 @@ let generate com = else loop (p + 1) in - error msg (loop 0) + abort msg (loop 0) end; let command cmd = try com.run_command cmd with _ -> -1 in let neko_file = (try Filename.chop_extension com.file with _ -> com.file) ^ ".neko" in @@ -819,5 +817,4 @@ let generate com = if command ("nekoc -p \"" ^ neko_file ^ "\"") <> 0 then failwith "Failed to print neko code"; Sys.remove neko_file; Sys.rename ((try Filename.chop_extension com.file with _ -> com.file) ^ "2.neko") neko_file; - end; - t() + end diff --git a/genphp.ml b/src/generators/genphp.ml similarity index 91% rename from genphp.ml rename to src/generators/genphp.ml index 7f7e3404..46f22293 100644 --- a/genphp.ml +++ b/src/generators/genphp.ml @@ -1,28 +1,26 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Ast open Type open Common +open Codegen type method_name = { mutable mpath : path; @@ -71,6 +69,23 @@ type context = { mutable lib_path : string; } +let follow = Abstract.follow_with_abstracts + +(** + Check if specified expression is of `Float` type +*) +let is_float expr = match follow expr.etype with TAbstract ({ a_path = ([], "Float") }, _) -> true | _ -> false + +(** + If `expr` is a TCast or TMeta, then returns underlying expression (recursively bypassing nested casts). + Otherwise returns `expr` as is. +*) +let rec reveal_expr expr = + match expr.eexpr with + | TCast (e, _) -> reveal_expr e + | TMeta (_, e) -> reveal_expr e + | _ -> expr + let join_class_path path separator = let result = match fst path, snd path with | [], s -> s @@ -210,9 +225,9 @@ let rec is_string_type t = let is_string_expr e = is_string_type e.etype let to_string ctx e = - let v = alloc_var "__call__" t_dynamic in + let v = alloc_var "__call__" t_dynamic e.epos in let f = mk (TLocal v) t_dynamic e.epos in - mk (TCall (f, [ Codegen.string ctx.com "_hx_string_rec" e.epos; e; Codegen.string ctx.com "" e.epos])) ctx.com.basic.tstring e.epos + mk (TCall (f, [ ExprBuilder.make_string ctx.com "_hx_string_rec" e.epos; e; ExprBuilder.make_string ctx.com "" e.epos])) ctx.com.basic.tstring e.epos let as_string_expr ctx e = match e.eexpr with @@ -223,9 +238,9 @@ let as_string_expr ctx e = | _ -> e (* for known String type that could have null value *) let to_string_null ctx e = - let v = alloc_var "__call__" t_dynamic in + let v = alloc_var "__call__" t_dynamic e.epos in let f = mk (TLocal v) t_dynamic e.epos in - mk (TCall (f, [ Codegen.string ctx.com "_hx_string_or_null" e.epos; e])) ctx.com.basic.tstring e.epos + mk (TCall (f, [ ExprBuilder.make_string ctx.com "_hx_string_or_null" e.epos; e])) ctx.com.basic.tstring e.epos let as_string_expr ctx e = match e.eexpr with @@ -307,8 +322,11 @@ let is_keyword n = | "include_once" | "isset" | "list" | "namespace" | "print" | "require" | "require_once" | "unset" | "use" | "__function__" | "__class__" | "__method__" | "final" | "php_user_filter" | "protected" | "abstract" | "__set" | "__get" | "__call" - | "clone" | "instanceof" | "break" | "case" | "class" | "continue" | "default" | "do" | "else" | "extends" | "for" | "function" | "if" | "new" | "return" | "static" | "switch" | "var" | "while" | "interface" | "implements" | "public" | "private" | "try" | "catch" | "throw" -> true - | "goto" + | "clone" | "instanceof" | "break" | "case" | "class" | "continue" | "default" + | "do" | "else" | "extends" | "for" | "function" | "if" | "new" | "return" + | "static" | "switch" | "var" | "while" | "interface" | "implements" | "public" + | "private" | "try" | "catch" | "throw" | "goto" | "yield" + -> true | _ -> false let s_ident n = @@ -341,7 +359,7 @@ let write_resource dir name data = close_out ch let stack_init com use_add = - Codegen.stack_context_init com "GLOBALS['%s']" "GLOBALS['%e']" "__hx__spos" "tmp" use_add null_pos + Codegen.stack_context_init com "GLOBALS['%s']" "GLOBALS['%e']" "__hx__spos" "tmp" use_add Globals.null_pos let init com cwd path def_type = let rec create acc = function @@ -361,7 +379,7 @@ let init com cwd path def_type = let ch = open_out (String.concat "/" dir ^ "/" ^ (filename path) ^ (if def_type = 0 then ".class" else if def_type = 1 then ".enum" else if def_type = 2 then ".interface" else ".extern") ^ ".php") in let imports = Hashtbl.create 0 in Hashtbl.add imports (snd path) [fst path]; - { + let ctx = { com = com; stack = stack_init com false; tabs = ""; @@ -390,8 +408,11 @@ let init com cwd path def_type = inline_index = 0; in_block = false; lib_path = match com.php_lib with None -> "lib" | Some s -> s; - } -let unsupported msg p = error ("This expression cannot be generated to PHP: " ^ msg) p + } in + Codegen.map_source_header com (fun s -> print ctx "// %s\n" s); + ctx + +let unsupported msg p = abort ("This expression cannot be generated to PHP: " ^ msg) p let newline ctx = match Buffer.nth ctx.buf (Buffer.length ctx.buf - 1) with @@ -530,7 +551,7 @@ and gen_call ctx e el = spr ctx "]"; genargs t) in - match e.eexpr , el with + match (reveal_expr e).eexpr , el with | TConst TSuper , params -> (match ctx.curclass.cl_super with | None -> assert false @@ -770,21 +791,41 @@ and is_static t = | _ -> false) | _ -> false +and get_constant_prefix meta = + let (_, args, pos) = Meta.get Meta.PhpConstants meta in + (match args with + | [EConst(String prefix), _] -> prefix + | [] -> "" + | _ -> abort "Invalid @:phpConstant parameters" pos) + and gen_member_access ctx isvar e s = match follow e.etype with | TAnon a -> (match !(a.a_status) with | EnumStatics _ -> print ctx "::%s%s" (if isvar then "$" else "") (s_ident s) - | Statics _ -> - print ctx "::%s%s" (if isvar then "$" else "") (s_ident s) + | Statics sta -> + let (sep, no_dollar) = if Meta.has Meta.PhpGlobal sta.cl_meta then + ("", false) + else + match e.eexpr with + | TField _ -> ("->", true) + | _ -> ("::", false) + in + let isconst = Meta.has Meta.PhpConstants sta.cl_meta in + let cprefix = if isconst then get_constant_prefix sta.cl_meta else "" in + print ctx "%s%s%s" sep (if isvar && not isconst && not no_dollar then "$" else cprefix) + (if sta.cl_extern && sep = "" then s else s_ident s) | _ -> print ctx "->%s" (if isvar then s_ident_field s else s_ident s)) | _ -> print ctx "->%s" (if isvar then s_ident_field s else s_ident s) and gen_field_access ctx isvar e s = match e.eexpr with | TTypeExpr t -> - spr ctx (s_path ctx (t_path t) false e.epos); + let isglobal = match t with + | TClassDecl(c) -> Meta.has Meta.PhpGlobal c.cl_meta && c.cl_extern + | _ -> false in + spr ctx (if isglobal then "" else (s_path ctx (t_path t) false e.epos)); gen_member_access ctx isvar e s | TLocal _ -> gen_expr ctx e; @@ -813,6 +854,9 @@ and gen_field_access ctx isvar e s = gen_value ctx e; spr ctx ")"; gen_member_access ctx isvar e s + | TConst TNull -> + spr ctx "_hx_deref(null)"; + gen_member_access ctx isvar e s | _ -> gen_expr ctx e; gen_member_access ctx isvar e s @@ -886,25 +930,32 @@ and gen_inline_function ctx f hasthis p = ctx.in_value <- Some "closure"; let args a = List.map (fun (v,_) -> v.v_name) a in - let arguments = ref [] in - if hasthis then begin arguments := "this" :: !arguments end; + let used_locals = ref PMap.empty in - PMap.iter (fun n _ -> arguments := !arguments @ [n]) old_li; + let rec loop e = match e.eexpr with + | TLocal v when not (start_with v.v_name "__hx__") && PMap.mem v.v_name old_l -> + used_locals := PMap.add v.v_name v.v_name !used_locals + | _ -> + Type.iter loop e + in + loop f.tf_expr; spr ctx "array(new _hx_lambda(array("; let c = ref 0 in - List.iter (fun a -> + let print_arg a = if !c > 0 then spr ctx ", "; incr c; print ctx "&$%s" a; - ) (remove_internals !arguments); + in + if hasthis then print_arg "this"; + PMap.iter (fun _ a -> print_arg a) !used_locals; spr ctx "), \""; - spr ctx (inline_function ctx (args f.tf_args) hasthis (fun_block ctx f p)); + spr ctx (inline_function ctx (args f.tf_args) hasthis !used_locals (fun_block ctx f p)); print ctx "\"), 'execute')"; ctx.in_value <- old; @@ -945,12 +996,13 @@ and gen_while_expr ctx e = ctx.in_loop <- old_loop and gen_tfield ctx e e1 s = + let name = (field_name s) in match follow e.etype with | TFun (args, _) -> (if ctx.is_call then begin - gen_field_access ctx false e1 s - end else if is_in_dynamic_methods ctx e1 s then begin - gen_field_access ctx true e1 s; + gen_field_access ctx false e1 name + end else if is_in_dynamic_methods ctx e1 name then begin + gen_field_access ctx true e1 name; end else begin let ob ex = (match ex with @@ -961,27 +1013,31 @@ and gen_tfield ctx e e1 s = | _ -> gen_expr ctx e1) in - spr ctx "(isset("; - gen_field_access ctx true e1 s; - spr ctx ") ? "; - gen_field_access ctx true e1 s; + spr ctx "(property_exists("; + ob e1.eexpr; + print ctx ", \"%s\") ? " (s_ident name); + gen_field_access ctx true e1 name; spr ctx ": array("; ob e1.eexpr; - print ctx ", \"%s\"))" (s_ident s); + print ctx ", \"%s\"))" (s_ident name); end) | TMono _ -> if ctx.is_call then - gen_field_access ctx false e1 s + gen_field_access ctx false e1 name else - gen_uncertain_string_var ctx s e1 + gen_uncertain_string_var ctx name e1 + | TDynamic _ when not ctx.is_call && (match s with FDynamic _ -> true | _ -> false) -> + spr ctx "_hx_field("; + gen_value ctx e1; + print ctx ", \"%s\")" name | _ -> if is_string_expr e1 then - gen_string_var ctx s e1 + gen_string_var ctx name e1 else if is_uncertain_expr e1 then - gen_uncertain_string_var ctx s e1 + gen_uncertain_string_var ctx name e1 else - gen_field_access ctx true e1 s + gen_field_access ctx true e1 name and gen_expr ctx e = let in_block = ctx.in_block in @@ -1176,6 +1232,7 @@ and gen_expr ctx e = end else if ((se1 = "Int" || se1 = "Null") && (se2 = "Int" || se2 = "Null")) || ((se1 = "Float" || se1 = "Null") && (se2 = "Float" || se2 = "Null")) + && not (is_float e1 && is_float e2) then begin gen_field_op ctx e1; spr ctx s_phop; @@ -1215,11 +1272,13 @@ and gen_expr ctx e = let tmp = define_local ctx "_t" in print ctx "(is_object($%s = " tmp; gen_field_op ctx e1; - print ctx ") && !($%s instanceof Enum) ? $%s%s" tmp tmp s_phop; + print ctx ") && ($%s instanceof Enum) ? $%s%s" tmp tmp s_op; gen_field_op ctx e2; - print ctx " : $%s%s" tmp s_op; + print ctx " : "; + if op = Ast.OpNotEq then spr ctx "!"; + print ctx "_hx_equal($%s, " tmp; gen_field_op ctx e2; - spr ctx ")"; + spr ctx "))"; end | Ast.OpGt | Ast.OpGte | Ast.OpLt | Ast.OpLte when is_string_expr e1 -> spr ctx "(strcmp("; @@ -1246,7 +1305,7 @@ and gen_expr ctx e = spr ctx ")"; print ctx "->params[%d]" i; | TField (e1,s) -> - gen_tfield ctx e e1 (field_name s) + gen_tfield ctx e e1 s | TTypeExpr t -> print ctx "_hx_qtype(\"%s\")" (s_path_haxe (t_path t)) | TParenthesis e -> @@ -1279,7 +1338,7 @@ and gen_expr ctx e = if ctx.in_loop then spr ctx "break" else print ctx "break %d" ctx.nested_loops | TContinue -> if ctx.in_loop then spr ctx "continue" else print ctx "continue %d" ctx.nested_loops - | TBlock [] -> + | TBlock [] when List.length ctx.dynamic_methods = 0 -> spr ctx "{}" | TBlock el -> let old_l = ctx.inv_locals in @@ -1460,7 +1519,7 @@ and gen_expr ctx e = ); | TField (e1,s) -> spr ctx (Ast.s_unop op); - gen_tfield ctx e e1 (field_name s) + gen_tfield ctx e e1 s | _ -> spr ctx (Ast.s_unop op); gen_value ctx e) @@ -1544,7 +1603,7 @@ and gen_expr ctx e = let catchall = ref false in let evar = define_local ctx "_ex_" in newline ctx; - print ctx "$%s = ($%s instanceof HException) ? $%s->e : $%s" evar ex ex ex; + print ctx "$%s = ($%s instanceof HException) && $%s->getCode() == null ? $%s->e : $%s" evar ex ex ex ex; old(); List.iter (fun (v,e) -> let ev = define_local ctx v.v_name in @@ -1680,7 +1739,7 @@ and inline_block ctx e = ctx.inline_methods <- ctx.inline_methods @ [block] -and inline_function ctx args hasthis e = +and inline_function ctx args hasthis used_args e = let index = ctx.inline_index in ctx.inline_index <- ctx.inline_index + 1; let block = { @@ -1689,9 +1748,9 @@ and inline_function ctx args hasthis e = ihasthis = hasthis; (* param this *) iarguments = args; iexpr = e; - ilocals = ctx.locals; + ilocals = used_args; iin_block = false; - iinv_locals = ctx.inv_locals; + iinv_locals = used_args; } in ctx.inline_methods <- ctx.inline_methods @ [block]; @@ -1746,7 +1805,9 @@ and gen_value ctx e = gen_value ctx e1 | TBlock [] -> () - | TCast (e, _) + | TCast (_, Some _) -> + gen_expr ctx e + | TCast (e, None) | TBlock [e] -> gen_value ctx e | TIf (cond,e,eelse) when (cangen_ternary e eelse) -> @@ -1878,13 +1939,13 @@ let generate_field ctx static f = | AccCall, _ -> let m = "get_" ^ f.cf_name in if not (is_method_defined ctx m static) then generate_self_method ctx rights m static false; - print ctx "%s $%s" rights (s_ident_field f.cf_name); + print ctx "%s $%s" rights (s_ident f.cf_name); gen_assigned_value ctx f.cf_expr; true | _, AccCall -> let m = "set_" ^ f.cf_name in if not (is_method_defined ctx m static) then generate_self_method ctx rights m static true; - print ctx "%s $%s" rights (s_ident_field f.cf_name); + print ctx "%s $%s" rights (s_ident f.cf_name); gen_assigned_value ctx f.cf_expr; true | _ -> @@ -2032,6 +2093,7 @@ let generate_class ctx c = } in ctx.constructor_block <- true; generate_field ctx false f; + ctx.constructor_block <- false; ); List.iter (generate_field ctx false) c.cl_ordered_fields; @@ -2123,11 +2185,13 @@ let createmain com e = spr ctx "if(version_compare(PHP_VERSION, '5.1.0', '<')) { exit('Your current PHP version is: ' . PHP_VERSION . '. Haxe/PHP generates code for version 5.1.0 or later'); +} else if(version_compare(PHP_VERSION, '5.4.0', '<')) { + trigger_error('Your current PHP version is: ' . PHP_VERSION . '. Code generated by Haxe/PHP might not work for versions < 5.4.0', E_USER_WARNING); }"; newline ctx; newline ctx; spr ctx ("require_once dirname(__FILE__).'/" ^ ctx.lib_path ^ "/php/" ^ (prefix_class com "Boot.class.php';\n\n")); - gen_value ctx e; + gen_expr ctx e; newline ctx; spr ctx "\n?>"; close ctx @@ -2230,9 +2294,9 @@ let generate com = else ((n = (prefixed_name false)) || (n = (prefixed_name true))) ) !lc_names in - unsupported ("method '" ^ (s_type_path c.cl_path) ^ "." ^ cf.cf_name ^ "' already exists here '" ^ (fst lc) ^ "' (different case?)") c.cl_pos + unsupported ("method '" ^ (Globals.s_type_path c.cl_path) ^ "." ^ cf.cf_name ^ "' already exists here '" ^ (fst lc) ^ "' (different case?)") c.cl_pos with Not_found -> - lc_names := ((s_type_path c.cl_path) ^ "." ^ cf.cf_name, prefixed_name static) :: !lc_names) + lc_names := ((Globals.s_type_path c.cl_path) ^ "." ^ cf.cf_name, prefixed_name static) :: !lc_names) | _ -> () ) lst diff --git a/src/generators/genphp7.ml b/src/generators/genphp7.ml new file mode 100644 index 00000000..675a0491 --- /dev/null +++ b/src/generators/genphp7.ml @@ -0,0 +1,3513 @@ +(** + Compatible with PHP 7+ +*) + +open Ast +open Type +open Common +open Meta +open Globals + +let debug = ref false + +(** + Escape string for constant strings generation. + Copy-pasted from genphp. +*) +let escape_bin s = + let b = Buffer.create 0 in + for i = 0 to String.length s - 1 do + match Char.code (String.unsafe_get s i) with + | c when c = Char.code('\\') || c = Char.code('"') || c = Char.code('$') -> + Buffer.add_string b "\\"; + Buffer.add_char b (Char.chr c) + | c when c < 32 -> + Buffer.add_string b (Printf.sprintf "\\x%.2X" c) + | c -> + Buffer.add_char b (Char.chr c) + done; + Buffer.contents b + +(** + Write resources passed to compiler via `-resource` flag + Copy-pasted from genphp +*) +let write_resource dir name data = + let rdir = dir ^ "/res" in + if not (Sys.file_exists dir) then Unix.mkdir dir 0o755; + if not (Sys.file_exists rdir) then Unix.mkdir rdir 0o755; + let name = Codegen.escape_res_name name false in + let ch = open_out_bin (rdir ^ "/" ^ name) in + output_string ch data; + close_out ch + +(** + Get list of keys in Hashtbl +*) +let hashtbl_keys tbl = Hashtbl.fold (fun key _ lst -> key :: lst) tbl [] + +(** + @return List of items in `list1` which `list2` does not contain +*) +let diff_lists list1 list2 = List.filter (fun x -> not (List.mem x list2)) list1 + +(** + Type path for native PHP Exception class +*) +let native_exception_path = ([], "Throwable") +(** + Type path for Haxe exceptions wrapper +*) +let hxexception_type_path = (["php"; "_Boot"], "HxException") +(** + Type path of `php.Boot` +*) +let boot_type_path = (["php"], "Boot") +(** + Type path of the base class for all enums: `php.Boot.HxEnum` +*) +let hxenum_type_path = (["php"; "_Boot"], "HxEnum") +(** + Type path of the implementation class for `Class` +*) +let hxclass_type_path = (["php"; "_Boot"], "HxClass") +(** + Type path of the implementation class for `String` +*) +let hxstring_type_path = (["php"; "_Boot"], "HxString") +(** + Type path of the special implementation class for `String` + which is used when Dynamic value is suspected to be a string +*) +let hxdynamicstr_type_path = (["php"; "_Boot"], "HxDynamicStr") +(** + Type path of the implementation class for anonymous objects +*) +let hxanon_type_path = (["php"; "_Boot"], "HxAnon") +(** + Type path of the implementation class for closures +*) +let hxclosure_type_path = (["php"; "_Boot"], "HxClosure") +(** + Type path for special PHP extern class to support specific language expressions +*) +let syntax_type_path = (["php"], "Syntax") +(** + Special abstract which enables passing function arguments and return value by reference +*) +let ref_type_path = (["php"], "Ref") +(** + Type path of the implementation class for `Array` +*) +let array_type_path = ([], "Array") +(** + Type path of the implementation class for `Array` +*) +let native_array_type_path = (["php"], "NativeArray") +(** + Type path of the `Void` +*) +let void_type_path = ([], "Void") +(** + Type path of the `Bool` +*) +let bool_type_path = ([], "Bool") +(** + Type path of the `Std` +*) +let std_type_path = ([], "Std") + +(** + Stub to use when you need a `Ast.pos` instance, but don't have one +*) +let dummy_pos = { pfile = ""; pmin = 0; pmax = 0 } + +(** + Check if specified string is a reserved word in PHP +*) +let is_keyword str = + match String.lowercase str with + | "__halt_compiler" | "abstract" | "and" | "array" | "as" | "break" | "callable" | "case" | "catch" | "class" + | "clone" | "const" | "continue" | "declare" | "default" | "die" | "do" | "echo" | "else" | "elseif" | "empty" + | "enddeclare" | "endfor" | "endforeach" | "endif" | "endswitch" | "endwhile" | "eval" | "exit" | "extends" + | "final" | "finally" | "for" | "foreach" | "function" | "global" | "goto" | "if" | "implements" | "include" + | "include_once" | "instanceof" | "insteadof" | "interface" | "isset" | "list" | "namespace" | "new" | "or" + | "print" | "private" | "protected" | "public" | "require" | "require_once" | "return" | "static" | "switch" + | "throw" | "trait" | "try" | "unset" | "use" | "var" | "while" | "xor" | "yield" | "__class__" | "__dir__" + | "__file__" | "__function__" | "__line__" | "__method__" | "__trait__" | "__namespace__" | "int" | "float" + | "bool" | "string" | "true" | "false" | "null" | "parent" | "void" | "iterable" + -> true + | _ -> false + +(** + Check if specified type is Void +*) +let is_void_type t = match follow t with TAbstract ({ a_path = void_type_path }, _) -> true | _ -> false + +(** + Check if specified type is Bool +*) +let is_bool_type t = match follow t with TAbstract ({ a_path = bool_type_path }, _) -> true | _ -> false + +(** + Check if specified type is php.NativeArray +*) +let is_native_array_type t = match follow t with TAbstract ({ a_path = native_array_type_path }, _) -> true | _ -> false + +(** + If `name` is not a reserved word in PHP then `name` is returned as-is. + Otherwise this method returns another string, which can be used instead of `name` +*) +let get_real_name name = if is_keyword name then name ^ "_hx" else name + +(** + If `path` contains some reserved in PHP words, they will be replaced with allowed words. +*) +let get_real_path path = List.map get_real_name path + +(** + Resolve real type (bypass abstracts and typedefs) +*) +let rec follow = Abstract.follow_with_abstracts + +let prefix = ref None +(** + Returns value of `--php-prefix` compiler flag +*) +let get_php_prefix ctx = + match !prefix with + | Some prefix -> prefix + | None -> + let lst = + match ctx.php_prefix with + | None -> [] + | Some str -> + if String.length str = 0 then + [] + else + Str.split (Str.regexp "\\.") str + in + prefix := Some lst; + lst + +(** + Adds packages specified by `--php-prefix` to `type_path`. + E.g. if `--php-prefix some.sub` and `type_path` is `(["pack"], "MyClass")`, then this function + will return `(["some", "sub", "pack"], "MyClass")` +*) +let add_php_prefix ctx type_path = + match type_path with + | (pack, name) -> ((get_php_prefix ctx) @ pack, name) + +(** + If `expr` is a TCast or TMeta, then returns underlying expression (recursively bypassing nested casts). + Otherwise returns `expr` as is. +*) +let rec reveal_expr expr = + match expr.eexpr with + | TCast (e, _) -> reveal_expr e + | TMeta (_, e) -> reveal_expr e + | _ -> expr + +(** + If `expr` is a TCast or TMeta or TParenthesis, then returns underlying expression (recursively bypassing nested casts and parenthesis). + Otherwise returns `expr` as is. +*) +let rec reveal_expr_with_parenthesis expr = + match expr.eexpr with + | TCast (e, _) -> reveal_expr_with_parenthesis e + | TMeta (_, e) -> reveal_expr_with_parenthesis e + | TParenthesis e -> reveal_expr_with_parenthesis e + | _ -> expr + +(** + @return Error message with position information +*) +let error_message pos message = (Lexer.get_error_pos (Printf.sprintf "%s:%d:") pos) ^ ": " ^ message + +(** + Terminates compiler process and prints user-friendly instructions about filing an issue in compiler repo. +*) +let fail hxpos mlpos = + match mlpos with + | (file, line, _) -> + Printf.printf "%s\n" (error_message hxpos "Unexpected expression. Please submit an issue with expression example and following information:"); + Printf.printf "%s:%d\n" file line; + assert false + +(** + Print compilation error message and abort compilation process. +*) +let error_and_exit pos message = + Printf.printf "%s" (error_message pos message); + exit 1 + +(** + Check if `target` is a `Dynamic` type +*) +let rec is_dynamic_type (target:Type.t) = match follow target with TDynamic _ -> true | _ -> false + +(** + Check if `target` is `php.Ref` +*) +let is_ref (target:Type.t) = match target with TType ({ t_path = type_path }, _) -> type_path = ref_type_path | _ -> false + +(** + Check if `field` is a `dynamic function` +*) +let rec is_dynamic_method (field:tclass_field) = + match field.cf_kind with + | Method MethDynamic -> true + | _ -> false + +(** + Check if specified expression is of `Dynamic` type +*) +let is_dynamic expr = is_dynamic_type expr.etype + +(** + Check if specified expression is of `Int` type +*) +let is_int expr = match follow expr.etype with TAbstract ({ a_path = ([], "Int") }, _) -> true | _ -> false + +(** + Check if specified expression is of `Float` type +*) +let is_float expr = match follow expr.etype with TAbstract ({ a_path = ([], "Float") }, _) -> true | _ -> false + +(** + Check if specified type is String +*) +let is_string_type t = match follow t with TInst ({ cl_path = ([], "String") }, _) -> true | _ -> false + +(** + Check if specified expression is of String type +*) +let is_string expr = is_string_type expr.etype + +(** + Check if `expr` is an access to a method of special `php.PHP` class +*) +let is_lang_extern expr = + match expr.eexpr with + | TField ({ eexpr = TTypeExpr (TClassDecl { cl_path = path }) }, _) when path = syntax_type_path -> true + | _ -> false + +(** + Check if specified type is actually a generic parameter +*) +let is_generic_parameter (target:Type.t) = + match follow target with + | TInst ({ cl_kind = KTypeParameter _ }, _) -> true + | _ -> false + +(** + Check if `target` type cannot be clarified on compilation +*) +let is_unknown_type (target:Type.t) = is_dynamic_type target || is_generic_parameter target + +(** + @return `Type.t` instance for `Void` +*) +let void = ref None +let get_void ctx : Type.t = + match !void with + | Some value -> value + | None -> + let find com_type = + match com_type with + | TAbstractDecl ({ a_path = ([], "Void") } as abstr) -> void := Some (TAbstract (abstr, [])); + | _ -> () + in + List.iter find ctx.types; + match !void with + | Some value -> value + | None -> fail dummy_pos (try assert false with Assert_failure mlpos -> mlpos) + +(** + @return `tclass` instance for `php.Boot` +*) +let boot = ref None +let get_boot ctx : tclass = + match !boot with + | Some value -> value + | None -> + let find com_type = + match com_type with + | TClassDecl ({ cl_path = path } as cls) when path = boot_type_path -> boot := Some cls; + | _ -> () + in + List.iter find ctx.types; + match !boot with + | Some value -> value + | None -> fail dummy_pos (try assert false with Assert_failure mlpos -> mlpos) + +(** + @return `expr` wrapped in parenthesis +*) +let parenthesis expr = {eexpr = TParenthesis expr; etype = expr.etype; epos = expr.epos} + +(** + Check if `current` binary should be surrounded with parenthesis +*) +let need_parenthesis_for_binop current parent = + if current = parent then + false + else + match (current, parent) with + | (_, OpAssign) -> false + | (_, OpAssignOp _) -> false + | (OpAdd, OpSub) -> false + | (OpSub, OpAdd) -> false + | (OpMult, OpDiv) -> false + | (OpDiv, OpMult) -> false + | (OpMult, OpAdd) -> false + | (OpMult, OpSub) -> false + | (OpDiv, OpAdd) -> false + | (OpDiv, OpSub) -> false + | _ -> true + +(** + Check if specified expression may require dereferencing if used as "temporary expression" +*) +let needs_dereferencing expr = + let rec is_create target_expr = + match target_expr.eexpr with + | TParenthesis e -> is_create e + | TCast (e, _) -> is_create e + | TNew _ -> true + | TArrayDecl _ -> true + | TObjectDecl _ -> true + | TConst TNull -> true + (* some of `php.Syntax` methods *) + | TCall ({ eexpr = TField (_, FStatic ({ cl_path = syntax_type_path }, { cf_name = name })) }, _) -> + (match name with + | "binop" | "object" | "array" -> true + | _ -> false + ) + | _ -> false + in + match expr.eexpr with + | TField (target_expr, _) -> is_create target_expr + | TArray (target_expr, _) -> is_create target_expr + | _ -> false + +(** + @return (arguments_list, return_type) +*) +let get_function_signature (field:tclass_field) : (string * bool * Type.t) list * Type.t = + match follow field.cf_type with + | TFun (args, return_type) -> (args, return_type) + | _ -> fail field.cf_pos (try assert false with Assert_failure mlpos -> mlpos) + +(** + Check if `target` is 100% guaranteed to be a scalar type in PHP. + Inversion of `is_sure_scalar` does not guarantee `target` is not scalar. +*) +let is_sure_scalar (target:Type.t) = + match follow target with + | TInst ({ cl_path = ([], "String") }, _) -> true + | TAbstract (abstr, _) -> + (match abstr.a_path with + | ([],"Int") -> true + | ([],"Float") -> true + | ([],"Bool") -> true + | _ -> false + ) + | _ -> false + +(** + Indicates if `expr` is guaranteed to be an access to a `var` field. +*) +let is_sure_var_field_access expr = + match (reveal_expr expr).eexpr with + | TField (_, FStatic (_, { cf_kind = Var _ })) -> true + | TField (_, FInstance (_, _, { cf_kind = Var _ })) -> true + (* | TField (_, FAnon { cf_kind = Var _ }) -> true *) (* Sometimes we get anon access to non-anonymous objects *) + | _ -> false + +(** + Check if specified unary operation modifies value in place +*) +let is_modifying_unop op = + match op with + | Increment + | Decrement -> true + | _ -> false + +(** + Indicates whether `expr` is a field access which should be generated as global namespace function +*) +let is_php_global expr = + match expr.eexpr with + | TField (_, FStatic ({ cl_extern = true; cl_meta = meta }, _)) -> Meta.has Meta.PhpGlobal meta + | _ -> false + +(** + Indicates whether `expr` is a field access which should be generated as class constant access +*) +let is_php_class_const expr = + match expr.eexpr with + | TField (_, FStatic ({ cl_extern = true }, { cf_meta = meta; cf_kind = Var _ })) -> + Meta.has Meta.PhpClassConst meta + | _ -> false + +(** + Check if specified enum constructor has arguments +*) +let is_enum_constructor_with_args (constructor:tenum_field) = + match follow constructor.ef_type with + | TFun _ -> true + | _ -> false + +(** + Check if `target` is 100% guaranteed to be or extend an extern class. + Inversion of `sure_extends_extern` does not guarantee `target` does not extend an extern class. +*) +let rec sure_extends_extern (target:Type.t) = + match follow target with + | TInst ({ cl_path = ([], "String") }, _) -> false + | TInst ({ cl_extern = true }, _) -> true + | TInst ({ cl_super = Some (tsuper, params) }, _) -> sure_extends_extern (TInst (tsuper,params)) + | _ -> false + +(** + @return `opt` value or `default` if `opt` is None +*) +let get_option_value (opt:'a option) default = + match opt with + | None -> default + | Some value -> value + +(** + @param path Something like [ "/some/path/first_dir_to_create"; "nested_level1"; "nested_level2" ] + @return String representation of created path (E.g. "/some/path/first_dir_to_create/nested_level1/nested_level2") +*) +let create_dir_recursive (path:string list) = + let rec create dir nested_dirs = + if not (Sys.file_exists dir) then (Unix.mkdir dir 0o755); + match nested_dirs with + | [] -> (); + | next :: rest -> create (dir ^ "/" ^ next) rest + in + match path with + | [] -> ""; + | root :: rest -> + create root rest; + (String.concat "/" path) + +(** + @return String representation of specified type path. E.g. returns "\example\Test" for (["example"], "Test") +*) +let get_full_type_name ?escape ?omit_first_slash (type_path:path) = + let name = + match type_path with + | (module_path, type_name) -> + let parts = + match omit_first_slash with + | Some true -> get_real_path module_path + | _ -> "" :: get_real_path module_path + in + (String.concat "\\" parts) ^ "\\" ^ type_name + in + match escape with + | Some true -> String.escaped name + | _ -> name + +(** + Check if `target` is or implements native PHP `Throwable` interface +*) +let rec is_native_exception (target:Type.t) = + match follow target with + | TInst ({ cl_path = path }, _) when path = native_exception_path -> true + | TInst ({ cl_super = parent ; cl_implements = interfaces ; cl_path = path }, _) -> + let (parent, params) = + match parent with + | Some (parent, params) -> (Some parent, params) + | None -> (None, []) + in + let found = ref false in + List.iter + (fun (cls, params) -> + if not !found then + found := is_native_exception (TInst (cls, params)) + ) + interfaces; + if !found then + true + else + (match parent with + | Some parent -> is_native_exception (TInst (parent, params)) + | None -> false + ) + | _ -> false + +(** + @return Short type name. E.g. returns "Test" for (["example"], "Test") +*) +let get_type_name (type_path:path) = match type_path with (_, type_name) -> type_name + +(** + @return E.g. returns ["example"] for (["example"], "Test") +*) +let get_module_path (type_path:path) = match type_path with (module_path, _) -> module_path + +(** + @return PHP visibility keyword. +*) +let get_visibility (meta:metadata) = if Meta.has Meta.Protected meta then "protected" else "public" + +(** + Writes arguments list to output buffer +*) +let rec write_args buffer arg_writer (args:'a) = + match args with + | [] -> () + | [arg] -> arg_writer arg + | arg :: rest -> + arg_writer arg; + Buffer.add_string buffer ", "; + write_args buffer arg_writer rest + +(** + Check if specified field is a var with non-constant expression +*) +let is_var_with_nonconstant_expr (field:tclass_field) = + match field.cf_kind with + | Var _ -> + (match field.cf_expr with + | None -> false + | Some ({eexpr = TConst _ }) -> false + | Some _ -> true + ) + | Method _ -> false + +(** + @return New TBlock expression which is composed of setting default values for optional arguments and function body. +*) +let inject_defaults (ctx:Common.context) (func:tfunc) = + let rec inject args body_exprs = + match args with + | [] -> body_exprs + | (_, None) :: rest -> inject rest body_exprs + | (_, Some TNull) :: rest -> inject rest body_exprs + | (var, Some const) :: rest -> + let expr = Codegen.set_default ctx var const func.tf_expr.epos in + expr :: (inject rest body_exprs) + in + let exprs = + match func.tf_expr.eexpr with + | TBlock exprs -> inject func.tf_args exprs + | _ -> inject func.tf_args [ func.tf_expr ] + in + { + eexpr = TBlock exprs; + etype = follow func.tf_expr.etype; + epos = func.tf_expr.epos; + } + +(** + Check if `expr` is a constant string +*) +let is_constant_string expr = + match expr.eexpr with + | TConst (TString _) -> true + | _ -> false + +(** + Check if `expr` is a constant null +*) +let is_constant_null expr = + match expr.eexpr with + | TConst TNull -> true + | _ -> false + +(** + Check if `expr` is a constant +*) +let is_constant expr = + match expr.eexpr with + | TConst _ -> true + | _ -> false + +(** + Check if `expr` is a concatenation +*) +let is_concatenation expr = + match expr.eexpr with + | TBinop (OpAdd, expr1, expr2) -> (is_string expr1) || (is_string expr2) + | _ -> false + +(** + Check if provided expression is a binary operation +*) +let is_binop expr = match expr.eexpr with TBinop _ -> true | _ -> false + +(** + Check if provided expression is an assignment binary operation +*) +let is_binop_assign expr = + match expr.eexpr with + | TBinop (operation, _, _) -> + (match operation with + | OpAssign | OpAssignOp _ -> true + | _ -> false + ) + | _ -> false + +(** + Check if specified expression is field access or array access +*) +let is_access expr = + match expr.eexpr with + | TField _ | TArray _ -> true + | _ -> false + +(** + Indicates if `expr` is actually a call to Haxe->PHP magic function + @see http://old.haxe.org/doc/advanced/magic#php-magic +*) +let is_magic expr = + match expr.eexpr with + | TCall ({ eexpr = TLocal { v_name = name }}, _) -> + (match name with + | "__php__" -> true + | "__call__" -> true + | "__physeq__" -> true + | "__var__" -> true + | _ -> false + ) + | _ -> false + +(** + Check if `expr1` and `expr2` can be reliably checked for equality only with `Boot.equal()` +*) +let need_boot_equal expr1 expr2 = + if is_constant_null expr1 || is_constant_null expr2 then + false + else + (is_int expr1 && (is_float expr2 || is_unknown_type expr2.etype)) + || (is_float expr1 && (is_float expr2 || is_int expr2 || is_unknown_type expr2.etype)) + || (is_unknown_type expr1.etype && (is_int expr2 || is_float expr2)) + || (is_unknown_type expr1.etype && is_unknown_type expr2.etype) + +(** + Adds `return` expression to block if it does not have one already +*) +let ensure_return_in_block block_expr = + match block_expr.eexpr with + | TBlock [] -> fail block_expr.epos (try assert false with Assert_failure mlpos -> mlpos) + | TBlock exprs -> + let reversed = List.rev exprs in + let last_expr = List.hd reversed in + let return_expr = { last_expr with eexpr = TReturn (Some last_expr) } in + let reversed = return_expr::(List.tl reversed) in + { block_expr with eexpr = TBlock (List.rev reversed) } + | _ -> fail block_expr.epos (try assert false with Assert_failure mlpos -> mlpos) + +(** + If `expr` is a block, then return list of expressions in that block. + Otherwise returns a list with `expr` as a single item. +*) +let unpack_block expr = + match expr.eexpr with + | TBlock exprs -> exprs + | _ -> [ expr ] + +(** + If `expr` is a block of a single expression, then return that single expression. + If `expr` is a block with multiple expressions, fail compilation. + Otherwise return `expr` as-is. +*) +let unpack_single_expr_block expr = + match expr.eexpr with + | TBlock [ e ] -> e + | TBlock _ -> fail expr.epos (try assert false with Assert_failure mlpos -> mlpos) + | _ -> expr + +(** + Check if specified type has rtti meta +*) +let has_rtti_meta ctx mtype = + match Codegen.build_metadata ctx mtype with + | None -> false + | Some _ -> true + +(** + Check if this var accesses and meta combination should generate a variable +*) +let is_real_var field = + if Meta.has IsVar field.cf_meta then + true + else + match field.cf_kind with + | Var { v_read = read; v_write = write } -> read = AccNormal || write = AccNormal + | _ -> false + +(** + Check if user-defined field has the same name as one of php magic methods, but with not compatible signature. +*) +let field_needs_rename field = + match field.cf_kind with + | Var _ -> false + | Method _ -> + match field.cf_name with + | "__construct" | "__destruct" | "__call" | "__callStatic" | "__get" | "__set" | "__isset" + | "__unset" | "__sleep" | "__wakeup" | "__toString" | "__invoke" | "__set_state" | "__clone" + | "__debugInfo" -> not (Meta.has Meta.PhpMagic field.cf_meta) + | _ -> false +(** + Get valid `field` name. +*) +let field_name field = + if field_needs_rename field then + "__hx__renamed" ^ field.cf_name + else + field.cf_name + +(** + Check if `expr` is `Std.is` +*) +let is_std_is expr = + match expr.eexpr with + | TField (_, FStatic ({ cl_path = path }, { cf_name = "is" })) -> path = boot_type_path || path = std_type_path + | _ -> false + +(** + Check if `subject_arg` and `type_arg` can be generated as `$subject instanceof Type` expression. +*) +let instanceof_compatible (subject_arg:texpr) (type_arg:texpr) : bool = + match (reveal_expr_with_parenthesis type_arg).eexpr with + | TTypeExpr (TClassDecl { cl_path = path }) when path <> ([], "String") && path <> ([], "Class") -> + let subject_arg = reveal_expr_with_parenthesis subject_arg in + (match subject_arg.eexpr with + | TLocal _ | TField _ | TCall _ | TArray _ -> not (is_magic subject_arg) + | _ -> false + ) + | _ -> false + + +(** + PHP DocBlock types +*) +type doc_type = + | DocVar of string * (string option) (* (type name, description) *) + | DocMethod of (string * bool * t) list * t * (string option) (* (arguments, return type, description) *) + | DocClass of string option + +(** + Common interface for module_type instances +*) +class virtual type_wrapper (type_path:path) (meta:metadata) (needs_generation:bool) = + object (self) + (** + Indicates if this type should be rendered to corresponding php file + *) + method needs_generation = needs_generation + (** + Indicates if class initialization method should be executed upon class loaded + *) + method virtual needs_initialization : bool + (** + Returns hx source file name where this type was declared + *) + method virtual get_source_file : string + (** + Returns `Type.module_type` instance for this type + *) + method virtual get_module_type : module_type + (** + Returns expression of a user-defined static __init__ method + @see http://old.haxe.org/doc/advanced/magic#initialization-magic + *) + method get_magic_init : texpr option = None + (** + Namespace path. E.g. ["some"; "pack"] for "some.pack.MyType" + *) + method get_namespace = get_module_path type_path + (** + Short type name. E.g. `SomeType` for `pack.SomeType` + *) + method get_name = get_type_name type_path + (** + Full type path + *) + method get_type_path = type_path + (** + If current type requires some additional type to be generated + *) + method get_service_type : module_type option = None + end + +(** + TClassDecl +*) +class class_wrapper (cls) = + object (self) + inherit type_wrapper cls.cl_path cls.cl_meta (not cls.cl_extern) + (** + Indicates if class initialization method should be executed upon class loaded + *) + method needs_initialization = + (* Interfaces may need initialization only for RTTI meta data. + But that meta is written in `class_wrapper#write_rtti_meta` *) + if cls.cl_interface then + false + else + match cls.cl_init with + | Some _ -> true + | None -> + let needs = ref false in + PMap.iter + (fun _ field -> + (* Check static vars with non-constant expressions *) + if not !needs then needs := is_var_with_nonconstant_expr field; + (* Check static dynamic functions *) + if not !needs then needs := is_dynamic_method field + ) + cls.cl_statics; + !needs + (** + Returns expression of a user-defined static __init__ method + @see http://old.haxe.org/doc/advanced/magic#initialization-magic + *) + method get_magic_init = cls.cl_init + (** + Returns hx source file name where this type was declared + *) + method get_source_file = cls.cl_pos.pfile + (** + Returns `Type.module_type` instance for this type + *) + method get_module_type = TClassDecl cls + (** + If current type requires some additional type to be generated + *) + method get_service_type : module_type option = + if not cls.cl_extern then + None + else + match cls.cl_init with + | None -> None + | Some body -> + let path = + match cls.cl_path with + | (pack, name) -> (pack @ ["_" ^ name], ("_extern_" ^ name)) + in + let additional_cls = { + cls with + cl_extern = false; + cl_path = path; + cl_fields = PMap.create (fun a b -> 0); + cl_statics = PMap.create (fun a b -> 0); + cl_ordered_fields = []; + cl_ordered_statics = []; + cl_constructor = None; + cl_overrides = []; + cl_init = Some body + } in + Some (TClassDecl additional_cls) + end + +(** + TEnumDecl +*) +class enum_wrapper (enm) = + object (self) + inherit type_wrapper enm.e_path enm.e_meta (not enm.e_extern) + (** + Indicates if class initialization method should be executed upon class loaded + *) + method needs_initialization = false + (** + Returns hx source file name where this type was declared + *) + method get_source_file = enm.e_pos.pfile + (** + Returns `Type.module_type` instance for this type + *) + method get_module_type = TEnumDecl enm + end + +(** + TTypeDecl +*) +class typedef_wrapper (tdef) = + object (self) + inherit type_wrapper tdef.t_path tdef.t_meta false + (** + Indicates if class initialization method should be executed upon class loaded + *) + method needs_initialization = false + (** + Returns hx source file name where this type was declared + *) + method get_source_file = tdef.t_pos.pfile + (** + Returns `Type.module_type` instance for this type + *) + method get_module_type = TTypeDecl tdef + end + +(** + TAbstractDecl +*) +class abstract_wrapper (abstr) = + object (self) + inherit type_wrapper abstr.a_path abstr.a_meta false + (** + Indicates if class initialization method should be executed upon class loaded + *) + method needs_initialization = false + (** + Returns hx source file name where this type was declared + *) + method get_source_file = abstr.a_pos.pfile + (** + Returns `Type.module_type` instance for this type + *) + method get_module_type = TAbstractDecl abstr + end + +(** + type_wrapper for classes +*) +let classes = Hashtbl.create 1000 +let get_class_wrapper cls : type_wrapper = + try + let wrapper = Hashtbl.find classes cls in + wrapper + with + | Not_found -> + let wrapper = new class_wrapper cls in + Hashtbl.add classes cls wrapper; + wrapper + | e -> raise e + +(** + type_wrapper for enums +*) +let enums = Hashtbl.create 200 +let get_enum_wrapper enm : type_wrapper= + try + let wrapper = Hashtbl.find enums enm in + wrapper + with + | Not_found -> + let wrapper = new enum_wrapper enm in + Hashtbl.add enums enm wrapper; + wrapper + | e -> raise e + +(** + type_wrapper for typedefs +*) +let typedefs = Hashtbl.create 200 +let get_typedef_wrapper typedef : type_wrapper = + try + let wrapper = Hashtbl.find typedefs typedef in + wrapper + with + | Not_found -> + let wrapper = new typedef_wrapper typedef in + Hashtbl.add typedefs typedef wrapper; + wrapper + | e -> raise e + +(** + type_wrapper for abstracts +*) +let abstracts = Hashtbl.create 200 +let get_abstract_wrapper abstr : type_wrapper = + try + let wrapper = Hashtbl.find abstracts abstr in + wrapper + with + | Not_found -> + let wrapper = new abstract_wrapper abstr in + Hashtbl.add abstracts abstr wrapper; + wrapper + | e -> raise e + +(** + Returns wrapper for module_type. + Caches wrappers so that each type will always return the same wrapper instance. +*) +let get_wrapper (mtype:module_type) : type_wrapper = + match mtype with + | TClassDecl cls -> get_class_wrapper cls + | TEnumDecl enm -> get_enum_wrapper enm + | TTypeDecl typedef -> get_typedef_wrapper typedef + | TAbstractDecl abstr -> get_abstract_wrapper abstr + +(** + Drop cached instances of type_wrapper +*) +let clear_wrappers () = + Hashtbl.clear classes; + Hashtbl.clear enums; + Hashtbl.clear typedefs; + Hashtbl.clear abstracts + +(** + Check if specified type name is used in specified namespace +*) +let namespaces_types_cache = Hashtbl.create 512 +let type_name_used_in_namespace ctx name namespace = + let types = Hashtbl.find_all namespaces_types_cache namespace in + match types with + | [] -> + List.iter + (fun ctx_type -> + let wrapper = get_wrapper ctx_type in + Hashtbl.add namespaces_types_cache wrapper#get_namespace wrapper#get_name + ) + ctx.types; + let types = Hashtbl.find_all namespaces_types_cache namespace in + List.mem name types + | _ -> + List.mem name types + +(** + Simple list intersection implementation. + @return A list of values existing in each of source lists. +*) +let rec list_intersect list1 list2 = + match list2 with + | [] -> [] + | item :: rest -> + if List.mem item list1 then + item :: (list_intersect list1 rest) + else + list_intersect list1 rest + +(** + Class to simplify collecting lists of declared and used local vars. + Collected data is needed to generate closures correctly. +*) +class local_vars = + object (self) + (** Hashtbl to collect local var used in current scope *) + val mutable used_locals = [Hashtbl.create 100] + (** Hashtbl to collect local vars declared in current scope *) + val mutable declared_locals = [Hashtbl.create 100] + (** Local vars which were captured in closures (passed via `use` directive in php) *) + val captured_locals = Hashtbl.create 0 + (** + Clear collected data + *) + method clear : unit = + used_locals <- [Hashtbl.create 100]; + declared_locals <- [Hashtbl.create 100]; + Hashtbl.clear captured_locals + (** + This method should be called upone entering deeper scope. + E.g. right before processing a closure. Just before closure arguments handling. + *) + method dive : unit = + used_locals <- (Hashtbl.create 100) :: used_locals; + declared_locals <- (Hashtbl.create 100) :: declared_locals + (** + This method should be called right after leaving a scope. + @return List of vars names used in finished scope, but declared in higher scopes. + And list of vars names declared in finished scope. + And list of vars names declared in finished scope and captured by closures via `use` directive + *) + method pop : string list * string list * string list = + match used_locals with + | [] -> assert false + | used :: rest_used -> + match declared_locals with + | [] -> assert false + | declared :: rest_declared -> + let higher_vars = diff_lists (hashtbl_keys used) (hashtbl_keys declared) + and declared_vars = hashtbl_keys declared in + used_locals <- rest_used; + declared_locals <- rest_declared; + List.iter self#used higher_vars; + let captured_vars = list_intersect declared_vars (hashtbl_keys captured_locals) in + List.iter (fun name -> Hashtbl.remove captured_locals name) declared_vars; + (higher_vars, declared_vars, captured_vars) + (** + This method should be called right after leaving a scope. + @return List of vars names used in finished scope, but declared in higher scopes + *) + method pop_used : string list = match self#pop with (higher_vars, _, _) -> higher_vars + (** + This method should be called right after leaving a scope. + @return List of vars names declared in finished scope + *) + method pop_declared : string list = match self#pop with (_, declared_vars, _) -> declared_vars + (** + Get current list of captured variables. + After leaving a scope all vars declared in that scope get removed from a list of captured variables. + *) + method pop_captured : string list = match self#pop with (_, _, captured_vars) -> captured_vars + (** + Specify local var name declared in current scope + *) + method declared (name:string) : unit = + match declared_locals with + | [] -> assert false + | current :: _ -> Hashtbl.replace current name name + (** + Specify local var name used in current scope + *) + method used (name:string) : unit = + match used_locals with + | [] -> assert false + | current :: _ -> Hashtbl.replace current name name + (** + Mark specified vars as captured by closures. + *) + method captured (var_names:string list) : unit = + List.iter (fun name -> Hashtbl.replace captured_locals name name) var_names + end + +(** + Base class for type builders +*) +class virtual type_builder ctx wrapper = + object (self) + (** This is required to make wrapper accessible by extending classes *) + val wrapper = wrapper + (** This is required to make conext accessible by extending classes *) + val ctx = ctx + (** List of types for "use" section *) + val use_table = Hashtbl.create 50 + (** Output buffer *) + val mutable buffer = Buffer.create 1024 + (** Cache for generated conent *) + val mutable contents = "" + (** Intendation used for each line written *) + val mutable indentation = "" + (** Expressions nesting. E.g. "if(callFn(ident))" will be represented as [ident, callFn, if] *) + val mutable expr_hierarchy : texpr list = [] + (** Object to collect local vars declarations and usage as we iterate through methods' expressions *) + val vars = new local_vars + (** + Get PHP namespace path + *) + method get_namespace = + match get_php_prefix ctx with + | [] -> get_real_path wrapper#get_namespace + | prefix -> get_real_path (prefix @ wrapper#get_namespace) + (** + Get type name + *) + method get_name : string = get_real_name wrapper#get_name + (** + Get full type path + *) + method get_type_path : path = + match wrapper#get_type_path with + | (path, name) -> (get_real_path path, get_real_name name) + (** + Returns hx source file name where this type was declared + *) + method get_source_file : string = wrapper#get_source_file + (** + Writes type declaration line to output buffer. + E.g. "class SomeClass extends Another implements IFace" + *) + method virtual private write_declaration : unit + (** + Writes type body to output buffer. + E.g. for "class SomeClass { }" writes part. + *) + method virtual private write_body : unit + (** + Writes expressions for `__hx__init` method + *) + method virtual private write_hx_init_body : unit + (** + Writes additional initialization code, which should be called before `__hx__init()` + *) + method virtual private write_pre_hx_init : unit + (** + Writes initialization code for type instances + *) + method virtual private write_instance_initialization : unit + (** + Indicates if type should be declared as `final` + *) + method is_final = false + (** + Indicates if `field` should be declared as `final` + *) + method is_final_field (field:tclass_field) : bool = false + (** + Increase indentation by one level + *) + method indent_more = + indentation <- indentation ^ "\t"; + (** + Decrease indentation by one level + *) + method indent_less = + indentation <- String.make ((String.length indentation) - 1) '\t'; + (** + Set indentation level (starting from zero for no indentation) + *) + method indent level = + indentation <- String.make level '\t'; + (** + Indicates if class has user-defined static __init__ method + @see http://old.haxe.org/doc/advanced/magic#initialization-magic + *) + method has_magic_init = match wrapper#get_magic_init with None -> false | Some _ -> true + (** + Returns generated file contents + *) + method get_contents = + if (String.length contents) = 0 then begin + self#write_declaration; + self#write_line " {"; (** opening bracket for a class *) + self#write_body; + if wrapper#needs_initialization then self#write_hx_init; + self#indent 0; + self#write_line "}"; (** closing bracket for a class *) + self#write_empty_lines; + let boot_class = self#use boot_type_path in + (* Boot initialization *) + if boot_type_path = self#get_type_path then + self#write_statement (boot_class ^ "::__hx__init()"); + (*let php_class = get_full_type_name ~escape:true ~omit_first_slash:true (add_php_prefix ctx self#get_type_path)*) + let haxe_class = match wrapper#get_type_path with (path, name) -> String.concat "." (path @ [name]) in + self#write_statement (boot_class ^ "::registerClass(" ^ (self#get_name) ^ "::class, '" ^ haxe_class ^ "')"); + self#write_rtti_meta; + self#write_pre_hx_init; + (* Current class initialization *) + if wrapper#needs_initialization && boot_type_path <> self#get_type_path then + self#write_statement (self#get_name ^ "::__hx__init()"); + let body = Buffer.contents buffer in + Buffer.clear buffer; + self#write_header; + self#write "\n"; + let header = Buffer.contents buffer in + contents <- header ^ body; + end; + contents + (** + Adds type to "use" section if not added yet. + If it's a top-level type then type name returned without adding to "use" section. + @return Unique alias for specified type. + *) + method use ?prefix (type_path:path) = + if type_path = wrapper#get_type_path then + self#get_name + else + let type_path = match type_path with (pack, name) -> (pack, get_real_name name) in + let type_path = + match prefix with + | Some false -> type_path + | _ -> add_php_prefix ctx type_path + in + let module_path = get_module_path type_path in + match type_path with + | ([], type_name) -> "\\" ^ type_name + | _ -> + let alias_source = ref (List.rev module_path) in + let get_alias_next_part () = + match !alias_source with + | [] -> failwith ("Failed to find already used type: " ^ get_full_type_name type_path) + | name :: rest -> + alias_source := rest; + String.capitalize name + and added = ref false + and alias = ref (get_type_name type_path) in + if !alias = self#get_name then + alias := get_alias_next_part () ^ !alias; + while not !added do + try + if (get_module_path type_path) <> wrapper#get_namespace && type_name_used_in_namespace ctx !alias wrapper#get_namespace then + alias := get_alias_next_part () ^ !alias + else + let used_type = Hashtbl.find use_table !alias in + if used_type = type_path then + added := true + else + alias := get_alias_next_part () ^ !alias; + with + | Not_found -> + Hashtbl.add use_table !alias type_path; + added := true + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + done; + !alias + (** + Extracts type path from Type.t value and execute self#use on it + @return Unique alias for specified type. + *) + method use_t (t_inst:Type.t) = + match follow t_inst with + | TEnum (tenum, _) -> self#use tenum.e_path + | TInst (tcls, _) -> + (match tcls.cl_kind with + | KTypeParameter _ -> "mixed" + | _ -> + (match tcls.cl_path with + | ([], "String") -> "string" + | _ -> self#use ~prefix:(not tcls.cl_extern) tcls.cl_path + ) + ) + | TFun _ -> self#use ~prefix:false ([], "Closure") + | TAnon _ -> "object" + | TDynamic _ -> "mixed" + | TLazy _ -> failwith "TLazy not implemented" + | TMono mono -> + (match !mono with + | None -> "mixed" + | Some t -> self#use_t t + ) + | TType _ -> failwith "TType not implemented" + | TAbstract (abstr, _) -> + match abstr.a_path with + | ([],"Int") -> "int" + | ([],"Float") -> "float" + | ([],"Bool") -> "bool" + | ([],"Void") -> "void" + | ([],"Enum") -> "Enum" + | ([], "Class") -> "Class" + | _ when Meta.has Meta.CoreType abstr.a_meta -> "mixed" + | _ -> self#use_t abstr.a_this + (** + Indicates if there is no constructor in inheritance chain of this type. + Own constructor is ignored. + *) + method private extends_no_constructor = true + (** + Indicates whether current expression nesting level is a top level of a block + *) + method private parent_expr_is_block single_expr_is_not_block = + let rec expr_is_block expr parents no_parent_is_block = + match expr.eexpr with + | TBlock [_] when single_expr_is_not_block -> + (match parents with + | { eexpr = TBlock _ } :: _ -> true + | { eexpr = TFunction _ } :: _ -> true + | _ :: _ -> false + | [] -> no_parent_is_block + ) + | TBlock _ -> true + | TIf (_, if_expr, Some else_expr) -> + if (expr_is_block if_expr [] false) || (expr_is_block else_expr [] false) then + true + else + (match parents with + | parent :: rest -> expr_is_block parent rest true + | [] -> false + ) + | TIf (_, _, None) -> true + | TTry _ -> true + | TWhile _ -> true + | TFor _ -> true + | TSwitch _ -> true + | _ -> false + in + match expr_hierarchy with + | _ :: parent :: rest -> expr_is_block parent rest true + | _ -> false + (** + Returns parent expression (bypasses casts and metas) + *) + method private parent_expr = + let rec traverse expr parents = + match expr.eexpr with + | TCast (_, None) + | TMeta _ -> + (match parents with + | parent :: rest -> traverse parent rest + | [] -> None + ) + | _ -> Some expr + in + match expr_hierarchy with + | _ :: parent :: rest -> traverse parent rest + | _ -> None + (** + Indicates if parent expression is a call (bypasses casts and metas) + *) + method private parent_expr_is_call = + match self#parent_expr with + | Some { eexpr = TCall _ } -> true + | _ -> false + (** + Position of currently generated code in source hx files + *) + method private pos = + match expr_hierarchy with + | { epos = pos } :: _ -> pos + | _ -> dummy_pos + (** + Add a function call to "dereference" part of expression to avoid "Cannot use temporary expression in write context" + erro in expressions like: + ``` + new MyClass().fieldName = 'value'; + ``` + *) + method private dereference expr = + let boot_cls = get_boot ctx in + let deref_field = PMap.find "deref" boot_cls.cl_statics in + match expr.eexpr with + | TField (target_expr, access) -> + { + expr with eexpr = TField ( + { + target_expr with eexpr = TCall ( + { + target_expr with eexpr = TField ( + { + target_expr with eexpr = TTypeExpr (TClassDecl boot_cls) + }, + FStatic (boot_cls, deref_field) + ) + }, + [ target_expr ] + ) + }, + access + ) + } + | TArray (target_expr, access_expr) -> + { + expr with eexpr = TArray ( + { + target_expr with eexpr = TCall ( + { + target_expr with eexpr = TField ( + { + target_expr with eexpr = TTypeExpr (TClassDecl boot_cls) + }, + FStatic (boot_cls, deref_field) + ) + }, + [ target_expr ] + ) + }, + access_expr + ) + } + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes specified string to output buffer + *) + method private write str = + Buffer.add_string buffer str + (** + Writes fixed amount of empty lines (E.g. between methods) + *) + method private write_empty_lines = + self#write "\n"; + self#write "\n" + (** + Writes current indentation to output buffer + *) + method private write_indentation = + Buffer.add_string buffer indentation + (** + Writes specified line to output buffer and appends \n + *) + method private write_line line = + Buffer.add_string buffer (indentation ^ line ^ "\n") + (** + Writes specified statement to output buffer and appends ";\n" + *) + method private write_statement statement = + Buffer.add_string buffer (indentation ^ statement ^ ";\n") + (** + Build file header ( self#write_line (" * " ^ s)); + if ctx.debug then self#write_line (" * Haxe source file: " ^ self#get_source_file); + self#write_line " */"; + self#write "\n"; + let namespace = self#get_namespace in + if List.length namespace > 0 then + self#write_line ("namespace " ^ (String.concat "\\" namespace) ^ ";\n"); + self#write_use + (** + Build "use" statements + *) + method private write_use = + self#indent 0; + let write alias type_path = + if (get_module_path type_path) <> wrapper#get_namespace then + if get_type_name type_path = alias then + self#write_statement ("use " ^ (get_full_type_name type_path)) + else + let full_name = get_full_type_name type_path in + self#write_statement ("use " ^ full_name ^ " as " ^ alias) + in + Hashtbl.iter write use_table + (** + Writes array item declaration to output buffer and appends ",\n" + *) + method private write_array_item ?key value_expr = + (match key with + | None -> + self#write_indentation; + self#write_expr value_expr; + | Some key_str -> + self#write (indentation ^ "\"" ^ (String.escaped key_str) ^ "\" => "); + self#write_expr value_expr + ); + self#write ",\n" + (** + Generates PHP docblock to output buffer. + *) + method private write_doc doc_block = + match doc_block with + | DocVar (type_name, doc) -> + self#write_line "/**"; + self#write_line (" * @var " ^ type_name); + (match doc with + | None -> () + | Some txt -> self#write_doc_description txt + ); + self#write_line " */" + | DocClass doc -> + (match doc with + | None -> () + | Some txt -> + self#write_line "/**"; + self#write_doc_description txt; + self#write_line " */" + ) + | DocMethod (args, return, doc) -> + self#write_method_docblock args return doc + (** + Writes description section of docblocks + *) + method write_doc_description (doc:string) = + let lines = Str.split (Str.regexp "\n") (String.trim doc) + and write_line line = + let trimmed = String.trim line in + if String.length trimmed > 0 then ( + if String.get trimmed 0 = '*' then + self#write_line (" " ^ trimmed) + else + self#write_line (" * " ^ trimmed) + ) + in + List.iter write_line lines + (** + Generates docblock for a method and writes it to output buffer + *) + method write_method_docblock args return_type doc = + self#write_line "/**"; + (match doc with + | None -> () + | Some txt -> + self#write_doc_description txt; + self#write_line " * " + ); + let write_arg arg = + match arg with + | (arg_name, is_optional, arg_type) -> + self#write_line (" * @param " ^ (self#use_t arg_type) ^ " $" ^ arg_name) + in + List.iter write_arg args; + if List.length args > 0 then self#write_line " * "; + self#write_line (" * @return " ^ (self#use_t return_type)); + self#write_line " */" + (** + Writes rtti meta to output buffer + *) + method write_rtti_meta = + match Codegen.build_metadata ctx wrapper#get_module_type with + | None -> () + | Some meta_expr -> + let boot_class = self#use boot_type_path in + self#write (boot_class ^ "::registerMeta(" ^ (self#get_name) ^ "::class, "); + self#write_expr meta_expr; + self#write ");\n" + (** + Writes expression to output buffer + *) + method private write_expr (expr:texpr) = + expr_hierarchy <- expr :: expr_hierarchy; + (match expr.eexpr with + | TConst const -> self#write_expr_const const + | TLocal var -> + vars#used var.v_name; + self#write ("$" ^ var.v_name) + | TArray (target, index) -> self#write_expr_array_access target index + | TBinop (operation, expr1, expr2) when needs_dereferencing expr1 -> + self#write_expr { expr with eexpr = TBinop (operation, self#dereference expr1, expr2) } + | TBinop (operation, expr1, expr2) -> self#write_expr_binop operation expr1 expr2 + | TField (fexpr, access) when is_php_global expr -> self#write_expr_php_global expr + | TField (fexpr, access) when is_php_class_const expr -> self#write_expr_php_class_const expr + | TField (expr, access) -> self#write_expr_field expr access + | TTypeExpr mtype -> self#write_expr_type mtype + | TParenthesis expr -> + self#write "("; + self#write_expr expr; + self#write ")" + | TObjectDecl fields -> self#write_expr_object_declaration fields + | TArrayDecl exprs -> self#write_expr_array_decl exprs + | TCall (target, [arg1; arg2]) when is_std_is target && instanceof_compatible arg1 arg2 -> self#write_expr_lang_instanceof [arg1; arg2] + | TCall ({ eexpr = TLocal { v_name = name }}, args) when is_magic expr -> self#write_expr_magic name args + | TCall ({ eexpr = TField (expr, access) }, args) when is_string expr -> self#write_expr_call_string expr access args + | TCall (expr, args) when is_lang_extern expr -> self#write_expr_call_lang_extern expr args + | TCall (target, args) when is_sure_var_field_access target -> self#write_expr_call (parenthesis target) args + | TCall (target, args) -> self#write_expr_call target args + | TNew (_, _, args) when is_string expr -> write_args buffer self#write_expr args + | TNew (tcls, _, args) -> self#write_expr_new tcls args + | TUnop (operation, flag, target_expr) when needs_dereferencing target_expr -> + self#write_expr { expr with eexpr = TUnop (operation, flag, self#dereference target_expr) } + | TUnop (operation, flag, expr) -> self#write_expr_unop operation flag expr + | TFunction fn -> self#write_expr_function fn + | TVar (var, expr) -> self#write_expr_var var expr + | TBlock exprs -> self#write_expr_block expr + | TFor (var, iterator, body) -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + | TIf (condition, if_expr, else_expr) -> self#write_expr_if condition if_expr else_expr + | TWhile (condition, expr, do_while) -> self#write_expr_while condition expr do_while + | TSwitch (switch, cases, default ) -> self#write_expr_switch switch cases default + | TTry (try_expr, catches) -> self#write_expr_try_catch try_expr catches + | TReturn expr -> self#write_expr_return expr + | TBreak -> self#write_expr_loop_flow "break" + | TContinue -> self#write_expr_loop_flow "continue" + | TThrow expr -> self#write_expr_throw expr + | TCast (expr, mtype) -> self#write_expr_cast expr mtype + | TMeta (_, expr) -> self#write_expr expr + | TEnumParameter (expr, constructor, index) -> self#write_expr_enum_parameter expr constructor index + ); + expr_hierarchy <- List.tl expr_hierarchy + (** + Writes type initialization method. + *) + method private write_hx_init = + self#write_empty_lines; + self#indent 1; + self#write_line "/**"; + self#write_line " * @internal"; + self#write_line " * @access private"; + self#write_line " */"; + self#write_line "static public function __hx__init ()"; + self#write_line "{"; + self#indent_more; + self#write_statement "static $called = false"; + self#write_statement "if ($called) return"; + self#write_statement "$called = true"; + self#write "\n"; + vars#clear; + (match wrapper#get_magic_init with + | None -> () + | Some expr -> self#write_fake_block expr + ); + self#write "\n"; + vars#clear; + self#write_hx_init_body; + self#indent 1; + self#write_line "}" + (** + Writes `continue N` or `break N` with required N depending on nearest parent loop and amount of `switch` between loop and + `continue/break` + *) + method private write_expr_loop_flow word = + let rec count_N parent_exprs count = + match parent_exprs with + | [] -> count + | { eexpr = TWhile _ } :: _ -> count + | { eexpr = TSwitch _ } :: rest -> count_N rest (count + 1) + | _ :: rest -> count_N rest count + in + let count = count_N expr_hierarchy 1 in + if count > 1 then + self#write (word ^ " " ^ (string_of_int count)) + else + self#write word + (** + Writes TConst to output buffer + *) + method private write_expr_const const = + match const with + | TFloat str -> self#write str + | TString str -> self#write ("\"" ^ (escape_bin str) ^ "\"") + | TBool value -> self#write (if value then "true" else "false") + | TNull -> self#write "null" + | TThis -> self#write "$this" + | TSuper -> self#write "parent" + | TInt value -> + (* See https://github.com/HaxeFoundation/haxe/issues/5289 *) + if value = Int32.min_int then + self#write "((int)-2147483648)" + else + self#write (Int32.to_string value) + (** + Writes TArrayDecl to output buffer + *) + method private write_expr_array_decl exprs = + match exprs with + | [] -> self#write ("new " ^ (self#use array_type_path) ^ "()") + | [expr] -> + self#write ((self#use array_type_path) ^ "::wrap(["); + self#write_expr expr; + self#write "])" + | _ -> + self#write ((self#use array_type_path) ^ "::wrap([\n"); + self#indent_more; + List.iter (fun expr -> self#write_array_item expr) exprs; + self#indent_less; + self#write_indentation; + self#write "])" + (** + Writes TArray to output buffer + *) + method private write_expr_array_access target index = + let write_index left_bracket right_bracket = + self#write left_bracket; + self#write_expr index; + self#write right_bracket + in + let write_fast_access () = + self#write "("; + self#write_expr target; + self#write "->arr"; + write_index "[" "] ?? null)" + and write_normal_access () = + self#write_expr target; + write_index "[" "]" + in + let write_depending_on e = + match (reveal_expr e).eexpr with + | TArray (t, i) when t == target -> + write_normal_access () + | _ -> + write_fast_access () + in + match follow target.etype with + | TInst ({ cl_path = path }, _) when path = array_type_path -> + (match self#parent_expr with + | None -> write_fast_access () + | Some expr -> + match (reveal_expr expr).eexpr with + | TUnop (op, _, e) when is_modifying_unop op -> + write_depending_on e + | TBinop (OpAssign, e, _) + | TBinop (OpAssignOp _, e, _) + | TField (e, _) + | TArray (e, _) -> + write_depending_on e + | _ -> + write_fast_access () + ) + | _ -> + write_normal_access () + (** + Writes TVar to output buffer + *) + method private write_expr_var var expr = + vars#declared var.v_name; + self#write ("$" ^ var.v_name ^ " = "); + match expr with + | None -> self#write "null" + | Some expr -> self#write_expr expr + (** + Writes TFunction to output buffer + *) + method private write_expr_function ?name func = + match name with + | None -> self#write_closure_declaration func self#write_function_arg + | Some "__construct" -> self#write_constructor_function_declaration func self#write_function_arg + | Some name -> self#write_method_function_declaration name func self#write_function_arg + (** + Writes constructor declaration (except visibility and `static` keywords) to output buffer + *) + method private write_constructor_function_declaration func write_arg = + self#write ("function __construct ("); + write_args buffer write_arg func.tf_args; + self#write ") {\n"; + self#indent_more; + self#write_instance_initialization; + let func = inject_defaults ctx func in + begin match func.eexpr with + | TBlock [] -> () + | _ -> self#write_fake_block func; + end; + self#indent_less; + self#write_indentation; + self#write "}" + (** + Writes method declaration (except visibility and `static` keywords) to output buffer + *) + method private write_method_function_declaration name func write_arg = + let by_ref = if is_ref func.tf_type then "&" else "" in + self#write ("function " ^ by_ref ^ name ^ " ("); + write_args buffer write_arg func.tf_args; + self#write ") "; + self#write_expr (inject_defaults ctx func) + (** + Writes closure declaration to output buffer + *) + method private write_closure_declaration func write_arg = + vars#dive; + self#write "function ("; + write_args buffer write_arg func.tf_args; + self#write ")"; + (* Generate closure body to separate buffer *) + let original_buffer = buffer in + buffer <- Buffer.create 256; + self#write_expr (inject_defaults ctx func); + let body = Buffer.contents buffer in + buffer <- original_buffer; + (* Capture local vars used in closures *) + let used_vars = vars#pop_used in + vars#captured used_vars; + self#write " "; + if List.length used_vars > 0 then begin + self#write " use ("; + write_args buffer (fun name -> self#write ("&$" ^ name)) used_vars; + self#write ") " + end; + self#write body + (** + Writes TBlock to output buffer + *) + method private write_expr_block block_expr = + (* Check if parent expr could not contain blocks in PHP, and this block needs to be wrapped in a closure. *) + let needs_closure = match self#parent_expr with + | None -> false + | Some e -> + match e.eexpr with + | TIf (_, _, _) -> false + | TWhile (_, _, _) -> false + | TTry (_, _) -> false + | TFor (_, _, _) -> false + | TFunction _ -> false + | TBlock _ -> false + | TSwitch (_, _, _) -> false + | _ -> true + in + if needs_closure then + begin + self#write "("; + self#write_expr { + block_expr with eexpr = TFunction { + tf_args = []; + tf_type = block_expr.etype; + tf_expr = ensure_return_in_block block_expr; + } + }; + self#write ")()" + end + else + begin + let inline_block = self#parent_expr_is_block false in + self#write_as_block ~inline:inline_block block_expr + end + (** + Emulates TBlock for parent expression and writes `expr` as inlined block + *) + method private write_fake_block expr = + self#write_indentation; + let fake_block = { expr with eexpr = TBlock [expr] } in + expr_hierarchy <- fake_block :: expr_hierarchy; + self#write_as_block ~inline:true expr; + expr_hierarchy <- List.tl expr_hierarchy + (** + Writes "{ }" to output buffer + *) + method private write_as_block ?inline ?unset_locals expr = + let unset_locals = match unset_locals with Some true -> true | _ -> false + and exprs = match expr.eexpr with TBlock exprs -> exprs | _ -> [expr] in + let write_body () = + let write_expr expr = + self#write_expr expr; + match expr.eexpr with + | TBlock _ | TIf _ | TTry _ | TSwitch _ | TWhile (_, _, NormalWhile) -> self#write "\n" + | _ -> self#write ";\n" + in + let write_expr_with_indent expr = + self#write_indentation; + write_expr expr + in + let write_exprs () = + match exprs with + | [] -> () + | first :: rest -> + write_expr first; (* write first expression without indentation in case of block inlining *) + List.iter write_expr_with_indent rest + in + if unset_locals then + begin + let original_buffer = buffer in + buffer <- Buffer.create 256; + vars#dive; + write_exprs(); + let body = Buffer.contents buffer in + buffer <- original_buffer; + let locals = vars#pop_captured in + if List.length locals > 0 then begin + self#write ("unset($" ^ (String.concat ", $" locals) ^ ");\n"); + self#write_indentation + end; + self#write body + end + else + write_exprs() + in + match inline with + | Some true -> write_body () + | _ -> + self#write "{\n"; + self#indent_more; + (match exprs with + | [] -> () + | _ -> + self#write_indentation; (* indentation for the first expression in block *) + write_body () + ); + self#indent_less; + self#write_indentation; + self#write "}" + (** + Writes TReturn to output buffer + *) + method private write_expr_return expr = + match expr with + | None -> self#write "return"; + | Some expr -> + self#write "return "; + self#write_expr expr + (** + Writes TThrow to output buffer + *) + method private write_expr_throw expr = + self#write "throw "; + if is_native_exception expr.etype then + self#write_expr expr + else if sure_extends_extern expr.etype || is_dynamic_type expr.etype then + begin + self#write "(is_object($__hx__throw = "; + self#write_expr expr; + self#write (") && $__hx__throw instanceof \\Throwable ? $__hx__throw : new " ^ (self#use hxexception_type_path) ^ "($__hx__throw))") + end + else + begin + self#write ("new " ^ (self#use hxexception_type_path) ^ "("); + self#write_expr expr; + self#write ")" + end + (** + Writes try...catch to output buffer + *) + method private write_expr_try_catch try_expr catches = + let catching_dynamic = ref false in + let haxe_exception = self#use hxexception_type_path + and first_catch = ref true in + let write_catch (var, expr) = + let dynamic = ref false in + (match follow var.v_type with + | TInst ({ cl_path = ([], "String") }, _) -> self#write "if (is_string($__hx__real_e)) {\n" + | TAbstract ({ a_path = ([], "Float") }, _) -> self#write "if (is_float($__hx__real_e)) {\n" + | TAbstract ({ a_path = ([], "Int") }, _) -> self#write "if (is_int($__hx__real_e)) {\n" + | TAbstract ({ a_path = ([], "Bool") }, _) -> self#write "if (is_bool($__hx__real_e)) {\n" + | TDynamic _ -> + dynamic := true; + catching_dynamic := true; + if not !first_catch then self#write "{\n" + | vtype -> self#write ("if ($__hx__real_e instanceof " ^ (self#use_t vtype) ^ ") {\n") + ); + if !dynamic && !first_catch then + begin + self#write ("$" ^ var.v_name ^ " = $__hx__real_e;\n"); + self#write_indentation; + self#write_as_block ~inline:true expr; + end + else + begin + self#indent_more; + self#write_statement ("$" ^ var.v_name ^ " = $__hx__real_e"); + self#write_indentation; + self#write_as_block ~inline:true expr; + self#indent_less; + self#write_indentation; + self#write "}"; + end; + if not !dynamic then self#write " else "; + first_catch := false; + in + self#write "try "; + self#write_as_block try_expr; + self#write " catch (\\Throwable $__hx__caught_e) {\n"; + self#indent_more; + if ctx.debug then + self#write_statement ((self#use (["haxe"], "CallStack")) ^ "::saveExceptionTrace($__hx__caught_e)"); + self#write_statement ("$__hx__real_e = ($__hx__caught_e instanceof " ^ haxe_exception ^ " ? $__hx__caught_e->e : $__hx__caught_e)"); + self#write_indentation; + List.iter write_catch catches; + if not !catching_dynamic then + self#write " throw $__hx__caught_e;\n" + else + (match catches with [_] -> () | _ -> self#write "\n"); + self#indent_less; + self#write_indentation; + self#write "}" + (** + Writes TCast to output buffer + *) + method private write_expr_cast expr (mtype:module_type option) = + match mtype with + | None -> self#write_expr expr + | Some mtype -> + self#write ((self#use boot_type_path) ^ "::typedCast("); + self#write_expr_type mtype; + self#write ", "; + self#write_expr expr; + self#write ")" + (** + Write Haxe->PHP magic function call + @see http://old.haxe.org/doc/advanced/magic#php-magic + *) + method private write_expr_magic name args = + let error = error_message self#pos ("Invalid arguments for " ^ name ^ " magic call") in + match args with + | [] -> failwith error + | { eexpr = TConst (TString code) } as expr :: args -> + (match name with + | "__php__" -> + (match expr.eexpr with + | TConst (TString php) -> + Codegen.interpolate_code ctx php args self#write self#write_expr self#pos + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + ) + | "__call__" -> + self#write (code ^ "("); + write_args buffer self#write_expr args; + self#write ")" + | "__physeq__" -> + (match args with + | [expr2] -> self#write_expr_binop OpEq expr expr2 + | _ -> failwith error + ) + | "__var__" -> + (match args with + | [] -> + self#write ("$" ^ code) + | [expr2] -> + self#write ("$" ^ code ^ "["); + self#write_expr expr2; + self#write "]" + | _ -> failwith error + ) + | _ -> failwith error + ) + | [expr1; expr2] -> + (match name with + | "__physeq__" -> + (match args with + | [expr1; expr2] -> self#write_expr_binop OpEq expr1 expr2 + | _ -> failwith error + ) + | _ -> failwith error + ) + | _ -> failwith error + (** + Writes TTypeExpr to output buffer + *) + method private write_expr_type (mtype:module_type) = + let ttype = type_of_module_type mtype in + match expr_hierarchy with + | _ :: { eexpr = TField _ } :: _ -> self#write (self#use_t ttype) + | _ -> + let class_name = + match self#use_t ttype with + | "int" -> "'Int'" + | "float" -> "'Float'" + | "bool" -> "'Bool'" + | "string" -> "'String'" + | "mixed" -> "'Dynamic'" + | "Enum" -> "'Enum'" + | "Class" -> "'Class'" + | name -> name ^ "::class" + in + self#write ((self#use boot_type_path) ^ "::getClass(" ^ class_name ^ ")") + (** + Writes binary operation to output buffer + *) + method private write_expr_binop operation expr1 expr2 = + let write_method method_name = + self#write (method_name ^ "("); + self#write_expr expr1; + self#write ", "; + self#write_expr expr2; + self#write ")" + in + let write_for_concat expr = + if ((is_constant expr) && not (is_constant_null expr)) || (is_concatenation expr) then + self#write_expr expr + else begin + self#write "("; + self#write_expr expr; + self#write "??'null')" + end + and write_binop ?writer ?right_writer str = + let write_left = match writer with None -> self#write_expr | Some writer -> writer in + let write_right = match right_writer with None -> write_left | Some writer -> writer + and need_parenthesis = + match expr_hierarchy with + | _ :: { eexpr = TBinop (parent, _, _) } :: _ -> need_parenthesis_for_binop operation parent + | _ -> false + in + if need_parenthesis then self#write "("; + write_left expr1; + self#write str; + write_right expr2; + if need_parenthesis then self#write ")" + and compare_strings op = + write_method "strcmp"; + self#write (op ^ "0") + in + let compare op = + if is_string expr1 && is_string expr2 then + compare_strings op + else + write_binop op + in + match operation with + | OpAdd -> + if (is_string expr1) || (is_string expr2) then + write_binop ~writer:write_for_concat " . " + else if (is_unknown_type expr1.etype) && (is_unknown_type expr2.etype) then + write_method ((self#use boot_type_path) ^ "::addOrConcat") + else + write_binop " + " + | OpMult -> write_binop " * " + | OpDiv -> write_binop " / " + | OpSub -> write_binop " - " + | OpAssign -> write_binop " = " + | OpEq -> + if need_boot_equal expr1 expr2 then + write_method ((self#use boot_type_path) ^ "::equal") + else + write_binop " === " + | OpNotEq -> + if need_boot_equal expr1 expr2 then + begin + self#write "!"; + write_method ((self#use boot_type_path) ^ "::equal") + end + else + write_binop " !== " + | OpGt -> compare " > " + | OpGte -> compare " >= " + | OpLt -> compare " < " + | OpLte -> compare " <= " + | OpAnd -> write_binop " & " + | OpOr -> write_binop " | " + | OpXor -> write_binop " ^ " + | OpBoolAnd -> write_binop " && " + | OpBoolOr -> write_binop " || " + | OpShl -> write_binop " << " + | OpShr -> write_binop " >> " + | OpMod -> + if is_int expr1 && is_int expr2 then + write_binop " % " + else + write_method "fmod" + | OpUShr -> write_method ((self#use boot_type_path) ^ "::shiftRightUnsigned") + | OpAssignOp OpAdd -> + if (is_string expr1) then + begin + self#write_expr expr1; + self#write " = "; + write_binop ~writer:write_for_concat " . " + end + else if (is_unknown_type expr1.etype) && (is_unknown_type expr2.etype) then + begin + self#write_expr expr1; + self#write " = "; + write_method ((self#use boot_type_path) ^ "::addOrConcat") + end + else + write_binop " += " + | OpAssignOp OpMult -> write_binop " *= " + | OpAssignOp OpDiv -> write_binop " /= " + | OpAssignOp OpSub -> write_binop " -= " + | OpAssignOp OpAnd -> write_binop " &= " + | OpAssignOp OpOr -> write_binop " |= " + | OpAssignOp OpXor -> write_binop " ^= " + | OpAssignOp OpShl -> write_binop " <<= " + | OpAssignOp OpShr -> write_binop " >>= " + | OpAssignOp OpMod -> + if is_int expr1 && is_int expr2 then + write_binop " %= " + else + write_method "fmod" + | OpAssignOp OpUShr -> + self#write_expr expr1; + self#write " = "; + write_method ((self#use boot_type_path) ^ "::shiftRightUnsigned") + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes TUnOp to output buffer + *) + method private write_expr_unop operation flag expr = + let write_unop operation = + match operation with + | Increment -> self#write "++" + | Decrement -> self#write "--" + | Not -> self#write "!" + | Neg -> self#write "-" + | NegBits -> self#write "~" + in + match flag with + | Prefix -> + write_unop operation; + self#write_expr expr + | Postfix -> + self#write_expr expr; + write_unop operation + (** + Writes TField to output buffer + *) + method private write_expr_field expr access = + let write_access access_str field_str = + let access_str = ref access_str in + let expr_without_casts = reveal_expr expr in + (match expr_without_casts.eexpr with + | TNew _ + | TArrayDecl _ + | TObjectDecl _ -> self#write_expr (parenthesis expr) + | TConst TSuper -> + self#write "parent"; + access_str := "::" + | _ -> self#write_expr expr + ); + self#write (!access_str ^ field_str) + in + match (follow expr.etype, access) with + | (TInst ({ cl_path = ([], "String") }, _), FInstance (_, _, { cf_name = "length"; cf_kind = Var _ })) -> + self#write "strlen("; + self#write_expr expr; + self#write ")" + | (_, FInstance (_, _, field)) -> write_access "->" (field_name field) + | (_, FStatic (_, ({ cf_kind = Var _ } as field))) -> + (match (reveal_expr expr).eexpr with + | TTypeExpr _ -> write_access "::" ("$" ^ (field_name field)) + | _ -> write_access "->" (field_name field) + ) + | (_, FStatic (_, ({ cf_kind = Method MethDynamic } as field))) -> + (match expr_hierarchy with + | _ :: { eexpr = TCall ({ eexpr = TField (e, a) }, _) } :: _ when a == access -> + self#write "("; + write_access "::" ("$" ^ (field_name field)); + self#write ")" + | _ -> + write_access "::" ("$" ^ (field_name field)) + ) + | (_, FStatic (_, ({ cf_kind = Method _ } as field))) -> self#write_expr_field_static expr field + | (_, FAnon field) -> + let written_as_probable_string = self#write_expr_field_if_string expr (field_name field) in + if not written_as_probable_string then write_access "->" (field_name field) + | (_, FDynamic field_name) -> + let written_as_probable_string = self#write_expr_field_if_string expr field_name in + if not written_as_probable_string then write_access "->" field_name + | (_, FClosure (tcls, field)) -> self#write_expr_field_closure tcls field expr + | (_, FEnum (_, field)) -> + if is_enum_constructor_with_args field then + if not self#parent_expr_is_call then + begin + self#write (self#use boot_type_path ^ "::closure("); + self#write_expr expr; + (match (reveal_expr expr).eexpr with + | TTypeExpr _ -> self#write "::class" + | _ -> self#write "->phpClassName" + ); + self#write (", '" ^ field.ef_name ^ "')") + end + else + write_access "::" field.ef_name + else + begin + write_access "::" field.ef_name; + self#write "()" + end + + (** + Writes field access on Dynamic expression to output buffer + *) + method private write_expr_field_if_string expr field_name = + (* Special case for String fields *) + match field_name with + | "length" + | "toUpperCase" + | "toLowerCase" + | "charAt" + | "indexOf" + | "lastIndexOf" + | "split" + | "toString" + | "substring" + | "substr" + | "charCodeAt" -> + self#write ((self#use hxdynamicstr_type_path) ^ "::wrap("); + self#write_expr expr; + self#write (")->" ^ field_name); + true + | _ -> + false + (** + Convert field access expressions for strings to native PHP string functions and write to output buffer + *) + method private write_expr_call_string expr access args = + match access with + | FInstance (_, _, ({ cf_kind = Method _ } as field)) -> + self#write ((self#use hxstring_type_path) ^ "::" ^ (field_name field) ^ "("); + write_args buffer self#write_expr (expr :: args); + self#write ")" + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes FStatic field access for methods to output buffer + *) + method private write_expr_field_static expr field = + let write_expr () = + match expr.eexpr with + | TTypeExpr (TClassDecl { cl_path = ([], "String") }) -> self#write (self#use hxstring_type_path) + | _ -> self#write_expr expr + and operator = + match (reveal_expr expr).eexpr with + | TTypeExpr _ -> "::" + | _ -> "->" + in + match expr_hierarchy with + | _ :: { eexpr = TCall ({ eexpr = TField (e, FStatic (_, f)) }, _) } :: _ when e == expr && f == field -> + write_expr (); + self#write (operator ^ (field_name field)) + | _ -> + let (args, return_type) = get_function_signature field in + self#write "function("; + write_args buffer (self#write_arg true) args; + self#write ") { return "; + write_expr (); + self#write (operator ^ (field_name field) ^ "("); + write_args buffer (self#write_arg false) args; + self#write "); }" + (** + Writes FClosure field access to output buffer + *) + method private write_expr_field_closure tcls field expr = + if is_dynamic_method field then + match expr.eexpr with + | TTypeExpr mtype -> + let class_name = self#use_t (type_of_module_type mtype) in + self#write (class_name ^ "::$" ^ (field_name field) ^ "'"); + | _ -> + self#write_expr expr; + self#write ("->" ^ (field_name field)) + else + let new_closure = "new " ^ (self#use hxclosure_type_path) in + match expr.eexpr with + | TTypeExpr mtype -> + let class_name = self#use_t (type_of_module_type mtype) in + self#write (new_closure ^ "(" ^ class_name ^ "::class, '" ^ (field_name field) ^ "')"); + | _ -> + self#write (new_closure ^ "("); + (match follow expr.etype with + | TInst ({ cl_path = ([], "String") }, []) -> + self#write ((self#use hxdynamicstr_type_path) ^ "::wrap("); + self#write_expr expr; + self#write ")" + | _ -> + self#write_expr expr + ); + self#write (", '" ^ (field_name field) ^ "')") + (** + Write anonymous object declaration to output buffer + *) + method private write_expr_object_declaration fields = + match fields with + | [] -> self#write ("new " ^ (self#use hxanon_type_path) ^ "()") + | _ -> + self#write ("new " ^ (self#use hxanon_type_path) ^ "([\n"); + self#indent_more; + let write_field (key, value) = self#write_array_item ~key:key value in + List.iter write_field fields; + self#indent_less; + self#write_indentation; + self#write "])" + (** + Writes specified type to output buffer depending on type of expression. + *) + method private write_type type_expr = + match type_expr.eexpr with + | TTypeExpr (TClassDecl tcls) -> + self#write (self#use_t (TInst (tcls, []))) + | _ -> + if is_string type_expr then + self#write_expr type_expr + else begin + self#write "("; + self#write_expr type_expr; + self#write "->phpClassName)"; + end + (** + Write language specific expression declared in `php.PHP` extern + *) + method private write_expr_call_lang_extern expr args = + let name = match expr.eexpr with + | TField (_, FStatic (_, field)) -> field_name field + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + in + match name with + | "int" | "float" + | "string" | "bool" + | "object" | "array" -> self#write_expr_lang_cast name args + | "binop" -> self#write_expr_lang_binop args + | "instanceof" -> self#write_expr_lang_instanceof args + | "foreach" -> self#write_expr_lang_foreach args + | "construct" -> self#write_expr_lang_construct args + | "getField" -> self#write_expr_lang_get_field args + | "setField" -> self#write_expr_lang_set_field args + | "getStaticField" -> self#write_expr_lang_get_static_field args + | "setStaticField" -> self#write_expr_lang_set_static_field args + | "call" -> self#write_expr_lang_call args + | "staticCall" -> self#write_expr_lang_static_call args + | "arrayDecl" -> self#write_expr_lang_array_decl args + | "splat" -> self#write_expr_lang_splat args + | "suppress" -> self#write_expr_lang_suppress args + | "keepVar" -> () + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes splat operator (for `php.Syntax.splat()`) + *) + method private write_expr_lang_splat args = + match args with + | [ args_expr ] -> + self#write "..."; + self#write_expr args_expr + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes error suppression operator (for `php.Syntax.suppress()`) + *) + method private write_expr_lang_suppress args = + match args with + | [ args_expr ] -> + self#write "@"; + self#write_expr args_expr + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes native array declaration (for `php.Syntax.arrayDecl()`) + *) + method private write_expr_lang_array_decl args = + self#write "["; + write_args buffer (fun e -> self#write_expr e) args; + self#write "]" + (** + Writes a call to instance method (for `php.Syntax.call()`) + *) + method private write_expr_lang_call args = + match args with + | obj_expr :: method_expr :: args -> + self#write_expr obj_expr; + self#write "->{"; + self#write_expr method_expr; + self#write "}("; + write_args buffer (fun e -> self#write_expr e) args; + self#write ")" + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes a call to a static method (for `php.Syntax.staticCall()`) + *) + method private write_expr_lang_static_call args = + match args with + | type_expr :: method_expr :: args -> + self#write_type type_expr; + self#write "::{"; + self#write_expr method_expr; + self#write "}("; + write_args buffer (fun e -> self#write_expr e) args; + self#write ")" + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes field access for reading (for `php.Syntax.getField()`) + *) + method private write_expr_lang_get_field args = + match args with + | obj_expr :: field_expr :: [] -> + self#write_expr obj_expr; + self#write "->{"; + self#write_expr field_expr; + self#write "}" + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes field access for writing (for `php.Syntax.setField()`) + *) + method private write_expr_lang_set_field args = + match args with + | obj_expr :: field_expr :: value_expr :: [] -> + self#write_expr obj_expr; + self#write "->{"; + self#write_expr field_expr; + self#write "}"; + self#write " = "; + self#write_expr value_expr + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes static field access for reading (for `php.Syntax.getStaticField()`) + *) + method private write_expr_lang_get_static_field args = + match args with + | type_expr :: field_expr :: [] -> + self#write_type type_expr; + self#write "::${"; + self#write_expr field_expr; + self#write "}" + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes static field access for writing (for `php.Syntax.setField()`) + *) + method private write_expr_lang_set_static_field args = + match args with + | type_expr :: field_expr :: value_expr :: [] -> + self#write_expr type_expr; + self#write "::${"; + self#write_expr field_expr; + self#write "}"; + self#write " = "; + self#write_expr value_expr + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes `new` expression with class name taken local variable (for `php.Syntax.construct()`) + *) + method private write_expr_lang_construct args = + let (class_expr, args) = match args with + | class_expr :: args -> (class_expr, args) + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + in + self#write "new "; + self#write_expr class_expr; + self#write "("; + write_args buffer (fun e -> self#write_expr e) args; + self#write ")" + (** + Writes native php type conversion to output buffer (e.g. `php.Syntax.int()`) + *) + method private write_expr_lang_cast type_name args = + match args with + | expr :: [] -> + let add_parentheses = match self#parent_expr with Some e -> is_access e | None -> false + and expr = match expr.eexpr with + | TLocal e -> expr + | _ -> parenthesis expr + in + if add_parentheses then self#write "("; + self#write ("(" ^ type_name ^")"); + self#write_expr expr; + if add_parentheses then self#write ")" + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Generates binary operation to output buffer (for `php.Syntax.binop()`) + *) + method private write_expr_lang_binop args = + match args with + | val_expr1 :: operator_expr :: val_expr2 :: [] -> + let operator = match operator_expr.eexpr with + | TConst (TString operator) -> operator + | _ -> error_and_exit self#pos "Second argument for php.Syntax.binop() must be a constant string" + in + self#write "("; + self#write_expr val_expr1; + self#write (" " ^ operator ^ " "); + self#write_expr val_expr2; + self#write ")" + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes `instanceof` expression to output buffer (for `php.Syntax.instanceof()`) + *) + method private write_expr_lang_instanceof args = + match args with + | val_expr :: type_expr :: [] -> + self#write "("; + self#write_expr val_expr; + self#write " instanceof "; + (match (reveal_expr type_expr).eexpr with + | TTypeExpr (TClassDecl tcls) -> + self#write (self#use_t (TInst (tcls, []))) + | _ -> + self#write_expr type_expr; + if not (is_string type_expr) then self#write "->phpClassName" + ); + self#write ")" + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes `foreach` expression to output buffer (for `php.Syntax.foreach()`) + *) + method private write_expr_lang_foreach args = + match args with + | collection_expr :: { eexpr = TFunction fn } :: [] -> + let (key_name, value_name) = match fn.tf_args with + | ({ v_name = key_name }, _) :: ({ v_name = value_name }, _) :: [] -> (key_name, value_name) + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + and add_parentheses = + match collection_expr.eexpr with + | TLocal _ -> false + | _ -> true + in + self#write "foreach ("; + if add_parentheses then self#write "("; + self#write_expr collection_expr; + if add_parentheses then self#write ")"; + self#write (" as $" ^ key_name ^ " => $" ^ value_name ^ ") "); + self#write_as_block fn.tf_expr + | _ -> + error_and_exit self#pos "PHP.foreach() only accepts anonymous function declaration for second argument." + (** + Writes TCall to output buffer + *) + method private write_expr_call target_expr args = + let target_expr = reveal_expr target_expr + and no_call = ref false in + (match target_expr.eexpr with + | TConst TSuper -> + no_call := self#extends_no_constructor; + if not !no_call then self#write "parent::__construct" + | TField (expr, FClosure (_,_)) -> self#write_expr (parenthesis target_expr) + | _ -> self#write_expr target_expr + ); + if not !no_call then + begin + self#write "("; + write_args buffer self#write_expr args; + self#write ")" + end + (** + Writes a name of a function or a constant from global php namespace + *) + method private write_expr_php_global target_expr = + match target_expr.eexpr with + | TField (_, FStatic (_, field)) -> self#write (field_name field) + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes access to PHP class constant + *) + method private write_expr_php_class_const target_expr = + match target_expr.eexpr with + | TField (_, FStatic (ecls, field)) -> + self#write ((self#use_t (TInst (ecls, []))) ^ "::" ^ (field_name field)) + | _ -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes TNew to output buffer + *) + method private write_expr_new inst_class args = + let needs_php_prefix = not inst_class.cl_extern in + self#write ("new " ^ (self#use ~prefix:needs_php_prefix inst_class.cl_path) ^ "("); + write_args buffer self#write_expr args; + self#write ")" + (** + Writes ternary operator expressions to output buffer + *) + method private write_expr_ternary condition if_expr (else_expr:texpr) pos = + let if_expr = unpack_single_expr_block if_expr + and else_expr = unpack_single_expr_block else_expr in + self#write "("; + (match condition.eexpr with + | TParenthesis expr -> self#write_expr expr; + | _ -> self#write_expr else_expr + ); + self#write " ? "; + self#write_expr if_expr; + self#write " : "; + self#write_expr else_expr; + self#write ")" + (** + Writes "if...else..." expression to output buffer + *) + method private write_expr_if condition if_expr (else_expr:texpr option) = + let is_ternary = + if self#parent_expr_is_block true then + false + else + match (if_expr.eexpr, else_expr) with + | (TBlock exprs, _) when (List.length exprs) > 1 -> false + | (_, Some { eexpr=TBlock exprs }) when (List.length exprs) > 1 -> false + | (_, None) -> false + | _ -> true + in + if is_ternary then + match else_expr with + | None -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + | Some expr -> + self#write_expr_ternary condition if_expr expr self#pos + else begin + self#write "if "; + self#write_expr condition; + self#write " "; + self#write_as_block if_expr; + (match else_expr with + | None -> () + | Some expr -> + self#write " else "; + match expr.eexpr with + | TIf _ -> self#write_expr expr + | _ -> self#write_as_block expr + ) + end + (** + Writes TWhile ("while..." or "do...while") to output buffer + *) + method private write_expr_while condition expr do_while = + match do_while with + | NormalWhile -> + self#write "while "; + self#write_expr condition; + self#write " "; + self#write_as_block ~unset_locals:true expr + | DoWhile -> + self#write "do "; + self#write_as_block ~unset_locals:true expr; + self#write " while "; + self#write_expr condition + (** + Writes TSwitch to output buffer + *) + method private write_expr_switch switch cases default = + let write_case (conditions, expr) = + List.iter + (fun condition -> + self#write_indentation; + self#write "case "; + self#write_expr condition; + self#write ":\n"; + ) + conditions; + self#indent_more; + self#write_indentation; + self#write_as_block ~inline:true expr; + self#write_statement "break"; + self#indent_less + in + self#write "switch "; + self#write_expr switch; + self#write " {\n"; + self#indent_more; + List.iter write_case cases; + (match default with + | None -> () + | Some expr -> + self#write_line "default:"; + self#indent_more; + self#write_indentation; + self#write_as_block ~inline:true expr; + self#write_statement "break"; + self#indent_less + ); + self#indent_less; + self#write_indentation; + self#write "}" + (** + Write TEnumParameter expression to output buffer + *) + method private write_expr_enum_parameter expr constructor index = + (match expr.eexpr with + | TConst TNull -> self#write "(null)" + | _ -> self#write_expr expr + ); + self#write ("->params[" ^ (string_of_int index) ^ "]") + (** + Writes argument for function declarations or calls + *) + method write_arg with_optionals (arg_name, optional, (arg_type:Type.t)) = + self#write ("$" ^ arg_name ^ (if with_optionals && optional then " = null" else "")) + (** + Writes argument with optional value for function declarations + *) + method write_function_arg arg = + match arg with + | ({ v_name = arg_name; v_type = arg_type }, default_value) -> + vars#declared arg_name; + if is_ref arg_type then self#write "&"; + self#write ("$" ^ arg_name); + match default_value with + | None -> () + | Some const -> + self#write " = "; + self#write_expr_const const + end + +(** + Builds enum contents +*) +class enum_builder ctx (enm:tenum) = + object (self) + inherit type_builder ctx (get_wrapper (TEnumDecl enm)) + (** + Writes type declaration line to output buffer. + E.g. "class SomeClass extends Another implements IFace" + *) + method private write_declaration = + self#write_doc (DocClass enm.e_doc); + self#write ("class " ^ self#get_name ^ " extends " ^ (self#use hxenum_type_path)) + (** + Writes type body to output buffer. + E.g. for "class SomeClass { }" writes part. + *) + method private write_body = + let write_empty_lines = ref false in + PMap.iter + (fun name field -> + if !write_empty_lines then + self#write_empty_lines + else + write_empty_lines := true; + self#write_constructor name field + ) + enm.e_constrs; + self#write_reflection + (** + Writes constructor declaration to output buffer + *) + method private write_constructor name (field:tenum_field) = + let args = + match follow field.ef_type with + | TFun (args, _) -> args + | TEnum _ -> [] + | _ -> fail field.ef_pos (try assert false with Assert_failure mlpos -> mlpos) + in + self#indent 1; + self#write_doc (DocMethod (args, TEnum (enm, []), field.ef_doc)); + self#write_indentation; + self#write ("static public function " ^ name ^ " ("); + write_args buffer (self#write_arg true) args; + self#write ") {\n"; + self#indent_more; + self#write_indentation; + self#write "return "; + let index_str = string_of_int field.ef_index in + (match args with + | [] -> self#write ((self#use hxenum_type_path) ^ "::singleton(static::class, '" ^ name ^ "', " ^ index_str ^")") + | args -> + self#write ("new " ^ self#get_name ^ "('" ^ name ^ "', " ^ index_str ^", ["); + write_args buffer (fun (name, _, _) -> self#write ("$" ^ name)) args; + self#write "])" + ); + self#write ";\n"; + self#indent_less; + self#write_line "}" + (** + Writes special methods for reflection + *) + method private write_reflection = + (* __hx__list *) + self#write_empty_lines; + self#indent 1; + self#write_line "/**"; + self#write_line " * Returns array of (constructorIndex => constructorName)"; + self#write_line " *"; + self#write_line " * @return string[]"; + self#write_line " */"; + self#write_line "static public function __hx__list () {"; + self#indent_more; + self#write_line "return ["; + self#indent_more; + PMap.iter + (fun name field -> + self#write_line ((string_of_int field.ef_index) ^ " => '" ^ name ^ "',") + ) + enm.e_constrs; + self#indent_less; + self#write_statement "]"; + self#indent_less; + self#write_line "}"; + (* __hx__paramsCount *) + self#write_empty_lines; + self#indent 1; + self#write_line "/**"; + self#write_line " * Returns array of (constructorName => parametersCount)"; + self#write_line " *"; + self#write_line " * @return int[]"; + self#write_line " */"; + self#write_line "static public function __hx__paramsCount () {"; + self#indent_more; + self#write_line "return ["; + self#indent_more; + PMap.iter + (fun name field -> + let count = match follow field.ef_type with + | TFun (params, _) -> List.length params + | TEnum _ -> 0 + | _ -> fail field.ef_pos (try assert false with Assert_failure mlpos -> mlpos) + in + self#write_line ("'" ^ name ^ "' => " ^ (string_of_int count) ^ ",") + ) + enm.e_constrs; + self#indent_less; + self#write_statement "]"; + self#indent_less; + self#write_line "}"; + (** + Method `__hx__init` is not needed for enums + **) + method private write_hx_init_body = () + (** + No need for additional initialization of enum instances + *) + method private write_instance_initialization = () + (** + No need for additional type initialization for enums + *) + method private write_pre_hx_init = () + end + +(** + Builds class contents +*) +class class_builder ctx (cls:tclass) = + object (self) + inherit type_builder ctx (get_wrapper (TClassDecl cls)) as super + (** + Indicates if type should be declared as `final` + *) + method is_final = + if not (Meta.has Meta.Final cls.cl_meta) then + false + else begin + let hacked = ref false in + List.iter + (fun com_type -> + if not !hacked then + match com_type with + | TClassDecl tcls -> + if self#extended_by tcls then hacked := Meta.has Meta.Hack tcls.cl_meta + | _ -> () + ) + ctx.types; + not !hacked + end + (** + Indicates if `field` should be declared as `final` + *) + method is_final_field (field:tclass_field) : bool = + Meta.has Meta.Final field.cf_meta + (** + Check if there is no native php constructor in inheritance chain of this class. + E.g. `StsClass` does have a constructor while still can be called with `new StdClass()`. + So this method will return true for `MyClass` if `MyClass extends StdClass`. + *) + method private extends_no_constructor = + let rec extends_no_constructor tcls = + match tcls.cl_super with + | None -> true + | Some (parent, _) -> + if Meta.has Meta.PhpNoConstructor parent.cl_meta then + true + else + match parent.cl_constructor with + | Some _ -> false + | None -> extends_no_constructor parent + in + extends_no_constructor cls + (** + Recursively check if current class is a parent class for a `child` + *) + method private extended_by child = + let result = + if child == cls then + false + else + let rec check current = + match current.cl_super with + | None -> false + | Some (scls, _) -> + if scls == cls then true else check scls + in + check child + in + result + (** + Writes type declaration line to output buffer. + E.g. "class SomeClass extends Another implements IFace" + *) + method private write_declaration = + if self#is_final then self#write "final "; + self#write_doc (DocClass cls.cl_doc); + self#write (if cls.cl_interface then "interface " else "class "); + self#write self#get_name; + ( + match cls.cl_super with + | None -> (); + | Some (super_class, params) -> + let super_name = self#use_t (TInst (super_class, params)) in + self#write (" extends " ^ super_name) + ); + if List.length cls.cl_implements > 0 then begin + self#write (if cls.cl_interface then " extends " else " implements "); + let use_interface iface = + match iface with + | (i, params) -> self#use_t (TInst (i, params)) + in + let interfaces = List.map use_interface cls.cl_implements in + self#write (String.concat ", " interfaces); + end; + (** + Returns either user-defined constructor or creates empty constructor if instance initialization is required. + *) + method private get_constructor : tclass_field option = + match cls.cl_constructor with + | Some field -> Some field + | None -> + if not self#constructor_is_required then + None + else + Some { + cf_name = "new"; + cf_type = TFun ([], get_void ctx); + cf_public = true; + cf_pos = cls.cl_pos; + cf_name_pos = cls.cl_pos; + cf_doc = None; + cf_meta = []; + cf_kind = Method MethNormal; + cf_params = []; + cf_expr = Some { + eexpr = TFunction { + tf_args = []; + tf_type = get_void ctx; + tf_expr = { eexpr = TBlock []; epos = cls.cl_pos; etype = get_void ctx; }; + }; + epos = cls.cl_pos; + etype = get_void ctx; + }; + cf_expr_unoptimized = None; + cf_overloads = []; + } + (** + Writes type body to output buffer. + E.g. for "class SomeClass { }" writes part. + *) + method private write_body = + let at_least_one_field_written = ref false in + let write_if_constant _ field = + match field.cf_kind with + | Var { v_read = AccInline; v_write = AccNever } -> + at_least_one_field_written := true; + self#write_field true field + | _ -> () + and write_if_method is_static _ field = + match field.cf_kind with + | Var _ -> () + | Method MethDynamic when is_static -> () + | Method _ -> + if !at_least_one_field_written then self#write_empty_lines; + at_least_one_field_written := true; + self#write_field is_static field + and write_if_var is_static _ field = + match field.cf_kind with + | Var { v_read = AccInline; v_write = AccNever } -> () + | Method MethDynamic -> + at_least_one_field_written := true; + let kind = Var { v_read = AccNormal; v_write = AccNormal; } in + self#write_field is_static { field with cf_kind = kind } + | Var _ -> + at_least_one_field_written := true; + self#write_field is_static field + | Method _ -> () + in + if boot_type_path = self#get_type_path then begin + self#write_php_prefix (); + at_least_one_field_written := true + end; + if not cls.cl_interface then begin + (* Inlined statc vars (constants) *) + PMap.iter (write_if_constant) cls.cl_statics; + if !at_least_one_field_written then self#write_empty_lines; + at_least_one_field_written := false; + (* Statc vars *) + PMap.iter (write_if_var true) cls.cl_statics; + if !at_least_one_field_written then self#write_empty_lines; + at_least_one_field_written := false; + (* instance vars *) + PMap.iter (write_if_var false) cls.cl_fields + end; + (* Statc methods *) + PMap.iter (write_if_method true) cls.cl_statics; + (* Constructor *) + (match self#get_constructor with + | Some field -> write_if_method false "new" field + | None -> () + ); + (* Instance methods *) + PMap.iter (write_if_method false) cls.cl_fields; + (* Generate `__toString()` if not defined by user, but has `toString()` *) + self#write_toString_if_required + method private write_toString_if_required = + if PMap.exists "toString" cls.cl_fields then + if (not cls.cl_interface) && (not (PMap.exists "__toString" cls.cl_statics)) && (not (PMap.exists "__toString" cls.cl_fields)) then + begin + self#write_empty_lines; + self#indent 1; + self#write_line "public function __toString() {"; + self#indent_more; + self#write_line "return $this->toString();"; + self#indent_less; + self#write_line "}" + end + (** + Check if this class requires constructor to be generated even if there is no user-defined one + *) + method private constructor_is_required = + if List.length self#get_namespace > 0 then + false + else begin + let required = ref false in + List.iter + (fun field -> + if not !required then + required := (String.lowercase field.cf_name = String.lowercase self#get_name) + ) + (cls.cl_ordered_statics @ cls.cl_ordered_fields); + !required + end + (** + Writes `--php-prefix` value as class constant PHP_PREFIX + *) + method private write_php_prefix () = + let prefix = String.concat "\\" (get_php_prefix ctx) in + let indentation = String.length indentation in + self#indent 1; + self#write_statement ("const PHP_PREFIX = \"" ^ (String.escaped prefix) ^ "\""); + self#indent indentation + (** + Writes expressions for `__hx__init` method + *) + method private write_hx_init_body = + (* `static dynamic function` initialization *) + let write_dynamic_method_initialization field = + let field_access = "self::$" ^ (field_name field) in + self#write_indentation; + self#write (field_access ^ " = "); + (match field.cf_expr with + | Some expr -> self#write_expr expr + | None -> fail field.cf_pos (try assert false with Assert_failure mlpos -> mlpos) + ); + self#write ";\n" + in + PMap.iter + (fun _ field -> + match field.cf_kind with + | Method MethDynamic -> write_dynamic_method_initialization field + | _ -> () + ) + cls.cl_statics; + (* `static var` initialization *) + let write_var_initialization _ field = + let write_assign expr = + self#write_indentation; + self#write ("self::$" ^ (field_name field) ^ " = "); + self#write_expr expr + in + (* Do not generate fields for RTTI meta, because this generator uses another way to store it *) + let is_auto_meta_var = field.cf_name = "__meta__" && (has_rtti_meta ctx wrapper#get_module_type) in + if (is_var_with_nonconstant_expr field) && (not is_auto_meta_var) then begin + (match field.cf_expr with + | None -> () + (* There can be not-inlined blocks when compiling with `-debug` *) + | Some { eexpr = TBlock exprs } -> + let rec write_per_line exprs = + match exprs with + | [] -> () + | [expr] -> write_assign expr + | expr :: rest -> + self#write_indentation; + self#write_expr expr; + self#write ";\n"; + write_per_line rest + in + write_per_line exprs + | Some expr -> write_assign expr + ); + self#write ";\n" + end + in + PMap.iter write_var_initialization cls.cl_statics + (** + Writes single field to output buffer. + *) + method private write_field is_static field = + match field.cf_kind with + | Var { v_read = AccInline; v_write = AccNever } -> self#write_const field + | Var _ when is_real_var field -> + (* Do not generate fields for RTTI meta, because this generator uses another way to store it *) + let is_auto_meta_var = is_static && field.cf_name = "__meta__" && (has_rtti_meta ctx wrapper#get_module_type) in + if not is_auto_meta_var then self#write_var field is_static; + | Var _ -> () + | Method MethMacro -> () + | Method MethDynamic when is_static -> () + | Method MethDynamic -> self#write_dynamic_method field + | Method _ -> self#write_method field is_static + (** + Writes var-field to output buffer + *) + method private write_var field is_static = + self#indent 1; + self#write_doc (DocVar (self#use_t field.cf_type, field.cf_doc)); + self#write_indentation; + if is_static then self#write "static "; + let visibility = get_visibility field.cf_meta in + self#write (visibility ^ " $" ^ (field_name field)); + match field.cf_expr with + | None -> self#write ";\n" + | Some expr -> + match expr.eexpr with + | TConst _ -> + self#write " = "; + self#write_expr expr; + self#write ";\n" + | _ -> self#write ";\n" + (** + Writes "inline var" to output buffer as constant + *) + method private write_const field = + self#indent 1; + self#write_doc (DocVar (self#use_t field.cf_type, field.cf_doc)); + self#write_indentation; + self#write ("const " ^ (field_name field) ^ " = "); + match field.cf_expr with + | None -> fail self#pos (try assert false with Assert_failure mlpos -> mlpos) + | Some expr -> + self#write_expr expr; + self#write ";\n" + (** + Writes method to output buffer + *) + method private write_method field is_static = + vars#clear; + self#indent 1; + let (args, return_type) = get_function_signature field in + List.iter (fun (arg_name, _, _) -> vars#declared arg_name) args; + self#write_doc (DocMethod (args, return_type, field.cf_doc)); + self#write_indentation; + if self#is_final_field field then self#write "final "; + if is_static then self#write "static "; + self#write ((get_visibility field.cf_meta) ^ " "); + match field.cf_expr with + | None -> + self#write ("function " ^ (field_name field) ^ " ("); + write_args buffer (self#write_arg true) args; + self#write ")"; + self#write " ;\n" + | Some { eexpr = TFunction fn } -> + let name = if field.cf_name = "new" then "__construct" else (field_name field) in + self#write_expr_function ~name:name fn; + self#write "\n" + | _ -> fail field.cf_pos (try assert false with Assert_failure mlpos -> mlpos) + (** + Writes dynamic method to output buffer. + Only for non-static methods. Static methods are created as static vars in `__hx__init`. + *) + method private write_dynamic_method field = + vars#clear; + self#indent 1; + let (args, return_type) = get_function_signature field in + List.iter (fun (arg_name, _, _) -> vars#declared arg_name) args; + self#write_doc (DocMethod (args, return_type, field.cf_doc)); + self#write_indentation; + self#write ((get_visibility field.cf_meta) ^ " function " ^ (field_name field)); + (match field.cf_expr with + | None -> (* interface *) + self#write " ("; + write_args buffer (self#write_arg true) args; + self#write ");\n"; + | Some { eexpr = TFunction fn } -> (* normal class *) + self#write " ("; + write_args buffer self#write_function_arg fn.tf_args; + self#write ")\n"; + self#write_line "{"; + self#indent_more; + self#write_indentation; + let field_access = "$this->" ^ (field_name field) + and default_value = "$this->__hx__default__" ^ (field_name field) in + self#write ("if (" ^ field_access ^ " !== " ^ default_value ^ ") return call_user_func_array(" ^ field_access ^ ", func_get_args());\n"); + self#write_fake_block fn.tf_expr; + self#indent_less; + self#write_line "}"; + (* Don't forget to create a field for default value *) + self#write_statement ("protected $__hx__default__" ^ (field_name field)) + | _ -> fail field.cf_pos (try assert false with Assert_failure mlpos -> mlpos) + ); + (** + Writes initialization code for instances of this class + *) + method private write_instance_initialization = + let init_dynamic_method field = + let field_name = field_name field in + let default_field = "$this->__hx__default__" ^ field_name in + self#write_line ("if (!" ^ default_field ^ ") {"); + self#indent_more; + self#write_statement (default_field ^ " = new " ^ (self#use hxclosure_type_path) ^ "($this, '" ^ field_name ^ "')"); + self#write_statement ("if ($this->" ^ field_name ^ " === null) $this->" ^ field_name ^ " = " ^ default_field); + self#indent_less; + self#write_line "}" + in + PMap.iter + (fun _ field -> + match field.cf_kind with + | Method MethDynamic -> init_dynamic_method field + | _ -> () + ) + cls.cl_fields + (** + Writes additional initialization code, which should be called before `__hx__init()` + *) + method private write_pre_hx_init = + let getters = ref [] + and setters = ref [] in + let collect field = + match field.cf_kind with + | Var { v_read = read; v_write = write } -> + if read = AccCall then getters := field.cf_name :: !getters; + if write = AccCall then setters := field.cf_name :: !setters; + | _ -> () + in + List.iter collect cls.cl_ordered_fields; + List.iter collect cls.cl_ordered_statics; + let rec write lst = + match lst with + | [] -> () + | [item] -> self#write_line ("'" ^ item ^ "' => true"); + | item :: rest -> + self#write_line ("'" ^ item ^ "' => true,"); + write rest + and type_name = get_full_type_name ~escape:true ~omit_first_slash:true (add_php_prefix ctx wrapper#get_type_path) in + let write_register register_method lst = + self#write_line ((self#use boot_type_path) ^ "::" ^ register_method ^ "('" ^ type_name ^ "', ["); + self#indent_more; + write lst; + self#indent_less; + self#write_statement "])" + in + if List.length !getters > 0 then write_register "registerGetters" !getters; + if List.length !setters > 0 then write_register "registerSetters" !setters; + end + +(** + Handles generation process +*) +class generator (com:context) = + object (self) + val mutable build_dir = "" + val root_dir = com.file + val mutable init_types = [] + val mutable boot : (type_builder * string) option = None + (** + Perform required actions before actual php files generation + *) + method initialize = + self#create_output_dirs; + (** + Generates php file for specified type + *) + method generate (builder:type_builder) = + let contents = builder#get_contents + and namespace = builder#get_namespace + and name = builder#get_name in + let filename = (create_dir_recursive (build_dir :: namespace)) ^ "/" ^ name ^ ".php" in + let channel = open_out filename in + output_string channel contents; + close_out channel; + if builder#get_type_path = boot_type_path then + boot <- Some (builder, filename) + else if builder#has_magic_init then + init_types <- (get_full_type_name (namespace, name)) :: init_types + (** + Perform actions which should be executed after all classes were processed + *) + method finalize : unit = + self#generate_magic_init; + self#generate_entry_point + (** + Generates calls to static __init__ methods in Boot.php + *) + method generate_magic_init : unit = + match init_types with + | [] -> () + | _ -> + match boot with + | None -> fail dummy_pos (try assert false with Assert_failure mlpos -> mlpos) + | Some (_, filename) -> + let channel = open_out_gen [Open_creat; Open_text; Open_append] 0o644 filename in + List.iter + (fun class_name -> output_string channel (class_name ^ "::__hx__init();\n")) + init_types; + close_out channel + (** + Creates `index.php` which can be used as entry-point for standalone Haxe->PHP app + *) + method generate_entry_point = + match self#get_main_class with + | None -> () + | Some main_class -> + let channel = open_out (root_dir ^ "/index.php") in + output_string channel " fail dummy_pos (try assert false with Assert_failure mlpos -> mlpos) + | Some (builder, filename) -> + let boot_class = get_full_type_name (add_php_prefix com builder#get_type_path) in + output_string channel (boot_class ^ "::__hx__init();\n") + ); + output_string channel (main_class ^ "::main();\n"); + close_out channel + (** + Create necessary directories before processing types + *) + method private create_output_dirs = + let build_path = (root_dir :: self#get_lib_path) in + build_dir <- create_dir_recursive build_path + (** + Returns path from `index.php` to directory which will contain all generated classes + *) + method private get_lib_path : string list = + match com.php_lib with + | None -> ["lib"]; + | Some path -> (Str.split (Str.regexp "/") path) + (** + Returns FQN for main class if defined + *) + method private get_main_class : string option = + match com.main_class with + | None -> None + | Some type_path -> Some (get_full_type_name (add_php_prefix com type_path)) + end + +(** + Entry point to Genphp7 +*) +let generate (com:context) = + let gen = new generator com in + gen#initialize; + let rec generate com_type = + let wrapper = get_wrapper com_type in + if wrapper#needs_generation then + (match com_type with + | TClassDecl cls -> gen#generate (new class_builder com cls); + | TEnumDecl enm -> gen#generate (new enum_builder com enm); + | TTypeDecl typedef -> (); + | TAbstractDecl abstr -> () + ); + match wrapper#get_service_type with + | None -> () + | Some service_type -> generate service_type + in + List.iter generate com.types; + gen#finalize; + Hashtbl.iter + (fun name data -> + write_resource com.file name data + ) + com.resources; + clear_wrappers (); diff --git a/genpy.ml b/src/generators/genpy.ml similarity index 86% rename from genpy.ml rename to src/generators/genpy.ml index f9d7c85b..ca3b2960 100644 --- a/genpy.ml +++ b/src/generators/genpy.ml @@ -1,34 +1,33 @@ (* - * Copyright (C)2005-2014 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) +open Globals open Ast open Type open Common +open Codegen.ExprBuilder module Utils = struct let class_of_module_type mt = match mt with | TClassDecl c -> c | _ -> failwith ("Not a class: " ^ (s_type_path (t_infos mt).mt_path)) - + let find_type com path = try List.find (fun mt -> match mt with @@ -36,7 +35,7 @@ module Utils = struct | _ -> (t_infos mt).mt_path = path ) com.types with Not_found -> - error (Printf.sprintf "Could not find type %s\n" (s_type_path path)) null_pos + abort (Printf.sprintf "Could not find type %s\n" (s_type_path path)) null_pos let mk_static_field c cf p = let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in @@ -80,7 +79,7 @@ module KeywordHandler = struct List.iter (fun s -> Hashtbl.add h s ()) [ "len"; "int"; "float"; "list"; "bool"; "str"; "isinstance"; "print"; "min"; "max"; "hasattr"; "getattr"; "setattr"; "delattr"; "callable"; "type"; "ord"; "chr"; "iter"; "map"; "filter"; - "tuple"; "dict"; "set"; "bytes"; "bytearray" + "tuple"; "dict"; "set"; "bytes"; "bytearray"; "self"; ]; h @@ -97,7 +96,8 @@ module KeywordHandler = struct else s let check_var_declaration v = - if Hashtbl.mem kwds2 v.v_name then v.v_name <- "_hx_" ^ v.v_name + if not (Meta.has Meta.This v.v_meta) then + if Hashtbl.mem kwds2 v.v_name then v.v_name <- "_hx_" ^ v.v_name end module Transformer = struct @@ -125,12 +125,12 @@ module Transformer = struct and debug_expr e = let s_type = Type.s_type (print_context()) in - let s = Type.s_expr_pretty "\t" s_type e in + let s = Type.s_expr_pretty false " " false s_type e in Printf.printf "%s\n" s and debug_expr_with_type e = let s_type = Type.s_type (print_context()) in - let es = Type.s_expr_pretty "\t" s_type e in + let es = Type.s_expr_pretty false " " false s_type e in let t = s_type e.etype in Printf.printf "%s : %s\n" es t @@ -174,19 +174,19 @@ module Transformer = struct let lift_expr1 is_value next_id blocks e = lift_expr ~is_value:is_value ~next_id:(Some next_id) ~blocks:blocks e - let to_tvar ?(capture = false) n t = - alloc_var n t + let to_tvar ?(capture = false) n t p = + alloc_var n t p (* { v_name = n; v_type = t; v_id = 0; v_capture = capture; v_extra = None; v_meta = [] } *) let create_non_local n pos = let s = "nonlocal " ^ (KeywordHandler.handle_keywords n) in (* TODO: this is a hack... *) - let id = mk (TLocal (to_tvar "python_Syntax._pythonCode" t_dynamic ) ) !t_void pos in - let id2 = mk (TLocal( to_tvar s t_dynamic )) !t_void pos in + let id = mk (TLocal (to_tvar "python_Syntax._pythonCode" t_dynamic pos) ) !t_void pos in + let id2 = mk (TLocal( to_tvar s t_dynamic pos)) !t_void pos in mk (TCall(id, [id2])) t_dynamic pos let to_tlocal_expr ?(capture = false) n t p = - mk (TLocal (to_tvar ~capture:capture n t)) t p + mk (TLocal (to_tvar ~capture:capture n t p)) t p let check_unification e t = match follow e.etype,follow t with | TAnon an1, TAnon an2 -> @@ -197,18 +197,19 @@ module Transformer = struct | _ -> e - let dynamic_field_read e s = - Utils.mk_static_call_2 ((!c_reflect)()) "field" [e;mk (TConst (TString s)) !t_string e.epos] e.epos + let dynamic_field_read e s t = + let e = Utils.mk_static_call_2 ((!c_reflect)()) "field" [e;mk (TConst (TString s)) !t_string e.epos] e.epos in + { e with etype = t } let dynamic_field_write e1 s e2 = Utils.mk_static_call_2 ((!c_reflect)()) "setField" [e1;mk (TConst (TString s)) !t_string e1.epos;e2] e1.epos - let dynamic_field_read_write next_id e1 s op e2 = + let dynamic_field_read_write next_id e1 s op e2 t = let id = next_id() in - let temp_var = to_tvar id e1.etype in + let temp_var = to_tvar id e1.etype e1.epos in let temp_var_def = mk (TVar(temp_var,Some e1)) e1.etype e1.epos in let temp_local = mk (TLocal temp_var) e1.etype e1.epos in - let e_field = dynamic_field_read temp_local s in + let e_field = dynamic_field_read temp_local s t in let e_op = mk (TBinop(op,e_field,e2)) e_field.etype e_field.epos in let e_set_field = dynamic_field_write temp_local s e_op in mk (TBlock [ @@ -273,18 +274,21 @@ module Transformer = struct let rec transform_function tf ae is_value = let p = tf.tf_expr.epos in - let assigns = List.fold_left (fun acc (v,value) -> match value with - | None | Some TNull -> - acc - | Some ct -> - let a_local = mk (TLocal v) v.v_type p in - let a_null = mk (TConst TNull) v.v_type p in - let a_cmp = mk (TBinop(OpEq,a_local,a_null)) !t_bool p in - let a_value = mk (TConst(ct)) v.v_type p in - let a_assign = mk (TBinop(OpAssign,a_local,a_value)) v.v_type p in - let a_if = mk (TIf(a_cmp,a_assign,None)) !t_void p in - a_if :: acc - ) [] tf.tf_args in + let assigns = List.fold_left (fun acc (v,value) -> + KeywordHandler.check_var_declaration v; + match value with + | None | Some TNull -> + acc + | Some ct -> + let a_local = mk (TLocal v) v.v_type p in + let a_null = mk (TConst TNull) v.v_type p in + let a_cmp = mk (TBinop(OpEq,a_local,a_null)) !t_bool p in + let a_value = mk (TConst(ct)) v.v_type p in + let a_assign = mk (TBinop(OpAssign,a_local,a_value)) v.v_type p in + let a_if = mk (TIf(a_cmp,a_assign,None)) !t_void p in + a_if :: acc + ) [] tf.tf_args + in let body = match assigns with | [] -> tf.tf_expr @@ -301,7 +305,7 @@ module Transformer = struct let fn = add_non_locals_to_func fn in if is_value then begin let new_name = ae.a_next_id() in - let new_var = alloc_var new_name tf.tf_type in + let new_var = alloc_var new_name tf.tf_type p in let new_local = mk (TLocal new_var) fn.etype p in let def = mk (TVar(new_var,Some fn)) fn.etype p in lift_expr1 false ae.a_next_id [def] new_local @@ -309,6 +313,7 @@ module Transformer = struct lift_expr fn and transform_var_expr ae eo v = + KeywordHandler.check_var_declaration v; let b,new_expr = match eo with | None -> [],None @@ -405,7 +410,7 @@ module Transformer = struct List.iter (fun es -> match es.eexpr with | TConst (TString s) -> - let l = String.length s in + let l = UTF8.length s in let sl = try Hashtbl.find length_map l with Not_found -> @@ -435,7 +440,7 @@ module Transformer = struct let c_string = match !t_string with TInst(c,_) -> c | _ -> assert false in let cf_length = PMap.find "length" c_string.cl_fields in let ef = mk (TField(e1,FInstance(c_string,[],cf_length))) !t_int e1.epos in - let res_var = alloc_var (ae.a_next_id()) ef.etype in + let res_var = alloc_var (ae.a_next_id()) ef.etype ef.epos in let res_local = {ef with eexpr = TLocal res_var} in let var_expr = {ef with eexpr = TVar(res_var,Some ef)} in let e = mk (TBlock [ @@ -448,7 +453,7 @@ module Transformer = struct let e1_ = transform_expr e1 ~is_value:true ~next_id:(Some ae.a_next_id) in let handle_as_local temp_local = let ex = ae.a_expr in - let res_var = alloc_var (ae.a_next_id()) ex.etype in + let res_var = alloc_var (ae.a_next_id()) ex.etype ex.epos in let res_local = {ex with eexpr = TLocal res_var} in let plus = {ex with eexpr = TBinop(op,temp_local,one)} in let var_expr = {ex with eexpr = TVar(res_var,Some temp_local)} in @@ -475,17 +480,17 @@ module Transformer = struct handle_as_local e1_.a_expr | TArray(e1,e2) -> let id = ae.a_next_id() in - let temp_var_l = alloc_var id e1.etype in + let temp_var_l = alloc_var id e1.etype e1.epos in let temp_local_l = {e1 with eexpr = TLocal temp_var_l} in let temp_var_l = {e1 with eexpr = TVar(temp_var_l,Some e1)} in let id = ae.a_next_id() in - let temp_var_r = alloc_var id e2.etype in + let temp_var_r = alloc_var id e2.etype e2.epos in let temp_local_r = {e2 with eexpr = TLocal temp_var_r} in let temp_var_r = {e2 with eexpr = TVar(temp_var_r,Some e2)} in let id = ae.a_next_id() in - let temp_var = alloc_var id e1_.a_expr.etype in + let temp_var = alloc_var id e1_.a_expr.etype e1_.a_expr.epos in let temp_local = {e1_.a_expr with eexpr = TLocal temp_var} in let temp_var_expr = {e1_.a_expr with eexpr = TArray(temp_local_l,temp_local_r)} in let temp_var = {e1_.a_expr with eexpr = TVar(temp_var,Some temp_var_expr)} in @@ -499,11 +504,11 @@ module Transformer = struct end else transform_exprs_to_block block ae.a_expr.etype false ae.a_expr.epos ae.a_next_id | TField(e1,fa) -> - let temp_var_l = alloc_var (ae.a_next_id()) e1.etype in + let temp_var_l = alloc_var (ae.a_next_id()) e1.etype e1.epos in let temp_local_l = {e1 with eexpr = TLocal temp_var_l} in let temp_var_l = {e1 with eexpr = TVar(temp_var_l,Some e1)} in - let temp_var = alloc_var (ae.a_next_id()) e1_.a_expr.etype in + let temp_var = alloc_var (ae.a_next_id()) e1_.a_expr.etype e1_.a_expr.epos in let temp_local = {e1_.a_expr with eexpr = TLocal temp_var} in let temp_var_expr = {e1_.a_expr with eexpr = TField(temp_local_l,fa)} in let temp_var = {e1_.a_expr with eexpr = TVar(temp_var,Some temp_var_expr)} in @@ -521,7 +526,7 @@ module Transformer = struct assert false and var_to_treturn_expr ?(capture = false) n t p = - let x = mk (TLocal (to_tvar ~capture:capture n t)) t p in + let x = mk (TLocal (to_tvar ~capture:capture n t p)) t p in mk (TReturn (Some x)) t p and exprs_to_func exprs name base = @@ -568,7 +573,7 @@ module Transformer = struct in let f1 = { tf_args = []; tf_type = TFun([],ex.etype); tf_expr = ex} in let fexpr = mk (TFunction f1) ex.etype ex.epos in - let fvar = to_tvar name fexpr.etype in + let fvar = to_tvar name fexpr.etype fexpr.epos in let f = add_non_locals_to_func fexpr in let assign = { ex with eexpr = TVar(fvar, Some(f))} in let call_expr = (mk (TLocal fvar) fexpr.etype ex.epos ) in @@ -627,7 +632,7 @@ module Transformer = struct tf_type = tr; tf_expr = my_block.a_expr; }) ae.a_expr.etype ae.a_expr.epos in - let t_var = alloc_var name ae.a_expr.etype in + let t_var = alloc_var name ae.a_expr.etype ae.a_expr.epos in let f = add_non_locals_to_func fn in let fn_assign = mk (TVar (t_var,Some f)) ae.a_expr.etype ae.a_expr.epos in let ev = mk (TLocal t_var) ae.a_expr.etype ae.a_expr.epos in @@ -656,11 +661,9 @@ module Transformer = struct let a2 = to_expr (trans false [] e2) in let name = (ae.a_next_id ()) in - let t_var = alloc_var name e1.etype in - - let mk_local v p = { eexpr = TLocal v; etype = v.v_type; epos = p } in + let t_var = alloc_var name e1.etype e1.epos in - let ev = mk_local t_var e1.epos in + let ev = make_local t_var e1.epos in let ehasnext = mk (TField(ev,quick_field e1.etype "hasNext")) (tfun [] (!t_bool) ) e1.epos in let ehasnext = mk (TCall(ehasnext,[])) ehasnext.etype ehasnext.epos in @@ -688,7 +691,7 @@ module Transformer = struct tf_expr = e1; }) ef.etype ef.epos in let f1 = add_non_locals_to_func f in - let var_n = alloc_var n ef.etype in + let var_n = alloc_var n ef.etype ef.epos in let f1_assign = mk (TVar(var_n,Some f1)) !t_void f1.epos in let var_local = mk (TLocal var_n) ef.etype f1.epos in let er = mk (TReturn (Some var_local)) t_dynamic ae.a_expr.epos in @@ -799,13 +802,13 @@ module Transformer = struct end (* anon field access on optional params *) | (is_value, TField(e,FAnon cf)) when Meta.has Meta.Optional cf.cf_meta -> - let e = dynamic_field_read e cf.cf_name in + let e = dynamic_field_read e cf.cf_name ae.a_expr.etype in transform_expr ~is_value:is_value e | (is_value, TBinop(OpAssign,{eexpr = TField(e1,FAnon cf)},e2)) when Meta.has Meta.Optional cf.cf_meta -> let e = dynamic_field_write e1 cf.cf_name e2 in transform_expr ~is_value:is_value e - | (is_value, TBinop(OpAssignOp op,{eexpr = TField(e1,FAnon cf)},e2)) when Meta.has Meta.Optional cf.cf_meta -> - let e = dynamic_field_read_write ae.a_next_id e1 cf.cf_name op e2 in + | (is_value, TBinop(OpAssignOp op,{eexpr = TField(e1,FAnon cf); etype = t},e2)) when Meta.has Meta.Optional cf.cf_meta -> + let e = dynamic_field_read_write ae.a_next_id e1 cf.cf_name op e2 t in transform_expr ~is_value:is_value e (* TODO we need to deal with Increment, Decrement too! @@ -835,17 +838,21 @@ module Transformer = struct lift_expr ~blocks:e1.a_blocks r | (is_value, TField(e,FDynamic s)) -> - let e = dynamic_field_read e s in + let e = dynamic_field_read e s ae.a_expr.etype in transform_expr ~is_value:is_value e | (is_value, TBinop(OpAssign,{eexpr = TField(e1,FDynamic s)},e2)) -> let e = dynamic_field_write e1 s e2 in transform_expr ~is_value:is_value e - | (is_value, TBinop(OpAssignOp op,{eexpr = TField(e1,FDynamic s)},e2)) -> - let e = dynamic_field_read_write ae.a_next_id e1 s op e2 in + | (is_value, TBinop(OpAssignOp op,{eexpr = TField(e1,FDynamic s); etype = t},e2)) -> + let e = dynamic_field_read_write ae.a_next_id e1 s op e2 t in transform_expr ~is_value:is_value e - | (is_value, TField(e1, FClosure(Some ({cl_path = [],("str" | "list")},_),cf))) -> - let e = dynamic_field_read e1 cf.cf_name in + (* + | (is_value, TField(e1, FClosure(Some ({cl_path = [],("str")},_),cf))) -> + + | (is_value, TField(e1, FClosure(Some ({cl_path = [],("list")},_),cf))) -> + let e = dynamic_field_read e1 cf.cf_name ae.a_expr.etype in transform_expr ~is_value:is_value e + *) | (is_value, TBinop(OpAssign, left, right))-> (let left = trans true [] left in let right = trans true [] right in @@ -891,7 +898,7 @@ module Transformer = struct lift_expr ~blocks:blocks r | (false, TTry(etry, catches)) -> let etry = trans false [] etry in - let catches = List.map (fun(v,e) -> v, trans false [] e) catches in + let catches = List.map (fun(v,e) -> KeywordHandler.check_var_declaration v; v, trans false [] e) catches in let blocks = List.flatten (List.map (fun (_,e) -> e.a_blocks) catches) in let catches = List.map (fun(v,e) -> v, e.a_expr) catches in let r = { a_expr with eexpr = TTry(etry.a_expr, catches)} in @@ -900,12 +907,12 @@ module Transformer = struct | (true, TTry(etry, catches)) -> let id = ae.a_next_id () in - let temp_var = to_tvar id a_expr.etype in + let temp_var = to_tvar id a_expr.etype a_expr.epos in let temp_var_def = { a_expr with eexpr = TVar(temp_var, None) } in let temp_local = { a_expr with eexpr = TLocal(temp_var)} in let mk_temp_assign right = { a_expr with eexpr = TBinop(OpAssign, temp_local, right)} in let etry = mk_temp_assign etry in - let catches = List.map (fun (v,e)-> v, mk_temp_assign e) catches in + let catches = List.map (fun (v,e)-> KeywordHandler.check_var_declaration v; v, mk_temp_assign e) catches in let new_try = { a_expr with eexpr = TTry(etry, catches)} in let block = [temp_var_def; new_try; temp_local] in let new_block = { a_expr with eexpr = TBlock(block)} in @@ -1090,12 +1097,11 @@ module Printer = struct let had_var_args = ref false in let had_kw_args = ref false in let sl = List.map (fun (v,cto) -> - let check_err () = if !had_var_args || !had_kw_args then error "Arguments after KwArgs/VarArgs are not allowed" p in - KeywordHandler.check_var_declaration v; + let check_err () = if !had_var_args || !had_kw_args then abort "Arguments after KwArgs/VarArgs are not allowed" p in let name = handle_keywords v.v_name in match follow v.v_type with | TAbstract({a_path = ["python"],"KwArgs"},_) -> - if !had_kw_args then error "Arguments after KwArgs are not allowed" p; + if !had_kw_args then abort "Arguments after KwArgs are not allowed" p; had_kw_args := true; "**" ^ name | TAbstract({a_path = ["python"],"VarArgs"},_) -> @@ -1138,8 +1144,8 @@ module Printer = struct | Some s -> handle_keywords s in let s_args = print_args tf.tf_args p in - let s_expr = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} tf.tf_expr in - Printf.sprintf "def %s(%s):\n%s\t%s" s_name s_args pctx.pc_indent s_expr + let s_expr = print_expr {pctx with pc_indent = " " ^ pctx.pc_indent} tf.tf_expr in + Printf.sprintf "def %s(%s):\n%s %s" s_name s_args pctx.pc_indent s_expr and print_tarray_list pctx e1 e2 = let s1 = (print_expr pctx e1) in @@ -1180,7 +1186,7 @@ module Printer = struct and print_expr pctx e = let indent = pctx.pc_indent in - let print_expr_indented e = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e in + let print_expr_indented e = print_expr {pctx with pc_indent = " " ^ pctx.pc_indent} e in match e.eexpr with | TConst ct -> print_constant ct @@ -1254,6 +1260,8 @@ module Printer = struct (* Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (fst ops) (print_expr pctx e2) *) | TInst({cl_path = [],("list")},_), _ -> Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (fst ops) (print_expr pctx e2) + | x, _ when is_underlying_array x -> + Printf.sprintf "(%s %s %s)" (print_expr pctx e1) (fst ops) (print_expr pctx e2) | TDynamic _, TDynamic _ -> Printf.sprintf "%s(%s,%s)" (third ops) (print_expr pctx e1) (print_expr pctx e2) | TDynamic _, x | x, TDynamic _ when is_list_or_anon x -> @@ -1317,7 +1325,7 @@ module Printer = struct print_call pctx e1 el e | TNew(c,_,el) -> let id = print_base_type (t_infos (TClassDecl c)) in - Printf.sprintf "%s(%s)" id (print_exprs pctx ", " el) + Printf.sprintf "%s(%s)" id (print_call_args pctx e el) | TUnop(Not,Prefix,e1) -> Printf.sprintf "(%s%s)" (print_unop Not) (print_expr pctx e1) | TUnop(op,Prefix,e1) -> @@ -1325,7 +1333,6 @@ module Printer = struct | TFunction tf -> print_function pctx tf None e.epos | TVar (v,eo) -> - KeywordHandler.check_var_declaration v; print_var pctx v eo | TBlock [] -> Printf.sprintf "pass" @@ -1342,9 +1349,9 @@ module Printer = struct | TIf(econd,eif,eelse) -> print_if_else pctx econd eif eelse false | TWhile(econd,e1,NormalWhile) -> - Printf.sprintf "while %s:\n%s\t%s" (print_expr pctx (remove_outer_parens econd)) indent (print_expr_indented e1) + Printf.sprintf "while %s:\n%s %s" (print_expr pctx (remove_outer_parens econd)) indent (print_expr_indented e1) | TWhile(econd,e1,DoWhile) -> - error "Currently not supported" e.epos + abort "Currently not supported" e.epos | TTry(e1,catches) -> print_try pctx e1 catches | TReturn eo -> @@ -1381,15 +1388,15 @@ module Printer = struct | TParenthesis e -> e | _ -> econd in - let if_str = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} eif in + let if_str = print_expr {pctx with pc_indent = " " ^ pctx.pc_indent} eif in let indent = pctx.pc_indent in let else_str = if as_elif then opt eelse (print_expr pctx) "el" else - opt eelse (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent}) (Printf.sprintf "else:\n%s\t" indent) + opt eelse (print_expr {pctx with pc_indent = " " ^ pctx.pc_indent}) (Printf.sprintf "else:\n%s " indent) in let else_str = if else_str = "" then "" else "\n" ^ indent ^ else_str in - Printf.sprintf "if %s:\n%s\t%s%s" (print_expr pctx (remove_outer_parens econd1)) indent if_str else_str + Printf.sprintf "if %s:\n%s %s%s" (print_expr pctx (remove_outer_parens econd1)) indent if_str else_str and print_field pctx e1 fa is_assign = let obj = match e1.eexpr with @@ -1420,12 +1427,20 @@ module Printer = struct Printf.sprintf "HxString.fromCharCode" | FStatic({cl_path = ["python";"internal"],"UBuiltins"},{cf_name = s}) -> s + | FClosure (Some(c,cf),_) when call_override(name) && ((is_type "" "list")(TClassDecl c)) -> + Printf.sprintf "_hx_partial(python_internal_ArrayImpl.%s, %s)" name obj + | FInstance (c,_,cf) when call_override(name) && ((is_type "" "list")(TClassDecl c)) -> + Printf.sprintf "_hx_partial(python_internal_ArrayImpl.%s, %s)" name obj + | FClosure (Some(c,cf),_) when call_override(name) && ((is_type "" "str")(TClassDecl c)) -> + Printf.sprintf "_hx_partial(HxString.%s, %s)" name obj + | FInstance (c,_,cf) when call_override(name) && ((is_type "" "str")(TClassDecl c)) -> + Printf.sprintf "_hx_partial(HxString.%s, %s)" name obj | FInstance _ | FStatic _ -> do_default () | FAnon cf when is_assign && call_override(name) -> begin match follow cf.cf_type with | TFun([],_) -> - Printf.sprintf "python_lib_FuncTools.partial(HxOverrides.%s, %s)" name obj + Printf.sprintf "_hx_partial(HxOverrides.%s, %s)" name obj | _ -> do_default() end @@ -1442,7 +1457,6 @@ module Printer = struct | _ -> false end in let print_catch pctx i (v,e) = - KeywordHandler.check_var_declaration v; let is_empty_expr = begin match e.eexpr with | TBlock [] -> true | _ -> false @@ -1453,7 +1467,7 @@ module Printer = struct let handle_base_type bt = let t = print_base_type bt in let print_type_check t_str = - Printf.sprintf "if isinstance(_hx_e1, %s):\n%s\t%s\t%s" t_str indent assign (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e) + Printf.sprintf "if isinstance(_hx_e1, %s):\n%s %s %s" t_str indent assign (print_expr {pctx with pc_indent = " " ^ pctx.pc_indent} e) in let res = match t with | "str" -> print_type_check "str" @@ -1473,7 +1487,7 @@ module Printer = struct Printf.sprintf "%s%s" assign (print_expr pctx e) else (* Dynamic is always the last block *) - Printf.sprintf "%selse:\n\t%s%s\t%s" indent indent assign (print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e) + Printf.sprintf "%selse:\n %s%s %s" indent indent assign (print_expr {pctx with pc_indent = " " ^ pctx.pc_indent} e) end | TInst(c,_) -> handle_base_type (t_infos (TClassDecl c)) @@ -1485,15 +1499,15 @@ module Printer = struct assert false in let indent = pctx.pc_indent in - let print_expr_indented e = print_expr {pctx with pc_indent = "\t" ^ pctx.pc_indent} e in - let try_str = Printf.sprintf "try:\n%s\t%s\n%s" indent (print_expr_indented e1) indent in + let print_expr_indented e = print_expr {pctx with pc_indent = " " ^ pctx.pc_indent} e in + let try_str = Printf.sprintf "try:\n%s %s\n%s" indent (print_expr_indented e1) indent in let except = if has_feature pctx "has_throw" then - Printf.sprintf "except Exception as _hx_e:\n%s\t_hx_e1 = _hx_e.val if isinstance(_hx_e, _HxException) else _hx_e\n%s\t" indent indent + Printf.sprintf "except Exception as _hx_e:\n%s _hx_e1 = _hx_e.val if isinstance(_hx_e, _HxException) else _hx_e\n%s " indent indent else - Printf.sprintf "except Exception as _hx_e:\n%s\t_hx_e1 = _hx_e\n%s\t" indent indent + Printf.sprintf "except Exception as _hx_e:\n%s _hx_e1 = _hx_e\n%s " indent indent in - let catch_str = String.concat (Printf.sprintf "\n") (ExtList.List.mapi (fun i catch -> print_catch {pctx with pc_indent = "\t" ^ pctx.pc_indent} i catch) catches) in - let except_end = if not has_catch_all then Printf.sprintf "\n%s\telse:\n%s\t\traise _hx_e" indent indent else "" in + let catch_str = String.concat (Printf.sprintf "\n") (ExtList.List.mapi (fun i catch -> print_catch {pctx with pc_indent = " " ^ pctx.pc_indent} i catch) catches) in + let except_end = if not has_catch_all then Printf.sprintf "\n%s else:\n%s raise _hx_e" indent indent else "" in Printf.sprintf "%s%s%s%s" try_str except catch_str except_end and print_call2 pctx e1 el = @@ -1509,7 +1523,7 @@ module Printer = struct let i = ref 0 in let err msg = let pos = { ecode.epos with pmin = ecode.epos.pmin + !i } in - error msg pos + abort msg pos in let regex = Str.regexp "[{}]" in let rec loop m = match m with @@ -1570,7 +1584,7 @@ module Printer = struct in Printf.sprintf "%s[%s%s]" (print_expr pctx e1) (print_exprs pctx ":" el) (if trailing_colon then ":" else "") | "python_Syntax.isIn",[e1;e2] -> - Printf.sprintf "%s in %s" (print_expr pctx e1) (print_expr pctx e2) + Printf.sprintf "(%s in %s)" (print_expr pctx e1) (print_expr pctx e2) | "python_Syntax.delete",[e1] -> Printf.sprintf "del %s" (print_expr pctx e1) | "python_Syntax.binop",[e0;{eexpr = TConst(TString id)};e2] -> @@ -1584,7 +1598,7 @@ module Printer = struct | "python_Syntax.opPow", [e1;e2] -> Printf.sprintf "(%s ** %s)" (print_expr pctx e1) (print_expr pctx e2) | "python_Syntax._foreach",[e1;e2;e3] -> - let pctx = {pctx with pc_indent = "\t" ^ pctx.pc_indent} in + let pctx = {pctx with pc_indent = " " ^ pctx.pc_indent} in let i = pctx.pc_indent in Printf.sprintf "for %s in %s:\n%s%s" (print_expr pctx e1) (print_expr pctx e2) i (print_expr pctx e3) | _,el -> @@ -1687,7 +1701,7 @@ module Printer = struct print_exprs pctx sep el and print_exprs_named pctx sep fl = - let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "'%s': %s" (handle_keywords s) (print_expr pctx e)) fl) in + let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "'%s': %s" (Ast.s_escape (handle_keywords s)) (print_expr pctx e)) fl) in Printf.sprintf "{%s}" args and print_params_named pctx sep fl = let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "%s= %s" (handle_keywords s) (print_expr pctx e)) fl) in @@ -1836,7 +1850,7 @@ module Generator = struct ) metas let gen_expr ctx e field indent = - let pctx = Printer.create_context ("\t" ^ indent) ctx.com ctx.com.debug in + let pctx = Printer.create_context (" " ^ indent) ctx.com ctx.com.debug in let e = match e.eexpr with | TFunction(f) -> {e with eexpr = TBlock [e]} @@ -1851,7 +1865,7 @@ module Generator = struct | e_last :: el -> let new_last = {e_last with eexpr = TReturn (Some e_last)} in let new_block = {expr2 with eexpr = TBlock (List.rev (new_last :: el))} in - let v_name = alloc_var name (tfun [] e_last.etype) in + let v_name = alloc_var name (tfun [] e_last.etype) e_last.epos in let f_name = mk (TLocal v_name) v_name.v_type e_last.epos in let call_f = mk (TCall(f_name,[])) e_last.etype e_last.epos in Some new_block,call_f @@ -1866,7 +1880,7 @@ module Generator = struct | Some e1,e2 -> let expr_string_1 = texpr_str e1 pctx in let expr_string_2 = texpr_str e2 pctx in - print ctx "%sdef %s():\n\t%s" indent name expr_string_1; + print ctx "%sdef %s():\n %s" indent name expr_string_1; newline ctx; print ctx "%s%s = %s" indent field expr_string_2; | None,e2 -> @@ -1876,14 +1890,18 @@ module Generator = struct else print ctx "%s%s = %s" indent field expr_string_2 - let gen_func_expr ctx e c name metas extra_args indent stat p = + let gen_func_expr ctx e c name metas add_self indent stat p = let pctx = Printer.create_context indent ctx.com ctx.com.debug in let e = match e.eexpr with | TFunction(f) -> - let args = List.map (fun s -> - alloc_var s t_dynamic,None - ) extra_args in - {e with eexpr = TFunction {f with tf_args = args @ f.tf_args}} + let args = if add_self then + let v = alloc_var "self" t_dynamic p in + v.v_meta <- (Meta.This,[],p) :: v.v_meta; + (v,None) :: f.tf_args + else + f.tf_args + in + {e with eexpr = TFunction {f with tf_args = args}} | _ -> e in @@ -1909,17 +1927,40 @@ module Generator = struct begin match cf.cf_expr with | Some ({eexpr = TFunction f} as ef) -> let ethis = mk (TConst TThis) (TInst(c,List.map snd c.cl_params)) cf.cf_pos in - let member_data = List.map (fun cf -> - let ef = mk (TField(ethis,FInstance(c,[],cf))) cf.cf_type cf.cf_pos in (* TODO *) - mk (TBinop(OpAssign,ef,null ef.etype ef.epos)) ef.etype ef.epos - ) member_inits in + let assigned_fields = ref [] in + (* Collect all fields that are assigned to but panic out as soon as `this`, + `super`, `return` or `throw` appears (regardless of control flow). *) + let collect_assignments e = + let rec loop e = match e.eexpr with + | TBinop(OpAssign,{eexpr = TField({eexpr = TConst TThis}, FInstance(_,_,cf))},e2) -> + loop e2; + assigned_fields := cf :: !assigned_fields + | TConst (TSuper | TThis) | TThrow _ | TReturn _ -> + raise Exit + (* TODO: We could do some branch intersection stunts to make this more accurate. *) + | TIf(e1,_,_) | TSwitch(e1,_,_) | TWhile(e1,_,_) -> + loop e1 + | _ -> + Type.iter loop e + in + try loop e with Exit -> () + in + collect_assignments f.tf_expr; + let member_data = List.fold_left (fun acc cf -> + if not (List.memq cf !assigned_fields) then begin + let ef = mk (TField(ethis,FInstance(c,[],cf))) cf.cf_type cf.cf_pos in (* TODO *) + let e = mk (TBinop(OpAssign,ef,null ef.etype ef.epos)) ef.etype ef.epos in + e :: acc + end else + acc + ) [] member_inits in let e = concat (mk (TBlock member_data) ctx.com.basic.tvoid cf.cf_pos) f.tf_expr in let ef = {ef with eexpr = TFunction {f with tf_expr = e}} in cf.cf_expr <- Some ef; newline ctx; newline ctx; - gen_func_expr ctx ef c "__init__" py_metas ["self"] "\t" false cf.cf_pos + gen_func_expr ctx ef c "__init__" py_metas true " " false cf.cf_pos | _ -> assert false end @@ -1928,17 +1969,17 @@ module Generator = struct let field = handle_keywords cf.cf_name in begin match cf.cf_expr with | None -> - ()(* print ctx "\t# var %s" field *) + ()(* print ctx " # var %s" field *) | Some e -> newline ctx; newline ctx; begin match cf.cf_kind with | Method _ -> let py_metas = filter_py_metas cf.cf_meta in - gen_func_expr ctx e c field py_metas ["self"] "\t" false cf.cf_pos; + gen_func_expr ctx e c field py_metas true " " false cf.cf_pos; | _ -> - gen_expr ctx e (Printf.sprintf "# var %s" field) "\t"; + gen_expr ctx e (Printf.sprintf "# var %s" field) " "; end end @@ -1946,7 +1987,7 @@ module Generator = struct if has_feature ctx "Type.createEmptyInstance" then begin newline ctx; newline ctx; - print ctx "\t@staticmethod\n\tdef _hx_empty_init(_hx_o):"; + print ctx " @staticmethod\n def _hx_empty_init(_hx_o):"; let found_fields = ref false in List.iter (fun cf -> match cf.cf_kind with | Var ({v_read = AccResolve | AccCall}) -> @@ -1954,12 +1995,12 @@ module Generator = struct | Var _ -> found_fields := true; newline ctx; - print ctx "\t\t_hx_o.%s = None" (handle_keywords cf.cf_name) + print ctx " _hx_o.%s = None" (handle_keywords cf.cf_name) | _ -> () ) cfl; if not !found_fields then - spr ctx "\t\tpass" + spr ctx " pass" end else begin newline ctx end @@ -1980,7 +2021,7 @@ module Generator = struct | None -> has_empty_static_vars := true; newline ctx; - print ctx "\t%s = None" field + print ctx " %s = None" field | Some e -> (let f = fun () -> newline ctx; @@ -1997,7 +2038,7 @@ module Generator = struct let py_metas = filter_py_metas cf.cf_meta in let e = match cf.cf_expr with Some e -> e | _ -> assert false in newline ctx; - gen_func_expr ctx e c field py_metas [] "\t" true cf.cf_pos; + gen_func_expr ctx e c field py_metas false " " true cf.cf_pos; ) methods; !has_static_methods || !has_empty_static_vars @@ -2047,7 +2088,7 @@ module Generator = struct if not is_nativegen then begin if has_feature ctx "python._hx_class_name" then begin use_pass := false; - print ctx "\n\t_hx_class_name = \"%s\"" p_name + print ctx "\n _hx_class_name = \"%s\"" p_name end; let print_field names field quote = @@ -2061,10 +2102,29 @@ module Generator = struct "[" ^ (String.concat ", " (List.map q names)) ^ "]" in use_pass := false; - print ctx "\n\t%s = %s" field s + print ctx "\n %s = %s" field s with Exit -> () in + (try ( + let real_fields = + List.filter (fun f -> match f.cf_kind with + | Method MethDynamic -> raise Exit (* if a class has dynamic method, we can't use __slots__ because python will complain *) + | Var _ -> not (is_extern_field f) + | _ -> false + ) c.cl_ordered_fields + in + let field_names = List.map (fun f -> handle_keywords f.cf_name) real_fields in + let field_names = match c.cl_dynamic with Some _ -> "__dict__" :: field_names | None -> field_names in + use_pass := false; + print ctx "\n __slots__ = ("; + (match field_names with + | [] -> () + | [name] -> print ctx "\"%s\"," name + | names -> print ctx "\"%s\"" (String.concat "\", \"" names)); + print ctx ")"; + ) with Exit -> ()); + print_field x.cfd_fields "_hx_fields" true; print_field x.cfd_methods "_hx_methods" true; (* TODO: It seems strange to have a separation for member fields but a plain _hx_statics for static ones *) @@ -2075,7 +2135,7 @@ module Generator = struct | None -> () | Some ps -> use_pass := false; - print ctx "\n\t_hx_super = %s\n" ps + print ctx "\n _hx_super = %s\n" ps ); end; @@ -2101,7 +2161,7 @@ module Generator = struct | [] -> c.cl_constructor = None | _ -> c.cl_interface in - if use_pass then spr ctx "\n\tpass"; + if use_pass then spr ctx "\n pass"; if not is_nativegen then begin if has_feature ctx "python._hx_class" then print ctx "\n%s._hx_class = %s" p p; @@ -2131,18 +2191,15 @@ module Generator = struct newline ctx; newline ctx; print ctx "class %s(Enum):" p; - - let use_pass = ref true in + print ctx "\n __slots__ = ()"; if has_feature ctx "python._hx_class_name" then begin - use_pass := false; - print ctx "\n\t_hx_class_name = \"%s\"" p_name + print ctx "\n _hx_class_name = \"%s\"" p_name end; if has_feature ctx "python._hx_constructs" then begin let fix = match enum_constructs with [] -> "" | _ -> "\"" in let enum_constructs_str = fix ^ (String.concat ("\", \"") (List.map (fun ef -> ef.ef_name) enum_constructs)) ^ fix in - use_pass := false; - print ctx "\n\t_hx_constructs = [%s]" enum_constructs_str; + print ctx "\n _hx_constructs = [%s]" enum_constructs_str; end; let const_constructors,param_constructors = List.partition (fun ef -> @@ -2175,14 +2232,11 @@ module Generator = struct let args_str = String.concat "," (List.map (fun (n,_,_) -> handle_keywords n) args) in newline ctx; newline ctx; - print ctx "\t@staticmethod\n\tdef %s(%s):\n" f param_str; - print ctx "\t\treturn %s(\"%s\", %i, [%s])" p ef.ef_name ef.ef_index args_str; - use_pass := false; + print ctx " @staticmethod\n def %s(%s):\n" f param_str; + print ctx " return %s(\"%s\", %i, [%s])" p ef.ef_name ef.ef_index args_str; | _ -> assert false ) param_constructors; - if !use_pass then spr ctx "\n\tpass"; - List.iter (fun ef -> (* TODO: haxe source has api.quoteString for ef.ef_name *) let f = handle_keywords ef.ef_name in @@ -2208,7 +2262,7 @@ module Generator = struct if has_feature ctx "python._hx_class_name" then begin use_pass := false; - print ctx "\n\t_hx_class_name = \"%s\"" p_name + print ctx "\n _hx_class_name = \"%s\"" p_name end; (match a.a_impl with @@ -2222,7 +2276,7 @@ module Generator = struct ) c.cl_ordered_statics | None -> ()); - if !use_pass then spr ctx "\n\tpass"; + if !use_pass then spr ctx "\n pass"; if has_feature ctx "python._hx_class" then print ctx "\n%s._hx_class = %s" p p; if has_feature ctx "python._hx_classes" then print ctx "\n_hx_classes[\"%s\"] = %s" p_name p @@ -2255,14 +2309,14 @@ module Generator = struct newline ctx; newline ctx; spr ctx "def _hx_resources__():"; - spr ctx "\n\timport inspect"; - spr ctx "\n\timport sys"; - spr ctx "\n\tif not hasattr(sys.modules[__name__], '__file__'):"; - print ctx "\n\t\t_file = '%s'" file_name; - spr ctx "\n\telse:"; - spr ctx "\n\t\t_file = __file__"; - - spr ctx "\n\treturn {"; + spr ctx "\n import inspect"; + spr ctx "\n import sys"; + spr ctx "\n if not hasattr(sys.modules[__name__], '__file__'):"; + print ctx "\n _file = '%s'" file_name; + spr ctx "\n else:"; + spr ctx "\n _file = __file__"; + + spr ctx "\n return {"; let first = ref true in Hashtbl.iter (fun k v -> let prefix = if !first then begin @@ -2273,7 +2327,10 @@ module Generator = struct in let k_enc = Codegen.escape_res_name k false in print ctx "%s\"%s\": open('%%s.%%s'%%(_file,'%s'),'rb').read()" prefix (Ast.s_escape k) k_enc; - Std.output_file (ctx.com.file ^ "." ^ k_enc) v + + let f = open_out_bin (ctx.com.file ^ "." ^ k_enc) in + output_string f v; + close_out f ) ctx.com.resources; spr ctx "}" end @@ -2303,13 +2360,16 @@ module Generator = struct | [(EConst(String(module_name)), _); (EConst(String(object_name)), _); (EBinop(OpAssign, (EConst(Ident("ignoreError")),_), (EConst(Ident("true")),_)),_)] -> IObject (module_name,object_name), true | _ -> - error "Unsupported @:pythonImport format" mp + abort "Unsupported @:pythonImport format" mp in let import = match import_type with | IModule module_name -> (* importing whole module *) - "import " ^ module_name ^ " as " ^ class_name + if module_name = class_name then + "import " ^ module_name + else + "import " ^ module_name ^ " as " ^ class_name | IObject (module_name,object_name) -> if String.contains object_name '.' then @@ -2317,13 +2377,16 @@ module Generator = struct "import " ^ module_name ^ " as _hx_temp_import; " ^ class_name ^ " = _hx_temp_import." ^ object_name ^ "; del _hx_temp_import" else (* importing a class from a module *) - "from " ^ module_name ^ " import " ^ object_name ^ " as " ^ class_name + if object_name = class_name then + "from " ^ module_name ^ " import " ^ object_name + else + "from " ^ module_name ^ " import " ^ object_name ^ " as " ^ class_name in newline ctx; if ignore_error then begin - spr ctx "try:\n\t"; + spr ctx "try:\n "; spr_line ctx import; - spr ctx "except:\n\tpass" + spr ctx "except:\n pass" end else spr ctx import end @@ -2342,17 +2405,17 @@ module Generator = struct Utils.find_type ctx.com path in let need_anon_for_trace = (has_feature ctx "has_anon_trace") && (has_feature ctx "haxe.Log.trace") in - if (has_feature ctx "has_anon") || (has_feature ctx "_hx_AnonObject") || need_anon_for_trace then begin - let with_body = (has_feature ctx "has_anon") || need_anon_for_trace in + if (has_feature ctx "has_anon") || (has_feature ctx "_hx_AnonObject") || (has_feature ctx "has_metadata") || need_anon_for_trace then begin + let with_body = (has_feature ctx "has_anon") || (has_feature ctx "has_metadata") || need_anon_for_trace in newline ctx; newline ctx; newline ctx; spr ctx "class _hx_AnonObject:\n"; if with_body then begin - spr ctx "\tdef __init__(self, fields):\n"; - spr ctx "\t\tself.__dict__ = fields" + spr ctx " def __init__(self, fields):\n"; + spr ctx " self.__dict__ = fields" end else - spr ctx "\tpass"; + spr ctx " pass"; Hashtbl.add used_paths ([],"_hx_AnonObject") true; end; if has_feature ctx "python._hx_classes" then begin @@ -2387,13 +2450,20 @@ module Generator = struct | Some e -> newline ctx; newline ctx; - gen_expr ctx e "" "" + match e.eexpr with + | TBlock el -> + List.iter (fun e -> gen_expr ctx e "" ""; newline ctx) el + | _ -> + gen_expr ctx e "" "" (* Entry point *) let run com = Transformer.init com; let ctx = mk_context com in + Codegen.map_source_header com (fun s -> print ctx "# %s\n# coding: utf-8\n" s); + if has_feature ctx "closure_Array" || has_feature ctx "closure_String" then + spr ctx "from functools import partial as _hx_partial"; gen_imports ctx; gen_resources ctx; gen_types ctx; @@ -2408,4 +2478,4 @@ module Generator = struct end let generate com = - Generator.run com \ No newline at end of file + Generator.run com diff --git a/genswf.ml b/src/generators/genswf.ml similarity index 90% rename from genswf.ml rename to src/generators/genswf.ml index e53ec3f2..cea1267b 100644 --- a/genswf.ml +++ b/src/generators/genswf.ml @@ -1,23 +1,20 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Swf @@ -27,6 +24,7 @@ open Genswf9 open Type open Common open Ast +open Globals let rec make_tpath = function | HMPath (pack,name) -> @@ -52,7 +50,7 @@ let rec make_tpath = function { tpackage = pack; tname = name; - tparams = if !pdyn then [TPType (CTPath { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; })] else[]; + tparams = if !pdyn then [TPType (CTPath { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; },null_pos)] else[]; tsub = None; } | HMName (id,ns) -> @@ -90,11 +88,11 @@ let rec make_tpath = function | HMAny -> assert false | HMParams (t,params) -> - let params = List.map (fun t -> TPType (CTPath (make_tpath t))) params in + let params = List.map (fun t -> TPType (CTPath (make_tpath t),null_pos)) params in { (make_tpath t) with tparams = params } let make_param cl p = - { tpackage = fst cl; tname = snd cl; tparams = [TPType (CTPath { tpackage = fst p; tname = snd p; tparams = []; tsub = None })]; tsub = None } + { tpackage = fst cl; tname = snd cl; tparams = [TPType (CTPath { tpackage = fst p; tname = snd p; tparams = []; tsub = None },null_pos)]; tsub = None } let make_topt = function | None -> { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None } @@ -112,7 +110,7 @@ let is_valid_path com pack name = | [] -> false | load :: l -> - match load (pack,name) Ast.null_pos with + match load (pack,name) null_pos with | None -> loop l | Some (file,(_,a)) -> true in @@ -125,12 +123,12 @@ let build_class com c file = match path with | { tpackage = ["flash";"utils"]; tname = ("Object"|"Function") } -> let inf = { - d_name = path.tname; + d_name = path.tname,null_pos; d_doc = None; d_params = []; d_meta = []; d_flags = []; - d_data = CTPath { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; }; + d_data = CTPath { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; },null_pos; } in (path.tpackage, [(ETypedef inf,pos)]) | _ -> @@ -140,7 +138,7 @@ let build_class com c file = let flags = (match c.hlc_super with | None | Some (HMPath ([],"Object")) -> flags | Some (HMPath ([],"Function")) -> flags (* found in AIR SDK *) - | Some s -> HExtends (make_tpath s) :: flags + | Some s -> HExtends (make_tpath s,null_pos) :: flags ) in let flags = List.map (fun i -> let i = (match i with @@ -154,9 +152,9 @@ let build_class com c file = | HMPath _ -> i | _ -> assert false ) in - if c.hlc_interface then HExtends (make_tpath i) else HImplements (make_tpath i) + if c.hlc_interface then HExtends (make_tpath i,null_pos) else HImplements (make_tpath i,null_pos) ) (Array.to_list c.hlc_implements) @ flags in - let flags = if c.hlc_sealed || Common.defined com Define.FlashStrict then flags else HImplements (make_tpath (HMPath ([],"Dynamic"))) :: flags in + let flags = if c.hlc_sealed || Common.defined com Define.FlashStrict then flags else HImplements (make_tpath (HMPath ([],"Dynamic")),null_pos) :: flags in (* make fields *) let getters = Hashtbl.create 0 in let setters = Hashtbl.create 0 in @@ -189,7 +187,7 @@ let build_class com c file = List.map (fun (s,cl) -> s, List.map (fun c -> EConst c,pos) cl, pos) (!meta) in let cf = { - cff_name = name; + cff_name = name,null_pos; cff_doc = None; cff_pos = pos; cff_meta = mk_meta(); @@ -199,9 +197,9 @@ let build_class com c file = match f.hlf_kind with | HFVar v -> if v.hlv_const then - cf.cff_kind <- FProp ("default","never",Some (make_type v.hlv_type),None) + cf.cff_kind <- FProp (("default",null_pos),("never",null_pos),Some (make_type v.hlv_type,null_pos),None) else - cf.cff_kind <- FVar (Some (make_dyn_type v.hlv_type),None); + cf.cff_kind <- FVar (Some (make_dyn_type v.hlv_type,null_pos),None); cf :: acc | HFMethod m when m.hlm_override -> Hashtbl.add override (name,stat) (); @@ -252,15 +250,15 @@ let build_class com c file = meta := (Meta.DefParam,[String aname;v]) :: !meta; Some (EConst v,pos) in - (aname,!is_opt,Some t,def_val) + ((aname,null_pos),!is_opt,[],Some (t,null_pos),def_val) ) t.hlmt_args in let args = if t.hlmt_var_args then - args @ List.map (fun _ -> incr pn; ("p" ^ string_of_int !pn,true,Some (make_type None),None)) [1;2;3;4;5] + args @ List.map (fun _ -> incr pn; (("p" ^ string_of_int !pn,null_pos),true,[],Some (make_type None,null_pos),None)) [1;2;3;4;5] else args in let f = { f_params = []; f_args = args; - f_type = Some (make_type t.hlmt_ret); + f_type = Some (make_type t.hlmt_ret,null_pos); f_expr = None; } in cf.cff_meta <- mk_meta(); @@ -299,12 +297,12 @@ let build_class com c file = let flags = [APublic] in let flags = if stat then AStatic :: flags else flags in { - cff_name = name; + cff_name = name,null_pos; cff_pos = pos; cff_doc = None; cff_access = flags; cff_meta = []; - cff_kind = if get && set then FVar (Some (make_dyn_type t), None) else FProp ((if get then "default" else "never"),(if set then "default" else "never"),Some (make_dyn_type t),None); + cff_kind = if get && set then FVar (Some (make_dyn_type t,null_pos), None) else FProp (((if get then "default" else "never"),null_pos),((if set then "default" else "never"),null_pos),Some (make_dyn_type t,null_pos),None); } in let fields = Hashtbl.fold (fun (name,stat) t acc -> @@ -326,7 +324,8 @@ let build_class com c file = | [] -> [] | f :: l -> match f.cff_kind with - | FVar (Some (CTPath { tpackage = []; tname = ("String" | "Int" | "UInt") as tname }),None) when List.mem AStatic f.cff_access -> + | FVar (Some (CTPath { tpackage = []; tname = ("String" | "Int" | "UInt") as tname },null_pos),None) + | FProp (("default",_),("never",_),Some (CTPath { tpackage = []; tname = ("String" | "Int" | "UInt") as tname },null_pos),None) when List.mem AStatic f.cff_access -> if !real_type = "" then real_type := tname else if !real_type <> tname then raise Exit; { ec_name = f.cff_name; @@ -337,7 +336,7 @@ let build_class com c file = ec_doc = None; ec_type = None; } :: loop l - | FFun { f_args = [] } when f.cff_name = "new" -> loop l + | FFun { f_args = [] } when fst f.cff_name = "new" -> loop l | _ -> raise Exit in List.iter (function HExtends _ | HImplements _ -> raise Exit | _ -> ()) flags; @@ -345,7 +344,7 @@ let build_class com c file = let name = "fakeEnum:" ^ String.concat "." (path.tpackage @ [path.tname]) in if not (Common.raw_defined com name) then raise Exit; let enum_data = { - d_name = path.tname; + d_name = path.tname,null_pos; d_doc = None; d_params = []; d_meta = [(Meta.FakeEnum,[EConst (Ident !real_type),pos],pos)]; @@ -355,17 +354,17 @@ let build_class com c file = (path.tpackage, [(EEnum enum_data,pos)]) with Exit -> let class_data = { - d_name = path.tname; + d_name = path.tname,null_pos; d_doc = None; d_params = []; - d_meta = if c.hlc_final && List.exists (fun f -> f.cff_name <> "new" && not (List.mem AStatic f.cff_access)) fields then [Meta.Final,[],pos] else []; + d_meta = if c.hlc_final && List.exists (fun f -> fst f.cff_name <> "new" && not (List.mem AStatic f.cff_access)) fields then [Meta.Final,[],pos] else []; d_flags = flags; d_data = fields; } in (path.tpackage, [(EClass class_data,pos)]) let extract_data (_,tags) = - let t = Common.timer "read swf" in + let t = Common.timer ["read";"swf"] in let h = Hashtbl.create 0 in let rec loop_field f = match f.hlf_kind with @@ -457,7 +456,7 @@ let remove_debug_infos as3 = As3hlparse.flatten (List.map loop_static hl) let parse_swf com file = - let t = Common.timer "read swf" in + let t = Common.timer ["read";"swf"] in let is_swc = file_extension file = "swc" || file_extension file = "ane" in let file = (try Common.find_file com file with Not_found -> failwith ((if is_swc then "SWC" else "SWF") ^ " Library not found : " ^ file)) in let ch = if is_swc then begin @@ -483,7 +482,7 @@ let parse_swf com file = IO.close_in ch; List.iter (fun t -> match t.tdata with - | TActionScript3 (id,as3) when not com.debug && com.display = DMNone -> + | TActionScript3 (id,as3) when not com.debug && not com.display.DisplayMode.dms_display -> t.tdata <- TActionScript3 (id,remove_debug_infos as3) | _ -> () ) tags; @@ -746,7 +745,7 @@ let detect_format data p = | '\xFF', i, _ when (int_of_char i) land 0xE2 = 0xE2 -> SMP3 | 'G', 'I', 'F' -> BGIF | _ -> - error "Unknown file format" p + abort "Unknown file format" p open TTFData @@ -788,7 +787,7 @@ let build_swf9 com file swc = if String.length file > 5 && String.sub file 0 5 = "data:" then String.sub file 5 (String.length file - 5) else - (try Std.input_file ~bin:true file with Invalid_argument("String.create") -> error "File is too big (max 16MB allowed)" p | _ -> error "File not found" p) + (try Std.input_file ~bin:true file with Invalid_argument("String.create") -> abort "File is too big (max 16MB allowed)" p | _ -> abort "File not found" p) in let bmp = List.fold_left (fun acc t -> match t with @@ -797,8 +796,8 @@ let build_swf9 com file swc = | [] -> acc | (Meta.Font,(EConst (String file),p) :: args,_) :: l -> let file = try Common.find_file com file with Not_found -> file in - let ch = try open_in_bin file with _ -> error "File not found" p in - let ttf = try TTFParser.parse ch with e -> error ("Error while parsing font " ^ file ^ " : " ^ Printexc.to_string e) p in + let ch = try open_in_bin file with _ -> abort "File not found" p in + let ttf = try TTFParser.parse ch with e -> abort ("Error while parsing font " ^ file ^ " : " ^ Printexc.to_string e) p in close_in ch; let get_string e = match fst e with | EConst (String s) -> Some s @@ -816,7 +815,7 @@ let build_swf9 com file swc = | _ :: [e] -> begin match fst e with | EObjectDecl fl -> - begin try ttf_config.ttfc_font_name <- get_string (List.assoc "fontName" fl) + begin try ttf_config.ttfc_font_name <- get_string (Expr.field_assoc "fontName" fl) with Not_found -> () end | _ -> () @@ -876,10 +875,10 @@ let build_swf9 com file swc = let adata = load_file_data afile p2 in (match detect_format ddata p1 with | BJPG -> () - | _ -> error "RGB channel must be a JPG file" p1); + | _ -> abort "RGB channel must be a JPG file" p1); (match detect_format adata p2 with | BPNG -> () - | _ -> error "Alpha channel must be a PNG file" p2); + | _ -> abort "Alpha channel must be a PNG file" p2); let png = Png.parse (IO.input_string adata) in let h = Png.header png in let amask = (match h.Png.png_color with @@ -891,7 +890,7 @@ let build_swf9 com file swc = String.unsafe_set alpha i (String.unsafe_get raw_data (i lsl 2)); done; Extc.zip alpha - | _ -> error "PNG file must contain 8 bit alpha channel" p2 + | _ -> abort "PNG file must contain 8 bit alpha channel" p2 ) in incr cid; classes := { f9_cid = Some !cid; f9_classname = s_type_path c.cl_path } :: !classes; @@ -930,9 +929,9 @@ let build_swf9 com file swc = let data = IO.nread i data_size in make_flags 0 (chan = 1) freq bits, (data_size * 8 / (chan * bits)), data with Exit | IO.No_more_input | IO.Overflow _ -> - error "Invalid WAV file" p + abort "Invalid WAV file" p | Failure msg -> - error ("Invalid WAV file (" ^ msg ^ ")") p + abort ("Invalid WAV file (" ^ msg ^ ")") p ) | SMP3 -> (try @@ -985,12 +984,12 @@ let build_swf9 com file swc = read_frame(); make_flags 2 !mono !sampling 16, (!samples), ("\x00\x00" ^ data) with Exit | IO.No_more_input | IO.Overflow _ -> - error "Invalid MP3 file" p + abort "Invalid MP3 file" p | Failure msg -> - error ("Invalid MP3 file (" ^ msg ^ ")") p + abort ("Invalid MP3 file (" ^ msg ^ ")") p ) | _ -> - error "Sound extension not supported (only WAV or MP3)" p + abort "Sound extension not supported (only WAV or MP3)" p ) in incr cid; classes := { f9_cid = Some !cid; f9_classname = s_type_path c.cl_path } :: !classes; @@ -1026,7 +1025,7 @@ let merge com file priority (h1,tags1) (h2,tags2) = let path = parse_path e.exp_name in let b = List.exists (fun t -> t_path t = path) com.types in if not b && fst path = [] then List.iter (fun t -> - if snd (t_path t) = snd path then error ("Linkage name '" ^ snd path ^ "' in '" ^ file ^ "' should be '" ^ s_type_path (t_path t) ^"'") (t_infos t).mt_pos; + if snd (t_path t) = snd path then abort ("Linkage name '" ^ snd path ^ "' in '" ^ file ^ "' should be '" ^ s_type_path (t_path t) ^"'") (t_infos t).mt_pos; ) com.types; b ) el in @@ -1076,8 +1075,7 @@ let merge com file priority (h1,tags1) (h2,tags2) = let tags = loop tags1 tags2 in header, tags -let generate com swf_header = - let t = Common.timer "generate swf" in +let generate swf_header com = let swc = if Common.defined com Define.Swc then Some (ref "") else None in let file , codeclip = (try let f , c = ExtString.String.split com.file "@" in f, Some c with _ -> com.file , None) in (* list exports *) @@ -1103,9 +1101,9 @@ let generate com swf_header = if Meta.has Meta.Bind c.cl_meta then toremove := (t_path t) :: !toremove else - error ("Class already exists in '" ^ file ^ "', use @:bind to redefine it") (t_infos t).mt_pos + abort ("Class already exists in '" ^ file ^ "', use @:bind to redefine it") (t_infos t).mt_pos | _ -> - error ("Invalid redefinition of class defined in '" ^ file ^ "'") (t_infos t).mt_pos + abort ("Invalid redefinition of class defined in '" ^ file ^ "'") (t_infos t).mt_pos ) com.types; ) el | _ -> () @@ -1115,6 +1113,7 @@ let generate com swf_header = let tags = build_swf9 com file swc in let header, bg = (match swf_header with None -> default_header com | Some h -> convert_header com h) in let bg = tag (TSetBgColor { cr = bg lsr 16; cg = (bg lsr 8) land 0xFF; cb = bg land 0xFF }) in + let scene = tag ~ext:true (TScenes ([(0,"Scene1")],[])) in let swf_debug_password = try Digest.to_hex(Digest.string (Common.defined_value com Define.SwfDebugPassword)) with Not_found -> @@ -1142,12 +1141,12 @@ let generate com swf_header = let fattr = if Common.defined com Define.AdvancedTelemetry then fattr @ [tag (TUnknown (0x5D,"\x00\x00"))] else fattr in let swf_script_limits = try let s = Common.defined_value com Define.SwfScriptTimeout in - let i = try int_of_string s with _ -> error "Argument to swf_script_timeout must be an integer" Ast.null_pos in + let i = try int_of_string s with _ -> abort "Argument to swf_script_timeout must be an integer" null_pos in [tag(TScriptLimits (256, if i < 0 then 0 else if i > 65535 then 65535 else i))] with Not_found -> [] in - let swf = header, fattr @ meta_data @ bg :: debug @ swf_script_limits @ tags @ [tag TShowFrame] in + let swf = header, fattr @ meta_data @ bg :: scene :: debug @ swf_script_limits @ tags @ [tag TShowFrame] in (* merge swf libraries *) let priority = ref (swf_header = None) in let swf = List.fold_left (fun swf (file,lib,cl) -> @@ -1165,9 +1164,8 @@ let generate com swf_header = in {header with h_frame_count = header.h_frame_count + 1},loop tags | _ -> swf in - t(); (* write swf/swc *) - let t = Common.timer "write swf" in + let t = Common.timer ["write";"swf"] in let level = (try int_of_string (Common.defined_value com Define.SwfCompressLevel) with Not_found -> 9) in SwfParser.init Extc.input_zip (Extc.output_zip ~level); (match swc with diff --git a/genswf9.ml b/src/generators/genswf9.ml similarity index 95% rename from genswf9.ml rename to src/generators/genswf9.ml index 1d3bf9f3..f66447d7 100644 --- a/genswf9.ml +++ b/src/generators/genswf9.ml @@ -1,25 +1,23 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) +open Globals open Ast open Type open As3 @@ -110,8 +108,8 @@ let rec follow t = match Type.follow t with | t -> t -let invalid_expr p = error "Invalid expression" p -let stack_error p = error "Stack error" p +let invalid_expr p = abort "Invalid expression" p +let stack_error p = abort "Stack error" p let index_int (x : int) : 'a index = Obj.magic (x + 1) let index_nz_int (x : int) : 'a index_nz = Obj.magic x @@ -216,17 +214,18 @@ let rec type_id ctx t = | TInst ({ cl_path = ["haxe"],"Int32" },_) -> type_path ctx ([],"Int") | TInst ({ cl_path = ["flash"],"Vector" } as c,pl) -> + let def() = HMParams (type_path ctx c.cl_path,List.map (type_id ctx) pl) in (match pl with - | [TInst({cl_kind = KTypeParameter _},_)] -> type_path ctx ([],"Object") - | _ -> HMParams (type_path ctx c.cl_path,List.map (type_id ctx) pl)) + | [t] -> (match follow t with + | TInst({cl_kind = KTypeParameter _},_) -> type_path ctx ([],"Object") + | _ -> def()) + | _ -> def()) | TInst (c,_) -> (match c.cl_kind with | KTypeParameter l -> (match l with | [t] -> type_id ctx t | _ -> type_path ctx ([],"Object")) - | KExtension (c,params) -> - type_id ctx (TInst (c,params)) | _ -> type_path ctx c.cl_path) | TAbstract (a,_) -> @@ -346,13 +345,6 @@ let property ctx p t = | "ffloor" | "fceil" | "fround" -> ident (String.sub p 1 (String.length p - 1)), None, false | _ -> ident p, None, false) | _ -> ident p, None, false) - | TInst ({ cl_kind = KExtension _ } as c,params) -> - (* cast type when accessing an extension field *) - (try - let f = PMap.find p c.cl_fields in - ident p, Some (classify ctx (apply_params c.cl_params params f.cf_type)), false - with Not_found -> - ident p, None, false) | TInst ({ cl_interface = true } as c,_) -> (* lookup the interface in which the field was actually declared *) let rec loop c = @@ -495,7 +487,7 @@ let define_local ctx ?(init=false) v p = let is_set v = (Obj.magic v) = Write let gen_local_access ctx v p (forset : 'a) : 'a access = - match snd (try PMap.find v.v_id ctx.locals with Not_found -> error ("Unbound variable " ^ v.v_name) p) with + match snd (try PMap.find v.v_id ctx.locals with Not_found -> abort ("Unbound variable " ^ v.v_name) p) with | LReg r -> VReg r | LScope n -> @@ -617,7 +609,7 @@ let debug_infos ?(is_min=true) ctx p = if ctx.debug then begin let line = Lexer.get_error_line (if is_min then p else { p with pmin = p.pmax }) in if ctx.last_file <> p.pfile then begin - write ctx (HDebugFile (if ctx.debugger then Common.get_full_path p.pfile else p.pfile)); + write ctx (HDebugFile (if ctx.debugger then Path.get_full_path p.pfile else p.pfile)); ctx.last_file <- p.pfile; ctx.last_line <- -1; end; @@ -718,7 +710,7 @@ let begin_fun ctx args tret el stat p = | TInt i -> if kind = KUInt then HVUInt i else HVInt i | TFloat s -> HVFloat (float_of_string s) | TBool b -> HVBool b - | TNull -> error ("In Flash9, null can't be used as basic type " ^ s_type (print_context()) t) p + | TNull -> abort ("In Flash9, null can't be used as basic type " ^ s_type (print_context()) t) p | _ -> assert false) | _, Some TNull -> HVNone | k, Some c -> @@ -893,7 +885,7 @@ let rec gen_access ctx e (forset : 'a) : 'a access = | TField (e1,fa) -> let f = field_name fa in let id, k, closure = property ctx f e1.etype in - if closure && not ctx.for_call then error "In Flash9, this method cannot be accessed this way : please define a local function" e1.epos; + if closure && not ctx.for_call then abort "In Flash9, this method cannot be accessed this way : please define a local function" e1.epos; (match e1.eexpr with | TConst (TThis|TSuper) when not ctx.in_static -> write ctx (HFindProp id) @@ -1081,6 +1073,10 @@ let rec gen_expr_content ctx retval e = | TNew ({ cl_path = [],"Array" },_,[]) -> (* it seems that [] is 4 time faster than new Array() *) write ctx (HArray 0) + | TNew ({ cl_path = ["flash"],"Vector" },[t],_) when (match follow t with TInst({ cl_kind = KTypeParameter _ },_) -> true | _ -> false) -> + write ctx (HString "Cannot create Vector without knowing runtime type"); + write ctx HThrow; + no_value ctx retval | TNew (c,tl,pl) -> let id = type_id ctx (TInst (c,tl)) in (match id with @@ -1128,7 +1124,7 @@ let rec gen_expr_content ctx retval e = | TUnop (op,flag,e) -> gen_unop ctx retval op flag e | TTry (e2,cases) -> - if ctx.infos.istack <> 0 then error "Cannot compile try/catch as a right-side expression in Flash9" e.epos; + if ctx.infos.istack <> 0 then abort "Cannot compile try/catch as a right-side expression in Flash9" e.epos; let branch = begin_branch ctx in let p = ctx.infos.ipos in gen_expr ctx retval e2; @@ -1380,8 +1376,8 @@ and gen_call ctx retval e el r = gen_expr ctx true counter; write ctx HForIn | TLocal { v_name = "__has_next__" }, [obj;counter] -> - let oreg = match gen_access ctx obj Read with VReg r -> r | _ -> error "Must be a local variable" obj.epos in - let creg = match gen_access ctx counter Read with VReg r -> r | _ -> error "Must be a local variable" obj.epos in + let oreg = match gen_access ctx obj Read with VReg r -> r | _ -> abort "Must be a local variable" obj.epos in + let creg = match gen_access ctx counter Read with VReg r -> r | _ -> abort "Must be a local variable" obj.epos in write ctx (HNext (oreg.rid,creg.rid)) | TLocal { v_name = "__hkeys__" }, [e2] | TLocal { v_name = "__foreach__" }, [e2] @@ -1572,7 +1568,7 @@ and check_binop ctx e1 e2 = let invalid = (match classify ctx e1.etype, classify ctx e2.etype with | KInt, KUInt | KUInt, KInt -> (match e1.eexpr, e2.eexpr with TConst (TInt i) , _ | _ , TConst (TInt i) -> i < 0l | _ -> true) | _ -> false) in - if invalid then error "Comparison of Int and UInt might lead to unexpected results" (punion e1.epos e2.epos); + if invalid then abort "Comparison of Int and UInt might lead to unexpected results" (punion e1.epos e2.epos); and gen_binop ctx retval op e1 e2 t p = let write_op op = @@ -1887,12 +1883,12 @@ let generate_class_init ctx c hc = | None -> () | Some e -> gen_expr ctx false e; - if ctx.block_vars <> [] then error "You can't have a local variable referenced from a closure inside __init__ (FP 10.1.53 crash)" e.epos; + if ctx.block_vars <> [] then abort "You can't have a local variable referenced from a closure inside __init__ (FP 10.1.53 crash)" e.epos; ); generate_class_statics ctx c true; if ctx.swc then begin generate_class_statics ctx c false; - if ctx.block_vars <> [] then error "You can't have a local variable referenced from a closure inside a static (FP 10.1.53 crash)" c.cl_pos; + if ctx.block_vars <> [] then abort "You can't have a local variable referenced from a closure inside a static (FP 10.1.53 crash)" c.cl_pos; end let generate_enum_init ctx e hc meta = @@ -1936,7 +1932,7 @@ let extract_meta meta = match a with | EConst (String s) -> (None, s) | EBinop (OpAssign,(EConst (Ident n),_),(EConst (String s),_)) -> (Some n, s) - | _ -> error "Invalid meta definition" p + | _ -> abort "Invalid meta definition" p in { hlmeta_name = n; hlmeta_data = Array.of_list (List.map mk_arg args) } :: loop l | _ :: l -> loop l @@ -1994,7 +1990,7 @@ let generate_field_kind ctx f c stat = ) args; let dparams = (match !dparams with None -> None | Some l -> Some (List.rev l)) in Some (HFMethod { - hlm_type = end_fun ctx (List.map (fun (a,opt,t) -> alloc_var a t, (if opt then Some TNull else None)) args) dparams tret; + hlm_type = end_fun ctx (List.map (fun (a,opt,t) -> alloc_var a t f.cf_pos, (if opt then Some TNull else None)) args) dparams tret; hlm_final = false; hlm_override = false; hlm_kind = snd (method_kind()); @@ -2017,10 +2013,19 @@ let check_constructor ctx c f = match e.eexpr with | TCall ({ eexpr = TConst TSuper },_) -> raise Exit | TBinop (OpAssign,{ eexpr = TField({ eexpr = TConst TThis },FInstance (cc,_,cf)) },_) when c != cc && (match classify ctx cf.cf_type with KFloat | KDynamic -> true | _ -> false) -> - error "You cannot assign some super class vars before calling super() in flash, this will reset them to default value" e.epos + abort "You cannot assign some super class vars before calling super() in flash, this will reset them to default value" e.epos + | _ -> () + in + (* only do so if we have a call to super() *) + let rec has_super e = + Type.iter has_super e; + match e.eexpr with + | TCall ({ eexpr = TConst TSuper },_) -> raise Exit | _ -> () in try + has_super f.tf_expr + with Exit -> try loop f.tf_expr with Exit -> () @@ -2116,9 +2121,11 @@ let generate_class ctx c = cf_meta = []; cf_doc = None; cf_pos = c.cl_pos; + cf_name_pos = null_pos; cf_type = TFun ([],t_dynamic); cf_params = []; cf_expr = None; + cf_expr_unoptimized = None; cf_kind = Method MethNormal; cf_overloads = []; } false; @@ -2171,7 +2178,7 @@ let generate_class ctx c = hlc_interface = c.cl_interface; hlc_namespace = (match !has_protected with None -> None | Some p -> Some (HNProtected p)); hlc_implements = Array.of_list (List.map (fun (c,_) -> - if not c.cl_interface then error "Can't implement class in Flash9" c.cl_pos; + if not c.cl_interface then abort "Can't implement class in Flash9" c.cl_pos; let pack, name = real_path c.cl_path in HMMultiName (Some name,[HNPublic (Some (String.concat "." pack))]) ) c.cl_implements); @@ -2184,7 +2191,7 @@ let generate_class ctx c = let generate_enum ctx e meta = let name_id = type_path ctx e.e_path in let api = ctx.com.basic in - let f = begin_fun ctx [alloc_var "tag" api.tstring, None;alloc_var "index" api.tint, None;alloc_var "params" (api.tarray (mk_mono())), None] api.tvoid [ethis] false e.e_pos in + let f = begin_fun ctx [alloc_var "tag" api.tstring e.e_pos, None;alloc_var "index" api.tint e.e_pos, None;alloc_var "params" (api.tarray (mk_mono())) e.e_pos, None] api.tvoid [ethis] false e.e_pos in let tag_id = ident "tag" in let index_id = ident "index" in let params_id = ident "params" in @@ -2215,7 +2222,7 @@ let generate_enum ctx e meta = hlf_slot = !st_count; hlf_kind = (match f.ef_type with | TFun (args,_) -> - let fdata = begin_fun ctx (List.map (fun (a,opt,t) -> alloc_var a t, (if opt then Some TNull else None)) args) (TEnum (e,[])) [] true f.ef_pos in + let fdata = begin_fun ctx (List.map (fun (a,opt,t) -> alloc_var a t e.e_pos, (if opt then Some TNull else None)) args) (TEnum (e,[])) [] true f.ef_pos in write ctx (HFindPropStrict name_id); write ctx (HString f.ef_name); write ctx (HInt f.ef_index); @@ -2324,7 +2331,7 @@ let rec generate_type ctx t = hlf_metas = extract_meta e.e_meta; }) | TAbstractDecl ({ a_path = [],"Dynamic" } as a) -> - generate_type ctx (TClassDecl (mk_class a.a_module a.a_path a.a_pos)) + generate_type ctx (TClassDecl (mk_class a.a_module a.a_path a.a_pos null_pos)) | TTypeDecl _ | TAbstractDecl _ -> None @@ -2332,8 +2339,8 @@ let resource_path name = (["_res"],"_" ^ String.concat "_" (ExtString.String.nsplit name ".")) let generate_resource ctx name = - let c = mk_class null_module (resource_path name) null_pos in - c.cl_super <- Some (mk_class null_module (["flash";"utils"],"ByteArray") null_pos,[]); + let c = mk_class null_module (resource_path name) null_pos null_pos in + c.cl_super <- Some (mk_class null_module (["flash";"utils"],"ByteArray") null_pos null_pos,[]); let t = TClassDecl c in match generate_type ctx t with | Some (m,f) -> (t,m,f) diff --git a/genxml.ml b/src/generators/genxml.ml similarity index 91% rename from genxml.ml rename to src/generators/genxml.ml index 34d86dba..5fa9b37f 100644 --- a/genxml.ml +++ b/src/generators/genxml.ml @@ -1,25 +1,23 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) +open Globals open Ast open Type open Common @@ -83,12 +81,12 @@ let rec follow_param t = t let gen_meta meta = - let meta = List.filter (fun (m,_,_) -> match m with Meta.Used | Meta.MaybeUsed | Meta.RealPath -> false | _ -> true) meta in + let meta = List.filter (fun (m,_,_) -> match m with Meta.Used | Meta.MaybeUsed | Meta.RealPath | Meta.Pure -> false | _ -> true) meta in match meta with | [] -> [] | _ -> let nodes = List.map (fun (m,el,_) -> - node "m" ["n",fst (MetaInfo.to_string m)] (List.map (fun e -> node "e" [] [gen_string (Ast.s_expr e)]) el) + node "m" ["n",Meta.to_string m] (List.map (fun e -> node "e" [] [gen_string (Ast.s_expr e)]) el) ) meta in [node "meta" [] nodes] @@ -288,10 +286,10 @@ let rec write_xml ch tabs x = IO.printf ch "" s let generate com file = - let t = Common.timer "construct xml" in + let t = Common.timer ["generate";"xml"] in let x = node "haxe" [] (List.map (gen_type_decl com true) (List.filter (fun t -> not (Meta.has Meta.NoDoc (t_infos t).mt_meta)) com.types)) in t(); - let t = Common.timer "write xml" in + let t = Common.timer ["write";"xml"] in let ch = IO.output_channel (open_out_bin file) in write_xml ch "" x; IO.close_out ch; @@ -428,15 +426,11 @@ let generate_type com t = | Meta.DefParam | Meta.CoreApi | Meta.Used | Meta.MaybeUsed | Meta.FlatEnum | Meta.Value | Meta.DirectlyUsed -> () | _ -> match pl with - | [] -> p "@%s " (fst (MetaInfo.to_string m)) - | l -> p "@%s(%s) " (fst (MetaInfo.to_string m)) (String.concat "," (List.map Ast.s_expr pl)) + | [] -> p "@%s " (Meta.to_string m) + | l -> p "@%s(%s) " (Meta.to_string m) (String.concat "," (List.map Ast.s_expr pl)) ) ml in - let access is_read a = - match a, pack with - | AccNever, "flash" :: _ -> "null" - | _ -> s_access is_read a - in + let access is_read a = s_access is_read a in let rec print_field stat f = p "\t"; print_meta f.cf_meta; @@ -505,7 +499,7 @@ let generate_type com t = ) in let ext = (match c.cl_path with | ["flash";"utils"], "ByteArray" -> " implements ArrayAccess" :: ext - | ["flash";"utils"], "Dictionnary" -> [" implements ArrayAccess"] + | ["flash";"utils"], "Dictionary" -> [" implements ArrayAccess"] | ["flash";"xml"], "XML" -> [" implements Dynamic"] | ["flash";"xml"], "XMLList" -> [" implements ArrayAccess"] | ["flash";"display"],"MovieClip" -> [" extends Sprite #if !flash_strict implements Dynamic #end"] diff --git a/src/generators/hl2c.ml b/src/generators/hl2c.ml new file mode 100644 index 00000000..00b541b4 --- /dev/null +++ b/src/generators/hl2c.ml @@ -0,0 +1,1410 @@ +(* + * Copyright (C)2005-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. + *) +open Hlcode + +type comparison = + | CEq + | CNeq + | CLt + | CGt + | CLte + | CGte + +type output_options = + | OOLabel + | OOCase of int + | OODefault + | OOIncreaseIndent + | OODecreaseIndent + | OOBeginBlock + | OOEndBlock + +type function_entry = { + mutable fe_name : string; + mutable fe_decl : fundecl option; + mutable fe_args : ttype list; + mutable fe_ret : ttype; +} + +type context = { + version : int; + out : Buffer.t; + mutable tabs : string; + hash_cache : (int, int32) Hashtbl.t; + hlcode : code; + dir : string; + mutable curfile : string; + mutable cfiles : string list; + ftable : function_entry array; + htypes : (ttype, int) PMap.t; +} + +let sprintf = Printf.sprintf + +let keywords = + let c_kwds = [ + "auto";"break";"case";"char";"const";"continue";"default";"do";"double";"else";"enum";"extern";"float";"for";"goto"; + "if";"int";"long";"register";"return";"short";"signed";"sizeof";"static";"struct";"switch";"typedef";"union";"unsigned"; + "void";"volatile";"while"; + (* MS specific *) + "__asm";"dllimport2";"__int8";"naked2";"__based1";"__except";"__int16";"__stdcall";"__cdecl";"__fastcall";"__int32"; + "thread2";"__declspec";"__finally";"__int64";"__try";"dllexport2";"__inline";"__leave";"asm"; + (* reserved by HLC *) + "t"; + (* C11 *) + "_Alignas";"_Alignof";"_Atomic";"_Bool";"_Complex";"_Generic";"_Imaginary";"_Noreturn";"_Static_assert";"_Thread_local";"_Pragma"; + "inline";"restrict" + ] in + let h = Hashtbl.create 0 in + List.iter (fun i -> Hashtbl.add h i ()) c_kwds; + h + +let ident i = if Hashtbl.mem keywords i then "_" ^ i else i + +let s_comp = function + | CLt -> "<" + | CGt -> ">" + | CEq -> "==" + | CLte -> "<=" + | CGte -> ">=" + | CNeq -> "!=" + +let core_types = + let vp = { vfields = [||]; vindex = PMap.empty } in + let ep = { ename = ""; eid = 0; eglobal = None; efields = [||] } in + [HVoid;HUI8;HUI16;HI32;HF32;HF64;HBool;HBytes;HDyn;HFun ([],HVoid);HObj null_proto;HArray;HType;HRef HVoid;HVirtual vp;HDynObj;HAbstract ("",0);HEnum ep;HNull HVoid] + +let tname str = + let n = String.concat "__" (ExtString.String.nsplit str ".") in + if Hashtbl.mem keywords ("_" ^ n) then "__" ^ n else n + +let is_gc_ptr = function + | HVoid | HUI8 | HUI16 | HI32 | HF32 | HF64 | HBool | HType | HRef _ -> false + | HBytes | HDyn | HFun _ | HObj _ | HArray | HVirtual _ | HDynObj | HAbstract _ | HEnum _ | HNull _ -> true + +let is_ptr = function + | HVoid | HUI8 | HUI16 | HI32 | HF32 | HF64 | HBool -> false + | _ -> true + +let rec ctype_no_ptr = function + | HVoid -> "void",0 + | HUI8 -> "unsigned char",0 + | HUI16 -> "unsigned short",0 + | HI32 -> "int",0 + | HF32 -> "float",0 + | HF64 -> "double",0 + | HBool -> "bool",0 + | HBytes -> "vbyte",1 + | HDyn -> "vdynamic",1 + | HFun _ -> "vclosure",1 + | HObj p -> tname p.pname,0 + | HArray -> "varray",1 + | HType -> "hl_type",1 + | HRef t -> let s,i = ctype_no_ptr t in s,i + 1 + | HVirtual _ -> "vvirtual",1 + | HDynObj -> "vdynobj",1 + | HAbstract (name,_) -> name,1 + | HEnum _ -> "venum",1 + | HNull _ -> "vdynamic",1 + +let ctype t = + let t, nptr = ctype_no_ptr t in + if nptr = 0 then t else t ^ String.make nptr '*' + +let cast_fun s args t = + sprintf "((%s (*)(%s))%s)" (ctype t) (String.concat "," (List.map ctype args)) s + +let dyn_value_field t = + "->v." ^ match t with + | HUI8 -> "ui8" + | HUI16 -> "ui16" + | HI32 -> "i" + | HF32 -> "f" + | HF64 -> "d" + | HBool -> "b" + | _ -> "ptr" + +let type_id t = + match t with + | HVoid -> "HVOID" + | HUI8 -> "HUI8" + | HUI16 -> "HUI16" + | HI32 -> "HI32" + | HF32 -> "HF32" + | HF64 -> "HF64" + | HBool -> "HBOOL" + | HBytes -> "HBYTES" + | HDyn -> "HDYN" + | HFun _ -> "HFUN" + | HObj _ -> "HOBJ" + | HArray -> "HARRAY" + | HType -> "HTYPE" + | HRef _ -> "HREF" + | HVirtual _ -> "HVIRTUAL" + | HDynObj -> "HDYNOBJ" + | HAbstract _ -> "HABSTRACT" + | HEnum _ -> "HENUM" + | HNull _ -> "HNULL" + +let var_type n t = + ctype t ^ " " ^ ident n + +let block ctx = + ctx.tabs <- ctx.tabs ^ "\t" + +let unblock ctx = + ctx.tabs <- String.sub ctx.tabs 0 (String.length ctx.tabs - 1) + +let hash ctx sid = + try + Hashtbl.find ctx.hash_cache sid + with Not_found -> + let h = hl_hash ctx.hlcode.strings.(sid) in + Hashtbl.add ctx.hash_cache sid h; + h + +let type_value ctx t = + let index = (try PMap.find t ctx.htypes with Not_found -> assert false) in + "&type$" ^ string_of_int index + +let enum_constr_type ctx e i = + let cname,_, tl = e.efields.(i) in + if Array.length tl = 0 then + "venum" + else + let name = if e.eid = 0 then + let index = (try PMap.find (HEnum e) ctx.htypes with Not_found -> assert false) in + "Enum$" ^ string_of_int index + else + String.concat "_" (ExtString.String.nsplit e.ename ".") + in + if cname = "" then + name + else + name ^ "_" ^ cname + +let output ctx str = + Buffer.add_string ctx.out str + +let output_char ctx c = + Buffer.add_char ctx.out c + +let line ctx str = + output ctx ctx.tabs; + output ctx str; + output_char ctx '\n' + +let expr ctx str = + output ctx ctx.tabs; + output ctx str; + output ctx ";\n" + +let unamed_field fid = "$_f" ^ string_of_int fid + +let obj_field fid name = + if name = "" then unamed_field fid else ident name + +let close_file ctx = + let str = Buffer.contents ctx.out in + Buffer.reset ctx.out; + let fpath = ctx.dir ^ "/" ^ ctx.curfile in + if String.sub ctx.curfile (String.length ctx.curfile - 2) 2 = ".c" then ctx.cfiles <- ctx.curfile :: ctx.cfiles; + ctx.curfile <- ""; + let fcontent = (try Std.input_file ~bin:true fpath with _ -> "") in + if fcontent <> str then begin + Common.mkdir_recursive "" (ExtString.String.nsplit (Filename.dirname fpath) "/"); + let ch = open_out_bin fpath in + output_string ch str; + close_out ch; + end + +let open_file ctx file = + if ctx.curfile <> "" then close_file ctx; + let version_major = ctx.version / 1000 in + let version_minor = (ctx.version mod 1000) / 100 in + let version_revision = (ctx.version mod 100) in + if file <> "hlc.json" then line ctx (sprintf "// Generated by HLC %d.%d.%d (HL v%d)" version_major version_minor version_revision ctx.hlcode.version); + ctx.curfile <- file + +let string_data_limit = 64 + +let string ctx sid = + let s = ctx.hlcode.strings.(sid) in + if String.length s < string_data_limit then + sprintf "USTR(\"%s\")" (Ast.s_escape ~hex:false s) + else + sprintf "string$%d" sid + +let generate_reflection ctx = + let line = line ctx and expr = expr ctx in + let sline fmt = Printf.ksprintf line fmt and sexpr fmt = Printf.ksprintf expr fmt in + + let funByArgs = Hashtbl.create 0 in + let type_kind t = + match t with + | HVoid | HF32 | HF64 -> t + | HBool | HUI8 | HUI16 | HI32 -> HI32 + | HBytes | HDyn | HFun _ | HObj _ | HArray | HType | HRef _ | HVirtual _ | HDynObj | HAbstract _ | HEnum _ | HNull _ -> HDyn + in + let type_kind_id t = + match t with + | HVoid -> 0 + | HBool | HUI8 | HUI16 | HI32 -> 1 (* same int representation *) + | HF32 -> 2 + | HF64 -> 3 + | _ -> 4 + in + let add_fun args t = + let nargs = List.length args in + let kargs = List.map type_kind args in + let kt = type_kind t in + let h = try Hashtbl.find funByArgs nargs with Not_found -> let h = Hashtbl.create 0 in Hashtbl.add funByArgs nargs h; h in + Hashtbl.replace h (kargs,kt) () + in + Array.iter (fun f -> + Array.iter (fun op -> + match op with + | OSafeCast (dst,_) | ODynGet (dst,_,_) -> + (match f.regs.(dst) with + | HFun (args, t) -> add_fun args t + | _ -> ()) + | _ -> () + ) f.code + ) ctx.hlcode.functions; + Array.iter (fun f -> add_fun f.fe_args f.fe_ret) ctx.ftable; + let argsCounts = List.sort compare (Hashtbl.fold (fun i _ acc -> i :: acc) funByArgs []) in + sexpr "static int TKIND[] = {%s}" (String.concat "," (List.map (fun t -> string_of_int (type_kind_id (type_kind t))) core_types)); + line ""; + line "void *hlc_static_call( void *fun, hl_type *t, void **args, vdynamic *out ) {"; + block ctx; + sexpr "int chk = TKIND[t->fun->ret->kind]"; + sexpr "vdynamic *d"; + line "switch( t->fun->nargs ) {"; + List.iter (fun nargs -> + sline "case %d:" nargs; + block ctx; + if nargs > 9 then sexpr "hl_fatal(\"Too many arguments, TODO:use more bits\")" else begin + for i = 0 to nargs-1 do + sexpr "chk |= TKIND[t->fun->args[%d]->kind] << %d" i ((i + 1) * 3); + done; + line "switch( chk ) {"; + Hashtbl.iter (fun (args,t) _ -> + let s = ref (-1) in + let chk = List.fold_left (fun chk t -> incr s; chk lor ((type_kind_id t) lsl (!s * 3))) 0 (t :: args) in + sline "case %d:" chk; + block ctx; + let idx = ref (-1) in + let vargs = List.map (fun t -> + incr idx; + if is_ptr t then + sprintf "(%s)args[%d]" (ctype t) !idx + else + sprintf "*(%s*)args[%d]" (ctype t) !idx + ) args in + let call = sprintf "%s(%s)" (cast_fun "fun" args t) (String.concat "," vargs) in + if is_ptr t then + sexpr "return %s" call + else if t = HVoid then begin + expr call; + expr "return NULL"; + end else begin + sexpr "out%s = %s" (dyn_value_field t) call; + sexpr "return &out%s" (dyn_value_field t); + end; + unblock ctx; + ) (Hashtbl.find funByArgs nargs); + sline "}"; + expr "break"; + end; + unblock ctx; + ) argsCounts; + line "}"; + sexpr "hl_fatal(\"Unsupported dynamic call\")"; + sexpr "return NULL"; + unblock ctx; + line "}"; + line ""; + let wrap_char = function + | HVoid -> "v" + | HUI8 | HUI16 | HBool | HI32 -> "i" + | HF32 -> "f" + | HF64 -> "d" + | _ -> "p" + in + let make_wrap_name args t = + String.concat "" (List.map wrap_char args) ^ "_" ^ wrap_char t + in + List.iter (fun nargs -> + Hashtbl.iter (fun (args,t) _ -> + let name = make_wrap_name args t in + sline "static %s wrap_%s(void *value%s) {" (ctype t) name (String.concat "" (list_mapi (fun i t -> "," ^ var_type ("p" ^ string_of_int i) t) args)); + block ctx; + if args <> [] then sexpr "void *args[] = {%s}" (String.concat "," (list_mapi (fun i t -> + if not (is_ptr t) then + sprintf "&p%d" i + else + sprintf "p%d" i + ) args)); + let vargs = if args = [] then "NULL" else "args" in + if t = HVoid then + sexpr "hl_wrapper_call(value,%s,NULL)" vargs + else if is_ptr t then + sexpr "return hl_wrapper_call(value,%s,NULL)" vargs + else begin + expr "vdynamic ret"; + sexpr "hl_wrapper_call(value,%s,&ret)" vargs; + sexpr "return ret.v.%s" (wrap_char t); + end; + unblock ctx; + line "}"; + ) (Hashtbl.find funByArgs nargs); + ) argsCounts; + line ""; + line "void *hlc_get_wrapper( hl_type *t ) {"; + block ctx; + sexpr "int chk = TKIND[t->fun->ret->kind]"; + line "switch( t->fun->nargs ) {"; + List.iter (fun nargs -> + sline "case %d:" nargs; + block ctx; + if nargs > 9 then sexpr "hl_fatal(\"Too many arguments, TODO:use more bits\")" else begin + for i = 0 to nargs-1 do + sexpr "chk |= TKIND[t->fun->args[%d]->kind] << %d" i ((i + 1) * 3); + done; + line "switch( chk ) {"; + Hashtbl.iter (fun (args,t) _ -> + let s = ref (-1) in + let chk = List.fold_left (fun chk t -> incr s; chk lor ((type_kind_id t) lsl (!s * 3))) 0 (t :: args) in + sexpr "case %d: return wrap_%s" chk (make_wrap_name args t); + ) (Hashtbl.find funByArgs nargs); + sline "}"; + expr "break"; + end; + unblock ctx; + ) argsCounts; + line "}"; + sexpr "return NULL"; + unblock ctx; + line "}"; + line "" + +let generate_function ctx f = + let line = line ctx and expr = expr ctx in + let sline fmt = Printf.ksprintf line fmt and sexpr fmt = Printf.ksprintf expr fmt in + let block() = block ctx and unblock() = unblock ctx in + let type_value = type_value ctx in + let code = ctx.hlcode in + + let rid = ref (-1) in + let reg id = "r" ^ string_of_int id in + + let label id = "label$" ^ string_of_int f.findex ^ "$" ^ string_of_int id in + + let rtype r = f.regs.(r) in + + let funname fid = ctx.ftable.(fid).fe_name in + + let rcast r t = + if tsame (rtype r) t then (reg r) + else Printf.sprintf "((%s)%s)" (ctype t) (reg r) + in + + let rfun r args t = + cast_fun (reg r ^ "->fun") args t + in + + let rassign r t = + let rt = rtype r in + if t = HVoid then "" else + let assign = reg r ^ " = " in + if tsame t rt then assign else + if not (safe_cast t rt) then assert false + else assign ^ "(" ^ ctype rt ^ ")" + in + + let ocall r fid args = + let ft = ctx.ftable.(fid) in + let rstr = rassign r ft.fe_ret in + sexpr "%s%s(%s)" rstr ft.fe_name (String.concat "," (List.map2 rcast args ft.fe_args)) + in + + + let dyn_prefix = function + | HUI8 | HUI16 | HI32 | HBool -> "i" + | HF32 -> "f" + | HF64 -> "d" + | _ -> "p" + in + + let type_value_opt t = + match t with HF32 | HF64 -> "" | _ -> "," ^ type_value t + in + + let dyn_call r f pl = + line "{"; + block(); + if pl <> [] then sexpr "vdynamic *args[] = {%s}" (String.concat "," (List.map (fun p -> + match rtype p with + | HDyn -> + reg p + | t -> + if is_dynamic t then + sprintf "(vdynamic*)%s" (reg p) + else + sprintf "hl_make_dyn(&%s,%s)" (reg p) (type_value t) + ) pl)); + let rt = rtype r in + let ret = if rt = HVoid then "" else if is_dynamic rt then sprintf "%s = (%s)" (reg r) (ctype rt) else "vdynamic *ret = " in + sexpr "%shl_dyn_call((vclosure*)%s,%s,%d)" ret (reg f) (if pl = [] then "NULL" else "args") (List.length pl); + if rt <> HVoid && not (is_dynamic rt) then sexpr "%s = (%s)hl_dyn_cast%s(&ret,&hlt_dyn%s)" (reg r) (ctype rt) (dyn_prefix rt) (type_value_opt rt); + unblock(); + line "}"; + in + + let mcall r fid = function + | [] -> assert false + | o :: args -> + match rtype o with + | HObj _ -> + let vfun = cast_fun (sprintf "%s->$type->vobj_proto[%d]" (reg o) fid) (rtype o :: List.map rtype args) (rtype r) in + sexpr "%s%s(%s)" (rassign r (rtype r)) vfun (String.concat "," (List.map reg (o::args))) + | HVirtual vp -> + let rt = rtype r in + let meth = sprintf "hl_vfields(%s)[%d]" (reg o) fid in + let meth = cast_fun meth (HDyn :: List.map rtype args) rt in + sline "if( hl_vfields(%s)[%d] ) %s%s(%s); else {" (reg o) fid (rassign r rt) meth (String.concat "," ((reg o ^ "->value") :: List.map reg args)); + block(); + if args <> [] then sexpr "void *args[] = {%s}" (String.concat "," (List.map (fun p -> + let t = rtype p in + if is_ptr t then + reg p + else + sprintf "&%s" (reg p) + ) args)); + let rt = rtype r in + let ret = if rt = HVoid then "" else if is_ptr rt then sprintf "%s = (%s)" (reg r) (ctype rt) else begin sexpr "vdynamic ret"; ""; end in + let fname, fid, ft = vp.vfields.(fid) in + sexpr "%shl_dyn_call_obj(%s->value,%s,%ld/*%s*/,%s,%s)" ret (reg o) (type_value ft) (hash ctx fid) fname (if args = [] then "NULL" else "args") (if is_ptr rt || rt == HVoid then "NULL" else "&ret"); + if rt <> HVoid && not (is_ptr rt) then sexpr "%s = (%s)ret.v.%s" (reg r) (ctype rt) (dyn_prefix rt); + unblock(); + sline "}" + | _ -> + assert false + in + + let set_field obj fid v = + match rtype obj with + | HObj o -> + let name, t = resolve_field o fid in + sexpr "%s->%s = %s" (reg obj) (obj_field fid name) (rcast v t) + | HVirtual vp -> + let name, nid, t = vp.vfields.(fid) in + let dset = sprintf "hl_dyn_set%s(%s->value,%ld/*%s*/%s,%s)" (dyn_prefix t) (reg obj) (hash ctx nid) name (type_value_opt (rtype v)) (reg v) in + (match t with + | HFun _ -> expr dset + | _ -> sexpr "if( hl_vfields(%s)[%d] ) *(%s*)(hl_vfields(%s)[%d]) = (%s)%s; else %s" (reg obj) fid (ctype t) (reg obj) fid (ctype t) (reg v) dset) + | _ -> + assert false + in + + let get_field r obj fid = + match rtype obj with + | HObj o -> + let name, t = resolve_field o fid in + sexpr "%s%s->%s" (rassign r t) (reg obj) (obj_field fid name) + | HVirtual v -> + let name, nid, t = v.vfields.(fid) in + let dget = sprintf "(%s)hl_dyn_get%s(%s->value,%ld/*%s*/%s)" (ctype t) (dyn_prefix t) (reg obj) (hash ctx nid) name (type_value_opt t) in + (match t with + | HFun _ -> sexpr "%s%s" (rassign r t) dget + | _ -> sexpr "%shl_vfields(%s)[%d] ? (*(%s*)(hl_vfields(%s)[%d])) : %s" (rassign r t) (reg obj) fid (ctype t) (reg obj) fid dget) + | _ -> + assert false + in + + let fret = (match f.ftype with + | HFun (args,t) -> + sline "%s %s(%s) {" (ctype t) (funname f.findex) (String.concat "," (List.map (fun t -> incr rid; var_type (reg !rid) t) args)); + t + | _ -> + assert false + ) in + block(); + let var_map = Hashtbl.create 0 in + Array.iteri (fun i t -> + if i <= !rid || t = HVoid then () + else + let key = ctype_no_ptr t in + Hashtbl.replace var_map key (try (reg i) :: Hashtbl.find var_map key with Not_found -> [reg i]) + ) f.regs; + Hashtbl.iter (fun (s,i) il -> + let prefix = String.make i '*' in + let il = List.rev_map (fun s -> prefix ^ s) il in + sexpr "%s %s" s (String.concat ", " il) + ) var_map; + let output_options = Array.make (Array.length f.code + 1) [] in + let output_at i oo = output_options.(i) <- oo :: output_options.(i) in + let output_at2 i ool = List.iter (output_at i) ool in + let has_label i = List.exists (function OOLabel -> true | _ -> false) output_options.(i) in + + let trap_depth = ref 0 in + let max_trap_depth = ref 0 in + Array.iter (fun op -> + match op with + | OTrap _ -> + incr trap_depth; + if !trap_depth > !max_trap_depth then max_trap_depth := !trap_depth + | OEndTrap true -> + decr trap_depth + | _ -> + () + ) f.code; + for i = 0 to !max_trap_depth - 1 do + sexpr "hl_trap_ctx trap$%d" i; + done; + + let flush_options i = + match output_options.(i) with + | [] -> () + | opts -> + (* put label after } *) + let opts = if has_label i && List.mem OOEndBlock opts then OOLabel :: List.filter (fun i -> i <> OOLabel) opts else opts in + let opts = List.rev opts in + List.iter (function + | OOLabel -> sline "%s:" (label i) + | OOCase i -> sline "case %i:" i + | OODefault -> line "default:" + | OOIncreaseIndent -> block() + | OODecreaseIndent -> unblock() + | OOBeginBlock -> line "{" + | OOEndBlock -> line "}" + ) opts + in + + Array.iteri (fun i op -> + flush_options i; + let label delta = + let addr = delta + i + 1 in + let label = label addr in + if not (has_label addr) then output_at addr OOLabel; + label + in + let todo() = + sexpr "hl_fatal(\"%s\")" (ostr (fun id -> "f" ^ string_of_int id) op) + in + let rec compare_op op a b d = + let phys_compare() = + sexpr "if( %s %s %s ) goto %s" (reg a) (s_comp op) (rcast b (rtype a)) (label d) + in + (* + safe_cast is already checked + two ways (same type) for eq + one way for comparisons + *) + match rtype a, rtype b with + | (HUI8 | HUI16 | HI32 | HF32 | HF64 | HBool), (HUI8 | HUI16 | HI32 | HF32 | HF64 | HBool) -> + phys_compare() + | HType, HType -> + sexpr "if( hl_same_type(%s,%s) %s 0 ) {} else goto %s" (reg a) (reg b) (s_comp op) (label d) + | HNull t, HNull _ -> + let field = dyn_value_field t in + let pcompare = sprintf "(%s%s %s %s%s)" (reg a) field (s_comp op) (reg b) field in + if op = CEq then + sexpr "if( %s == %s || (%s && %s && %s) ) goto %s" (reg a) (reg b) (reg a) (reg b) pcompare (label d) + else if op = CNeq then + sexpr "if( %s != %s && (!%s || !%s || %s) ) goto %s" (reg a) (reg b) (reg a) (reg b) pcompare (label d) + else + sexpr "if( %s && %s && %s ) goto %s" (reg a) (reg b) pcompare (label d) + | HDyn , _ | _, HDyn -> + let inv = if op = CGt || op = CGte then "&& i != hl_invalid_comparison " else "" in + sexpr "{ int i = hl_dyn_compare((vdynamic*)%s,(vdynamic*)%s); if( i %s 0 %s) goto %s; }" (reg a) (reg b) (s_comp op) inv (label d) + | HObj oa, HObj _ -> + (try + let fid = PMap.find "__compare" oa.pfunctions in + if op = CEq then + sexpr "if( %s == %s || (%s && %s && %s(%s,%s) == 0) ) goto %s" (reg a) (reg b) (reg a) (reg b) (funname fid) (reg a) (reg b) (label d) + else if op = CNeq then + sexpr "if( %s != %s && (!%s || !%s || %s(%s,%s) != 0) ) goto %s" (reg a) (reg b) (reg a) (reg b) (funname fid) (reg a) (reg b) (label d) + else + sexpr "if( %s && %s && %s(%s,%s) %s 0 ) goto %s" (reg a) (reg b) (funname fid) (reg a) (reg b) (s_comp op) (label d) + with Not_found -> + phys_compare()) + | HVirtual _, HVirtual _ -> + if op = CEq then + sexpr "if( %s == %s || (%s && %s && %s->value && %s->value && %s->value == %s->value) ) goto %s" (reg a) (reg b) (reg a) (reg b) (reg a) (reg b) (reg a) (reg b) (label d) + else if op = CNeq then + sexpr "if( %s != %s && (!%s || !%s || !%s->value || !%s->value || %s->value != %s->value) ) goto %s" (reg a) (reg b) (reg a) (reg b) (reg a) (reg b) (reg a) (reg b) (label d) + else + assert false + | HEnum _, HEnum _ | HDynObj, HDynObj -> + phys_compare() + | HVirtual _, HObj _-> + if op = CEq then + sexpr "if( %s ? (%s && %s->value == (vdynamic*)%s) : (%s == NULL) ) goto %s" (reg a) (reg b) (reg a) (reg b) (reg b) (label d) + else if op = CNeq then + sexpr "if( %s ? (%s == NULL || %s->value != (vdynamic*)%s) : (%s != NULL) ) goto %s" (reg a) (reg b) (reg a) (reg b) (reg b) (label d) + else + assert false + | HObj _, HVirtual _ -> + compare_op op b a d + | HFun _, HFun _ -> + phys_compare() + | ta, tb -> + failwith ("Don't know how to compare " ^ tstr ta ^ " and " ^ tstr tb ^ " (hlc)") + in + match op with + | OMov (r,v) -> + if rtype r <> HVoid then sexpr "%s = %s" (reg r) (rcast v (rtype r)) + | OInt (r,idx) -> + if code.ints.(idx) = 0x80000000l then + sexpr "%s = 0x80000000" (reg r) + else + sexpr "%s = %ld" (reg r) code.ints.(idx) + | OFloat (r,idx) -> + sexpr "%s = %.19g" (reg r) code.floats.(idx) + | OBool (r,b) -> + sexpr "%s = %s" (reg r) (if b then "true" else "false") + | OBytes (r,idx) -> + sexpr "%s = bytes$%d" (reg r) idx + | OString (r,idx) -> + sexpr "%s = (vbyte*)%s" (reg r) (string ctx idx) + | ONull r -> + sexpr "%s = NULL" (reg r) + | OAdd (r,a,b) -> + sexpr "%s = %s + %s" (reg r) (reg a) (reg b) + | OSub (r,a,b) -> + sexpr "%s = %s - %s" (reg r) (reg a) (reg b) + | OMul (r,a,b) -> + sexpr "%s = %s * %s" (reg r) (reg a) (reg b) + | OSDiv (r,a,b) -> + (match rtype r with + | HUI8 | HUI16 | HI32 -> + sexpr "%s = %s == 0 ? 0 : %s / %s" (reg r) (reg b) (reg a) (reg b) + | _ -> + sexpr "%s = %s / %s" (reg r) (reg a) (reg b)) + | OUDiv (r,a,b) -> + sexpr "%s = %s == 0 ? 0 : ((unsigned)%s) / ((unsigned)%s)" (reg r) (reg b) (reg a) (reg b) + | OSMod (r,a,b) -> + (match rtype r with + | HUI8 | HUI16 | HI32 -> + sexpr "%s = %s == 0 ? 0 : %s %% %s" (reg r) (reg b) (reg a) (reg b) + | HF32 -> + sexpr "%s = fmodf(%s,%s)" (reg r) (reg a) (reg b) + | HF64 -> + sexpr "%s = fmod(%s,%s)" (reg r) (reg a) (reg b) + | _ -> + assert false) + | OUMod (r,a,b) -> + sexpr "%s = %s == 0 ? 0 : ((unsigned)%s) %% ((unsigned)%s)" (reg r) (reg b) (reg a) (reg b) + | OShl (r,a,b) -> + sexpr "%s = %s << %s" (reg r) (reg a) (reg b) + | OSShr (r,a,b) -> + sexpr "%s = %s >> %s" (reg r) (reg a) (reg b) + | OUShr (r,a,b) -> + sexpr "%s = ((unsigned)%s) >> %s" (reg r) (reg a) (reg b) + | OAnd (r,a,b) -> + sexpr "%s = %s & %s" (reg r) (reg a) (reg b) + | OOr (r,a,b) -> + sexpr "%s = %s | %s" (reg r) (reg a) (reg b) + | OXor (r,a,b) -> + sexpr "%s = %s ^ %s" (reg r) (reg a) (reg b) + | ONeg (r,v) -> + sexpr "%s = -%s" (reg r) (reg v) + | ONot (r,v) -> + sexpr "%s = !%s" (reg r) (reg v) + | OIncr r -> + sexpr "++%s" (reg r) + | ODecr r -> + sexpr "--%s" (reg r) + | OCall0 (r,fid) -> + ocall r fid [] + | OCall1 (r,fid,a) -> + ocall r fid [a] + | OCall2 (r,fid,a,b) -> + ocall r fid [a;b] + | OCall3 (r,fid,a,b,c) -> + ocall r fid [a;b;c] + | OCall4 (r,fid,a,b,c,d) -> + ocall r fid [a;b;c;d] + | OCallN (r,fid,rl) -> + ocall r fid rl + | OCallMethod (r,fid,pl) -> + mcall r fid pl + | OCallThis (r,fid,pl) -> + mcall r fid (0 :: pl) + | OCallClosure (r,cl,pl) -> + (match rtype cl with + | HDyn -> + dyn_call r cl pl + | HFun (args,ret) -> + let sargs = String.concat "," (List.map2 rcast pl args) in + sexpr "%s%s->hasValue ? %s((vdynamic*)%s->value%s) : %s(%s)" (rassign r ret) (reg cl) (rfun cl (HDyn :: args) ret) (reg cl) (if sargs = "" then "" else "," ^ sargs) (rfun cl args ret) sargs + | _ -> + assert false) + | OStaticClosure (r,fid) -> + sexpr "%s = &cl$%d" (reg r) fid + | OInstanceClosure (r,fid,ptr) -> + let ft = ctx.ftable.(fid) in + sexpr "%s = hl_alloc_closure_ptr(%s,%s,%s)" (reg r) (type_value (HFun (ft.fe_args,ft.fe_ret))) (funname fid) (reg ptr) + | OVirtualClosure (r,o,m) -> + (match rtype o with + | HObj p -> + let ft = ctx.ftable.(p.pvirtuals.(m)) in + let s = sprintf "%s->$type->vobj_proto[%d]" (reg o) m in + sexpr "%s = hl_alloc_closure_ptr(%s,%s,%s)" (reg r) (type_value (HFun(ft.fe_args,ft.fe_ret))) s (reg o) + | _ -> + todo()) + | OGetGlobal (r,g) -> + sexpr "%s = (%s)global$%d" (reg r) (ctype (rtype r)) g + | OSetGlobal (g,r) -> + sexpr "global$%d = (%s)%s" g (ctype code.globals.(g)) (reg r) + | ORet r -> + if rtype r = HVoid then expr "return" else sexpr "return %s" (rcast r fret) + | OJTrue (r,d) | OJNotNull (r,d) -> + sexpr "if( %s ) goto %s" (reg r) (label d) + | OJFalse (r,d) | OJNull (r,d) -> + sexpr "if( !%s ) goto %s" (reg r) (label d) + | OJSLt (a,b,d) -> + compare_op CLt a b d + | OJSGte (a,b,d) -> + compare_op CGte a b d + | OJSGt (a,b,d) -> + compare_op CGt a b d + | OJSLte (a,b,d) -> + compare_op CLte a b d + | OJULt (a,b,d) -> + sexpr "if( ((unsigned)%s) < ((unsigned)%s) ) goto %s" (reg a) (reg b) (label d) + | OJUGte (a,b,d) -> + sexpr "if( ((unsigned)%s) >= ((unsigned)%s) ) goto %s" (reg a) (reg b) (label d) + | OJEq (a,b,d) -> + compare_op CEq a b d + | OJNotEq (a,b,d) -> + compare_op CNeq a b d + | OJAlways d -> + sexpr "goto %s" (label d) + | OLabel _ -> + if not (has_label i) then sline "%s:" (label (-1)) + | OToDyn (r,v) -> + if is_ptr (rtype v) then begin + sline "if( %s == NULL ) %s = NULL; else {" (reg v) (reg r); + block(); + end; + sexpr "%s = hl_alloc_dynamic(%s)" (reg r) (type_value (rtype v)); + (match rtype v with + | HUI8 | HUI16 | HI32 | HBool -> + sexpr "%s->v.i = %s" (reg r) (reg v) + | HF32 -> + sexpr "%s->v.f = %s" (reg r) (reg v) + | HF64 -> + sexpr "%s->v.d = %s" (reg r) (reg v) + | _ -> + sexpr "%s->v.ptr = %s" (reg r) (reg v)); + if is_ptr (rtype v) then begin + unblock(); + line "}"; + end; + | OToSFloat (r,v) -> + sexpr "%s = (%s)%s" (reg r) (ctype (rtype r)) (reg v) + | OToUFloat (r,v) -> + sexpr "%s = (%s)(unsigned)%s" (reg r) (ctype (rtype r)) (reg v) + | OToInt (r,v) -> + sexpr "%s = (int)%s" (reg r) (reg v) + | ONew r -> + (match rtype r with + | HObj o -> sexpr "%s = (%s)hl_alloc_obj(%s)" (reg r) (tname o.pname) (tname o.pname ^ "__val") + | HDynObj -> sexpr "%s = hl_alloc_dynobj()" (reg r) + | HVirtual _ as t -> sexpr "%s = hl_alloc_virtual(%s)" (reg r) (type_value t) + | _ -> assert false) + | OField (r,obj,fid) -> + get_field r obj fid + | OSetField (obj,fid,v) -> + set_field obj fid v + | OGetThis (r,fid) -> + get_field r 0 fid + | OSetThis (fid,r) -> + set_field 0 fid r + | OThrow r -> + sexpr "hl_throw((vdynamic*)%s)" (reg r) + | ORethrow r -> + sexpr "hl_rethrow((vdynamic*)%s)" (reg r) + | OGetUI8 (r,b,idx) -> + sexpr "%s = *(unsigned char*)(%s + %s)" (reg r) (reg b) (reg idx) + | OGetUI16 (r,b,idx) -> + sexpr "%s = *(unsigned short*)(%s + %s)" (reg r) (reg b) (reg idx) + | OGetI32 (r,b,idx) -> + sexpr "%s = *(int*)(%s + %s)" (reg r) (reg b) (reg idx) + | OGetF32 (r,b,idx) -> + sexpr "%s = *(float*)(%s + %s)" (reg r) (reg b) (reg idx) + | OGetF64 (r,b,idx) -> + sexpr "%s = *(double*)(%s + %s)" (reg r) (reg b) (reg idx) + | OGetArray (r, arr, idx) -> + sexpr "%s = ((%s*)(%s + 1))[%s]" (reg r) (ctype (rtype r)) (reg arr) (reg idx) + | OSetUI8 (b,idx,r) -> + sexpr "*(unsigned char*)(%s + %s) = (unsigned char)%s" (reg b) (reg idx) (reg r) + | OSetUI16 (b,idx,r) -> + sexpr "*(unsigned short*)(%s + %s) = (unsigned short)%s" (reg b) (reg idx) (reg r) + | OSetI32 (b,idx,r) -> + sexpr "*(int*)(%s + %s) = %s" (reg b) (reg idx) (reg r) + | OSetF32 (b,idx,r) -> + sexpr "*(float*)(%s + %s) = (float)%s" (reg b) (reg idx) (reg r) + | OSetF64 (b,idx,r) -> + sexpr "*(double*)(%s + %s) = %s" (reg b) (reg idx) (reg r) + | OSetArray (arr,idx,v) -> + sexpr "((%s*)(%s + 1))[%s] = %s" (ctype (rtype v)) (reg arr) (reg idx) (reg v) + | OSafeCast (r,v) -> + let tsrc = rtype v in + let t = rtype r in + if tsrc = HNull t then + sexpr "%s = %s ? %s%s : 0" (reg r) (reg v) (reg v) (dyn_value_field t) + else + sexpr "%s = (%s)hl_dyn_cast%s(&%s,%s%s)" (reg r) (ctype t) (dyn_prefix t) (reg v) (type_value (rtype v)) (type_value_opt t) + | OUnsafeCast (r,v) -> + sexpr "%s = (%s)%s" (reg r) (ctype (rtype r)) (reg v) + | OArraySize (r,a) -> + sexpr "%s = %s->size" (reg r) (reg a) + | OType (r,t) -> + sexpr "%s = %s" (reg r) (type_value t) + | OGetType (r,v) -> + sexpr "%s = %s ? ((vdynamic*)%s)->t : &hlt_void" (reg r) (reg v) (reg v) + | OGetTID (r,v) -> + sexpr "%s = %s->kind" (reg r) (reg v) + | ORef (r,v) -> + sexpr "%s = &%s" (reg r) (reg v) + | OUnref (r,v) -> + sexpr "%s = *%s" (reg r) (reg v) + | OSetref (r,v) -> + sexpr "*%s = %s" (reg r) (reg v) + | OToVirtual (r,v) -> + sexpr "%s = hl_to_virtual(%s,(vdynamic*)%s)" (reg r) (type_value (rtype r)) (reg v) + | ODynGet (r,o,sid) -> + let t = rtype r in + let h = hash ctx sid in + sexpr "%s = (%s)hl_dyn_get%s((vdynamic*)%s,%ld/*%s*/%s)" (reg r) (ctype t) (dyn_prefix t) (reg o) h code.strings.(sid) (type_value_opt t) + | ODynSet (o,sid,v) -> + let h = hash ctx sid in + sexpr "hl_dyn_set%s((vdynamic*)%s,%ld/*%s*/%s,%s)" (dyn_prefix (rtype v)) (reg o) h code.strings.(sid) (type_value_opt (rtype v)) (reg v) + | OMakeEnum (r,cid,rl) -> + let e, et = (match rtype r with HEnum e -> e, enum_constr_type ctx e cid | _ -> assert false) in + let has_ptr = List.exists (fun r -> is_gc_ptr (rtype r)) rl in + let need_tmp = List.mem r rl in + let tmp = if not need_tmp then reg r else begin + sexpr "{ venum *tmp"; + "tmp" + end in + sexpr "%s = (venum*)hl_gc_alloc%s(sizeof(%s))" tmp (if has_ptr then "" else "_noptr") et; + sexpr "%s->index = %d" tmp cid; + let _,_,tl = e.efields.(cid) in + list_iteri (fun i v -> + sexpr "((%s*)%s)->p%d = %s" et tmp i (rcast v tl.(i)) + ) rl; + if need_tmp then sexpr "%s = tmp; }" (reg r) + | OEnumAlloc (r,cid) -> + let et, (_,_,tl) = (match rtype r with HEnum e -> enum_constr_type ctx e cid, e.efields.(cid) | _ -> assert false) in + let has_ptr = List.exists is_gc_ptr (Array.to_list tl) in + sexpr "%s = (venum*)hl_gc_alloc%s(sizeof(%s))" (reg r) (if has_ptr then "" else "_noptr") et; + sexpr "memset(%s,0,sizeof(%s))" (reg r) et; + if cid <> 0 then sexpr "%s->index = %d" (reg r) cid + | OEnumIndex (r,v) -> + (match rtype v with + | HEnum _ -> + sexpr "%s = %s->index" (reg r) (reg v) + | HDyn -> + sexpr "%s = ((venum*)%s->v.ptr)->index" (reg r) (reg v) + | _ -> + assert false) + | OEnumField (r,e,cid,pid) -> + let tname,(_,_,tl) = (match rtype e with HEnum e -> enum_constr_type ctx e cid, e.efields.(cid) | _ -> assert false) in + sexpr "%s((%s*)%s)->p%d" (rassign r tl.(pid)) tname (reg e) pid + | OSetEnumField (e,pid,r) -> + let tname, (_,_,tl) = (match rtype e with HEnum e -> enum_constr_type ctx e 0, e.efields.(0) | _ -> assert false) in + sexpr "((%s*)%s)->p%d = (%s)%s" tname (reg e) pid (ctype tl.(pid)) (reg r) + | OSwitch (r,idx,eend) -> + sline "switch(%s) {" (reg r); + block(); + output_at2 (i + 1) [OODefault;OOIncreaseIndent]; + Array.iteri (fun k delta -> output_at2 (delta + i + 1) [OODecreaseIndent;OOCase k;OOIncreaseIndent]) idx; + let pend = i+1+eend in + (* insert at end if we have another switch case here *) + let old = output_options.(pend) in + output_options.(pend) <- []; + output_at2 pend ([OODecreaseIndent;OODecreaseIndent;OOEndBlock] @ List.rev old); + | ONullCheck r -> + sexpr "if( %s == NULL ) hl_null_access()" (reg r) + | OTrap (r,d) -> + sexpr "hl_trap(trap$%d,%s,%s)" !trap_depth (reg r) (label d); + incr trap_depth + | OEndTrap b -> + sexpr "hl_endtrap(trap$%d)" (!trap_depth - 1); + if b then decr trap_depth; + | ONop _ -> + () + ) f.code; + flush_options (Array.length f.code); + unblock(); + line "}"; + line "" + +let write_c com file (code:code) = + + let all_types, htypes = gather_types code in + + let ctx = { + version = com.Common.version; + out = Buffer.create 1024; + tabs = ""; + hlcode = code; + hash_cache = Hashtbl.create 0; + dir = (match Filename.dirname file with "" -> "." | dir -> String.concat "/" (ExtString.String.nsplit dir "\\")); + curfile = ""; + cfiles = []; + ftable = Array.init (Array.length code.functions + Array.length code.natives) (fun _ -> { fe_args = []; fe_ret = HVoid; fe_name = ""; fe_decl = None; }); + htypes = htypes; + } in + + let line = line ctx and expr = expr ctx in + let sline fmt = Printf.ksprintf line fmt and sexpr fmt = Printf.ksprintf expr fmt in + + open_file ctx "hl/code.h"; + line "#ifndef HL_CODE_H"; + line "#define HL_CODE_H"; + line ""; + line "#define HLC_BOOT"; + line "#include "; + line "#include \"typedefs.h\""; + line "#include \"types.h\""; + line "#include \"functions.h\""; + line "#include \"globals.h\""; + line "#include \"natives.h\""; + line ""; + line "#endif"; + + let used_closures = Hashtbl.create 0 in + let bytes_strings = Hashtbl.create 0 in + Array.iter (fun f -> + Array.iteri (fun i op -> + match op with + | OStaticClosure (_,fid) -> + Hashtbl.replace used_closures fid () + | OBytes (_,sid) -> + Hashtbl.replace bytes_strings sid () + | _ -> + () + ) f.code + ) code.functions; + + open_file ctx "hl/typedefs.h"; + line "// Types definitions"; + Array.iter (fun t -> + match t with + | HObj o -> + let name = tname o.pname in + expr ("typedef struct _" ^ name ^ " *" ^ name); + | HAbstract (name,_) -> + expr ("typedef struct _" ^ name ^ " " ^ name); + | _ -> + () + ) all_types; + + line ""; + line "// Types implementation"; + + Array.iter (fun t -> + match t with + | HObj o -> + let name = tname o.pname in + line ("struct _" ^ name ^ " {"); + block ctx; + let rec loop o = + (match o.psuper with + | None -> expr ("hl_type *$type"); + | Some c -> loop c); + Array.iteri (fun i (n,_,t) -> + let rec abs_index p v = + match p with + | None -> v + | Some o -> abs_index o.psuper (Array.length o.pfields + v) + in + expr (var_type (if n = "" then unamed_field (abs_index o.psuper i) else n) t) + ) o.pfields; + in + loop o; + unblock ctx; + expr "}"; + | HEnum e -> + Array.iteri (fun i (_,_,pl) -> + if Array.length pl <> 0 then begin + line ("typedef struct {"); + block ctx; + expr "int index"; + Array.iteri (fun i t -> + expr (var_type ("p" ^ string_of_int i) t) + ) pl; + unblock ctx; + sexpr "} %s" (enum_constr_type ctx e i); + end; + ) e.efields + | _ -> + () + ) all_types; + + open_file ctx "hl/types.h"; + line "// Types values declaration"; + Array.iteri (fun i t -> + sexpr "extern hl_type type$%d" i; + match t with + | HObj o -> + sline "#define %s__val &type$%d" (tname o.pname) i + | _ -> + () + ) all_types; + line ""; + sexpr "void hl_init_types( hl_module_context *ctx )"; + + open_file ctx "hl/natives.h"; + line "// Natives functions"; + let native_libs = Hashtbl.create 0 in + Array.iter (fun (lib,name,t,idx) -> + match t with + | HFun (args,t) -> + let fname = + let lib = code.strings.(lib) in + Hashtbl.replace native_libs lib (); + let lib = if lib = "std" then "hl" else lib in + lib ^ "_" ^ code.strings.(name) + in + sexpr "HL_API %s %s(%s)" (ctype t) fname (String.concat "," (List.map ctype args)); + let ft = ctx.ftable.(idx) in + ft.fe_name <- fname; + ft.fe_args <- args; + ft.fe_ret <- t; + | _ -> + assert false + ) code.natives; + + open_file ctx "hl/functions.h"; + line "// Functions declaration"; + Array.iter (fun f -> + match f.ftype with + | HFun (args,t) -> + let fname = String.concat "_" (ExtString.String.nsplit (fundecl_name f) ".") in + sexpr "%s %s(%s)" (ctype t) fname (String.concat "," (List.map ctype args)); + let ft = ctx.ftable.(f.findex) in + ft.fe_name <- fname; + ft.fe_args <- args; + ft.fe_ret <- t; + ft.fe_decl <- Some f; + | _ -> + assert false + ) code.functions; + line ""; + sexpr "extern void *hl_functions_ptrs[]"; + sexpr "extern hl_type *hl_functions_types[]"; + + + open_file ctx "hl/globals.h"; + line "// Globals"; + Array.iteri (fun i t -> + let name = "global$" ^ string_of_int i in + sexpr "extern %s" (var_type name t) + ) code.globals; + + Array.iteri (fun i str -> + if Hashtbl.mem bytes_strings i then + sexpr "extern vbyte bytes$%d[]" i + else if String.length str >= string_data_limit then + sexpr "vbyte string$%d[]" i + ) code.strings; + + Hashtbl.iter (fun fid _ -> sexpr "extern vclosure cl$%d" fid) used_closures; + line ""; + sexpr "void hl_init_roots()"; + + open_file ctx "hl/globals.c"; + line "#include "; + line "// Globals"; + Array.iteri (fun i t -> + let name = "global$" ^ string_of_int i in + sexpr "%s = 0" (var_type name t) + ) code.globals; + line ""; + line "void hl_init_roots() {"; + block ctx; + Array.iteri (fun i t -> + if is_ptr t then sexpr "hl_add_root((void**)&global$%d)" i; + ) code.globals; + unblock ctx; + line "}"; + + Array.iteri (fun i str -> + let rec loop s i = + if i = String.length s then [] else + let c = String.get s i in + string_of_int (int_of_char c) :: loop s (i+1) + in + if Hashtbl.mem bytes_strings i then + sexpr "vbyte bytes$%d[] = {%s}" i (String.concat "," (loop str 0)) + else if String.length str >= string_data_limit then + let s = utf8_to_utf16 str in + sline "// %s..." (String.escaped (String.sub str 0 (string_data_limit-4))); + sexpr "vbyte string$%d[] = {%s}" i (String.concat "," (loop s 0)) + ) code.strings; + + Hashtbl.iter (fun fid _ -> + let ft = ctx.ftable.(fid) in + sexpr "vclosure cl$%d = { %s, %s, 0 }" fid (type_value ctx (HFun (ft.fe_args,ft.fe_ret))) ft.fe_name + ) used_closures; + + open_file ctx "hl/types.c"; + line "#include "; + line "// Types values"; + Array.iteri (fun i t -> + sexpr "hl_type type$%d = { %s } /* %s */" i (type_id t) (tstr t); + ) all_types; + + line ""; + line "// Types values data"; + Array.iteri (fun i t -> + let field_value (_,name_id,t) = + sprintf "{(const uchar*)%s, %s, %ld}" (string ctx name_id) (type_value ctx t) (hash ctx name_id) + in + match t with + | HObj o -> + let proto_value p = + sprintf "{(const uchar*)%s, %d, %d, %ld}" (string ctx p.fid) p.fmethod (match p.fvirtual with None -> -1 | Some i -> i) (hash ctx p.fid) + in + let fields = + if Array.length o.pfields = 0 then "NULL" else + let name = sprintf "fields$%d" i in + sexpr "static hl_obj_field %s[] = {%s}" name (String.concat "," (List.map field_value (Array.to_list o.pfields))); + name + in + let proto = + if Array.length o.pproto = 0 then "NULL" else + let name = sprintf "proto$%d" i in + sexpr "static hl_obj_proto %s[] = {%s}" name (String.concat "," (List.map proto_value (Array.to_list o.pproto))); + name + in + let bindings = + if o.pbindings = [] then "NULL" else + let name = sprintf "bindings$%d" i in + sexpr "static int %s[] = {%s}" name (String.concat "," (List.map (fun (fid,fidx) -> string_of_int fid ^ "," ^ string_of_int fidx) o.pbindings)); + name + in + let ofields = [ + string_of_int (Array.length o.pfields); + string_of_int (Array.length o.pproto); + string_of_int (List.length o.pbindings); + sprintf "(const uchar*)%s" (string ctx o.pid); + (match o.psuper with None -> "NULL" | Some c -> sprintf "%s__val" (tname c.pname)); + fields; + proto; + bindings + ] in + sexpr "static hl_type_obj obj$%d = {%s}" i (String.concat "," ofields); + | HEnum e -> + let constr_name = sprintf "econstructs$%d" i in + let constr_value cid (name,nid,tl) = + let tval = if Array.length tl = 0 then "NULL" else + let name = sprintf "econstruct$%d_%d" i cid in + sexpr "static hl_type *%s[] = {%s}" name (String.concat "," (List.map (type_value ctx) (Array.to_list tl))); + name + in + let size = if Array.length tl = 0 then "0" else sprintf "sizeof(%s)" (enum_constr_type ctx e cid) in + let offsets = if Array.length tl = 0 then "NULL" else + let name = sprintf "eoffsets$%d_%d" i cid in + sexpr "static int %s[] = {%s}" name (String.concat "," (List.map (fun _ -> "0") (Array.to_list tl))); + name + in + let has_ptr = List.exists is_gc_ptr (Array.to_list tl) in + sprintf "{(const uchar*)%s, %d, %s, %s, %s, %s}" (string ctx nid) (Array.length tl) tval size (if has_ptr then "true" else "false") offsets + in + sexpr "static hl_enum_construct %s[] = {%s}" constr_name (String.concat "," (Array.to_list (Array.mapi constr_value e.efields))); + let efields = [ + if e.eid = 0 then "NULL" else sprintf "(const uchar*)%s" (string ctx e.eid); + string_of_int (Array.length e.efields); + constr_name + ] in + sexpr "static hl_type_enum enum$%d = {%s}" i (String.concat "," efields); + | HVirtual v -> + let fields_name = + if Array.length v.vfields = 0 then "NULL" else + let name = sprintf "vfields$%d" i in + sexpr "static hl_obj_field %s[] = {%s}" name (String.concat "," (List.map field_value (Array.to_list v.vfields))); + name + in + let vfields = [ + fields_name; + string_of_int (Array.length v.vfields) + ] in + sexpr "static hl_type_virtual virt$%d = {%s}" i (String.concat "," vfields); + | HFun (args,t) -> + let aname = if args = [] then "NULL" else + let name = sprintf "fargs$%d" i in + sexpr "static hl_type *%s[] = {%s}" name (String.concat "," (List.map (type_value ctx) args)); + name + in + sexpr "static hl_type_fun tfun$%d = {%s,%s,%d}" i aname (type_value ctx t) (List.length args) + | _ -> + () + ) all_types; + + line ""; + line "void hl_init_types( hl_module_context *ctx ) {"; + block ctx; + Array.iteri (fun i t -> + match t with + | HObj o -> + sexpr "obj$%d.m = ctx" i; + (match o.pclassglobal with None -> () | Some g -> sexpr "obj$%d.global_value = (void**)&global$%d" i g); + sexpr "type$%d.obj = &obj$%d" i i + | HNull t | HRef t -> + sexpr "type$%d.tparam = %s" i (type_value ctx t) + | HEnum e -> + sexpr "type$%d.tenum = &enum$%d" i i; + (match e.eglobal with None -> () | Some g -> sexpr "enum$%d.global_value = (void**)&global$%d" i g); + sexpr "hl_init_enum(&type$%d)" i; + | HVirtual _ -> + sexpr "type$%d.virt = &virt$%d" i i; + sexpr "hl_init_virtual(&type$%d,ctx)" i; + | HFun _ -> + sexpr "type$%d.fun = &tfun$%d" i i + | _ -> + () + ) all_types; + unblock ctx; + line "}"; + + open_file ctx "hl/reflect.c"; + line "#include "; + line "// Reflection helpers"; + generate_reflection ctx; + + let gen_functions = Hashtbl.create 0 in + let all_protos = Hashtbl.create 0 in + Array.iter (fun t -> + match t with + | HObj o -> + Hashtbl.add all_protos o.pname o + | _ -> () + ) all_types; + + Array.iter (fun t -> + match t with + | HObj o when Hashtbl.mem all_protos o.pname -> + let file = ref false in + let base_name, path = match List.rev (ExtString.String.nsplit o.pname ".") with + | [] -> assert false + | name :: acc -> (if name.[0] = '$' then String.sub name 1 (String.length name - 1) else name), List.rev acc + in + let generate fid = + match ctx.ftable.(fid).fe_decl with + | None -> () + | Some f -> + if not !file then begin + file := true; + let path = path @ [base_name] in + let path = List.map (fun n -> if String.length n > 128 then Digest.to_hex (Digest.string n) else n) path in + let path = (match path with [name] -> ["_std";name] | _ -> path) in + open_file ctx (String.concat "/" path ^ ".c"); + line "#include "; + line ""; + end; + Hashtbl.replace gen_functions f.findex (); + generate_function ctx f + in + let gen_proto name = + try + let full_name = String.concat "." (path @ [name]) in + let o = Hashtbl.find all_protos full_name in + Array.iter (fun p -> generate p.fmethod) o.pproto; + List.iter (fun (_,mid) -> generate mid) o.pbindings; + Hashtbl.remove all_protos full_name; + with Not_found -> + () + in + gen_proto base_name; + gen_proto ("$" ^ base_name); + | _ -> () + ) all_types; + + open_file ctx "hl/functions.c"; + line "#include "; + line ""; + sexpr "void *hl_functions_ptrs[] = {%s}" (String.concat "," (List.map (fun f -> f.fe_name) (Array.to_list ctx.ftable))); + let rec loop i = + if i = Array.length ctx.ftable then [] else + let ft = ctx.ftable.(i) in + (type_value ctx (HFun (ft.fe_args,ft.fe_ret))) :: loop (i + 1) + in + sexpr "hl_type *hl_functions_types[] = {%s}" (String.concat "," (loop 0)); + line ""; + Array.iter (fun f -> + if not (Hashtbl.mem gen_functions f.findex) then generate_function ctx f; + ) code.functions; + + open_file ctx "hl/hashes.c"; + line "#include "; + line ""; + line "void hl_init_hashes() {"; + block ctx; + Hashtbl.iter (fun i _ -> sexpr "hl_hash((vbyte*)%s)" (string ctx i)) ctx.hash_cache; + unblock ctx; + line "}"; + + open_file ctx (Filename.basename file); + line "#include "; + line "#include "; + line ""; + line "#ifndef HL_MAKE"; + List.iter (sline "# include <%s>") ctx.cfiles; + line "#endif"; + line ""; + expr "void hl_init_hashes()"; + line ""; + line "// Entry point"; + line "void hl_entry_point() {"; + block ctx; + expr "hl_module_context ctx"; + expr "hl_alloc_init(&ctx.alloc)"; + expr "ctx.functions_ptrs = hl_functions_ptrs"; + expr "ctx.functions_types = hl_functions_types"; + expr "hl_init_types(&ctx)"; + expr "hl_init_hashes()"; + expr "hl_init_roots()"; + sexpr "%s()" ctx.ftable.(code.entrypoint).fe_name; + unblock ctx; + line "}"; + line ""; + + open_file ctx "hlc.json"; + + line "{"; + block ctx; + sline "\"version\" : %d," ctx.version; + sline "\"libs\" : [%s]," (String.concat "," (Hashtbl.fold (fun k _ acc -> sprintf "\"%s\"" k :: acc) native_libs [])); + sline "\"defines\" : {%s\n\t}," (String.concat "," (PMap.foldi (fun k v acc -> sprintf "\n\t\t\"%s\" : \"%s\"" k v :: acc) com.Common.defines [])); + sline "\"files\" : [%s\n\t]" (String.concat "," (List.map (sprintf "\n\t\t\"%s\"") ctx.cfiles)); + unblock ctx; + line "}"; + + close_file ctx + diff --git a/src/generators/hlcode.ml b/src/generators/hlcode.ml new file mode 100644 index 00000000..00a689c2 --- /dev/null +++ b/src/generators/hlcode.ml @@ -0,0 +1,659 @@ +(* + * Copyright (C)2005-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. + *) + +type reg = int +type global = int +type 'a index = int +type functable + +type ttype = + | HVoid + | HUI8 + | HUI16 + | HI32 + | HF32 + | HF64 + | HBool + | HBytes + | HDyn + | HFun of ttype list * ttype + | HObj of class_proto + | HArray + | HType + | HRef of ttype + | HVirtual of virtual_proto + | HDynObj + | HAbstract of string * string index + | HEnum of enum_proto + | HNull of ttype + +and class_proto = { + pname : string; + pid : int; + mutable pclassglobal : int option; + mutable psuper : class_proto option; + mutable pvirtuals : int array; + mutable pproto : field_proto array; + mutable pnfields : int; + mutable pfields : (string * string index * ttype) array; + mutable pindex : (string, int * ttype) PMap.t; + mutable pfunctions : (string, int) PMap.t; + mutable pinterfaces : (ttype, int) PMap.t; + mutable pbindings : (int * int) list; +} + +and enum_proto = { + ename : string; + eid : int; + mutable eglobal : int option; + mutable efields : (string * string index * ttype array) array; +} + +and field_proto = { + fname : string; + fid : int; + fmethod : functable index; + fvirtual : int option; +} + +and virtual_proto = { + mutable vfields : (string * string index * ttype) array; + mutable vindex : (string, int) PMap.t; +} + +type unused = int +type field + +type opcode = + (* register storing *) + | OMov of reg * reg + | OInt of reg * int index + | OFloat of reg * float index + | OBool of reg * bool + | OBytes of reg * string index + | OString of reg * string index + | ONull of reg + (* binops *) + | OAdd of reg * reg * reg + | OSub of reg * reg * reg + | OMul of reg * reg * reg + | OSDiv of reg * reg * reg + | OUDiv of reg * reg * reg + | OSMod of reg * reg * reg + | OUMod of reg * reg * reg + | OShl of reg * reg * reg + | OSShr of reg * reg * reg + | OUShr of reg * reg * reg + | OAnd of reg * reg * reg + | OOr of reg * reg * reg + | OXor of reg * reg * reg + (* unops *) + | ONeg of reg * reg + | ONot of reg * reg + | OIncr of reg + | ODecr of reg + (* calls *) + | OCall0 of reg * functable index + | OCall1 of reg * functable index * reg + | OCall2 of reg * functable index * reg * reg + | OCall3 of reg * functable index * reg * reg * reg + | OCall4 of reg * functable index * reg * reg * reg * reg + | OCallN of reg * functable index * reg list + | OCallMethod of reg * field index * reg list + | OCallThis of reg * field index * reg list + | OCallClosure of reg * reg * reg list + (* closures *) + | OStaticClosure of reg * functable index (* Class.method *) + | OInstanceClosure of reg * functable index * reg (* instance.method *) + | OVirtualClosure of reg * reg * field index (* instance.overriddenMethod *) + (* field access *) + | OGetGlobal of reg * global + | OSetGlobal of global * reg + | OField of reg * reg * field index + | OSetField of reg * field index * reg + | OGetThis of reg * field index + | OSetThis of field index * reg + | ODynGet of reg * reg * string index + | ODynSet of reg * string index * reg + (* jumps *) + | OJTrue of reg * int + | OJFalse of reg * int + | OJNull of reg * int + | OJNotNull of reg * int + | OJSLt of reg * reg * int + | OJSGte of reg * reg * int + | OJSGt of reg * reg * int + | OJSLte of reg * reg * int + | OJULt of reg * reg * int + | OJUGte of reg * reg * int + | OJEq of reg * reg * int + | OJNotEq of reg * reg * int + | OJAlways of int + (* coerce *) + | OToDyn of reg * reg + | OToSFloat of reg * reg + | OToUFloat of reg * reg + | OToInt of reg * reg + | OSafeCast of reg * reg + | OUnsafeCast of reg * reg + | OToVirtual of reg * reg + (* control flow *) + | OLabel of unused + | ORet of reg + | OThrow of reg + | ORethrow of reg + | OSwitch of reg * int array * int + | ONullCheck of reg + | OTrap of reg * int + | OEndTrap of bool + (* memory access *) + | OGetUI8 of reg * reg * reg + | OGetUI16 of reg * reg * reg + | OGetI32 of reg * reg * reg + | OGetF32 of reg * reg * reg + | OGetF64 of reg * reg * reg + | OGetArray of reg * reg * reg + | OSetUI8 of reg * reg * reg + | OSetUI16 of reg * reg * reg + | OSetI32 of reg * reg * reg + | OSetF32 of reg * reg * reg + | OSetF64 of reg * reg * reg + | OSetArray of reg * reg * reg + (* type operations *) + | ONew of reg + | OArraySize of reg * reg + | OType of reg * ttype + | OGetType of reg * reg + | OGetTID of reg * reg + (* references *) + | ORef of reg * reg + | OUnref of reg * reg + | OSetref of reg * reg + (* enums *) + | OMakeEnum of reg * field index * reg list + | OEnumAlloc of reg * field index + | OEnumIndex of reg * reg + | OEnumField of reg * reg * field index * int + | OSetEnumField of reg * int * reg + (* misc *) + | ONop of string + +type fundecl = { + fpath : string * string; + findex : functable index; + ftype : ttype; + regs : ttype array; + code : opcode array; + debug : (int * int) array; +} + +type code = { + version : int; + entrypoint : global; + strings : string array; + ints : int32 array; + floats : float array; + (* types : ttype array // only in bytecode, rebuilt on save() *) + globals : ttype array; + natives : (string index * string index * ttype * functable index) array; + functions : fundecl array; + debugfiles : string array; +} + +let null_proto = + { + pname = ""; + pid = 0; + pclassglobal = None; + psuper = None; + pvirtuals = [||]; + pproto = [||]; + pfields = [||]; + pnfields = 0; + pindex = PMap.empty; + pfunctions = PMap.empty; + pinterfaces = PMap.empty; + pbindings = []; + } + +let list_iteri f l = + let p = ref (-1) in + List.iter (fun v -> incr p; f !p v) l + +let list_mapi f l = + let p = ref (-1) in + List.map (fun v -> incr p; f !p v) l + +(* + does the runtime value can be set to null +*) +let is_nullable t = + match t with + | HBytes | HDyn | HFun _ | HObj _ | HArray | HVirtual _ | HDynObj | HAbstract _ | HEnum _ | HNull _ | HRef _ -> true + | HUI8 | HUI16 | HI32 | HF32 | HF64 | HBool | HVoid | HType -> false + + +let is_int = function + | HUI8 | HUI16 | HI32 -> true + | _ -> false + +let is_float = function + | HF32 | HF64 -> true + | _ -> false + +let is_number = function + | HUI8 | HUI16 | HI32 | HF32 | HF64 -> true + | _ -> false + +(* + does the runtime value carry its type +*) +let is_dynamic t = + match t with + | HDyn | HFun _ | HObj _ | HArray | HVirtual _ | HDynObj | HNull _ -> true + | _ -> false + +let rec tsame t1 t2 = + if t1 == t2 then true else + match t1, t2 with + | HFun (args1,ret1), HFun (args2,ret2) when List.length args1 = List.length args2 -> List.for_all2 tsame args1 args2 && tsame ret2 ret1 + | HObj p1, HObj p2 -> p1 == p2 + | HEnum e1, HEnum e2 -> e1 == e2 + | HAbstract (_,a1), HAbstract (_,a2) -> a1 == a2 + | HVirtual v1, HVirtual v2 -> + if v1 == v2 then true else + if Array.length v1.vfields <> Array.length v2.vfields then false else + let rec loop i = + if i = Array.length v1.vfields then true else + let _, i1, t1 = v1.vfields.(i) in + let _, i2, t2 = v2.vfields.(i) in + if i1 = i2 && tsame t1 t2 then loop (i + 1) else false + in + loop 0 + | HNull t1, HNull t2 -> tsame t1 t2 + | HRef t1, HRef t2 -> tsame t1 t2 + | _ -> false + +(* + can we use a value of t1 as t2 +*) +let rec safe_cast t1 t2 = + if t1 == t2 then true else + match t1, t2 with + | _, HDyn -> is_dynamic t1 + | HVirtual v1, HVirtual v2 when Array.length v2.vfields < Array.length v1.vfields -> + let rec loop i = + if i = Array.length v2.vfields then true else + let n1, _, t1 = v1.vfields.(i) in + let n2, _, t2 = v2.vfields.(i) in + if n1 = n2 && tsame t1 t2 then loop (i + 1) else false + in + loop 0 + | HObj p1, HObj p2 -> + (* allow subtyping *) + let rec loop p = + p.pname = p2.pname || (match p.psuper with None -> false | Some p -> loop p) + in + loop p1 + | HFun (args1,t1), HFun (args2,t2) when List.length args1 = List.length args2 -> + List.for_all2 (fun t1 t2 -> safe_cast t2 t1 || (t1 = HDyn && is_dynamic t2)) args1 args2 && safe_cast t1 t2 + | _ -> + tsame t1 t2 + +let hl_hash b = + let h = ref Int32.zero in + let rec loop i = + let c = if i = String.length b then 0 else int_of_char b.[i] in + if c <> 0 then begin + h := Int32.add (Int32.mul !h 223l) (Int32.of_int c); + loop (i + 1) + end else + Int32.rem !h 0x1FFFFF7Bl + in + loop 0 + +let utf16_add buf c = + let add c = + Buffer.add_char buf (char_of_int (c land 0xFF)); + Buffer.add_char buf (char_of_int (c lsr 8)); + in + if c >= 0 && c < 0x10000 then begin + if c >= 0xD800 && c <= 0xDFFF then failwith ("Invalid unicode char " ^ string_of_int c); + add c; + end else if c < 0x110000 then begin + let c = c - 0x10000 in + add ((c asr 10) + 0xD800); + add ((c land 1023) + 0xDC00); + end else + failwith ("Invalid unicode char " ^ string_of_int c) + +let utf8_to_utf16 str = + let b = Buffer.create (String.length str * 2) in + (try UTF8.iter (fun c -> utf16_add b (UChar.code c)) str with Invalid_argument _ | UChar.Out_of_range -> ()); (* if malformed *) + utf16_add b 0; + Buffer.contents b + +let rec get_index name p = + try + PMap.find name p.pindex + with Not_found -> + match p.psuper with + | None -> raise Not_found + | Some p -> get_index name p + +let resolve_field p fid = + let rec loop pl p = + let pl = p :: pl in + match p.psuper with + | None -> + let rec fetch id = function + | [] -> raise Not_found + | p :: pl -> + let d = id - Array.length p.pfields in + if d < 0 then + let name, _, t = p.pfields.(id) in + name, t + else + fetch d pl + in + fetch fid pl + | Some p -> + loop pl p + in + loop [] p + +let gather_types (code:code) = + let types = ref PMap.empty in + let arr = DynArray.create() in + let rec get_type t = + (match t with HObj { psuper = Some p } -> get_type (HObj p) | _ -> ()); + if PMap.mem t !types then () else + let index = DynArray.length arr in + DynArray.add arr t; + types := PMap.add t index !types; + match t with + | HFun (args, ret) -> + List.iter get_type args; + get_type ret + | HObj p -> + Array.iter (fun (_,n,t) -> get_type t) p.pfields + | HNull t | HRef t -> + get_type t + | HVirtual v -> + Array.iter (fun (_,_,t) -> get_type t) v.vfields + | HEnum e -> + Array.iter (fun (_,_,tl) -> Array.iter get_type tl) e.efields + | _ -> + () + in + List.iter (fun t -> get_type t) [HVoid; HUI8; HUI16; HI32; HF32; HF64; HBool; HType; HDyn]; (* make sure all basic types get lower indexes *) + Array.iter (fun g -> get_type g) code.globals; + Array.iter (fun (_,_,t,_) -> get_type t) code.natives; + Array.iter (fun f -> + get_type f.ftype; + Array.iter (fun r -> get_type r) f.regs; + Array.iter (function + | OType (_,t) -> get_type t + | _ -> () + ) f.code; + ) code.functions; + DynArray.to_array arr, !types + +let lookup_type types t = + try PMap.find t types with Not_found -> assert false + +(* --------------------------------------------------------------------------------------------------------------------- *) +(* DUMP *) + +let rec tstr ?(stack=[]) ?(detailed=false) t = + match t with + | HVoid -> "void" + | HUI8 -> "ui8" + | HUI16 -> "ui16" + | HI32 -> "i32" + | HF32 -> "f32" + | HF64 -> "f64" + | HBool -> "bool" + | HBytes -> "bytes" + | HDyn -> "dyn" + | HFun (args,ret) -> "(" ^ String.concat "," (List.map (tstr ~stack ~detailed) args) ^ "):" ^ tstr ~stack ~detailed ret + | HObj o when not detailed -> "#" ^ o.pname + | HObj o -> + let fields = "{" ^ String.concat "," (List.map (fun(s,_,t) -> s ^ " : " ^ tstr ~detailed:false t) (Array.to_list o.pfields)) ^ "}" in + let proto = "{" ^ String.concat "," (List.map (fun p -> (match p.fvirtual with None -> "" | Some _ -> "virtual ") ^ p.fname ^ "@" ^ string_of_int p.fmethod) (Array.to_list o.pproto)) ^ "}" in + "#" ^ o.pname ^ "[" ^ (match o.psuper with None -> "" | Some p -> ">" ^ p.pname ^ " ") ^ "fields=" ^ fields ^ " proto=" ^ proto ^ "]" + | HArray -> + "array" + | HType -> + "type" + | HRef t -> + "ref(" ^ tstr t ^ ")" + | HVirtual v when List.memq v stack -> + "..." + | HVirtual v -> + "virtual(" ^ String.concat "," (List.map (fun (f,_,t) -> f ^":"^tstr ~stack:(v::stack) t) (Array.to_list v.vfields)) ^ ")" + | HDynObj -> + "dynobj" + | HAbstract (s,_) -> + "abstract(" ^ s ^ ")" + | HEnum e when e.eid = 0 -> + let _,_,fl = e.efields.(0) in + "enum(" ^ String.concat "," (List.map tstr (Array.to_list fl)) ^ ")" + | HEnum e -> + "enum(" ^ e.ename ^ ")" + | HNull t -> "null(" ^ tstr t ^ ")" + +let ostr fstr o = + match o with + | OMov (a,b) -> Printf.sprintf "mov %d,%d" a b + | OInt (r,i) -> Printf.sprintf "int %d,@%d" r i + | OFloat (r,i) -> Printf.sprintf "float %d,@%d" r i + | OString (r,s) -> Printf.sprintf "string %d,@%d" r s + | OBytes (r,s) -> Printf.sprintf "bytes %d,@%d" r s + | OBool (r,b) -> if b then Printf.sprintf "true %d" r else Printf.sprintf "false %d" r + | ONull r -> Printf.sprintf "null %d" r + | OAdd (r,a,b) -> Printf.sprintf "add %d,%d,%d" r a b + | OSub (r,a,b) -> Printf.sprintf "sub %d,%d,%d" r a b + | OMul (r,a,b) -> Printf.sprintf "mul %d,%d,%d" r a b + | OSDiv (r,a,b) -> Printf.sprintf "sdiv %d,%d,%d" r a b + | OUDiv (r,a,b) -> Printf.sprintf "udiv %d,%d,%d" r a b + | OSMod (r,a,b) -> Printf.sprintf "smod %d,%d,%d" r a b + | OUMod (r,a,b) -> Printf.sprintf "umod %d,%d,%d" r a b + | OShl (r,a,b) -> Printf.sprintf "shl %d,%d,%d" r a b + | OSShr (r,a,b) -> Printf.sprintf "sshr %d,%d,%d" r a b + | OUShr (r,a,b) -> Printf.sprintf "ushr %d,%d,%d" r a b + | OAnd (r,a,b) -> Printf.sprintf "and %d,%d,%d" r a b + | OOr (r,a,b) -> Printf.sprintf "or %d,%d,%d" r a b + | OXor (r,a,b) -> Printf.sprintf "xor %d,%d,%d" r a b + | ONeg (r,v) -> Printf.sprintf "neg %d,%d" r v + | ONot (r,v) -> Printf.sprintf "not %d,%d" r v + | OIncr r -> Printf.sprintf "incr %d" r + | ODecr r -> Printf.sprintf "decr %d" r + | OCall0 (r,g) -> Printf.sprintf "call %d, %s()" r (fstr g) + | OCall1 (r,g,a) -> Printf.sprintf "call %d, %s(%d)" r (fstr g) a + | OCall2 (r,g,a,b) -> Printf.sprintf "call %d, %s(%d,%d)" r (fstr g) a b + | OCall3 (r,g,a,b,c) -> Printf.sprintf "call %d, %s(%d,%d,%d)" r (fstr g) a b c + | OCall4 (r,g,a,b,c,d) -> Printf.sprintf "call %d, %s(%d,%d,%d,%d)" r (fstr g) a b c d + | OCallN (r,g,rl) -> Printf.sprintf "call %d, %s(%s)" r (fstr g) (String.concat "," (List.map string_of_int rl)) + | OCallMethod (r,f,[]) -> "callmethod ???" + | OCallMethod (r,f,o :: rl) -> Printf.sprintf "callmethod %d, %d[%d](%s)" r o f (String.concat "," (List.map string_of_int rl)) + | OCallClosure (r,f,rl) -> Printf.sprintf "callclosure %d, %d(%s)" r f (String.concat "," (List.map string_of_int rl)) + | OCallThis (r,f,rl) -> Printf.sprintf "callthis %d, [%d](%s)" r f (String.concat "," (List.map string_of_int rl)) + | OStaticClosure (r,f) -> Printf.sprintf "staticclosure %d, %s" r (fstr f) + | OInstanceClosure (r,f,v) -> Printf.sprintf "instanceclosure %d, %s(%d)" r (fstr f) v + | OGetGlobal (r,g) -> Printf.sprintf "global %d, %d" r g + | OSetGlobal (g,r) -> Printf.sprintf "setglobal %d, %d" g r + | ORet r -> Printf.sprintf "ret %d" r + | OJTrue (r,d) -> Printf.sprintf "jtrue %d,%d" r d + | OJFalse (r,d) -> Printf.sprintf "jfalse %d,%d" r d + | OJNull (r,d) -> Printf.sprintf "jnull %d,%d" r d + | OJNotNull (r,d) -> Printf.sprintf "jnotnull %d,%d" r d + | OJSLt (a,b,i) -> Printf.sprintf "jslt %d,%d,%d" a b i + | OJSGte (a,b,i) -> Printf.sprintf "jsgte %d,%d,%d" a b i + | OJSGt (r,a,b) -> Printf.sprintf "jsgt %d,%d,%d" r a b + | OJSLte (r,a,b) -> Printf.sprintf "jslte %d,%d,%d" r a b + | OJULt (a,b,i) -> Printf.sprintf "jult %d,%d,%d" a b i + | OJUGte (a,b,i) -> Printf.sprintf "jugte %d,%d,%d" a b i + | OJEq (a,b,i) -> Printf.sprintf "jeq %d,%d,%d" a b i + | OJNotEq (a,b,i) -> Printf.sprintf "jnoteq %d,%d,%d" a b i + | OJAlways d -> Printf.sprintf "jalways %d" d + | OToDyn (r,a) -> Printf.sprintf "todyn %d,%d" r a + | OToSFloat (r,a) -> Printf.sprintf "tosfloat %d,%d" r a + | OToUFloat (r,a) -> Printf.sprintf "toufloat %d,%d" r a + | OToInt (r,a) -> Printf.sprintf "toint %d,%d" r a + | OLabel _ -> "label" + | ONew r -> Printf.sprintf "new %d" r + | OField (r,o,i) -> Printf.sprintf "field %d,%d[%d]" r o i + | OVirtualClosure (r,o,m) -> Printf.sprintf "virtualclosure %d,%d[%d]" r o m + | OSetField (o,i,r) -> Printf.sprintf "setfield %d[%d],%d" o i r + | OGetThis (r,i) -> Printf.sprintf "getthis %d,[%d]" r i + | OSetThis (i,r) -> Printf.sprintf "setthis [%d],%d" i r + | OThrow r -> Printf.sprintf "throw %d" r + | ORethrow r -> Printf.sprintf "rethrow %d" r + | OGetUI8 (r,b,p) -> Printf.sprintf "getui8 %d,%d[%d]" r b p + | OGetUI16 (r,b,p) -> Printf.sprintf "getui16 %d,%d[%d]" r b p + | OGetI32 (r,b,p) -> Printf.sprintf "geti32 %d,%d[%d]" r b p + | OGetF32 (r,b,p) -> Printf.sprintf "getf32 %d,%d[%d]" r b p + | OGetF64 (r,b,p) -> Printf.sprintf "getf64 %d,%d[%d]" r b p + | OGetArray (r,a,i) -> Printf.sprintf "getarray %d,%d[%d]" r a i + | OSetUI8 (r,p,v) -> Printf.sprintf "setui8 %d,%d,%d" r p v + | OSetUI16 (r,p,v) -> Printf.sprintf "setui16 %d,%d,%d" r p v + | OSetI32 (r,p,v) -> Printf.sprintf "seti32 %d,%d,%d" r p v + | OSetF32 (r,p,v) -> Printf.sprintf "setf32 %d,%d,%d" r p v + | OSetF64 (r,p,v) -> Printf.sprintf "setf64 %d,%d,%d" r p v + | OSetArray (a,i,v) -> Printf.sprintf "setarray %d[%d],%d" a i v + | OSafeCast (r,v) -> Printf.sprintf "safecast %d,%d" r v + | OUnsafeCast (r,v) -> Printf.sprintf "unsafecast %d,%d" r v + | OArraySize (r,a) -> Printf.sprintf "arraysize %d,%d" r a + | OType (r,t) -> Printf.sprintf "type %d,%s" r (tstr t) + | OGetType (r,v) -> Printf.sprintf "gettype %d,%d" r v + | OGetTID (r,v) -> Printf.sprintf "gettid %d,%d" r v + | ORef (r,v) -> Printf.sprintf "ref %d,&%d" r v + | OUnref (v,r) -> Printf.sprintf "unref %d,*%d" v r + | OSetref (r,v) -> Printf.sprintf "setref *%d,%d" r v + | OToVirtual (r,v) -> Printf.sprintf "tovirtual %d,%d" r v + | ODynGet (r,o,f) -> Printf.sprintf "dynget %d,%d[@%d]" r o f + | ODynSet (o,f,v) -> Printf.sprintf "dynset %d[@%d],%d" o f v + | OMakeEnum (r,e,pl) -> Printf.sprintf "makeenum %d, %d(%s)" r e (String.concat "," (List.map string_of_int pl)) + | OEnumAlloc (r,e) -> Printf.sprintf "enumalloc %d, %d" r e + | OEnumIndex (r,e) -> Printf.sprintf "enumindex %d, %d" r e + | OEnumField (r,e,i,n) -> Printf.sprintf "enumfield %d, %d[%d:%d]" r e i n + | OSetEnumField (e,i,r) -> Printf.sprintf "setenumfield %d[%d], %d" e i r + | OSwitch (r,idx,eend) -> Printf.sprintf "switch %d [%s] %d" r (String.concat "," (Array.to_list (Array.map string_of_int idx))) eend + | ONullCheck r -> Printf.sprintf "nullcheck %d" r + | OTrap (r,i) -> Printf.sprintf "trap %d, %d" r i + | OEndTrap b -> Printf.sprintf "endtrap %b" b + | ONop s -> if s = "" then "nop" else "nop " ^ s + +let fundecl_name f = if snd f.fpath = "" then "fun$" ^ (string_of_int f.findex) else (fst f.fpath) ^ "." ^ (snd f.fpath) + +let dump pr code = + let all_protos = Hashtbl.create 0 in + let funnames = Hashtbl.create 0 in + let tstr t = + (match t with + | HObj p -> Hashtbl.replace all_protos p.pname p + | _ -> ()); + tstr t + in + let str idx = + try + code.strings.(idx) + with _ -> + "INVALID:" ^ string_of_int idx + in + let fstr fid = + try + Hashtbl.find funnames fid + with _ -> + Printf.sprintf "f@%X" fid + in + let debug_infos (fid,line) = + (try code.debugfiles.(fid) with _ -> "???") ^ ":" ^ string_of_int line + in + pr ("hl v" ^ string_of_int code.version); + pr ("entry @" ^ string_of_int code.entrypoint); + pr (string_of_int (Array.length code.strings) ^ " strings"); + Array.iteri (fun i s -> + pr (" @" ^ string_of_int i ^ " : " ^ String.escaped s); + ) code.strings; + pr (string_of_int (Array.length code.ints) ^ " ints"); + Array.iteri (fun i v -> + pr (" @" ^ string_of_int i ^ " : " ^ Int32.to_string v); + ) code.ints; + pr (string_of_int (Array.length code.floats) ^ " floats"); + Array.iteri (fun i f -> + pr (" @" ^ string_of_int i ^ " : " ^ string_of_float f); + ) code.floats; + pr (string_of_int (Array.length code.globals) ^ " globals"); + Array.iteri (fun i g -> + pr (" @" ^ string_of_int i ^ " : " ^ tstr g); + ) code.globals; + pr (string_of_int (Array.length code.natives) ^ " natives"); + Array.iter (fun (lib,name,t,fidx) -> + pr (" @" ^ string_of_int fidx ^ " native " ^ str lib ^ "@" ^ str name ^ " " ^ tstr t); + Hashtbl.add funnames fidx (str lib ^ "@" ^ str name) + ) code.natives; + Array.iter (fun f -> Hashtbl.add funnames f.findex (fundecl_name f)) code.functions; + pr (string_of_int (Array.length code.functions) ^ " functions"); + Array.iter (fun f -> + pr (Printf.sprintf " fun@%d(%Xh) %s" f.findex f.findex (tstr f.ftype)); + let fid, _ = f.debug.(0) in + let cur_fid = ref fid in + pr (Printf.sprintf " ; %s (%s)" (debug_infos f.debug.(0)) (fundecl_name f)); + Array.iteri (fun i r -> + pr (" r" ^ string_of_int i ^ " " ^ tstr r); + ) f.regs; + Array.iteri (fun i o -> + let fid, line = f.debug.(i) in + if fid <> !cur_fid then begin + cur_fid := fid; + pr (Printf.sprintf " ; %s" (debug_infos (fid,line))); + end; + pr (Printf.sprintf " .%-5d @%X %s" line i (ostr fstr o)) + ) f.code; + ) code.functions; + let protos = Hashtbl.fold (fun _ p acc -> p :: acc) all_protos [] in + pr (string_of_int (List.length protos) ^ " objects protos"); + List.iter (fun p -> + pr (" " ^ p.pname ^ " " ^ (match p.pclassglobal with None -> "no global" | Some i -> "@" ^ string_of_int i)); + (match p.psuper with + | None -> () + | Some p -> pr (" extends " ^ p.pname)); + pr (" " ^ string_of_int (Array.length p.pfields) ^ " fields"); + let rec loop = function + | None -> 0 + | Some p -> Array.length p.pfields + loop p.psuper + in + let start_field = loop p.psuper in + Array.iteri (fun i (_,id,t) -> + pr (" @" ^ string_of_int (i + start_field) ^ " " ^ str id ^ " " ^ tstr t) + ) p.pfields; + pr (" " ^ string_of_int (Array.length p.pproto) ^ " methods"); + Array.iteri (fun i f -> + pr (" @" ^ string_of_int i ^ " " ^ str f.fid ^ " fun@" ^ string_of_int f.fmethod ^ (match f.fvirtual with None -> "" | Some p -> "[" ^ string_of_int p ^ "]")) + ) p.pproto; + pr (" " ^ string_of_int (List.length p.pbindings) ^ " bindings"); + List.iter (fun (i,fidx) -> + pr (" @" ^ string_of_int i ^ " fun@" ^ string_of_int fidx) + ) p.pbindings; + ) protos diff --git a/src/generators/hlinterp.ml b/src/generators/hlinterp.ml new file mode 100644 index 00000000..bbd65f1d --- /dev/null +++ b/src/generators/hlinterp.ml @@ -0,0 +1,2853 @@ +(* + * Copyright (C)2005-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. + *) +open Unix +open Hlcode + +type value = + | VNull + | VInt of int32 + | VFloat of float + | VBool of bool + | VDyn of value * ttype + | VObj of vobject + | VClosure of vfunction * value option + | VBytes of string + | VArray of value array * ttype + | VUndef + | VType of ttype + | VRef of ref_value * ttype + | VVirtual of vvirtual + | VDynObj of vdynobj + | VEnum of int * value array + | VAbstract of vabstract + | VVarArgs of vfunction * value option + +and ref_value = + | RStack of int + | RValue of value ref + +and vabstract = + | AHashBytes of (string, value) Hashtbl.t + | AHashInt of (int32, value) Hashtbl.t + | AHashObject of (value * value) list ref + | AReg of regexp + | ARandom + | APos of Globals.pos + | ATDecl of Type.module_type + | AUnsafe of Obj.t + | ALazyType of ((unit -> Type.t) ref) * (unit -> value) + +and vfunction = + | FFun of fundecl + | FNativeFun of string * (value list -> value) * ttype + +and vobject = { + oproto : vproto; + ofields : value array; +} + +and vproto = { + pclass : class_proto; + pmethods : vfunction array; +} + +and vvirtual = { + vtype : virtual_proto; + mutable vindexes : vfield array; + mutable vtable : value array; + mutable vvalue : value; +} + +and vdynobj = { + dfields : (string, int) Hashtbl.t; + mutable dtypes : ttype array; + mutable dvalues : value array; + mutable dvirtuals : vvirtual list; +} + +and vfield = + | VFNone + | VFIndex of int + +and regexp = { + r : Str.regexp; + mutable r_string : string; + mutable r_groups : (int * int) option array; +} + +exception Return of value +exception Runtime_error of string +exception InterpThrow of value +exception Sys_exit of int + +type context = { + mutable t_globals : value array; + mutable t_functions : vfunction array; + mutable call_stack : (fundecl * int ref) list; + mutable error_stack : (fundecl * int ref) list; + mutable stack : value array; + mutable stack_pos : int; + mutable fcall : vfunction -> value list -> value; + mutable code : code; + mutable on_error : value -> (fundecl * int ref) list -> unit; + mutable resolve_macro_api : string -> (value list -> value) option; + checked : bool; + cached_protos : (int, vproto * ttype array * (int * (value -> value)) list) Hashtbl.t; + cached_strings : (int, string) Hashtbl.t; + cached_hashes : (int32, string) Hashtbl.t; +} + +let default t = + match t with + | HUI8 | HUI16 | HI32 -> VInt Int32.zero + | HF32 | HF64 -> VFloat 0. + | HBool -> VBool false + | _ -> if is_nullable t then VNull else VUndef + +let get_type = function + | VDyn (_,t) -> Some t + | VObj o -> Some (HObj o.oproto.pclass) + | VDynObj _ -> Some HDynObj + | VVirtual v -> Some (HVirtual v.vtype) + | VArray _ -> Some HArray + | VClosure (f,None) -> Some (match f with FFun f -> f.ftype | FNativeFun (_,_,t) -> t) + | VClosure (f,Some _) -> Some (match f with FFun { ftype = HFun(_::args,ret) } | FNativeFun (_,_,HFun(_::args,ret)) -> HFun (args,ret) | _ -> assert false) + | VVarArgs _ -> Some (HFun ([],HDyn)) + | _ -> None + +let v_dynamic = function + | VNull | VDyn _ | VObj _ | VClosure _ | VArray _ | VVirtual _ | VDynObj _ | VVarArgs _ -> true + | _ -> false + +let rec is_compatible v t = + match v, t with + | VInt _, (HUI8 | HUI16 | HI32) -> true + | VFloat _, (HF32 | HF64) -> true + | VBool _, HBool -> true + | _, HVoid -> true + | VNull, t -> is_nullable t + | VObj o, HObj _ -> safe_cast (HObj o.oproto.pclass) t + | VClosure _, HFun _ -> safe_cast (match get_type v with None -> assert false | Some t -> t) t + | VBytes _, HBytes -> true + | VDyn (_,t1), HNull t2 -> tsame t1 t2 + | v, HNull t -> is_compatible v t + | v, HDyn -> v_dynamic v + | VType _, HType -> true + | VArray _, HArray -> true + | VDynObj _, HDynObj -> true + | VVirtual v, HVirtual _ -> safe_cast (HVirtual v.vtype) t + | VRef (_,t1), HRef t2 -> tsame t1 t2 + | VAbstract _, HAbstract _ -> true + | VEnum _, HEnum _ -> true + | _ -> false + +type cast = + | CNo + | CDyn of ttype + | CUnDyn of ttype + | CCast of ttype * ttype + +let error msg = raise (Runtime_error msg) + +let get_function ctx f = + ctx.t_functions.(f) + +let rec get_proto ctx p = + try + Hashtbl.find ctx.cached_protos p.pid + with Not_found -> + let fields, bindings = (match p.psuper with None -> [||],[] | Some p -> let _, fields, bindings = get_proto ctx p in fields, bindings) in + let meths = Array.map (get_function ctx) p.pvirtuals in + let fields = Array.append fields (Array.map (fun (_,_,t) -> t) p.pfields) in + let bindings = List.fold_left (fun acc (fid,fidx) -> + let f = get_function ctx fidx in + let ft = (match f with FFun f -> f.ftype | FNativeFun _ -> assert false) in + let need_closure = (match ft, fields.(fid) with HFun (args,_), HFun(args2,_) -> List.length args > List.length args2 | HFun _, HDyn -> false | _ -> assert false) in + let acc = List.filter (fun (fid2,_) -> fid2 <> fid) acc in + (fid, (fun v -> VClosure (f,if need_closure then Some v else None))) :: acc + ) bindings p.pbindings in + let proto = ({ pclass = p; pmethods = meths },fields,bindings) in + Hashtbl.replace ctx.cached_protos p.pid proto; + proto + +let alloc_obj ctx t = + match t with + | HDynObj -> + VDynObj { dfields = Hashtbl.create 0; dvalues = [||]; dtypes = [||]; dvirtuals = []; } + | HObj p -> + let p, fields, bindings = get_proto ctx p in + let ftable = Array.map default fields in + let obj = VObj { oproto = p; ofields = ftable } in + List.iter (fun (fid,mk) -> ftable.(fid) <- mk obj) bindings; + obj + | HVirtual v -> + let o = { + dfields = Hashtbl.create 0; + dvalues = Array.map (fun (_,_,t) -> default t) v.vfields; + dtypes = Array.map (fun (_,_,t) -> t) v.vfields; + dvirtuals = []; + } in + Array.iteri (fun i (n,_,_) -> Hashtbl.add o.dfields n i) v.vfields; + let v = { vtype = v; vvalue = VDynObj o; vtable = o.dvalues; vindexes = Array.mapi (fun i _ -> VFIndex i) v.vfields } in + o.dvirtuals <- [v]; + VVirtual v + | _ -> + assert false + +let float_to_string f = + let s = string_of_float f in + let len = String.length s in + if String.unsafe_get s (len - 1) = '.' then String.sub s 0 (len - 1) else s + +let rec get_method p name = + let m = ref None in + Array.iter (fun p -> if p.fname = name then m := Some p.fmethod) p.pproto; + match !m , p.psuper with + | Some i, _ -> Some i + | None, Some s -> get_method s name + | None, None -> None + +let get_to_string ctx p = + match get_method p "__string" with + | Some f -> + (match get_function ctx f with + | (FFun { ftype = HFun([_],HBytes) } as f) -> Some f + | _ -> None) + | None -> + None + +let set_i32 b p v = + try + String.set b p (char_of_int ((Int32.to_int v) land 0xFF)); + String.set b (p+1) (char_of_int ((Int32.to_int (Int32.shift_right_logical v 8)) land 0xFF)); + String.set b (p+2) (char_of_int ((Int32.to_int (Int32.shift_right_logical v 16)) land 0xFF)); + String.set b (p+3) (char_of_int (Int32.to_int (Int32.shift_right_logical v 24))); + with _ -> + error "Set outside of bytes bounds" + +let get_i32 b p = + let i = int_of_char (String.get b p) in + let j = int_of_char (String.get b (p + 1)) in + let k = int_of_char (String.get b (p + 2)) in + let l = int_of_char (String.get b (p + 3)) in + Int32.logor (Int32.of_int (i lor (j lsl 8) lor (k lsl 16))) (Int32.shift_left (Int32.of_int l) 24) + +let make_dyn v t = + if v = VNull || is_dynamic t then + v + else + VDyn (v,t) + +let get_ref ctx = function + | RStack i -> ctx.stack.(i) + | RValue r -> !r + +let set_ref ctx r v = + match r with + | RStack i -> ctx.stack.(i) <- v + | RValue r -> r := v + +let fstr = function + | FFun f -> "function@" ^ string_of_int f.findex + | FNativeFun (s,_,_) -> "native[" ^ s ^ "]" + +let caml_to_hl str = utf8_to_utf16 str + +let hash ctx str = + let h = hl_hash str in + if not (Hashtbl.mem ctx.cached_hashes h) then Hashtbl.add ctx.cached_hashes h (String.sub str 0 (try String.index str '\000' with _ -> String.length str)); + h + +let utf16_iter f s = + let get v = int_of_char s.[v] in + let rec loop p = + if p = String.length s then () else + let c = (get p) lor ((get (p+1)) lsl 8) in + if c >= 0xD800 && c <= 0xDFFF then begin + let c = c - 0xD800 in + let c2 = ((get (p+2)) lor ((get(p+3)) lsl 8)) - 0xDC00 in + f ((c2 lor (c lsl 10)) + 0x10000); + loop (p + 4); + end else begin + f c; + loop (p + 2); + end; + in + loop 0 + +let utf16_char buf c = + utf16_add buf (int_of_char c) + +let hl_to_caml str = + let utf16_eof s = + let get v = int_of_char s.[v] in + let rec loop p = + let c = (get p) lor ((get (p+1)) lsl 8) in + if c = 0 then String.sub s 0 p else loop (p + 2); + in + loop 0 + in + let b = UTF8.Buf.create (String.length str / 2) in + utf16_iter (fun c -> UTF8.Buf.add_char b (UChar.chr c)) (utf16_eof str); + UTF8.Buf.contents b + +let null_access() = + error "Null value bypass null pointer check" + +let throw ctx v = + ctx.error_stack <- []; + raise (InterpThrow v) + +let throw_msg ctx msg = + throw ctx (VDyn (VBytes (caml_to_hl msg),HBytes)) + +let rec vstr_d ctx v = + let vstr_d = vstr_d ctx in + match v with + | VNull -> "null" + | VInt i -> Int32.to_string i ^ "i" + | VFloat f -> string_of_float f ^ "f" + | VBool b -> if b then "true" else "false" + | VDyn (v,t) -> "dyn(" ^ vstr_d v ^ ":" ^ tstr t ^ ")" + | VObj o -> + let p = "#" ^ o.oproto.pclass.pname in + (match get_to_string ctx o.oproto.pclass with + | Some f -> p ^ ":" ^ vstr_d (ctx.fcall f [v]) + | None -> p) + | VBytes b -> "bytes(" ^ String.escaped b ^ ")" + | VClosure (f,o) -> + (match o with + | None -> fstr f + | Some v -> fstr f ^ "[" ^ vstr_d v ^ "]") + | VArray (a,t) -> "array<" ^ tstr t ^ ">(" ^ String.concat "," (Array.to_list (Array.map vstr_d a)) ^ ")" + | VUndef -> "undef" + | VType t -> "type(" ^ tstr t ^ ")" + | VRef (r,_) -> "ref(" ^ vstr_d (get_ref ctx r) ^ ")" + | VVirtual v -> "virtual(" ^ vstr_d v.vvalue ^ ")" + | VDynObj d -> "dynobj(" ^ String.concat "," (Hashtbl.fold (fun f i acc -> (f^":"^vstr_d d.dvalues.(i)) :: acc) d.dfields []) ^ ")" + | VEnum (i,vals) -> "enum#" ^ string_of_int i ^ "(" ^ String.concat "," (Array.to_list (Array.map vstr_d vals)) ^ ")" + | VAbstract _ -> "abstract" + | VVarArgs _ -> "varargs" + +let rec to_virtual ctx v vp = + match v with + | VNull -> + VNull + | VObj o -> + let indexes = Array.mapi (fun i (n,_,t) -> + try + let idx, ft = get_index n o.oproto.pclass in + if idx < 0 || not (tsame t ft) then raise Not_found; + VFIndex idx + with Not_found -> + VFNone (* most likely a method *) + ) vp.vfields in + let v = { + vtype = vp; + vindexes = indexes; + vtable = o.ofields; + vvalue = v; + } in + VVirtual v + | VDynObj d -> + (try + VVirtual (List.find (fun v -> v.vtype == vp) d.dvirtuals) + with Not_found -> + let indexes = Array.mapi (fun i (n,_,t) -> + try + let idx = Hashtbl.find d.dfields n in + if not (tsame t d.dtypes.(idx)) then raise Not_found; + VFIndex idx + with Not_found -> + VFNone + ) vp.vfields in + let v = { + vtype = vp; + vindexes = indexes; + vtable = d.dvalues; + vvalue = v; + } in + d.dvirtuals <- v :: d.dvirtuals; + VVirtual v + ) + | VVirtual vd -> + if vd.vtype == vp then + v + else if vd.vvalue = VNull then + assert false + else + to_virtual ctx vd.vvalue vp + | _ -> + throw_msg ctx ("Invalid ToVirtual " ^ vstr_d ctx v ^ " : " ^ tstr (HVirtual vp)) + +let rec dyn_cast ctx v t rt = + let invalid() = + throw_msg ctx ("Can't cast " ^ vstr_d ctx v ^ ":" ^ tstr t ^ " to " ^ tstr rt) + in + let default() = + let v = default rt in + if v = VUndef then invalid(); + v + in + if safe_cast t rt then + v + else if v = VNull then + default() + else match t, rt with + | (HUI8|HUI16|HI32), (HF32|HF64) -> + (match v with VInt i -> VFloat (Int32.to_float i) | _ -> assert false) + | (HF32|HF64), (HUI8|HUI16|HI32) -> + (match v with VFloat f -> VInt (Int32.of_float f) | _ -> assert false) + | (HUI8|HUI16|HI32|HF32|HF64), HNull ((HUI8|HUI16|HI32|HF32|HF64) as rt) -> + let v = dyn_cast ctx v t rt in + VDyn (v,rt) + | HBool, HNull HBool -> + VDyn (v,HBool) + | _, HDyn -> + make_dyn v t + | _, HRef t2 when t = t2 -> + VRef (RValue (ref v),t) + | HFun (args1,t1), HFun (args2,t2) when List.length args1 = List.length args2 -> + (match v with + | VClosure (fn,farg) -> + let get_conv t1 t2 = + if safe_cast t1 t2 || (t2 = HDyn && is_dynamic t1) then CNo + else if t2 = HDyn then CDyn t1 + else if t1 = HDyn then CUnDyn t2 + else CCast (t1,t2) + in + let conv = List.map2 get_conv args2 args1 in + let rconv = get_conv t1 t2 in + let convert v c = + match c with + | CNo -> v + | CDyn t -> make_dyn v t + | CUnDyn t -> dyn_cast ctx v HDyn t + | CCast (t1,t2) -> dyn_cast ctx v t1 t2 + in + VClosure (FNativeFun ("~convert",(fun args -> + let args = List.map2 convert args conv in + let ret = ctx.fcall fn (match farg with None -> args | Some a -> a :: args) in + convert ret rconv + ),rt),None) + | _ -> + assert false) + | HDyn, HFun (targs,tret) when (match v with VVarArgs _ -> true | _ -> false) -> + VClosure (FNativeFun ("~varargs",(fun args -> + dyn_call ctx v (List.map2 (fun v t -> (v,t)) args targs) tret + ),rt),None) + | HDyn, _ -> + (match get_type v with + | None -> assert false + | Some t -> dyn_cast ctx (match v with VDyn (v,_) -> v | _ -> v) t rt) + | HNull t, _ -> + (match v with + | VDyn (v,t) -> dyn_cast ctx v t rt + | _ -> assert false) + | HObj _, HObj b when safe_cast rt t && (match get_type v with Some t -> safe_cast t rt | None -> assert false) -> + (* downcast *) + v + | (HObj _ | HDynObj | HVirtual _), HVirtual vp -> + to_virtual ctx v vp + | HVirtual _, _ -> + (match v with + | VVirtual v -> dyn_cast ctx v.vvalue (match get_type v.vvalue with None -> assert false | Some t -> t) rt + | _ -> assert false) + | HObj p, _ -> + (match get_method p "__cast" with + | None -> invalid() + | Some f -> + if v = VNull then VNull else + let ret = ctx.fcall (get_function ctx f) [v;VType rt] in + if ret <> VNull && (match get_type ret with None -> assert false | Some vt -> safe_cast vt rt) then ret else invalid()) + | _ -> + invalid() + +and dyn_call ctx v args tret = + match v with + | VClosure (f,a) -> + let ft = (match f with FFun f -> f.ftype | FNativeFun (_,_,t) -> t) in + let fargs, fret = (match ft with HFun (a,t) -> a, t | _ -> assert false) in + let full_args = args and full_fargs = (match a with None -> fargs | Some _ -> List.tl fargs) in + let rec loop args fargs = + match args, fargs with + | [], [] -> [] + | _, [] -> throw_msg ctx (Printf.sprintf "Too many arguments (%s) != (%s)" (String.concat "," (List.map (fun (v,_) -> vstr_d ctx v) full_args)) (String.concat "," (List.map tstr full_fargs))) + | (v,t) :: args, ft :: fargs -> dyn_cast ctx v t ft :: loop args fargs + | [], _ :: fargs -> default ft :: loop args fargs + in + let vargs = loop args full_fargs in + let v = ctx.fcall f (match a with None -> vargs | Some a -> a :: vargs) in + dyn_cast ctx v fret tret + | VNull -> + null_access() + | VVarArgs (f,a) -> + let arr = VArray (Array.of_list (List.map (fun (v,t) -> make_dyn v t) args),HDyn) in + dyn_call ctx (VClosure (f,a)) [arr,HArray] tret + | _ -> + throw_msg ctx (vstr_d ctx v ^ " cannot be called") + +let invalid_comparison = 255 + +let rec dyn_compare ctx a at b bt = + if a == b && (match at with HF32 | HF64 -> false | _ -> true) then 0 else + let fcompare (a:float) (b:float) = if a = b then 0 else if a > b then 1 else if a < b then -1 else invalid_comparison in + match a, b with + | VInt a, VInt b -> Int32.compare a b + | VInt a, VFloat b -> fcompare (Int32.to_float a) b + | VFloat a, VInt b -> fcompare a (Int32.to_float b) + | VFloat a, VFloat b -> fcompare a b + | VBool a, VBool b -> compare a b + | VNull, VNull -> 0 + | VType t1, VType t2 -> if tsame t1 t2 then 0 else 1 + | VNull, _ -> 1 + | _, VNull -> -1 + | VObj oa, VObj ob -> + if oa == ob then 0 else + (match get_method oa.oproto.pclass "__compare" with + | None -> invalid_comparison + | Some f -> (match ctx.fcall (get_function ctx f) [a;b] with VInt i -> Int32.to_int i | _ -> assert false)); + | VDyn (v,t), _ -> + dyn_compare ctx v t b bt + | _, VDyn (v,t) -> + dyn_compare ctx a at v t + | VVirtual v, _ -> + dyn_compare ctx v.vvalue HDyn b bt + | _, VVirtual v -> + dyn_compare ctx a at v.vvalue HDyn + | _ -> + invalid_comparison + +let rec dyn_get_field ctx obj field rt = + let get_with v t = dyn_cast ctx v t rt in + match obj with + | VDynObj d -> + (try + let idx = Hashtbl.find d.dfields field in + get_with d.dvalues.(idx) d.dtypes.(idx) + with Not_found -> + default rt) + | VObj o -> + let default rt = + match get_method o.oproto.pclass "__get_field" with + | None -> default rt + | Some f -> + get_with (ctx.fcall (get_function ctx f) [obj; VInt (hash ctx field)]) HDyn + in + let rec loop p = + try + let fid = PMap.find field p.pfunctions in + (match get_function ctx fid with + | FFun fd as f -> get_with (VClosure (f,Some obj)) (match fd.ftype with HFun (_::args,t) -> HFun(args,t) | _ -> assert false) + | FNativeFun _ -> assert false) + with Not_found -> + match p.psuper with + | None -> default rt + | Some p -> loop p + in + (try + let idx, t = get_index field o.oproto.pclass in + if idx < 0 then raise Not_found; + get_with o.ofields.(idx) t + with Not_found -> + loop o.oproto.pclass) + | VVirtual vp -> + (match vp.vvalue with + | VNull -> + (try + let idx = PMap.find field vp.vtype.vindex in + match vp.vindexes.(idx) with + | VFNone -> VNull + | VFIndex i -> vp.vtable.(i) + with Not_found -> + VNull) + | v -> dyn_get_field ctx v field rt) + | VNull -> + null_access() + | _ -> + throw_msg ctx "Invalid object access" + +let rebuild_virtuals ctx d = + let old = d.dvirtuals in + d.dvirtuals <- []; + List.iter (fun v -> + let v2 = (match to_virtual ctx (VDynObj d) v.vtype with VVirtual v -> v | _ -> assert false) in + v.vindexes <- v2.vindexes; + v.vtable <- d.dvalues; + ) old; + d.dvirtuals <- old + +let rec dyn_set_field ctx obj field v vt = + let v, vt = (match vt with + | HDyn -> + (match get_type v with + | None -> if v = VNull then VNull, HDyn else assert false + | Some t -> (match v with VDyn (v,_) -> v | _ -> v), t) + | t -> v, t + ) in + match obj with + | VDynObj d -> + (try + let idx = Hashtbl.find d.dfields field in + d.dvalues.(idx) <- v; + if not (tsame d.dtypes.(idx) vt) then begin + d.dtypes.(idx) <- vt; + rebuild_virtuals ctx d; + end; + with Not_found -> + let idx = Array.length d.dvalues in + Hashtbl.add d.dfields field idx; + let vals2 = Array.make (idx + 1) VNull in + let types2 = Array.make (idx + 1) HVoid in + Array.blit d.dvalues 0 vals2 0 idx; + Array.blit d.dtypes 0 types2 0 idx; + vals2.(idx) <- v; + types2.(idx) <- vt; + d.dvalues <- vals2; + d.dtypes <- types2; + rebuild_virtuals ctx d; + ) + | VObj o -> + (try + let idx, t = get_index field o.oproto.pclass in + if idx < 0 then raise Not_found; + o.ofields.(idx) <- dyn_cast ctx v vt t + with Not_found -> + throw_msg ctx (o.oproto.pclass.pname ^ " has no field " ^ field)) + | VVirtual vp -> + dyn_set_field ctx vp.vvalue field v vt + | VNull -> + null_access() + | _ -> + throw_msg ctx "Invalid object access" + +let make_stack ctx (f,pos) = + let pos = !pos - 1 in + try let fid, line = f.debug.(pos) in ctx.code.debugfiles.(fid), line with _ -> "???", 0 + +let stack_frame ctx (f,pos) = + let file, line = make_stack ctx (f,pos) in + Printf.sprintf "%s:%d: Called from fun@%d @x%X" file line f.findex (!pos - 1) + +let virt_make_val v = + let hfields = Hashtbl.create 0 in + let ftypes = DynArray.create() in + let values = DynArray.create() in + Array.iteri (fun i idx -> + match idx with + | VFNone -> () + | VFIndex k -> + let n, _, t = v.vtype.vfields.(i) in + Hashtbl.add hfields n (DynArray.length values); + DynArray.add values v.vtable.(k); + DynArray.add ftypes t; + ) v.vindexes; + VDynObj { + dfields = hfields; + dtypes = DynArray.to_array ftypes; + dvalues = DynArray.to_array values; + dvirtuals = [v]; + } + +let rec vstr ctx v t = + let vstr = vstr ctx in + match v with + | VNull -> "null" + | VInt i -> Int32.to_string i + | VFloat f -> float_to_string f + | VBool b -> if b then "true" else "false" + | VDyn (v,t) -> + vstr v t + | VObj o -> + (match get_to_string ctx o.oproto.pclass with + | None -> "#" ^ o.oproto.pclass.pname + | Some f -> vstr (ctx.fcall f [v]) HBytes) + | VBytes b -> (try hl_to_caml b with _ -> "?" ^ String.escaped b) + | VClosure (f,_) -> fstr f + | VArray (a,t) -> "[" ^ String.concat ", " (Array.to_list (Array.map (fun v -> vstr v t) a)) ^ "]" + | VUndef -> "undef" + | VType t -> tstr t + | VRef (r,t) -> "*" ^ (vstr (get_ref ctx r) t) + | VVirtual v -> + (match v.vvalue with + | VNull -> + vstr (virt_make_val v) HDyn + | _ -> + vstr v.vvalue HDyn) + | VDynObj d -> + (try + let fid = Hashtbl.find d.dfields "__string" in + (match d.dtypes.(fid) with HFun ([],HBytes) -> () | _ -> raise Not_found); + vstr (dyn_call ctx d.dvalues.(fid) [] HBytes) HBytes + with Not_found -> + "{" ^ String.concat ", " (Hashtbl.fold (fun f i acc -> (f^":"^vstr d.dvalues.(i) d.dtypes.(i)) :: acc) d.dfields []) ^ "}") + | VAbstract _ -> "abstract" + | VEnum (i,vals) -> + (match t with + | HEnum e -> + let n, _, pl = e.efields.(i) in + if Array.length pl = 0 then + n + else + let rec loop i = + if i = Array.length pl then [] + else let v = vals.(i) in vstr v pl.(i) :: loop (i + 1) + in + n ^ "(" ^ String.concat "," (loop 0) ^ ")" + | _ -> + assert false) + | VVarArgs _ -> "varargs" + +let interp ctx f args = + let func = get_function ctx in + let spos = ctx.stack_pos in + if spos + Array.length f.regs > Array.length ctx.stack then begin + let nsize = spos + Array.length f.regs + 256 in + let nstack = Array.make nsize VUndef in + Array.blit ctx.stack 0 nstack 0 ctx.stack_pos; + ctx.stack <- nstack; + end; + if ctx.checked then for i = 0 to Array.length f.regs - 1 do ctx.stack.(i + spos) <- VUndef; done; + ctx.stack_pos <- spos + Array.length f.regs; + + let pos = ref 1 in + ctx.call_stack <- (f,pos) :: ctx.call_stack; + let fret = (match f.ftype with + | HFun (fargs,fret) -> + if ctx.checked && List.length fargs <> List.length args then error (Printf.sprintf "Invalid args: (%s) should be (%s)" (String.concat "," (List.map (vstr_d ctx) args)) (String.concat "," (List.map tstr fargs))); + fret + | _ -> assert false + ) in + let fcall = ctx.fcall in + let rtype i = Array.unsafe_get f.regs i in + let check v t id = + if ctx.checked && not (is_compatible v t) then error (Printf.sprintf "Can't set %s(%s) with %s" (id()) (tstr t) (vstr_d ctx v)) + in + let cached_string idx = + try + Hashtbl.find ctx.cached_strings idx + with Not_found -> + let s = caml_to_hl ctx.code.strings.(idx) in + Hashtbl.add ctx.cached_strings idx s; + s + in + let check_obj v o fid = + if ctx.checked then match o with + | VObj o -> + let _, fields, _ = get_proto ctx o.oproto.pclass in + check v fields.(fid) (fun() -> "obj field") + | VVirtual vp -> + let _,_, t = vp.vtype.vfields.(fid) in + check v t (fun() -> "virtual field") + | _ -> + () + in + let set r v = + check v (rtype r) (fun() -> "register " ^ string_of_int r); + Array.unsafe_set ctx.stack (r + spos) v + in + list_iteri set args; + let get r = Array.unsafe_get ctx.stack (r + spos) in + let global g = Array.unsafe_get ctx.t_globals g in + let traps = ref [] in + let numop iop fop a b = + match rtype a with + (* todo : sign-extend and mask after result for HUI8/16 *) + | HUI8 | HUI16 | HI32 -> + (match get a, get b with + | VInt a, VInt b -> VInt (iop a b) + | _ -> assert false) + | HF32 | HF64 -> + (match get a, get b with + | VFloat a, VFloat b -> VFloat (fop a b) + | _ -> assert false) + | _ -> + assert false + in + let iop f a b = + match rtype a with + (* todo : sign-extend and mask after result for HUI8/16 *) + | HUI8 | HUI16 | HI32 -> + (match get a, get b with + | VInt a, VInt b -> VInt (f a b) + | _ -> assert false) + | _ -> + assert false + in + let iunop iop r = + match rtype r with + | HUI8 | HUI16 | HI32 -> + (match get r with + | VInt a -> VInt (iop a) + | _ -> assert false) + | _ -> + assert false + in + let ucompare a b = + match a, b with + | VInt a, VInt b -> + let d = Int32.sub (Int32.shift_right_logical a 16) (Int32.shift_right_logical b 16) in + Int32.to_int (if d = 0l then Int32.sub (Int32.logand a 0xFFFFl) (Int32.logand b 0xFFFFl) else d) + | _ -> assert false + in + let vcompare ra rb op = + let a = get ra in + let b = get rb in + let t = rtype ra in + let r = dyn_compare ctx a t b t in + if r = invalid_comparison then false else op r 0 + in + let ufloat v = + if v < 0l then Int32.to_float v +. 4294967296. else Int32.to_float v + in + let rec loop() = + let op = Array.unsafe_get f.code (!pos) in + incr pos; + (match op with + | OMov (a,b) -> set a (get b) + | OInt (r,i) -> set r (VInt ctx.code.ints.(i)) + | OFloat (r,i) -> set r (VFloat (Array.unsafe_get ctx.code.floats i)) + | OString (r,s) -> set r (VBytes (cached_string s)) + | OBytes (r,s) -> set r (VBytes (ctx.code.strings.(s) ^ "\x00")) + | OBool (r,b) -> set r (VBool b) + | ONull r -> set r VNull + | OAdd (r,a,b) -> set r (numop Int32.add ( +. ) a b) + | OSub (r,a,b) -> set r (numop Int32.sub ( -. ) a b) + | OMul (r,a,b) -> set r (numop Int32.mul ( *. ) a b) + | OSDiv (r,a,b) -> set r (numop (fun a b -> if b = 0l then 0l else Int32.div a b) ( /. ) a b) + | OUDiv (r,a,b) -> set r (iop (fun a b -> if b = 0l then 0l else Int32.of_float ((ufloat a) /. (ufloat b))) a b) + | OSMod (r,a,b) -> set r (numop (fun a b -> if b = 0l then 0l else Int32.rem a b) mod_float a b) + | OUMod (r,a,b) -> set r (iop (fun a b -> if b = 0l then 0l else Int32.of_float (mod_float (ufloat a) (ufloat b))) a b) + | OShl (r,a,b) -> set r (iop (fun a b -> Int32.shift_left a (Int32.to_int b)) a b) + | OSShr (r,a,b) -> set r (iop (fun a b -> Int32.shift_right a (Int32.to_int b)) a b) + | OUShr (r,a,b) -> set r (iop (fun a b -> Int32.shift_right_logical a (Int32.to_int b)) a b) + | OAnd (r,a,b) -> set r (iop Int32.logand a b) + | OOr (r,a,b) -> set r (iop Int32.logor a b) + | OXor (r,a,b) -> set r (iop Int32.logxor a b) + | ONeg (r,v) -> set r (match get v with VInt v -> VInt (Int32.neg v) | VFloat f -> VFloat (-. f) | _ -> assert false) + | ONot (r,v) -> set r (match get v with VBool b -> VBool (not b) | _ -> assert false) + | OIncr r -> set r (iunop (fun i -> Int32.add i 1l) r) + | ODecr r -> set r (iunop (fun i -> Int32.sub i 1l) r) + | OCall0 (r,f) -> set r (fcall (func f) []) + | OCall1 (r,f,r1) -> set r (fcall (func f) [get r1]) + | OCall2 (r,f,r1,r2) -> set r (fcall (func f) [get r1;get r2]) + | OCall3 (r,f,r1,r2,r3) -> set r (fcall (func f) [get r1;get r2;get r3]) + | OCall4 (r,f,r1,r2,r3,r4) -> set r (fcall (func f) [get r1;get r2;get r3;get r4]) + | OCallN (r,f,rl) -> set r (fcall (func f) (List.map get rl)) + | OGetGlobal (r,g) -> set r (global g) + | OSetGlobal (g,r) -> + let v = get r in + check v ctx.code.globals.(g) (fun() -> "global " ^ string_of_int g); + Array.unsafe_set ctx.t_globals g v + | OJTrue (r,i) -> if get r = VBool true then pos := !pos + i + | OJFalse (r,i) -> if get r = VBool false then pos := !pos + i + | ORet r -> raise (Return (get r)) + | OJNull (r,i) -> if get r == VNull then pos := !pos + i + | OJNotNull (r,i) -> if get r != VNull then pos := !pos + i + | OJSLt (a,b,i) -> if vcompare a b (<) then pos := !pos + i + | OJSGte (a,b,i) -> if vcompare a b (>=) then pos := !pos + i + | OJSGt (a,b,i) -> if vcompare a b (>) then pos := !pos + i + | OJSLte (a,b,i) -> if vcompare a b (<=) then pos := !pos + i + | OJULt (a,b,i) -> if ucompare (get a) (get b) < 0 then pos := !pos + i + | OJUGte (a,b,i) -> if ucompare (get a) (get b) >= 0 then pos := !pos + i + | OJEq (a,b,i) -> if vcompare a b (=) then pos := !pos + i + | OJNotEq (a,b,i) -> if not (vcompare a b (=)) then pos := !pos + i + | OJAlways i -> pos := !pos + i + | OToDyn (r,a) -> set r (make_dyn (get a) f.regs.(a)) + | OToSFloat (r,a) -> set r (match get a with VInt v -> VFloat (Int32.to_float v) | VFloat _ as v -> v | _ -> assert false) + | OToUFloat (r,a) -> set r (match get a with VInt v -> VFloat (ufloat v) | VFloat _ as v -> v | _ -> assert false) + | OToInt (r,a) -> set r (match get a with VFloat v -> VInt (Int32.of_float v) | VInt _ as v -> v | _ -> assert false) + | OLabel _ -> () + | ONew r -> + set r (alloc_obj ctx (rtype r)) + | OField (r,o,fid) -> + set r (match get o with + | VObj v -> v.ofields.(fid) + | VVirtual v as obj -> + (match v.vindexes.(fid) with + | VFNone -> dyn_get_field ctx obj (let n,_,_ = v.vtype.vfields.(fid) in n) (rtype r) + | VFIndex i -> v.vtable.(i)) + | VNull -> null_access() + | _ -> assert false) + | OSetField (o,fid,r) -> + let rv = get r in + let o = get o in + (match o with + | VObj v -> + check_obj rv o fid; + v.ofields.(fid) <- rv + | VVirtual v -> + (match v.vindexes.(fid) with + | VFNone -> + dyn_set_field ctx o (let n,_,_ = v.vtype.vfields.(fid) in n) rv (rtype r) + | VFIndex i -> + check_obj rv o fid; + v.vtable.(i) <- rv) + | VNull -> null_access() + | _ -> assert false) + | OGetThis (r, fid) -> + set r (match get 0 with VObj v -> v.ofields.(fid) | _ -> assert false) + | OSetThis (fid, r) -> + (match get 0 with + | VObj v as o -> + let rv = get r in + check_obj rv o fid; + v.ofields.(fid) <- rv + | _ -> assert false) + | OCallMethod (r,m,rl) -> + (match get (List.hd rl) with + | VObj v -> set r (fcall v.oproto.pmethods.(m) (List.map get rl)) + | VVirtual v -> + let name, _, _ = v.vtype.vfields.(m) in + (match v.vvalue with + | VObj o as obj -> + (try + let m = PMap.find name o.oproto.pclass.pfunctions in + set r (dyn_call ctx (VClosure (get_function ctx m,Some obj)) (List.map (fun r -> get r, rtype r) (List.tl rl)) (rtype r)) + with Not_found -> + assert false) + | VDynObj _ -> + set r (dyn_call ctx v.vvalue (List.map (fun r -> get r, rtype r) (List.tl rl)) (rtype r)) + | _ -> + assert false) + | VNull -> null_access() + | _ -> assert false) + | OCallThis (r,m,rl) -> + (match get 0 with + | VObj v as o -> set r (fcall v.oproto.pmethods.(m) (o :: List.map get rl)) + | _ -> assert false) + | OCallClosure (r,v,rl) -> + if rtype v = HDyn then + set r (dyn_call ctx (get v) (List.map (fun r -> get r, rtype r) rl) (rtype r)) + else (match get v with + | VClosure (f,None) -> set r (fcall f (List.map get rl)) + | VClosure (f,Some arg) -> set r (fcall f (arg :: List.map get rl)) + | VNull -> null_access() + | _ -> throw_msg ctx (vstr_d ctx (get v))) + | OStaticClosure (r, fid) -> + let f = get_function ctx fid in + set r (VClosure (f,None)) + | OInstanceClosure (r, fid, v) -> + let f = get_function ctx fid in + set r (VClosure (f,Some (get v))) + | OVirtualClosure (r, o, m) -> + let m = (match get o with + | VObj v as obj -> VClosure (v.oproto.pmethods.(m), Some obj) + | VNull -> null_access() + | VVirtual v -> + let name, _, _ = v.vtype.vfields.(m) in + (match v.vvalue with + | VObj o as obj -> + (try + let m = PMap.find name o.oproto.pclass.pfunctions in + VClosure (get_function ctx m, Some obj) + with Not_found -> + VNull) + | _ -> assert false) + | _ -> assert false + ) in + set r (if m = VNull then m else dyn_cast ctx m (match get_type m with None -> assert false | Some v -> v) (rtype r)) + | OThrow r -> + throw ctx (get r) + | ORethrow r -> + ctx.call_stack <- List.rev ctx.error_stack @ ctx.call_stack; + throw ctx (get r) + | OGetUI8 (r,b,p) -> + (match get b, get p with + | VBytes b, VInt p -> set r (VInt (Int32.of_int (int_of_char (String.get b (Int32.to_int p))))) + | _ -> assert false) + | OGetUI16 (r,b,p) -> + (match get b, get p with + | VBytes b, VInt p -> + let a = int_of_char (String.get b (Int32.to_int p)) in + let b = int_of_char (String.get b (Int32.to_int p + 1)) in + set r (VInt (Int32.of_int (a lor (b lsl 8)))) + | _ -> assert false) + | OGetI32 (r,b,p) -> + (match get b, get p with + | VBytes b, VInt p -> set r (VInt (get_i32 b (Int32.to_int p))) + | _ -> assert false) + | OGetF32 (r,b,p) -> + (match get b, get p with + | VBytes b, VInt p -> set r (VFloat (Int32.float_of_bits (get_i32 b (Int32.to_int p)))) + | _ -> assert false) + | OGetF64 (r,b,p) -> + (match get b, get p with + | VBytes b, VInt p -> + let p = Int32.to_int p in + let i64 = Int64.logor (Int64.logand (Int64.of_int32 (get_i32 b p)) 0xFFFFFFFFL) (Int64.shift_left (Int64.of_int32 (get_i32 b (p + 4))) 32) in + set r (VFloat (Int64.float_of_bits i64)) + | _ -> assert false) + | OGetArray (r,a,i) -> + (match get a, get i with + | VArray (a,_), VInt i -> set r a.(Int32.to_int i) + | _ -> assert false); + | OSetUI8 (r,p,v) -> + (match get r, get p, get v with + | VBytes b, VInt p, VInt v -> String.set b (Int32.to_int p) (char_of_int ((Int32.to_int v) land 0xFF)) + | _ -> assert false) + | OSetUI16 (r,p,v) -> + (match get r, get p, get v with + | VBytes b, VInt p, VInt v -> + String.set b (Int32.to_int p) (char_of_int ((Int32.to_int v) land 0xFF)); + String.set b (Int32.to_int p + 1) (char_of_int (((Int32.to_int v) lsr 8) land 0xFF)) + | _ -> assert false) + | OSetI32 (r,p,v) -> + (match get r, get p, get v with + | VBytes b, VInt p, VInt v -> set_i32 b (Int32.to_int p) v + | _ -> assert false) + | OSetF32 (r,p,v) -> + (match get r, get p, get v with + | VBytes b, VInt p, VFloat v -> set_i32 b (Int32.to_int p) (Int32.bits_of_float v) + | _ -> assert false) + | OSetF64 (r,p,v) -> + (match get r, get p, get v with + | VBytes b, VInt p, VFloat v -> + let p = Int32.to_int p in + let v64 = Int64.bits_of_float v in + set_i32 b p (Int64.to_int32 v64); + set_i32 b (p + 4) (Int64.to_int32 (Int64.shift_right_logical v64 32)); + | _ -> assert false) + | OSetArray (a,i,v) -> + (match get a, get i with + | VArray (a,t), VInt i -> + let v = get v in + check v t (fun() -> "array"); + a.(Int32.to_int i) <- v + | _ -> assert false); + | OSafeCast (r, v) -> + set r (dyn_cast ctx (get v) (rtype v) (rtype r)) + | OUnsafeCast (r,v) -> + set r (get v) + | OArraySize (r,a) -> + (match get a with + | VArray (a,_) -> set r (VInt (Int32.of_int (Array.length a))); + | _ -> assert false) + | OType (r,t) -> + set r (VType t) + | OGetType (r,v) -> + let v = get v in + let v = (match v with VVirtual { vvalue = VNull } -> assert false | VVirtual v -> v.vvalue | _ -> v) in + set r (VType (if v = VNull then HVoid else match get_type v with None -> assert false | Some t -> t)); + | OGetTID (r,v) -> + set r (match get v with + | VType t -> + (VInt (Int32.of_int (match t with + | HVoid -> 0 + | HUI8 -> 1 + | HUI16 -> 2 + | HI32 -> 3 + | HF32 -> 4 + | HF64 -> 5 + | HBool -> 6 + | HBytes -> 7 + | HDyn -> 8 + | HFun _ -> 9 + | HObj _ -> 10 + | HArray -> 11 + | HType -> 12 + | HRef _ -> 13 + | HVirtual _ -> 14 + | HDynObj -> 15 + | HAbstract _ -> 16 + | HEnum _ -> 17 + | HNull _ -> 18))) + | _ -> assert false); + | ORef (r,v) -> + set r (VRef (RStack (v + spos),rtype v)) + | OUnref (v,r) -> + set v (match get r with + | VRef (r,_) -> get_ref ctx r + | _ -> assert false) + | OSetref (r,v) -> + (match get r with + | VRef (r,t) -> + let v = get v in + check v t (fun() -> "ref"); + set_ref ctx r v + | _ -> assert false) + | OToVirtual (r,rv) -> + set r (to_virtual ctx (get rv) (match rtype r with HVirtual vp -> vp | _ -> assert false)) + | ODynGet (r,o,f) -> + set r (dyn_get_field ctx (get o) ctx.code.strings.(f) (rtype r)) + | ODynSet (o,fid,vr) -> + dyn_set_field ctx (get o) ctx.code.strings.(fid) (get vr) (rtype vr) + | OMakeEnum (r,e,pl) -> + set r (VEnum (e,Array.map get (Array.of_list pl))) + | OEnumAlloc (r,f) -> + (match rtype r with + | HEnum e -> + let _, _, fl = e.efields.(f) in + let vl = Array.create (Array.length fl) VUndef in + set r (VEnum (f, vl)) + | _ -> assert false + ) + | OEnumIndex (r,v) -> + (match get v with + | VEnum (i,_) | VDyn (VEnum (i,_),_) -> set r (VInt (Int32.of_int i)) + | _ -> assert false) + | OEnumField (r, v, _, i) -> + (match get v with + | VEnum (_,vl) -> set r vl.(i) + | _ -> assert false) + | OSetEnumField (v, i, r) -> + (match get v, rtype v with + | VEnum (id,vl), HEnum e -> + let rv = get r in + let _, _, fields = e.efields.(id) in + check rv fields.(i) (fun() -> "enumfield"); + vl.(i) <- rv + | _ -> assert false) + | OSwitch (r, indexes, _) -> + (match get r with + | VInt i -> + let i = Int32.to_int i in + if i >= 0 && i < Array.length indexes then pos := !pos + indexes.(i) + | _ -> assert false) + | ONullCheck r -> + if get r = VNull then throw_msg ctx "Null access" + | OTrap (r,j) -> + let target = !pos + j in + traps := (r,target) :: !traps + | OEndTrap _ -> + traps := List.tl !traps + | ONop _ -> + () + ); + loop() + in + let rec exec() = + try + loop() + with + | Return v -> + check v fret (fun() -> "return value"); + ctx.call_stack <- List.tl ctx.call_stack; + ctx.stack_pos <- spos; + v + | InterpThrow v -> + match !traps with + | [] -> + ctx.error_stack <- List.hd ctx.call_stack :: ctx.error_stack; + ctx.call_stack <- List.tl ctx.call_stack; + raise (InterpThrow v) + | (r,target) :: tl -> + traps := tl; + ctx.error_stack <- (f,ref !pos) :: ctx.error_stack; + pos := target; + ctx.stack_pos <- spos + Array.length f.regs; + set r v; + exec() + in + pos := 0; + exec() + + +let call_fun ctx f args = + match f with + | FFun f -> interp ctx f args + | FNativeFun (_,f,_) -> + try + f args + with InterpThrow v -> + raise (InterpThrow v) + | Failure msg -> + throw_msg ctx msg + | e -> + throw_msg ctx (Printexc.to_string e) + +let call_wrap ?(final=(fun()->())) ctx f args = + let old_st = ctx.call_stack in + let old_pos = ctx.stack_pos in + let restore() = + ctx.call_stack <- old_st; + ctx.stack_pos <- old_pos; + in + try + let v = call_fun ctx f args in + final(); + v + with + | InterpThrow v -> + restore(); + final(); + ctx.on_error v (List.rev ctx.error_stack); + VNull + | Runtime_error msg -> + let stack = ctx.call_stack in + restore(); + final(); + ctx.on_error (VBytes (caml_to_hl ("HL Interp error " ^ msg))) stack; + VNull + +(* ------------------------------- HL RUNTIME ---------------------------------------------- *) + +let load_native ctx lib name t = + let unresolved() = (fun args -> error ("Unresolved native " ^ lib ^ "@" ^ name)) in + let int = Int32.to_int in + let to_int i = VInt (Int32.of_int i) in + let date d = + Unix.localtime (Int32.to_float d) + in + let to_date d = + let t, _ = Unix.mktime d in + VInt (Int32.of_float t) + in + let hl_to_caml_sub str pos len = + hl_to_caml (String.sub str pos len ^ "\x00\x00") + in + let no_virtual v = + match v with + | VVirtual v when v.vvalue <> VNull -> v.vvalue + | _ -> v + in + let set_ref = set_ref ctx in + let f = (match lib with + | "std" -> + (match name with + | "alloc_bytes" -> + (function + | [VInt i] -> VBytes (String.create (int i)) + | _ -> assert false) + | "alloc_array" -> + (function + | [VType t;VInt i] -> VArray (Array.create (int i) (default t),t) + | _ -> assert false) + | "alloc_obj" -> + (function + | [VType t] -> alloc_obj ctx t + | _ -> assert false) + | "alloc_enum" -> + (function + | [VType (HEnum e); VInt idx; VArray (vl,vt); VInt len] -> + let idx = int idx in + let len = int len in + let _, _, args = e.efields.(idx) in + if Array.length args <> len then + VNull + else + VDyn (VEnum (idx,Array.mapi (fun i v -> dyn_cast ctx v vt args.(i)) (Array.sub vl 0 len)),HEnum e) + | vl -> + assert false) + | "array_blit" -> + (function + | [VArray (dst,_); VInt dp; VArray (src,_); VInt sp; VInt len] -> + Array.blit src (int sp) dst (int dp) (int len); + VUndef + | _ -> assert false) + | "bytes_blit" -> + (function + | [VBytes dst; VInt dp; VBytes src; VInt sp; VInt len] -> + String.blit src (int sp) dst (int dp) (int len); + VUndef + | [(VBytes _ | VNull); VInt _; (VBytes _ | VNull); VInt _; VInt len] -> + if len = 0l then VUndef else error "bytes_blit to NULL bytes"; + | _ -> assert false) + | "bsort_i32" -> + (function + | [VBytes b; VInt pos; VInt len; VClosure (f,c)] -> + let pos = int pos and len = int len in + let a = Array.init len (fun i -> get_i32 b (pos + i * 4)) in + Array.stable_sort (fun a b -> + match ctx.fcall f (match c with None -> [VInt a;VInt b] | Some v -> [v;VInt a;VInt b]) with + | VInt i -> int i + | _ -> assert false + ) a; + Array.iteri (fun i v -> set_i32 b (pos + i * 4) v) a; + VUndef; + | _ -> + assert false) + | "bsort_f64" -> + (function + | [VBytes b; VInt pos; VInt len; VClosure _] -> + assert false + | _ -> + assert false) + | "itos" -> + (function + | [VInt v; VRef (r,_)] -> + let str = Int32.to_string v in + set_ref r (to_int (String.length str)); + VBytes (caml_to_hl str) + | _ -> assert false); + | "ftos" -> + (function + | [VFloat f; VRef (r,_)] -> + let str = float_to_string f in + set_ref r (to_int (String.length str)); + VBytes (caml_to_hl str) + | _ -> assert false); + | "value_to_string" -> + (function + | [v; VRef (r,_)] -> + let str = caml_to_hl (vstr ctx v HDyn) in + set_ref r (to_int ((String.length str) lsr 1 - 1)); + VBytes str + | _ -> assert false); + | "math_isnan" -> (function [VFloat f] -> VBool (classify_float f = FP_nan) | _ -> assert false) + | "math_isfinite" -> (function [VFloat f] -> VBool (match classify_float f with FP_infinite | FP_nan -> false | _ -> true) | _ -> assert false) + | "math_round" -> (function [VFloat f] -> VInt (Int32.of_float (floor (f +. 0.5))) | _ -> assert false) + | "math_floor" -> (function [VFloat f] -> VInt (Int32.of_float (floor f)) | _ -> assert false) + | "math_ceil" -> (function [VFloat f] -> VInt (Int32.of_float (ceil f)) | _ -> assert false) + | "math_ffloor" -> (function [VFloat f] -> VFloat (floor f) | _ -> assert false) + | "math_fceil" -> (function [VFloat f] -> VFloat (ceil f) | _ -> assert false) + | "math_fround" -> (function [VFloat f] -> VFloat (floor (f +. 0.5)) | _ -> assert false) + | "math_abs" -> (function [VFloat f] -> VFloat (abs_float f) | _ -> assert false) + | "math_sqrt" -> (function [VFloat f] -> VFloat (if f < 0. then nan else sqrt f) | _ -> assert false) + | "math_cos" -> (function [VFloat f] -> VFloat (cos f) | _ -> assert false) + | "math_sin" -> (function [VFloat f] -> VFloat (sin f) | _ -> assert false) + | "math_tan" -> (function [VFloat f] -> VFloat (tan f) | _ -> assert false) + | "math_acos" -> (function [VFloat f] -> VFloat (acos f) | _ -> assert false) + | "math_asin" -> (function [VFloat f] -> VFloat (asin f) | _ -> assert false) + | "math_atan" -> (function [VFloat f] -> VFloat (atan f) | _ -> assert false) + | "math_atan2" -> (function [VFloat a; VFloat b] -> VFloat (atan2 a b) | _ -> assert false) + | "math_log" -> (function [VFloat f] -> VFloat (Pervasives.log f) | _ -> assert false) + | "math_exp" -> (function [VFloat f] -> VFloat (exp f) | _ -> assert false) + | "math_pow" -> (function [VFloat a; VFloat b] -> VFloat (a ** b) | _ -> assert false) + | "parse_int" -> + (function + | [VBytes str; VInt pos; VInt len] -> + (try + let i = (match Interp.parse_int (hl_to_caml_sub str (int pos) (int len)) with + | Interp.VInt v -> Int32.of_int v + | Interp.VInt32 v -> v + | _ -> assert false + ) in + VDyn (VInt i,HI32) + with _ -> + VNull) + | l -> assert false) + | "parse_float" -> + (function + | [VBytes str; VInt pos; VInt len] -> (try VFloat (Interp.parse_float (hl_to_caml_sub str (int pos) (int len))) with _ -> VFloat nan) + | _ -> assert false) + | "dyn_compare" -> + (function + | [a;b] -> to_int (dyn_compare ctx a HDyn b HDyn) + | _ -> assert false) + | "fun_compare" -> + let ocompare o1 o2 = + match o1, o2 with + | None, None -> true + | Some o1, Some o2 -> o1 == o2 + | _ -> false + in + (function + | [VClosure (FFun f1,o1);VClosure (FFun f2,o2)] -> VBool (f1 == f2 && ocompare o1 o2) + | [VClosure (FNativeFun (f1,_,_),o1);VClosure (FNativeFun (f2,_,_),o2)] -> VBool (f1 = f2 && ocompare o1 o2) + | _ -> VBool false) + | "array_type" -> + (function + | [VArray (_,t)] -> VType t + | _ -> assert false) + | "value_cast" -> + (function + | [v;VType t] -> if is_compatible v t then v else throw_msg ctx ("Cannot cast " ^ vstr_d ctx v ^ " to " ^ tstr t); + | _ -> assert false) + | "hballoc" -> + (function + | [] -> VAbstract (AHashBytes (Hashtbl.create 0)) + | _ -> assert false) + | "hbset" -> + (function + | [VAbstract (AHashBytes h);VBytes b;v] -> + Hashtbl.replace h (hl_to_caml b) v; + VUndef + | _ -> assert false) + | "hbget" -> + (function + | [VAbstract (AHashBytes h);VBytes b] -> + (try Hashtbl.find h (hl_to_caml b) with Not_found -> VNull) + | _ -> assert false) + | "hbvalues" -> + (function + | [VAbstract (AHashBytes h)] -> + let values = Hashtbl.fold (fun _ v acc -> v :: acc) h [] in + VArray (Array.of_list values, HDyn) + | _ -> assert false) + | "hbkeys" -> + (function + | [VAbstract (AHashBytes h)] -> + let keys = Hashtbl.fold (fun s _ acc -> VBytes (caml_to_hl s) :: acc) h [] in + VArray (Array.of_list keys, HBytes) + | _ -> assert false) + | "hbexists" -> + (function + | [VAbstract (AHashBytes h);VBytes b] -> VBool (Hashtbl.mem h (hl_to_caml b)) + | _ -> assert false) + | "hbremove" -> + (function + | [VAbstract (AHashBytes h);VBytes b] -> + let m = Hashtbl.mem h (hl_to_caml b) in + if m then Hashtbl.remove h (hl_to_caml b); + VBool m + | _ -> assert false) + | "hialloc" -> + (function + | [] -> VAbstract (AHashInt (Hashtbl.create 0)) + | _ -> assert false) + | "hiset" -> + (function + | [VAbstract (AHashInt h);VInt i;v] -> + Hashtbl.replace h i v; + VUndef + | _ -> assert false) + | "higet" -> + (function + | [VAbstract (AHashInt h);VInt i] -> + (try Hashtbl.find h i with Not_found -> VNull) + | _ -> assert false) + | "hivalues" -> + (function + | [VAbstract (AHashInt h)] -> + let values = Hashtbl.fold (fun _ v acc -> v :: acc) h [] in + VArray (Array.of_list values, HDyn) + | _ -> assert false) + | "hikeys" -> + (function + | [VAbstract (AHashInt h)] -> + let keys = Hashtbl.fold (fun i _ acc -> VInt i :: acc) h [] in + VArray (Array.of_list keys, HI32) + | _ -> assert false) + | "hiexists" -> + (function + | [VAbstract (AHashInt h);VInt i] -> VBool (Hashtbl.mem h i) + | _ -> assert false) + | "hiremove" -> + (function + | [VAbstract (AHashInt h);VInt i] -> + let m = Hashtbl.mem h i in + if m then Hashtbl.remove h i; + VBool m + | _ -> assert false) + | "hoalloc" -> + (function + | [] -> VAbstract (AHashObject (ref [])) + | _ -> assert false) + | "hoset" -> + (function + | [VAbstract (AHashObject l);o;v] -> + let o = no_virtual o in + let rec replace l = + match l with + | [] -> [o,v] + | (o2,_) :: l when o == o2 -> (o,v) :: l + | p :: l -> p :: replace l + in + l := replace !l; + VUndef + | _ -> assert false) + | "hoget" -> + (function + | [VAbstract (AHashObject l);o] -> + (try List.assq (no_virtual o) !l with Not_found -> VNull) + | _ -> assert false) + | "hovalues" -> + (function + | [VAbstract (AHashObject l)] -> + VArray (Array.of_list (List.map snd !l), HDyn) + | _ -> assert false) + | "hokeys" -> + (function + | [VAbstract (AHashObject l)] -> + VArray (Array.of_list (List.map fst !l), HDyn) + | _ -> assert false) + | "hoexists" -> + (function + | [VAbstract (AHashObject l);o] -> VBool (List.mem_assq (no_virtual o) !l) + | _ -> assert false) + | "horemove" -> + (function + | [VAbstract (AHashObject rl);o] -> + let rec loop acc = function + | [] -> false + | (o2,_) :: l when o == o2 -> + rl := (List.rev acc) @ l; + true + | p :: l -> loop (p :: acc) l + in + VBool (loop [] !rl) + | _ -> assert false) + | "sys_print" -> + (function + | [VBytes str] -> print_string (hl_to_caml str); VUndef + | _ -> assert false) + | "sys_time" -> + (function + | [] -> VFloat (Unix.gettimeofday()) + | _ -> assert false) + | "sys_exit" -> + (function + | [VInt code] -> raise (Sys_exit (Int32.to_int code)) + | _ -> assert false) + | "sys_utf8_path" -> + (function + | [] -> VBool true + | _ -> assert false) + | "sys_string" -> + let cached_sys_name = ref None in + (function + | [] -> + VBytes (caml_to_hl (match Sys.os_type with + | "Unix" -> + (match !cached_sys_name with + | Some n -> n + | None -> + let ic = Unix.open_process_in "uname" in + let uname = (match input_line ic with + | "Darwin" -> "Mac" + | n -> n + ) in + close_in ic; + cached_sys_name := Some uname; + uname) + | "Win32" | "Cygwin" -> "Windows" + | s -> s)) + | _ -> + assert false) + | "sys_is64" -> + (function + | [] -> VBool (Sys.word_size = 64) + | _ -> assert false) + | "hash" -> + (function + | [VBytes str] -> VInt (hash ctx (hl_to_caml str)) + | _ -> assert false) + | "type_safe_cast" -> + (function + | [VType a; VType b] -> VBool (safe_cast a b) + | _ -> assert false) + | "type_super" -> + (function + | [VType t] -> VType (match t with HObj { psuper = Some o } -> HObj o | _ -> HVoid) + | _ -> assert false) + | "type_args_count" -> + (function + | [VType t] -> to_int (match t with HFun (args,_) -> List.length args | _ -> 0) + | _ -> assert false) + | "type_get_global" -> + (function + | [VType t] -> + (match t with + | HObj c -> (match c.pclassglobal with None -> VNull | Some g -> ctx.t_globals.(g)) + | HEnum e -> (match e.eglobal with None -> VNull | Some g -> ctx.t_globals.(g)) + | _ -> VNull) + | _ -> assert false) + | "type_set_global" -> + (function + | [VType t; v] -> + VBool (match t with + | HObj c -> (match c.pclassglobal with None -> false | Some g -> ctx.t_globals.(g) <- v; true) + | HEnum e -> (match e.eglobal with None -> false | Some g -> ctx.t_globals.(g) <- v; true) + | _ -> false) + | _ -> assert false) + | "type_name" -> + (function + | [VType t] -> + VBytes (caml_to_hl (match t with + | HObj o -> o.pname + | HEnum e -> e.ename + | _ -> assert false)) + | _ -> assert false) + | "obj_fields" -> + let rec get_fields v isRec = + match v with + | VDynObj o -> + VArray (Array.of_list (Hashtbl.fold (fun n _ acc -> VBytes (caml_to_hl n) :: acc) o.dfields []), HBytes) + | VObj o -> + let rec loop p = + let fields = Array.map (fun (n,_,_) -> VBytes (caml_to_hl n)) p.pfields in + match p.psuper with Some p when isRec -> fields :: loop p | _ -> [fields] + in + VArray (Array.concat (loop o.oproto.pclass), HBytes) + | VVirtual v -> + get_fields v.vvalue isRec + | _ -> + VNull + in + (function + | [v] -> get_fields v true + | _ -> assert false) + | "obj_copy" -> + (function + | [VDynObj d | VVirtual { vvalue = VDynObj d }] -> + VDynObj { dfields = Hashtbl.copy d.dfields; dvalues = Array.copy d.dvalues; dtypes = Array.copy d.dtypes; dvirtuals = [] } + | [_] -> VNull + | _ -> assert false) + | "enum_parameters" -> + (function + | [VDyn (VEnum (idx,pl),HEnum e)] -> + let _,_, ptypes = e.efields.(idx) in + VArray (Array.mapi (fun i v -> make_dyn v ptypes.(i)) pl,HDyn) + | _ -> + assert false) + | "type_instance_fields" -> + (function + | [VType t] -> + (match t with + | HObj o -> + let rec fields o = + let sup = (match o.psuper with None -> [||] | Some o -> fields o) in + Array.concat [ + sup; + Array.map (fun (s,_,_) -> VBytes (caml_to_hl s)) o.pfields; + Array.of_list (Array.fold_left (fun acc f -> + let is_override = (match o.psuper with None -> false | Some p -> try ignore(get_index f.fname p); true with Not_found -> false) in + if is_override then acc else VBytes (caml_to_hl f.fname) :: acc + ) [] o.pproto) + ] + in + VArray (fields o,HBytes) + | _ -> VNull) + | _ -> assert false) + | "type_enum_fields" -> + (function + | [VType t] -> + (match t with + | HEnum e -> VArray (Array.map (fun (f,_,_) -> VBytes (caml_to_hl f)) e.efields,HBytes) + | _ -> VNull) + | _ -> assert false) + | "type_enum_values" -> + (function + | [VType (HEnum e as t)] -> + VArray (Array.mapi (fun i (_,_,args) -> if Array.length args <> 0 then VNull else VDyn (VEnum (i,[||]),t)) e.efields,HDyn) + | _ -> assert false) + | "type_enum_eq" -> + (function + | [VDyn (VEnum _, HEnum _); VNull] | [VNull; VDyn (VEnum _, HEnum _)] -> VBool false + | [VNull; VNull] -> VBool true + | [VDyn (VEnum _ as v1, HEnum e1); VDyn (VEnum _ as v2, HEnum e2)] -> + let rec loop v1 v2 e = + match v1, v2 with + | VEnum (t1,_), VEnum (t2,_) when t1 <> t2 -> false + | VEnum (t,vl1), VEnum (_,vl2) -> + let _, _, pl = e.efields.(t) in + let rec chk i = + if i = Array.length pl then true + else + (match pl.(i) with + | HEnum e -> loop vl1.(i) vl2.(i) e + | t -> dyn_compare ctx vl1.(i) t vl2.(i) t = 0) && chk (i + 1) + in + chk 0 + | _ -> assert false + in + VBool (if e1 != e2 then false else loop v1 v2 e1) + | _ -> assert false) + | "obj_get_field" -> + (function + | [o;VInt hash] -> + let f = (try Hashtbl.find ctx.cached_hashes hash with Not_found -> assert false) in + (match o with + | VObj _ | VDynObj _ | VVirtual _ -> dyn_get_field ctx o f HDyn + | _ -> VNull) + | _ -> assert false) + | "obj_set_field" -> + (function + | [o;VInt hash;v] -> + let f = (try Hashtbl.find ctx.cached_hashes hash with Not_found -> assert false) in + dyn_set_field ctx o f v HDyn; + VUndef + | _ -> assert false) + | "obj_has_field" -> + (function + | [o;VInt hash] -> + let f = (try Hashtbl.find ctx.cached_hashes hash with Not_found -> assert false) in + let rec loop o = + match o with + | VDynObj d -> Hashtbl.mem d.dfields f + | VObj o -> + let rec loop p = + if PMap.mem f p.pindex then let idx, _ = PMap.find f p.pindex in idx >= 0 else match p.psuper with None -> false | Some p -> loop p + in + loop o.oproto.pclass + | VVirtual v -> loop v.vvalue + | _ -> false + in + VBool (loop o) + | _ -> assert false) + | "obj_delete_field" -> + (function + | [o;VInt hash] -> + let f = (try Hashtbl.find ctx.cached_hashes hash with Not_found -> assert false) in + let rec loop o = + match o with + | VDynObj d when Hashtbl.mem d.dfields f -> + let idx = Hashtbl.find d.dfields f in + let count = Array.length d.dvalues in + Hashtbl.remove d.dfields f; + let fields = Hashtbl.fold (fun name i acc -> (name,if i < idx then i else i - 1) :: acc) d.dfields [] in + Hashtbl.clear d.dfields; + List.iter (fun (n,i) -> Hashtbl.add d.dfields n i) fields; + let vals2 = Array.make (count - 1) VNull in + let types2 = Array.make (count - 1) HVoid in + let len = count - idx - 1 in + Array.blit d.dvalues 0 vals2 0 idx; + Array.blit d.dvalues (idx + 1) vals2 idx len; + Array.blit d.dtypes 0 types2 0 idx; + Array.blit d.dtypes (idx + 1) types2 idx len; + d.dvalues <- vals2; + d.dtypes <- types2; + rebuild_virtuals ctx d; + true + | VVirtual v -> loop v.vvalue + | _ -> false + in + VBool (loop o) + | _ -> assert false) + | "get_virtual_value" -> + (function + | [VVirtual v] -> v.vvalue + | _ -> assert false) + | "ucs2length" -> + (function + | [VBytes s; VInt pos] -> + let delta = int pos in + let rec loop p = + let c = int_of_char s.[p+delta] lor ((int_of_char s.[p+delta+1]) lsl 8) in + if c = 0 then p lsr 1 else loop (p + 2) + in + to_int (loop 0) + | _ -> assert false) + | "utf8_to_utf16" -> + (function + | [VBytes s; VInt pos; VRef (r,HI32)] -> + let s = String.sub s (int pos) (String.length s - (int pos)) in + let u16 = caml_to_hl (try String.sub s 0 (String.index s '\000') with Not_found -> assert false) in + set_ref r (to_int (String.length u16 - 2)); + VBytes u16 + | _ -> assert false) + | "utf16_to_utf8" -> + (function + | [VBytes s; VInt pos; VRef (r,HI32)] -> + let s = String.sub s (int pos) (String.length s - (int pos)) in + let u8 = hl_to_caml s in + set_ref r (to_int (String.length u8)); + VBytes (u8 ^ "\x00") + | _ -> assert false) + | "ucs2_upper" -> + (function + | [VBytes s; VInt pos; VInt len] -> + let buf = Buffer.create 0 in + utf16_iter (fun c -> + let c = + if c >= int_of_char 'a' && c <= int_of_char 'z' then c + int_of_char 'A' - int_of_char 'a' + else c + in + utf16_add buf c + ) (String.sub s (int pos) ((int len) lsl 1)); + utf16_add buf 0; + VBytes (Buffer.contents buf) + | _ -> assert false) + | "ucs2_lower" -> + (function + | [VBytes s; VInt pos; VInt len] -> + let buf = Buffer.create 0 in + utf16_iter (fun c -> + let c = + if c >= int_of_char 'A' && c <= int_of_char 'Z' then c + int_of_char 'a' - int_of_char 'A' + else c + in + utf16_add buf c + ) (String.sub s (int pos) ((int len) lsl 1)); + utf16_add buf 0; + VBytes (Buffer.contents buf) + | _ -> assert false) + | "url_encode" -> + (function + | [VBytes s; VRef (r, HI32)] -> + let s = hl_to_caml s in + let buf = Buffer.create 0 in + let hex = "0123456789ABCDEF" in + for i = 0 to String.length s - 1 do + let c = String.unsafe_get s i in + match c with + | 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' | '-' | '.' -> + utf16_char buf c + | _ -> + utf16_char buf '%'; + utf16_char buf (String.unsafe_get hex (int_of_char c lsr 4)); + utf16_char buf (String.unsafe_get hex (int_of_char c land 0xF)); + done; + utf16_add buf 0; + let str = Buffer.contents buf in + set_ref r (to_int (String.length str lsr 1 - 1)); + VBytes str + | _ -> assert false) + | "url_decode" -> + (function + | [VBytes s; VRef (r, HI32)] -> + let s = hl_to_caml s in + let b = Buffer.create 0 in + let len = String.length s in + let decode c = + match c with + | '0'..'9' -> Some (int_of_char c - int_of_char '0') + | 'a'..'f' -> Some (int_of_char c - int_of_char 'a' + 10) + | 'A'..'F' -> Some (int_of_char c - int_of_char 'A' + 10) + | _ -> None + in + let rec loop i = + if i = len then () else + let c = String.unsafe_get s i in + match c with + | '%' -> + let p1 = (try decode (String.get s (i + 1)) with _ -> None) in + let p2 = (try decode (String.get s (i + 2)) with _ -> None) in + (match p1, p2 with + | Some c1, Some c2 -> + Buffer.add_char b (char_of_int ((c1 lsl 4) lor c2)); + loop (i + 3) + | _ -> + loop (i + 1)); + | '+' -> + Buffer.add_char b ' '; + loop (i + 1) + | c -> + Buffer.add_char b c; + loop (i + 1) + in + loop 0; + let str = Buffer.contents b in + set_ref r (to_int (UTF8.length str)); + VBytes (caml_to_hl str) + | _ -> assert false) + | "call_method" -> + (function + | [f;VArray (args,HDyn)] -> dyn_call ctx f (List.map (fun v -> v,HDyn) (Array.to_list args)) HDyn + | _ -> assert false) + | "no_closure" -> + (function + | [VClosure (f,_)] -> VClosure (f,None) + | _ -> assert false) + | "get_closure_value" -> + (function + | [VClosure (_,None)] -> VNull + | [VClosure (_,Some v)] -> v + | _ -> assert false) + | "make_var_args" -> + (function + | [VClosure (f,arg)] -> VVarArgs (f,arg) + | _ -> assert false) + | "bytes_find" -> + (function + | [VBytes src; VInt pos; VInt len; VBytes chk; VInt cpos; VInt clen; ] -> + to_int (try int pos + ExtString.String.find (String.sub src (int pos) (int len)) (String.sub chk (int cpos) (int clen)) with ExtString.Invalid_string -> -1) + | _ -> assert false) + | "bytes_compare" -> + (function + | [VBytes a; VInt apos; VBytes b; VInt bpos; VInt len] -> to_int (String.compare (String.sub a (int apos) (int len)) (String.sub b (int bpos) (int len))) + | _ -> assert false) + | "bytes_fill" -> + (function + | [VBytes a; VInt pos; VInt len; VInt v] -> + String.fill a (int pos) (int len) (char_of_int ((int v) land 0xFF)); + VUndef + | _ -> assert false) + | "exception_stack" -> + (function + | [] -> VArray (Array.map (fun e -> VBytes (caml_to_hl (stack_frame ctx e))) (Array.of_list (List.rev ctx.error_stack)),HBytes) + | _ -> assert false) + | "date_new" -> + (function + | [VInt y; VInt mo; VInt d; VInt h; VInt m; VInt s] -> + let t = Unix.localtime (Unix.time()) in + let t = { t with + tm_year = int y - 1900; + tm_mon = int mo; + tm_mday = int d; + tm_hour = int h; + tm_min = int m; + tm_sec = int s; + } in + to_date t + | _ -> + assert false) + | "date_now" -> + (function + | [] -> to_date (Unix.localtime (Unix.time())) + | _ -> assert false) + | "date_get_time" -> + (function + | [VInt v] -> VFloat (fst (Unix.mktime (date v)) *. 1000.) + | _ -> assert false) + | "date_from_time" -> + (function + | [VFloat f] -> to_date (Unix.localtime (f /. 1000.)) + | _ -> assert false) + | "date_get_inf" -> + (function + | [VInt d;year;month;day;hours;minutes;seconds;wday] -> + let d = date d in + let set r v = + match r with + | VNull -> () + | VRef (r,HI32) -> set_ref r (to_int v) + | _ -> assert false + in + set year (d.tm_year + 1900); + set month d.tm_mon; + set day d.tm_mday; + set hours d.tm_hour; + set minutes d.tm_min; + set seconds d.tm_sec; + set wday d.tm_wday; + VUndef + | _ -> assert false) + | "date_to_string" -> + (function + | [VInt d; VRef (r,HI32)] -> + let t = date d in + let str = Printf.sprintf "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" (t.tm_year + 1900) (t.tm_mon + 1) t.tm_mday t.tm_hour t.tm_min t.tm_sec in + set_ref r (to_int (String.length str)); + VBytes (caml_to_hl str) + | _ -> assert false) + | "rnd_init_system" -> + (function + | [] -> Random.self_init(); VAbstract ARandom + | _ -> assert false) + | "rnd_int" -> + (function + | [VAbstract ARandom] -> VInt (Int32.of_int (Random.bits())) + | _ -> assert false) + | "rnd_float" -> + (function + | [VAbstract ARandom] -> VFloat (Random.float 1.) + | _ -> assert false) + | "regexp_new_options" -> + (function + | [VBytes str; VBytes opt] -> + let case_sensitive = ref true in + List.iter (function + | 'm' -> () (* always ON ? *) + | 'i' -> case_sensitive := false + | c -> failwith ("Unsupported regexp option '" ^ String.make 1 c ^ "'") + ) (ExtString.String.explode (hl_to_caml opt)); + let buf = Buffer.create 0 in + let rec loop prev esc = function + | [] -> () + | c :: l when esc -> + (match c with + | 'n' -> Buffer.add_char buf '\n' + | 'r' -> Buffer.add_char buf '\r' + | 't' -> Buffer.add_char buf '\t' + | 's' -> Buffer.add_string buf "[ \t\r\n]" + | 'd' -> Buffer.add_string buf "[0-9]" + | '\\' -> Buffer.add_string buf "\\\\" + | '(' | ')' | '{' | '}' -> Buffer.add_char buf c + | '1'..'9' | '+' | '$' | '^' | '*' | '?' | '.' | '[' | ']' -> + Buffer.add_char buf '\\'; + Buffer.add_char buf c; + | _ -> + Buffer.add_char buf c); + loop c false l + | c :: l -> + match c with + | '\\' -> loop prev true l + | '(' | '|' | ')' -> + Buffer.add_char buf '\\'; + Buffer.add_char buf c; + loop c false l + | '?' when prev = '(' && (match l with ':' :: _ -> true | _ -> false) -> + failwith "Non capturing groups '(?:' are not supported in macros" + | '?' when prev = '*' -> + failwith "Ungreedy *? are not supported in macros" + | _ -> + Buffer.add_char buf c; + loop c false l + in + loop '\000' false (ExtString.String.explode (hl_to_caml str)); + let str = Buffer.contents buf in + let r = { + r = if !case_sensitive then Str.regexp str else Str.regexp_case_fold str; + r_string = ""; + r_groups = [||]; + } in + VAbstract (AReg r) + | _ -> + assert false); + | "regexp_match" -> + (function + | [VAbstract (AReg r);VBytes str;VInt pos;VInt len] -> + let str = hl_to_caml str and pos = int pos and len = int len in + let nstr, npos, delta = (if len = String.length str - pos then str, pos, 0 else String.sub str pos len, 0, pos) in + (try + ignore(Str.search_forward r.r nstr npos); + let rec loop n = + if n = 9 then + [] + else try + (Some (Str.group_beginning n + delta, Str.group_end n + delta)) :: loop (n + 1) + with Not_found -> + None :: loop (n + 1) + | Invalid_argument _ -> + [] + in + r.r_string <- str; + r.r_groups <- Array.of_list (loop 0); + VBool true; + with Not_found -> + VBool false) + | _ -> assert false); + | "regexp_matched_pos" -> + (function + | [VAbstract (AReg r); VInt n; VRef (rr,HI32)] -> + let n = int n in + (match (try r.r_groups.(n) with _ -> failwith ("Invalid group " ^ string_of_int n)) with + | None -> to_int (-1) + | Some (pos,pend) -> set_ref rr (to_int (pend - pos)); to_int pos) + | [VAbstract (AReg r); VInt n; VNull] -> + let n = int n in + (match (try r.r_groups.(n) with _ -> failwith ("Invalid group " ^ string_of_int n)) with + | None -> to_int (-1) + | Some (pos,pend) -> to_int pos) + | _ -> assert false) + | "make_macro_pos" -> + (function + | [VBytes file;VInt min;VInt max] -> + VAbstract (APos { Globals.pfile = String.sub file 0 (String.length file - 1); pmin = Int32.to_int min; pmax = Int32.to_int max }) + | _ -> assert false) + | _ -> + unresolved()) + | "macro" -> + (match ctx.resolve_macro_api name with + | None -> unresolved() + | Some f -> f) + | _ -> + unresolved() + ) in + FNativeFun (lib ^ "@" ^ name, f, t) + +let create checked = + let ctx = { + t_globals = [||]; + t_functions = [||]; + call_stack = []; + error_stack = []; + stack = [||]; + stack_pos = 0; + cached_protos = Hashtbl.create 0; + cached_strings = Hashtbl.create 0; + cached_hashes = Hashtbl.create 0; + code = { + functions = [||]; + globals = [||]; + natives = [||]; + strings = [||]; + ints = [||]; + debugfiles = [||]; + floats = [||]; + entrypoint = 0; + version = 0; + }; + checked = checked; + fcall = (fun _ _ -> assert false); + on_error = (fun _ _ -> assert false); + resolve_macro_api = (fun _ -> None); + } in + ctx.on_error <- (fun msg stack -> failwith (vstr ctx msg HDyn ^ "\n" ^ String.concat "\n" (List.map (stack_frame ctx) stack))); + ctx.fcall <- call_fun ctx; + ctx + +let set_error_handler ctx e = + ctx.on_error <- e + +let set_macro_api ctx f = + ctx.resolve_macro_api <- f + +let add_code ctx code = + (* expand global table *) + let globals = Array.map default code.globals in + Array.blit ctx.t_globals 0 globals 0 (Array.length ctx.t_globals); + ctx.t_globals <- globals; + (* expand function table *) + let nfunctions = Array.length code.functions + Array.length code.natives in + let functions = Array.create nfunctions (FNativeFun ("",(fun _ -> assert false),HDyn)) in + Array.blit ctx.t_functions 0 functions 0 (Array.length ctx.t_functions); + let rec loop i = + if i = Array.length code.natives then () else + let lib, name, t, idx = code.natives.(i) in + functions.(idx) <- load_native ctx code.strings.(lib) code.strings.(name) t; + loop (i + 1) + in + loop (Array.length ctx.code.natives); + let rec loop i = + if i = Array.length code.functions then () else + let fd = code.functions.(i) in + functions.(fd.findex) <- FFun fd; + loop (i + 1) + in + loop (Array.length ctx.code.functions); + ctx.t_functions <- functions; + ctx.code <- code; + (* call entrypoint *) + ignore(call_wrap ctx functions.(code.entrypoint) []) + +(* ------------------------------- CHECK ---------------------------------------------- *) + +let check code macros = + let ftypes = Array.create (Array.length code.natives + Array.length code.functions) HVoid in + let is_native_fun = Hashtbl.create 0 in + + let check_fun f = + let pos = ref 0 in + let error msg = + let dfile, dline = f.debug.(!pos) in + let file = code.debugfiles.(dfile) in + let msg = Printf.sprintf "Check failure at fun@%d @%X - %s" f.findex (!pos) msg in + if macros then begin + let low = dline land 0xFFFFF in + let pos = { + Globals.pfile = file; + Globals.pmin = low; + Globals.pmax = low + (dline lsr 20); + } in + Common.abort msg pos + end else + failwith (Printf.sprintf "\n%s:%d: %s" file dline msg) + in + let targs, tret = (match f.ftype with HFun (args,ret) -> args, ret | _ -> assert false) in + let rtype i = try f.regs.(i) with _ -> HObj { null_proto with pname = "OUT_OF_BOUNDS:" ^ string_of_int i } in + let check t1 t2 = + if not (safe_cast t1 t2) then error (tstr t1 ^ " should be " ^ tstr t2) + in + let reg_inf r = + "Register " ^ string_of_int r ^ "(" ^ tstr (rtype r) ^ ")" + in + let reg r t = + if not (safe_cast (rtype r) t) then error (reg_inf r ^ " should be " ^ tstr t ^ " and not " ^ tstr (rtype r)) + in + let numeric r = + match rtype r with + | HUI8 | HUI16 | HI32 | HF32 | HF64 -> () + | _ -> error (reg_inf r ^ " should be numeric") + in + let int r = + match rtype r with + | HUI8 | HUI16 | HI32 -> () + | _ -> error (reg_inf r ^ " should be integral") + in + let float r = + match rtype r with + | HF32 | HF64 -> () + | _ -> error (reg_inf r ^ " should be float") + in + let call f args r = + match ftypes.(f) with + | HFun (targs, tret) -> + if List.length args <> List.length targs then error (tstr (HFun (List.map rtype args, rtype r)) ^ " should be " ^ tstr ftypes.(f)); + List.iter2 reg args targs; + check tret (rtype r) + | _ -> assert false + in + let can_jump delta = + if !pos + 1 + delta < 0 || !pos + 1 + delta >= Array.length f.code then error "Jump outside function bounds"; + if delta < 0 && Array.get f.code (!pos + 1 + delta) <> OLabel 0 then error "Jump back without Label"; + in + let is_obj r = + match rtype r with + | HObj _ -> () + | _ -> error (reg_inf r ^ " should be object") + in + let is_enum r = + match rtype r with + | HEnum _ -> () + | _ -> error (reg_inf r ^ " should be enum") + in + let is_dyn r = + if not (is_dynamic (rtype r)) then error (reg_inf r ^ " should be castable to dynamic") + in + let tfield o fid proto = + if fid < 0 then error (reg_inf o ^ " does not have " ^ (if proto then "proto " else "") ^ "field " ^ string_of_int fid); + match rtype o with + | HObj p -> + if proto then ftypes.(p.pvirtuals.(fid)) else (try snd (resolve_field p fid) with Not_found -> error (reg_inf o ^ " does not have field " ^ string_of_int fid)) + | HVirtual v when not proto -> + let _,_, t = v.vfields.(fid) in + t + | _ -> + is_obj o; + HVoid + in + list_iteri reg targs; + Array.iteri (fun i op -> + pos := i; + match op with + | OMov (a,b) -> + reg b (rtype a) + | OInt (r,i) -> + ignore(code.ints.(i)); + int r + | OFloat (r,i) -> + if rtype r <> HF32 then reg r HF64; + if i < 0 || i >= Array.length code.floats then error "float outside range"; + | OBool (r,_) -> + reg r HBool + | OString (r,i) | OBytes (r,i) -> + reg r HBytes; + if i < 0 || i >= Array.length code.strings then error "string outside range"; + | ONull r -> + let t = rtype r in + if not (is_nullable t) then error (tstr t ^ " is not nullable") + | OAdd (r,a,b) | OSub (r,a,b) | OMul (r,a,b) | OSDiv (r,a,b) | OUDiv (r,a,b) | OSMod (r,a,b) | OUMod(r,a,b) -> + numeric r; + reg a (rtype r); + reg b (rtype r); + | ONeg (r,a) -> + numeric r; + reg a (rtype r); + | OShl (r,a,b) | OSShr (r,a,b) | OUShr (r,a,b) | OAnd (r,a,b) | OOr (r,a,b) | OXor (r,a,b) -> + int r; + reg a (rtype r); + reg b (rtype r); + | OIncr r -> + int r + | ODecr r -> + int r + | ONot (a,b) -> + reg a HBool; + reg b HBool; + | OCall0 (r,f) -> + call f [] r + | OCall1 (r, f, a) -> + call f [a] r + | OCall2 (r, f, a, b) -> + call f [a;b] r + | OCall3 (r, f, a, b, c) -> + call f [a;b;c] r + | OCall4 (r, f, a, b, c, d) -> + call f [a;b;c;d] r + | OCallN (r,f,rl) -> + call f rl r + | OCallThis (r, m, rl) -> + (match tfield 0 m true with + | HFun (tobj :: targs, tret) when List.length targs = List.length rl -> reg 0 tobj; List.iter2 reg rl targs; check tret (rtype r) + | t -> check t (HFun (rtype 0 :: List.map rtype rl, rtype r))); + | OCallMethod (r, m, rl) -> + (match rl with + | [] -> assert false + | obj :: rl2 -> + let t, rl = (match rtype obj with + | HVirtual v -> + let _, _, t = v.vfields.(m) in + t, rl2 + | _ -> + tfield obj m true, rl + ) in + match t with + | HFun (targs, tret) when List.length targs = List.length rl -> List.iter2 reg rl targs; check tret (rtype r) + | t -> check t (HFun (List.map rtype rl, rtype r))) + | OCallClosure (r,f,rl) -> + (match rtype f with + | HFun (targs,tret) when List.length targs = List.length rl -> List.iter2 reg rl targs; check tret (rtype r) + | HDyn -> List.iter (fun r -> ignore(rtype r)) rl; + | _ -> reg f (HFun(List.map rtype rl,rtype r))) + | OGetGlobal (r,g) -> + if not (safe_cast code.globals.(g) (rtype r)) then reg r code.globals.(g) + | OSetGlobal (g,r) -> + reg r code.globals.(g) + | ORet r -> + reg r tret + | OJTrue (r,delta) | OJFalse (r,delta) -> + reg r HBool; + can_jump delta + | OJNull (r,delta) | OJNotNull (r,delta) -> + ignore(rtype r); + can_jump delta + | OJUGte (a,b,delta) | OJULt (a,b,delta) | OJSGte (a,b,delta) | OJSLt (a,b,delta) | OJSGt (a,b,delta) | OJSLte (a,b,delta) -> + if not (safe_cast (rtype a) (rtype b)) then reg b (rtype a); + can_jump delta + | OJEq (a,b,delta) | OJNotEq (a,b,delta) -> + (match rtype a, rtype b with + | (HObj _ | HVirtual _), (HObj _ | HVirtual _) -> () + | ta, tb when safe_cast tb ta -> () + | _ -> reg a (rtype b)); + can_jump delta + | OJAlways d -> + can_jump d + | OToDyn (r,a) -> + (* we can still use OToDyn on nullable if we want to turn them into dynamic *) + if is_dynamic (rtype a) then reg a HI32; (* don't wrap as dynamic types that can safely be cast to it *) + if rtype r <> HDyn then reg r (HNull (rtype a)) + | OToSFloat (a,b) | OToUFloat (a,b) -> + float a; + (match rtype b with HF32 | HF64 -> () | _ -> int b); + | OToInt (a,b) -> + int a; + (match rtype b with HF32 | HF64 -> () | _ -> int b); + | OLabel _ -> + () + | ONew r -> + (match rtype r with + | HDynObj | HVirtual _ -> () + | _ -> is_obj r) + | OField (r,o,fid) -> + check (tfield o fid false) (rtype r) + | OSetField (o,fid,r) -> + reg r (tfield o fid false) + | OGetThis (r,fid) -> + check (tfield 0 fid false) (rtype r) + | OSetThis(fid,r) -> + reg r (tfield 0 fid false) + | OStaticClosure (r,f) -> + reg r ftypes.(f) + | OVirtualClosure (r,o,fid) -> + (match rtype o with + | HObj _ -> + (match tfield o fid true with + | HFun (t :: tl, tret) -> + reg o t; + reg r (HFun (tl,tret)); + | _ -> + assert false) + | HVirtual v -> + let _,_, t = v.vfields.(fid) in + reg r t; + | _ -> + is_obj o) + | OInstanceClosure (r,f,arg) -> + (match ftypes.(f) with + | HFun (t :: tl, tret) -> + reg arg t; + if not (is_nullable t) then error (reg_inf r ^ " should be nullable"); + reg r (HFun (tl,tret)); + | _ -> assert false); + | OThrow r -> + reg r HDyn + | ORethrow r -> + reg r HDyn + | OGetArray (v,a,i) -> + reg a HArray; + reg i HI32; + ignore(rtype v); + | OGetUI8 (r,b,p) | OGetI32 (r,b,p) | OGetUI16(r,b,p) -> + reg r HI32; + reg b HBytes; + reg p HI32; + | OGetF32 (r,b,p) -> + reg r HF32; + reg b HBytes; + reg p HI32; + | OGetF64 (r,b,p) -> + reg r HF64; + reg b HBytes; + reg p HI32; + | OSetUI8 (r,p,v) | OSetI32 (r,p,v) | OSetUI16 (r,p,v) -> + reg r HBytes; + reg p HI32; + reg v HI32; + | OSetF32 (r,p,v) -> + reg r HBytes; + reg p HI32; + reg v HF32; + | OSetF64 (r,p,v) -> + reg r HBytes; + reg p HI32; + reg v HF64; + | OSetArray (a,i,v) -> + reg a HArray; + reg i HI32; + ignore(rtype v); + | OUnsafeCast (a,b) -> + is_dyn a; + is_dyn b; + | OSafeCast (a,b) -> + ignore(rtype a); + ignore(rtype b); + | OArraySize (r,a) -> + reg a HArray; + reg r HI32 + | OType (r,_) -> + reg r HType + | OGetType (r,v) -> + reg r HType; + is_dyn v; + | OGetTID (r,v) -> + reg r HI32; + reg v HType; + | OUnref (v,r) -> + (match rtype r with + | HRef t -> check t (rtype v) + | _ -> reg r (HRef (rtype v))) + | ORef (r,v) + | OSetref (r,v) -> + (match rtype r with HRef t -> reg v t | _ -> reg r (HRef (rtype v))) + | OToVirtual (r,v) -> + (match rtype r with + | HVirtual _ -> () + | _ -> reg r (HVirtual {vfields=[||];vindex=PMap.empty;})); + (match rtype v with + | HObj _ | HDynObj | HDyn | HVirtual _ -> () + | _ -> reg v HDynObj) + | ODynGet (v,r,f) | ODynSet (r,f,v) -> + ignore(code.strings.(f)); + ignore(rtype v); + (match rtype r with + | HObj _ | HDyn | HDynObj | HVirtual _ -> () + | _ -> reg r HDynObj) + | OMakeEnum (r,index,pl) -> + (match rtype r with + | HEnum e -> + let _,_, fl = e.efields.(index) in + if Array.length fl <> List.length pl then error ("MakeEnum has " ^ (string_of_int (List.length pl)) ^ " params while " ^ (string_of_int (Array.length fl)) ^ " are required"); + List.iter2 (fun r t -> reg r t) pl (Array.to_list fl) + | _ -> + is_enum r) + | OEnumAlloc (r,index) -> + (match rtype r with + | HEnum e -> + ignore(e.efields.(index)) + | _ -> + is_enum r) + | OEnumIndex (r,v) -> + if rtype v <> HDyn then is_enum v; + reg r HI32; + | OEnumField (r,e,f,i) -> + (match rtype e with + | HEnum e -> + let _, _, tl = e.efields.(f) in + check tl.(i) (rtype r) + | _ -> is_enum e) + | OSetEnumField (e,i,r) -> + (match rtype e with + | HEnum e -> + let _, _, tl = e.efields.(0) in + check (rtype r) tl.(i) + | _ -> is_enum e) + | OSwitch (r,idx,eend) -> + reg r HI32; + Array.iter can_jump idx; + if eend + 1 + i <> Array.length f.code then can_jump eend + | ONullCheck r -> + ignore(rtype r) + | OTrap (r, idx) -> + reg r HDyn; + can_jump idx + | OEndTrap _ -> + () + | ONop _ -> + () + ) f.code + (* TODO : check that all path correctly initialize NULL values and reach a return *) + in + Array.iter (fun fd -> + if fd.findex >= Array.length ftypes then failwith ("Invalid function index " ^ string_of_int fd.findex); + if ftypes.(fd.findex) <> HVoid then failwith ("Duplicate function bind " ^ string_of_int fd.findex ^ " " ^ fundecl_name fd); + ftypes.(fd.findex) <- fd.ftype; + ) code.functions; + Array.iter (fun (lib,name,t,idx) -> + if idx >= Array.length ftypes then failwith ("Invalid native function index " ^ string_of_int idx ^ " for "^ code.strings.(lib) ^ "@" ^ code.strings.(name)); + if ftypes.(idx) <> HVoid then failwith ("Duplicate native function bind " ^ string_of_int idx); + Hashtbl.add is_native_fun idx true; + ftypes.(idx) <- t + ) code.natives; + (* TODO : check that no object type has a virtual native in his proto *) + Array.iter check_fun code.functions + +(* ------------------------------- SPEC ---------------------------------------------- *) + +open Hlopt + +type svalue = + | SUndef + | SArg of int + | SInt of int32 + | SFloat of float + | SString of string + | SBool of bool + | SNull + | SType of ttype + | SOp of string * svalue * svalue + | SUnop of string * svalue + | SResult of string + | SFun of int * svalue option + | SMeth of svalue * int + | SGlobal of int + | SField of svalue * int + | SDField of svalue * string + | SConv of string * svalue + | SCast of svalue * ttype + | SMem of svalue * svalue * ttype + | SEnum of int * svalue list + | SEnumField of svalue * int * int + | SUnion of svalue list + | SRef of int + | SRefResult of string + | SUnreach + | SExc + | SDelayed of string * svalue list option ref + +type call_spec = + | SFid of int + | SMethod of int + | SClosure of svalue + +type spec = + | SCall of call_spec * svalue list + | SGlobalSet of int * svalue + | SFieldSet of svalue * int * svalue + | SFieldDSet of svalue * string * svalue + | SJEq of string * svalue + | SJComp of string * svalue * svalue + | SJump + | SRet of svalue + | SNullCheck of svalue + | SThrow of svalue + | SSwitch of svalue + | SWriteMem of svalue * svalue * svalue * ttype + | SSetRef of svalue * svalue + | SSetEnumField of svalue * int * svalue + | SStoreResult of string * spec + | SNew of ttype * int + | SVal of svalue + +let rec svalue_string v = + let sval = svalue_string in + match v with + | SUndef -> "undef" + | SArg i -> "arg" ^ string_of_int i + | SInt i -> Int32.to_string i + | SFloat f -> string_of_float f + | SString s -> "\"" ^ s ^ "\"" + | SBool b -> if b then "true" else "false" + | SNull -> "null" + | SRef _ -> "ref" + | SRefResult s -> Printf.sprintf "refresult(%s)" s + | SType t -> tstr t + | SOp (op,a,b) -> Printf.sprintf "(%s %s %s)" (sval a) op (sval b) + | SUnop (op,v) -> op ^ sval v + | SResult i -> i + | SFun (i,None) -> "fun" ^ string_of_int i + | SFun (i,Some v) -> Printf.sprintf "fun%d(%s)" i (sval v) + | SMeth (v,i) -> Printf.sprintf "meth%d(%s)" i (sval v) + | SGlobal g -> Printf.sprintf "G[%d]" g + | SField (o,i) -> Printf.sprintf "%s[%d]" (sval o) i + | SDField (o,f) -> Printf.sprintf "%s.%s" (sval o) f + | SConv (f,v) -> Printf.sprintf "%s(%s)" f (sval v) + | SCast (v,t) -> Printf.sprintf "cast(%s,%s)" (sval v) (tstr t) + | SMem (m,idx,t) -> Printf.sprintf "(%s*)%s[%s]" (tstr t) (sval m) (sval idx) + | SEnum (i,vl) -> Printf.sprintf "enum%d(%s)" i (String.concat "," (List.map sval vl)) + | SEnumField (v,k,i) -> Printf.sprintf "%s[%d:%d]" (sval v) k i + | SUnion vl -> Printf.sprintf "union(%s)" (String.concat " | " (List.map sval vl)) + | SUnreach -> "unreach" + | SExc -> "exc" + | SDelayed (str,_) -> str + +let svalue_iter f = function + | SUndef | SArg _ | SInt _ | SFloat _ | SString _ | SBool _ | SNull | SType _ | SResult _ + | SFun (_,None) | SGlobal _ | SRef _ | SRefResult _ | SUnreach | SExc | SDelayed _ -> + () + | SOp (_,a,b) | SMem (a,b,_) -> f a; f b + | SUnop (_,a) | SFun (_,Some a) | SMeth (a,_) | SField (a,_) | SDField (a,_) | SConv (_,a) | SCast (a,_) | SEnumField (a,_,_) -> f a + | SUnion vl | SEnum (_,vl) -> List.iter f vl + +let spec_iter fs fv = function + | SCall (c,vl) -> + (match c with SClosure v -> fv v | _ -> ()); + List.iter fv vl + | SVal v + | SJEq (_,v) + | SRet v + | SNullCheck v + | SThrow v + | SSwitch v + | SGlobalSet (_,v) -> fv v + | SJComp (_,a,b) + | SSetRef (a,b) + | SSetEnumField (a,_,b) + | SFieldDSet (a,_,b) | SFieldSet (a,_,b) -> fv a; fv b + | SJump -> + () + | SWriteMem (m,a,b,_) -> + fv m; fv a; fv b + | SStoreResult (_,s) -> + fs s + | SNew _ -> + () + +let rec svalue_same a b = + let vsame = svalue_same in + match a, b with + | SType t1, SType t2 -> tsame t1 t2 + | SOp (op1,a1,b1), SOp (op2,a2,b2) -> op1 = op2 && vsame a1 a2 && vsame b1 b2 + | SUnop (op1,v1), SUnop (op2,v2) -> op1 = op2 && vsame v1 v2 + | SFun (f1,Some v1), SFun (f2,Some v2) -> f1 = f2 && vsame v1 v2 + | SMeth (v1,m1), SMeth (v2,m2) -> vsame v1 v2 && m1 = m2 + | SField (v1,f1), SField (v2,f2) -> vsame v1 v2 && f1 = f2 + | SDField (v1,f1), SDField (v2,f2) -> vsame v1 v2 && f1 = f2 + | SConv (op1,v1), SConv (op2,v2) -> op1 = op2 && vsame v1 v2 + | SCast (v1,t1), SCast (v2,t2) -> vsame v1 v2 && tsame t1 t2 + | SMem (m1,i1,t1), SMem (m2,i2,t2) -> vsame m1 m2 && vsame i1 i2 && tsame t1 t2 + | SEnum (i1,vl1), SEnum (i2,vl2) -> i1 = i2 && List.length vl1 = List.length vl2 && List.for_all2 vsame vl1 vl2 + | SEnumField (v1,c1,i1), SEnumField (v2,c2,i2) -> vsame v1 v2 && c1 = c2 && i1 = i2 + | SUnion vl1, SUnion vl2 -> List.length vl1 = List.length vl2 && List.for_all2 vsame vl1 vl2 + | SDelayed (id1,_), SDelayed (id2,_) -> id1 = id2 + | _ -> a = b + +let rec spec_string s = + let sval = svalue_string in + match s with + | SCall (c,vl) -> + let cstr = (match c with + | SFid i -> Printf.sprintf "fun%d" i + | SMethod i -> Printf.sprintf "meth%d" i + | SClosure v -> Printf.sprintf "closure(%s)" (sval v) + ) in + Printf.sprintf "%s(%s)" cstr (String.concat "," (List.map sval vl)) + | SGlobalSet (i,v) -> + Printf.sprintf "G[%d] = %s" i (sval v) + | SFieldSet (o,fid,v) | SSetEnumField (o,fid,v) -> + Printf.sprintf "%s[%d] = %s" (sval o) fid (sval v) + | SFieldDSet (o,f,v) -> + Printf.sprintf "%s.%s = %s" (sval o) f (sval v) + | SJEq (s,v) -> + Printf.sprintf "j%s(%s)" s (sval v) + | SJComp (s,a,b) -> + Printf.sprintf "jump(%s %s %s)" (sval a) s (sval b) + | SJump -> + "jump" + | SRet v -> + "ret " ^ sval v + | SNullCheck v -> + "nullcheck " ^ sval v + | SThrow v -> + "throw " ^ sval v + | SSwitch v -> + "switch " ^ sval v + | SWriteMem (m,idx,v,t) -> + Printf.sprintf "(%s*)%s[%s] = %s" (tstr t) (sval m) (sval idx) (sval v) + | SSetRef (r,v) -> + Printf.sprintf "*%s = %s" (sval r) (sval v) + | SStoreResult (r,s) -> + r ^ " <- " ^ spec_string s + | SNew (t,idx) -> + Printf.sprintf "new %s(%d)" (tstr t) idx + | SVal v -> + sval v + +let make_spec (code:code) (f:fundecl) = + let op = Array.get f.code in + let out_spec = ref [] in + let alloc_count = ref (-1) in + + let digest str = + let d = Digest.to_hex (Digest.string str) in + String.sub d 0 4 + in + + let rec semit s = + let rec loop_spec s = + spec_iter loop_spec loop_val s + + and loop_val v = + match v with + | SDelayed (r,used) -> + (match !used with + | None -> () + | Some vl -> used := None; semit (SStoreResult (r,SVal (SUnion vl)))) + | _ -> + svalue_iter loop_val v + in + loop_spec s; + out_spec := s :: !out_spec + in + + let emit (s:spec) = + let d = digest (spec_string s) in + semit (SStoreResult (d,s)); + SResult d + in + + let big_unions = Hashtbl.create 0 in + + let block_args = Hashtbl.create 0 in + let rec get_args b = + try + Hashtbl.find block_args b.bstart + with Not_found -> + assert false + + and calc_spec b = + let bprev = List.filter (fun b2 -> b2.bstart < b.bstart) b.bprev in + let args = (match bprev with + | [] -> + let args = Array.make (Array.length f.regs) SUndef in + (match f.ftype with + | HFun (tl,_) -> list_iteri (fun i _ -> args.(i) <- SArg i) tl + | _ -> assert false); + args + | b2 :: l -> + let args = Array.copy (get_args b2) in + List.iter (fun b2 -> + let args2 = get_args b2 in + for i = 0 to Array.length args - 1 do + if not (svalue_same args.(i) args2.(i)) then begin + let l1 = (match args.(i) with SUnion l -> l | v -> [v]) in + let l2 = (match args2.(i) with SUnion l -> l | v -> [v]) in + let l = l1 @ List.filter (fun v -> not (List.exists (svalue_same v) l1)) l2 in + if List.length l > 10 then begin + (try + let ident, used = Hashtbl.find big_unions l in + args.(i) <- SDelayed (ident, used); + with Not_found -> + let ident = digest (String.concat "," (List.map svalue_string l)) in + let used = ref (Some l) in + Hashtbl.replace big_unions l (ident,used); + args.(i) <- SDelayed (ident, used)) + end else + args.(i) <- SUnion l; + end + done; + ) l; + if l = [] then (match op b2.bend with OTrap (r,_) -> args.(r) <- SExc | _ -> ()); + args + ) in + let make_call c vl = + let r = emit (SCall (c,vl)) in + (match r with + | SResult result -> List.iter (fun v -> match v with SRef r -> args.(r) <- SRefResult result | _ -> ()) vl + | _ -> assert false); + r + in + for i = b.bstart to b.bend do + match op i with + | OMov (d,r) -> args.(d) <- args.(r) + | OInt (d,i) -> args.(d) <- SInt code.ints.(i) + | OFloat (d,f) -> args.(d) <- SFloat code.floats.(f) + | OBool (d,b) -> args.(d) <- SBool b + | OBytes (d,s) | OString (d,s) -> args.(d) <- SString code.strings.(s) + | ONull d -> args.(d) <- SNull + | OAdd (d,a,b) -> args.(d) <- SOp ("+",args.(a),args.(b)) + | OSub (d,a,b) -> args.(d) <- SOp ("-",args.(a),args.(b)) + | OMul (d,a,b) -> args.(d) <- SOp ("*",args.(a),args.(b)) + | OSDiv (d,a,b) -> args.(d) <- SOp ("/",args.(a),args.(b)) + | OUDiv (d,a,b) -> args.(d) <- SOp ("//",args.(a),args.(b)) + | OSMod (d,a,b) -> args.(d) <- SOp ("%",args.(a),args.(b)) + | OUMod (d,a,b) -> args.(d) <- SOp ("%%",args.(a),args.(b)) + | OShl (d,a,b) -> args.(d) <- SOp ("<<",args.(a),args.(b)) + | OSShr (d,a,b) -> args.(d) <- SOp (">>",args.(a),args.(b)) + | OUShr (d,a,b) -> args.(d) <- SOp (">>>",args.(a),args.(b)) + | OAnd (d,a,b) -> args.(d) <- SOp ("&",args.(a),args.(b)) + | OOr (d,a,b) -> args.(d) <- SOp ("|",args.(a),args.(b)) + | OXor (d,a,b) -> args.(d) <- SOp ("^",args.(a),args.(b)) + | ONeg (d,r) -> args.(d) <- SUnop ("-",args.(r)) + | ONot (d,r) -> args.(d) <- SUnop ("!",args.(r)) + | OIncr r -> args.(r) <- SUnop ("++",args.(r)) + | ODecr r -> args.(r) <- SUnop ("++",args.(r)) + | OCall0 (d,f) -> args.(d) <- make_call (SFid f) [] + | OCall1 (d,f,a) -> args.(d) <- make_call (SFid f) [args.(a)] + | OCall2 (d,f,a,b) -> args.(d) <- make_call (SFid f) [args.(a);args.(b)] + | OCall3 (d,f,a,b,c) -> args.(d) <- make_call (SFid f) [args.(a);args.(b);args.(c)] + | OCall4 (d,f,a,b,c,k) -> args.(d) <- make_call (SFid f) [args.(a);args.(b);args.(c);args.(k)] + | OCallN (d,f,rl) -> args.(d) <- make_call (SFid f) (List.map (fun r -> args.(r)) rl) + | OCallMethod (d,fid,rl) -> args.(d) <- make_call (SMethod fid) (List.map (fun r -> args.(r)) rl) + | OCallThis (d,fid,rl) -> args.(d) <- make_call (SMethod fid) (List.map (fun r -> args.(r)) (0 :: rl)) + | OCallClosure (d,r,rl) -> args.(d) <- make_call (SClosure args.(r)) (List.map (fun r -> args.(r)) rl) + | OStaticClosure (d,fid) -> args.(d) <- SFun (fid,None) + | OInstanceClosure (d,fid,r) -> args.(d) <- SFun (fid,Some args.(r)) + | OVirtualClosure (d,r,index) -> args.(d) <- SMeth (args.(r),index) + | OGetGlobal (d,g) -> args.(d) <- SGlobal g + | OSetGlobal (g,r) -> semit (SGlobalSet (g,args.(r))) + | OField (d,r,f) -> args.(d) <- SField (args.(r),f) + | OSetField (o,f,r) -> semit (SFieldSet (args.(o),f,args.(r))) + | OGetThis (d,fid) -> args.(d) <- SField (args.(0),fid) + | OSetThis (f,r) -> semit (SFieldSet (args.(0),f,args.(r))) + | ODynGet (d,o,f) -> args.(d) <- SDField (args.(o),code.strings.(f)) + | ODynSet (o,f,v) -> semit (SFieldDSet (args.(o),code.strings.(f),args.(v))) + | OJTrue (r,_) -> semit (SJEq ("true",args.(r))) + | OJFalse (r,_) -> semit (SJEq ("false",args.(r))) + | OJNull (r,_) -> semit (SJEq ("null",args.(r))) + | OJNotNull (r,_) -> semit (SJEq ("not null",args.(r))) + | OJSLt (a,b,_) -> semit (SJComp ("<",args.(a),args.(b))) + | OJSGte (a,b,_) -> semit (SJComp (">=",args.(a),args.(b))) + | OJSGt (a,b,_) -> semit (SJComp (">",args.(a),args.(b))) + | OJSLte (a,b,_) -> semit (SJComp ("<=",args.(a),args.(b))) + | OJULt (a,b,_) -> semit (SJComp (" semit (SJComp (">=!",args.(a),args.(b))) + | OJEq (a,b,_) -> semit (SJComp ("==",args.(a),args.(b))) + | OJNotEq (a,b,_) -> semit (SJComp ("!=",args.(a),args.(b))) + | OJAlways _ -> semit SJump + | OToDyn (d,r) -> args.(d) <- SConv ("dyn",args.(r)) + | OToSFloat (d,r) -> args.(d) <- SConv ("sfloat",args.(r)) + | OToUFloat (d,r) -> args.(d) <- SConv ("ufloat",args.(r)) + | OToInt (d,r) -> args.(d) <- SConv ("int",args.(r)) + | OSafeCast (d,r) -> args.(d) <- SCast (args.(r),f.regs.(d)) + | OUnsafeCast (d,r) -> args.(d) <- SConv ("cast", args.(r)) + | OToVirtual (d,r) -> args.(d) <- SConv ("virtual",args.(r)) + | OLabel _ -> () + | ORet r -> + semit (SRet (if f.regs.(r) = HVoid then SUndef else args.(r))); + if i < b.bend then for i = 0 to Array.length args - 1 do args.(i) <- SUnreach done + | OThrow r | ORethrow r -> + semit (SThrow args.(r)); + if i < b.bend then for i = 0 to Array.length args - 1 do args.(i) <- SUnreach done + | OSwitch (r,_,_) -> semit (SSwitch args.(r)) + | ONullCheck r -> semit (SNullCheck args.(r)) + | OTrap _ | OEndTrap _ -> () + | OGetUI8 (d,b,i) -> args.(d) <- SMem (args.(b),args.(i),HUI8) + | OGetUI16 (d,b,i) -> args.(d) <- SMem (args.(b),args.(i),HUI16) + | OGetI32 (d,b,i) -> args.(d) <- SMem (args.(b),args.(i),HI32) + | OGetF32 (d,b,i) -> args.(d) <- SMem (args.(b),args.(i),HF32) + | OGetF64 (d,b,i) -> args.(d) <- SMem (args.(b),args.(i),HF64) + | OGetArray (d,b,i) -> args.(d) <- SMem (args.(b),args.(i),HArray) + | OSetUI8 (b,i,v) -> semit (SWriteMem (args.(b),args.(i),args.(v),HUI8)) + | OSetUI16 (b,i,v) -> semit (SWriteMem (args.(b),args.(i),args.(v),HUI16)) + | OSetI32 (b,i,v) -> semit (SWriteMem (args.(b),args.(i),args.(v),HI32)) + | OSetF32 (b,i,v) -> semit (SWriteMem (args.(b),args.(i),args.(v),HF32)) + | OSetF64 (b,i,v) -> semit (SWriteMem (args.(b),args.(i),args.(v),HF64)) + | OSetArray (b,i,v) -> semit (SWriteMem (args.(b),args.(i),args.(v),HArray)) + | ONew d -> + incr alloc_count; + args.(d) <- emit (SNew (f.regs.(d),!alloc_count)) + | OArraySize (d,r) -> args.(d) <- SConv ("size",args.(r)) + | OType (d,t) -> args.(d) <- SType t + | OGetType (d,r) -> args.(d) <- SConv ("type",args.(r)) + | OGetTID (d,r) -> args.(d) <- SConv ("tid",args.(r)) + | ORef (d,r) -> args.(d) <- SRef r + | OUnref (d,r) -> + (match args.(r) with + | SRef r -> args.(d) <- args.(r) + | _ -> args.(d) <- SConv ("unref",args.(r))) + | OSetref (r,v) -> + (match args.(r) with + | SRef r -> args.(r) <- args.(v) + | _ -> ()); + semit (SSetRef (args.(r),args.(v))) + | OMakeEnum (d,fid,rl) -> args.(d) <- SEnum (fid, List.map (fun r -> args.(r)) rl) + | OEnumAlloc (d,fid) -> args.(d) <- SEnum (fid, []) + | OEnumIndex (d,r) -> args.(d) <- SConv ("index",args.(r)) + | OEnumField (d,r,fid,cid) -> args.(d) <- SEnumField (args.(r),fid,cid) + | OSetEnumField (e,fid,r) -> semit (SSetEnumField (args.(e),fid,args.(r))) + | ONop _ -> () + done; + Hashtbl.add block_args b.bstart args + in + let all_blocks, _ = Hlopt.code_graph f in + let rec loop i = + if i = Array.length f.code then () else + if not (Hashtbl.mem all_blocks i) then loop (i + 1) else (* unreachable code *) + let b = try Hashtbl.find all_blocks i with Not_found -> failwith (Printf.sprintf "Missing block %s(%d)" (fundecl_name f) i) in + calc_spec b; + loop (b.bend + 1) + in + loop 0; + List.rev !out_spec diff --git a/src/generators/hlopt.ml b/src/generators/hlopt.ml new file mode 100644 index 00000000..66ee3f78 --- /dev/null +++ b/src/generators/hlopt.ml @@ -0,0 +1,834 @@ +(* + * Copyright (C)2005-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. + *) +open Hlcode + +module ISet = Set.Make(struct + let compare = Pervasives.compare + type t = int +end) + +type cur_value = + | VUndef + | VReg of int + +type reg_state = { + mutable rindex : int; + mutable ralias : reg_state; + mutable rbind : reg_state list; + mutable rnullcheck : bool; +} + +type block = { + bstart : int; + mutable bend : int; + mutable bnext : block list; + mutable bprev : block list; + mutable bloop : bool; + mutable bstate : reg_state array option; + mutable bneed : ISet.t; + mutable bneed_all : ISet.t option; + mutable bwrite : (int, int) PMap.t; +} + +type control = + | CNo + | CJCond of int + | CJAlways of int + | CTry of int + | CSwitch of int array + | CRet + | CThrow + | CLabel + +let control = function + | OJTrue (_,d) | OJFalse (_,d) | OJNull (_,d) | OJNotNull (_,d) + | OJSLt (_,_,d) | OJSGte (_,_,d) | OJSGt (_,_,d) | OJSLte (_,_,d) | OJULt (_,_,d) | OJUGte (_,_,d) | OJEq (_,_,d) | OJNotEq (_,_,d) -> + CJCond d + | OJAlways d -> + CJAlways d + | OLabel _ -> + CLabel + | ORet _ -> + CRet + | OThrow _ | ORethrow _ -> + CThrow + | OSwitch (_,cases,_) -> + CSwitch cases + | OTrap (_,d) -> + CTry d + | _ -> + CNo + +let opcode_fx frw op = + let read r = frw r true and write r = frw r false in + match op with + | OMov (d,a) | ONeg (d,a) | ONot (d,a) -> + read a; write d + | OInt (d,_) | OFloat (d,_) | OBool (d,_) | OBytes (d,_) | OString (d,_) | ONull d -> + write d + | OAdd (d,a,b) | OSub (d,a,b) | OMul (d,a,b) | OSDiv (d,a,b) | OUDiv (d,a,b) | OSMod (d,a,b)| OUMod (d,a,b) | OShl (d,a,b) | OSShr (d,a,b) | OUShr (d,a,b) | OAnd (d,a,b) | OOr (d,a,b) | OXor (d,a,b) -> + read a; read b; write d + | OIncr a | ODecr a -> + read a; write a + | OCall0 (d,_) -> + write d + | OCall1 (d,_,a) -> + read a; write d + | OCall2 (d,_,a,b) -> + read a; read b; write d + | OCall3 (d,_,a,b,c) -> + read a; read b; read c; write d + | OCall4 (d,_,a,b,c,k) -> + read a; read b; read c; read k; write d + | OCallN (d,_,rl) | OCallMethod (d,_,rl) | OCallThis (d,_,rl) -> + List.iter read rl; write d + | OCallClosure (d,f,rl) -> + read f; List.iter read rl; write d + | OStaticClosure (d,_) -> + write d + | OInstanceClosure (d, _, a) | OVirtualClosure (d,a,_) -> + read a; write d + | OGetGlobal (d,_) -> + write d + | OSetGlobal (_,a) -> + read a; + | OField (d,a,_) | ODynGet (d,a,_) -> + read a; write d + | OSetField (a,_,b) | ODynSet (a,_,b)-> + read a; read b + | OGetThis (d,_) -> + write d + | OSetThis (_,a) -> + read a + | OJTrue (r,_) | OJFalse (r,_) | OJNull (r,_) | OJNotNull (r,_) -> + read r + | OJSLt (a,b,_) | OJSGte (a,b,_) | OJSGt (a,b,_) | OJSLte (a,b,_) | OJULt (a,b,_) | OJUGte (a,b,_) | OJEq (a,b,_) | OJNotEq (a,b,_) -> + read a; read b; + | OJAlways _ | OLabel _ -> + () + | OToDyn (d, a) | OToSFloat (d,a) | OToUFloat (d,a) | OToInt (d,a) | OSafeCast (d,a) | OUnsafeCast (d,a) | OToVirtual (d,a) -> + read a; write d + | ORet r | OThrow r | ORethrow r | OSwitch (r,_,_) | ONullCheck r -> + read r + | OTrap (r,_) -> + write r + | OEndTrap _ -> + () (* ??? *) + | OGetUI8 (d,a,b) | OGetUI16 (d,a,b) | OGetI32 (d,a,b) | OGetF32 (d,a,b) | OGetF64 (d,a,b) | OGetArray (d,a,b) -> + read a; read b; write d + | OSetUI8 (a,b,c) | OSetUI16 (a,b,c) | OSetI32 (a,b,c) | OSetF32 (a,b,c) | OSetF64 (a,b,c) | OSetArray (a,b,c) -> + read a; read b; read c + | ONew d -> + write d + | OArraySize (d, a) | OGetType (d,a) | OGetTID (d,a) | ORef (d, a) | OUnref (d,a) | OSetref (d, a) | OEnumIndex (d, a) | OEnumField (d,a,_,_) -> + read a; + write d + | OType (d,_) | OEnumAlloc (d,_) -> + write d + | OMakeEnum (d,_,rl) -> + List.iter read rl; + write d + | OSetEnumField (a,_,b) -> + read a; read b + | ONop _ -> + () + +let opcode_eq a b = + match a, b with + | OType (r1,t1), OType (r2,t2) -> + r1 = r2 && t1 == t2 + | _ -> + a = b + +let opcode_map read write op = + match op with + | OMov (d,a) -> + let a = read a in + OMov (write d, a) + | ONeg (d,a) -> + let a = read a in + ONeg (write d, a) + | ONot (d,a) -> + let a = read a in + ONot (write d, a) + | OInt (d,idx) -> + OInt (write d, idx) + | OFloat (d,idx) -> + OFloat (write d, idx) + | OBool (d,idx) -> + OBool (write d, idx) + | OBytes (d,idx) -> + OBytes (write d, idx) + | OString (d,idx) -> + OString (write d, idx) + | ONull d -> + ONull (write d) + | OAdd (d,a,b) -> + let a = read a and b = read b in + OAdd (write d, a, b) + | OSub (d,a,b) -> + let a = read a and b = read b in + OSub (write d, a, b) + | OMul (d,a,b) -> + let a = read a and b = read b in + OMul (write d, a, b) + | OSDiv (d,a,b) -> + let a = read a and b = read b in + OSDiv (write d, a, b) + | OUDiv (d,a,b) -> + let a = read a and b = read b in + OUDiv (write d, a, b) + | OSMod (d,a,b) -> + let a = read a and b = read b in + OSMod (write d, a, b) + | OUMod (d,a,b) -> + let a = read a and b = read b in + OUMod (write d, a, b) + | OShl (d,a,b) -> + let a = read a and b = read b in + OShl (write d, a, b) + | OSShr (d,a,b) -> + let a = read a and b = read b in + OSShr (write d, a, b) + | OUShr (d,a,b) -> + let a = read a and b = read b in + OUShr (write d, a, b) + | OAnd (d,a,b) -> + let a = read a and b = read b in + OAnd (write d, a, b) + | OOr (d,a,b) -> + let a = read a and b = read b in + OOr (write d, a, b) + | OXor (d,a,b) -> + let a = read a and b = read b in + OXor (write d, a, b) + | OIncr a -> + OIncr (write a) + | ODecr a -> + ODecr (write a) + | OCall0 (d,f) -> + OCall0 (write d, f) + | OCall1 (d,f,a) -> + let a = read a in + OCall1 (write d, f, a) + | OCall2 (d,f,a,b) -> + let a = read a in + let b = read b in + OCall2 (write d, f, a, b) + | OCall3 (d,f,a,b,c) -> + let a = read a in + let b = read b in + let c = read c in + OCall3 (write d, f, a, b, c) + | OCall4 (w,f,a,b,c,d) -> + let a = read a in + let b = read b in + let c = read c in + let d = read d in + OCall4 (write w, f, a, b, c, d) + | OCallN (d,f,rl) -> + let rl = List.map read rl in + OCallN (write d, f, rl) + | OCallMethod (d,f,rl) -> + let rl = List.map read rl in + OCallMethod (write d, f, rl) + | OCallThis (d,f,rl) -> + let rl = List.map read rl in + OCallThis (write d, f, rl) + | OCallClosure (d,f,rl) -> + let f = read f in + let rl = List.map read rl in + OCallClosure (write d, f, rl) + | OStaticClosure (d,f) -> + OStaticClosure (write d, f) + | OInstanceClosure (d, f, a) -> + let a = read a in + OInstanceClosure (write d, f, a) + | OVirtualClosure (d,a,f) -> + let a = read a in + OVirtualClosure (write d, a, f) + | OGetGlobal (d,g) -> + OGetGlobal (write d, g) + | OSetGlobal (g,r) -> + OSetGlobal (g, read r) + | OField (d,a,f) -> + let a = read a in + OField (write d, a, f) + | ODynGet (d,a,f) -> + let a = read a in + ODynGet (write d, a, f) + | OSetField (a,f,b) -> + OSetField (read a, f, read b) + | ODynSet (a,f,b) -> + ODynSet (read a, f, read b) + | OGetThis (d,f) -> + OGetThis (write d, f) + | OSetThis (f,a) -> + OSetThis (f, read a) + | OJTrue (r,d) -> + OJTrue (read r, d) + | OJFalse (r,d) -> + OJFalse (read r, d) + | OJNull (r,d) -> + OJNull (read r, d) + | OJNotNull (r,d) -> + OJNotNull (read r, d) + | OJSLt (a,b,d) -> + OJSLt (read a, read b, d) + | OJSGte (a,b,d) -> + OJSGte (read a, read b, d) + | OJSGt (a,b,d) -> + OJSGt (read a, read b, d) + | OJSLte (a,b,d) -> + OJSLte (read a, read b, d) + | OJULt (a,b,d) -> + OJULt (read a, read b, d) + | OJUGte (a,b,d) -> + OJUGte (read a, read b, d) + | OJEq (a,b,d) -> + OJEq (read a, read b, d) + | OJNotEq (a,b,d) -> + OJNotEq (read a, read b, d) + | OJAlways _ | OLabel _ -> + op + | OToDyn (d, a) -> + let a = read a in + OToDyn (write d, a) + | OToSFloat (d,a) -> + let a = read a in + OToSFloat (write d, a) + | OToUFloat (d,a) -> + let a = read a in + OToUFloat (write d, a) + | OToInt (d,a) -> + let a = read a in + OToInt (write d, a) + | OSafeCast (d,a) -> + let a = read a in + OSafeCast (write d, a) + | OUnsafeCast (d,a) -> + let a = read a in + OUnsafeCast (write d, a) + | OToVirtual (d,a) -> + let a = read a in + OToVirtual (write d, a) + | ORet r -> + ORet (read r) + | OThrow r -> + OThrow (read r) + | ORethrow r -> + ORethrow (read r) + | OSwitch (r,cases,def) -> + OSwitch (read r, cases, def) + | ONullCheck r -> + ONullCheck (read r) + | OTrap (r,d) -> + OTrap (write r, d) + | OEndTrap _ -> + op (* ??? *) + | OGetUI8 (d,a,b) -> + let a = read a and b = read b in + OGetUI8 (write d, a, b) + | OGetUI16 (d,a,b) -> + let a = read a and b = read b in + OGetUI16 (write d, a, b) + | OGetI32 (d,a,b) -> + let a = read a and b = read b in + OGetI32 (write d, a, b) + | OGetF32 (d,a,b) -> + let a = read a and b = read b in + OGetF32 (write d, a, b) + | OGetF64 (d,a,b) -> + let a = read a and b = read b in + OGetF64 (write d, a, b) + | OGetArray (d,a,b) -> + let a = read a and b = read b in + OGetArray (write d, a, b) + | OSetUI8 (a,b,c) -> + let a = read a and b = read b and c = read c in + OSetUI8 (a, b, c) + | OSetUI16 (a,b,c) -> + let a = read a and b = read b and c = read c in + OSetUI16 (a, b, c) + | OSetI32 (a,b,c) -> + let a = read a and b = read b and c = read c in + OSetI32 (a, b, c) + | OSetF32 (a,b,c) -> + let a = read a and b = read b and c = read c in + OSetF32 (a, b, c) + | OSetF64 (a,b,c) -> + let a = read a and b = read b and c = read c in + OSetF64 (a, b, c) + | OSetArray (a,b,c) -> + let a = read a and b = read b and c = read c in + OSetArray (a, b, c) + | ONew d -> + ONew (write d) + | OArraySize (d, a) -> + let a = read a in + OArraySize (write d, a) + | OGetType (d,a) -> + let a = read a in + OGetType (write d, a) + | OGetTID (d,a) -> + let a = read a in + OGetTID (write d, a) + | ORef (d, a) -> + let a = read a in + ORef (write d, a) + | OUnref (d,a) -> + let a = read a in + OUnref (write d, a) + | OSetref (d, a) -> + let a = read a in + OSetref (write d, a) + | OEnumIndex (d, a) -> + let a = read a in + OEnumIndex (write d, a) + | OEnumField (d,a,cs,idx) -> + let a = read a in + OEnumField (write d, a, cs, idx) + | OType (d,t) -> + OType (write d, t) + | OEnumAlloc (d,e) -> + OEnumAlloc (write d, e) + | OMakeEnum (d,e,rl) -> + let rl = List.map read rl in + OMakeEnum (write d, e, rl) + | OSetEnumField (a,f,b) -> + OSetEnumField (read a, f, read b) + | ONop _ -> + op + +(* build code graph *) + +let code_graph (f:fundecl) = + let op index = f.code.(index) in + let blocks_pos = Hashtbl.create 0 in + let all_blocks = Hashtbl.create 0 in + for i = 0 to Array.length f.code - 1 do + match control (op i) with + | CJAlways d | CJCond d -> Hashtbl.replace all_blocks (i + 1 + d) true + | _ -> () + done; + let rec make_block pos = + try + Hashtbl.find blocks_pos pos + with Not_found -> + let b = { + bstart = pos; + bend = 0; + bnext = []; + bprev = []; + bloop = false; + bstate = None; + bneed = ISet.empty; + bwrite = PMap.empty; + bneed_all = None; + } in + Hashtbl.add blocks_pos pos b; + let rec loop i = + let goto d = + let b2 = make_block (i + 1 + d) in + b2.bprev <- b :: b2.bprev; + b2 + in + if i > pos && Hashtbl.mem all_blocks i then begin + b.bend <- i - 1; + b.bnext <- [goto (-1)]; + end else match control (op i) with + | CNo -> + loop (i + 1) + | CRet | CThrow -> + b.bend <- i + | CJAlways d -> + b.bend <- i; + b.bnext <- [goto d]; + | CSwitch pl -> + b.bend <- i; + b.bnext <- goto 0 :: Array.to_list (Array.map goto pl) + | CJCond d | CTry d -> + b.bend <- i; + b.bnext <- [goto 0; goto d]; + | CLabel -> + b.bloop <- true; + loop (i + 1) + in + loop pos; + b + in + blocks_pos, make_block 0 + +let optimize dump (f:fundecl) = + let nregs = Array.length f.regs in + let old_code = match dump with None -> f.code | Some _ -> Array.copy f.code in + let op index = f.code.(index) in + let set_op index op = f.code.(index) <- op in + let nop_count = ref 0 in + let set_nop index r = f.code.(index) <- (ONop r); incr nop_count in + let write str = match dump with None -> () | Some ch -> IO.nwrite ch (str ^ "\n") in + + let blocks_pos, root = code_graph f in + + let read_counts = Array.make nregs 0 in + let write_counts = Array.make nregs 0 in + let last_write = Array.make nregs (-1) in + + let bit_regs = 30 in + let stride = (nregs + bit_regs - 1) / bit_regs in + let live_bits = Array.make (Array.length f.code * stride) 0 in + + let set_live r min max = + let offset = r / bit_regs in + let mask = 1 lsl (r - offset * bit_regs) in + if min < 0 || max >= Array.length f.code then assert false; + for i=min to max do + let p = i * stride + offset in + Array.unsafe_set live_bits p ((Array.unsafe_get live_bits p) lor mask); + done; + in + let is_live r i = + let offset = r / bit_regs in + let mask = 1 lsl (r - offset * bit_regs) in + live_bits.(i * stride + offset) land mask <> 0 + in + + let read_count r = read_counts.(r) <- read_counts.(r) + 1 in + let write_count r = write_counts.(r) <- write_counts.(r) + 1 in + + let empty_state() = Array.init nregs (fun i -> + let r = { rindex = i; ralias = Obj.magic 0; rbind = []; rnullcheck = false } in + r.ralias <- r; + r + ) in + + let print_state i s = + let state_str s = + if s.ralias == s && s.rbind == [] then "" else + Printf.sprintf "%d%s[%s]" s.rindex (if s.ralias == s then "" else "=" ^ string_of_int s.ralias.rindex) (String.concat "," (List.map (fun s -> string_of_int s.rindex) s.rbind)) + in + write (Printf.sprintf "@%X %s" i (String.concat " " (Array.to_list (Array.map state_str s)))) + in + + let dstate = false in + + let rec propagate b = + let state = if b.bloop then + empty_state() + else match b.bprev with + | [] -> empty_state() + | b2 :: l -> + let s = get_state b2 in + let s = (match b2.bnext with + | [] -> assert false + | [_] -> s (* reuse *) + | _ :: l -> + let s2 = empty_state() in + for i = 0 to nregs - 1 do + let sold = s.(i) and snew = s2.(i) in + snew.ralias <- s2.(sold.ralias.rindex); + snew.rbind <- List.map (fun b -> s2.(b.rindex)) sold.rbind; + snew.rnullcheck <- sold.rnullcheck; + done; + s2 + ) in + List.iter (fun b2 -> + let s2 = get_state b2 in + for i = 0 to nregs - 1 do + let s1 = s.(i) and s2 = s2.(i) in + if s1.ralias.rindex <> s2.ralias.rindex then s1.ralias <- s1 + done; + for i = 0 to nregs - 1 do + let s1 = s.(i) and s2 = s2.(i) in + s1.rbind <- List.filter (fun s -> s.ralias == s1) s1.rbind; + s1.rnullcheck <- s1.rnullcheck && s2.rnullcheck; + (match s2.rbind with + | [] -> () + | l -> s1.rbind <- List.fold_left (fun acc sb2 -> let s = s.(sb2.rindex) in if s.ralias == s1 && not (List.memq s s1.rbind) then s :: acc else acc) s1.rbind s2.rbind) + done; + ) l; + s + in + let unalias r = + r.ralias.rbind <- List.filter (fun r2 -> r2 != r) r.ralias.rbind; + r.ralias <- r + in + let rec loop i = + let do_read r = + let w = last_write.(r) in + if w < b.bstart || w > i then begin + last_write.(r) <- i; + set_live r b.bstart i; + b.bneed <- ISet.add r b.bneed; + end else + set_live r (w + 1) i; + read_count r + in + let do_write r = + let s = state.(r) in + List.iter (fun s2 -> s2.ralias <- s2) s.rbind; + s.rbind <- []; + s.rnullcheck <- false; + last_write.(r) <- i; + b.bwrite <- PMap.add r i b.bwrite; + write_count r; + unalias s + in + if i > b.bend then () else + let op = op i in + if dstate then print_state i state; + (match op with + | OIncr r | ODecr r | ORef (_,r) -> unalias state.(r) + | OCallClosure (_,r,_) when f.regs.(r) = HDyn && (match f.regs.(state.(r).ralias.rindex) with HFun (_,rt) -> not (is_dynamic rt) | HDyn -> false | _ -> true) -> unalias state.(r) (* Issue3218.hx *) + | _ -> ()); + let op = opcode_map (fun r -> + let s = state.(r) in + s.ralias.rindex + ) (fun w -> w) op in + set_op i op; + (match op with + | OMov (d, v) when d = v -> + set_nop i "mov" + | OMov (d, v) -> + let sv = state.(v) in + let sd = state.(d) in + do_read v; + do_write d; + sd.ralias <- sv; + sd.rnullcheck <- sv.rnullcheck; + if not (List.memq sd sv.rbind) then sv.rbind <- sd :: sv.rbind; + | OIncr r | ODecr r -> + do_read r; + do_write r; + | ONullCheck r -> + let s = state.(r) in + if s.rnullcheck then set_nop i "nullcheck" else begin do_read r; s.rnullcheck <- true; end; + | _ -> + opcode_fx (fun r read -> + if read then do_read r else do_write r + ) op + ); + loop (i + 1) + in + loop b.bstart; + b.bstate <- Some state; + List.iter (fun b2 -> ignore (get_state b2)) b.bnext + + and get_state b = + match b.bstate with + | None -> + (* recurse before calculating *) + List.iter (fun b2 -> if b2.bstart < b.bstart then ignore(get_state b2)) b.bprev; + (match b.bstate with + | None -> + propagate b; + get_state b + | Some b -> b); + | Some state -> + state + in + propagate root; + + (* unreachable code *) + + let rec loop i = + if i = Array.length f.code then () else + try + let b = Hashtbl.find blocks_pos i in + loop (b.bend + 1) + with Not_found -> + (match op i with + | OEndTrap true -> () + | _ -> set_nop i "unreach"); + loop (i + 1) + in + loop 0; + + (* liveness *) + + let rec live b = + match b.bneed_all with + | Some a -> a + | None -> + let need_sub = List.fold_left (fun acc b2 -> + (* loop : first pass does not recurse, second pass uses cache *) + if b2.bloop && b2.bstart < b.bstart then (match b2.bneed_all with None -> acc | Some s -> ISet.union acc s) else + ISet.union acc (live b2) + ) ISet.empty b.bnext in + let need_sub = ISet.filter (fun r -> + try + let w = PMap.find r b.bwrite in + set_live r (w + 1) b.bend; + false + with Not_found -> + set_live r b.bstart b.bend; + true + ) need_sub in + let need = ISet.union b.bneed need_sub in + b.bneed_all <- Some need; + if b.bloop then begin + (* + if we are a loop, we need a second pass to perform fixed point + first clear the cache within the loop from backward + then rebuild the cache to make sure liveness ranges are correctly set + *) + let rec clear b2 = + match b2.bneed_all with + | Some _ when b2.bstart > b.bstart -> + b2.bneed_all <- None; + List.iter clear b2.bprev + | _ -> () + in + List.iter (fun b2 -> if b2.bstart > b.bstart then clear b2) b.bprev; + List.iter (fun b -> ignore(live b)) b.bnext; + end; + need + in + ignore(live root); + + (* nop *) + + for i=0 to Array.length f.code - 1 do + (match op i with + | OMov (d,r) when not (is_live d (i + 1)) -> + let n = read_counts.(r) - 1 in + read_counts.(r) <- n; + write_counts.(d) <- write_counts.(d) - 1; + set_nop i "unused" + | _ -> ()); + done; + + (* reg map *) + + let used_regs = ref 0 in + let reg_map = read_counts in + let nargs = (match f.ftype with HFun (args,_) -> List.length args | _ -> assert false) in + for i=0 to nregs-1 do + if read_counts.(i) > 0 || write_counts.(i) > 0 || i < nargs then begin + reg_map.(i) <- !used_regs; + incr used_regs; + end else + reg_map.(i) <- -1; + done; + let reg_remap = !used_regs <> nregs in + + (* done *) + if dump <> None then begin + let rec loop i block = + if i = Array.length f.code then () else + let block = try + let b = Hashtbl.find blocks_pos i in + write (Printf.sprintf "\t----- [%s] (%X)" + (String.concat "," (List.map (fun b -> Printf.sprintf "%X" b.bstart) b.bnext)) + b.bend + ); + let need = String.concat "," (List.map string_of_int (ISet.elements b.bneed)) in + let wr = String.concat " " (List.rev (PMap.foldi (fun r p acc -> Printf.sprintf "r%d:%X" r p :: acc) b.bwrite [])) in + write ("\t" ^ (if b.bloop then "LOOP " else "") ^ "NEED=" ^ need ^ "\tWRITE=" ^ wr); + b + with Not_found -> + block + in + let old = old_code.(i) in + let op = op i in + let rec live_loop r l = + if r = nregs then List.rev l else + live_loop (r + 1) (if is_live r i then r :: l else l) + in + let live = "LIVE=" ^ String.concat "," (List.map string_of_int (live_loop 0 [])) in + write (Printf.sprintf "\t@%-3X %-20s %-20s%s" i (ostr string_of_int old) (if opcode_eq old op then "" else ostr string_of_int op) live); + loop (i + 1) block + in + write (Printf.sprintf "%s@%d" (fundecl_name f) f.findex); + if reg_remap then begin + for i=0 to nregs-1 do + write (Printf.sprintf "\tr%-2d %-10s%s" i (tstr f.regs.(i)) (if reg_map.(i) < 0 then " unused" else if reg_map.(i) = i then "" else Printf.sprintf " r%-2d" reg_map.(i))) + done; + end; + loop 0 root; + write ""; + write ""; + (match dump with None -> () | Some ch -> IO.flush ch); + end; + + (* remap *) + + let code = ref f.code in + let regs = ref f.regs in + let debug = ref f.debug in + + if !nop_count > 0 || reg_remap then begin + let new_pos = Array.make (Array.length f.code) 0 in + let jumps = ref [] in + let out_pos = ref 0 in + let out_code = Array.make (Array.length f.code - !nop_count) (ONop "") in + let new_debug = Array.make (Array.length f.code - !nop_count) (0,0) in + Array.iteri (fun i op -> + Array.unsafe_set new_pos i !out_pos; + match op with + | ONop _ -> () + | _ -> + (match op with + | OJTrue _ | OJFalse _ | OJNull _ | OJNotNull _ | OJSLt _ | OJSGte _ | OJSGt _ | OJSLte _ | OJULt _ | OJUGte _ | OJEq _ | OJNotEq _ | OJAlways _ | OSwitch _ | OTrap _ -> + jumps := i :: !jumps + | _ -> ()); + let op = if reg_remap then opcode_map (fun r -> reg_map.(r)) (fun r -> reg_map.(r)) op else op in + out_code.(!out_pos) <- op; + new_debug.(!out_pos) <- f.debug.(i); + incr out_pos + ) f.code; + List.iter (fun j -> + let pos d = + new_pos.(j + 1 + d) - new_pos.(j + 1) + in + let p = new_pos.(j) in + out_code.(p) <- (match out_code.(p) with + | OJTrue (r,d) -> OJTrue (r,pos d) + | OJFalse (r,d) -> OJFalse (r,pos d) + | OJNull (r,d) -> OJNull (r, pos d) + | OJNotNull (r,d) -> OJNotNull (r, pos d) + | OJSLt (a,b,d) -> OJSLt (a,b,pos d) + | OJSGte (a,b,d) -> OJSGte (a,b,pos d) + | OJSLte (a,b,d) -> OJSLte (a,b,pos d) + | OJSGt (a,b,d) -> OJSGt (a,b,pos d) + | OJULt (a,b,d) -> OJULt (a,b,pos d) + | OJUGte (a,b,d) -> OJUGte (a,b,pos d) + | OJEq (a,b,d) -> OJEq (a,b,pos d) + | OJNotEq (a,b,d) -> OJNotEq (a,b,pos d) + | OJAlways d -> OJAlways (pos d) + | OSwitch (r,cases,send) -> OSwitch (r, Array.map pos cases, pos send) + | OTrap (r,d) -> OTrap (r,pos d) + | _ -> assert false) + ) !jumps; + code := out_code; + debug := new_debug; + if reg_remap then begin + let new_regs = Array.make !used_regs HVoid in + for i=0 to nregs-1 do + let p = reg_map.(i) in + if p >= 0 then new_regs.(p) <- f.regs.(i) + done; + regs := new_regs; + end; + end; + + { f with code = !code; regs = !regs; debug = !debug } \ No newline at end of file diff --git a/src/globals.ml b/src/globals.ml new file mode 100644 index 00000000..11d06d91 --- /dev/null +++ b/src/globals.ml @@ -0,0 +1,64 @@ +type pos = { + pfile : string; + pmin : int; + pmax : int; +} + +module IntMap = Map.Make(struct type t = int let compare a b = a - b end) +module StringMap = Map.Make(struct type t = string let compare = String.compare end) + +type platform = + | Cross + | Js + | Lua + | Neko + | Flash + | Php + | Cpp + | Cs + | Java + | Python + | Hl + +let version = 3400 +let version_major = version / 1000 +let version_minor = (version mod 1000) / 100 +let version_revision = (version mod 100) +let version_is_stable = version_minor land 1 = 0 + +let macro_platform = ref Neko + +let is_windows = Sys.os_type = "Win32" || Sys.os_type = "Cygwin" + +let s_version = + Printf.sprintf "%d.%d.%d%s" version_major version_minor version_revision (match Version.version_extra with None -> "" | Some v -> " " ^ v) + +let platforms = [ + Js; + Lua; + Neko; + Flash; + Php; + Cpp; + Cs; + Java; + Python; + Hl; +] + +let platform_name = function + | Cross -> "cross" + | Js -> "js" + | Lua -> "lua" + | Neko -> "neko" + | Flash -> "flash" + | Php -> "php" + | Cpp -> "cpp" + | Cs -> "cs" + | Java -> "java" + | Python -> "python" + | Hl -> "hl" + +let null_pos = { pfile = "?"; pmin = -1; pmax = -1 } + +let s_type_path (p,s) = match p with [] -> s | _ -> String.concat "." p ^ "." ^ s \ No newline at end of file diff --git a/src/json.ml b/src/json.ml new file mode 100644 index 00000000..550d9b08 --- /dev/null +++ b/src/json.ml @@ -0,0 +1,104 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +type t = + | JString of string + | JFloat of float + | JInt of int + | JObject of (string * t) list + | JArray of t list + | JBool of bool + | JNull + +let write_iter f_el f_sep l = + let rec rest = function + | [] -> () + | v :: l -> + f_sep(); + f_el v; + rest l + in + match l with + | [] -> () + | v :: l -> + f_el v; + rest l + +let write_sep w = + w "," + +let rec write_json w v = + match v with + | JNull -> write_null w + | JBool b -> write_bool w b + | JString s -> write_string w s + | JFloat f -> write_float w f + | JInt i -> write_int w i + | JObject o -> write_object w o + | JArray a -> write_array w a + +and write_null w = + w "null" + +and write_bool w b = + w (if b then "true" else "false") + +and write_string w s = + w "\""; + let b = Buffer.create (String.length s) in + for i = 0 to String.length s - 1 do + match String.unsafe_get s i with + | '"' -> Buffer.add_string b "\\\"" + | '\t' -> Buffer.add_string b "\\t" + | '\r' -> Buffer.add_string b "\\r" + | '\b' -> Buffer.add_string b "\\b" + | '\n' -> Buffer.add_string b "\\n" + | '\012' -> Buffer.add_string b "\\f" + | '\\' -> Buffer.add_string b "\\\\" + | '\x00'..'\x1F' | '\x7F' as c -> Buffer.add_string b (Printf.sprintf "\\u%04X" (int_of_char c)) + | c -> Buffer.add_char b c + done; + w (Buffer.contents b); + w "\"" + +and write_int w i = + w (string_of_int i) + +and write_float w f = + match classify_float f with + | FP_nan | FP_infinite -> failwith "NaN and infinity floats are unsupported in JSON" + | _ -> + let s = Printf.sprintf "%.16g" f in + let s = if float_of_string s = f then s else Printf.sprintf "%.17g" f in + w s + +and write_array w a = + w "["; + write_iter (write_json w) (fun() -> write_sep w) a; + w "]" + +and write_object w o = + let write_el (k, v) = + write_string w k; + w ":"; + write_json w v + in + w "{"; + write_iter write_el (fun() -> write_sep w) o; + w "}" diff --git a/src/macro/hlmacro.ml b/src/macro/hlmacro.ml new file mode 100644 index 00000000..ddd4b8a5 --- /dev/null +++ b/src/macro/hlmacro.ml @@ -0,0 +1,554 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) +open Globals +open Type +open Ast +open Hlcode +open Hlinterp +open MacroApi + +type value = Hlinterp.value + +type context = { + com : Common.context; (* macro one *) + mutable gen : Genhl.context option; + interp : Hlinterp.context; + types : (Type.path,int) Hashtbl.t; + cached_protos : (obj_type, (virtual_proto * vfield array)) Hashtbl.t; + cached_enums : (enum_type, ttype) Hashtbl.t; + mutable curapi : value MacroApi.compiler_api; + mutable has_error : bool; +} + +exception Error of string * Globals.pos list + +let debug = true (* TODO !!! set to false for speed++ ! *) + +let get_ctx_ref = ref (fun() -> assert false) +let get_ctx() : context = (!get_ctx_ref)() +let macro_lib = Hashtbl.create 0 +let interp() = (get_ctx()).interp + +let setup get_api = + let api = get_api (fun() -> (get_ctx()).curapi.get_com()) (fun() -> (get_ctx()).curapi) in + List.iter (fun (n,v) -> Hashtbl.replace macro_lib n (match v with VClosure (FNativeFun (_,v,_),None) -> v | _ -> assert false)) api; + Globals.macro_platform := Globals.Hl + +let select ctx = + get_ctx_ref := (fun() -> ctx) + +let error_handler ctx v stack = + let make_pos st = + let file, line = Hlinterp.make_stack ctx.interp st in + let low = line land 0xFFFFF in + { + Globals.pfile = file; + Globals.pmin = low; + Globals.pmax = low + (line lsr 20); + } + in + (*let rec loop o = + if o == ctx.error_proto then true else match o.oproto with None -> false | Some p -> loop p + in + (match v with + | VObject o when loop o -> + (match get_field o (hash "message"), get_field o (hash "pos") with + | VObject msg, VAbstract (APos pos) -> + (match get_field msg h_s with + | VString msg -> raise (Error.Error (Error.Custom msg,pos)) + | _ -> ()); + | _ -> ()); + | _ -> ());*) + raise (Error (Hlinterp.vstr ctx.interp v Hlcode.HDyn,List.map make_pos stack)) + +let create com api = + let ctx = { + com = com; + gen = None; + interp = Hlinterp.create debug; + curapi = api; + types = Hashtbl.create 0; + has_error = false; + cached_protos = Hashtbl.create 0; + cached_enums = Hashtbl.create 0; + } in + select ctx; + Hlinterp.set_error_handler ctx.interp (error_handler ctx); + Hlinterp.set_macro_api ctx.interp (fun name -> try Some (Hashtbl.find macro_lib name) with Not_found -> None); + ctx + +let init ctx = + if ctx.gen = None then ctx.gen <- Some (Genhl.create_context ctx.com true false) + +let set_error ctx e = + ctx.has_error <- e + +let add_types ctx types ready = + let types = List.filter (fun t -> match t with + | TAbstractDecl a when not (Meta.has Meta.CoreType a.a_meta) -> + (* A @:native on an abstract causes the implementation class and the abstract + to have the same path. Let's skip all abstracts so this doesn't matter. *) + false + | _ -> + let path = Type.t_path t in + if Hashtbl.mem ctx.types path then false else begin + Hashtbl.add ctx.types path (Type.t_infos t).mt_module.m_id; + true; + end + ) types in + List.iter ready types; + if ctx.gen = None then init ctx; + match ctx.gen with + | None -> assert false + | Some gen -> + Genhl.add_types gen types; + if debug then Genhl.check gen; + let code = Genhl.build_code gen types None in + if debug then begin + try + Hlinterp.check code true + with Failure _ | Common.Abort _ as exn -> + let ch = open_out_bin "hlcode.txt" in + Hlcode.dump (fun s -> output_string ch (s ^ "\n")) code; + close_out ch; + raise exn + end; + Hlinterp.add_code ctx.interp code + +let do_reuse ctx api = + ctx.curapi <- api + +let can_reuse ctx types = + let has_old_version t = + let inf = Type.t_infos t in + try + Hashtbl.find ctx.types inf.mt_path <> inf.mt_module.m_id + with Not_found -> + false + in + not (List.exists has_old_version types) + +let catch_errors ctx ?(final=(fun() -> ())) f = + let prev = get_ctx() in (* switch context in case we have an older one, see #5676 *) + select ctx; + try + let v = f() in + final(); + select prev; + Some v + with Error _ as e -> + final(); + select prev; + raise e + | Abort -> + final(); + select prev; + None + +let call_path ctx cpath (f:string) args api = + if ctx.has_error then + None + else let old = ctx.curapi in + ctx.curapi <- api; + let gid = Genhl.resolve_class_global (match ctx.gen with None -> assert false | Some ctx -> ctx) (String.concat "." cpath) in + let gval = ctx.interp.Hlinterp.t_globals.(gid) in + let fval = Hlinterp.dyn_get_field ctx.interp gval f Hlcode.HDyn in + match fval with + | Hlinterp.VClosure (f,None) -> + catch_errors ~final:(fun() -> ctx.curapi <- old) ctx (fun() -> call_wrap ctx.interp f args) + | _ -> + prerr_endline (Hlinterp.vstr_d ctx.interp gval); + assert false + +let vnull = VNull +let vbool b = VBool b +let vint i = VInt (Int32.of_int i) +let vint32 i = VInt i +let vfloat f = VFloat f + +let vfun0 f = + let callb args = match args with [] -> f() | _ -> assert false in + VClosure(FNativeFun ("fun0",callb,HVoid), None) + +let vfun1 f = + let callb args = match args with [a] -> f a | _ -> assert false in + VClosure(FNativeFun ("fun1",callb,HVoid), None) + +let vfun2 f = + let callb args = match args with [a;b] -> f a b | _ -> assert false in + VClosure(FNativeFun ("fun2",callb,HVoid), None) + +let vfun3 f = + let callb args = match args with [a;b;c] -> f a b c | _ -> assert false in + VClosure(FNativeFun ("fun3",callb,HVoid), None) + +let vfun4 f = + let callb args = match args with [a;b;c;d] -> f a b c d | _ -> assert false in + VClosure(FNativeFun ("fun4",callb,HVoid), None) + +let vfun5 f = + let callb args = match args with [a;b;c;d;e] -> f a b c d e | _ -> assert false in + VClosure(FNativeFun ("fun5",callb,HVoid), None) + +let exc_string msg = + Hlinterp.throw_msg (interp()) msg + +let compiler_error msg pos = + assert false (* TODO : raise haxe.macro.Error(msg,pos) *) + +let eval_expr ctx (e:texpr) = + assert false + +let eval_delayed _ _ = + assert false (* macro - in - macro *) + +let prepare_callback f n = + assert false + +let encode_pos p = VAbstract (APos p) + +let decode_pos = function + | VAbstract (APos p) -> p + | _ -> raise Invalid_expr + +let last_enum_type = ref IExpr + +let encode_enum t pos tag pl = + last_enum_type := t; + match pos with + | None -> VEnum (tag,Array.of_list pl) + | Some p -> VEnum (tag,Array.of_list (List.rev (encode_pos p :: List.rev pl))) + +let decode_enum = function + | VEnum (tag,arr) -> tag, Array.to_list arr + | _ -> raise Invalid_expr + +let decode_enum_with_pos = function + | VEnum (tag,arr) when Array.length arr > 0 && (match arr.(Array.length arr - 1) with VAbstract (APos _) -> true | _ -> false) -> + let rec loop i = + if i = Array.length arr - 1 then [] else arr.(i) :: loop (i + 1) + in + (tag, loop 0), decode_pos arr.(Array.length arr - 1) + | e -> + decode_enum e, Globals.null_pos + + +let encode_tdecl t = VAbstract (ATDecl t) +let encode_unsafe o = VAbstract (AUnsafe o) + +let decode_unsafe = function + | VAbstract (AUnsafe v) -> v + | _ -> raise Invalid_expr + +let decode_tdecl = function + | VAbstract (ATDecl t) -> t + | _ -> raise Invalid_expr + +let dec_int = function + | VInt i -> Int32.to_int i + | _ -> raise Invalid_expr + +let dec_i32 = function + | VInt i -> i + | _ -> raise Invalid_expr + +let dec_bool = function + | VBool b -> b + | _ -> raise Invalid_expr + +let field o n = + match o with + | VDynObj _ | VVirtual _ | VObj _ -> Hlinterp.dyn_get_field (interp()) o n HDyn + | _ -> raise Invalid_expr + +let dec_string = function + | VObj { ofields = [|VBytes s;VInt _|] } -> Hlinterp.hl_to_caml s + | _ -> raise Invalid_expr + +let dec_array = function + | VObj { ofields = [|VInt len;VArray (arr,_)|] } -> + let len = Int32.to_int len in + let rec loop i = + if i = len then [] else arr.(i) :: loop (i+1) + in + loop 0 + | v -> + raise Invalid_expr + +let encode_lazytype f t = VAbstract (ALazyType (f,t)) + +let decode_lazytype = function + | VAbstract (ALazyType (t,_)) -> t + | _ -> raise Invalid_expr + +let enc_obj t fields = + match t with + | OMetaAccess -> + let h = Hashtbl.create 0 in + let rec loop i = function + | [] -> () + | (n,_) :: l -> + Hashtbl.add h n i; + loop (i + 1) l + in + loop 0 fields; + let values = Array.of_list (List.map snd fields) in + VDynObj { + dfields = h; + dvalues = values; + dtypes = Array.make (Array.length values) HDyn; + dvirtuals = []; + } + | _ -> + let ctx = get_ctx() in + let to_str (name,f) = + match f with + | None -> name + | Some f -> name ^ "." ^ f + in + let vp, idx = try + Hashtbl.find ctx.cached_protos t + with Not_found -> + let name, field = proto_name t in + let gen = (match ctx.gen with None -> assert false | Some gen -> gen) in + let vt = (try + let t = Hashtbl.find gen.Genhl.macro_typedefs name in + (match t, field with + | _, None -> t + | HVirtual v, Some f -> + let idx = (try PMap.find f v.vindex with Not_found -> failwith (name ^ " has no field definition " ^ f)) in + let _,_, t = v.vfields.(idx) in + (match t with + | HVirtual _ -> t + | _ -> failwith ("Unexpected type " ^ tstr t ^ " for definition " ^ to_str (name,field))) + | _ -> + assert false + ) + with Not_found -> try + let t = PMap.find (["haxe";"macro"],name) gen.Genhl.cached_types in + (match t, field with + | HEnum e, Some f -> + let rec loop i = + if i = Array.length e.efields then raise Not_found; + let n, _, tl = e.efields.(i) in + if n = f then + tl.(0) + else + loop (i + 1) + in + loop 0 + | _ -> + failwith ("Unexpected type " ^ tstr t ^ " for definition " ^ to_str (name,field))) + with Not_found -> + failwith ("Macro definition missing " ^ to_str (name,field)) + ) in + match vt with + | HVirtual vp -> + let vindexes = Array.map (fun (n,_,_) -> + let rec loop i = function + | [] -> VFNone + | (n2,_) :: _ when n = n2 -> VFIndex i + | _ :: l -> loop (i + 1) l + in + loop 0 fields + ) vp.vfields in + Hashtbl.replace ctx.cached_protos t (vp, vindexes); + vp, vindexes + | _ -> + failwith (to_str (name,field) ^ " returned invalid type " ^ tstr vt) + in + if debug then begin + let farr = Array.of_list fields in + Array.iteri (fun i idx -> + let name, _ ,_ = vp.vfields.(i) in + match idx with + | VFNone -> + if List.mem_assoc name fields then failwith ("Field " ^ name ^ " is present in " ^ to_str (proto_name t)) + | VFIndex i when i >= Array.length farr -> + failwith ("Missing field " ^ name ^ " of " ^ to_str (proto_name t)) + | VFIndex i when fst farr.(i) <> name -> + failwith ("Field " ^ name ^ " of " ^ to_str (proto_name t) ^ " is wrongly mapped on " ^ fst farr.(i)) + | _ -> + () + ) idx; + List.iter (fun (n,_) -> + if n <> "name_pos" && not (PMap.mem n vp.vindex) then failwith ("Field " ^ n ^ " has data but is not part of type " ^ to_str (proto_name t)); + ) fields; + end; + VVirtual { + vtype = vp; + vindexes = idx; + vtable = Array.map snd (Array.of_list fields); + vvalue = VNull; + } + +let enc_inst path fields = + let ctx = get_ctx() in + let t = (match ctx.gen with None -> assert false | Some gen -> try Genhl.resolve_type gen path with Not_found -> assert false) in + match t with + | HObj o -> + let proto, _, _ = Hlinterp.get_proto ctx.interp o in + VObj { oproto = proto; ofields = fields } + | _ -> + assert false + +let enc_string s = + enc_inst ([],"String") [|VBytes (caml_to_hl s);VInt (Int32.of_int (String.length s))|] + +let enc_array vl = + let arr = Array.of_list (List.map (fun v -> + match v with + | VNull | VObj _ | VVirtual _ -> v + | VEnum _ -> + let ctx = get_ctx() in + let et = !last_enum_type in + let t = try + Hashtbl.find ctx.cached_enums et + with Not_found -> + let name = enum_name et in + let t = (match ctx.gen with + | None -> assert false + | Some gen -> try PMap.find (["haxe";"macro"],name) gen.Genhl.cached_types with Not_found -> failwith ("Missing enum type " ^ name) + ) in + Hashtbl.replace ctx.cached_enums et t; + t + in + VDyn (v,t) + | _ -> failwith "Invalid array value" + ) vl) in + enc_inst (["hl";"types"],"ArrayObj") [|VInt (Int32.of_int (Array.length arr));VArray (arr,HDyn)|] + +let encode_bytes s = + enc_inst (["haxe";"io"],"Bytes") [|VInt (Int32.of_int (String.length s)); VBytes s|] + +let encode_string_map convert pmap = + let h = Hashtbl.create 0 in + PMap.iter (fun k v -> Hashtbl.add h k (convert v)) pmap; + enc_inst (["haxe";"ds"],"StringMap") [|VAbstract (AHashBytes h)|] + +let decode_bytes = function + | VObj { ofields = [|VInt _;VBytes s|] } -> s + | _ -> raise Invalid_expr + +let encode_ref v convert tostr = + let h = Hashtbl.create 0 in + Hashtbl.add h "get" 0; + Hashtbl.add h "__string" 1; + Hashtbl.add h "toString" 2; + Hashtbl.add h "$" 3; + VDynObj { + dfields = h; + dvalues = [| + vfun0 (fun() -> convert v); + vfun0 (fun() -> VBytes (caml_to_hl (tostr()))); + vfun0 (fun() -> enc_string (tostr())); + VAbstract (AUnsafe (Obj.repr v)) + |]; + dtypes = [| + HFun ([],HDyn); + HFun ([],HBytes); + HFun ([],HDyn); + HDyn; + |]; + dvirtuals = []; + } + +let decode_ref v : 'a = + match field v "$" with + | VAbstract (AUnsafe t) -> Obj.obj t + | _ -> raise Invalid_expr + +let value_string v = + Hlinterp.vstr (get_ctx()).interp v HDyn + +let value_signature v = + failwith "signature() not supported in HL macros" + +let value_to_expr v p = + let ctx = get_ctx() in + let error v = failwith ("Unsupported value " ^ vstr ctx.interp v Hlcode.HDyn) in + (* + let h_enum = hash "__enum__" and h_et = hash "__et__" and h_ct = hash "__ct__" in + let h_tag = hash "tag" and h_args = hash "args" in + let h_length = hash "length" in + let make_path t = + let rec loop = function + | [] -> assert false + | [name] -> (Ast.EConst (Ast.Ident name),p) + | name :: l -> (Ast.EField (loop l,name),p) + in + let t = t_infos t in + loop (List.rev (if t.mt_module.m_path = t.mt_path then fst t.mt_path @ [snd t.mt_path] else fst t.mt_module.m_path @ [snd t.mt_module.m_path;snd t.mt_path])) + in*) + let rec loop = function + | VNull -> (Ast.EConst (Ast.Ident "null"),p) + | VBool b -> (Ast.EConst (Ast.Ident (if b then "true" else "false")),p) + | VInt i -> (Ast.EConst (Ast.Int (Int32.to_string i)),p) + | VFloat f -> + let std = (Ast.EConst (Ast.Ident "std"), p) in + let math = (Ast.EField (std, "Math"), p) in + if (f = infinity) then + (Ast.EField (math, "POSITIVE_INFINITY"), p) + else if (f = neg_infinity) then + (Ast.EField (math, "NEGATIVE_INFINITY"), p) + else if (f <> f) then + (Ast.EField (math, "NaN"), p) + else + (Ast.EConst (Ast.Float (Common.float_repres f)), p) + | VAbstract (APos p) -> + (Ast.EObjectDecl ( + (("fileName",Globals.null_pos) , (Ast.EConst (Ast.String p.Globals.pfile) , p)) :: + (("lineNumber",Globals.null_pos) , (Ast.EConst (Ast.Int (string_of_int (Lexer.get_error_line p))),p)) :: + (("className",Globals.null_pos) , (Ast.EConst (Ast.String ("")),p)) :: + [] + ), p) + | VObj { oproto = { pclass = { pname = "String" } }; ofields = [|VBytes content;VInt _|] } -> + (Ast.EConst (Ast.String (hl_to_caml content)),p) + | v -> + error v + (* + | VObject o as v -> + match o.oproto with + | None -> + (match get_field_opt o h_ct with + | Some (VAbstract (ATDecl t)) -> + make_path t + | _ -> + let fields = List.fold_left (fun acc (fid,v) -> ((field_name ctx fid,Globals.null_pos), loop v) :: acc) [] (Array.to_list o.ofields) in + (Ast.EObjectDecl fields, p)) + | Some proto -> + match get_field_opt proto h_enum, get_field_opt o h_a, get_field_opt o h_s, get_field_opt o h_length with + | _, Some (VArray a), _, Some (VInt len) -> + (Ast.EArrayDecl (List.map loop (Array.to_list (Array.sub a 0 len))),p) + | Some (VObject en), _, _, _ -> + (match get_field en h_et, get_field o h_tag with + | VAbstract (ATDecl t), VString tag -> + let e = (Ast.EField (make_path t,tag),p) in + (match get_field_opt o h_args with + | Some (VArray args) -> + let args = List.map loop (Array.to_list args) in + (Ast.ECall (e,args),p) + | _ -> e) + | _ -> + error v) + | _ -> + error v + *) + in + loop v diff --git a/interp.ml b/src/macro/interp.ml similarity index 50% rename from interp.ml rename to src/macro/interp.ml index 492b909b..eb7b7e37 100644 --- a/interp.ml +++ b/src/macro/interp.ml @@ -1,29 +1,28 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) +open Globals open Common open Nast open Unix open Type +open MacroApi (* ---------------------------------------------------------------------- *) (* TYPES *) @@ -52,7 +51,7 @@ and vabstract = | AHash of (value, value) Hashtbl.t | ARandom of Random.State.t ref | ABuffer of Buffer.t - | APos of Ast.pos + | APos of Globals.pos | AFRead of (in_channel * bool ref) | AFWrite of out_channel | AReg of regexp @@ -62,7 +61,7 @@ and vabstract = | ASocket of Unix.file_descr | ATDecl of module_type | AUnsafe of Obj.t - | ALazyType of (unit -> Type.t) ref + | ALazyType of ((unit -> Type.t) ref) * (unit -> value) | ANekoAbstract of Extc.value | ANekoBuffer of value | ACacheRef of value @@ -80,9 +79,9 @@ and vfunction = | FunVar of (value list -> value) and regexp = { - r : Str.regexp; + r : Pcre.regexp; mutable r_string : string; - mutable r_groups : (int * int) option array; + mutable r_groups : int array; } and zlib = { @@ -96,41 +95,6 @@ type cmp = | CInf | CUndef -type extern_api = { - pos : Ast.pos; - get_com : unit -> Common.context; - get_type : string -> Type.t option; - get_module : string -> Type.t list; - on_generate : (Type.t list -> unit) -> unit; - after_generate : (unit -> unit) -> unit; - on_type_not_found : (string -> value) -> unit; - parse_string : string -> Ast.pos -> bool -> Ast.expr; - type_expr : Ast.expr -> Type.texpr; - store_typed_expr : Type.texpr -> Ast.expr; - get_display : string -> string; - allow_package : string -> unit; - type_patch : string -> string -> bool -> string option -> unit; - meta_patch : string -> string -> string option -> bool -> unit; - set_js_generator : (value -> unit) -> unit; - get_local_type : unit -> t option; - get_expected_type : unit -> t option; - get_call_arguments : unit -> Ast.expr list option; - get_local_method : unit -> string; - get_local_using : unit -> tclass list; - get_local_vars : unit -> (string, Type.tvar) PMap.t; - get_build_fields : unit -> value; - get_pattern_locals : Ast.expr -> Type.t -> (string,Type.tvar * Ast.pos) PMap.t; - define_type : value -> unit; - define_module : string -> value list -> ((string * Ast.pos) list * Ast.import_mode) list -> Ast.type_path list -> unit; - module_dependency : string -> string -> bool -> unit; - current_module : unit -> module_def; - delayed_macro : int -> (unit -> (unit -> value)); - use_cache : unit -> bool; - format_string : string -> Ast.pos -> Ast.expr; - cast_or_unify : Type.t -> texpr -> Ast.pos -> Type.texpr; - add_global_metadata : string -> string -> (bool * bool * bool) -> unit; -} - type callstack = { cpos : pos; cthis : value; @@ -160,9 +124,7 @@ type context = { mutable vthis : value; mutable venv : value array; (* context *) - mutable curapi : extern_api; - mutable on_reused : (unit -> bool) list; - mutable is_reused : bool; + mutable curapi : value MacroApi.compiler_api; (* eval *) mutable locals_map : (string, int) PMap.t; mutable locals_count : int; @@ -182,65 +144,35 @@ type access = exception Runtime of value exception Builtin_error -exception Error of string * Ast.pos list +exception Error of string * Globals.pos list -exception Abort exception Continue exception Break of value exception Return of value -exception Invalid_expr exception Sys_exit of int (* ---------------------------------------------------------------------- *) (* UTILS *) let get_ctx_ref = ref (fun() -> assert false) -let encode_complex_type_ref = ref (fun t -> assert false) -let encode_type_ref = ref (fun t -> assert false) -let decode_type_ref = ref (fun t -> assert false) -let encode_expr_ref = ref (fun e -> assert false) -let decode_expr_ref = ref (fun e -> assert false) -let encode_texpr_ref = ref (fun e -> assert false) -let decode_texpr_ref = ref (fun e -> assert false) -let encode_clref_ref = ref (fun c -> assert false) -let enc_hash_ref = ref (fun h -> assert false) -let enc_array_ref = ref (fun l -> assert false) -let dec_array_ref = ref (fun v -> assert false) -let enc_string_ref = ref (fun s -> assert false) -let make_ast_ref = ref (fun _ -> assert false) -let make_complex_type_ref = ref (fun _ -> assert false) -let encode_tvar_ref = ref (fun _ -> assert false) -let decode_path_ref = ref (fun _ -> assert false) -let decode_import_ref = ref (fun _ -> assert false) let get_ctx() = (!get_ctx_ref)() -let enc_array (l:value list) : value = (!enc_array_ref) l -let dec_array (l:value) : value list = (!dec_array_ref) l -let encode_complex_type (t:Ast.complex_type) : value = (!encode_complex_type_ref) t -let encode_type (t:Type.t) : value = (!encode_type_ref) t -let decode_type (v:value) : Type.t = (!decode_type_ref) v -let encode_expr (e:Ast.expr) : value = (!encode_expr_ref) e -let decode_expr (e:value) : Ast.expr = (!decode_expr_ref) e -let encode_texpr (e:Type.texpr) : value = (!encode_texpr_ref) e -let decode_texpr (v:value) : Type.texpr = (!decode_texpr_ref) v -let encode_clref (c:tclass) : value = (!encode_clref_ref) c -let enc_hash (h:('a,'b) Hashtbl.t) : value = (!enc_hash_ref) h -let make_ast (e:texpr) : Ast.expr = (!make_ast_ref) e -let enc_string (s:string) : value = (!enc_string_ref) s -let make_complex_type (t:Type.t) : Ast.complex_type = (!make_complex_type_ref) t -let encode_tvar (v:tvar) : value = (!encode_tvar_ref) v -let decode_path (v:value) : Ast.type_path = (!decode_path_ref) v -let decode_import (v:value) : ((string * Ast.pos) list * Ast.import_mode) = (!decode_import_ref) v let to_int f = Int32.of_float (mod_float f 2147483648.0) let need_32_bits i = Int32.compare (Int32.logand (Int32.add i 0x40000000l) 0x80000000l) Int32.zero <> 0 let best_int i = if need_32_bits i then VInt32 i else VInt (Int32.to_int i) +let macro_lib = Hashtbl.create 0 + +let setup get_api = + let api = get_api (fun() -> (get_ctx()).curapi.get_com()) (fun() -> (get_ctx()).curapi) in + List.iter (fun (n,v) -> Hashtbl.replace macro_lib n (match v with VFunction v -> v | _ -> assert false)) api + let make_pos p = let low = p.pline land 0xFFFFF in { - Ast.pfile = p.psource; - Ast.pmin = low; - Ast.pmax = low + (p.pline lsr 20); + Globals.pfile = p.psource; + Globals.pmin = low; + Globals.pmax = low + (p.pline lsr 20); } let warn ctx msg p = @@ -276,8 +208,8 @@ let constants = "$";"add";"remove";"has";"__t";"module";"isPrivate";"isPublic";"isExtern";"isInterface";"exclude"; "constructs";"names";"superClass";"interfaces";"fields";"statics";"constructor";"init";"t"; "gid";"uid";"atime";"mtime";"ctime";"dev";"ino";"nlink";"rdev";"size";"mode";"pos";"len"; - "binops";"unops";"from";"to";"array";"op";"isPostfix";"impl"; - "id";"capture";"extra";"v";"ids";"vars";"en";"overrides";"status"]; + "binops";"unops";"from";"to";"array";"op";"isPostfix";"impl";"resolve"; + "id";"capture";"extra";"v";"ids";"vars";"en";"overrides";"status";"overloads";"path";"namePos"]; h let h_get = hash "__get" and h_set = hash "__set" @@ -294,6 +226,25 @@ and h_class = hash "__class__" let exc v = raise (Runtime v) +let exc_string str = + exc (VString str) + +let select ctx = + get_ctx_ref := (fun() -> ctx) + +let s_value_kind = function + | VNull -> "VNull" + | VBool _ -> "VBool" + | VInt _ -> "VInt" + | VFloat _ -> "VFloat" + | VString _ -> "VString" + | VObject _ -> "VObject" + | VArray _ -> "VArray" + | VAbstract _ -> "VAbstract" + | VFunction _ -> "VFunction" + | VClosure _ -> "VClosure" + | VInt32 _ -> "VInt32" + let hash_field ctx f = let h = hash f in (try @@ -451,13 +402,17 @@ let rec get_field_opt o fid = let catch_errors ctx ?(final=(fun() -> ())) f = let n = DynArray.length ctx.stack in + let prev = get_ctx() in (* switch context in case we have an older one, see #5676 *) + select ctx; try let v = f() in final(); + select prev; Some v with Runtime v -> pop ctx (DynArray.length ctx.stack - n); final(); + select prev; let rec loop o = if o == ctx.error_proto then true else match o.oproto with None -> false | Some p -> loop p in @@ -466,7 +421,7 @@ let catch_errors ctx ?(final=(fun() -> ())) f = (match get_field o (hash "message"), get_field o (hash "pos") with | VObject msg, VAbstract (APos pos) -> (match get_field msg h_s with - | VString msg -> raise (Typecore.Error (Typecore.Custom msg,pos)) + | VString msg -> raise (Error.Error (Error.Custom msg,pos)) | _ -> ()); | _ -> ()); | _ -> ()); @@ -474,6 +429,7 @@ let catch_errors ctx ?(final=(fun() -> ())) f = | Abort -> pop ctx (DynArray.length ctx.stack - n); final(); + select prev; None let make_library fl = @@ -491,240 +447,18 @@ type neko_context = { call : primitive -> value list -> value; } -let neko = - let is_win = Sys.os_type = "Win32" || Sys.os_type = "Cygwin" in - let neko = Extc.dlopen (if is_win then "neko.dll" else "libneko.so") in +(* try to load dl in order *) +let rec dlopen dls = let null = Extc.dlint 0 in - let neko = if Obj.magic neko == null && not is_win then Extc.dlopen "libneko.dylib" else neko in - if Obj.magic neko == null then - None - else - let load v = - let s = Extc.dlsym neko v in - if (Obj.magic s) == null then failwith ("Could not load neko." ^ v); - s - in - ignore(Extc.dlcall0 (load "neko_global_init")); - let vm = Extc.dlcall1 (load "neko_vm_alloc") null in - ignore(Extc.dlcall1 (load "neko_vm_select") vm); - let loader = Extc.dlcall2 (load "neko_default_loader") null null in - let loadprim = - let l1 = load "neko_val_field" in - let l2 = Extc.dlcall1 (load "neko_val_id") (Extc.dlstring "loadprim") in - Extc.dlcall2 (l1) loader (l2) in - - let callN = load "neko_val_callN" in - let callEx = load "neko_val_callEx" in - let copy_string = load "neko_copy_string" in - - let alloc_root = load "neko_alloc_root" in - let free_root = load "neko_free_root" in - - let alloc_root v = - let r = Extc.dlcall1 alloc_root (Extc.dlint 1) in - Extc.dlsetptr r v; - r - in - let free_root r = - ignore(Extc.dlcall1 free_root r) - in - - ignore(alloc_root vm); - ignore(alloc_root loader); - ignore(alloc_root loadprim); - - let alloc_string s = - Extc.dlcall2 copy_string (Extc.dlstring s) (Extc.dlint (String.length s)) - in - let alloc_int (i:int) : Extc.value = - Obj.magic i - in - let loadprim n args = - let exc = ref null in - let vargs = [|alloc_string n;alloc_int args|] in - let p = Extc.dlcall5 callEx loader loadprim (Obj.magic vargs) (Extc.dlint 2) (Obj.magic exc) in - if !exc != null then failwith ("Failed to load " ^ n ^ ":" ^ string_of_int args); - ignore(alloc_root p); - (n,p,args) - in - let call_raw_prim (_,p,nargs) (args:Extc.value array) = - Extc.dlcall3 callN p (Obj.magic args) (Extc.dlint nargs) - in - - (* a bit tricky since load "val_true" does not work as expected on Windows *) - let unser = try loadprim "std@unserialize" 2 with _ -> ("",null,0) in - - (* did we fail to load std.ndll ? *) - if (match unser with ("",_,_) -> true | _ -> false) then None else - - let val_true = call_raw_prim unser [|alloc_string "T";loader|] in - let val_false = call_raw_prim unser [|alloc_string "F";loader|] in - let val_null = call_raw_prim unser [|alloc_string "N";loader|] in - - let is_64 = call_raw_prim (loadprim "std@sys_is64" 0) [||] == val_true in - let alloc_i32, is_v2 = (try load "neko_alloc_int32", true with _ -> Obj.magic 0, false) in - let alloc_i32 = if is_v2 then - (fun i -> Extc.dlcall1 alloc_i32 (Extc.dlint32 i)) - else - (fun i -> alloc_int (Int32.to_int (if Int32.compare i Int32.zero < 0 then Int32.logand i 0x7FFFFFFFl else Int32.logor i 0x80000000l))) - in - let tag_bits = if is_v2 then 4 else 3 in - let tag_mask = (1 lsl tag_bits) - 1 in - let ptr_size = if is_64 then 8 else 4 in - let val_field v i = Extc.dladdr v ((i + 1) * ptr_size) in - let val_str v = Extc.dladdr v 4 in - let val_fun_env v = Extc.dladdr v (8 + ptr_size) in - - (* alloc support *) - - let alloc_function = load "neko_alloc_function" in - let alloc_array = load "neko_alloc_array" in - let alloc_float = load "neko_alloc_float" in - let alloc_object = load "neko_alloc_object" in - let alloc_field = load "neko_alloc_field" in - let alloc_abstract = load "neko_alloc_abstract" in - let val_gc = load "neko_val_gc" in - let val_field_name = load "neko_val_field_name" in - let val_iter_fields = load "neko_val_iter_fields" in - let gen_callback = Extc.dlcaml_callback 2 in - - (* roots *) - - let on_abstract_gc = Extc.dlcaml_callback 1 in - let root_index = ref 0 in - let roots = Hashtbl.create 0 in - Callback.register "dlcallb1" (fun a -> - let index : int = Obj.magic (Extc.dlptr (val_field a 1)) in - Hashtbl.remove roots index; - null - ); - - (* wrapping *) - - let copy_string v = - let head = Extc.dltoint (Extc.dlptr v) in - let size = head asr tag_bits in - let s = String.create size in - Extc.dlmemcpy (Extc.dlstring s) (val_str v) size; - s - in - - let buffers = ref [] in - - let rec value_neko ?(obj=VNull) = function - | VNull -> val_null - | VBool b -> if b then val_true else val_false - | VInt i -> alloc_int i - | VAbstract (ANekoAbstract a) -> a - | VAbstract (ANekoBuffer (VString buf)) -> - let v = value_neko (VString buf) in - buffers := (buf,v) :: !buffers; - v - | VString s -> - let v = alloc_string s in (* make a copy *) - ignore(copy_string v); - v - | VObject o as obj -> - let vo = Extc.dlcall1 alloc_object null in - Array.iter (fun (id,v) -> - ignore(Extc.dlcall3 alloc_field vo (Extc.dlint id) (value_neko ~obj v)) - ) o.ofields; - vo - | VClosure _ -> - failwith "Closure not supported" - | VFunction f -> - let callb = Extc.dlcall3 alloc_function gen_callback (Extc.dlint (-1)) (Obj.magic "") in - let index = !root_index in - incr root_index; - Hashtbl.add roots index (f,obj); - let a = Extc.dlcall2 alloc_abstract null (Obj.magic index) in - if Extc.dlptr (val_field a 1) != Obj.magic index then assert false; - ignore(Extc.dlcall2 val_gc a on_abstract_gc); - Extc.dlsetptr (val_fun_env callb) a; - callb - | VArray a -> - let va = Extc.dlcall1 alloc_array (Extc.dlint (Array.length a)) in - Array.iteri (fun i v -> - Extc.dlsetptr (val_field va i) (value_neko v) - ) a; - va - | VFloat f -> - Extc.dlcall1 alloc_float (Obj.magic f) - | VAbstract _ -> - failwith "Abstract not supported" - | VInt32 i -> - alloc_i32 i - in - let obj_r = ref [] in - let obj_fun = (fun v id -> obj_r := (v,id) :: !obj_r; val_null) in - let rec neko_value (v:Extc.value) = - if Obj.is_int (Obj.magic v) then - VInt (Obj.magic v) + match dls with + | dl_path :: dls -> + let dl = Extc.dlopen dl_path in + if (Obj.magic dl) == null then + dlopen dls else - let head = Extc.dltoint (Extc.dlptr v) in - match head land tag_mask with - | 0 -> VNull - | 2 -> VBool (v == val_true) - | 3 -> VString (copy_string v) - | 4 -> - ignore(Extc.dlcall3 val_iter_fields v (Extc.dlcallback 2) (Obj.magic obj_fun)); - let r = !obj_r in - obj_r := []; - let ctx = get_ctx() in - let fields = List.rev_map (fun (v,id) -> - let iid = Extc.dltoint id in - if not (Hashtbl.mem ctx.fields_cache iid) then begin - let name = copy_string (Extc.dlcall1 val_field_name id) in - ignore(hash_field ctx name); - end; - iid, neko_value v - ) r in - VObject { ofields = Array.of_list fields; oproto = None } - | 5 -> - VArray (Array.init (head asr tag_bits) (fun i -> neko_value (Extc.dlptr (val_field v i)))) - | 7 -> - let r = alloc_root v in - let a = ANekoAbstract v in - Gc.finalise (fun _ -> free_root r) a; - VAbstract a - | t -> - failwith ("Unsupported Neko value tag " ^ string_of_int t) - in - - Callback.register "dlcallb2" (fun args nargs -> - (* get back the VM env, which was set in value_neko *) - let env = Extc.dlptr (Extc.dladdr vm (2 * ptr_size)) in - (* extract the index stored in abstract data *) - let index : int = Obj.magic (Extc.dlptr (val_field env 1)) in - let f, obj = (try Hashtbl.find roots index with Not_found -> assert false) in - let nargs = Extc.dltoint nargs in - let rec loop i = - if i = nargs then [] else neko_value (Extc.dlptr (Extc.dladdr args (i * ptr_size))) :: loop (i + 1) - in - let v = (get_ctx()).do_call obj (VFunction f) (loop 0) { psource = ""; pline = 0; } in - value_neko v - ); - - let callprim (n,p,nargs) args = - let arr = Array.of_list (List.map value_neko args) in - let exc = ref null in - if Array.length arr <> nargs then failwith n; - let ret = Extc.dlcall5 callEx val_null p (Obj.magic arr) (Extc.dlint nargs) (Obj.magic exc) in - if !exc != null then raise (Runtime (neko_value !exc)); - (match !buffers with - | [] -> () - | l -> - buffers := []; - (* copy back data *) - List.iter (fun (buf,v) -> - Extc.dlmemcpy (Extc.dlstring buf) (val_str v) (String.length buf); - ) l); - neko_value ret - in - Some { - load = loadprim; - call = callprim; - } + Some dl; + | _ -> + None (* ---------------------------------------------------------------------- *) (* BUILTINS *) @@ -762,7 +496,7 @@ let builtins = let build_stack sl = let make p = let p = make_pos p in - VArray [|VString p.Ast.pfile;VInt (Lexer.get_error_line p)|] + VArray [|VString p.Globals.pfile;VInt (Lexer.get_error_line p)|] in VArray (Array.of_list (List.map make sl)) in @@ -966,8 +700,7 @@ let builtins = Hashtbl.replace h k v; VBool (not old); ); - "hadd", Fun4 (fun h k v cmp -> - if cmp <> VNull then assert false; + "hadd", Fun3 (fun h k v -> let h = vhash h in let old = Hashtbl.mem h k in Hashtbl.add h k v; @@ -1031,7 +764,7 @@ let builtins = ); (* extra *) "use_neko_dll", Fun0 (fun() -> - VBool (neko <> None) + VBool false ); ] in let vals = [ @@ -1121,7 +854,7 @@ let std_lib = "math_floor", Fun1 (fun v -> match v with VInt _ | VInt32 _ -> v | _ -> best_int (to_int (floor (num v)))); "math_round", Fun1 (fun v -> match v with VInt _ | VInt32 _ -> v | _ -> best_int (to_int (floor (num v +. 0.5)))); "math_pi", Fun0 (fun() -> VFloat (4.0 *. atan 1.0)); - "math_sqrt", Fun1 (fun v -> VFloat (sqrt (num v))); + "math_sqrt", Fun1 (fun v -> let v = num v in VFloat (if v < 0. then nan else sqrt v)); "math_atan", Fun1 (fun v -> VFloat (atan (num v))); "math_cos", Fun1 (fun v -> VFloat (cos (num v))); "math_sin", Fun1 (fun v -> VFloat (sin (num v))); @@ -1430,8 +1163,8 @@ let std_lib = | "rb" -> AFRead (open_in_gen [Open_rdonly;Open_binary] 0 f,ref false) | "w" -> AFWrite (open_out_gen [Open_wronly;Open_creat;Open_trunc] perms f) | "wb" -> AFWrite (open_out_gen [Open_wronly;Open_creat;Open_trunc;Open_binary] perms f) - | "a" -> AFWrite (open_out_gen [Open_append] perms f) - | "ab" -> AFWrite (open_out_gen [Open_append;Open_binary] perms f) + | "a" -> AFWrite (open_out_gen [Open_append;Open_creat] perms f) + | "ab" -> AFWrite (open_out_gen [Open_append;Open_creat;Open_binary] perms f) | _ -> error()) | _ -> error() ); @@ -1679,7 +1412,7 @@ let std_lib = VInt (((get_ctx()).curapi.get_com()).run_command (vstring cmd)) ); "sys_exit", Fun1 (fun code -> - if (get_ctx()).curapi.use_cache() then raise (Typecore.Fatal_error ("",Ast.null_pos)); + if (get_ctx()).curapi.use_cache() then raise (Error.Fatal_error ("",Globals.null_pos)); raise (Sys_exit(vint code)); ); "sys_exists", Fun1 (fun file -> @@ -1749,6 +1482,17 @@ let std_lib = "sys_exe_path", Fun0 (fun() -> VString (Sys.argv.(0)) ); + "sys_program_path", Fun0 (fun() -> + let ctx = get_ctx() in + let com = ctx.curapi.get_com() in + match com.main_class with + | None -> error() + | Some p -> + match ctx.curapi.get_type (s_type_path p) with + | Some(TInst (c, _)) -> + VString (Extc.get_full_path c.cl_pos.Globals.pfile) + | _ -> error(); + ); "sys_env", Fun0 (fun() -> let env = Unix.environment() in let rec loop acc i = @@ -1842,7 +1586,8 @@ let std_lib = (* process *) "process_run", (Fun2 (fun p args -> match p, args with - | VString p, VArray args -> VAbstract (AProcess (Process.run p (Array.map vstring args))) + | VString p, VArray args -> VAbstract (AProcess (Process.run p (Some (Array.map vstring args)))) + | VString p, _ -> VAbstract (AProcess (Process.run p None)) | _ -> error() )); "process_stdout_read", (Fun4 (fun p str pos len -> @@ -1880,9 +1625,14 @@ let std_lib = | VAbstract (AProcess p) -> Process.close p; free_abstract vp; VNull | _ -> error() )); + "process_kill", (Fun1 (fun vp -> + match vp with + | VAbstract (AProcess p) -> Process.kill p; free_abstract vp; VNull + | _ -> error() + )); (* xml *) - "parse_xml", (match neko with - | None -> Fun2 (fun str o -> + "parse_xml", + (Fun2 (fun str o -> match str, o with | VString str, VObject events -> let ctx = get_ctx() in @@ -1915,21 +1665,9 @@ let std_lib = | e -> failwith ("Parser failure (" ^ Printexc.to_string e ^ ")")); VNull | _ -> error()) - | Some neko -> - let parse_xml = neko.load "std@parse_xml" 2 in - Fun2 (fun str o -> neko.call parse_xml [str;o]) ); (* memory, module : not planned *) - ] - (* process *) - @ (match neko with - | None -> [] - | Some neko -> - let win_ec = (try Some (neko.load "std@win_env_changed" 0) with _ -> None) in - [ - "win_env_changed", (Fun0 (fun() -> match win_ec with None -> error() | Some f -> neko.call f [])); - ])) - + ]) (* ---------------------------------------------------------------------- *) (* REGEXP LIBRARY *) @@ -1938,122 +1676,70 @@ let reg_lib = let error() = raise Builtin_error in - (* try to load regexp first : we might fail if pcre is not installed *) - let neko = (match neko with - | None -> None - | Some neko -> - (try ignore(neko.load "regexp@regexp_new_options" 2); Some neko with _ -> None) - ) in - match neko with - | None -> + let open Pcre in + let string_of_pcre_error = function + | BadPattern(s,i) -> Printf.sprintf "at %i: %s" i s + | Partial -> "Partial" + | BadPartial -> "BadPartial" + | BadUTF8 -> "BadUTF8" + | BadUTF8Offset -> "BadUTF8Offset" + | MatchLimit -> "MatchLimit" + | RecursionLimit -> "RecursionLimit" + | InternalError s -> "InternalError: " ^ s + in make_library [ - (* regexp_new : deprecated *) "regexp_new_options", Fun2 (fun str opt -> - match str, opt with - | VString str, VString opt -> - let case_sensitive = ref true in - List.iter (function - | 'm' -> () (* always ON ? *) - | 'i' -> case_sensitive := false + match str,opt with + | VString str,VString opt -> + let flags = List.map (function + | 'i' -> `CASELESS + | 's' -> `DOTALL + | 'm' -> `MULTILINE + | 'u' -> `UTF8 + | 'g' -> `UNGREEDY | c -> failwith ("Unsupported regexp option '" ^ String.make 1 c ^ "'") - ) (ExtString.String.explode opt); - let buf = Buffer.create 0 in - let rec loop prev esc = function - | [] -> () - | c :: l when esc -> - (match c with - | 'n' -> Buffer.add_char buf '\n' - | 'r' -> Buffer.add_char buf '\r' - | 't' -> Buffer.add_char buf '\t' - | 'd' -> Buffer.add_string buf "[0-9]" - | '\\' -> Buffer.add_string buf "\\\\" - | '(' | ')' -> Buffer.add_char buf c - | '1'..'9' | '+' | '$' | '^' | '*' | '?' | '.' | '[' | ']' -> - Buffer.add_char buf '\\'; - Buffer.add_char buf c; - | _ -> failwith ("Unsupported escaped char '" ^ String.make 1 c ^ "'")); - loop c false l - | c :: l -> - match c with - | '\\' -> loop prev true l - | '(' | '|' | ')' -> - Buffer.add_char buf '\\'; - Buffer.add_char buf c; - loop c false l - | '?' when prev = '(' && (match l with ':' :: _ -> true | _ -> false) -> - failwith "Non capturing groups '(?:' are not supported in macros" - | '?' when prev = '*' -> - failwith "Ungreedy *? are not supported in macros" - | _ -> - Buffer.add_char buf c; - loop c false l - in - loop '\000' false (ExtString.String.explode str); - let str = Buffer.contents buf in - let r = { - r = if !case_sensitive then Str.regexp str else Str.regexp_case_fold str; + ) (ExtString.String.explode opt) in + let r = try regexp ~flags str with Error error -> failwith (string_of_pcre_error error) in + let pcre = { + r = r; r_string = ""; - r_groups = [||]; + r_groups = [||] } in - VAbstract (AReg r) - | _ -> error() - ); - "regexp_match", Fun4 (fun r str pos len -> - match r, str, pos, len with - | VAbstract (AReg r), VString str, VInt pos, VInt len -> - let nstr, npos, delta = (if len = String.length str - pos then str, pos, 0 else String.sub str pos len, 0, pos) in - (try - ignore(Str.search_forward r.r nstr npos); - let rec loop n = - if n = 9 then - [] - else try - (Some (Str.group_beginning n + delta, Str.group_end n + delta)) :: loop (n + 1) - with Not_found -> - None :: loop (n + 1) - | Invalid_argument _ -> - [] - in - r.r_string <- str; - r.r_groups <- Array.of_list (loop 0); - VBool true; + VAbstract (AReg pcre) + | _ -> error() + ); + "regexp_match", Fun4 (fun rex str pos len -> match rex, str, pos, len with + | VAbstract (AReg rex),VString str,VInt pos,VInt len -> + begin try + (* A bit awkward, but the PCRE bindings don't seem to expose the len argument... *) + if pos + len > String.length str then raise Not_found; + let str = String.sub str 0 (pos + len) in + let a = pcre_exec ~rex:rex.r ~pos str in + rex.r_string <- str; + rex.r_groups <- a; + VBool true with Not_found -> - VBool false) + VBool false + end | _ -> error() ); - "regexp_matched", Fun2 (fun r n -> - match r, n with - | VAbstract (AReg r), VInt n -> - (match (try r.r_groups.(n) with _ -> failwith ("Invalid group " ^ string_of_int n)) with - | None -> VNull - | Some (pos,pend) -> VString (String.sub r.r_string pos (pend - pos))) + "regexp_matched", Fun2 (fun r n -> match r, n with + | VAbstract (AReg r),VInt n -> + let pos = r.r_groups.(n * 2) in + let len = r.r_groups.(n * 2 + 1) - pos in + if pos = -1 then VNull + else VString (String.sub r.r_string pos len) | _ -> error() ); - "regexp_matched_pos", Fun2 (fun r n -> - match r, n with - | VAbstract (AReg r), VInt n -> - (match (try r.r_groups.(n) with _ -> failwith ("Invalid group " ^ string_of_int n)) with - | None -> VNull - | Some (pos,pend) -> VObject (obj (hash_field (get_ctx())) ["pos",VInt pos;"len",VInt (pend - pos)])) + "regexp_matched_pos", Fun2 (fun r n -> match r, n with + | VAbstract (AReg r),VInt n -> + let pos = r.r_groups.(n * 2) in + let len = r.r_groups.(n * 2 + 1) - pos in + VObject (obj (hash_field (get_ctx())) ["pos",VInt pos;"len",VInt len]) | _ -> error() ); - (* regexp_replace : not used by Haxe *) - (* regexp_replace_all : not used by Haxe *) - (* regexp_replace_fun : not used by Haxe *) - ] - | Some neko -> - let regexp_new_options = neko.load "regexp@regexp_new_options" 2 in - let regexp_match = neko.load "regexp@regexp_match" 4 in - let regexp_matched = neko.load "regexp@regexp_matched" 2 in - let regexp_matched_pos = neko.load "regexp@regexp_matched_pos" 2 in - make_library [ - "regexp_new_options", Fun2 (fun str opt -> neko.call regexp_new_options [str;opt]); - "regexp_match", Fun4 (fun r str pos len -> neko.call regexp_match [r;str;pos;len]); - "regexp_matched", Fun2 (fun r n -> neko.call regexp_matched [r;n]); - "regexp_matched_pos", Fun2 (fun r n -> neko.call regexp_matched_pos [r;n]); ] - (* ---------------------------------------------------------------------- *) (* ZLIB LIBRARY *) @@ -2122,569 +1808,6 @@ let z_lib = ); ] -(* ---------------------------------------------------------------------- *) -(* MACRO LIBRARY *) - -(* convert float value to haxe expression, handling inf/-inf/nan *) -let haxe_float f p = - let std = (Ast.EConst (Ast.Ident "std"), p) in - let math = (Ast.EField (std, "Math"), p) in - if (f = infinity) then - (Ast.EField (math, "POSITIVE_INFINITY"), p) - else if (f = neg_infinity) then - (Ast.EField (math, "NEGATIVE_INFINITY"), p) - else if (f <> f) then - (Ast.EField (math, "NaN"), p) - else - (Ast.EConst (Ast.Float (float_repres f)), p) - -let macro_lib = - let error() = - raise Builtin_error - in - let ccom() = - (get_ctx()).curapi.get_com() - in - make_library [ - "curpos", Fun0 (fun() -> VAbstract (APos (get_ctx()).curapi.pos)); - "error", Fun2 (fun msg p -> - match msg, p with - | VString s, VAbstract (APos p) -> - (ccom()).Common.error s p; - raise Abort - | _ -> error() - ); - "fatal_error", Fun2 (fun msg p -> - match msg, p with - | VString s, VAbstract (APos p) -> - raise (Typecore.Fatal_error (s,p)) - | _ -> error() - ); - "warning", Fun2 (fun msg p -> - match msg, p with - | VString s, VAbstract (APos p) -> - (ccom()).warning s p; - VNull; - | _ -> error() - ); - "class_path", Fun0 (fun() -> - VArray (Array.of_list (List.map (fun s -> VString s) (ccom()).class_path)); - ); - "resolve", Fun1 (fun file -> - match file with - | VString s -> VString (try Common.find_file (ccom()) s with Not_found -> failwith ("File not found '" ^ s ^ "'")) - | _ -> error(); - ); - "define", Fun1 (fun s -> - match s with - | VString s -> Common.raw_define (ccom()) s; VNull - | _ -> error(); - ); - "defined", Fun1 (fun s -> - match s with - | VString s -> VBool (Common.raw_defined (ccom()) s) - | _ -> error(); - ); - "defined_value", Fun1 (fun s -> - match s with - | VString s -> (try VString (Common.raw_defined_value (ccom()) s) with Not_found -> VNull) - | _ -> error(); - ); - "get_defines", Fun0 (fun() -> - let defines = (ccom()).defines in - let h = Hashtbl.create 0 in - PMap.iter (fun n v -> Hashtbl.replace h (VString n) (VString v)) defines; - enc_hash h - ); - "get_type", Fun1 (fun s -> - match s with - | VString s -> - (match (get_ctx()).curapi.get_type s with - | None -> failwith ("Type not found '" ^ s ^ "'") - | Some t -> encode_type t) - | _ -> error() - ); - "get_module", Fun1 (fun s -> - match s with - | VString s -> - enc_array (List.map encode_type ((get_ctx()).curapi.get_module s)) - | _ -> error() - ); - "on_generate", Fun1 (fun f -> - match f with - | VFunction (Fun1 _) -> - let ctx = get_ctx() in - ctx.curapi.on_generate (fun tl -> - ignore(catch_errors ctx (fun() -> ctx.do_call VNull f [enc_array (List.map encode_type tl)] null_pos)); - ); - VNull - | _ -> error() - ); - "after_generate", Fun1 (fun f -> - match f with - | VFunction (Fun0 _) -> - let ctx = get_ctx() in - ctx.curapi.after_generate (fun () -> - ignore(catch_errors ctx (fun() -> ctx.do_call VNull f [] null_pos)); - ); - VNull - | _ -> error() - ); - "on_type_not_found", Fun1 (fun f -> - match f with - | VFunction (Fun1 _) -> - let ctx = get_ctx() in - ctx.curapi.on_type_not_found (fun path -> - match catch_errors ctx (fun () -> ctx.do_call VNull f [enc_string path] null_pos) with - | Some v -> v - | None -> VNull - ); - VNull - | _ -> error() - ); - "parse", Fun3 (fun s p b -> - match s, p, b with - | VString s, VAbstract (APos p), VBool b when s <> "" -> - (try encode_expr ((get_ctx()).curapi.parse_string s p b) with Invalid_expr -> error()) - | _ -> error() - ); - "make_expr", Fun2 (fun v p -> - match p with - | VAbstract (APos p) -> - let h_enum = hash "__enum__" and h_et = hash "__et__" and h_ct = hash "__ct__" in - let h_tag = hash "tag" and h_args = hash "args" in - let h_length = hash "length" in - let ctx = get_ctx() in - let error v = failwith ("Unsupported value " ^ ctx.do_string v) in - let make_path t = - let rec loop = function - | [] -> assert false - | [name] -> (Ast.EConst (Ast.Ident name),p) - | name :: l -> (Ast.EField (loop l,name),p) - in - let t = t_infos t in - loop (List.rev (if t.mt_module.m_path = t.mt_path then fst t.mt_path @ [snd t.mt_path] else fst t.mt_module.m_path @ [snd t.mt_module.m_path;snd t.mt_path])) - in - let rec loop = function - | VNull -> (Ast.EConst (Ast.Ident "null"),p) - | VBool b -> (Ast.EConst (Ast.Ident (if b then "true" else "false")),p) - | VInt i -> (Ast.EConst (Ast.Int (string_of_int i)),p) - | VInt32 i -> (Ast.EConst (Ast.Int (Int32.to_string i)),p) - | VFloat f -> haxe_float f p - | VAbstract (APos p) -> - (Ast.EObjectDecl ( - ("fileName" , (Ast.EConst (Ast.String p.Ast.pfile) , p)) :: - ("lineNumber" , (Ast.EConst (Ast.Int (string_of_int (Lexer.get_error_line p))),p)) :: - ("className" , (Ast.EConst (Ast.String ("")),p)) :: - [] - ), p) - | VString _ | VArray _ | VAbstract _ | VFunction _ | VClosure _ as v -> error v - | VObject o as v -> - match o.oproto with - | None -> - (match get_field_opt o h_ct with - | Some (VAbstract (ATDecl t)) -> - make_path t - | _ -> - let fields = List.fold_left (fun acc (fid,v) -> (field_name ctx fid, loop v) :: acc) [] (Array.to_list o.ofields) in - (Ast.EObjectDecl fields, p)) - | Some proto -> - match get_field_opt proto h_enum, get_field_opt o h_a, get_field_opt o h_s, get_field_opt o h_length with - | _, Some (VArray a), _, Some (VInt len) -> - (Ast.EArrayDecl (List.map loop (Array.to_list (Array.sub a 0 len))),p) - | _, _, Some (VString s), _ -> - (Ast.EConst (Ast.String s),p) - | Some (VObject en), _, _, _ -> - (match get_field en h_et, get_field o h_tag with - | VAbstract (ATDecl t), VString tag -> - let e = (Ast.EField (make_path t,tag),p) in - (match get_field_opt o h_args with - | Some (VArray args) -> - let args = List.map loop (Array.to_list args) in - (Ast.ECall (e,args),p) - | _ -> e) - | _ -> - error v) - | _ -> - error v - in - encode_expr (loop v) - | _ -> error() - ); - "signature", Fun1 (fun v -> - let cache = ref [] in - let cache_count = ref 0 in - let hfiles = Hashtbl.create 0 in - let get_file f = - try - Hashtbl.find hfiles f - with Not_found -> - let ff = Common.unique_full_path f in - Hashtbl.add hfiles f ff; - ff - in - let do_cache (v:value) (v2:value) = - (* - tricky : we need to have a quick not-linear cache based on objects address - but we can't use address since the GC might be triggered here. - Instead let's mutate the object temporary. - *) - let vt = Obj.repr v in - let old = Obj.tag vt in - let old_val = Obj.field vt 0 in - let abstract_tag = 7 in - Obj.set_tag vt abstract_tag; - Obj.set_field vt 0 (Obj.repr (ACacheRef v2)); - cache := (vt,old,old_val) :: !cache; - incr cache_count - in - let rec loop v = - match v with - | VNull | VBool _ | VInt _ | VFloat _ | VString _ | VInt32 _ -> v - | VObject o -> - let o2 = { ofields = [||]; oproto = None } in - let v2 = VObject o2 in - do_cache v v2; - Array.iter (fun (f,v) -> if f <> h_class then set_field o2 f (loop v)) o.ofields; - (match o.oproto with - | None -> () - | Some p -> (match loop (VObject p) with VObject p2 -> o2.oproto <- Some p2 | _ -> assert false)); - v2 - | VArray a -> - let a2 = Array.create (Array.length a) VNull in - let v2 = VArray a2 in - do_cache v v2; - for i = 0 to Array.length a - 1 do - a2.(i) <- loop a.(i); - done; - v2 - | VFunction f -> - let v2 = VFunction (Obj.magic !cache_count) in - do_cache v v2; - v2 - | VClosure (vl,f) -> - let rl = ref [] in - let v2 = VClosure (Obj.magic rl, Obj.magic !cache_count) in - (* in ocaml 4.0+ it was reported some stack overflow, related to vl being GC'ed or mutated in do_cache. - let's make sure to have a real pointer to it first. The fix will trigger an alloc which might have simply moved the problem away *) - let vl = VNull :: vl in - do_cache v v2; - rl := List.map loop vl; - v2 - | VAbstract (APos p) -> VAbstract (APos { p with Ast.pfile = get_file p.Ast.pfile }) - | VAbstract (ACacheRef v) -> v - | VAbstract (AHash h) -> - let h2 = Hashtbl.create 0 in - let v2 = VAbstract (AHash h2) in - do_cache v v2; - Hashtbl.iter (fun k v -> Hashtbl.add h2 k (loop v)) h2; - v2 - | VAbstract _ -> - let v2 = VAbstract (Obj.magic !cache_count) in - do_cache v v2; - v2 - in - let v = loop v in - (* restore *) - List.iter (fun (vt,tag,field) -> - Obj.set_tag vt tag; - Obj.set_field vt 0 field; - ) !cache; - VString (Digest.to_hex (Digest.string (Marshal.to_string v [Marshal.Closures]))) - ); - "to_complex", Fun1 (fun v -> - try encode_complex_type (make_complex_type (decode_type v)) - with Exit -> VNull - ); - "unify", Fun2 (fun t1 t2 -> - let e1 = mk (TObjectDecl []) (decode_type t1) Ast.null_pos in - try ignore(((get_ctx()).curapi.cast_or_unify) (decode_type t2) e1 Ast.null_pos); VBool true - with Typecore.Error (Typecore.Unify _,_) -> VBool false - ); - "typeof", Fun1 (fun v -> - encode_type ((get_ctx()).curapi.type_expr (decode_expr v)).etype - ); - "type_expr", Fun1 (fun v -> - encode_texpr ((get_ctx()).curapi.type_expr (decode_expr v)) - ); - "s_type", Fun1 (fun v -> - VString (Type.s_type (print_context()) (decode_type v)) - ); - "s_expr", Fun2 (fun v b -> - let f = match b with VBool true -> Type.s_expr_pretty "" | _ -> Type.s_expr_ast true "" in - VString (f (Type.s_type (print_context())) (decode_texpr v)) - ); - "is_fmt_string", Fun1 (fun v -> - match v with - | VAbstract (APos p) -> VBool(Lexer.is_fmt_string p) - | _ -> VNull - ); - "format_string", Fun2 (fun s p -> - match s,p with - | VString(s),VAbstract(APos p) -> encode_expr ((get_ctx()).curapi.format_string s p) - | _ -> VNull - ); - "display", Fun1 (fun v -> - match v with - | VString s -> - VString ((get_ctx()).curapi.get_display s) - | _ -> - error() - ); - "allow_package", Fun1 (fun v -> - match v with - | VString s -> - (get_ctx()).curapi.allow_package s; - VNull - | _ -> error()); - "type_patch", Fun4 (fun t f s v -> - let p = (get_ctx()).curapi.type_patch in - (match t, f, s, v with - | VString t, VString f, VBool s, VString v -> p t f s (Some v) - | VString t, VString f, VBool s, VNull -> p t f s None - | _ -> error()); - VNull - ); - "meta_patch", Fun4 (fun m t f s -> - let p = (get_ctx()).curapi.meta_patch in - (match m, t, f, s with - | VString m, VString t, VString f, VBool s -> p m t (Some f) s - | VString m, VString t, VNull, VBool s -> p m t None s - | _ -> error()); - VNull - ); - "add_global_metadata", Fun5 (fun v1 v2 v3 v4 v5 -> - match v1,v2,v3,v4,v5 with - | VString s1,VString s2,VBool b1,VBool b2,VBool b3 -> - (get_ctx()).curapi.add_global_metadata s1 s2 (b1,b2,b3); - VNull - | _ -> - error() - ); - "custom_js", Fun1 (fun f -> - match f with - | VFunction (Fun1 _) -> - let ctx = get_ctx() in - ctx.curapi.set_js_generator (fun api -> - ignore(catch_errors ctx (fun() -> ctx.do_call VNull f [api] null_pos)); - ); - VNull - | _ -> error() - ); - "get_pos_infos", Fun1 (fun p -> - match p with - | VAbstract (APos p) -> VObject (obj (hash_field (get_ctx())) ["min",VInt p.Ast.pmin;"max",VInt p.Ast.pmax;"file",VString p.Ast.pfile]) - | _ -> error() - ); - "make_pos", Fun3 (fun min max file -> - match min, max, file with - | VInt min, VInt max, VString file -> VAbstract (APos { Ast.pmin = min; Ast.pmax = max; Ast.pfile = file }) - | _ -> error() - ); - "add_resource", Fun2 (fun name data -> - match name, data with - | VString name, VString data -> - Hashtbl.replace (ccom()).resources name data; - let m = (get_ctx()).curapi.current_module() in - m.m_extra.m_binded_res <- PMap.add name data m.m_extra.m_binded_res; - VNull - | _ -> error() - ); - "get_resources", Fun0 (fun() -> - let res = (ccom()).resources in - let h = Hashtbl.create 0 in - Hashtbl.iter (fun n v -> Hashtbl.replace h (VString n) (VString v)) res; - enc_hash h - ); - "local_module", Fun0 (fun() -> - let m = (get_ctx()).curapi.current_module() in - VString (Ast.s_type_path m.m_path); - ); - "local_type", Fun0 (fun() -> - match (get_ctx()).curapi.get_local_type() with - | None -> VNull - | Some t -> encode_type t - ); - "expected_type", Fun0 (fun() -> - match (get_ctx()).curapi.get_expected_type() with - | None -> VNull - | Some t -> encode_type t - ); - "call_arguments", Fun0 (fun() -> - match (get_ctx()).curapi.get_call_arguments() with - | None -> VNull - | Some el -> enc_array (List.map encode_expr el) - ); - "local_method", Fun0 (fun() -> - VString ((get_ctx()).curapi.get_local_method()) - ); - "local_using", Fun0 (fun() -> - enc_array (List.map encode_clref ((get_ctx()).curapi.get_local_using())) - ); - "local_vars", Fun1 (fun as_var -> - let as_var = match as_var with - | VNull | VBool false -> false - | VBool true -> true - | _ -> error() - in - let vars = (get_ctx()).curapi.get_local_vars() in - let h = Hashtbl.create 0 in - if as_var then - PMap.iter (fun n v -> Hashtbl.replace h (VString n) (encode_tvar v)) vars - else - PMap.iter (fun n v -> Hashtbl.replace h (VString n) (encode_type v.v_type)) vars; - enc_hash h - ); - "follow", Fun2 (fun v once -> - let t = decode_type v in - let follow_once t = - match t with - | TMono r -> - (match !r with - | None -> t - | Some t -> t) - | TAbstract _ | TEnum _ | TInst _ | TFun _ | TAnon _ | TDynamic _ -> - t - | TType (t,tl) -> - apply_params t.t_params tl t.t_type - | TLazy f -> - (!f)() - in - encode_type (match once with VNull | VBool false -> follow t | VBool true -> follow_once t | _ -> error()) - ); - "build_fields", Fun0 (fun() -> - (get_ctx()).curapi.get_build_fields() - ); - "define_type", Fun1 (fun v -> - (get_ctx()).curapi.define_type v; - VNull - ); - "define_module", Fun4 (fun p v i u -> - match p, v, i, u with - | VString path, VArray vl, VArray ui, VArray ul -> - (get_ctx()).curapi.define_module path (Array.to_list vl) (List.map decode_import (Array.to_list ui)) (List.map decode_path (Array.to_list ul)); - VNull - | _ -> - error() - ); - "add_class_path", Fun1 (fun v -> - match v with - | VString cp -> - let com = ccom() in - com.class_path <- (Common.normalize_path cp) :: com.class_path; - Hashtbl.clear com.file_lookup_cache; - VNull - | _ -> - error() - ); - "add_native_lib", Fun1 (fun v -> - match v with - | VString file -> - let com = ccom() in - (match com.platform with - | Flash -> Genswf.add_swf_lib com file false - | Java -> Genjava.add_java_lib com file false - | Cs -> - let file, is_std = match ExtString.String.nsplit file "@" with - | [file] -> - file,false - | [file;"std"] -> - file,true - | _ -> failwith ("unsupported file@`std` format: " ^ file) - in - Gencs.add_net_lib com file is_std - | _ -> failwith "Unsupported platform"); - VNull - | _ -> - error() - ); - "add_native_arg", Fun1 (fun v -> - match v with - | VString arg -> - let com = ccom() in - (match com.platform with - | Java | Cs | Cpp -> - com.c_args <- arg :: com.c_args - | _ -> failwith "Unsupported platform"); - VNull - | _ -> - error() - ); - "module_dependency", Fun2 (fun m file -> - match m, file with - | VString m, VString file -> - (get_ctx()).curapi.module_dependency m file false; - VNull - | _ -> error() - ); - "module_reuse_call", Fun2 (fun m mcall -> - match m, mcall with - | VString m, VString mcall -> - (get_ctx()).curapi.module_dependency m mcall true; - VNull - | _ -> error() - ); - "get_typed_expr", Fun1 (fun e -> - let e = decode_texpr e in - encode_expr (make_ast e) - ); - "store_typed_expr", Fun1 (fun e -> - let e = try decode_texpr e with Invalid_expr -> error() in - encode_expr ((get_ctx()).curapi.store_typed_expr e) - ); - "get_output", Fun0 (fun() -> - VString (ccom()).file - ); - "set_output", Fun1 (fun s -> - match s with - | VString s -> (ccom()).file <- s; VNull - | _ -> error() - ); - "get_display_pos", Fun0 (fun() -> - let p = !Parser.resume_display in - if p = Ast.null_pos then - VNull - else - VObject (obj (hash_field (get_ctx())) ["file",VString p.Ast.pfile;"pos",VInt p.Ast.pmin]) - ); - "pattern_locals", Fun2 (fun e t -> - let loc = (get_ctx()).curapi.get_pattern_locals (decode_expr e) (decode_type t) in - let h = Hashtbl.create 0 in - PMap.iter (fun n (v,_) -> Hashtbl.replace h (VString n) (encode_type v.v_type)) loc; - enc_hash h - ); - "macro_context_reused", Fun1 (fun c -> - match c with - | VFunction (Fun0 _) -> - let ctx = get_ctx() in - ctx.on_reused <- (fun() -> catch_errors ctx (fun() -> ctx.do_call VNull c [] null_pos) = Some (VBool true)) :: ctx.on_reused; - VNull - | _ -> error() - ); - "apply_params", Fun3 (fun tpl tl t -> - let tpl = List.map (fun v -> - match v with - | VObject o -> - let name = match get_field o (hash "name") with VString s -> s | _ -> assert false in - let t = decode_type (get_field o (hash "t")) in - name,t - | _ -> assert false - ) (dec_array tpl) in - let tl = List.map decode_type (dec_array tl) in - let rec map t = match t with - | TInst({cl_kind = KTypeParameter _},_) -> - begin try - (* use non-physical equality check here to make apply_params work *) - snd (List.find (fun (_,t2) -> type_iseq t t2) tpl) - with Not_found -> - Type.map map t - end - | _ -> Type.map map t - in - encode_type (apply_params tpl tl (map (decode_type t))) - ); - ] - (* ---------------------------------------------------------------------- *) (* EVAL *) @@ -2726,7 +1849,11 @@ let get_ident ctx s = let no_env = [||] -let rec eval ctx (e,p) = +let rec eval_expr ctx e = + let e = Genneko.gen_expr ctx.gen e in + catch_errors ctx (fun() -> (eval ctx e)()) + +and eval ctx (e,p) = match e with | EConst c -> (match c with @@ -2774,12 +1901,12 @@ let rec eval ctx (e,p) = | VObject o -> get_field o h | _ -> throw ctx p ("Invalid field access : " ^ f) ) - | ECall ((EConst (Builtin "mk_pos"),_),[(ECall (_,[EConst (String file),_]),_);(EConst (Int min),_);(EConst (Int max),_)]) -> - let pos = VAbstract (APos { Ast.pfile = file; Ast.pmin = min; Ast.pmax = max }) in + | ECall ((EConst (Builtin "__mk_pos__"),_),[(ECall (_,[EConst (String file),_]),_);(EConst (Int min),_);(EConst (Int max),_)]) -> + let pos = VAbstract (APos { Globals.pfile = file; Globals.pmin = min; Globals.pmax = max }) in (fun() -> pos) | ECall ((EConst (Builtin "typewrap"),_),[t]) -> (fun() -> VAbstract (ATDecl (Obj.magic t))) - | ECall ((EConst (Builtin "delay_call"),_),[EConst (Int index),_]) -> + | ECall ((EConst (Builtin "__delayed_call__"),_),[EConst (Int index),_]) -> let f = ctx.curapi.delayed_macro index in let fbuild = ref None in let old = { ctx with gen = ctx.gen } in @@ -3359,8 +2486,8 @@ and eval_op ctx op e1 e2 p = let e2 = eval ctx e2 in (fun() -> match e1() with - | VBool false as v -> v - | _ -> e2()) + | VBool true -> e2() + | _ -> VBool false) | "||" -> let e1 = eval ctx e1 in let e2 = eval ctx e2 in @@ -3403,15 +2530,15 @@ and call ctx vthis vfun pl p = | [a;b;c;d;e], Fun5 f -> f a b c d e | _, FunVar f -> f pl | _ -> exc (VString (Printf.sprintf "Invalid call (%d args instead of %d)" (List.length pl) (nargs f)))) - | VAbstract (ALazyType f) -> - encode_type ((!f)()) + | VAbstract (ALazyType (f,get)) -> + get() | _ -> exc (VString "Invalid call")) with Return v -> v | Stack_overflow -> exc (VString "Compiler Stack overflow") | Sys_error msg | Failure msg -> exc (VString msg) | Unix.Unix_error (_,cmd,msg) -> exc (VString ("Error " ^ cmd ^ " " ^ msg)) - (* | Invalid_expr -> exc (VString "Invalid input value") *) + | Invalid_expr -> exc (VString "Invalid input value") | Builtin_error | Invalid_argument _ -> exc (VString "Invalid call")) in ctx.vthis <- oldthis; ctx.venv <- oldenv; @@ -3420,6 +2547,9 @@ and call ctx vthis vfun pl p = pop ctx (DynArray.length ctx.stack - stackpos); ret +let eval_delayed ctx e = + eval ctx (Genneko.gen_expr ctx.gen e) + (* ---------------------------------------------------------------------- *) (* OTHERS *) @@ -3466,7 +2596,7 @@ let rec to_string ctx n v = Buffer.contents b let rec compare ctx a b = - let fcmp (a:float) b = if a = b then CEq else if a < b then CInf else CSup in + let fcmp (a:float) b = if a = b then CEq else if a < b then CInf else if a > b then CSup else CUndef in let scmp (a:string) b = if a = b then CEq else if a < b then CInf else CSup in let icmp (a:int32) b = let l = Int32.compare a b in if l = 0 then CEq else if l < 0 then CInf else CSup in match a, b with @@ -3506,8 +2636,10 @@ let rec compare ctx a b = | _ -> CUndef -let select ctx = - get_ctx_ref := (fun() -> ctx) +let value_match_failure s expected actual = + let sl = String.concat ", " in + let slv l = sl (List.map s_value_kind l) in + Printf.sprintf "%s (expected [%s], got [%s])" s (sl expected) (slv actual) let load_prim ctx f n = match f, n with @@ -3526,7 +2658,7 @@ let load_prim ctx f n = with Not_found -> VFunction (FunVar (fun _ -> exc (VString ("Primitive not found " ^ f ^ ":" ^ string_of_int n))))) | _ -> - exc (VString "Invalid call") + exc (VString (value_match_failure "Invalid call" ["VString";"VInt"] [f;n])) let create com api = let loader = obj hash [ @@ -3563,8 +2695,6 @@ let create com api = (* context *) curapi = api; loader = VObject loader; - on_reused = []; - is_reused = true; exports = VObject { ofields = [||]; oproto = None }; } in ctx.do_call <- call ctx; @@ -3575,10 +2705,7 @@ let create com api = List.iter (fun e -> ignore((eval ctx e)())) (Genneko.header()); ctx - - let do_reuse ctx api = - ctx.is_reused <- false; ctx.curapi <- api let can_reuse ctx types = @@ -3589,33 +2716,25 @@ let can_reuse ctx types = with Not_found -> false in - if List.exists has_old_version types then - false - else if ctx.is_reused then - true - else if not (List.for_all (fun f -> f()) ctx.on_reused) then - false - else begin - ctx.is_reused <- true; - true; - end + not (List.exists has_old_version types) let add_types ctx types ready = - let types = List.filter (fun t -> - let path = Type.t_path t in - if Hashtbl.mem ctx.types path then false else begin - Hashtbl.add ctx.types path (Type.t_infos t).mt_module.m_id; - true; - end + let types = List.filter (fun t -> match t with + | TAbstractDecl a when not (Meta.has Meta.CoreType a.a_meta) -> + (* A @:native on an abstract causes the implementation class and the abstract + to have the same path. Let's skip all abstracts so this doesn't matter. *) + false + | _ -> + let path = Type.t_path t in + if Hashtbl.mem ctx.types path then false else begin + Hashtbl.add ctx.types path (Type.t_infos t).mt_module.m_id; + true; + end ) types in List.iter ready types; let e = (EBlock (Genneko.build ctx.gen types), null_pos) in ignore(catch_errors ctx (fun() -> ignore((eval ctx e)()))) -let eval_expr ctx e = - let e = Genneko.gen_expr ctx.gen e in - catch_errors ctx (fun() -> (eval ctx e)()) - let get_path ctx path p = let rec loop = function | [] -> assert false @@ -3638,54 +2757,12 @@ let call_path ctx path f vl api = | VObject o -> let f = get_field o (hash f) in call ctx (VObject o) f vl p - | _ -> assert false + | v -> + print_endline (value_match_failure ("Unexpected value for " ^ (String.concat "." path)) ["VObject"] [v]); + assert false ) -(* ---------------------------------------------------------------------- *) -(* EXPR ENCODING *) - -type enum_index = - | IExpr - | IBinop - | IUnop - | IConst - | ITParam - | ICType - | IField - | IType - | IFieldKind - | IMethodKind - | IVarAccess - | IAccess - | IClassKind - | ITypedExpr - | ITConstant - | IModuleType - | IFieldAccess - | IAnonStatus - -let enum_name = function - | IExpr -> "ExprDef" - | IBinop -> "Binop" - | IUnop -> "Unop" - | IConst -> "Constant" - | ITParam -> "TypeParam" - | ICType -> "ComplexType" - | IField -> "FieldType" - | IType -> "Type" - | IFieldKind -> "FieldKind" - | IMethodKind -> "MethodKind" - | IVarAccess -> "VarAccess" - | IAccess -> "Access" - | IClassKind -> "ClassKind" - | ITypedExpr -> "TypedExprDef" - | ITConstant -> "TConstant" - | IModuleType -> "ModuleType" - | IFieldAccess -> "FieldAccess" - | IAnonStatus -> "AnonStatus" - let init ctx = - let enums = [IExpr;IBinop;IUnop;IConst;ITParam;ICType;IField;IType;IFieldKind;IMethodKind;IVarAccess;IAccess;IClassKind;ITypedExpr;ITConstant;IModuleType;IFieldAccess;IAnonStatus] in let get_enum_proto e = match get_path ctx ["haxe";"macro";enum_name e] null_pos with | VObject e -> @@ -3702,586 +2779,131 @@ let init ctx = | _ -> assert false) | _ -> failwith ("haxe.macro." ^ enum_name e ^ " does not exists") in - ctx.enums <- Array.of_list (List.map get_enum_proto enums); + ctx.enums <- Array.of_list (List.map get_enum_proto MacroApi.all_enums); ctx.error_proto <- (match get_path ctx ["haxe";"macro";"Error";"prototype"] null_pos with VObject p -> p | _ -> failwith ("haxe.macro.Error does not exists")) -open Ast +(* ---------------------------------------------------------------------- *) +(* MACRO API IMPL *) -let null f = function - | None -> VNull - | Some v -> f v +let vnull = VNull -let encode_pos p = - VAbstract (APos p) +let vint i = VInt i +let vint32 i = VInt32 i +let vfun0 f = VFunction (Fun0 f) +let vfun1 f = VFunction (Fun1 f) +let vfun2 f = VFunction (Fun2 f) +let vfun3 f = VFunction (Fun3 f) +let vfun4 f = VFunction (Fun4 f) +let vfun5 f = VFunction (Fun5 f) +let vbool b = VBool b +let vfloat f = VFloat f -let enc_inst path fields = - let ctx = get_ctx() in - let p = (try Hashtbl.find ctx.prototypes path with Not_found -> try - (match get_path ctx (path@["prototype"]) Nast.null_pos with - | VObject o -> Hashtbl.add ctx.prototypes path o; o - | _ -> raise (Runtime VNull)) - with Runtime _ -> - failwith ("Prototype not found " ^ String.concat "." path) - ) in - let o = obj hash fields in - o.oproto <- Some p; - VObject o +let encode_unsafe o = VAbstract (AUnsafe o) -let enc_array l = - let a = Array.of_list l in - enc_inst ["Array"] [ - "__a", VArray a; - "length", VInt (Array.length a); - ] - -let enc_string s = - enc_inst ["String"] [ - "__s", VString s; - "length", VInt (String.length s) - ] - -let enc_hash h = - enc_inst ["haxe";"ds";"StringMap"] [ - "h", VAbstract (AHash h); - ] - -let enc_obj l = VObject (obj hash l) - -let enc_enum (i:enum_index) index pl = - let eindex : int = Obj.magic i in - let edef = (get_ctx()).enums.(eindex) in - if pl = [] then - fst edef.(index) - else - enc_inst ["haxe";"macro";enum_name i] [ - "tag", VString (snd edef.(index)); - "index", VInt index; - "args", VArray (Array.of_list pl); - ] - -let compiler_error msg pos = - exc (enc_inst ["haxe";"macro";"Error"] [("message",enc_string msg);("pos",encode_pos pos)]) - -let encode_const c = - let tag, pl = match c with - | Int s -> 0, [enc_string s] - | Float s -> 1, [enc_string s] - | String s -> 2, [enc_string s] - | Ident s -> 3, [enc_string s] - | Regexp (s,opt) -> 4, [enc_string s;enc_string opt] - in - enc_enum IConst tag pl - -let rec encode_binop op = - let tag, pl = match op with - | OpAdd -> 0, [] - | OpMult -> 1, [] - | OpDiv -> 2, [] - | OpSub -> 3, [] - | OpAssign -> 4, [] - | OpEq -> 5, [] - | OpNotEq -> 6, [] - | OpGt -> 7, [] - | OpGte -> 8, [] - | OpLt -> 9, [] - | OpLte -> 10, [] - | OpAnd -> 11, [] - | OpOr -> 12, [] - | OpXor -> 13, [] - | OpBoolAnd -> 14, [] - | OpBoolOr -> 15, [] - | OpShl -> 16, [] - | OpShr -> 17, [] - | OpUShr -> 18, [] - | OpMod -> 19, [] - | OpAssignOp op -> 20, [encode_binop op] - | OpInterval -> 21, [] - | OpArrow -> 22, [] - in - enc_enum IBinop tag pl - -let encode_unop op = - let tag = match op with - | Increment -> 0 - | Decrement -> 1 - | Not -> 2 - | Neg -> 3 - | NegBits -> 4 - in - enc_enum IUnop tag [] - -let rec encode_path t = - let fields = [ - "pack", enc_array (List.map enc_string t.tpackage); - "name", enc_string t.tname; - "params", enc_array (List.map encode_tparam t.tparams); - ] in - enc_obj (match t.tsub with - | None -> fields - | Some s -> ("sub", enc_string s) :: fields) - -and encode_tparam = function - | TPType t -> enc_enum ITParam 0 [encode_ctype t] - | TPExpr e -> enc_enum ITParam 1 [encode_expr e] - -and encode_access a = - let tag = match a with - | APublic -> 0 - | APrivate -> 1 - | AStatic -> 2 - | AOverride -> 3 - | ADynamic -> 4 - | AInline -> 5 - | AMacro -> 6 - in - enc_enum IAccess tag [] - -and encode_meta_entry (m,ml,p) = - enc_obj [ - "name", enc_string (fst (MetaInfo.to_string m)); - "params", enc_array (List.map encode_expr ml); - "pos", encode_pos p; - ] - -and encode_meta_content m = - enc_array (List.map encode_meta_entry m) - -and encode_field (f:class_field) = - let tag, pl = match f.cff_kind with - | FVar (t,e) -> 0, [null encode_ctype t; null encode_expr e] - | FFun f -> 1, [encode_fun f] - | FProp (get,set, t, e) -> 2, [enc_string get; enc_string set; null encode_ctype t; null encode_expr e] - in - enc_obj [ - "name",enc_string f.cff_name; - "doc", null enc_string f.cff_doc; - "pos", encode_pos f.cff_pos; - "kind", enc_enum IField tag pl; - "meta", encode_meta_content f.cff_meta; - "access", enc_array (List.map encode_access f.cff_access); - ] - -and encode_ctype t = - let tag, pl = match t with - | CTPath p -> - 0, [encode_path p] - | CTFunction (pl,r) -> - 1, [enc_array (List.map encode_ctype pl);encode_ctype r] - | CTAnonymous fl -> - 2, [enc_array (List.map encode_field fl)] - | CTParent t -> - 3, [encode_ctype t] - | CTExtend (tl,fields) -> - 4, [enc_array (List.map encode_path tl); enc_array (List.map encode_field fields)] - | CTOptional t -> - 5, [encode_ctype t] - in - enc_enum ICType tag pl - -and encode_tparam_decl tp = - enc_obj [ - "name", enc_string tp.tp_name; - "params", enc_array (List.map encode_tparam_decl tp.tp_params); - "constraints", enc_array (List.map encode_ctype tp.tp_constraints); - ] - -and encode_fun f = - enc_obj [ - "params", enc_array (List.map encode_tparam_decl f.f_params); - "args", enc_array (List.map (fun (n,opt,t,e) -> - enc_obj [ - "name", enc_string n; - "opt", VBool opt; - "type", null encode_ctype t; - "value", null encode_expr e; - ] - ) f.f_args); - "ret", null encode_ctype f.f_type; - "expr", null encode_expr f.f_expr - ] - -and encode_expr e = - let rec loop (e,p) = - let tag, pl = match e with - | EConst c -> - 0, [encode_const c] - | EArray (e1,e2) -> - 1, [loop e1;loop e2] - | EBinop (op,e1,e2) -> - 2, [encode_binop op;loop e1;loop e2] - | EField (e,f) -> - 3, [loop e;enc_string f] - | EParenthesis e -> - 4, [loop e] - | EObjectDecl fl -> - 5, [enc_array (List.map (fun (f,e) -> enc_obj [ - "field",enc_string f; - "expr",loop e; - ]) fl)] - | EArrayDecl el -> - 6, [enc_array (List.map loop el)] - | ECall (e,el) -> - 7, [loop e;enc_array (List.map loop el)] - | ENew (p,el) -> - 8, [encode_path p; enc_array (List.map loop el)] - | EUnop (op,flag,e) -> - 9, [encode_unop op; VBool (match flag with Prefix -> false | Postfix -> true); loop e] - | EVars vl -> - 10, [enc_array (List.map (fun (v,t,eo) -> - enc_obj [ - "name",enc_string v; - "type",null encode_ctype t; - "expr",null loop eo; - ] - ) vl)] - | EFunction (name,f) -> - 11, [null enc_string name; encode_fun f] - | EBlock el -> - 12, [enc_array (List.map loop el)] - | EFor (e,eloop) -> - 13, [loop e;loop eloop] - | EIn (e1,e2) -> - 14, [loop e1;loop e2] - | EIf (econd,e,eelse) -> - 15, [loop econd;loop e;null loop eelse] - | EWhile (econd,e,flag) -> - 16, [loop econd;loop e;VBool (match flag with NormalWhile -> true | DoWhile -> false)] - | ESwitch (e,cases,eopt) -> - 17, [loop e;enc_array (List.map (fun (ecl,eg,e) -> - enc_obj [ - "values",enc_array (List.map loop ecl); - "guard",null loop eg; - "expr",null loop e - ] - ) cases);null encode_null_expr eopt] - | ETry (e,catches) -> - 18, [loop e;enc_array (List.map (fun (v,t,e) -> - enc_obj [ - "name",enc_string v; - "type",encode_ctype t; - "expr",loop e - ] - ) catches)] - | EReturn eo -> - 19, [null loop eo] - | EBreak -> - 20, [] - | EContinue -> - 21, [] - | EUntyped e -> - 22, [loop e] - | EThrow e -> - 23, [loop e] - | ECast (e,t) -> - 24, [loop e; null encode_ctype t] - | EDisplay (e,flag) -> - 25, [loop e; VBool flag] - | EDisplayNew t -> - 26, [encode_path t] - | ETernary (econd,e1,e2) -> - 27, [loop econd;loop e1;loop e2] - | ECheckType (e,t) -> - 28, [loop e; encode_ctype t] - | EMeta (m,e) -> - 29, [encode_meta_entry m;loop e] - in - enc_obj [ - "pos", encode_pos p; - "expr", enc_enum IExpr tag pl; - ] - in - loop e - -and encode_null_expr e = - match e with - | None -> - enc_obj ["pos", VNull;"expr",VNull] - | Some e -> - encode_expr e - -(* ---------------------------------------------------------------------- *) -(* EXPR DECODING *) - -let opt f v = - match v with - | VNull -> None - | _ -> Some (f v) - -let opt_list f v = - match v with - | VNull -> [] - | _ -> f v - -let decode_pos = function - | VAbstract (APos p) -> p - | _ -> raise Invalid_expr +let value_string v = to_string (get_ctx()) 0 v let field v f = match v with | VObject o -> get_field o (hash f) | _ -> raise Invalid_expr -let decode_enum v = - match field v "index", field v "args" with - | VInt i, VNull -> i, [] - | VInt i, VArray a -> i, Array.to_list a - | _ -> raise Invalid_expr - -let dec_bool = function - | VBool b -> b - | _ -> raise Invalid_expr - let dec_string v = match field v "__s" with | VString s -> s | _ -> raise Invalid_expr +let decode_bytes v = + match field v "b" with + | VString s -> s + | _ -> raise Invalid_expr + let dec_array v = match field v "__a", field v "length" with | VArray a, VInt l -> Array.to_list (if Array.length a = l then a else Array.sub a 0 l) | _ -> raise Invalid_expr -let decode_const c = - match decode_enum c with - | 0, [s] -> Int (dec_string s) - | 1, [s] -> Float (dec_string s) - | 2, [s] -> String (dec_string s) - | 3, [s] -> Ident (dec_string s) - | 4, [s;opt] -> Regexp (dec_string s, dec_string opt) - | 5, [s] -> Ident (dec_string s) (** deprecated CType, keep until 3.0 release **) +let decode_lazytype = function + | VAbstract (ALazyType (t,_)) -> t | _ -> raise Invalid_expr -let rec decode_op op = - match decode_enum op with - | 0, [] -> OpAdd - | 1, [] -> OpMult - | 2, [] -> OpDiv - | 3, [] -> OpSub - | 4, [] -> OpAssign - | 5, [] -> OpEq - | 6, [] -> OpNotEq - | 7, [] -> OpGt - | 8, [] -> OpGte - | 9, [] -> OpLt - | 10, [] -> OpLte - | 11, [] -> OpAnd - | 12, [] -> OpOr - | 13, [] -> OpXor - | 14, [] -> OpBoolAnd - | 15, [] -> OpBoolOr - | 16, [] -> OpShl - | 17, [] -> OpShr - | 18, [] -> OpUShr - | 19, [] -> OpMod - | 20, [op] -> OpAssignOp (decode_op op) - | 21, [] -> OpInterval - | 22,[] -> OpArrow - | _ -> raise Invalid_expr +let encode_lazytype t f = VAbstract (ALazyType (t,f)) +let encode_tdecl t = VAbstract (ATDecl t) -let decode_unop op = - match decode_enum op with - | 0, [] -> Increment - | 1, [] -> Decrement - | 2, [] -> Not - | 3, [] -> Neg - | 4, [] -> NegBits +let decode_tdecl = function + | VAbstract (ATDecl t) -> t | _ -> raise Invalid_expr -let decode_import_mode t = - match decode_enum t with - | 0, [] -> INormal - | 1, [alias] -> IAsName (dec_string alias) - | 2, [] -> IAll +let dec_int = function + | VInt i -> i + | VInt32 i -> Int32.to_int i | _ -> raise Invalid_expr -let decode_import t = (List.map (fun o -> ((dec_string (field o "name")), (decode_pos (field o "pos")))) (dec_array (field t "path")), decode_import_mode (field t "mode")) - -let rec decode_path t = - { - tpackage = List.map dec_string (dec_array (field t "pack")); - tname = dec_string (field t "name"); - tparams = (match field t "params" with VNull -> [] | a -> List.map decode_tparam (dec_array a)); - tsub = opt dec_string (field t "sub"); - } - -and decode_tparam v = - match decode_enum v with - | 0,[t] -> TPType (decode_ctype t) - | 1,[e] -> TPExpr (decode_expr e) +let dec_i32 = function + | VInt i -> Int32.of_int i + | VInt32 i -> i | _ -> raise Invalid_expr -and decode_tparams = function - | VNull -> [] - | a -> List.map decode_tparam_decl (dec_array a) - -and decode_tparam_decl v = - { - tp_name = dec_string (field v "name"); - tp_constraints = (match field v "constraints" with VNull -> [] | a -> List.map decode_ctype (dec_array a)); - tp_params = decode_tparams (field v "params"); - } +let dec_bytes = function + | VString s -> s + | _ -> raise Invalid_expr -and decode_fun v = - { - f_params = decode_tparams (field v "params"); - f_args = List.map (fun o -> - (dec_string (field o "name"),(match field o "opt" with VNull -> false | v -> dec_bool v),opt decode_ctype (field o "type"),opt decode_expr (field o "value")) - ) (dec_array (field v "args")); - f_type = opt decode_ctype (field v "ret"); - f_expr = opt decode_expr (field v "expr"); - } +let encode_pos p = + VAbstract (APos p) -and decode_access v = - match decode_enum v with - | 0, [] -> APublic - | 1, [] -> APrivate - | 2, [] -> AStatic - | 3, [] -> AOverride - | 4, [] -> ADynamic - | 5, [] -> AInline - | 6, [] -> AMacro - | _ -> raise Invalid_expr +let enc_inst path fields = + let ctx = get_ctx() in + let p = (try Hashtbl.find ctx.prototypes path with Not_found -> try + (match get_path ctx (path@["prototype"]) Nast.null_pos with + | VObject o -> Hashtbl.add ctx.prototypes path o; o + | _ -> raise (Runtime VNull)) + with Runtime _ -> + failwith ("Prototype not found " ^ String.concat "." path) + ) in + let o = obj hash fields in + o.oproto <- Some p; + VObject o -and decode_meta_entry v = - MetaInfo.from_string (dec_string (field v "name")), (match field v "params" with VNull -> [] | a -> List.map decode_expr (dec_array a)), decode_pos (field v "pos") - -and decode_meta_content = function - | VNull -> [] - | v -> List.map decode_meta_entry (dec_array v) - -and decode_field v = - let fkind = match decode_enum (field v "kind") with - | 0, [t;e] -> - FVar (opt decode_ctype t, opt decode_expr e) - | 1, [f] -> - FFun (decode_fun f) - | 2, [get;set; t; e] -> - FProp (dec_string get, dec_string set, opt decode_ctype t, opt decode_expr e) - | _ -> - raise Invalid_expr - in - { - cff_name = dec_string (field v "name"); - cff_doc = opt dec_string (field v "doc"); - cff_pos = decode_pos (field v "pos"); - cff_kind = fkind; - cff_access = List.map decode_access (opt_list dec_array (field v "access")); - cff_meta = opt_list decode_meta_content (field v "meta"); - } +let enc_array l = + let a = Array.of_list l in + enc_inst ["Array"] [ + "__a", VArray a; + "length", VInt (Array.length a); + ] -and decode_ctype t = - match decode_enum t with - | 0, [p] -> - CTPath (decode_path p) - | 1, [a;r] -> - CTFunction (List.map decode_ctype (dec_array a), decode_ctype r) - | 2, [fl] -> - CTAnonymous (List.map decode_field (dec_array fl)) - | 3, [t] -> - CTParent (decode_ctype t) - | 4, [tl;fl] -> - CTExtend (List.map decode_path (dec_array tl), List.map decode_field (dec_array fl)) - | 5, [t] -> - CTOptional (decode_ctype t) - | _ -> - raise Invalid_expr +let enc_string s = + enc_inst ["String"] [ + "__s", VString s; + "length", VInt (String.length s) + ] -let rec decode_expr v = - let rec loop v = - (decode (field v "expr"), decode_pos (field v "pos")) - and decode e = - match decode_enum e with - | 0, [c] -> - EConst (decode_const c) - | 1, [e1;e2] -> - EArray (loop e1, loop e2) - | 2, [op;e1;e2] -> - EBinop (decode_op op, loop e1, loop e2) - | 3, [e;f] -> - EField (loop e, dec_string f) - | 4, [e] -> - EParenthesis (loop e) - | 5, [a] -> - EObjectDecl (List.map (fun o -> - (dec_string (field o "field"), loop (field o "expr")) - ) (dec_array a)) - | 6, [a] -> - EArrayDecl (List.map loop (dec_array a)) - | 7, [e;el] -> - ECall (loop e,List.map loop (dec_array el)) - | 8, [t;el] -> - ENew (decode_path t,List.map loop (dec_array el)) - | 9, [op;VBool f;e] -> - EUnop (decode_unop op,(if f then Postfix else Prefix),loop e) - | 10, [vl] -> - EVars (List.map (fun v -> - (dec_string (field v "name"),opt decode_ctype (field v "type"),opt loop (field v "expr")) - ) (dec_array vl)) - | 11, [fname;f] -> - EFunction (opt dec_string fname,decode_fun f) - | 12, [el] -> - EBlock (List.map loop (dec_array el)) - | 13, [e1;e2] -> - EFor (loop e1, loop e2) - | 14, [e1;e2] -> - EIn (loop e1, loop e2) - | 15, [e1;e2;e3] -> - EIf (loop e1, loop e2, opt loop e3) - | 16, [e1;e2;VBool flag] -> - EWhile (loop e1,loop e2,if flag then NormalWhile else DoWhile) - | 17, [e;cases;eo] -> - let cases = List.map (fun c -> - (List.map loop (dec_array (field c "values")),opt loop (field c "guard"),opt loop (field c "expr")) - ) (dec_array cases) in - ESwitch (loop e,cases,opt decode_null_expr eo) - | 18, [e;catches] -> - let catches = List.map (fun c -> - (dec_string (field c "name"),decode_ctype (field c "type"),loop (field c "expr")) - ) (dec_array catches) in - ETry (loop e, catches) - | 19, [e] -> - EReturn (opt loop e) - | 20, [] -> - EBreak - | 21, [] -> - EContinue - | 22, [e] -> - EUntyped (loop e) - | 23, [e] -> - EThrow (loop e) - | 24, [e;t] -> - ECast (loop e,opt decode_ctype t) - | 25, [e;f] -> - EDisplay (loop e,dec_bool f) - | 26, [t] -> - EDisplayNew (decode_path t) - | 27, [e1;e2;e3] -> - ETernary (loop e1,loop e2,loop e3) - | 28, [e;t] -> - ECheckType (loop e, decode_ctype t) - | 29, [m;e] -> - EMeta (decode_meta_entry m,loop e) - | 30, [e;f] -> - EField (loop e, dec_string f) (*** deprecated EType, keep until haxe 3 **) - | _ -> - raise Invalid_expr - in - try - loop v - with Stack_overflow -> - raise Invalid_expr +let encode_bytes s = + enc_inst ["haxe";"io";"Bytes"] [ + "b", VString s; + "length", VInt (String.length s) + ] -and decode_null_expr v = - match field v "expr" with - | VNull -> None - | _ -> Some (decode_expr v) +let enc_hash h = + enc_inst ["haxe";"ds";"StringMap"] [ + "h", VAbstract (AHash h); + ] +let enc_obj _ l = VObject (obj hash l) -(* ---------------------------------------------------------------------- *) -(* TYPE ENCODING *) +let encode_enum (i:enum_type) pos index pl = + let eindex : int = Obj.magic i in + let edef = (get_ctx()).enums.(eindex) in + if pl = [] then + fst edef.(index) + else + enc_inst ["haxe";"macro";enum_name i] ( + ("tag", VString (snd edef.(index))) :: + ("index", VInt index) :: + ("args", VArray (Array.of_list pl)) :: + (match pos with None -> [] | Some p -> ["pos", encode_pos p]) + ) let encode_ref v convert tostr = - enc_obj [ + enc_obj O__Const [ "get", VFunction (Fun0 (fun() -> convert v)); "__string", VFunction (Fun0 (fun() -> VString (tostr()))); "toString", VFunction (Fun0 (fun() -> enc_string (tostr()))); @@ -4293,813 +2915,189 @@ let decode_ref v : 'a = | VAbstract (AUnsafe t) -> Obj.obj t | _ -> raise Invalid_expr -let encode_pmap convert m = +let encode_string_map convert m = let h = Hashtbl.create 0 in PMap.iter (fun k v -> Hashtbl.add h (VString k) (convert v)) m; enc_hash h -let encode_pmap_array convert m = - let l = ref [] in - PMap.iter (fun _ v -> l := !l @ [(convert v)]) m; - enc_array !l - -let encode_array convert l = - enc_array (List.map convert l) - -let encode_meta m set = - let meta = ref m in - enc_obj [ - "get", VFunction (Fun0 (fun() -> - encode_meta_content (!meta) - )); - "add", VFunction (Fun3 (fun k vl p -> - (try - let el = List.map decode_expr (dec_array vl) in - meta := (MetaInfo.from_string (dec_string k), el, decode_pos p) :: !meta; - set (!meta) - with Invalid_expr -> - failwith "Invalid expression"); - VNull - )); - "extract", VFunction (Fun1 (fun k -> - let k = MetaInfo.from_string (try dec_string k with Invalid_expr -> raise Builtin_error) in - encode_array encode_meta_entry (List.filter (fun (m,_,_) -> m = k) (!meta)) - )); - "remove", VFunction (Fun1 (fun k -> - let k = MetaInfo.from_string (try dec_string k with Invalid_expr -> raise Builtin_error) in - meta := List.filter (fun (m,_,_) -> m <> k) (!meta); - set (!meta); - VNull - )); - "has", VFunction (Fun1 (fun k -> - let k = MetaInfo.from_string (try dec_string k with Invalid_expr -> raise Builtin_error) in - VBool (List.exists (fun (m,_,_) -> m = k) (!meta)); - )); - ] - -let rec encode_mtype t fields = - let i = t_infos t in - enc_obj ([ - "__t", VAbstract (ATDecl t); - "pack", enc_array (List.map enc_string (fst i.mt_path)); - "name", enc_string (snd i.mt_path); - "pos", encode_pos i.mt_pos; - "module", enc_string (s_type_path i.mt_module.m_path); - "isPrivate", VBool i.mt_private; - "meta", encode_meta i.mt_meta (fun m -> i.mt_meta <- m); - "doc", null enc_string i.mt_doc; - "params", encode_type_params i.mt_params; - ] @ fields) - -and encode_type_params tl = - enc_array (List.map (fun (n,t) -> enc_obj ["name",enc_string n;"t",encode_type t]) tl) - -and encode_tenum e = - encode_mtype (TEnumDecl e) [ - "isExtern", VBool e.e_extern; - "exclude", VFunction (Fun0 (fun() -> e.e_extern <- true; VNull)); - "constructs", encode_pmap encode_efield e.e_constrs; - "names", enc_array (List.map enc_string e.e_names); - ] - -and encode_tabstract a = - encode_mtype (TAbstractDecl a) [ - "type", encode_type a.a_this; - "impl", (match a.a_impl with None -> VNull | Some c -> encode_clref c); - "binops", enc_array (List.map (fun (op,cf) -> enc_obj [ "op",encode_binop op; "field",encode_cfield cf]) a.a_ops); - "unops", enc_array (List.map (fun (op,postfix,cf) -> enc_obj [ "op",encode_unop op; "isPostfix",VBool (match postfix with Postfix -> true | Prefix -> false); "field",encode_cfield cf]) a.a_unops); - "from", enc_array ((List.map (fun t -> enc_obj [ "t",encode_type t; "field",VNull]) a.a_from) @ (List.map (fun (t,cf) -> enc_obj [ "t",encode_type t; "field",encode_cfield cf]) a.a_from_field)); - "to", enc_array ((List.map (fun t -> enc_obj [ "t",encode_type t; "field",VNull]) a.a_to) @ (List.map (fun (t,cf) -> enc_obj [ "t",encode_type t; "field",encode_cfield cf]) a.a_to_field)); - "array", enc_array (List.map encode_cfield a.a_array); - ] - -and encode_efield f = - enc_obj [ - "name", enc_string f.ef_name; - "type", encode_type f.ef_type; - "pos", encode_pos f.ef_pos; - "index", VInt f.ef_index; - "meta", encode_meta f.ef_meta (fun m -> f.ef_meta <- m); - "doc", null enc_string f.ef_doc; - "params", encode_type_params f.ef_params; - ] - -and encode_cfield f = - enc_obj [ - "name", enc_string f.cf_name; - "type", (match f.cf_kind with Method _ -> encode_lazy_type f.cf_type | _ -> encode_type f.cf_type); - "isPublic", VBool f.cf_public; - "params", encode_type_params f.cf_params; - "meta", encode_meta f.cf_meta (fun m -> f.cf_meta <- m); - "expr", (VFunction (Fun0 (fun() -> ignore(follow f.cf_type); (match f.cf_expr with None -> VNull | Some e -> encode_texpr e)))); - "kind", encode_field_kind f.cf_kind; - "pos", encode_pos f.cf_pos; - "doc", null enc_string f.cf_doc; - ] - -and encode_field_kind k = - let tag, pl = (match k with - | Type.Var v -> 0, [encode_var_access v.v_read; encode_var_access v.v_write] - | Method m -> 1, [encode_method_kind m] - ) in - enc_enum IFieldKind tag pl - -and encode_var_access a = - let tag, pl = (match a with - | AccNormal -> 0, [] - | AccNo -> 1, [] - | AccNever -> 2, [] - | AccResolve -> 3, [] - | AccCall -> 4, [] - | AccInline -> 5, [] - | AccRequire (s,msg) -> 6, [enc_string s; null enc_string msg] - ) in - enc_enum IVarAccess tag pl - -and encode_method_kind m = - let tag, pl = (match m with - | MethNormal -> 0, [] - | MethInline -> 1, [] - | MethDynamic -> 2, [] - | MethMacro -> 3, [] - ) in - enc_enum IMethodKind tag pl - -and encode_class_kind k = - let tag, pl = (match k with - | KNormal -> 0, [] - | KTypeParameter pl -> 1, [encode_tparams pl] - | KExtension (cl, params) -> 2, [encode_clref cl; encode_tparams params] - | KExpr e -> 3, [encode_expr e] - | KGeneric -> 4, [] - | KGenericInstance (cl, params) -> 5, [encode_clref cl; encode_tparams params] - | KMacroType -> 6, [] - | KAbstractImpl a -> 7, [encode_abref a] - | KGenericBuild cfl -> 8, [] - ) in - enc_enum IClassKind tag pl - -and encode_tclass c = - ignore(c.cl_build()); - encode_mtype (TClassDecl c) [ - "kind", encode_class_kind c.cl_kind; - "isExtern", VBool c.cl_extern; - "exclude", VFunction (Fun0 (fun() -> c.cl_extern <- true; c.cl_init <- None; VNull)); - "isInterface", VBool c.cl_interface; - "superClass", (match c.cl_super with - | None -> VNull - | Some (c,pl) -> enc_obj ["t",encode_clref c;"params",encode_tparams pl] - ); - "interfaces", enc_array (List.map (fun (c,pl) -> enc_obj ["t",encode_clref c;"params",encode_tparams pl]) c.cl_implements); - "fields", encode_ref c.cl_ordered_fields (encode_array encode_cfield) (fun() -> "class fields"); - "statics", encode_ref c.cl_ordered_statics (encode_array encode_cfield) (fun() -> "class fields"); - "constructor", (match c.cl_constructor with None -> VNull | Some cf -> encode_cfref cf); - "init", (match c.cl_init with None -> VNull | Some e -> encode_texpr e); - "overrides", (enc_array (List.map encode_cfref c.cl_overrides)) - ] - -and encode_ttype t = - encode_mtype (TTypeDecl t) [ - "isExtern", VBool false; - "exclude", VFunction (Fun0 (fun() -> VNull)); - "type", encode_type t.t_type; - ] - -and encode_tanon a = - enc_obj [ - "fields", encode_pmap_array encode_cfield a.a_fields; - "status", encode_anon_status !(a.a_status); - ] - -and encode_anon_status s = - let tag, pl = (match s with - | Closed -> 0, [] - | Opened -> 1, [] - | Type.Const -> 2, [] - | Extend tl -> 3, [encode_ref tl (fun tl -> enc_array (List.map encode_type tl)) (fun() -> "")] - | Statics cl -> 4, [encode_clref cl] - | EnumStatics en -> 5, [encode_enref en] - | AbstractStatics ab -> 6, [encode_abref ab] - ) - in - enc_enum IAnonStatus tag pl - -and encode_tparams pl = - enc_array (List.map encode_type pl) - -and encode_clref c = - encode_ref c encode_tclass (fun() -> s_type_path c.cl_path) - -and encode_enref en = - encode_ref en encode_tenum (fun() -> s_type_path en.e_path) - -and encode_cfref cf = - encode_ref cf encode_cfield (fun() -> cf.cf_name) - -and encode_abref ab = - encode_ref ab encode_tabstract (fun() -> s_type_path ab.a_path) - -and encode_type t = - let rec loop = function - | TMono r -> - (match !r with - | None -> 0, [encode_ref r (fun r -> match !r with None -> VNull | Some t -> encode_type t) (fun() -> "")] - | Some t -> loop t) - | TEnum (e, pl) -> - 1 , [encode_ref e encode_tenum (fun() -> s_type_path e.e_path); encode_tparams pl] - | TInst (c, pl) -> - 2 , [encode_clref c; encode_tparams pl] - | TType (t,pl) -> - 3 , [encode_ref t encode_ttype (fun() -> s_type_path t.t_path); encode_tparams pl] - | TFun (pl,ret) -> - let pl = List.map (fun (n,o,t) -> - enc_obj [ - "name",enc_string n; - "opt",VBool o; - "t",encode_type t - ] - ) pl in - 4 , [enc_array pl; encode_type ret] - | TAnon a -> - 5, [encode_ref a encode_tanon (fun() -> "")] - | TDynamic tsub as t -> - if t == t_dynamic then - 6, [VNull] - else - 6, [encode_type tsub] - | TLazy f -> - loop (!f()) - | TAbstract (a, pl) -> - 8, [encode_abref a; encode_tparams pl] - in - let tag, pl = loop t in - enc_enum IType tag pl - -and encode_lazy_type t = - let rec loop = function - | TMono r -> - (match !r with - | Some t -> loop t - | _ -> encode_type t) - | TLazy f -> - enc_enum IType 7 [VAbstract (ALazyType f)] - | _ -> - encode_type t - in - loop t - -and decode_type t = - match decode_enum t with - | 0, [r] -> TMono (decode_ref r) - | 1, [e; pl] -> TEnum (decode_ref e, List.map decode_type (dec_array pl)) - | 2, [c; pl] -> TInst (decode_ref c, List.map decode_type (dec_array pl)) - | 3, [t; pl] -> TType (decode_ref t, List.map decode_type (dec_array pl)) - | 4, [pl; r] -> TFun (List.map (fun p -> dec_string (field p "name"), dec_bool (field p "opt"), decode_type (field p "t")) (dec_array pl), decode_type r) - | 5, [a] -> TAnon (decode_ref a) - | 6, [VNull] -> t_dynamic - | 6, [t] -> TDynamic (decode_type t) - | 7, [VAbstract (ALazyType f)] -> TLazy f - | 8, [a; pl] -> TAbstract (decode_ref a, List.map decode_type (dec_array pl)) - | _ -> raise Invalid_expr - -let decode_tdecl v = - match v with - | VObject o -> - (match get_field o (hash "__t") with - | VAbstract (ATDecl t) -> t - | _ -> raise Invalid_expr) - | _ -> raise Invalid_expr - -(* ---------------------------------------------------------------------- *) -(* TEXPR Encoding *) - -let vopt f v = match v with - | None -> VNull - | Some v -> f v - -let rec encode_tconst c = - let tag, pl = match c with - | TInt i -> 0,[best_int i] - | TFloat f -> 1,[enc_string f] - | TString s -> 2,[enc_string s] - | TBool b -> 3,[VBool b] - | TNull -> 4,[] - | TThis -> 5,[] - | TSuper -> 6,[] - in - enc_enum ITConstant tag pl - -and encode_tvar v = - let f_extra (pl,e) = - enc_obj [ - "params",encode_type_params pl; - "expr",vopt encode_texpr e - ] - in - enc_obj [ - "id", VInt v.v_id; - "name", enc_string v.v_name; - "t", encode_type v.v_type; - "capture", VBool v.v_capture; - "extra", vopt f_extra v.v_extra; - "meta", encode_meta_content v.v_meta; - "$", VAbstract (AUnsafe (Obj.repr v)); - ] - -and encode_module_type mt = - let tag,pl = match mt with - | TClassDecl c -> 0,[encode_clref c] - | TEnumDecl e -> 1,[encode_enref e] - | TTypeDecl t -> 2,[encode_ref t encode_ttype (fun () -> s_type_path t.t_path)] - | TAbstractDecl a -> 3,[encode_abref a] - in - enc_enum IModuleType tag pl - -and encode_tfunc func = - enc_obj [ - "args",enc_array (List.map (fun (v,c) -> - enc_obj [ - "v",encode_tvar v; - "value",match c with None -> VNull | Some c -> encode_tconst c - ] - ) func.tf_args); - "t",encode_type func.tf_type; - "expr",encode_texpr func.tf_expr - ] - -and encode_field_access fa = - let encode_instance c tl = - enc_obj [ - "c",encode_clref c; - "params",encode_tparams tl - ] - in - let tag,pl = match fa with - | FInstance(c,tl,cf) -> 0,[encode_clref c;encode_tparams tl;encode_cfref cf] - | FStatic(c,cf) -> 1,[encode_clref c;encode_cfref cf] - | FAnon(cf) -> 2,[encode_cfref cf] - | FDynamic(s) -> 3,[enc_string s] - | FClosure(co,cf) -> 4,[(match co with Some (c,tl) -> encode_instance c tl | None -> VNull);encode_cfref cf] - | FEnum(en,ef) -> 5,[encode_enref en;encode_efield ef] - in - enc_enum IFieldAccess tag pl - -and encode_texpr e = - let rec loop e = - let tag, pl = match e.eexpr with - | TConst c -> 0,[encode_tconst c] - | TLocal v -> 1,[encode_tvar v] - | TArray(e1,e2) -> 2,[loop e1; loop e2] - | TBinop(op,e1,e2) -> 3,[encode_binop op;loop e1;loop e2] - | TField(e1,fa) -> 4,[loop e1;encode_field_access fa] - | TTypeExpr mt -> 5,[encode_module_type mt] - | TParenthesis e1 -> 6,[loop e1] - | TObjectDecl fl -> 7, [enc_array (List.map (fun (f,e) -> - enc_obj [ - "name",enc_string f; - "expr",loop e; - ]) fl)] - | TArrayDecl el -> 8,[encode_texpr_list el] - | TCall(e1,el) -> 9,[loop e1;encode_texpr_list el] - | TNew(c,pl,el) -> 10,[encode_clref c;encode_tparams pl;encode_texpr_list el] - | TUnop(op,flag,e1) -> 11,[encode_unop op;VBool (flag = Postfix);loop e1] - | TFunction func -> 12,[encode_tfunc func] - | TVar (v,eo) -> 13,[encode_tvar v;vopt encode_texpr eo] - | TBlock el -> 14,[encode_texpr_list el] - | TFor(v,e1,e2) -> 15,[encode_tvar v;loop e1;loop e2] - | TIf(eif,ethen,eelse) -> 16,[loop eif;loop ethen;vopt encode_texpr eelse] - | TWhile(econd,e1,flag) -> 17,[loop econd;loop e1;VBool (flag = NormalWhile)] - | TSwitch(e1,cases,edef) -> 18,[ - loop e1; - enc_array (List.map (fun (el,e) -> enc_obj ["values",encode_texpr_list el;"expr",loop e]) cases); - vopt encode_texpr edef - ] - | TTry(e1,catches) -> 19,[ - loop e1; - enc_array (List.map (fun (v,e) -> - enc_obj [ - "v",encode_tvar v; - "expr",loop e - ]) catches - )] - | TReturn e1 -> 20,[vopt encode_texpr e1] - | TBreak -> 21,[] - | TContinue -> 22,[] - | TThrow e1 -> 23,[loop e1] - | TCast(e1,mt) -> 24,[loop e1;match mt with None -> VNull | Some mt -> encode_module_type mt] - | TMeta(m,e1) -> 25,[encode_meta_entry m;loop e1] - | TEnumParameter(e1,ef,i) -> 26,[loop e1;encode_efield ef;VInt i] - in - enc_obj [ - "pos", encode_pos e.epos; - "expr", enc_enum ITypedExpr tag pl; - "t", encode_type e.etype - ] - in - loop e - -and encode_texpr_list el = - enc_array (List.map encode_texpr el) - -(* ---------------------------------------------------------------------- *) -(* TEXPR Decoding *) - -let decode_tconst c = - match decode_enum c with - | 0, [s] -> TInt (match s with VInt i -> Int32.of_int i | VInt32 i -> i | _ -> raise Invalid_expr) - | 1, [s] -> TFloat (dec_string s) - | 2, [s] -> TString (dec_string s) - | 3, [s] -> TBool (dec_bool s) - | 4, [] -> TNull - | 5, [] -> TThis - | 6, [] -> TSuper +let decode_pos = function + | VAbstract (APos p) -> p | _ -> raise Invalid_expr -let decode_type_params v = - List.map (fun v -> dec_string (field v "name"),decode_type (field v "t")) (dec_array v) - -let decode_tvar v = - match field v "$" with - | VAbstract (AUnsafe t) -> Obj.obj t +let decode_enum v = + match field v "index", field v "args" with + | VInt i, VNull -> i, [] + | VInt i, VArray a -> i, Array.to_list a | _ -> raise Invalid_expr -let decode_var_access v = - match decode_enum v with - | 0, [] -> AccNormal - | 1, [] -> AccNo - | 2, [] -> AccNever - | 3, [] -> AccResolve - | 4, [] -> AccCall - | 5, [] -> AccInline - | 6, [s1;s2] -> AccRequire(dec_string s1, opt dec_string s2) - | _ -> raise Invalid_expr +let decode_enum_with_pos v = + (match field v "index", field v "args" with + | VInt i, VNull -> i, [] + | VInt i, VArray a -> i, Array.to_list a + | _ -> raise Invalid_expr),(match field v "pos" with + | VAbstract(APos p) -> p + | _ -> Globals.null_pos) (* Can happen from reification and other sources. *) -let decode_method_kind v = - match decode_enum v with - | 0, [] -> MethNormal - | 1, [] -> MethInline - | 2, [] -> MethDynamic - | 3, [] -> MethMacro +let dec_bool = function + | VBool b -> b | _ -> raise Invalid_expr -let decode_field_kind v = - match decode_enum v with - | 0, [vr;vw] -> Type.Var({v_read = decode_var_access vr; v_write = decode_var_access vw}) - | 1, [m] -> Method (decode_method_kind m) +let decode_unsafe = function + | VAbstract (AUnsafe o) -> o | _ -> raise Invalid_expr -let decode_cfield v = - { - cf_name = dec_string (field v "name"); - cf_type = decode_type (field v "type"); - cf_public = dec_bool (field v "isPublic"); - cf_pos = decode_pos (field v "pos"); - cf_doc = opt dec_string (field v "doc"); - cf_meta = []; (* TODO *) - cf_kind = decode_field_kind (field v "kind"); - cf_params = decode_type_params (field v "params"); - cf_expr = None; - cf_overloads = []; - } - -let decode_efield v = - { - ef_name = dec_string (field v "name"); - ef_type = decode_type (field v "type"); - ef_pos = decode_pos (field v "pos"); - ef_index = (match field v "index" with VInt i -> i | _ -> raise Invalid_expr); - ef_meta = []; (* TODO *) - ef_doc = opt dec_string (field v "doc"); - ef_params = decode_type_params (field v "params") - } +let compiler_error msg pos = + exc (enc_inst ["haxe";"macro";"Error"] [("message",enc_string msg);("pos",encode_pos pos)]) -let decode_field_access v = - match decode_enum v with - | 0, [c;tl;cf] -> - let c = decode_ref c in - FInstance(c,List.map decode_type (dec_array tl),decode_ref cf) - | 1, [c;cf] -> FStatic(decode_ref c,decode_ref cf) - | 2, [cf] -> FAnon(decode_ref cf) - | 3, [s] -> FDynamic(dec_string s) - | 4, [co;cf] -> - let co = match co with - | VNull -> None - | _ -> Some (decode_ref (field co "c"),List.map decode_type (dec_array (field co "params"))) +let value_to_expr v p = + let h_enum = hash "__enum__" and h_et = hash "__et__" and h_ct = hash "__ct__" in + let h_tag = hash "tag" and h_args = hash "args" in + let h_length = hash "length" in + let ctx = get_ctx() in + let error v = failwith ("Unsupported value " ^ ctx.do_string v) in + let make_path t = + let rec loop = function + | [] -> assert false + | [name] -> (Ast.EConst (Ast.Ident name),p) + | name :: l -> (Ast.EField (loop l,name),p) in - FClosure(co,decode_ref cf) - | 5, [e;ef] -> FEnum(decode_ref e,decode_efield ef) - | _ -> raise Invalid_expr - -let decode_module_type v = - match decode_enum v with - | 0, [c] -> TClassDecl (decode_ref c) - | 1, [en] -> TEnumDecl (decode_ref en) - | 2, [t] -> TTypeDecl (decode_ref t) - | 3, [a] -> TAbstractDecl (decode_ref a) - | _ -> raise Invalid_expr - -let decode_tfunc v = - { - tf_args = List.map (fun v -> decode_tvar (field v "v"),opt decode_tconst (field v "value")) (dec_array (field v "args")); - tf_type = decode_type (field v "t"); - tf_expr = decode_texpr (field v "expr") - } - -let rec decode_texpr v = - let rec loop v = - mk (decode (field v "expr")) (decode_type (field v "t")) (decode_pos (field v "pos")) - and decode e = - match decode_enum e with - | 0, [c] -> TConst(decode_tconst c) - | 1, [v] -> TLocal(decode_tvar v) - | 2, [v1;v2] -> TArray(loop v1,loop v2) - | 3, [op;v1;v2] -> TBinop(decode_op op,loop v1,loop v2) - | 4, [v1;fa] -> TField(loop v1,decode_field_access fa) - | 5, [mt] -> TTypeExpr(decode_module_type mt) - | 6, [v1] -> TParenthesis(loop v1) - | 7, [v] -> TObjectDecl(List.map (fun v -> dec_string (field v "name"),loop (field v "expr")) (dec_array v)) - | 8, [vl] -> TArrayDecl(List.map loop (dec_array vl)) - | 9, [v1;vl] -> TCall(loop v1,List.map loop (dec_array vl)) - | 10, [c;tl;vl] -> TNew(decode_ref c,List.map decode_type (dec_array tl),List.map loop (dec_array vl)) - | 11, [op;pf;v1] -> TUnop(decode_unop op,(if dec_bool pf then Postfix else Prefix),loop v1) - | 12, [f] -> TFunction(decode_tfunc f) - | 13, [v;eo] -> TVar(decode_tvar v,opt loop eo) - | 14, [vl] -> TBlock(List.map loop (dec_array vl)) - | 15, [v;v1;v2] -> TFor(decode_tvar v,loop v1,loop v2) - | 16, [vif;vthen;velse] -> TIf(loop vif,loop vthen,opt loop velse) - | 17, [vcond;v1;b] -> TWhile(loop vcond,loop v1,if dec_bool b then NormalWhile else DoWhile) - | 18, [v1;cl;vdef] -> TSwitch(loop v1,List.map (fun v -> List.map loop (dec_array (field v "values")),loop (field v "expr")) (dec_array cl),opt loop vdef) - | 19, [v1;cl] -> TTry(loop v1,List.map (fun v -> decode_tvar (field v "v"),loop (field v "expr")) (dec_array cl)) - | 20, [vo] -> TReturn(opt loop vo) - | 21, [] -> TBreak - | 22, [] -> TContinue - | 23, [v1] -> TThrow(loop v1) - | 24, [v1;mto] -> TCast(loop v1,opt decode_module_type mto) - | 25, [m;v1] -> TMeta(decode_meta_entry m,loop v1) - | 26, [v1;ef;i] -> TEnumParameter(loop v1,decode_efield ef,match i with VInt i -> i | _ -> raise Invalid_expr) - | i,el -> Printf.printf "%i %i\n" i (List.length el); raise Invalid_expr + let t = t_infos t in + loop (List.rev (if t.mt_module.m_path = t.mt_path then fst t.mt_path @ [snd t.mt_path] else fst t.mt_module.m_path @ [snd t.mt_module.m_path;snd t.mt_path])) in - try - loop v - with Stack_overflow -> - raise Invalid_expr + let rec loop = function + | VNull -> (Ast.EConst (Ast.Ident "null"),p) + | VBool b -> (Ast.EConst (Ast.Ident (if b then "true" else "false")),p) + | VInt i -> (Ast.EConst (Ast.Int (string_of_int i)),p) + | VInt32 i -> (Ast.EConst (Ast.Int (Int32.to_string i)),p) + | VFloat f -> haxe_float f p + | VAbstract (APos p) -> + (Ast.EObjectDecl ( + (("fileName",Globals.null_pos) , (Ast.EConst (Ast.String p.Globals.pfile) , p)) :: + (("lineNumber",Globals.null_pos) , (Ast.EConst (Ast.Int (string_of_int (Lexer.get_error_line p))),p)) :: + (("className",Globals.null_pos) , (Ast.EConst (Ast.String ("")),p)) :: + [] + ), p) + | VString _ | VArray _ | VAbstract _ | VFunction _ | VClosure _ as v -> error v + | VObject o as v -> + match o.oproto with + | None -> + (match get_field_opt o h_ct with + | Some (VAbstract (ATDecl t)) -> + make_path t + | _ -> + let fields = List.fold_left (fun acc (fid,v) -> ((field_name ctx fid,Globals.null_pos), loop v) :: acc) [] (Array.to_list o.ofields) in + (Ast.EObjectDecl fields, p)) + | Some proto -> + match get_field_opt proto h_enum, get_field_opt o h_a, get_field_opt o h_s, get_field_opt o h_length with + | _, Some (VArray a), _, Some (VInt len) -> + (Ast.EArrayDecl (List.map loop (Array.to_list (Array.sub a 0 len))),p) + | _, _, Some (VString s), _ -> + (Ast.EConst (Ast.String s),p) + | Some (VObject en), _, _, _ -> + (match get_field en h_et, get_field o h_tag with + | VAbstract (ATDecl t), VString tag -> + let e = (Ast.EField (make_path t,tag),p) in + (match get_field_opt o h_args with + | Some (VArray args) -> + let args = List.map loop (Array.to_list args) in + (Ast.ECall (e,args),p) + | _ -> e) + | _ -> + error v) + | _ -> + error v + in + loop v -(* ---------------------------------------------------------------------- *) -(* TYPE DEFINITION *) - -let decode_type_def v = - let pack = List.map dec_string (dec_array (field v "pack")) in - let name = dec_string (field v "name") in - let meta = decode_meta_content (field v "meta") in - let pos = decode_pos (field v "pos") in - let isExtern = (match field v "isExtern" with VNull -> false | v -> dec_bool v) in - let fields = List.map decode_field (dec_array (field v "fields")) in - let mk fl dl = - { - d_name = name; - d_doc = None; - d_params = decode_tparams (field v "params"); - d_meta = meta; - d_flags = fl; - d_data = dl; - } +let value_signature v = + let cache = ref [] in + let cache_count = ref 0 in + let hfiles = Hashtbl.create 0 in + let get_file f = + try + Hashtbl.find hfiles f + with Not_found -> + let ff = Path.unique_full_path f in + Hashtbl.add hfiles f ff; + ff + in + let do_cache (v:value) (v2:value) = + (* + tricky : we need to have a quick not-linear cache based on objects address + but we can't use address since the GC might be triggered here. + Instead let's mutate the object temporary. + *) + let vt = Obj.repr v in + let old = Obj.tag vt in + let old_val = Obj.field vt 0 in + let abstract_tag = 7 in + Obj.set_tag vt abstract_tag; + Obj.set_field vt 0 (Obj.repr (ACacheRef v2)); + cache := (vt,old,old_val) :: !cache; + incr cache_count in - let tdef = (match decode_enum (field v "kind") with - | 0, [] -> - let conv f = - let loop (n,opt,t,_) = - match t with - | None -> raise Invalid_expr - | Some t -> n, opt, t - in - let args, params, t = (match f.cff_kind with - | FVar (t,None) -> [], [], t - | FFun f -> List.map loop f.f_args, f.f_params, f.f_type - | _ -> raise Invalid_expr - ) in - { - ec_name = f.cff_name; - ec_doc = f.cff_doc; - ec_meta = f.cff_meta; - ec_pos = f.cff_pos; - ec_args = args; - ec_params = params; - ec_type = t; - } - in - EEnum (mk (if isExtern then [EExtern] else []) (List.map conv fields)) - | 1, [] -> - ETypedef (mk (if isExtern then [EExtern] else []) (CTAnonymous fields)) - | 2, [ext;impl;interf] -> - let flags = if isExtern then [HExtern] else [] in - let flags = (match interf with VNull | VBool false -> flags | VBool true -> HInterface :: flags | _ -> raise Invalid_expr) in - let flags = (match opt decode_path ext with None -> flags | Some t -> HExtends t :: flags) in - let flags = (match opt (fun v -> List.map decode_path (dec_array v)) impl with None -> flags | Some l -> List.map (fun t -> HImplements t) l @ flags) in - EClass (mk flags fields) - | 3, [t] -> - ETypedef (mk (if isExtern then [EExtern] else []) (decode_ctype t)) - | 4, [tthis;tfrom;tto] -> - let flags = match opt dec_array tfrom with None -> [] | Some ta -> List.map (fun t -> AFromType (decode_ctype t)) ta in - let flags = match opt dec_array tto with None -> flags | Some ta -> (List.map (fun t -> AToType (decode_ctype t)) ta) @ flags in - let flags = match opt decode_ctype tthis with None -> flags | Some t -> (AIsType t) :: flags in - EAbstract(mk flags fields) + let rec loop v = + match v with + | VNull | VBool _ | VInt _ | VFloat _ | VString _ | VInt32 _ -> v + | VObject o -> + let o2 = { ofields = [||]; oproto = None } in + let v2 = VObject o2 in + do_cache v v2; + Array.iter (fun (f,v) -> if f <> h_class then set_field o2 f (loop v)) o.ofields; + (match o.oproto with + | None -> () + | Some p -> (match loop (VObject p) with VObject p2 -> o2.oproto <- Some p2 | _ -> assert false)); + v2 + | VArray a -> + let a2 = Array.create (Array.length a) VNull in + let v2 = VArray a2 in + do_cache v v2; + for i = 0 to Array.length a - 1 do + a2.(i) <- loop a.(i); + done; + v2 + | VFunction f -> + let v2 = VFunction (Obj.magic !cache_count) in + do_cache v v2; + v2 + | VClosure (vl,f) -> + let rl = ref [] in + let v2 = VClosure (Obj.magic rl, Obj.magic !cache_count) in + (* in ocaml 4.0+ it was reported some stack overflow, related to vl being GC'ed or mutated in do_cache. + let's make sure to have a real pointer to it first. The fix will trigger an alloc which might have simply moved the problem away *) + let vl = VNull :: vl in + do_cache v v2; + rl := List.map loop vl; + v2 + | VAbstract (APos p) -> VAbstract (APos { p with Globals.pfile = get_file p.Globals.pfile }) + | VAbstract (ACacheRef v) -> v + | VAbstract (AHash h) -> + let h2 = Hashtbl.create 0 in + let v2 = VAbstract (AHash h2) in + do_cache v v2; + Hashtbl.iter (fun k v -> Hashtbl.add h2 k (loop v)) h2; + v2 + | VAbstract _ -> + let v2 = VAbstract (Obj.magic !cache_count) in + do_cache v v2; + v2 + in + let v = loop v in + (* restore *) + List.iter (fun (vt,tag,field) -> + Obj.set_tag vt tag; + Obj.set_field vt 0 field; + ) !cache; + Digest.string (Marshal.to_string v [Marshal.Closures]) + +let prepare_callback v n = + match v with + | VFunction _ | VClosure _ -> + let ctx = get_ctx() in + (fun args -> + match catch_errors ctx (fun() -> ctx.do_call VNull v args null_pos) with + | None -> VNull + | Some v -> v + ) | _ -> raise Invalid_expr - ) in - (* if our package ends with an uppercase letter, then it's the module name *) - let pack,name = (match List.rev pack with - | last :: l when not (is_lower_ident last) -> List.rev l, last - | _ -> pack, name - ) in - (pack, name), tdef, pos - -(* ---------------------------------------------------------------------- *) -(* VALUE-TO-CONSTANT *) - -let rec make_const e = - match e.eexpr with - | TConst c -> - (match c with - | TInt i -> best_int i - | TFloat s -> VFloat (float_of_string s) - | TString s -> enc_string s - | TBool b -> VBool b - | TNull -> VNull - | TThis | TSuper -> raise Exit) - | TParenthesis e | TMeta(_,e) -> - make_const e - | TObjectDecl el -> - VObject (obj (hash_field (get_ctx())) (List.map (fun (f,e) -> f, make_const e) el)) - | TArrayDecl al -> - enc_array (List.map make_const al) - | _ -> - raise Exit - -(* ---------------------------------------------------------------------- *) -(* TEXPR-TO-AST-EXPR *) - -open Ast - -let tpath p mp pl = - if snd mp = snd p then - CTPath { - tpackage = fst p; - tname = snd p; - tparams = List.map (fun t -> TPType t) pl; - tsub = None; - } - else CTPath { - tpackage = fst mp; - tname = snd mp; - tparams = List.map (fun t -> TPType t) pl; - tsub = Some (snd p); - } - -let rec make_type = function - | TMono r -> - (match !r with - | None -> raise Exit - | Some t -> make_type t) - | TEnum (e,pl) -> - tpath e.e_path e.e_module.m_path (List.map make_type pl) - | TInst({cl_kind = KTypeParameter _} as c,pl) -> - tpath ([],snd c.cl_path) ([],snd c.cl_path) (List.map make_type pl) - | TInst (c,pl) -> - tpath c.cl_path c.cl_module.m_path (List.map make_type pl) - | TType (t,pl) as tf -> - (* recurse on type-type *) - if (snd t.t_path).[0] = '#' then make_type (follow tf) else tpath t.t_path t.t_module.m_path (List.map make_type pl) - | TAbstract (a,pl) -> - tpath a.a_path a.a_module.m_path (List.map make_type pl) - | TFun (args,ret) -> - CTFunction (List.map (fun (_,_,t) -> make_type t) args, make_type ret) - | TAnon a -> - begin match !(a.a_status) with - | Statics c -> tpath ([],"Class") ([],"Class") [tpath c.cl_path c.cl_path []] - | EnumStatics e -> tpath ([],"Enum") ([],"Enum") [tpath e.e_path e.e_path []] - | _ -> - CTAnonymous (PMap.foldi (fun _ f acc -> - { - cff_name = f.cf_name; - cff_kind = FVar (mk_ot f.cf_type,None); - cff_pos = f.cf_pos; - cff_doc = f.cf_doc; - cff_meta = f.cf_meta; - cff_access = []; - } :: acc - ) a.a_fields []) - end - | (TDynamic t2) as t -> - tpath ([],"Dynamic") ([],"Dynamic") (if t == t_dynamic then [] else [make_type t2]) - | TLazy f -> - make_type ((!f)()) - -and mk_ot t = - match follow t with - | TMono _ -> None - | _ -> (try Some (make_type t) with Exit -> None) - -let rec make_ast e = - let full_type_path t = - let mp,p = match t with - | TClassDecl c -> c.cl_module.m_path,c.cl_path - | TEnumDecl en -> en.e_module.m_path,en.e_path - | TAbstractDecl a -> a.a_module.m_path,a.a_path - | TTypeDecl t -> t.t_module.m_path,t.t_path - in - if snd mp = snd p then p else (fst mp) @ [snd mp],snd p - in - let mk_path (pack,name) p = - match List.rev pack with - | [] -> (EConst (Ident name),p) - | pl -> - let rec loop = function - | [] -> assert false - | [n] -> (EConst (Ident n),p) - | n :: l -> (EField (loop l, n),p) - in - (EField (loop pl,name),p) - in - let mk_const = function - | TInt i -> Int (Int32.to_string i) - | TFloat s -> Float s - | TString s -> String s - | TBool b -> Ident (if b then "true" else "false") - | TNull -> Ident "null" - | TThis -> Ident "this" - | TSuper -> Ident "super" - in - let mk_ident = function - | "`trace" -> Ident "trace" - | n -> Ident n - in - let eopt = function None -> None | Some e -> Some (make_ast e) in - ((match e.eexpr with - | TConst c -> - EConst (mk_const c) - | TLocal v -> EConst (mk_ident v.v_name) - | TArray (e1,e2) -> EArray (make_ast e1,make_ast e2) - | TBinop (op,e1,e2) -> EBinop (op, make_ast e1, make_ast e2) - | TField (e,f) -> EField (make_ast e, Type.field_name f) - | TTypeExpr t -> fst (mk_path (full_type_path t) e.epos) - | TParenthesis e -> EParenthesis (make_ast e) - | TObjectDecl fl -> EObjectDecl (List.map (fun (f,e) -> f, make_ast e) fl) - | TArrayDecl el -> EArrayDecl (List.map make_ast el) - | TCall (e,el) -> ECall (make_ast e,List.map make_ast el) - | TNew (c,pl,el) -> ENew ((match (try make_type (TInst (c,pl)) with Exit -> make_type (TInst (c,[]))) with CTPath p -> p | _ -> assert false),List.map make_ast el) - | TUnop (op,p,e) -> EUnop (op,p,make_ast e) - | TFunction f -> - let arg (v,c) = v.v_name, false, mk_ot v.v_type, (match c with None -> None | Some c -> Some (EConst (mk_const c),e.epos)) in - EFunction (None,{ f_params = []; f_args = List.map arg f.tf_args; f_type = mk_ot f.tf_type; f_expr = Some (make_ast f.tf_expr) }) - | TVar (v,eo) -> - EVars ([v.v_name, mk_ot v.v_type, eopt eo]) - | TBlock el -> EBlock (List.map make_ast el) - | TFor (v,it,e) -> - let ein = (EIn ((EConst (Ident v.v_name),it.epos),make_ast it),it.epos) in - EFor (ein,make_ast e) - | TIf (e,e1,e2) -> EIf (make_ast e,make_ast e1,eopt e2) - | TWhile (e1,e2,flag) -> EWhile (make_ast e1, make_ast e2, flag) - | TSwitch (e,cases,def) -> - let cases = List.map (fun (vl,e) -> - List.map make_ast vl,None,(match e.eexpr with TBlock [] -> None | _ -> Some (make_ast e)) - ) cases in - let def = match eopt def with None -> None | Some (EBlock [],_) -> Some None | e -> Some e in - ESwitch (make_ast e,cases,def) - | TEnumParameter _ -> - (* these are considered complex, so the AST is handled in TMeta(Meta.Ast) *) - assert false - | TTry (e,catches) -> ETry (make_ast e,List.map (fun (v,e) -> v.v_name, (try make_type v.v_type with Exit -> assert false), make_ast e) catches) - | TReturn e -> EReturn (eopt e) - | TBreak -> EBreak - | TContinue -> EContinue - | TThrow e -> EThrow (make_ast e) - | TCast (e,t) -> - let t = (match t with - | None -> None - | Some t -> - let t = (match t with TClassDecl c -> TInst (c,[]) | TEnumDecl e -> TEnum (e,[]) | TTypeDecl t -> TType (t,[]) | TAbstractDecl a -> TAbstract (a,[])) in - Some (try make_type t with Exit -> assert false) - ) in - ECast (make_ast e,t) - | TMeta ((Meta.Ast,[e1,_],_),_) -> e1 - | TMeta (m,e) -> EMeta(m,make_ast e)) - ,e.epos) - -;; -make_ast_ref := make_ast; -make_complex_type_ref := make_type; -encode_complex_type_ref := encode_ctype; -enc_array_ref := enc_array; -dec_array_ref := dec_array; -encode_type_ref := encode_type; -decode_type_ref := decode_type; -encode_expr_ref := encode_expr; -decode_expr_ref := decode_expr; -encode_clref_ref := encode_clref; -enc_string_ref := enc_string; -enc_hash_ref := enc_hash; -encode_texpr_ref := encode_texpr; -decode_texpr_ref := decode_texpr; -encode_tvar_ref := encode_tvar; -decode_path_ref := decode_path; -decode_import_ref := decode_import; diff --git a/src/macro/macroApi.ml b/src/macro/macroApi.ml new file mode 100644 index 00000000..9a0c2c87 --- /dev/null +++ b/src/macro/macroApi.ml @@ -0,0 +1,1872 @@ +open Ast +open Type +open Common + +exception Invalid_expr +exception Abort + +(** + Our access to the compiler from the macro api +**) + +type 'value compiler_api = { + pos : Globals.pos; + get_com : unit -> Common.context; + get_type : string -> Type.t option; + get_module : string -> Type.t list; + after_typing : (module_type list -> unit) -> unit; + on_generate : (Type.t list -> unit) -> unit; + after_generate : (unit -> unit) -> unit; + on_type_not_found : (string -> 'value) -> unit; + parse_string : string -> Globals.pos -> bool -> Ast.expr; + type_expr : Ast.expr -> Type.texpr; + resolve_type : Ast.complex_type -> Globals.pos -> t; + type_macro_expr : Ast.expr -> Type.texpr; + store_typed_expr : Type.texpr -> Ast.expr; + allow_package : string -> unit; + type_patch : string -> string -> bool -> string option -> unit; + meta_patch : string -> string -> string option -> bool -> unit; + set_js_generator : (Genjs.ctx -> unit) -> unit; + get_local_type : unit -> t option; + get_expected_type : unit -> t option; + get_call_arguments : unit -> Ast.expr list option; + get_local_method : unit -> string; + get_local_imports : unit -> Ast.import list; + get_local_using : unit -> tclass list; + get_local_vars : unit -> (string, Type.tvar) PMap.t; + get_build_fields : unit -> 'value; + get_pattern_locals : Ast.expr -> Type.t -> (string,Type.tvar * Globals.pos) PMap.t; + define_type : 'value -> unit; + define_module : string -> 'value list -> ((string * Globals.pos) list * Ast.import_mode) list -> Ast.type_path list -> unit; + module_dependency : string -> string -> bool -> unit; + current_module : unit -> module_def; + on_reuse : (unit -> bool) -> unit; + mutable current_macro_module : unit -> module_def; + delayed_macro : int -> (unit -> (unit -> 'value)); + use_cache : unit -> bool; + format_string : string -> Globals.pos -> Ast.expr; + cast_or_unify : Type.t -> texpr -> Globals.pos -> Type.texpr; + add_global_metadata : string -> string -> (bool * bool * bool) -> unit; + add_module_check_policy : string list -> int list -> bool -> int -> unit; +} + + +type enum_type = + | IExpr + | IBinop + | IUnop + | IConst + | ITParam + | ICType + | IField + | IType + | IFieldKind + | IMethodKind + | IVarAccess + | IAccess + | IClassKind + | ITypedExpr + | ITConstant + | IModuleType + | IFieldAccess + | IAnonStatus + | IImportMode + +type obj_type = + (* make_const *) + | O__Const + (* Expr *) + | OImportExpr + | OImportExpr_path + | OTypePath + | OMetadataEntry + | OField + | OTypeParamDecl + | OFunction + | OFunctionArg + | OExprDef_fields + | OVar + | OCase + | OCatch + | OExpr + (* Type *) + | OMetaAccess + | OTypeParameter + | OClassType + | OAbstractType + | OAnonType + | ODefType + | OEnumType + | OClassField + | OAbstractType_binops + | OAbstractType_unops + | OAbstractType_from + | OAbstractType_to + | OEnumField + | OClassType_superClass + | OClassType_interfaces + | OType_args + | OTVar + | OTVar_extra + | OTFunc + | OTFunc_args + | OFieldAccess_c + | OTypedExprDef + | OTypedExprDef_fields + | OTypedExprDef_cases + | OTypedExprDef_catches + | OJSGenApi + | OContext_getPosInfos + | OCompiler_getDisplayPos + | ORef +(* ---- ^^^^^ please exactly match the name of the typedef or use TypeName_field if it's a anonymous *) + +(** + Our access to the interpreter from the macro api +**) + +module type InterpApi = sig + type value + + val vnull : value + val vint : int -> value + val vfloat : float -> value + val vint32 : int32 -> value + val vbool : bool -> value + + val enc_array : value list -> value + val enc_string : string -> value + val enc_obj : obj_type -> (string * value) list -> value + + val vfun0 : (unit -> value) -> value + val vfun1 : (value -> value) -> value + val vfun2 : (value -> value -> value) -> value + val vfun3 : (value -> value -> value -> value) -> value + val vfun4 : (value -> value -> value -> value -> value) -> value + val vfun5 : (value -> value -> value -> value -> value -> value) -> value + + val encode_pos : Globals.pos -> value + val encode_enum : enum_type -> Globals.pos option -> int -> value list -> value + val encode_string_map : ('a -> value) -> (string, 'a) PMap.t -> value + + val encode_tdecl : Type.module_type -> value + val encode_lazytype : (unit -> Type.t) ref -> (unit -> value) -> value + val encode_unsafe : Obj.t -> value + + val field : value -> string -> value + + val dec_bool : value -> bool + val dec_int : value -> int + val dec_i32 : value -> int32 + val dec_string : value -> string + val dec_array : value -> value list + + val decode_pos : value -> Globals.pos + val decode_enum : value -> int * value list + val decode_tdecl : value -> Type.module_type + val decode_lazytype : value -> (unit -> Type.t) ref + val decode_unsafe : value -> Obj.t + + val decode_enum_with_pos : value -> (int * value list) * Globals.pos + + val encode_ref : 'a -> ('a -> value) -> (unit -> string) -> value + val decode_ref : value -> 'a + + val compiler_error : string -> Globals.pos -> 'a + val value_to_expr : value -> Globals.pos -> Ast.expr + val value_signature : value -> string + + val encode_bytes : string -> value + val decode_bytes : value -> string (* haxe.io.Bytes *) + + val prepare_callback : value -> int -> (value list -> value) + + val value_string : value -> string + +end + +let enum_name = function + | IExpr -> "ExprDef" + | IBinop -> "Binop" + | IUnop -> "Unop" + | IConst -> "Constant" + | ITParam -> "TypeParam" + | ICType -> "ComplexType" + | IField -> "FieldType" + | IType -> "Type" + | IFieldKind -> "FieldKind" + | IMethodKind -> "MethodKind" + | IVarAccess -> "VarAccess" + | IAccess -> "Access" + | IClassKind -> "ClassKind" + | ITypedExpr -> "TypedExprDef" + | ITConstant -> "TConstant" + | IModuleType -> "ModuleType" + | IFieldAccess -> "FieldAccess" + | IAnonStatus -> "AnonStatus" + | IImportMode -> "ImportMode" + +let proto_name = function + | O__Const -> assert false + | OImportExpr -> "ImportExpr", None + | OImportExpr_path -> "ImportExpr", Some "path" + | OTypePath -> "TypePath", None + | OMetadataEntry -> "MetadataEntry", None + | OField -> "Field", None + | OTypeParamDecl -> "TypeParamDecl", None + | OFunction -> "Function", None + | OFunctionArg -> "FunctionArg", None + | OExprDef_fields -> "ExprDef", Some "fields" + | OVar -> "Var", None + | OCase -> "Case", None + | OCatch -> "Catch", None + | OExpr -> "Expr", None + | OMetaAccess -> "MetaAccess", None + | OTypeParameter -> "TypeParameter", None + | OClassType -> "ClassType", None + | OAbstractType -> "AbstracType", None + | OAnonType -> "AnonType", None + | ODefType -> "DefType", None + | OEnumType -> "EnumType", None + | OClassField -> "ClassField", None + | OAbstractType_binops -> "AbstractType", Some "binops" + | OAbstractType_unops -> "AbstractType", Some "unops" + | OAbstractType_from -> "AbstractType", Some "from" + | OAbstractType_to -> "AbstractType", Some "to" + | OEnumField -> "EnumField", None + | OClassType_superClass -> "ClassType", Some "superClass" + | OClassType_interfaces -> "ClassType", Some "interfaces" + | OType_args -> "Type", Some "args" + | OTVar -> "TVar", None + | OTVar_extra -> "TVar", Some "extra" + | OTFunc -> "TFunc", None + | OTFunc_args -> "TFunc", Some "args" + | OFieldAccess_c -> "FieldAccess", Some "c" + | OTypedExprDef -> "TypedExprDef", None + | OTypedExprDef_fields -> "TypedExprDef", Some "fields" + | OTypedExprDef_cases -> "TypedExprDef", Some "cases" + | OTypedExprDef_catches -> "TypedExprDef", Some "catches" + | OJSGenApi -> "JSGenApi", None + | OContext_getPosInfos -> "Context", Some "getPosInfos" + | OCompiler_getDisplayPos -> "Compiler", Some "getDisplayPos" + | ORef -> "Ref", None + +let all_enums = + let last = IImportMode in + let rec loop i = + let e : enum_type = Obj.magic i in + if e = last then [e] else e :: loop (i + 1) + in + loop 0 + + +let s_type_path = Globals.s_type_path + +(* convert float value to haxe expression, handling inf/-inf/nan *) +let haxe_float f p = + let std = (Ast.EConst (Ast.Ident "std"), p) in + let math = (Ast.EField (std, "Math"), p) in + if (f = infinity) then + (Ast.EField (math, "POSITIVE_INFINITY"), p) + else if (f = neg_infinity) then + (Ast.EField (math, "NEGATIVE_INFINITY"), p) + else if (f <> f) then + (Ast.EField (math, "NaN"), p) + else + (Ast.EConst (Ast.Float (float_repres f)), p) + +(* ------------------------------------------------------------------------------------------------------------- *) +(* Our macro api functor *) + +module MacroApiImpl(InterpImpl:InterpApi) = struct + +open InterpImpl + +(* + The whole encoding/decoding of compiler values from/to interpreter values based on interpreter api +*) + +let null f = function + | None -> vnull + | Some v -> f v + +let encode_enum ?(pos=None) k tag vl = encode_enum k pos tag vl + +let encode_const c = + let tag, pl = match c with + | Int s -> 0, [enc_string s] + | Float s -> 1, [enc_string s] + | String s -> 2, [enc_string s] + | Ident s -> 3, [enc_string s] + | Regexp (s,opt) -> 4, [enc_string s;enc_string opt] + in + encode_enum IConst tag pl + +let rec encode_binop op = + let tag, pl = match op with + | OpAdd -> 0, [] + | OpMult -> 1, [] + | OpDiv -> 2, [] + | OpSub -> 3, [] + | OpAssign -> 4, [] + | OpEq -> 5, [] + | OpNotEq -> 6, [] + | OpGt -> 7, [] + | OpGte -> 8, [] + | OpLt -> 9, [] + | OpLte -> 10, [] + | OpAnd -> 11, [] + | OpOr -> 12, [] + | OpXor -> 13, [] + | OpBoolAnd -> 14, [] + | OpBoolOr -> 15, [] + | OpShl -> 16, [] + | OpShr -> 17, [] + | OpUShr -> 18, [] + | OpMod -> 19, [] + | OpAssignOp op -> 20, [encode_binop op] + | OpInterval -> 21, [] + | OpArrow -> 22, [] + in + encode_enum IBinop tag pl + +let encode_unop op = + let tag = match op with + | Increment -> 0 + | Decrement -> 1 + | Not -> 2 + | Neg -> 3 + | NegBits -> 4 + in + encode_enum IUnop tag [] + +let encode_import (path,mode) = + let tag,pl = match mode with + | INormal -> 0, [] + | IAsName s -> 1, [enc_string s] + | IAll -> 2,[] + in + let mode = encode_enum IImportMode tag pl in + enc_obj OImportExpr [ + "path", enc_array (List.map (fun (name,p) -> enc_obj OImportExpr_path [ "pos", encode_pos p; "name", enc_string name]) path); + "mode", mode + ] + +let encode_placed_name (s,p) = + enc_string s + +let rec encode_path (t,_) = + let fields = [ + "pack", enc_array (List.map enc_string t.tpackage); + "name", enc_string t.tname; + "params", enc_array (List.map encode_tparam t.tparams); + ] in + enc_obj OTypePath (match t.tsub with + | None -> fields + | Some s -> ("sub", enc_string s) :: fields) + +and encode_tparam = function + | TPType t -> encode_enum ITParam 0 [encode_ctype t] + | TPExpr e -> encode_enum ITParam 1 [encode_expr e] + +and encode_access a = + let tag = match a with + | APublic -> 0 + | APrivate -> 1 + | AStatic -> 2 + | AOverride -> 3 + | ADynamic -> 4 + | AInline -> 5 + | AMacro -> 6 + in + encode_enum IAccess tag [] + +and encode_meta_entry (m,ml,p) = + enc_obj OMetadataEntry [ + "name", enc_string (Meta.to_string m); + "params", enc_array (List.map encode_expr ml); + "pos", encode_pos p; + ] + +and encode_meta_content m = + enc_array (List.map encode_meta_entry m) + +and encode_field (f:class_field) = + let tag, pl = match f.cff_kind with + | FVar (t,e) -> 0, [null encode_ctype t; null encode_expr e] + | FFun f -> 1, [encode_fun f] + | FProp (get,set, t, e) -> 2, [encode_placed_name get; encode_placed_name set; null encode_ctype t; null encode_expr e] + in + enc_obj OField [ + "name",encode_placed_name f.cff_name; + "name_pos", encode_pos (pos f.cff_name); + "doc", null enc_string f.cff_doc; + "pos", encode_pos f.cff_pos; + "kind", encode_enum IField tag pl; + "meta", encode_meta_content f.cff_meta; + "access", enc_array (List.map encode_access f.cff_access); + ] + +and encode_ctype t = + let tag, pl = match fst t with + | CTPath p -> + 0, [encode_path (p,Globals.null_pos)] + | CTFunction (pl,r) -> + 1, [enc_array (List.map encode_ctype pl);encode_ctype r] + | CTAnonymous fl -> + 2, [enc_array (List.map encode_field fl)] + | CTParent t -> + 3, [encode_ctype t] + | CTExtend (tl,fields) -> + 4, [enc_array (List.map encode_path tl); enc_array (List.map encode_field fields)] + | CTOptional t -> + 5, [encode_ctype t] + in + encode_enum ~pos:(Some (pos t)) ICType tag pl + +and encode_tparam_decl tp = + enc_obj OTypeParamDecl [ + "name", encode_placed_name tp.tp_name; + "name_pos", encode_pos (pos tp.tp_name); + "params", enc_array (List.map encode_tparam_decl tp.tp_params); + "constraints", enc_array (List.map encode_ctype tp.tp_constraints); + "meta", encode_meta_content tp.tp_meta; + ] + +and encode_fun f = + enc_obj OFunction [ + "params", enc_array (List.map encode_tparam_decl f.f_params); + "args", enc_array (List.map (fun (n,opt,m,t,e) -> + enc_obj OFunctionArg [ + "name", encode_placed_name n; + "name_pos", encode_pos (pos n); + "opt", vbool opt; + "meta", encode_meta_content m; + "type", null encode_ctype t; + "value", null encode_expr e; + ] + ) f.f_args); + "ret", null encode_ctype f.f_type; + "expr", null encode_expr f.f_expr + ] + +and encode_expr e = + let rec loop (e,p) = + let tag, pl = match e with + | EConst c -> + 0, [encode_const c] + | EArray (e1,e2) -> + 1, [loop e1;loop e2] + | EBinop (op,e1,e2) -> + 2, [encode_binop op;loop e1;loop e2] + | EField (e,f) -> + 3, [loop e;enc_string f] + | EParenthesis e -> + 4, [loop e] + | EObjectDecl fl -> + 5, [enc_array (List.map (fun ((f,p),e) -> enc_obj OExprDef_fields [ + "field",enc_string f; + "name_pos",encode_pos p; + "expr",loop e; + ]) fl)] + | EArrayDecl el -> + 6, [enc_array (List.map loop el)] + | ECall (e,el) -> + 7, [loop e;enc_array (List.map loop el)] + | ENew (p,el) -> + 8, [encode_path p; enc_array (List.map loop el)] + | EUnop (op,flag,e) -> + 9, [encode_unop op; vbool (match flag with Prefix -> false | Postfix -> true); loop e] + | EVars vl -> + 10, [enc_array (List.map (fun (v,t,eo) -> + enc_obj OVar [ + "name",encode_placed_name v; + "name_pos",encode_pos (pos v); + "type",null encode_ctype t; + "expr",null loop eo; + ] + ) vl)] + | EFunction (name,f) -> + 11, [null enc_string name; encode_fun f] + | EBlock el -> + 12, [enc_array (List.map loop el)] + | EFor (e,eloop) -> + 13, [loop e;loop eloop] + | EIn (e1,e2) -> + 14, [loop e1;loop e2] + | EIf (econd,e,eelse) -> + 15, [loop econd;loop e;null loop eelse] + | EWhile (econd,e,flag) -> + 16, [loop econd;loop e;vbool (match flag with NormalWhile -> true | DoWhile -> false)] + | ESwitch (e,cases,eopt) -> + 17, [loop e;enc_array (List.map (fun (ecl,eg,e,p) -> + enc_obj OCase [ + "values",enc_array (List.map loop ecl); + "guard",null loop eg; + "expr",null loop e; + "pos",encode_pos p; + ] + ) cases);null (fun (e,_) -> encode_null_expr e) eopt] + | ETry (e,catches) -> + 18, [loop e;enc_array (List.map (fun (v,t,e,p) -> + enc_obj OCatch [ + "name",encode_placed_name v; + "name_pos",encode_pos (pos v); + "type",encode_ctype t; + "expr",loop e; + "pos",encode_pos p + ] + ) catches)] + | EReturn eo -> + 19, [null loop eo] + | EBreak -> + 20, [] + | EContinue -> + 21, [] + | EUntyped e -> + 22, [loop e] + | EThrow e -> + 23, [loop e] + | ECast (e,t) -> + 24, [loop e; null encode_ctype t] + | EDisplay (e,flag) -> + 25, [loop e; vbool flag] + | EDisplayNew t -> + 26, [encode_path t] + | ETernary (econd,e1,e2) -> + 27, [loop econd;loop e1;loop e2] + | ECheckType (e,t) -> + 28, [loop e; encode_ctype t] + | EMeta (m,e) -> + 29, [encode_meta_entry m;loop e] + in + enc_obj OExpr [ + "pos", encode_pos p; + "expr", encode_enum IExpr tag pl; + ] + in + loop e + +and encode_null_expr e = + match e with + | None -> + enc_obj OExpr ["pos", vnull;"expr",vnull] + | Some e -> + encode_expr e + +(* ---------------------------------------------------------------------- *) +(* EXPR DECODING *) + +let opt f v = + if v = vnull then None else Some (f v) + +let opt_list f v = + if v = vnull then [] else f v + +let dec_opt_bool v = + if v = vnull then false else dec_bool v + +let decode_const c = + match decode_enum c with + | 0, [s] -> Int (dec_string s) + | 1, [s] -> Float (dec_string s) + | 2, [s] -> String (dec_string s) + | 3, [s] -> Ident (dec_string s) + | 4, [s;opt] -> Regexp (dec_string s, dec_string opt) + | 5, [s] -> Ident (dec_string s) (** deprecated CType, keep until 3.0 release **) + | _ -> raise Invalid_expr + +let rec decode_op op = + match decode_enum op with + | 0, [] -> OpAdd + | 1, [] -> OpMult + | 2, [] -> OpDiv + | 3, [] -> OpSub + | 4, [] -> OpAssign + | 5, [] -> OpEq + | 6, [] -> OpNotEq + | 7, [] -> OpGt + | 8, [] -> OpGte + | 9, [] -> OpLt + | 10, [] -> OpLte + | 11, [] -> OpAnd + | 12, [] -> OpOr + | 13, [] -> OpXor + | 14, [] -> OpBoolAnd + | 15, [] -> OpBoolOr + | 16, [] -> OpShl + | 17, [] -> OpShr + | 18, [] -> OpUShr + | 19, [] -> OpMod + | 20, [op] -> OpAssignOp (decode_op op) + | 21, [] -> OpInterval + | 22,[] -> OpArrow + | _ -> raise Invalid_expr + +let decode_unop op = + match decode_enum op with + | 0, [] -> Increment + | 1, [] -> Decrement + | 2, [] -> Not + | 3, [] -> Neg + | 4, [] -> NegBits + | _ -> raise Invalid_expr + +let decode_import_mode t = + match decode_enum t with + | 0, [] -> INormal + | 1, [alias] -> IAsName (dec_string alias) + | 2, [] -> IAll + | _ -> raise Invalid_expr + +let decode_import t = (List.map (fun o -> ((dec_string (field o "name")), (decode_pos (field o "pos")))) (dec_array (field t "path")), decode_import_mode (field t "mode")) + +let maybe_decode_pos p = try decode_pos p with Invalid_expr -> Globals.null_pos + +let decode_placed_name vp v = + dec_string v,maybe_decode_pos vp + +let dec_opt_array f v = + if v = vnull then [] else List.map f (dec_array v) + +let rec decode_path t = + { + tpackage = List.map dec_string (dec_array (field t "pack")); + tname = dec_string (field t "name"); + tparams = dec_opt_array decode_tparam (field t "params"); + tsub = opt dec_string (field t "sub"); + },Globals.null_pos + +and decode_tparam v = + match decode_enum v with + | 0,[t] -> TPType (decode_ctype t) + | 1,[e] -> TPExpr (decode_expr e) + | _ -> raise Invalid_expr + +and decode_tparams v = + dec_opt_array decode_tparam_decl v + +and decode_tparam_decl v = + { + tp_name = decode_placed_name (field v "name_pos") (field v "name"); + tp_constraints = dec_opt_array decode_ctype (field v "constraints"); + tp_params = decode_tparams (field v "params"); + tp_meta = decode_meta_content (field v "meta"); + } + +and decode_fun v = + { + f_params = decode_tparams (field v "params"); + f_args = List.map (fun o -> + decode_placed_name (field o "name_pos") (field o "name"), + dec_opt_bool (field o "opt"), + decode_meta_content (field o "meta"), + opt decode_ctype (field o "type"), + opt decode_expr (field o "value") + ) (dec_array (field v "args")); + f_type = opt decode_ctype (field v "ret"); + f_expr = opt decode_expr (field v "expr"); + } + +and decode_access v = + match decode_enum v with + | 0, [] -> APublic + | 1, [] -> APrivate + | 2, [] -> AStatic + | 3, [] -> AOverride + | 4, [] -> ADynamic + | 5, [] -> AInline + | 6, [] -> AMacro + | _ -> raise Invalid_expr + +and decode_meta_entry v = + Meta.from_string (dec_string (field v "name")), dec_opt_array decode_expr (field v "params"), decode_pos (field v "pos") + +and decode_meta_content m = dec_opt_array decode_meta_entry m + +and decode_field v = + let fkind = match decode_enum (field v "kind") with + | 0, [t;e] -> + FVar (opt decode_ctype t, opt decode_expr e) + | 1, [f] -> + FFun (decode_fun f) + | 2, [get;set; t; e] -> + FProp (decode_placed_name vnull get, decode_placed_name vnull set, opt decode_ctype t, opt decode_expr e) + | _ -> + raise Invalid_expr + in + { + cff_name = decode_placed_name (field v "name_pos") (field v "name"); + cff_doc = opt dec_string (field v "doc"); + cff_pos = decode_pos (field v "pos"); + cff_kind = fkind; + cff_access = List.map decode_access (opt_list dec_array (field v "access")); + cff_meta = opt_list decode_meta_content (field v "meta"); + } + +and decode_ctype t = + let (i,args),p = decode_enum_with_pos t in + (match i,args with + | 0, [p] -> + CTPath (fst (decode_path p)) + | 1, [a;r] -> + CTFunction (List.map decode_ctype (dec_array a), decode_ctype r) + | 2, [fl] -> + CTAnonymous (List.map decode_field (dec_array fl)) + | 3, [t] -> + CTParent (decode_ctype t) + | 4, [tl;fl] -> + CTExtend (List.map decode_path (dec_array tl), List.map decode_field (dec_array fl)) + | 5, [t] -> + CTOptional (decode_ctype t) + | _ -> + raise Invalid_expr),p + +and decode_expr v = + let rec loop v = + let p = decode_pos (field v "pos") in + (decode (field v "expr") p, p) + and decode e p = + match decode_enum e with + | 0, [c] -> + EConst (decode_const c) + | 1, [e1;e2] -> + EArray (loop e1, loop e2) + | 2, [op;e1;e2] -> + EBinop (decode_op op, loop e1, loop e2) + | 3, [e;f] -> + EField (loop e, dec_string f) + | 4, [e] -> + EParenthesis (loop e) + | 5, [a] -> + EObjectDecl (List.map (fun o -> + (decode_placed_name (field o "name_pos") (field o "field")),loop (field o "expr") + ) (dec_array a)) + | 6, [a] -> + EArrayDecl (List.map loop (dec_array a)) + | 7, [e;el] -> + ECall (loop e,List.map loop (dec_array el)) + | 8, [t;el] -> + ENew (decode_path t,List.map loop (dec_array el)) + | 9, [op;f;e] -> + EUnop (decode_unop op,(if dec_bool f then Postfix else Prefix),loop e) + | 10, [vl] -> + EVars (List.map (fun v -> + ((decode_placed_name (field v "name_pos") (field v "name")),opt decode_ctype (field v "type"),opt loop (field v "expr")) + ) (dec_array vl)) + | 11, [fname;f] -> + EFunction (opt dec_string fname,decode_fun f) + | 12, [el] -> + EBlock (List.map loop (dec_array el)) + | 13, [e1;e2] -> + EFor (loop e1, loop e2) + | 14, [e1;e2] -> + EIn (loop e1, loop e2) + | 15, [e1;e2;e3] -> + EIf (loop e1, loop e2, opt loop e3) + | 16, [e1;e2;flag] -> + EWhile (loop e1,loop e2,if dec_bool flag then NormalWhile else DoWhile) + | 17, [e;cases;eo] -> + let cases = List.map (fun c -> + (List.map loop (dec_array (field c "values")),opt loop (field c "guard"),opt loop (field c "expr"),maybe_decode_pos (field c "pos")) + ) (dec_array cases) in + ESwitch (loop e,cases,opt (fun v -> (if field v "expr" = vnull then None else Some (decode_expr v)),Globals.null_pos) eo) + | 18, [e;catches] -> + let catches = List.map (fun c -> + ((decode_placed_name (field c "name_pos") (field c "name")),(decode_ctype (field c "type")),loop (field c "expr"),maybe_decode_pos (field c "pos")) + ) (dec_array catches) in + ETry (loop e, catches) + | 19, [e] -> + EReturn (opt loop e) + | 20, [] -> + EBreak + | 21, [] -> + EContinue + | 22, [e] -> + EUntyped (loop e) + | 23, [e] -> + EThrow (loop e) + | 24, [e;t] -> + ECast (loop e,opt decode_ctype t) + | 25, [e;f] -> + EDisplay (loop e,dec_bool f) + | 26, [t] -> + EDisplayNew (decode_path t) + | 27, [e1;e2;e3] -> + ETernary (loop e1,loop e2,loop e3) + | 28, [e;t] -> + ECheckType (loop e, (decode_ctype t)) + | 29, [m;e] -> + EMeta (decode_meta_entry m,loop e) + | 30, [e;f] -> + EField (loop e, dec_string f) (*** deprecated EType, keep until haxe 3 **) + | _ -> + raise Invalid_expr + in + try + loop v + with Stack_overflow -> + raise Invalid_expr + +(* ---------------------------------------------------------------------- *) +(* TYPE ENCODING *) + +let encode_pmap_array convert m = + let l = ref [] in + PMap.iter (fun _ v -> l := !l @ [(convert v)]) m; + enc_array !l + +let encode_array convert l = + enc_array (List.map convert l) + +let vopt f v = match v with + | None -> vnull + | Some v -> f v + +let encode_meta m set = + let meta = ref m in + enc_obj OMetaAccess [ + "get", vfun0 (fun() -> + encode_meta_content (!meta) + ); + "add", vfun3 (fun k vl p -> + (try + let el = List.map decode_expr (dec_array vl) in + meta := (Meta.from_string (dec_string k), el, decode_pos p) :: !meta; + set (!meta) + with Invalid_expr -> + failwith "Invalid expression"); + vnull + ); + "extract", vfun1 (fun k -> + let k = Meta.from_string (dec_string k) in + encode_array encode_meta_entry (List.filter (fun (m,_,_) -> m = k) (!meta)) + ); + "remove", vfun1 (fun k -> + let k = Meta.from_string (dec_string k) in + meta := List.filter (fun (m,_,_) -> m <> k) (!meta); + set (!meta); + vnull + ); + "has", vfun1 (fun k -> + let k = Meta.from_string (dec_string k) in + vbool (List.exists (fun (m,_,_) -> m = k) (!meta)); + ); + ] + +let rec encode_mtype ot t fields = + let i = t_infos t in + enc_obj ot ([ + "__t", encode_tdecl t; + "pack", enc_array (List.map enc_string (fst i.mt_path)); + "name", enc_string (snd i.mt_path); + "pos", encode_pos i.mt_pos; + "module", enc_string (s_type_path i.mt_module.m_path); + "isPrivate", vbool i.mt_private; + "meta", encode_meta i.mt_meta (fun m -> i.mt_meta <- m); + "doc", null enc_string i.mt_doc; + "params", encode_type_params i.mt_params; + ] @ fields) + +and encode_type_params tl = + enc_array (List.map (fun (n,t) -> enc_obj OTypeParameter ["name",enc_string n;"t",encode_type t]) tl) + +and encode_tenum e = + encode_mtype OEnumType (TEnumDecl e) [ + "isExtern", vbool e.e_extern; + "exclude", vfun0 (fun() -> e.e_extern <- true; vnull); + "constructs", encode_string_map encode_efield e.e_constrs; + "names", enc_array (List.map enc_string e.e_names); + ] + +and encode_tabstract a = + encode_mtype OAbstractType (TAbstractDecl a) [ + "type", encode_type a.a_this; + "impl", (match a.a_impl with None -> vnull | Some c -> encode_clref c); + "binops", enc_array (List.map (fun (op,cf) -> enc_obj OAbstractType_binops [ "op",encode_binop op; "field",encode_cfield cf]) a.a_ops); + "unops", enc_array (List.map (fun (op,postfix,cf) -> enc_obj OAbstractType_unops [ "op",encode_unop op; "isPostfix",vbool (match postfix with Postfix -> true | Prefix -> false); "field",encode_cfield cf]) a.a_unops); + "from", enc_array ((List.map (fun t -> enc_obj OAbstractType_from [ "t",encode_type t; "field",vnull]) a.a_from) @ (List.map (fun (t,cf) -> enc_obj OAbstractType_from [ "t",encode_type t; "field",encode_cfield cf]) a.a_from_field)); + "to", enc_array ((List.map (fun t -> enc_obj OAbstractType_to [ "t",encode_type t; "field",vnull]) a.a_to) @ (List.map (fun (t,cf) -> enc_obj OAbstractType_to [ "t",encode_type t; "field",encode_cfield cf]) a.a_to_field)); + "array", enc_array (List.map encode_cfield a.a_array); + "resolve", (match a.a_resolve with None -> vnull | Some cf -> encode_cfref cf) + ] + +and encode_efield f = + enc_obj OEnumField [ + "name", enc_string f.ef_name; + "type", encode_type f.ef_type; + "pos", encode_pos f.ef_pos; + "namePos", encode_pos f.ef_name_pos; + "index", vint f.ef_index; + "meta", encode_meta f.ef_meta (fun m -> f.ef_meta <- m); + "doc", null enc_string f.ef_doc; + "params", encode_type_params f.ef_params; + ] + +and encode_cfield f = + enc_obj OClassField [ + "name", enc_string f.cf_name; + "type", (match f.cf_kind with Method _ -> encode_lazy_type f.cf_type | _ -> encode_type f.cf_type); + "isPublic", vbool f.cf_public; + "params", encode_type_params f.cf_params; + "meta", encode_meta f.cf_meta (fun m -> f.cf_meta <- m); + "expr", vfun0 (fun() -> ignore(follow f.cf_type); (match f.cf_expr with None -> vnull | Some e -> encode_texpr e)); + "kind", encode_field_kind f.cf_kind; + "pos", encode_pos f.cf_pos; + "namePos",encode_pos f.cf_name_pos; + "doc", null enc_string f.cf_doc; + "overloads", encode_ref f.cf_overloads (encode_array encode_cfield) (fun() -> "overloads"); + ] + +and encode_field_kind k = + let tag, pl = (match k with + | Type.Var v -> 0, [encode_var_access v.v_read; encode_var_access v.v_write] + | Method m -> 1, [encode_method_kind m] + ) in + encode_enum IFieldKind tag pl + +and encode_var_access a = + let tag, pl = (match a with + | AccNormal -> 0, [] + | AccNo -> 1, [] + | AccNever -> 2, [] + | AccResolve -> 3, [] + | AccCall -> 4, [] + | AccInline -> 5, [] + | AccRequire (s,msg) -> 6, [enc_string s; null enc_string msg] + ) in + encode_enum IVarAccess tag pl + +and encode_method_kind m = + let tag, pl = (match m with + | MethNormal -> 0, [] + | MethInline -> 1, [] + | MethDynamic -> 2, [] + | MethMacro -> 3, [] + ) in + encode_enum IMethodKind tag pl + +and encode_class_kind k = + let tag, pl = (match k with + | KNormal -> 0, [] + | KTypeParameter pl -> 1, [encode_tparams pl] + (* KExtension was here *) + | KExpr e -> 3, [encode_expr e] + | KGeneric -> 4, [] + | KGenericInstance (cl, params) -> 5, [encode_clref cl; encode_tparams params] + | KMacroType -> 6, [] + | KAbstractImpl a -> 7, [encode_abref a] + | KGenericBuild cfl -> 8, [] + ) in + encode_enum IClassKind tag pl + +and encode_tclass c = + ignore(c.cl_build()); + encode_mtype OClassType (TClassDecl c) [ + "kind", encode_class_kind c.cl_kind; + "isExtern", vbool c.cl_extern; + "exclude", vfun0 (fun() -> c.cl_extern <- true; c.cl_init <- None; vnull); + "isInterface", vbool c.cl_interface; + "superClass", (match c.cl_super with + | None -> vnull + | Some (c,pl) -> enc_obj OClassType_superClass ["t",encode_clref c;"params",encode_tparams pl] + ); + "interfaces", enc_array (List.map (fun (c,pl) -> enc_obj OClassType_interfaces ["t",encode_clref c;"params",encode_tparams pl]) c.cl_implements); + "fields", encode_ref c.cl_ordered_fields (encode_array encode_cfield) (fun() -> "class fields"); + "statics", encode_ref c.cl_ordered_statics (encode_array encode_cfield) (fun() -> "class fields"); + "constructor", (match c.cl_constructor with None -> vnull | Some cf -> encode_cfref cf); + "init", (match c.cl_init with None -> vnull | Some e -> encode_texpr e); + "overrides", (enc_array (List.map encode_cfref c.cl_overrides)) + ] + +and encode_ttype t = + encode_mtype ODefType (TTypeDecl t) [ + "isExtern", vbool false; + "exclude", vfun0 (fun() -> vnull); + "type", encode_type t.t_type; + ] + +and encode_tanon a = + enc_obj OAnonType [ + "fields", encode_pmap_array encode_cfield a.a_fields; + "status", encode_anon_status !(a.a_status); + ] + +and encode_anon_status s = + let tag, pl = (match s with + | Closed -> 0, [] + | Opened -> 1, [] + | Type.Const -> 2, [] + | Extend tl -> 3, [encode_ref tl (fun tl -> enc_array (List.map encode_type tl)) (fun() -> "")] + | Statics cl -> 4, [encode_clref cl] + | EnumStatics en -> 5, [encode_enref en] + | AbstractStatics ab -> 6, [encode_abref ab] + ) + in + encode_enum IAnonStatus tag pl + +and encode_tparams pl = + enc_array (List.map encode_type pl) + +and encode_clref c = + encode_ref c encode_tclass (fun() -> s_type_path c.cl_path) + +and encode_enref en = + encode_ref en encode_tenum (fun() -> s_type_path en.e_path) + +and encode_cfref cf = + encode_ref cf encode_cfield (fun() -> cf.cf_name) + +and encode_abref ab = + encode_ref ab encode_tabstract (fun() -> s_type_path ab.a_path) + +and encode_type t = + let rec loop = function + | TMono r -> + (match !r with + | None -> 0, [encode_ref r (fun r -> match !r with None -> vnull | Some t -> encode_type t) (fun() -> "")] + | Some t -> loop t) + | TEnum (e, pl) -> + 1 , [encode_ref e encode_tenum (fun() -> s_type_path e.e_path); encode_tparams pl] + | TInst (c, pl) -> + 2 , [encode_clref c; encode_tparams pl] + | TType (t,pl) -> + 3 , [encode_ref t encode_ttype (fun() -> s_type_path t.t_path); encode_tparams pl] + | TFun (pl,ret) -> + let pl = List.map (fun (n,o,t) -> + enc_obj OType_args [ + "name",enc_string n; + "opt",vbool o; + "t",encode_type t + ] + ) pl in + 4 , [enc_array pl; encode_type ret] + | TAnon a -> + 5, [encode_ref a encode_tanon (fun() -> "")] + | TDynamic tsub as t -> + if t == t_dynamic then + 6, [vnull] + else + 6, [encode_type tsub] + | TLazy f -> + loop (!f()) + | TAbstract (a, pl) -> + 8, [encode_abref a; encode_tparams pl] + in + let tag, pl = loop t in + encode_enum IType tag pl + +and encode_lazy_type t = + let rec loop = function + | TMono r -> + (match !r with + | Some t -> loop t + | _ -> encode_type t) + | TLazy f -> + encode_enum IType 7 [encode_lazytype f (fun() -> encode_type (!f()))] + | _ -> + encode_type t + in + loop t + +and decode_type t = + match decode_enum t with + | 0, [r] -> TMono (decode_ref r) + | 1, [e; pl] -> TEnum (decode_ref e, List.map decode_type (dec_array pl)) + | 2, [c; pl] -> TInst (decode_ref c, List.map decode_type (dec_array pl)) + | 3, [t; pl] -> TType (decode_ref t, List.map decode_type (dec_array pl)) + | 4, [pl; r] -> TFun (List.map (fun p -> dec_string (field p "name"), dec_bool (field p "opt"), decode_type (field p "t")) (dec_array pl), decode_type r) + | 5, [a] -> TAnon (decode_ref a) + | 6, [t] -> if t = vnull then t_dynamic else TDynamic (decode_type t) + | 7, [f] -> TLazy (decode_lazytype f) + | 8, [a; pl] -> TAbstract (decode_ref a, List.map decode_type (dec_array pl)) + | _ -> raise Invalid_expr + +and decode_type_decl t = + decode_tdecl (field t "__t") + +(* ---------------------------------------------------------------------- *) +(* TEXPR Encoding *) + +and encode_tconst c = + let tag, pl = match c with + | TInt i -> 0,[vint32 i] + | TFloat f -> 1,[enc_string f] + | TString s -> 2,[enc_string s] + | TBool b -> 3,[vbool b] + | TNull -> 4,[] + | TThis -> 5,[] + | TSuper -> 6,[] + in + encode_enum ITConstant tag pl + +and encode_tvar v = + let f_extra (pl,e) = + enc_obj OTVar_extra [ + "params",encode_type_params pl; + "expr",vopt encode_texpr e + ] + in + enc_obj OTVar [ + "id", vint v.v_id; + "name", enc_string v.v_name; + "t", encode_type v.v_type; + "capture", vbool v.v_capture; + "extra", vopt f_extra v.v_extra; + "meta", encode_meta v.v_meta (fun m -> v.v_meta <- m); + "$", encode_unsafe (Obj.repr v); + ] + +and encode_module_type mt = + let tag,pl = match mt with + | TClassDecl c -> 0,[encode_clref c] + | TEnumDecl e -> 1,[encode_enref e] + | TTypeDecl t -> 2,[encode_ref t encode_ttype (fun () -> s_type_path t.t_path)] + | TAbstractDecl a -> 3,[encode_abref a] + in + encode_enum IModuleType tag pl + +and encode_tfunc func = + enc_obj OTFunc [ + "args",enc_array (List.map (fun (v,c) -> + enc_obj OTFunc_args [ + "v",encode_tvar v; + "value",match c with None -> vnull | Some c -> encode_tconst c + ] + ) func.tf_args); + "t",encode_type func.tf_type; + "expr",encode_texpr func.tf_expr + ] + +and encode_field_access fa = + let encode_instance c tl = + enc_obj OFieldAccess_c [ + "c",encode_clref c; + "params",encode_tparams tl + ] + in + let tag,pl = match fa with + | FInstance(c,tl,cf) -> 0,[encode_clref c;encode_tparams tl;encode_cfref cf] + | FStatic(c,cf) -> 1,[encode_clref c;encode_cfref cf] + | FAnon(cf) -> 2,[encode_cfref cf] + | FDynamic(s) -> 3,[enc_string s] + | FClosure(co,cf) -> 4,[(match co with Some (c,tl) -> encode_instance c tl | None -> vnull);encode_cfref cf] + | FEnum(en,ef) -> 5,[encode_enref en;encode_efield ef] + in + encode_enum IFieldAccess tag pl + +and encode_texpr e = + let rec loop e = + let tag, pl = match e.eexpr with + | TConst c -> 0,[encode_tconst c] + | TLocal v -> 1,[encode_tvar v] + | TArray(e1,e2) -> 2,[loop e1; loop e2] + | TBinop(op,e1,e2) -> 3,[encode_binop op;loop e1;loop e2] + | TField(e1,fa) -> 4,[loop e1;encode_field_access fa] + | TTypeExpr mt -> 5,[encode_module_type mt] + | TParenthesis e1 -> 6,[loop e1] + | TObjectDecl fl -> 7, [enc_array (List.map (fun (f,e) -> + enc_obj OTypedExprDef_fields [ + "name",enc_string f; + "expr",loop e; + ]) fl)] + | TArrayDecl el -> 8,[encode_texpr_list el] + | TCall(e1,el) -> 9,[loop e1;encode_texpr_list el] + | TNew(c,pl,el) -> 10,[encode_clref c;encode_tparams pl;encode_texpr_list el] + | TUnop(op,flag,e1) -> 11,[encode_unop op;vbool (flag = Postfix);loop e1] + | TFunction func -> 12,[encode_tfunc func] + | TVar (v,eo) -> 13,[encode_tvar v;vopt encode_texpr eo] + | TBlock el -> 14,[encode_texpr_list el] + | TFor(v,e1,e2) -> 15,[encode_tvar v;loop e1;loop e2] + | TIf(eif,ethen,eelse) -> 16,[loop eif;loop ethen;vopt encode_texpr eelse] + | TWhile(econd,e1,flag) -> 17,[loop econd;loop e1;vbool (flag = NormalWhile)] + | TSwitch(e1,cases,edef) -> 18,[ + loop e1; + enc_array (List.map (fun (el,e) -> enc_obj OTypedExprDef_cases ["values",encode_texpr_list el;"expr",loop e]) cases); + vopt encode_texpr edef + ] + | TTry(e1,catches) -> 19,[ + loop e1; + enc_array (List.map (fun (v,e) -> + enc_obj OTypedExprDef_catches [ + "v",encode_tvar v; + "expr",loop e + ]) catches + )] + | TReturn e1 -> 20,[vopt encode_texpr e1] + | TBreak -> 21,[] + | TContinue -> 22,[] + | TThrow e1 -> 23,[loop e1] + | TCast(e1,mt) -> 24,[loop e1;match mt with None -> vnull | Some mt -> encode_module_type mt] + | TMeta(m,e1) -> 25,[encode_meta_entry m;loop e1] + | TEnumParameter(e1,ef,i) -> 26,[loop e1;encode_efield ef;vint i] + in + enc_obj OTypedExprDef [ + "pos", encode_pos e.epos; + "expr", encode_enum ITypedExpr tag pl; + "t", encode_type e.etype + ] + in + loop e + +and encode_texpr_list el = + enc_array (List.map encode_texpr el) + +(* ---------------------------------------------------------------------- *) +(* TEXPR Decoding *) + +let decode_tconst c = + match decode_enum c with + | 0, [s] -> TInt (dec_i32 s) + | 1, [s] -> TFloat (dec_string s) + | 2, [s] -> TString (dec_string s) + | 3, [s] -> TBool (dec_bool s) + | 4, [] -> TNull + | 5, [] -> TThis + | 6, [] -> TSuper + | _ -> raise Invalid_expr + +let decode_type_params v = + List.map (fun v -> dec_string (field v "name"),decode_type (field v "t")) (dec_array v) + +let decode_tvar v = + (Obj.obj (decode_unsafe (field v "$")) : tvar) + +let decode_var_access v = + match decode_enum v with + | 0, [] -> AccNormal + | 1, [] -> AccNo + | 2, [] -> AccNever + | 3, [] -> AccResolve + | 4, [] -> AccCall + | 5, [] -> AccInline + | 6, [s1;s2] -> AccRequire(dec_string s1, opt dec_string s2) + | _ -> raise Invalid_expr + +let decode_method_kind v = + match decode_enum v with + | 0, [] -> MethNormal + | 1, [] -> MethInline + | 2, [] -> MethDynamic + | 3, [] -> MethMacro + | _ -> raise Invalid_expr + +let decode_field_kind v = + match decode_enum v with + | 0, [vr;vw] -> Type.Var({v_read = decode_var_access vr; v_write = decode_var_access vw}) + | 1, [m] -> Method (decode_method_kind m) + | _ -> raise Invalid_expr + +let decode_cfield v = + { + cf_name = dec_string (field v "name"); + cf_type = decode_type (field v "type"); + cf_public = dec_bool (field v "isPublic"); + cf_pos = decode_pos (field v "pos"); + cf_name_pos = decode_pos (field v "namePos"); + cf_doc = opt dec_string (field v "doc"); + cf_meta = []; (* TODO *) + cf_kind = decode_field_kind (field v "kind"); + cf_params = decode_type_params (field v "params"); + cf_expr = None; + cf_expr_unoptimized = None; + cf_overloads = decode_ref (field v "overloads"); + } + +let decode_efield v = + { + ef_name = dec_string (field v "name"); + ef_type = decode_type (field v "type"); + ef_pos = decode_pos (field v "pos"); + ef_name_pos = decode_pos (field v "namePos"); + ef_index = dec_int (field v "index"); + ef_meta = []; (* TODO *) + ef_doc = opt dec_string (field v "doc"); + ef_params = decode_type_params (field v "params") + } + +let decode_field_access v = + match decode_enum v with + | 0, [c;tl;cf] -> + let c = decode_ref c in + FInstance(c,List.map decode_type (dec_array tl),decode_ref cf) + | 1, [c;cf] -> FStatic(decode_ref c,decode_ref cf) + | 2, [cf] -> FAnon(decode_ref cf) + | 3, [s] -> FDynamic(dec_string s) + | 4, [co;cf] -> + let co = if co = vnull then None else Some (decode_ref (field co "c"),List.map decode_type (dec_array (field co "params"))) in + FClosure(co,decode_ref cf) + | 5, [e;ef] -> FEnum(decode_ref e,decode_efield ef) + | _ -> raise Invalid_expr + +let decode_module_type v = + match decode_enum v with + | 0, [c] -> TClassDecl (decode_ref c) + | 1, [en] -> TEnumDecl (decode_ref en) + | 2, [t] -> TTypeDecl (decode_ref t) + | 3, [a] -> TAbstractDecl (decode_ref a) + | _ -> raise Invalid_expr + +let rec decode_tfunc v = + { + tf_args = List.map (fun v -> decode_tvar (field v "v"),opt decode_tconst (field v "value")) (dec_array (field v "args")); + tf_type = decode_type (field v "t"); + tf_expr = decode_texpr (field v "expr") + } + +and decode_texpr v = + let rec loop v = + mk (decode (field v "expr")) (decode_type (field v "t")) (decode_pos (field v "pos")) + and decode e = + match decode_enum e with + | 0, [c] -> TConst(decode_tconst c) + | 1, [v] -> TLocal(decode_tvar v) + | 2, [v1;v2] -> TArray(loop v1,loop v2) + | 3, [op;v1;v2] -> TBinop(decode_op op,loop v1,loop v2) + | 4, [v1;fa] -> TField(loop v1,decode_field_access fa) + | 5, [mt] -> TTypeExpr(decode_module_type mt) + | 6, [v1] -> TParenthesis(loop v1) + | 7, [v] -> TObjectDecl(List.map (fun v -> dec_string (field v "name"),loop (field v "expr")) (dec_array v)) + | 8, [vl] -> TArrayDecl(List.map loop (dec_array vl)) + | 9, [v1;vl] -> TCall(loop v1,List.map loop (dec_array vl)) + | 10, [c;tl;vl] -> TNew(decode_ref c,List.map decode_type (dec_array tl),List.map loop (dec_array vl)) + | 11, [op;pf;v1] -> TUnop(decode_unop op,(if dec_bool pf then Postfix else Prefix),loop v1) + | 12, [f] -> TFunction(decode_tfunc f) + | 13, [v;eo] -> TVar(decode_tvar v,opt loop eo) + | 14, [vl] -> TBlock(List.map loop (dec_array vl)) + | 15, [v;v1;v2] -> TFor(decode_tvar v,loop v1,loop v2) + | 16, [vif;vthen;velse] -> TIf(loop vif,loop vthen,opt loop velse) + | 17, [vcond;v1;b] -> TWhile(loop vcond,loop v1,if dec_bool b then NormalWhile else DoWhile) + | 18, [v1;cl;vdef] -> TSwitch(loop v1,List.map (fun v -> List.map loop (dec_array (field v "values")),loop (field v "expr")) (dec_array cl),opt loop vdef) + | 19, [v1;cl] -> TTry(loop v1,List.map (fun v -> decode_tvar (field v "v"),loop (field v "expr")) (dec_array cl)) + | 20, [vo] -> TReturn(opt loop vo) + | 21, [] -> TBreak + | 22, [] -> TContinue + | 23, [v1] -> TThrow(loop v1) + | 24, [v1;mto] -> TCast(loop v1,opt decode_module_type mto) + | 25, [m;v1] -> TMeta(decode_meta_entry m,loop v1) + | 26, [v1;ef;i] -> TEnumParameter(loop v1,decode_efield ef,dec_int i) + | i,el -> Printf.printf "%i %i\n" i (List.length el); raise Invalid_expr + in + try + loop v + with Stack_overflow -> + raise Invalid_expr + +(* ---------------------------------------------------------------------- *) +(* TYPE DEFINITION *) + +let decode_type_def v = + let pack = List.map dec_string (dec_array (field v "pack")) in + let name = decode_placed_name (field v "name_pos") (field v "name") in + let meta = decode_meta_content (field v "meta") in + let pos = decode_pos (field v "pos") in + let isExtern = dec_opt_bool (field v "isExtern") in + let fields = List.map decode_field (dec_array (field v "fields")) in + let mk fl dl = + { + d_name = name; + d_doc = None; + d_params = decode_tparams (field v "params"); + d_meta = meta; + d_flags = fl; + d_data = dl; + } + in + let tdef = (match decode_enum (field v "kind") with + | 0, [] -> + let conv f = + let loop ((n,_),opt,_,t,_) = + match t with + | None -> raise Invalid_expr + | Some t -> n, opt, t + in + let args, params, t = (match f.cff_kind with + | FVar (t,None) -> [], [], t + | FFun f -> List.map loop f.f_args, f.f_params, f.f_type + | _ -> raise Invalid_expr + ) in + { + ec_name = f.cff_name; + ec_doc = f.cff_doc; + ec_meta = f.cff_meta; + ec_pos = f.cff_pos; + ec_args = args; + ec_params = params; + ec_type = t; + } + in + EEnum (mk (if isExtern then [EExtern] else []) (List.map conv fields)) + | 1, [] -> + ETypedef (mk (if isExtern then [EExtern] else []) (CTAnonymous fields,Globals.null_pos)) + | 2, [ext;impl;interf] -> + let flags = if isExtern then [HExtern] else [] in + let is_interface = dec_opt_bool interf in + let interfaces = (match opt (fun v -> List.map decode_path (dec_array v)) impl with Some l -> l | _ -> [] ) in + let flags = (match opt decode_path ext with None -> flags | Some t -> HExtends t :: flags) in + let flags = if is_interface then begin + let flags = HInterface :: flags in + List.map (fun t -> HExtends t) interfaces @ flags + end else begin + List.map (fun t -> HImplements t) interfaces @ flags + end + in + EClass (mk flags fields) + | 3, [t] -> + ETypedef (mk (if isExtern then [EExtern] else []) (decode_ctype t)) + | 4, [tthis;tfrom;tto] -> + let flags = match opt dec_array tfrom with None -> [] | Some ta -> List.map (fun t -> AFromType (decode_ctype t)) ta in + let flags = match opt dec_array tto with None -> flags | Some ta -> (List.map (fun t -> AToType (decode_ctype t)) ta) @ flags in + let flags = match opt decode_ctype tthis with None -> flags | Some t -> (AIsType t) :: flags in + EAbstract(mk flags fields) + | _ -> + raise Invalid_expr + ) in + (* if our package ends with an uppercase letter, then it's the module name *) + let pack,name = (match List.rev pack with + | last :: l when not (is_lower_ident last) -> List.rev l, last + | _ -> pack, fst name + ) in + (pack, name), tdef, pos + +(* ---------------------------------------------------------------------- *) +(* VALUE-TO-CONSTANT *) + +let rec make_const e = + match e.eexpr with + | TConst c -> + (match c with + | TInt i -> vint32 i + | TFloat s -> vfloat (float_of_string s) + | TString s -> enc_string s + | TBool b -> vbool b + | TNull -> vnull + | TThis | TSuper -> raise Exit) + | TParenthesis e | TMeta(_,e) | TCast(e,None) -> + make_const e + | TObjectDecl el -> + enc_obj O__Const (List.map (fun (f,e) -> f, make_const e) el) + | TArrayDecl al -> + enc_array (List.map make_const al) + | _ -> + raise Exit + + +(* ------------------------------------------------------------------------- *) +(* MACRO API *) + +(** + + Our macro API implementation. It gets called by the interpreter and + accesses the compiler with the compiler_api + +**) + +let macro_api ccom get_api = + [ + "current_pos", vfun0 (fun() -> + encode_pos (get_api()).pos + ); + "error", vfun2 (fun msg p -> + let msg = dec_string msg in + let p = decode_pos p in + (ccom()).error msg p; + raise Abort + ); + "fatal_error", vfun2 (fun msg p -> + let msg = dec_string msg in + let p = decode_pos p in + raise (Error.Fatal_error (msg,p)) + ); + "warning", vfun2 (fun msg p -> + let msg = dec_string msg in + let p = decode_pos p in + (ccom()).warning msg p; + vnull + ); + "class_path", vfun0 (fun() -> + enc_array (List.map enc_string (ccom()).class_path); + ); + "resolve_path", vfun1 (fun file -> + let file = dec_string file in + enc_string (try Common.find_file (ccom()) file with Not_found -> failwith ("File not found '" ^ file ^ "'")) + ); + "define", vfun2 (fun s v -> + let v = if v = vnull then "" else "=" ^ (dec_string v) in + Common.raw_define (ccom()) ((dec_string s) ^ v); + vnull + ); + "defined", vfun1 (fun s -> + vbool (Common.raw_defined (ccom()) (dec_string s)) + ); + "defined_value", vfun1 (fun s -> + try enc_string (Common.raw_defined_value (ccom()) (dec_string s)) with Not_found -> vnull + ); + "get_defines", vfun0 (fun() -> + encode_string_map enc_string (ccom()).defines + ); + "get_type", vfun1 (fun s -> + let tname = dec_string s in + match (get_api()).get_type tname with + | None -> failwith ("Type not found '" ^ tname ^ "'") + | Some t -> encode_type t + ); + "get_module", vfun1 (fun s -> + enc_array (List.map encode_type ((get_api()).get_module (dec_string s))) + ); + "on_after_typing", vfun1 (fun f -> + let f = prepare_callback f 1 in + (get_api()).after_typing (fun tl -> ignore(f [enc_array (List.map encode_module_type tl)])); + vnull + ); + "on_generate", vfun1 (fun f -> + let f = prepare_callback f 1 in + (get_api()).on_generate (fun tl -> ignore(f [enc_array (List.map encode_type tl)])); + vnull + ); + "on_after_generate", vfun1 (fun f -> + let f = prepare_callback f 0 in + (get_api()).after_generate (fun () -> ignore(f [])); + vnull + ); + "on_type_not_found", vfun1 (fun f -> + let f = prepare_callback f 1 in + (get_api()).on_type_not_found (fun path -> f [enc_string path]); + vnull + ); + "do_parse", vfun3 (fun s p b -> + let s = dec_string s in + if s = "" then raise Invalid_expr; + encode_expr ((get_api()).parse_string s (decode_pos p) (dec_bool b)) + ); + "make_expr", vfun2 (fun v p -> + encode_expr (value_to_expr v (decode_pos p)) + ); + "signature", vfun1 (fun v -> + enc_string (Digest.to_hex (value_signature v)) + ); + "to_complex_type", vfun1 (fun v -> + try encode_ctype (TExprToExpr.convert_type' (decode_type v)) + with Exit -> vnull + ); + "unify", vfun2 (fun t1 t2 -> + let e1 = mk (TObjectDecl []) (decode_type t1) Globals.null_pos in + try ignore(((get_api()).cast_or_unify) (decode_type t2) e1 Globals.null_pos); vbool true + with Error.Error (Error.Unify _,_) -> vbool false + ); + "typeof", vfun1 (fun v -> + encode_type ((get_api()).type_expr (decode_expr v)).etype + ); + "type_expr", vfun1 (fun v -> + encode_texpr ((get_api()).type_expr (decode_expr v)) + ); + "resolve_type", vfun2 (fun t p -> + encode_type ((get_api()).resolve_type (fst (decode_ctype t)) (decode_pos p)); + ); + "s_type", vfun1 (fun v -> + enc_string (Type.s_type (print_context()) (decode_type v)) + ); + "s_expr", vfun2 (fun v b -> + let f = if dec_opt_bool b then Type.s_expr_pretty false "" false else Type.s_expr_ast true "" in + enc_string (f (Type.s_type (print_context())) (decode_texpr v)) + ); + "is_fmt_string", vfun1 (fun p -> + vbool (Lexer.is_fmt_string (decode_pos p)) + ); + "format_string", vfun2 (fun s p -> + encode_expr ((get_api()).format_string (dec_string s) (decode_pos p)) + ); + "allow_package", vfun1 (fun s -> + (get_api()).allow_package (dec_string s); + vnull + ); + "type_patch", vfun4 (fun t f s v -> + (get_api()).type_patch (dec_string t) (dec_string f) (dec_bool s) (opt dec_string v); + vnull + ); + "meta_patch", vfun4 (fun m t f s -> + (get_api()).meta_patch (dec_string m) (dec_string t) (opt dec_string f) (dec_bool s); + vnull + ); + "add_global_metadata_impl", vfun5 (fun s1 s2 b1 b2 b3 -> + (get_api()).add_global_metadata (dec_string s1) (dec_string s2) (dec_bool b1,dec_bool b2,dec_bool b3); + vnull + ); + "set_custom_js_generator", vfun1 (fun f -> + let f = prepare_callback f 1 in + (get_api()).set_js_generator (fun js_ctx -> + let com = ccom() in + let api = enc_obj OJSGenApi [ + "outputFile", enc_string com.file; + "types", enc_array (List.map (fun t -> encode_type (type_of_module_type t)) com.types); + "main", (match com.main with None -> vnull | Some e -> encode_texpr e); + "generateValue", vfun1 (fun v -> + let e = decode_texpr v in + let str = Genjs.gen_single_expr js_ctx e false in + enc_string str + ); + "isKeyword", vfun1 (fun v -> + vbool (Hashtbl.mem Genjs.kwds (dec_string v)) + ); + "hasFeature", vfun1 (fun v -> + vbool (Common.has_feature com (dec_string v)) + ); + "addFeature", vfun1 (fun v -> + Common.add_feature com (dec_string v); + vnull + ); + "quoteString", vfun1 (fun v -> + enc_string ("\"" ^ Ast.s_escape (dec_string v) ^ "\"") + ); + "buildMetaData", vfun1 (fun t -> + match Codegen.build_metadata com (decode_type_decl t) with + | None -> vnull + | Some e -> encode_texpr e + ); + "generateStatement", vfun1 (fun v -> + let e = decode_texpr v in + let str = Genjs.gen_single_expr js_ctx e true in + enc_string str + ); + "setTypeAccessor", vfun1 (fun callb -> + let callb = prepare_callback callb 1 in + js_ctx.Genjs.type_accessor <- (fun t -> + dec_string (callb [encode_type (type_of_module_type t)]) + ); + vnull + ); + "setCurrentClass", vfun1 (fun c -> + Genjs.set_current_class js_ctx (match decode_type_decl c with TClassDecl c -> c | _ -> assert false); + vnull + ); + ] in + ignore(f [api]); + ); + vnull + ); + "get_pos_infos", vfun1 (fun p -> + let p = decode_pos p in + enc_obj OContext_getPosInfos ["min",vint p.Globals.pmin;"max",vint p.Globals.pmax;"file",enc_string p.Globals.pfile] + ); + "make_position", vfun3 (fun min max file -> + encode_pos { Globals.pmin = dec_int min; Globals.pmax = dec_int max; Globals.pfile = dec_string file } + ); + "add_resource", vfun2 (fun name data -> + let name = dec_string name in + let data = decode_bytes data in + if name = "" then failwith "Empty resource name"; + Hashtbl.replace (ccom()).resources name data; + let m = if name.[0] = '$' then (get_api()).current_macro_module() else (get_api()).current_module() in + m.m_extra.m_binded_res <- PMap.add name data m.m_extra.m_binded_res; + vnull + ); + "get_resources", vfun0 (fun() -> + encode_string_map encode_bytes (Hashtbl.fold (fun k v acc -> PMap.add k v acc) (ccom()).resources PMap.empty) + ); + "get_local_module", vfun0 (fun() -> + let m = (get_api()).current_module() in + enc_string (s_type_path m.m_path); + ); + "get_local_type", vfun0 (fun() -> + match (get_api()).get_local_type() with + | None -> vnull + | Some t -> encode_type t + ); + "get_expected_type", vfun0 (fun() -> + match (get_api()).get_expected_type() with + | None -> vnull + | Some t -> encode_type t + ); + "get_call_arguments", vfun0 (fun() -> + match (get_api()).get_call_arguments() with + | None -> vnull + | Some el -> enc_array (List.map encode_expr el) + ); + "get_local_method", vfun0 (fun() -> + enc_string ((get_api()).get_local_method()) + ); + "get_local_using", vfun0 (fun() -> + enc_array (List.map encode_clref ((get_api()).get_local_using())) + ); + "get_local_imports", vfun0 (fun() -> + enc_array (List.map encode_import ((get_api()).get_local_imports())) + ); + "local_vars", vfun1 (fun as_var -> + let as_var = dec_opt_bool as_var in + let vars = (get_api()).get_local_vars() in + encode_string_map (if as_var then encode_tvar else (fun v -> encode_type v.v_type)) vars + ); + "follow_with_abstracts", vfun2 (fun v once -> + let t = decode_type v in + let follow_once t = + match t with + | TMono r -> + (match !r with + | None -> t + | Some t -> t) + | TAbstract (a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> + Abstract.get_underlying_type a tl + | TAbstract _ | TEnum _ | TInst _ | TFun _ | TAnon _ | TDynamic _ -> + t + | TType (t,tl) -> + apply_params t.t_params tl t.t_type + | TLazy f -> + (!f)() + in + encode_type (if dec_opt_bool once then follow_once t else Abstract.follow_with_abstracts t) + ); + "follow", vfun2 (fun v once -> + let t = decode_type v in + let follow_once t = + match t with + | TMono r -> + (match !r with + | None -> t + | Some t -> t) + | TAbstract _ | TEnum _ | TInst _ | TFun _ | TAnon _ | TDynamic _ -> + t + | TType (t,tl) -> + apply_params t.t_params tl t.t_type + | TLazy f -> + (!f)() + in + encode_type (if dec_opt_bool once then follow_once t else follow t) + ); + "get_build_fields", vfun0 (fun() -> + (get_api()).get_build_fields() + ); + "define_type", vfun1 (fun v -> + (get_api()).define_type v; + vnull + ); + "define_module", vfun4 (fun path vl ui ul -> + (get_api()).define_module (dec_string path) (dec_array vl) (List.map decode_import (dec_array ui)) (List.map fst (List.map decode_path (dec_array ul))); + vnull + ); + "add_class_path", vfun1 (fun cp -> + let com = ccom() in + let cp = dec_string cp in + let cp = Path.add_trailing_slash cp in + com.class_path <- cp :: com.class_path; + (match com.get_macros() with + | Some(mcom) -> + mcom.class_path <- cp :: com.class_path; + | None -> + ()); + Hashtbl.clear com.file_lookup_cache; + vnull + ); + "add_native_lib", vfun1 (fun file -> + let file = dec_string file in + let com = ccom() in + (match com.platform with + | Globals.Flash -> Genswf.add_swf_lib com file false + | Globals.Java -> Genjava.add_java_lib com file false + | Globals.Cs -> + let file, is_std = match ExtString.String.nsplit file "@" with + | [file] -> + file,false + | [file;"std"] -> + file,true + | _ -> failwith ("unsupported file@`std` format: " ^ file) + in + Gencs.add_net_lib com file is_std + | _ -> failwith "Unsupported platform"); + vnull + ); + "add_native_arg", vfun1 (fun arg -> + let arg = dec_string arg in + let com = ccom() in + (match com.platform with + | Globals.Java | Globals.Cs | Globals.Cpp -> + com.c_args <- arg :: com.c_args + | _ -> failwith "Unsupported platform"); + vnull + ); + "register_module_dependency", vfun2 (fun m file -> + (get_api()).module_dependency (dec_string m) (dec_string file) false; + vnull + ); + "register_module_reuse_call", vfun2 (fun m mcall -> + (get_api()).module_dependency (dec_string m) (dec_string mcall) true; + vnull + ); + "get_typed_expr", vfun1 (fun e -> + let e = decode_texpr e in + encode_expr (TExprToExpr.convert_expr e) + ); + "store_typed_expr", vfun1 (fun e -> + let e = decode_texpr e in + encode_expr ((get_api()).store_typed_expr e) + ); + "get_output", vfun0 (fun() -> + enc_string (ccom()).file + ); + "set_output", vfun1 (fun s -> + (ccom()).file <- dec_string s; + vnull + ); + "get_display_pos", vfun0 (fun() -> + let p = !Parser.resume_display in + if p = Globals.null_pos then + vnull + else + enc_obj OCompiler_getDisplayPos ["file",enc_string p.Globals.pfile;"pos",vint p.Globals.pmin] + ); + "pattern_locals", vfun2 (fun e t -> + let loc = (get_api()).get_pattern_locals (decode_expr e) (decode_type t) in + encode_string_map (fun (v,_) -> encode_type v.v_type) loc + ); + "on_macro_context_reused", vfun1 (fun c -> + let c = prepare_callback c 0 in + (get_api()).on_reuse (fun() -> dec_bool (c [])); + vnull + ); + "apply_params", vfun3 (fun tpl tl t -> + let tl = List.map decode_type (dec_array tl) in + let tpl = List.map (fun v -> dec_string (field v "name"), decode_type (field v "t")) (dec_array tpl) in + let rec map t = match t with + | TInst({cl_kind = KTypeParameter _},_) -> + begin try + (* use non-physical equality check here to make apply_params work *) + snd (List.find (fun (_,t2) -> type_iseq t t2) tpl) + with Not_found -> + Type.map map t + end + | _ -> Type.map map t + in + encode_type (apply_params tpl tl (map (decode_type t))) + ); + "include_file", vfun2 (fun file position -> + let file = dec_string file in + let position = dec_string position in + let file = if Sys.file_exists file then + file + else try Common.find_file (ccom()) file with + | Not_found -> + failwith ("unable to find file for inclusion: " ^ file) + in + (ccom()).include_files <- (file, position) :: (ccom()).include_files; + vnull + ); + (* Compilation server *) + "server_add_module_check_policy", vfun4 (fun filter policy recursive context_options -> + let filter = List.map dec_string (dec_array filter) in + let policy = List.map dec_int (dec_array policy) in + (get_api()).add_module_check_policy filter policy (dec_bool recursive) (dec_int context_options); + vnull + ); + "server_invalidate_files", vfun1 (fun a -> + let cs = match CompilationServer.get() with Some cs -> cs | None -> failwith "compilation server not running" in + List.iter (fun v -> + let s = dec_string v in + let s = Path.unique_full_path s in + CompilationServer.taint_modules cs s; + CompilationServer.remove_files cs s; + ) (dec_array a); + vnull + ); + ] + + +end diff --git a/src/macro/macroContext.ml b/src/macro/macroContext.ml new file mode 100644 index 00000000..b19a3a02 --- /dev/null +++ b/src/macro/macroContext.ml @@ -0,0 +1,765 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Ast +open Common.DisplayMode +open Common +open Type +open Typecore +open Error +open Globals + +module InterpImpl = Interp (* Hlmacro *) + +module Interp = struct + module BuiltApi = MacroApi.MacroApiImpl(InterpImpl) + include InterpImpl + include BuiltApi +end + +let macro_enable_cache = ref false +let macro_interp_cache = ref None +let macro_interp_on_reuse = ref [] +let macro_interp_reused = ref false + +let delayed_macro_result = ref ((fun() -> assert false) : unit -> unit -> Interp.value) +let unify_call_args_ref = ref (fun _ _ _ _ _ _ _-> assert false) +let unify_call_args a b c d e f g : (texpr list * t) = !unify_call_args_ref a b c d e f g + +let get_next_stored_typed_expr_id = + let uid = ref 0 in + (fun() -> incr uid; !uid) + +let get_stored_typed_expr com id = + let e = PMap.find id com.stored_typed_exprs in + Texpr.duplicate_tvars e + +let get_type_patch ctx t sub = + let new_patch() = + { tp_type = None; tp_remove = false; tp_meta = [] } + in + let path = Ast.parse_path t in + let h, tp = (try + Hashtbl.find ctx.g.type_patches path + with Not_found -> + let h = Hashtbl.create 0 in + let tp = new_patch() in + Hashtbl.add ctx.g.type_patches path (h,tp); + h, tp + ) in + match sub with + | None -> tp + | Some k -> + try + Hashtbl.find h k + with Not_found -> + let tp = new_patch() in + Hashtbl.add h k tp; + tp + +let macro_timer ctx l = + Common.timer (if Common.defined ctx.com Define.MacroTimes then ("macro" :: l) else ["macro"]) + +let typing_timer ctx need_type f = + let t = Common.timer ["typing"] in + let old = ctx.com.error and oldp = ctx.pass in + (* + disable resumable errors... unless we are in display mode (we want to reach point of completion) + *) + (*if ctx.com.display = DMNone then ctx.com.error <- (fun e p -> raise (Error(Custom e,p)));*) (* TODO: review this... *) + ctx.com.error <- (fun e p -> raise (Error(Custom e,p))); + if need_type && ctx.pass < PTypeField then ctx.pass <- PTypeField; + let exit() = + t(); + ctx.com.error <- old; + ctx.pass <- oldp; + in + try + let r = f() in + exit(); + r + with Error (ekind,p) -> + exit(); + Interp.compiler_error (error_msg ekind) p + | WithTypeError (l,p) -> + exit(); + Interp.compiler_error (error_msg l) p + | e -> + exit(); + raise e + +let load_macro_ref : (typer -> bool -> path -> string -> pos -> (typer * ((string * bool * t) list * t * tclass * Type.tclass_field) * (Interp.value list -> Interp.value option))) ref = ref (fun _ _ _ _ -> assert false) + +let make_macro_api ctx p = + let parse_expr_string s p inl = + typing_timer ctx false (fun() -> try Parser.parse_expr_string ctx.com s p error inl with Exit -> raise MacroApi.Invalid_expr) + in + { + MacroApi.pos = p; + MacroApi.get_com = (fun() -> ctx.com); + MacroApi.get_type = (fun s -> + typing_timer ctx true (fun() -> + let path = parse_path s in + let tp = match List.rev (fst path) with + | s :: sl when String.length s > 0 && (match s.[0] with 'A'..'Z' -> true | _ -> false) -> + { tpackage = List.rev sl; tname = s; tparams = []; tsub = Some (snd path) } + | _ -> + { tpackage = fst path; tname = snd path; tparams = []; tsub = None } + in + try + let m = Some (Typeload.load_instance ctx (tp,null_pos) true p) in + m + with Error (Module_not_found _,p2) when p == p2 -> + None + ) + ); + MacroApi.resolve_type = (fun t p -> + typing_timer ctx true (fun() -> Typeload.load_complex_type ctx false p (t,null_pos)) + ); + MacroApi.get_module = (fun s -> + typing_timer ctx true (fun() -> + let path = parse_path s in + let m = List.map type_of_module_type (Typeload.load_module ctx path p).m_types in + m + ) + ); + MacroApi.after_typing = (fun f -> + Common.add_typing_filter ctx.com (fun tl -> + let t = macro_timer ctx ["afterTyping"] in + f tl; + t() + ) + ); + MacroApi.on_generate = (fun f -> + Common.add_filter ctx.com (fun() -> + let t = macro_timer ctx ["onGenerate"] in + f (List.map type_of_module_type ctx.com.types); + t() + ) + ); + MacroApi.after_generate = (fun f -> + Common.add_final_filter ctx.com (fun() -> + let t = macro_timer ctx ["afterGenerate"] in + f(); + t() + ) + ); + MacroApi.on_type_not_found = (fun f -> + ctx.com.load_extern_type <- ctx.com.load_extern_type @ [fun path p -> + let td = f (s_type_path path) in + if td = Interp.vnull then + None + else + let (pack,name),tdef,p = Interp.decode_type_def td in + Some (name,(pack,[tdef,p])) + ]; + ); + MacroApi.parse_string = parse_expr_string; + MacroApi.type_expr = (fun e -> + typing_timer ctx true (fun() -> type_expr ctx e Value) + ); + MacroApi.type_macro_expr = (fun e -> + let e = typing_timer ctx true (fun() -> type_expr ctx e Value) in + let rec loop e = match e.eexpr with + | TField(_,FStatic(c,({cf_kind = Method _} as cf))) -> ignore(!load_macro_ref ctx false c.cl_path cf.cf_name e.epos) + | _ -> Type.iter loop e + in + loop e; + e + ); + MacroApi.store_typed_expr = (fun te -> + let p = te.epos in + let id = get_next_stored_typed_expr_id() in + ctx.com.stored_typed_exprs <- PMap.add id te ctx.com.stored_typed_exprs; + let eid = (EConst (Int (string_of_int id))), p in + (EMeta ((Meta.StoredTypedExpr,[],p), eid)), p + ); + MacroApi.allow_package = (fun v -> Common.allow_package ctx.com v); + MacroApi.type_patch = (fun t f s v -> + typing_timer ctx false (fun() -> + let v = (match v with None -> None | Some s -> + match Parser.parse_string ctx.com ("typedef T = " ^ s) null_pos error false with + | _,[ETypedef { d_data = ct },_] -> Some ct + | _ -> assert false + ) in + let tp = get_type_patch ctx t (Some (f,s)) in + match v with + | None -> tp.tp_remove <- true + | Some _ -> tp.tp_type <- Option.map fst v + ); + ); + MacroApi.meta_patch = (fun m t f s -> + let m = (match Parser.parse_string ctx.com (m ^ " typedef T = T") null_pos error false with + | _,[ETypedef t,_] -> t.d_meta + | _ -> assert false + ) in + let tp = get_type_patch ctx t (match f with None -> None | Some f -> Some (f,s)) in + tp.tp_meta <- tp.tp_meta @ m; + ); + MacroApi.set_js_generator = (fun gen -> + let js_ctx = Genjs.alloc_ctx ctx.com in + ctx.com.js_gen <- Some (fun() -> + let t = macro_timer ctx ["jsGenerator"] in + gen js_ctx; + t() + ); + ); + MacroApi.get_local_type = (fun() -> + match ctx.g.get_build_infos() with + | Some (mt,tl,_) -> + Some (match mt with + | TClassDecl c -> TInst (c,tl) + | TEnumDecl e -> TEnum (e,tl) + | TTypeDecl t -> TType (t,tl) + | TAbstractDecl a -> TAbstract(a,tl)) + | None -> + if ctx.curclass == null_class then + None + else + Some (TInst (ctx.curclass,[])) + ); + MacroApi.get_expected_type = (fun() -> + match ctx.with_type_stack with + | (WithType t) :: _ -> Some t + | _ -> None + ); + MacroApi.get_call_arguments = (fun() -> + match ctx.call_argument_stack with + | [] -> None + | el :: _ -> Some el + ); + MacroApi.get_local_method = (fun() -> + ctx.curfield.cf_name; + ); + MacroApi.get_local_using = (fun() -> + List.map fst ctx.m.module_using; + ); + MacroApi.get_local_imports = (fun() -> + ctx.m.module_imports; + ); + MacroApi.get_local_vars = (fun () -> + ctx.locals; + ); + MacroApi.get_build_fields = (fun() -> + match ctx.g.get_build_infos() with + | None -> Interp.vnull + | Some (_,_,fields) -> Interp.enc_array (List.map Interp.encode_field fields) + ); + MacroApi.get_pattern_locals = (fun e t -> + !get_pattern_locals_ref ctx e t + ); + MacroApi.define_type = (fun v -> + let m, tdef, pos = (try Interp.decode_type_def v with MacroApi.Invalid_expr -> Interp.exc_string "Invalid type definition") in + let add is_macro ctx = + let mnew = Typeload.type_module ctx m ctx.m.curmod.m_extra.m_file [tdef,pos] pos in + mnew.m_extra.m_kind <- if is_macro then MMacro else MFake; + add_dependency mnew ctx.m.curmod; + in + add false ctx; + (* if we are adding a class which has a macro field, we also have to add it to the macro context (issue #1497) *) + if not ctx.in_macro then match tdef,ctx.g.macros with + | EClass c,Some (_,mctx) when List.exists (fun cff -> (Meta.has Meta.Macro cff.cff_meta || List.mem AMacro cff.cff_access)) c.d_data -> + add true mctx + | _ -> + () + ); + MacroApi.define_module = (fun m types imports usings -> + let types = List.map (fun v -> + let _, tdef, pos = (try Interp.decode_type_def v with MacroApi.Invalid_expr -> Interp.exc_string "Invalid type definition") in + tdef, pos + ) types in + let pos = (match types with [] -> null_pos | (_,p) :: _ -> p) in + let imports = List.map (fun (il,ik) -> EImport(il,ik),pos) imports in + let usings = List.map (fun tp -> + let sl = tp.tpackage @ [tp.tname] @ (match tp.tsub with None -> [] | Some s -> [s]) in + EUsing (List.map (fun s -> s,null_pos) sl),pos + ) usings in + let types = imports @ usings @ types in + let mpath = Ast.parse_path m in + begin try + let m = Hashtbl.find ctx.g.modules mpath in + ignore(Typeload.type_types_into_module ctx m types pos) + with Not_found -> + let mnew = Typeload.type_module ctx mpath ctx.m.curmod.m_extra.m_file types pos in + mnew.m_extra.m_kind <- MFake; + add_dependency mnew ctx.m.curmod; + end + ); + MacroApi.module_dependency = (fun mpath file ismacro -> + let m = typing_timer ctx false (fun() -> Typeload.load_module ctx (parse_path mpath) p) in + if ismacro then + m.m_extra.m_macro_calls <- file :: List.filter ((<>) file) m.m_extra.m_macro_calls + else + add_dependency m (create_fake_module ctx file); + ); + MacroApi.current_module = (fun() -> + ctx.m.curmod + ); + MacroApi.current_macro_module = (fun () -> assert false); + MacroApi.delayed_macro = (fun i -> + let mctx = (match ctx.g.macros with None -> assert false | Some (_,mctx) -> mctx) in + let f = (try DynArray.get mctx.g.delayed_macros i with _ -> failwith "Delayed macro retrieve failure") in + f(); + let ret = !delayed_macro_result in + delayed_macro_result := (fun() -> assert false); + ret + ); + MacroApi.use_cache = (fun() -> + !macro_enable_cache + ); + MacroApi.format_string = (fun s p -> + ctx.g.do_format_string ctx s p + ); + MacroApi.cast_or_unify = (fun t e p -> + AbstractCast.cast_or_unify_raise ctx t e p + ); + MacroApi.add_global_metadata = (fun s1 s2 config -> + let meta = (match Parser.parse_string ctx.com (s2 ^ " typedef T = T") null_pos error false with + | _,[ETypedef t,_] -> t.d_meta + | _ -> assert false + ) in + List.iter (fun m -> + ctx.g.global_metadata <- (ExtString.String.nsplit s1 ".",m,config) :: ctx.g.global_metadata; + ) meta; + ); + MacroApi.add_module_check_policy = (fun sl il b i -> + let add ctx = + ctx.g.module_check_policies <- (List.fold_left (fun acc s -> (ExtString.String.nsplit s ".",List.map Obj.magic il,b) :: acc) ctx.g.module_check_policies sl); + Hashtbl.iter (fun _ m -> m.m_extra.m_check_policy <- Typeload.get_policy ctx m.m_path) ctx.g.modules; + in + let add_macro ctx = match ctx.g.macros with + | None -> () + | Some(_,mctx) -> add mctx; + in + match Obj.magic i with + | CompilationServer.NormalContext -> add ctx + | CompilationServer.MacroContext -> add_macro ctx + | CompilationServer.NormalAndMacroContext -> add ctx; add_macro ctx; + ); + MacroApi.on_reuse = (fun f -> + macro_interp_on_reuse := f :: !macro_interp_on_reuse + ); + } + +let rec init_macro_interp ctx mctx mint = + let p = null_pos in + ignore(Typeload.load_module mctx (["haxe";"macro"],"Expr") p); + ignore(Typeload.load_module mctx (["haxe";"macro"],"Type") p); + flush_macro_context mint ctx; + Interp.init mint; + if !macro_enable_cache && not (Common.defined mctx.com Define.NoMacroCache) then begin + macro_interp_cache := Some mint; + macro_interp_on_reuse := []; + macro_interp_reused := true; + end + +and flush_macro_context mint ctx = + let t = macro_timer ctx ["flush"] in + let mctx = (match ctx.g.macros with None -> assert false | Some (_,mctx) -> mctx) in + ctx.g.do_finalize mctx; + let _, types, modules = ctx.g.do_generate mctx in + mctx.com.types <- types; + mctx.com.Common.modules <- modules; + let check_reuse() = + if !macro_interp_reused then + true + else if not (List.for_all (fun f -> f()) !macro_interp_on_reuse) then + false + else begin + macro_interp_reused := true; + true; + end + in + (* if one of the type we are using has been modified, we need to create a new macro context from scratch *) + let mint = if not (Interp.can_reuse mint types && check_reuse()) then begin + let com2 = mctx.com in + let mint = Interp.create com2 (make_macro_api ctx Globals.null_pos) in + let macro = ((fun() -> Interp.select mint), mctx) in + ctx.g.macros <- Some macro; + mctx.g.macros <- Some macro; + init_macro_interp ctx mctx mint; + mint + end else mint in + (* we should maybe ensure that all filters in Main are applied. Not urgent atm *) + let expr_filters = [AbstractCast.handle_abstract_casts mctx; Filters.captured_vars mctx.com; Filters.rename_local_vars mctx] in + + (* + some filters here might cause side effects that would break compilation server. + let's save the minimal amount of information we need + *) + let minimal_restore t = + match t with + | TClassDecl c -> + let meta = c.cl_meta in + let path = c.cl_path in + c.cl_restore <- (fun() -> c.cl_meta <- meta; c.cl_path <- path); + | _ -> + () + in + let type_filters = [ + Filters.add_field_inits mctx; + minimal_restore; + Filters.apply_native_paths mctx + ] in + let ready = fun t -> + Filters.apply_filters_once mctx expr_filters t; + List.iter (fun f -> f t) type_filters + in + (try Interp.add_types mint types ready + with Error (e,p) -> t(); raise (Fatal_error(error_msg e,p))); + t(); + Filters.next_compilation() + +let create_macro_interp ctx mctx = + let com2 = mctx.com in + let mint, init = (match !macro_interp_cache with + | None -> + let mint = Interp.create com2 (make_macro_api ctx null_pos) in + mint, (fun() -> init_macro_interp ctx mctx mint) + | Some mint -> + macro_interp_reused := false; + Interp.do_reuse mint (make_macro_api ctx null_pos); + mint, (fun() -> ()) + ) in + let on_error = com2.error in + com2.error <- (fun e p -> + Interp.set_error (Interp.get_ctx()) true; + macro_interp_cache := None; + on_error e p + ); + let macro = ((fun() -> Interp.select mint), mctx) in + ctx.g.macros <- Some macro; + mctx.g.macros <- Some macro; + (* mctx.g.core_api <- ctx.g.core_api; // causes some issues because of optional args and Null type in Flash9 *) + init() + +let get_macro_context ctx p = + let api = make_macro_api ctx p in + match ctx.g.macros with + | Some (select,ctx) -> + select(); + api, ctx + | None -> + let com2 = Common.clone ctx.com in + ctx.com.get_macros <- (fun() -> Some com2); + com2.package_rules <- PMap.empty; + com2.main_class <- None; + com2.display <- DisplayMode.create DMNone; + List.iter (fun p -> com2.defines <- PMap.remove (Globals.platform_name p) com2.defines) Globals.platforms; + com2.defines_signature <- None; + com2.class_path <- List.filter (fun s -> not (ExtString.String.exists s "/_std/")) com2.class_path; + let name = platform_name !Globals.macro_platform in + com2.class_path <- List.map (fun p -> p ^ name ^ "/_std/") com2.std_path @ com2.class_path; + let to_remove = List.map (fun d -> fst (Define.infos d)) [Define.NoTraces] in + let to_remove = to_remove @ List.map (fun (_,d) -> "flash" ^ d) Common.flash_versions in + com2.defines <- PMap.foldi (fun k v acc -> if List.mem k to_remove then acc else PMap.add k v acc) com2.defines PMap.empty; + Common.define com2 Define.Macro; + Common.init_platform com2 !Globals.macro_platform; + let mctx = ctx.g.do_create com2 in + mctx.is_display_file <- ctx.is_display_file; + create_macro_interp ctx mctx; + api, mctx + +let load_macro ctx display cpath f p = + let t = macro_timer ctx ["typing";s_type_path cpath ^ "." ^ f] in + let api, mctx = get_macro_context ctx p in + let mint = Interp.get_ctx() in + let cpath, sub = (match List.rev (fst cpath) with + | name :: pack when name.[0] >= 'A' && name.[0] <= 'Z' -> (List.rev pack,name), Some (snd cpath) + | _ -> cpath, None + ) in + let meth = try Hashtbl.find mctx.com.cached_macros (cpath,f) with Not_found -> + (* Temporarily enter display mode while typing the macro. *) + if display then mctx.com.display <- ctx.com.display; + let m = (try Hashtbl.find ctx.g.types_module cpath with Not_found -> cpath) in + let mloaded = Typeload.load_module mctx m p in + api.MacroApi.current_macro_module <- (fun() -> mloaded); + mctx.m <- { + curmod = mloaded; + module_types = []; + module_using = []; + module_globals = PMap.empty; + wildcard_packages = []; + module_imports = []; + }; + add_dependency ctx.m.curmod mloaded; + let mt = Typeload.load_type_def mctx p { tpackage = fst cpath; tname = snd cpath; tparams = []; tsub = sub } in + let cl, meth = (match mt with + | TClassDecl c -> + let t = macro_timer ctx ["finalize"] in + mctx.g.do_finalize mctx; + t(); + c, (try PMap.find f c.cl_statics with Not_found -> error ("Method " ^ f ^ " not found on class " ^ s_type_path cpath) p) + | _ -> error "Macro should be called on a class" p + ) in + if not (Common.defined ctx.com Define.NoDeprecationWarnings) then + Display.DeprecationCheck.check_cf mctx.com meth p; + let meth = (match follow meth.cf_type with TFun (args,ret) -> args,ret,cl,meth | _ -> error "Macro call should be a method" p) in + mctx.com.display <- DisplayMode.create DMNone; + if not ctx.in_macro then flush_macro_context mint ctx; + Hashtbl.add mctx.com.cached_macros (cpath,f) meth; + mctx.m <- { + curmod = null_module; + module_types = []; + module_using = []; + module_globals = PMap.empty; + wildcard_packages = []; + module_imports = []; + }; + meth + in + t(); + let call args = + let t = macro_timer ctx ["execution";s_type_path cpath ^ "." ^ f] in + incr stats.s_macros_called; + let r = Interp.call_path (Interp.get_ctx()) ((fst cpath) @ [(match sub with None -> snd cpath | Some s -> s)]) f args api in + t(); + r + in + mctx, meth, call + +type macro_arg_type = + | MAExpr + | MAFunction + | MAOther + +let type_macro ctx mode cpath f (el:Ast.expr list) p = + let mctx, (margs,mret,mclass,mfield), call_macro = load_macro ctx (mode = MDisplay) cpath f p in + let mpos = mfield.cf_pos in + let ctexpr = { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = None } in + let expr = Typeload.load_instance mctx (ctexpr,null_pos) false p in + (match mode with + | MDisplay -> + raise Exit (* We don't have to actually call the macro. *) + | MExpr -> + unify mctx mret expr mpos; + | MBuild -> + let ctfields = { tpackage = []; tname = "Array"; tparams = [TPType (CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = Some "Field" },null_pos)]; tsub = None } in + let tfields = Typeload.load_instance mctx (ctfields,null_pos) false p in + unify mctx mret tfields mpos + | MMacroType -> + let cttype = { tpackage = ["haxe";"macro"]; tname = "Type"; tparams = []; tsub = None } in + let ttype = Typeload.load_instance mctx (cttype,null_pos) false p in + try + unify_raise mctx mret ttype mpos; + (* TODO: enable this again in the future *) + (* ctx.com.warning "Returning Type from @:genericBuild macros is deprecated, consider returning ComplexType instead" p; *) + with Error (Unify _,_) -> + let cttype = { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = Some ("ComplexType") } in + let ttype = Typeload.load_instance mctx (cttype,null_pos) false p in + unify_raise mctx mret ttype mpos; + ); + (* + if the function's last argument is of Array, split the argument list and use [] for unify_call_args + *) + let el,el2 = match List.rev margs with + | (_,_,TInst({cl_path=([], "Array")},[e])) :: rest when (try Type.type_eq EqStrict e expr; true with Unify_error _ -> false) -> + let rec loop (acc1,acc2) el1 el2 = match el1,el2 with + | [],[] -> + List.rev acc1, List.rev acc2 + | [], e2 :: [] -> + (List.rev ((EArrayDecl [],p) :: acc1), []) + | [], _ -> + (* not enough arguments, will be handled by unify_call_args *) + List.rev acc1, List.rev acc2 + | e1 :: l1, e2 :: [] -> + loop (((EArrayDecl [],p) :: acc1), [e1]) l1 [] + | e1 :: l1, [] -> + loop (acc1, e1 :: acc2) l1 [] + | e1 :: l1, e2 :: l2 -> + loop (e1 :: acc1, acc2) l1 l2 + in + loop ([],[]) el margs + | _ -> + el,[] + in + let todo = ref [] in + let args = + (* + force default parameter types to haxe.macro.Expr, and if success allow to pass any value type since it will be encoded + *) + let eargs = List.map (fun (n,o,t) -> + try unify_raise mctx t expr p; (n, o, t_dynamic), MAExpr + with Error (Unify _,_) -> match follow t with + | TFun _ -> + (n,o,t_dynamic), MAFunction + | _ -> + (n,o,t), MAOther + ) margs in + (* + this is quite tricky here : we want to use unify_call_args which will type our AST expr + but we want to be able to get it back after it's been padded with nulls + *) + let index = ref (-1) in + let constants = List.map (fun e -> + let p = snd e in + let e = (try + (match Codegen.type_constant_value ctx.com e with + | { eexpr = TConst (TString _); epos = p } when Lexer.is_fmt_string p -> + Lexer.remove_fmt_string p; + todo := (fun() -> Lexer.add_fmt_string p) :: !todo; + | _ -> ()); + e + with Error (Custom _,_) -> + (* if it's not a constant, let's make something that is typed as haxe.macro.Expr - for nice error reporting *) + (EBlock [ + (EVars [("__tmp",null_pos),Some (CTPath ctexpr,p),Some (EConst (Ident "null"),p)],p); + (EConst (Ident "__tmp"),p); + ],p) + ) in + (* let's track the index by doing [e][index] (we will keep the expression type this way) *) + incr index; + (EArray ((EArrayDecl [e],p),(EConst (Int (string_of_int (!index))),p)),p) + ) el in + let elt, _ = unify_call_args mctx constants (List.map fst eargs) t_dynamic p false false in + List.iter (fun f -> f()) (!todo); + List.map2 (fun (_,mct) e -> + let e, et = (match e.eexpr with + (* get back our index and real expression *) + | TArray ({ eexpr = TArrayDecl [e] }, { eexpr = TConst (TInt index) }) -> List.nth el (Int32.to_int index), e + (* added by unify_call_args *) + | TConst TNull -> (EConst (Ident "null"),e.epos), e + | _ -> assert false + ) in + let ictx = Interp.get_ctx() in + match mct with + | MAExpr -> + Interp.encode_expr e + | MAFunction -> + let e = ictx.Interp.curapi.MacroApi.type_macro_expr e in + begin match Interp.eval_expr ictx e with + | Some v -> v + | None -> Interp.vnull + end + | MAOther -> match Interp.eval_expr ictx et with + | None -> assert false + | Some v -> v + ) eargs elt + in + let args = match el2 with + | [] -> args + | _ -> (match List.rev args with _::args -> List.rev args | [] -> []) @ [Interp.enc_array (List.map Interp.encode_expr el2)] + in + let call() = + match call_macro args with + | None -> None + | Some v -> + try + Some (match mode with + | MExpr | MDisplay -> Interp.decode_expr v + | MBuild -> + let fields = if v = Interp.vnull then + (match ctx.g.get_build_infos() with + | None -> assert false + | Some (_,_,fields) -> fields) + else + List.map Interp.decode_field (Interp.dec_array v) + in + (EVars [("fields",null_pos),Some (CTAnonymous fields,p),None],p) + | MMacroType -> + let t = if v = Interp.vnull then + mk_mono() + else try + let ct = Interp.decode_ctype v in + Typeload.load_complex_type ctx false p ct; + with MacroApi.Invalid_expr -> + Interp.decode_type v + in + ctx.ret <- t; + (EBlock [],p) + ) + with MacroApi.Invalid_expr -> + if v = Interp.vnull then + error "Unexpected null value returned from macro" p + else + error "The macro didn't return a valid result" p + in + let e = (if ctx.in_macro then begin + (* + this is super-tricky : we can't evaluate a macro inside a macro because we might trigger some cycles. + So instead, we generate a haxe.macro.Context.delayedCalled(i) expression that will only evaluate the + macro if/when it is called. + + The tricky part is that the whole delayed-evaluation process has to use the same contextual informations + as if it was evaluated now. + *) + let ctx = { + ctx with locals = ctx.locals; + } in + let pos = DynArray.length mctx.g.delayed_macros in + DynArray.add mctx.g.delayed_macros (fun() -> + delayed_macro_result := (fun() -> + let mint = Interp.get_ctx() in + match call() with + | None -> (fun() -> raise MacroApi.Abort) + | Some e -> Interp.eval_delayed mint (type_expr ctx e Value) + ); + ); + ctx.m.curmod.m_extra.m_time <- -1.; (* disable caching for modules having macro-in-macro *) + if Common.defined ctx.com Define.MacroDebug then + ctx.com.warning "Macro-in-macro call detected" p; + let e = (EConst (Ident "$__delayed_call__"),p) in + Some (EUntyped (ECall (e,[EConst (Int (string_of_int pos)),p]),p),p) + end else + call() + ) in + e + +let call_macro ctx path meth args p = + let mctx, (margs,_,mclass,mfield), call = load_macro ctx false path meth p in + let el, _ = unify_call_args mctx args margs t_dynamic p false false in + call (List.map (fun e -> try Interp.make_const e with Exit -> error "Parameter should be a constant" e.epos) el) + +let call_init_macro ctx e = + let p = { pfile = "--macro"; pmin = 0; pmax = 0 } in + let e = try + Parser.parse_expr_string ctx.com e p error false + with err -> + display_error ctx ("Could not parse `" ^ e ^ "`") p; + raise err + in + match fst e with + | ECall (e,args) -> + let rec loop e = + match fst e with + | EField (e,f) -> f :: loop e + | EConst (Ident i) -> [i] + | _ -> error "Invalid macro call" p + in + let path, meth = (match loop e with + | [meth] -> (["haxe";"macro"],"Compiler"), meth + | [meth;"server"] -> (["haxe";"macro"],"CompilationServer"), meth + | meth :: cl :: path -> (List.rev path,cl), meth + | _ -> error "Invalid macro call" p) in + ignore(call_macro ctx path meth args p); + | _ -> + error "Invalid macro call" p + +let interpret ctx = + let mctx = Interp.create ctx.com (make_macro_api ctx null_pos) in + Interp.add_types mctx ctx.com.types (fun t -> ()); + match ctx.com.main with + | None -> () + | Some e -> ignore(Interp.eval_expr mctx e) + +let setup() = + Interp.setup Interp.macro_api + +;; +load_macro_ref := load_macro; diff --git a/src/main.ml b/src/main.ml new file mode 100644 index 00000000..5fc1140e --- /dev/null +++ b/src/main.ml @@ -0,0 +1,963 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +(* + Conventions: + - e: expression (typed or untyped) + - c: class + - en: enum + - td: typedef (tdef) + - a: abstract + - an: anon + - tf: tfunc + - cf: class_field + - ef: enum_field + - t: type (t) + - ct: complex_type + - v: local variable (tvar) + - m: module (module_def) + - mt: module_type + - p: pos + + "param" refers to type parameters + "arg" refers to function arguments + leading s_ means function returns string + trailing l means list (but we also use natural plurals such as "metas") + semantic suffixes may be used freely (e.g. e1, e_if, e') +*) + +open Printf +open Genswf +open Common +open Common.DisplayMode +open Type +open Server +open Globals + +exception Abort + +let executable_path() = + Extc.executable_path() + +let format msg p = + if p = null_pos then + msg + else begin + let error_printer file line = sprintf "%s:%d:" file line in + let epos = Lexer.get_error_pos error_printer p in + let msg = String.concat ("\n" ^ epos ^ " : ") (ExtString.String.nsplit msg "\n") in + sprintf "%s : %s" epos msg + end + +let message ctx msg p = + ctx.messages <- format msg p :: ctx.messages + +let deprecated = [] + +let limit_string s offset = + let rest = 80 - offset in + let words = ExtString.String.nsplit s " " in + let rec loop i words = match words with + | word :: words -> + if String.length word + i + 1 > rest then (Printf.sprintf "\n%*s" offset "") :: word :: loop (String.length word) words + else (if i = 0 then "" else " ") :: word :: loop (i + 1 + String.length word) words + | [] -> + [] + in + String.concat "" (loop 0 words) + +let error ctx msg p = + let msg = try List.assoc msg deprecated with Not_found -> msg in + message ctx msg p; + ctx.has_error <- true + +let reserved_flags = [ + "cross";"js";"lua";"neko";"flash";"php";"cpp";"cs";"java";"python"; + "as3";"swc";"macro";"sys" + ] + +let delete_file f = try Sys.remove f with _ -> () + +let expand_env ?(h=None) path = + let r = Str.regexp "%\\([A-Za-z0-9_]+\\)%" in + Str.global_substitute r (fun s -> + let key = Str.matched_group 1 s in + try + Sys.getenv key + with Not_found -> try + match h with + | None -> raise Not_found + | Some h -> Hashtbl.find h key + with Not_found -> + "%" ^ key ^ "%" + ) path + +let add_libs com libs = + let call_haxelib() = + let t = Common.timer ["haxelib"] in + let cmd = "haxelib path " ^ String.concat " " libs in + let pin, pout, perr = Unix.open_process_full cmd (Unix.environment()) in + let lines = Std.input_list pin in + let err = Std.input_list perr in + let ret = Unix.close_process_full (pin,pout,perr) in + if ret <> Unix.WEXITED 0 then failwith (match lines, err with + | [], [] -> "Failed to call haxelib (command not found ?)" + | [], [s] when ExtString.String.ends_with (ExtString.String.strip s) "Module not found : path" -> "The haxelib command has been strip'ed, please install it again" + | _ -> String.concat "\n" (lines@err)); + t(); + lines + in + match libs with + | [] -> [] + | _ -> + let lines = match CompilationServer.get() with + | Some cs -> + (try + (* if we are compiling, really call haxelib since library path might have changed *) + if not com.display.dms_display then raise Not_found; + CompilationServer.find_haxelib cs libs + with Not_found -> + let lines = call_haxelib() in + CompilationServer.cache_haxelib cs libs lines; + lines) + | _ -> call_haxelib() + in + let extra_args = ref [] in + let lines = List.fold_left (fun acc l -> + let l = ExtString.String.strip l in + if l = "" then acc else + if l.[0] <> '-' then l :: acc else + match (try ExtString.String.split l " " with _ -> l, "") with + | ("-L",dir) -> + com.neko_libs <- String.sub l 3 (String.length l - 3) :: com.neko_libs; + acc + | param, value -> + extra_args := param :: !extra_args; + if value <> "" then extra_args := value :: !extra_args; + acc + ) [] lines in + com.class_path <- lines @ com.class_path; + List.rev !extra_args + +let run_command ctx cmd = + let h = Hashtbl.create 0 in + Hashtbl.add h "__file__" ctx.com.file; + Hashtbl.add h "__platform__" (platform_name ctx.com.platform); + let t = Common.timer ["command"] in + let cmd = expand_env ~h:(Some h) cmd in + let len = String.length cmd in + if len > 3 && String.sub cmd 0 3 = "cd " then begin + Sys.chdir (String.sub cmd 3 (len - 3)); + 0 + end else + let binary_string s = + if not Globals.is_windows then s else String.concat "\n" (Str.split (Str.regexp "\r\n") s) + in + let pout, pin, perr = Unix.open_process_full cmd (Unix.environment()) in + let iout = Unix.descr_of_in_channel pout in + let ierr = Unix.descr_of_in_channel perr in + let berr = Buffer.create 0 in + let bout = Buffer.create 0 in + let tmp = String.create 1024 in + let result = ref None in + (* + we need to read available content on process out/err if we want to prevent + the process from blocking when the pipe is full + *) + let is_process_running() = + let pid, r = Unix.waitpid [Unix.WNOHANG] (-1) in + if pid = 0 then + true + else begin + result := Some r; + false; + end + in + let rec loop ins = + let (ch,_,_), timeout = (try Unix.select ins [] [] 0.02, true with _ -> ([],[],[]),false) in + match ch with + | [] -> + (* make sure we read all *) + if timeout && is_process_running() then + loop ins + else begin + Buffer.add_string berr (IO.read_all (IO.input_channel perr)); + Buffer.add_string bout (IO.read_all (IO.input_channel pout)); + end + | s :: _ -> + let n = Unix.read s tmp 0 (String.length tmp) in + if s == iout && n > 0 then + ctx.com.print (String.sub tmp 0 n) + else + Buffer.add_substring (if s == iout then bout else berr) tmp 0 n; + loop (if n = 0 then List.filter ((!=) s) ins else ins) + in + (try loop [iout;ierr] with Unix.Unix_error _ -> ()); + let serr = binary_string (Buffer.contents berr) in + let sout = binary_string (Buffer.contents bout) in + if serr <> "" then ctx.messages <- (if serr.[String.length serr - 1] = '\n' then String.sub serr 0 (String.length serr - 1) else serr) :: ctx.messages; + if sout <> "" then ctx.com.print sout; + let r = (match (try Unix.close_process_full (pout,pin,perr) with Unix.Unix_error (Unix.ECHILD,_,_) -> (match !result with None -> assert false | Some r -> r)) with + | Unix.WEXITED e -> e + | Unix.WSIGNALED s | Unix.WSTOPPED s -> if s = 0 then -1 else s + ) in + t(); + r + +module Initialize = struct + let set_platform com pf file = + if com.platform <> Cross then failwith "Multiple targets"; + Common.init_platform com pf; + com.file <- file; + if (pf = Flash) && file_extension file = "swc" then Common.define com Define.Swc + + let initialize_target ctx com classes = + let add_std dir = + com.class_path <- List.filter (fun s -> not (List.mem s com.std_path)) com.class_path @ List.map (fun p -> p ^ dir ^ "/_std/") com.std_path @ com.std_path + in + match com.platform with + | Cross -> + (* no platform selected *) + set_platform com Cross ""; + "?" + | Flash -> + let rec loop = function + | [] -> () + | (v,_) :: _ when v > com.flash_version -> () + | (v,def) :: l -> + Common.raw_define com ("flash" ^ def); + loop l + in + loop Common.flash_versions; + Common.raw_define com "flash"; + com.package_rules <- PMap.remove "flash" com.package_rules; + add_std "flash"; + "swf" + | Neko -> + add_std "neko"; + "n" + | Js -> + if not (PMap.exists (fst (Define.infos Define.JqueryVer)) com.defines) then + Common.define_value com Define.JqueryVer "11204"; + + let es_version = + try + int_of_string (Common.defined_value com Define.JsEs) + with + | Not_found -> + (Common.define_value com Define.JsEs "5"; 5) + | _ -> + 0 + in + + if es_version < 3 || es_version = 4 then (* we don't support ancient and there's no 4th *) + failwith "Invalid -D js-es value"; + + if es_version >= 5 then Common.raw_define com "js-es5"; (* backward-compatibility *) + + add_std "js"; + "js" + | Lua -> + add_std "lua"; + "lua" + | Php -> + if Common.is_php7 com then + begin + com.package_rules <- PMap.add "php" (Directory "php7") com.package_rules; + com.package_rules <- PMap.add "php7" Forbidden com.package_rules; + add_std "php7" + end + else + add_std "php"; + "php" + | Cpp -> + Common.define_value com Define.HxcppApiLevel "331"; + add_std "cpp"; + if Common.defined com Define.Cppia then + classes := (Path.parse_path "cpp.cppia.HostClasses" ) :: !classes; + "cpp" + | Cs -> + let old_flush = ctx.flush in + ctx.flush <- (fun () -> + com.net_libs <- []; + old_flush() + ); + Gencs.before_generate com; + add_std "cs"; "cs" + | Java -> + let old_flush = ctx.flush in + ctx.flush <- (fun () -> + List.iter (fun (_,_,close,_,_) -> close()) com.java_libs; + com.java_libs <- []; + old_flush() + ); + Genjava.before_generate com; + add_std "java"; "java" + | Python -> + add_std "python"; + "python" + | Hl -> + add_std "hl"; + "hl" +end + +let generate tctx ext xml_out interp swf_header = + let com = tctx.Typecore.com in + (* check file extension. In case of wrong commandline, we don't want + to accidentaly delete a source file. *) + if file_extension com.file = ext then delete_file com.file; + if com.platform = Flash || com.platform = Cpp || com.platform = Hl then List.iter (Codegen.fix_overrides com) com.types; + if Common.defined com Define.Dump then Codegen.Dump.dump_types com; + if Common.defined com Define.DumpDependencies then begin + Codegen.Dump.dump_dependencies com; + if not tctx.Typecore.in_macro then match tctx.Typecore.g.Typecore.macros with + | None -> () + | Some(_,ctx) -> print_endline "generate"; Codegen.Dump.dump_dependencies ~target_override:(Some "macro") ctx.Typecore.com + end; + begin match com.platform with + | Neko | Hl when interp -> () + | Cpp when Common.defined com Define.Cppia -> () + | Cpp | Cs | Java | Php -> Common.mkdir_from_path (com.file ^ "/.") + | _ -> Common.mkdir_from_path com.file + end; + if interp then + MacroContext.interpret tctx + else if com.platform = Cross then + () + else begin + let generate,name = match com.platform with + | Flash when Common.defined com Define.As3 -> + Genas3.generate,"AS3" + | Flash -> + Genswf.generate swf_header,"swf" + | Neko -> + Genneko.generate,"neko" + | Js -> + Genjs.generate,"js" + | Lua -> + Genlua.generate,"lua" + | Php -> + if Common.is_php7 com then + Genphp7.generate,"php" + else + Genphp.generate,"php" + | Cpp -> + Gencpp.generate,"cpp" + | Cs -> + Gencs.generate,"cs" + | Java -> + Genjava.generate,"java" + | Python -> + Genpy.generate,"python" + | Hl -> + Genhl.generate,"hl" + | Cross -> + assert false + in + Common.log com ("Generating " ^ name ^ ": " ^ com.file); + let t = Common.timer ["generate";name] in + generate com; + t() + end + +let get_std_class_paths () = + try + let p = Sys.getenv "HAXE_STD_PATH" in + let rec loop = function + | drive :: path :: l -> + if String.length drive = 1 && ((drive.[0] >= 'a' && drive.[0] <= 'z') || (drive.[0] >= 'A' && drive.[0] <= 'Z')) then + (drive ^ ":" ^ path) :: loop l + else + drive :: loop (path :: l) + | l -> + l + in + let parts = Str.split_delim (Str.regexp "[;:]") p in + "" :: List.map Path.add_trailing_slash (loop parts) + with Not_found -> + if Sys.os_type = "Unix" then + [ + "/usr/lib/haxe/std/"; + "/usr/share/haxe/std/"; + "/usr/local/lib/haxe/std/"; + "/usr/lib/haxe/extraLibs/"; + "/usr/local/lib/haxe/extraLibs/"; + "" + ] + else + let base_path = Path.add_trailing_slash (Path.get_real_path (try executable_path() with _ -> "./")) in + [ + base_path ^ "std/"; + base_path ^ "extraLibs/"; + "" + ] + +let rec process_params create pl = + let each_params = ref [] in + let rec loop acc = function + | [] -> + let ctx = create (!each_params @ (List.rev acc)) in + init ctx; + ctx.flush() + | "--next" :: l when acc = [] -> (* skip empty --next *) + loop [] l + | "--next" :: l -> + let ctx = create (!each_params @ (List.rev acc)) in + ctx.has_next <- true; + init ctx; + ctx.flush(); + loop [] l + | "--each" :: l -> + each_params := List.rev acc; + loop [] l + | "--cwd" :: dir :: l -> + (* we need to change it immediately since it will affect hxml loading *) + (try Unix.chdir dir with _ -> raise (Arg.Bad ("Invalid directory: " ^ dir))); + loop acc l + | "--connect" :: hp :: l -> + (match CompilationServer.get() with + | None -> + let host, port = (try ExtString.String.split hp ":" with _ -> "127.0.0.1", hp) in + do_connect host (try int_of_string port with _ -> raise (Arg.Bad "Invalid port")) ((List.rev acc) @ l) + | Some _ -> + (* already connected : skip *) + loop acc l) + | "--run" :: cl :: args -> + let acc = cl :: "-main" :: "--interp" :: acc in + let ctx = create (!each_params @ (List.rev acc)) in + ctx.com.sys_args <- args; + init ctx; + ctx.flush() + | arg :: l -> + match List.rev (ExtString.String.nsplit arg ".") with + | "hxml" :: _ when (match acc with "-cmd" :: _ -> false | _ -> true) -> + let acc, l = (try acc, parse_hxml arg @ l with Not_found -> (arg ^ " (file not found)") :: acc, l) in + loop acc l + | _ -> loop (arg :: acc) l + in + (* put --display in front if it was last parameter *) + let pl = (match List.rev pl with + | file :: "--display" :: pl when file <> "memory" -> "--display" :: file :: List.rev pl + | "use_rtti_doc" :: "-D" :: file :: "--display" :: pl -> "--display" :: file :: List.rev pl + | _ -> pl + ) in + loop [] pl + +and init ctx = + let usage = Printf.sprintf + "Haxe Compiler %s - (C)2005-2017 Haxe Foundation\n Usage : haxe%s -main [-swf|-js|-neko|-php|-cpp|-cppia|-as3|-cs|-java|-python|-hl|-lua] [options]\n Options :" + Globals.s_version (if Sys.os_type = "Win32" then ".exe" else "") + in + let com = ctx.com in + let classes = ref [([],"Std")] in +try + let xml_out = ref None in + let swf_header = ref None in + let cmds = ref [] in + let config_macros = ref [] in + let cp_libs = ref [] in + let added_libs = Hashtbl.create 0 in + let no_output = ref false in + let did_something = ref false in + let force_typing = ref false in + let pre_compilation = ref [] in + let interp = ref false in + let swf_version = ref false in + let evals = ref [] in + Common.define_value com Define.HaxeVer (float_repres (float_of_int Globals.version /. 1000.)); + Common.raw_define com "haxe3"; + Common.define_value com Define.Dce "std"; + com.warning <- (fun msg p -> message ctx ("Warning : " ^ msg) p); + com.error <- error ctx; + if CompilationServer.runs() then com.run_command <- run_command ctx; + Parser.display_error := (fun e p -> com.error (Parser.error_msg e) p); + Parser.use_doc := !Common.display_default <> DMNone || (CompilationServer.runs()); + com.class_path <- get_std_class_paths (); + com.std_path <- List.filter (fun p -> ExtString.String.ends_with p "std/" || ExtString.String.ends_with p "std\\") com.class_path; + let define f = Arg.Unit (fun () -> Common.define com f) in + let process_ref = ref (fun args -> ()) in + let process_libs() = + let libs = List.filter (fun l -> not (Hashtbl.mem added_libs l)) (List.rev !cp_libs) in + cp_libs := []; + List.iter (fun l -> Hashtbl.add added_libs l ()) libs; + (* immediately process the arguments to insert them at the place -lib was defined *) + match add_libs com libs with + | [] -> () + | args -> (!process_ref) args + in + let arg_delays = ref [] in + let basic_args_spec = [ + ("-cp",Arg.String (fun path -> + process_libs(); + com.class_path <- Path.add_trailing_slash path :: com.class_path + )," : add a directory to find source files"); + ("-js",Arg.String (Initialize.set_platform com Js)," : compile code to JavaScript file"); + ("-lua",Arg.String (Initialize.set_platform com Lua)," : compile code to Lua file"); + ("-swf",Arg.String (Initialize.set_platform com Flash)," : compile code to Flash SWF file"); + ("-as3",Arg.String (fun dir -> + Initialize.set_platform com Flash dir; + Common.define com Define.As3; + Common.define com Define.NoInline; + )," : generate AS3 code into target directory"); + ("-neko",Arg.String (Initialize.set_platform com Neko)," : compile code to Neko Binary"); + ("-php",Arg.String (fun dir -> + classes := (["php"],"Boot") :: !classes; + Initialize.set_platform com Php dir; + )," : generate PHP code into target directory"); + ("-cpp",Arg.String (fun dir -> + Initialize.set_platform com Cpp dir; + )," : generate C++ code into target directory"); + ("-cppia",Arg.String (fun file -> + Initialize.set_platform com Cpp file; + Common.define com Define.Cppia; + )," : generate Cppia code into target file"); + ("-cs",Arg.String (fun dir -> + cp_libs := "hxcs" :: !cp_libs; + Initialize.set_platform com Cs dir; + )," : generate C# code into target directory"); + ("-java",Arg.String (fun dir -> + cp_libs := "hxjava" :: !cp_libs; + Initialize.set_platform com Java dir; + )," : generate Java code into target directory"); + ("-python",Arg.String (fun dir -> + Initialize.set_platform com Python dir; + )," : generate Python code as target file"); + ("-hl",Arg.String (fun file -> + Initialize.set_platform com Hl file; + )," : compile HL code as target file"); + ("-xml",Arg.String (fun file -> + Parser.use_doc := true; + xml_out := Some file + )," : generate XML types description"); + ("-main",Arg.String (fun cl -> + if com.main_class <> None then raise (Arg.Bad "Multiple -main"); + let cpath = Path.parse_type_path cl in + com.main_class <- Some cpath; + classes := cpath :: !classes + )," : select startup class"); + ("-lib",Arg.String (fun l -> + cp_libs := l :: !cp_libs; + Common.raw_define com l; + )," : use a haxelib library"); + ("-D",Arg.String (fun var -> + begin match var with + | "no_copt" | "no-copt" -> com.foptimize <- false; + | "use_rtti_doc" | "use-rtti-doc" -> Parser.use_doc := true; + | _ -> if List.mem var reserved_flags then raise (Arg.Bad (var ^ " is a reserved compiler flag and cannot be defined from command line")); + end; + Common.raw_define com var; + )," : define a conditional compilation flag"); + ("-v",Arg.Unit (fun () -> + com.verbose <- true + ),": turn on verbose mode"); + ("-debug", Arg.Unit (fun() -> + Common.define com Define.Debug; + com.debug <- true; + ), ": add debug information to the compiled code"); + ] in + let adv_args_spec = [ + ("-dce", Arg.String (fun mode -> + (match mode with + | "std" | "full" | "no" -> () + | _ -> raise (Arg.Bad "Invalid DCE mode, expected std | full | no")); + Common.define_value com Define.Dce mode + ),"[std|full|no] : set the dead code elimination mode (default std)"); + ("-swf-version",Arg.Float (fun v -> + if not !swf_version || com.flash_version < v then com.flash_version <- v; + swf_version := true; + )," : change the SWF version"); + ("-swf-header",Arg.String (fun h -> + try + swf_header := Some (match ExtString.String.nsplit h ":" with + | [width; height; fps] -> + (int_of_string width,int_of_string height,float_of_string fps,0xFFFFFF) + | [width; height; fps; color] -> + let color = if ExtString.String.starts_with color "0x" then color else "0x" ^ color in + (int_of_string width, int_of_string height, float_of_string fps, int_of_string color) + | _ -> raise Exit) + with + _ -> raise (Arg.Bad "Invalid SWF header format, expected width:height:fps[:color]") + ),"
: define SWF header (width:height:fps:color)"); + ("-swf-lib",Arg.String (fun file -> + process_libs(); (* linked swf order matters, and lib might reference swf as well *) + Genswf.add_swf_lib com file false + )," : add the SWF library to the compiled SWF"); + ("-swf-lib-extern",Arg.String (fun file -> + Genswf.add_swf_lib com file true + )," : use the SWF library for type checking"); + ("-java-lib",Arg.String (fun file -> + let std = file = "lib/hxjava-std.jar" in + arg_delays := (fun () -> Genjava.add_java_lib com file std) :: !arg_delays; + )," : add an external JAR or class directory library"); + ("-net-lib",Arg.String (fun file -> + let file, is_std = match ExtString.String.nsplit file "@" with + | [file] -> + file,false + | [file;"std"] -> + file,true + | _ -> raise Exit + in + arg_delays := (fun () -> Gencs.add_net_lib com file is_std) :: !arg_delays; + ),"[@std] : add an external .NET DLL file"); + ("-net-std",Arg.String (fun file -> + Gencs.add_net_std com file + )," : add a root std .NET DLL search path"); + ("-c-arg",Arg.String (fun arg -> + com.c_args <- arg :: com.c_args + )," : pass option to the native Java/C# compiler"); + ("-x", Arg.String (fun file -> + let neko_file = file ^ ".n" in + Initialize.set_platform com Neko neko_file; + if com.main_class = None then begin + let cpath = Path.parse_type_path file in + com.main_class <- Some cpath; + classes := cpath :: !classes + end; + cmds := ("neko " ^ neko_file) :: !cmds; + )," : shortcut for compiling and executing a neko file"); + ("-resource",Arg.String (fun res -> + let file, name = (match ExtString.String.nsplit res "@" with + | [file; name] -> file, name + | [file] -> file, file + | _ -> raise (Arg.Bad "Invalid Resource format, expected file@name") + ) in + let file = (try Common.find_file com file with Not_found -> file) in + let data = (try + let s = Std.input_file ~bin:true file in + if String.length s > 12000000 then raise Exit; + s; + with + | Sys_error _ -> failwith ("Resource file not found : " ^ file) + | _ -> failwith ("Resource '" ^ file ^ "' excess the maximum size of 12MB") + ) in + if Hashtbl.mem com.resources name then failwith ("Duplicate resource name " ^ name); + Hashtbl.add com.resources name data + ),"[@name] : add a named resource file"); + ("-prompt", Arg.Unit (fun() -> prompt := true),": prompt on error"); + ("-cmd", Arg.String (fun cmd -> + cmds := DisplayOutput.unquote cmd :: !cmds + ),": run the specified command after successful compilation"); + ("--flash-strict", define Define.FlashStrict, ": more type strict flash API"); + ("--no-traces", define Define.NoTraces, ": don't compile trace calls in the program"); + ("--gen-hx-classes", Arg.Unit (fun() -> + force_typing := true; + pre_compilation := (fun() -> + List.iter (fun (_,_,extract) -> + Hashtbl.iter (fun n _ -> classes := n :: !classes) (extract()) + ) com.swf_libs; + List.iter (fun (_,std,_,all_files,_) -> + if not std then + List.iter (fun path -> if path <> (["java";"lang"],"String") then classes := path :: !classes) (all_files()) + ) com.java_libs; + List.iter (fun (_,std,all_files,_) -> + if not std then + List.iter (fun path -> classes := path :: !classes) (all_files()) + ) com.net_libs; + ) :: !pre_compilation; + xml_out := Some "hx" + ),": generate hx headers for all input classes"); + ("--next", Arg.Unit (fun() -> assert false), ": separate several haxe compilations"); + ("--each", Arg.Unit (fun() -> assert false), ": append preceding parameters to all haxe compilations separated by --next"); + ("--display", Arg.String (fun file_pos -> + DisplayOutput.handle_display_argument com file_pos pre_compilation did_something; + ),": display code tips"); + ("--no-output", Arg.Unit (fun() -> no_output := true),": compiles but does not generate any file"); + ("--times", Arg.Unit (fun() -> measure_times := true),": measure compilation times"); + ("--no-inline", define Define.NoInline, ": disable inlining"); + ("--no-opt", Arg.Unit (fun() -> + com.foptimize <- false; + Common.define com Define.NoOpt; + ), ": disable code optimizations"); + ("--php-front",Arg.String (fun f -> + if com.php_front <> None then raise (Arg.Bad "Multiple --php-front"); + com.php_front <- Some f; + )," : select the name for the php front file"); + ("--php-lib",Arg.String (fun f -> + if com.php_lib <> None then raise (Arg.Bad "Multiple --php-lib"); + com.php_lib <- Some f; + )," : select the name for the php lib folder"); + ("--php-prefix", Arg.String (fun f -> + if com.php_prefix <> None then raise (Arg.Bad "Multiple --php-prefix"); + com.php_prefix <- Some f; + Common.define com Define.PhpPrefix; + )," : prefix all classes with given name"); + ("--remap", Arg.String (fun s -> + let pack, target = (try ExtString.String.split s ":" with _ -> raise (Arg.Bad "Invalid remap format, expected source:target")) in + com.package_rules <- PMap.add pack (Remap target) com.package_rules; + )," : remap a package to another one"); + ("--interp", Arg.Unit (fun() -> + Common.define com Define.Interp; + Initialize.set_platform com (!Globals.macro_platform) ""; + interp := true; + ),": interpret the program using internal macro system"); + ("--macro", Arg.String (fun e -> + force_typing := true; + config_macros := e :: !config_macros + )," : call the given macro before typing anything else"); + ("--eval", Arg.String (fun s -> + force_typing := true; + evals := s :: !evals; + ), " : evaluates argument as Haxe module code"); + ("--wait", Arg.String (fun hp -> + let accept = match hp with + | "stdio" -> + Server.init_wait_stdio() + | _ -> + let host, port = (try ExtString.String.split hp ":" with _ -> "127.0.0.1", hp) in + let port = try int_of_string port with _ -> raise (Arg.Bad "Invalid port") in + init_wait_socket com.verbose host port + in + wait_loop process_params com.verbose accept + ),"<[host:]port> : wait on the given port for commands to run)"); + ("--connect",Arg.String (fun _ -> + assert false + ),"<[host:]port> : connect on the given port and run commands there)"); + ("--cwd", Arg.String (fun dir -> + assert false + )," : set current working directory"); + ("-version",Arg.Unit (fun() -> + message ctx Globals.s_version null_pos; + did_something := true; + ),": print version and exit"); + ("--help-defines", Arg.Unit (fun() -> + let m = ref 0 in + let rec loop i = + let d = Obj.magic i in + if d <> Define.Last then begin + let t, doc = Define.infos d in + if String.length t > !m then m := String.length t; + ((String.concat "-" (ExtString.String.nsplit t "_")),doc) :: (loop (i + 1)) + end else + [] + in + let all = List.sort (fun (s1,_) (s2,_) -> String.compare s1 s2) (loop 0) in + let all = List.map (fun (n,doc) -> Printf.sprintf " %-*s: %s" !m n (limit_string doc (!m + 3))) all in + List.iter (fun msg -> ctx.com.print (msg ^ "\n")) all; + did_something := true + ),": print help for all compiler specific defines"); + ("--help-metas", Arg.Unit (fun() -> + let all,max_length = Meta.get_documentation_list() in + let all = List.map (fun (n,doc) -> Printf.sprintf " %-*s: %s" max_length n (limit_string doc (max_length + 3))) all in + List.iter (fun msg -> ctx.com.print (msg ^ "\n")) all; + did_something := true + ),": print help for all compiler metadatas"); + ] in + let args_callback cl = + let path,name = Path.parse_path cl in + if Path.starts_uppercase name then + classes := (path,name) :: !classes + else begin + force_typing := true; + config_macros := (Printf.sprintf "include('%s', true, null, null, true)" cl) :: !config_macros; + end + in + let all_args_spec = basic_args_spec @ adv_args_spec in + let process args = + let current = ref 0 in + (try + Arg.parse_argv ~current (Array.of_list ("" :: List.map expand_env args)) all_args_spec args_callback usage; + List.iter (fun fn -> fn()) !arg_delays + with (Arg.Bad msg) as exc -> + let r = Str.regexp "unknown option `\\([-A-Za-z]+\\)'" in + try + ignore(Str.search_forward r msg 0); + let s = Str.matched_group 1 msg in + let sl = List.map (fun (s,_,_) -> s) all_args_spec in + let msg = StringError.string_error_raise s sl (Printf.sprintf "Invalid command: %s" s) in + raise (Arg.Bad msg) + with Not_found -> + raise exc); + arg_delays := [] + in + process_ref := process; + process ctx.com.args; + process_libs(); + if com.display.dms_display then begin + com.warning <- if com.display.dms_error_policy = EPCollect then (fun s p -> add_diagnostics_message com s p DisplayTypes.DiagnosticsSeverity.Warning) else message ctx; + com.error <- error ctx; + end; + DisplayOutput.process_display_file com classes; + let ext = Initialize.initialize_target ctx com classes in + (* if we are at the last compilation step, allow all packages accesses - in case of macros or opening another project file *) + if com.display.dms_display then begin + if not ctx.has_next then com.package_rules <- PMap.foldi (fun p r acc -> match r with Forbidden -> acc | _ -> PMap.add p r acc) com.package_rules PMap.empty; + end; + com.config <- get_config com; (* make sure to adapt all flags changes defined after platform *) + List.iter (fun f -> f()) (List.rev (!pre_compilation)); + if !classes = [([],"Std")] && not !force_typing then begin + let help_spec = basic_args_spec @ [ + ("-help", Arg.Unit (fun () -> ()),": show extended help information"); + ("--help", Arg.Unit (fun () -> ()),": show extended help information"); + ("--help-defines", Arg.Unit (fun () -> ()),": print help for all compiler specific defines"); + ("--help-metas", Arg.Unit (fun () -> ()),": print help for all compiler metadatas"); + ("", Arg.Unit (fun () -> ()),": compile the module specified by dot-path"); + ] in + if !cmds = [] && not !did_something then Arg.usage help_spec usage; + end else begin + ctx.setup(); + Common.log com ("Classpath : " ^ (String.concat ";" com.class_path)); + Common.log com ("Defines : " ^ (String.concat ";" (PMap.foldi (fun k v acc -> (match v with "1" -> k | _ -> k ^ "=" ^ v) :: acc) com.defines []))); + let t = Common.timer ["typing"] in + Typecore.type_expr_ref := (fun ctx e with_type -> Typer.type_expr ctx e with_type); + let tctx = Typer.create com in + List.iter (MacroContext.call_init_macro tctx) (List.rev !config_macros); + List.iter (Typer.eval tctx) !evals; + List.iter (fun cpath -> ignore(tctx.Typecore.g.Typecore.do_load_module tctx cpath null_pos)) (List.rev !classes); + Typer.finalize tctx; + t(); + if not ctx.com.display.dms_display && ctx.has_error then raise Abort; + if ctx.com.display.dms_exit_during_typing then begin + if ctx.has_next || ctx.has_error then raise Abort; + failwith "No completion point was found"; + end; + let t = Common.timer ["filters"] in + let main, types, modules = Typer.generate tctx in + com.main <- main; + com.types <- types; + com.modules <- modules; + DisplayOutput.process_global_display_mode com tctx; + if not (Common.defined com Define.NoDeprecationWarnings) then + Display.DeprecationCheck.run com; + Filters.run com tctx main; + t(); + if ctx.has_error then raise Abort; + (match !xml_out with + | None -> () + | Some "hx" -> + Genxml.generate_hx com + | Some file -> + Common.log com ("Generating xml : " ^ file); + Common.mkdir_from_path file; + Genxml.generate com file); + if not !no_output then generate tctx ext !xml_out !interp !swf_header; + end; + Sys.catch_break false; + List.iter (fun f -> f()) (List.rev com.callbacks.after_generation); + if not !no_output then begin + List.iter (fun c -> + let r = run_command ctx c in + if r <> 0 then failwith ("Command failed with error " ^ string_of_int r) + ) (List.rev !cmds) + end +with + | Abort -> + () + | Error.Fatal_error (m,p) -> + error ctx m p + | Common.Abort (m,p) -> + error ctx m p + | Lexer.Error (m,p) -> + error ctx (Lexer.error_msg m) p + | Parser.Error (m,p) -> + error ctx (Parser.error_msg m) p + | Typecore.Forbid_package ((pack,m,p),pl,pf) -> + if !Common.display_default <> DMNone && ctx.has_next then begin + ctx.has_error <- false; + ctx.messages <- []; + end else begin + error ctx (Printf.sprintf "You cannot access the %s package while %s (for %s)" pack (if pf = "macro" then "in a macro" else "targeting " ^ pf) (s_type_path m) ) p; + List.iter (error ctx " referenced here") (List.rev pl); + end + | Error.Error (m,p) -> + error ctx (Error.error_msg m) p + | Interp.Error (msg,p :: l) | Hlmacro.Error (msg,p :: l) -> + message ctx msg p; + List.iter (message ctx "Called from") l; + error ctx "Aborted" null_pos; + | Typeload.Generic_Exception(m,p) -> + error ctx m p + | Arg.Bad msg -> + error ctx ("Error: " ^ msg) null_pos + | Failure msg when not (is_debug_run()) -> + error ctx ("Error: " ^ msg) null_pos + | Arg.Help msg -> + message ctx msg null_pos + | Display.DisplayPackage pack -> + raise (DisplayOutput.Completion (String.concat "." pack)) + | Display.DisplayFields fields -> + let fields = List.map ( + fun (name,kind,doc) -> name, kind, (Option.default "" doc) + ) fields in + let fields = + if !measure_times then begin + close_times(); + (List.map (fun (name,value) -> ("@TIME " ^ name, Display.FKTimer value, "")) (DisplayOutput.get_timer_fields !start_time)) @ fields + end else + fields + in + raise (DisplayOutput.Completion (DisplayOutput.print_fields fields)) + | Display.DisplayType (t,p,doc) -> + let doc = match doc with Some _ -> doc | None -> DisplayOutput.find_doc t in + raise (DisplayOutput.Completion (DisplayOutput.print_type t p doc)) + | Display.DisplaySignatures(tl,display_arg) -> + if ctx.com.display.dms_kind = DMSignature then + raise (DisplayOutput.Completion (DisplayOutput.print_signature tl display_arg)) + else + raise (DisplayOutput.Completion (DisplayOutput.print_signatures tl)) + | Display.DisplayPosition pl -> + raise (DisplayOutput.Completion (DisplayOutput.print_positions pl)) + | Display.DisplayToplevel il -> + let il = + if !measure_times then begin + close_times(); + (List.map (fun (name,value) -> IdentifierType.ITTimer ("@TIME " ^ name ^ ": " ^ value)) (DisplayOutput.get_timer_fields !start_time)) @ il + end else + il + in + raise (DisplayOutput.Completion (DisplayOutput.print_toplevel il)) + | Parser.TypePath (p,c,is_import) -> + let fields = + try begin match c with + | None -> + DisplayOutput.TypePathHandler.complete_type_path com p + | Some (c,cur_package) -> + DisplayOutput.TypePathHandler.complete_type_path_inner com p c cur_package is_import + end with Common.Abort(msg,p) -> + error ctx msg p; + None + in + Option.may (fun fields -> raise (DisplayOutput.Completion (DisplayOutput.print_fields fields))) fields + | Display.ModuleSymbols s | Display.Diagnostics s | Display.Statistics s | Display.Metadata s -> + raise (DisplayOutput.Completion s) + | Interp.Sys_exit i | Hlinterp.Sys_exit i -> + ctx.flush(); + exit i + | e when (try Sys.getenv "OCAMLRUNPARAM" <> "b" || CompilationServer.runs() with _ -> true) && not (is_debug_run()) -> + error ctx (Printexc.to_string e) null_pos + +;; +let other = Common.timer ["other"] in +Sys.catch_break true; +MacroContext.setup(); +let args = List.tl (Array.to_list Sys.argv) in +(try + let server = Sys.getenv "HAXE_COMPILATION_SERVER" in + let host, port = (try ExtString.String.split server ":" with _ -> "127.0.0.1", server) in + do_connect host (try int_of_string port with _ -> failwith "Invalid HAXE_COMPILATION_SERVER port") args +with Not_found -> try + process_params create_context args +with DisplayOutput.Completion c -> + prerr_endline c; + exit 0 +| Arg.Bad msg -> + prerr_endline ("Error: " ^ msg); + exit 1 +); +other(); +if !measure_times then report_times prerr_endline diff --git a/src/optimization/analyzer.ml b/src/optimization/analyzer.ml new file mode 100644 index 00000000..827abcea --- /dev/null +++ b/src/optimization/analyzer.ml @@ -0,0 +1,1060 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Ast +open Type +open Common +open AnalyzerTexpr +open AnalyzerTypes +open OptimizerTexpr +open Globals + +(* File organization: + * analyzer.ml: The controlling file with all graph-based optimizations + * analyzerConfig.ml: The general configuration which is used in multiple modules + * analyzerTexpr.ml: Transformations and query functions on texpr, independent of graph/blocks + * analyzerTexprTransformer.ml: Translation of texpr to graph/blocks + * analyzerTypes.ml: Definition of graph, block and the analyzer context +*) + +(* + Ssa changes the expressions of a graph to conform to SSA rules. All variables are assigned to only once + and SSA-phi expressions are created where necessary. + + The first pass inserts SSA-phi expressions for each variable in the dominance frontier of all its defining + blocks. + + The second pass then creates and renames variables to ensure SSA property. +*) +module Ssa = struct + open BasicBlock + open Graph + + let add_phi g bb v = + let p = bb.bb_pos in + let ev = mk (TLocal v) v.v_type p in + let el = List.map (fun _ -> ev) bb.bb_incoming in + let e_phi = mk (TConst (TString "phi")) t_dynamic p in + let ec = mk (TCall(e_phi,el)) t_dynamic p in + let e = mk (TBinop(OpAssign,ev,ec)) t_dynamic p in + DynArray.add bb.bb_phi e + + let insert_phi ctx = + DynArray.iter (fun vi -> + let v = vi.vi_var in + if vi.vi_bb_declare == ctx.graph.g_unreachable then + () + else begin + let done_list = Hashtbl.create 0 in + let w = ref vi.vi_writes in + while !w <> [] do + let x = List.hd !w in + w := List.tl !w; + List.iter (fun y -> + if not (Hashtbl.mem done_list y.bb_id) then begin + Hashtbl.add done_list y.bb_id true; + if in_scope y vi.vi_bb_declare then begin + add_phi ctx.graph y v; + if not (List.memq y vi.vi_writes) then + w := y :: !w + end + end + ) x.bb_df; + done + end + ) ctx.graph.g_var_infos + + let set_reaching_def g v vo = + let vi = get_var_info g v in + vi.vi_reaching_def <- vo + + let get_reaching_def g v = + (get_var_info g v).vi_reaching_def + + let rec dominates bb_dom bb = + bb_dom == bb || bb.bb_dominator == bb_dom || (bb.bb_dominator != bb && dominates bb_dom bb.bb_dominator) + + let dominates ctx r bb = + let l = (get_var_info ctx.graph r).vi_writes in + List.exists (fun bb' -> dominates bb' bb) l + + let update_reaching_def ctx v bb = + let rec loop r = match r with + | Some r -> + if dominates ctx r bb then + Some r + else + loop (get_reaching_def ctx.graph r) + | None -> + None + in + let v' = (loop (get_reaching_def ctx.graph v)) in + set_reaching_def ctx.graph v v' + + let local ctx e v bb = + update_reaching_def ctx v bb; + match get_reaching_def ctx.graph v with + | Some v' -> v' + | None -> v + + let update_phi ctx edge = + let bb = edge.cfg_to in + let rec loop i e = + match e.eexpr with + | TBinop(OpAssign,({eexpr = TLocal v0} as e1), ({eexpr = TCall({eexpr = TConst (TString "phi")} as ephi,el)} as ecall)) -> + let el = List.map2 (fun e inc -> + let bb_pred = inc.cfg_from in + if bb_pred != edge.cfg_from then + e + else match e.eexpr with + | TLocal v -> + let v' = local ctx e v edge.cfg_from in + add_ssa_edge ctx.graph v' bb true i; + {e with eexpr = TLocal v'} + | _ -> + assert false + ) el edge.cfg_to.bb_incoming in + let ephi = {ecall with eexpr = TCall(ephi,el)} in + set_var_value ctx.graph v0 bb true i; + {e with eexpr = TBinop(OpAssign,e1,ephi)} + | _ -> + Type.map_expr (loop i) e + in + dynarray_mapi loop bb.bb_phi + + let rec rename_in_block ctx bb = + let write_var v is_phi i = + update_reaching_def ctx v bb; + let v' = alloc_var (v.v_name) v.v_type v.v_pos in + declare_var ctx.graph v' bb; + v'.v_meta <- v.v_meta; + v'.v_capture <- v.v_capture; + add_var_def ctx.graph bb v'; + set_reaching_def ctx.graph v' (get_reaching_def ctx.graph v); + set_reaching_def ctx.graph v (Some v'); + set_var_value ctx.graph v' bb is_phi i; + add_var_origin ctx.graph v' v; + v' + in + let rec loop is_phi i e = match e.eexpr with + | TLocal v when not (is_unbound v) -> + let v' = local ctx e v bb in + add_ssa_edge ctx.graph v' bb is_phi i; + {e with eexpr = TLocal v'} + | TVar(v,Some e1) when not (is_unbound v) -> + let e1 = (loop is_phi i) e1 in + let v' = write_var v is_phi i in + {e with eexpr = TVar(v',Some e1)} + | TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) when not (is_unbound v) -> + let e2 = (loop is_phi i) e2 in + let v' = write_var v is_phi i in + {e with eexpr = TBinop(OpAssign,{e1 with eexpr = TLocal v'},e2)}; + | TCall({eexpr = TConst (TString "phi")},_) -> + e + | _ -> + Type.map_expr (loop is_phi i) e + in + dynarray_mapi (loop true) bb.bb_phi; + dynarray_mapi (loop false) bb.bb_el; + List.iter (update_phi ctx) bb.bb_outgoing; + List.iter (rename_in_block ctx) bb.bb_dominated + + let apply ctx = + Graph.infer_dominance_frontier ctx.graph; + insert_phi ctx; + rename_in_block ctx ctx.graph.g_root +end + +module type DataFlowApi = sig + type t + val flag : BasicBlock.cfg_edge_Flag + val transfer : analyzer_context -> BasicBlock.t -> texpr -> t (* The transfer function *) + val equals : t -> t -> bool (* The equality function *) + val bottom : t (* The bottom element of the lattice *) + val top : t (* The top element of the lattice *) + val get_cell : int -> t (* Lattice cell getter *) + val set_cell : int -> t -> unit (* Lattice cell setter *) + val init : analyzer_context -> unit (* The initialization function which is called at the start *) + val commit : analyzer_context -> unit (* The commit function which is called at the end *) + val conditional : bool (* Whether or not conditional branches are checked *) +end + +(* + DataFlow provides a framework for data flow analysis. It follows CFG edges from the root of the graph + and visits the expressions and SSA-phi expressions of blocks on its way. + + If such an expression assigns to a variable (TVar or TBinop(OpAsssign)), all uses of that variable are + checked by following the variable's SSA edges. + + A conditional branch edge (CFGCondBranch and CFGCondElse) is only followed if the available information + suggests that it might be executable. This causes information from dead branches to not be taken into + account. + + For SSA-phi nodes, only those incoming edges which are considered to be executable are processed. + + The algorithm continues until no further changes occur. +*) +module DataFlow (M : DataFlowApi) = struct + open Graph + open BasicBlock + + let get_ssa_edges_from g v = + (get_var_info g v).vi_ssa_edges + + let run ctx = + let g = ctx.graph in + let ssa_work_list = ref [] in + let cfg_work_list = ref g.g_root.bb_outgoing in + let add_ssa_edge edge = + ssa_work_list := edge :: !ssa_work_list + in + let add_cfg_edge edge = + cfg_work_list := edge :: !cfg_work_list + in + let visit_phi bb v el = + let el = List.fold_left2 (fun acc e edge -> + if has_flag edge M.flag then e :: acc else acc + ) [] el bb.bb_incoming in + let el = List.map (fun e -> M.transfer ctx bb e) el in + match el with + | e1 :: el when List.for_all (M.equals e1) el -> + e1; + | _ -> + M.bottom; + in + let set_lattice_cell v e = + let e' = M.get_cell v.v_id in + M.set_cell v.v_id e; + if not (M.equals e e') then + List.iter (fun edge -> add_ssa_edge edge) (get_ssa_edges_from g v); + in + let visit_assignment bb v e = + match e.eexpr with + | TCall({eexpr = TConst (TString "phi")},el) -> + set_lattice_cell v (visit_phi bb v el) + | _ -> + if List.exists (fun edge -> has_flag edge M.flag) bb.bb_incoming then + set_lattice_cell v (M.transfer ctx bb e) + in + let visit_expression bb e = + match e.eexpr with + | TBinop(OpAssign,{eexpr = TLocal v},e2) | TVar(v,Some e2) -> + visit_assignment bb v e2; + false + | TMeta((Meta.Custom ":cond-branch",_,_),e1) when M.conditional -> + let e1 = M.transfer ctx bb e1 in + let edges = if e1 == M.bottom || e1 == M.top then + bb.bb_outgoing + else begin + let rec loop yes maybe also edges = match edges with + | edge :: edges -> + begin match edge.cfg_kind with + | CFGCondBranch e -> + let e = M.transfer ctx bb e in + if M.equals e e1 then + loop (edge :: yes) maybe also edges + else + loop yes maybe also edges + | CFGCondElse -> + loop yes (edge :: maybe) also edges + | CFGGoto | CFGFunction | CFGMaybeThrow -> + loop yes maybe (edge :: also) edges + end + | [] -> + yes,maybe,also + in + let yes,maybe,also = loop [] [] [] bb.bb_outgoing in + match yes,maybe with + | [],[] -> bb.bb_outgoing + | [],maybe -> maybe @ also + | yes,_ -> yes @ also + end in + List.iter add_cfg_edge edges; + true + | _ -> + false + in + let visit_expressions bb = + let b = DynArray.fold_left (fun b e -> + visit_expression bb e || b + ) false bb.bb_el in + if not b then List.iter add_cfg_edge bb.bb_outgoing + in + let visit_phis bb = + DynArray.iter (fun e -> + match e.eexpr with + | TBinop(OpAssign,{eexpr = TLocal v},{eexpr = TCall({eexpr = TConst (TString "phi")},el)}) -> + set_lattice_cell v (visit_phi bb v el) + | _ -> assert false + ) bb.bb_phi + in + let rec loop () = match !cfg_work_list,!ssa_work_list with + | edge :: edges,_ -> + cfg_work_list := edges; + if not (has_flag edge M.flag) then begin + edge.cfg_flags <- M.flag :: edge.cfg_flags; + visit_phis edge.cfg_to; + let i = List.fold_left (fun i edge -> i + if has_flag edge M.flag then 1 else 0) 0 edge.cfg_to.bb_incoming in + if i = 1 || edge.cfg_to == g.g_root then + visit_expressions edge.cfg_to; + begin match edge.cfg_to.bb_outgoing with + | [edge] -> add_cfg_edge edge + | _ -> () + end + end; + loop(); + | [],((bb,is_phi,i) :: edges) -> + ssa_work_list := edges; + let e = get_texpr bb is_phi i in + ignore(visit_expression bb e); + loop() + | [],[] -> + () + in + loop () + + let apply ctx = + M.init ctx; + run ctx; + M.commit ctx +end + +(* + ConstPropagation implements sparse conditional constant propagation using the DataFlow algorithm. Its lattice consists of + constants and enum values, but only the former are propagated. Enum values are treated as immutable data tuples and allow + extracting constants, their index or other enum values. + + This module also deals with binop/unop optimization and standard API inlining. +*) +module ConstPropagation = DataFlow(struct + open BasicBlock + + type t = + | Top + | Bottom + | Const of tconstant + | EnumValue of int * t list + + let conditional = true + let flag = FlagExecutable + + let lattice = Hashtbl.create 0 + + let get_cell i = try Hashtbl.find lattice i with Not_found -> Top + let set_cell i ct = Hashtbl.replace lattice i ct + + let top = Top + let bottom = Bottom + + let equals lat1 lat2 = match lat1,lat2 with + | Top,Top | Bottom,Bottom -> true + | Const ct1,Const ct2 -> ct1 = ct2 + | EnumValue(i1,_),EnumValue(i2,_) -> i1 = i2 + | _ -> false + + let transfer ctx bb e = + let rec eval bb e = + let wrap = function + | Const ct -> mk (TConst ct) t_dynamic null_pos + | _ -> raise Exit + in + let unwrap e = match e.eexpr with + | TConst ct -> Const ct + | _ -> raise Exit + in + match e.eexpr with + | TConst (TSuper | TThis | TNull) -> + Bottom + | TConst ct -> + Const ct + | TLocal v -> + if is_unbound v || (follow v.v_type) == t_dynamic || v.v_capture then + Bottom + else + get_cell v.v_id + | TBinop(OpAssign,_,e2) -> + eval bb e2 + | TBinop(op,e1,e2) -> + let cl1 = eval bb e1 in + let cl2 = eval bb e2 in + let e1 = wrap cl1 in + let e2 = wrap cl2 in + let e = {e with eexpr = TBinop(op,e1,e2)} in + let e' = optimize_binop e op e1 e2 in + if e != e' then + eval bb e' + else + unwrap e' + | TUnop(op,flag,e1) -> + let cl1 = eval bb e1 in + let e1 = wrap cl1 in + let e = {e with eexpr = TUnop(op,flag,e1)} in + let e' = optimize_unop e op flag e1 in + if e != e' then + eval bb e' + else + unwrap e' + | TField(_,FEnum(_,ef)) -> + EnumValue(ef.ef_index,[]) + | TCall({eexpr = TField(_,FEnum(_,ef))},el) -> + let cll = List.map (fun e -> try eval bb e with Exit -> Bottom) el in + EnumValue(ef.ef_index,cll) + | TEnumParameter(e1,_,i) -> + begin match eval bb e1 with + | EnumValue(_,el) -> (try List.nth el i with Failure _ -> raise Exit) + | _ -> raise Exit + end; + | TCall ({ eexpr = TField (_,FStatic(c,cf))},el) -> + let el = List.map (eval bb) el in + let el = List.map wrap el in + begin match Optimizer.api_inline2 ctx.com c cf.cf_name el e.epos with + | None -> raise Exit + | Some e -> eval bb e + end + | TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) -> + eval bb e1 + | _ -> + let e1 = match ctx.com.platform,e.eexpr with + | Js,TArray(e1,{eexpr = TConst(TInt i)}) when Int32.to_int i = 1 -> e1 + | Cpp,TCall({eexpr = TField(e1,FDynamic "__Index")},[]) -> e1 + | Neko,TField(e1,FDynamic "index") -> e1 + | _ -> raise Exit + in + begin match follow e1.etype,eval bb e1 with + | TEnum _,EnumValue(i,_) -> Const (TInt (Int32.of_int i)) + | _ -> raise Exit + end + in + try + eval bb e + with Exit -> + Bottom + + let init ctx = + Hashtbl.clear lattice + + let commit ctx = + let inline e i = match get_cell i with + | Top | Bottom | EnumValue _ -> + raise Not_found + | Const ct -> + let e' = Codegen.type_constant ctx.com (tconst_to_const ct) e.epos in + if not (type_change_ok ctx.com e'.etype e.etype) then raise Not_found; + e' + in + let is_special_var v = v.v_capture || is_asvar_type v.v_type in + let rec commit e = match e.eexpr with + | TLocal v when not (is_special_var v) -> + begin try + inline e v.v_id + with Not_found -> + e + end + | TBinop((OpAssign | OpAssignOp _ as op),({eexpr = TLocal v} as e1),e2) -> + let e2 = try + if (has_side_effect e2) then raise Not_found; + inline e2 v.v_id + with Not_found -> + commit e2 + in + {e with eexpr = TBinop(op,e1,e2)} + | TVar(v,Some e1) when not (has_side_effect e1) -> + let e1 = try inline e1 v.v_id with Not_found -> commit e1 in + {e with eexpr = TVar(v,Some e1)} + | _ -> + Type.map_expr commit e + in + Graph.iter_dom_tree ctx.graph (fun bb -> + if not (List.exists (fun edge -> has_flag edge FlagExecutable) bb.bb_incoming) then bb.bb_dominator <- ctx.graph.Graph.g_unreachable; + dynarray_map commit bb.bb_el + ); +end) + +(* + Propagates local variables to other local variables. + + Respects scopes on targets where it matters (all except JS and As3). +*) +module CopyPropagation = DataFlow(struct + open BasicBlock + open Graph + + type t = + | Top + | Bottom + | Local of tvar + + let to_string = function + | Top -> "Top" + | Bottom -> "Bottom" + | Local v -> Printf.sprintf "%s<%i>" v.v_name v.v_id + + let conditional = false + let flag = FlagCopyPropagation + let lattice = Hashtbl.create 0 + + let get_cell i = try Hashtbl.find lattice i with Not_found -> Top + let set_cell i ct = Hashtbl.replace lattice i ct + + let top = Top + let bottom = Bottom + + let equals t1 t2 = match t1,t2 with + | Top,Top -> true + | Bottom,Bottom -> true + | Local v1,Local v2 -> v1.v_id = v2.v_id + | _ -> false + + let transfer ctx bb e = + let rec loop e = match e.eexpr with + | TLocal v when not v.v_capture -> + Local v + | TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) -> + loop e1 + | _ -> + Bottom + in + loop e + + let init ctx = + Hashtbl.clear lattice + + let commit ctx = + let rec commit bb e = match e.eexpr with + | TLocal v when not v.v_capture -> + begin try + let lat = get_cell v.v_id in + let leave () = + Hashtbl.remove lattice v.v_id; + raise Not_found + in + let v' = match lat with Local v -> v | _ -> leave() in + if not (type_change_ok ctx.com v'.v_type v.v_type) then leave(); + let v'' = get_var_origin ctx.graph v' in + (* This restriction is in place due to how we currently reconstruct the AST. Multiple SSA-vars may be turned back to + the same origin var, which creates interference that is not tracked in the analysis. We address this by only + considering variables whose origin-variables are assigned to at most once. *) + let writes = (get_var_info ctx.graph v'').vi_writes in + begin match writes with + | [bb'] when in_scope bb bb' -> () + | _ -> leave() + end; + commit bb {e with eexpr = TLocal v'} + with Not_found -> + e + end + | TBinop((OpAssign | OpAssignOp _ as op),({eexpr = TLocal _} as e1),e2) -> + let e2 = commit bb e2 in + {e with eexpr = TBinop(op,e1,e2)} + | _ -> + Type.map_expr (commit bb) e + in + Graph.iter_dom_tree ctx.graph (fun bb -> + dynarray_map (commit bb) bb.bb_el + ); +end) + +(* + LocalDce implements a mark & sweep dead code elimination. The mark phase follows the CFG edges of the graphs to find + variable usages and marks variables accordingly. If ConstPropagation was run before, only CFG edges which are + considered executable are processed. + + If a variable is marked as used, its reaching definition is recursively marked as used too. Furthermore its + value is processed as an expression. + + The sweep phase removes all variable declarations and assignments of unused variables, keeping only the assigned + expression in case of side-effects. +*) +module LocalDce = struct + open BasicBlock + open Graph + open AnalyzerConfig + + let rec has_side_effect e = + let rec loop e = + match e.eexpr with + | TConst _ | TLocal _ | TTypeExpr _ | TFunction _ -> () + | TCall ({ eexpr = TField(_,FStatic({ cl_path = ([],"Std") },{ cf_name = "string" })) },args) -> Type.iter loop e + | TCall ({eexpr = TField(_,FEnum _)},_) -> Type.iter loop e + | TCall ({eexpr = TConst (TString ("phi" | "fun"))},_) -> () + | TCall({eexpr = TField(e1,fa)},el) when PurityState.is_pure_field_access fa -> loop e1; List.iter loop el + | TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit + | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit + | TFor _ -> raise Exit + | TArray _ | TEnumParameter _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ + | TField _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TBlock _ | TObjectDecl _ | TVar _ -> Type.iter loop e + in + try + loop e; + false + with Exit -> + true + + let rec apply ctx = + let is_used v = + Meta.has Meta.Used v.v_meta + in + let keep v = + is_used v || (not (Meta.has Meta.CompilerGenerated v.v_meta) && not ctx.config.local_dce) || is_ref_type v.v_type || v.v_capture || Meta.has Meta.This v.v_meta + in + let rec use v = + if not (is_used v) then begin + v.v_meta <- (Meta.Used,[],null_pos) :: v.v_meta; + (try expr (get_var_value ctx.graph v) with Not_found -> ()); + begin match Ssa.get_reaching_def ctx.graph v with + | None -> use (get_var_origin ctx.graph v) + | Some v -> use v; + end + end + and expr e = match e.eexpr with + | TLocal v when not (is_unbound v) -> + use v; + | TBinop(OpAssign,{eexpr = TLocal v},e1) | TVar(v,Some e1) when not (is_unbound v) -> + if has_side_effect e1 || keep v then expr e1 + else () + | _ -> + Type.iter expr e + in + let bb_marked = ref [] in + let rec mark bb = + bb_marked := bb :: !bb_marked; + DynArray.iter expr bb.bb_el; + DynArray.iter expr bb.bb_phi; + List.iter (fun edge -> + if not (has_flag edge FlagDce) then begin + edge.cfg_flags <- FlagDce :: edge.cfg_flags; + if not ctx.config.const_propagation || has_flag edge FlagExecutable then + mark edge.cfg_from; + end + ) bb.bb_incoming + in + mark ctx.graph.g_exit; + let rec sweep e = match e.eexpr with + | TBinop(OpAssign,{eexpr = TLocal v},e2) | TVar(v,Some e2) when not (keep v) -> + if has_side_effect e2 then + e2 + else + mk (TConst TNull) e.etype e.epos + | TVar(v,None) when not (keep v) -> + mk (TConst TNull) e.etype e.epos + | _ -> + Type.map_expr sweep e + in + List.iter (fun bb -> + dynarray_map sweep bb.bb_el + ) !bb_marked; +end + +module Debug = struct + open BasicBlock + open Graph + + type node_info = + | NIExpr + | NIVars + | NIPhi + | NILoopGroups + | NIScopes + + let s_var v = Printf.sprintf "%s<%i>" v.v_name v.v_id + + let dot_debug_node g ch nil bb = + let s = Printf.sprintf "(%i)" bb.bb_id in + let s = List.fold_left (fun s ni -> s ^ match ni with + | NIExpr -> if DynArray.length bb.bb_el = 0 then "" else "\n" ^ String.concat "\n" (DynArray.to_list (DynArray.map s_expr_pretty bb.bb_el)) + | NIPhi -> if DynArray.length bb.bb_phi = 0 then "" else "\n" ^ String.concat "\n" (DynArray.to_list (DynArray.map (fun e -> s_expr_pretty e) bb.bb_phi)) + | NIVars -> if bb.bb_var_writes = [] then "" else "\n" ^ String.concat ", " (List.map (fun v -> s_var v) bb.bb_var_writes) + | NILoopGroups -> if bb.bb_loop_groups = [] then "" else "\nLoops: " ^ (String.concat ", " (List.map string_of_int bb.bb_loop_groups)) + | NIScopes -> if bb.bb_scopes = [] then "" else "\nScopes: " ^ (String.concat ", " (List.map string_of_int bb.bb_scopes)) + ) s nil in + let s_kind = match bb.bb_kind with + | BKRoot -> "\n" + | BKFunctionBegin _ -> "\n" + | BKFunctionEnd -> "\n" + | BKLoopHead -> "\n" + | _ -> "" + in + Printf.fprintf ch "n%i [shape=box,label=\"%s%s\"];\n" bb.bb_id s_kind (s_escape s) + + let dot_debug_cfg_edge ch edge = + let label = match edge.cfg_kind with + | CFGGoto -> "goto" + | CFGFunction -> "function" + | CFGMaybeThrow -> "throw?" + | CFGCondBranch _ -> "branch" + | CFGCondElse -> "else" + in + let s_edge_flag = function + | FlagExecutable -> "exe" + | FlagDce -> "dce" + | FlagCopyPropagation -> "copy" + in + let label = label ^ match edge.cfg_flags with + | [] -> "" + | _ -> Printf.sprintf " [%s]" (String.concat ", " (List.map s_edge_flag edge.cfg_flags)) + in + Printf.fprintf ch "n%i -> n%i[label=\"%s\"];\n" edge.cfg_from.bb_id edge.cfg_to.bb_id (s_escape label) + + let dot_debug_syntax_edge ch bb se = + let edge bb' label = + Printf.fprintf ch "n%i -> n%i[style=\"dashed\",color=\"gray\",label=\"%s\"];\n" bb.bb_id bb'.bb_id label; + in + match se with + | SESubBlock(bb_sub,bb_next) -> + edge bb_sub "sub"; + edge bb_next "next"; + | SEIfThen(bb_then,bb_next,_) -> + edge bb_then "then"; + edge bb_next "next" + | SEIfThenElse(bb_then,bb_else,bb_next,_,_) -> + edge bb_then "then"; + edge bb_else "else"; + edge bb_next "next"; + | SEWhile(bb_head,bb_body,bb_next) -> + edge bb_head "loop-head"; + edge bb_body "loop-body"; + edge bb_next "next"; + | SEMerge bb_next -> + edge bb_next "merge" + | SESwitch(bbl,bo,bb_next,_) -> + List.iter (fun (el,bb) -> edge bb ("case " ^ (String.concat " | " (List.map s_expr_pretty el)))) bbl; + (match bo with None -> () | Some bb -> edge bb "default"); + edge bb_next "next"; + | SETry(bb_try,_,bbl,bb_next,_) -> + edge bb_try "try"; + List.iter (fun (_,bb_catch) -> edge bb_catch "catch") bbl; + edge bb_next "next"; + | SEEnd -> + () + | SENone -> + () + + let htmlescape s = + let s = String.concat "&" (ExtString.String.nsplit s "&") in + let s = String.concat "<" (ExtString.String.nsplit s "<") in + let s = String.concat ">" (ExtString.String.nsplit s ">") in + s + + let generate_cfg_ssa ch g = + Printf.fprintf ch "\tnode [shape=plaintext];\n"; + let expr_name b i = Printf.sprintf "e%s%i" (if b then "p" else "") i in + List.iter (fun bb -> + Printf.fprintf ch "n%i[label=<\n\t\n" bb.bb_id bb.bb_id (BasicBlock.s_block_kind bb.bb_kind); + let s_expr b i e = + Printf.fprintf ch "\t\n" (expr_name b i) (s_escape (htmlescape (s_expr_pretty e))) + in + DynArray.iteri (s_expr true) bb.bb_phi; + DynArray.iteri (s_expr false) bb.bb_el; + Printf.fprintf ch "\t\n
(%i) %s
%s
>];\n"; + ) g.g_nodes; + Graph.iter_edges g (fun edge -> + Printf.fprintf ch "n%i:out -> n%i:in[label=\"%s\"];\n" edge.cfg_from.bb_id edge.cfg_to.bb_id (BasicBlock.s_cfg_edge_kind edge.cfg_kind) + ); + DynArray.iter (fun vi -> + begin try + let (bb,is_phi,i) = match vi.vi_value with None -> raise Not_found | Some i -> i in + let n1 = Printf.sprintf "n%i:%s" bb.bb_id (expr_name is_phi i) in + List.iter (fun (bb',is_phi',i') -> + if bb != bb' then begin (* intra-node edges look stupid in dot *) + let n2 = Printf.sprintf "n%i:%s" bb'.bb_id (expr_name is_phi' i') in + Printf.fprintf ch "%s -> %s[color=lightblue,constraint=false];\n" n1 n2; + end + ) vi.vi_ssa_edges; + with Not_found -> + () + end + ) g.g_var_infos + + let get_dump_path ctx c cf = + "dump" :: [platform_name ctx.com.platform] @ (fst c.cl_path) @ [Printf.sprintf "%s.%s" (snd c.cl_path) cf.cf_name] + + let dot_debug ctx c cf = + let g = ctx.graph in + let start_graph ?(graph_config=[]) suffix = + let ch = Codegen.Dump.create_file suffix [] (get_dump_path ctx c cf) in + Printf.fprintf ch "digraph graphname {\n"; + List.iter (fun s -> Printf.fprintf ch "%s;\n" s) graph_config; + ch,(fun () -> + Printf.fprintf ch "}\n"; + close_out ch + ) + in + let ch,f = start_graph "-cfg.dot" in + List.iter (fun bb -> dot_debug_node g ch [NILoopGroups;NIScopes;NIPhi;NIExpr] bb) g.g_nodes; + Graph.iter_edges g (dot_debug_cfg_edge ch); + f(); + let ch,f = start_graph "-cfg-ssa.dot" in + generate_cfg_ssa ch g; + f(); + let ch,f = start_graph "-dj.dot" in + List.iter (fun bb -> + dot_debug_node g ch [] bb; + List.iter (fun einc -> + let bb' = einc.cfg_from in + let style = if bb' == bb.bb_dominator then "solid" else "dashed" in + Printf.fprintf ch "n%i -> n%i[style=\"%s\"];\n" bb'.bb_id bb.bb_id style; + ) bb.bb_incoming; + ) g.g_nodes; + f(); + let ch,f = start_graph "-df.dot" in + List.iter (fun bb -> + dot_debug_node g ch [NIVars] bb; + List.iter (fun bb' -> Printf.fprintf ch "n%i -> n%i;\n" bb.bb_id bb'.bb_id) bb.bb_df; + ) g.g_nodes; + f(); + let ch,f = start_graph "-dom.dot" in + List.iter (fun bb -> + dot_debug_node g ch [NIVars] bb; + List.iter (fun bb' -> Printf.fprintf ch "n%i -> n%i;\n" bb.bb_id bb'.bb_id) bb.bb_dominated; + ) g.g_nodes; + f(); + let ch,f = start_graph "-syntax.dot" in + List.iter (fun bb -> + dot_debug_node g ch [NIExpr] bb; + dot_debug_syntax_edge ch bb bb.bb_syntax_edge + ) g.g_nodes; + f(); + let ch,f = start_graph "-ssa-edges.dot" in + let nodes = ref PMap.empty in + let node_name bb is_phi i = Printf.sprintf "e%i_%b_%i" bb.bb_id is_phi i in + let node_name2 bb is_phi i = + let n = node_name bb is_phi i in + nodes := PMap.add n true !nodes; + n + in + DynArray.iter (fun vi -> + begin try + let (bb,is_phi,i) = match vi.vi_value with None -> raise Not_found | Some i -> i in + let n1 = node_name2 bb is_phi i in + List.iter (fun (bb',is_phi',i') -> + let n2 = node_name2 bb' is_phi' i' in + Printf.fprintf ch "%s -> %s;\n" n1 n2 + ) vi.vi_ssa_edges + with Not_found -> + () + end + ) g.g_var_infos; + List.iter (fun bb -> + let f is_phi acc i e = + let n = node_name bb is_phi i in + (i + 1),if PMap.mem n !nodes then + (n,s_expr_pretty e) :: acc + else + acc + in + let _,active_nodes = DynArray.fold_left (fun (i,acc) -> f true acc i) (0,[]) bb.bb_phi in + let _,active_nodes = DynArray.fold_left (fun (i,acc) -> f false acc i) (0,active_nodes) bb.bb_el in + if active_nodes <> [] then begin + Printf.fprintf ch "subgraph cluster_%i {\n" bb.bb_id; + Printf.fprintf ch "label=%i;\n" bb.bb_id; + Printf.fprintf ch "style=filled;\n"; + Printf.fprintf ch "color=lightblue;\n"; + List.iter (fun (n,s) -> + Printf.fprintf ch "%s[shape=box,label=\"%s\"];\n" n (s_escape s) + ) active_nodes; + Printf.fprintf ch "}\n"; + end; + ) g.g_nodes; + f() +end + +module Run = struct + open AnalyzerConfig + open Graph + + let with_timer detailed s f = + let timer = timer (if detailed then "analyzer" :: s else ["analyzer"]) in + let r = f() in + timer(); + r + + let create_analyzer_context com config e = + let g = Graph.create e.etype e.epos in + let ctx = { + com = com; + config = config; + graph = g; + (* For CPP we want to use variable names which are "probably" not used by users in order to + avoid problems with the debugger, see https://github.com/HaxeFoundation/hxcpp/issues/365 *) + temp_var_name = (match com.platform with Cpp -> "_hx_tmp" | _ -> "tmp"); + entry = g.g_unreachable; + has_unbound = false; + loop_counter = 0; + loop_stack = []; + debug_exprs = []; + name_stack = []; + } in + ctx + + let add_debug_expr ctx s e = + ctx.debug_exprs <- (s,e) :: ctx.debug_exprs + + let there actx e = + if actx.com.debug then add_debug_expr actx "initial" e; + let e = with_timer actx.config.detail_times ["->";"var-lazifier"] (fun () -> VarLazifier.apply actx.com e) in + if actx.com.debug then add_debug_expr actx "after var-lazifier" e; + let e = with_timer actx.config.detail_times ["->";"filter-apply"] (fun () -> TexprFilter.apply actx.com e) in + if actx.com.debug then add_debug_expr actx "after filter-apply" e; + let tf,t,is_real_function = match e.eexpr with + | TFunction tf -> + tf,e.etype,true + | _ -> + (* Wrap expression in a function so we don't have to treat it as a special case throughout. *) + let e = mk (TReturn (Some e)) t_dynamic e.epos in + let tf = { tf_args = []; tf_type = e.etype; tf_expr = e; } in + tf,tfun [] e.etype,false + in + with_timer actx.config.detail_times ["->";"from-texpr"] (fun () -> AnalyzerTexprTransformer.from_tfunction actx tf t e.epos); + is_real_function + + let back_again actx is_real_function = + let e = with_timer actx.config.detail_times ["<-";"to-texpr"] (fun () -> AnalyzerTexprTransformer.to_texpr actx) in + if actx.com.debug then add_debug_expr actx "after to-texpr" e; + DynArray.iter (fun vi -> + vi.vi_var.v_extra <- vi.vi_extra; + ) actx.graph.g_var_infos; + let e = if actx.config.fusion then with_timer actx.config.detail_times ["<-";"fusion"] (fun () -> Fusion.apply actx.com actx.config e) else e in + if actx.com.debug then add_debug_expr actx "after fusion" e; + let e = with_timer actx.config.detail_times ["<-";"cleanup"] (fun () -> Cleanup.apply actx.com e) in + if actx.com.debug then add_debug_expr actx "after cleanup" e; + let e = if is_real_function then + e + else begin + (* Get rid of the wrapping function and its return expressions. *) + let rec loop first e = match e.eexpr with + | TReturn (Some e) -> e + | TFunction tf when first -> + begin match loop false tf.tf_expr with + | {eexpr = TBlock _ | TIf _ | TSwitch _ | TTry _} when actx.com.platform = Cpp || actx.com.platform = Hl -> + mk (TCall(e,[])) tf.tf_type e.epos + | e -> + e + end + | TBlock [e] -> loop first e + | TFunction _ -> e + | _ -> Type.map_expr (loop first) e + in + loop true e + end in + e + + let run_on_expr actx e = + let is_real_function = there actx e in + with_timer actx.config.detail_times ["->";"idom"] (fun () -> Graph.infer_immediate_dominators actx.graph); + with_timer actx.config.detail_times ["->";"infer_scopes"] (fun () -> Graph.infer_scopes actx.graph); + with_timer actx.config.detail_times ["->";"var writes"] (fun () -> Graph.infer_var_writes actx.graph); + if actx.com.debug then Graph.check_integrity actx.graph; + if actx.config.optimize && not actx.has_unbound then begin + with_timer actx.config.detail_times ["optimize";"ssa-apply"] (fun () -> Ssa.apply actx); + if actx.config.const_propagation then with_timer actx.config.detail_times ["optimize";"const-propagation"] (fun () -> ConstPropagation.apply actx); + if actx.config.copy_propagation then with_timer actx.config.detail_times ["optimize";"copy-propagation"] (fun () -> CopyPropagation.apply actx); + with_timer actx.config.detail_times ["optimize";"local-dce"] (fun () -> LocalDce.apply actx); + end; + back_again actx is_real_function + + let rec reduce_control_flow ctx e = + let e = Type.map_expr (reduce_control_flow ctx) e in + Optimizer.reduce_control_flow ctx e + + let run_on_field ctx config c cf = match cf.cf_expr with + | Some e when not (is_ignored cf.cf_meta) && not (Typecore.is_removable_field ctx cf) -> + let config = update_config_from_meta ctx.Typecore.com config cf.cf_meta in + (match e.eexpr with TFunction tf -> cf.cf_expr_unoptimized <- Some tf | _ -> ()); + let actx = create_analyzer_context ctx.Typecore.com config e in + let debug() = + prerr_endline (Printf.sprintf "While analyzing %s.%s" (s_type_path c.cl_path) cf.cf_name); + List.iter (fun (s,e) -> + prerr_endline (Printf.sprintf "<%s>" s); + prerr_endline (Type.s_expr_pretty true "" false (s_type (print_context())) e); + prerr_endline (Printf.sprintf "" s); + ) (List.rev actx.debug_exprs); + Debug.dot_debug actx c cf; + prerr_endline (Printf.sprintf "dot graph written to %s" (String.concat "/" (Debug.get_dump_path actx c cf))); + in + let e = try + run_on_expr actx e + with + | Error.Error _ | Abort _ as exc -> + raise exc + | exc -> + debug(); + raise exc + in + let e = reduce_control_flow ctx e in + begin match config.debug_kind with + | DebugNone -> () + | DebugDot -> Debug.dot_debug actx c cf; + | DebugFull -> debug() + end; + cf.cf_expr <- Some e; + | _ -> () + + let run_on_class ctx config c = + let config = update_config_from_meta ctx.Typecore.com config c.cl_meta in + let process_field stat cf = match cf.cf_kind with + | Var _ when not stat -> () + | _ -> run_on_field ctx config c cf + in + List.iter (process_field false) c.cl_ordered_fields; + List.iter (process_field true) c.cl_ordered_statics; + begin match c.cl_constructor with + | None -> () + | Some f -> process_field false f; + end; + begin match c.cl_init with + | None -> + () + | Some e -> + let tf = { tf_args = []; tf_type = e.etype; tf_expr = e; } in + let e = mk (TFunction tf) (tfun [] e.etype) e.epos in + let actx = create_analyzer_context ctx.Typecore.com {config with optimize = false} e in + let e = run_on_expr actx e in + let e = match e.eexpr with + | TFunction tf -> tf.tf_expr + | _ -> assert false + in + c.cl_init <- Some e + end + + let run_on_type ctx config t = + match t with + | TClassDecl c when (is_ignored c.cl_meta) -> () + | TClassDecl c -> run_on_class ctx config c + | TEnumDecl _ -> () + | TTypeDecl _ -> () + | TAbstractDecl _ -> () + + let run_on_types ctx types = + let com = ctx.Typecore.com in + let config = get_base_config com in + with_timer config.detail_times ["other"] (fun () -> + let cfl = if config.optimize && config.purity_inference then with_timer config.detail_times ["optimize";"purity-inference"] (fun () -> Purity.infer com) else [] in + List.iter (run_on_type ctx config) types; + List.iter (fun cf -> cf.cf_meta <- List.filter (fun (m,_,_) -> m <> Meta.Pure) cf.cf_meta) cfl + ) +end +;; +Typecore.analyzer_run_on_expr_ref := (fun com e -> + let config = AnalyzerConfig.get_base_config com in + (* We always want to optimize because const propagation might be required to obtain + a constant expression for inline field initializations (see issue #4977). *) + let config = {config with AnalyzerConfig.optimize = true} in + let actx = Run.create_analyzer_context com config e in + Run.run_on_expr actx e +) \ No newline at end of file diff --git a/src/optimization/analyzerConfig.ml b/src/optimization/analyzerConfig.ml new file mode 100644 index 00000000..d93cad09 --- /dev/null +++ b/src/optimization/analyzerConfig.ml @@ -0,0 +1,140 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Ast +open Type +open Common +open Globals + +type debug_kind = + | DebugNone + | DebugDot + | DebugFull + +type t = { + optimize : bool; + const_propagation : bool; + copy_propagation : bool; + local_dce : bool; + fusion : bool; + purity_inference : bool; + debug_kind : debug_kind; + detail_times : bool; + user_var_fusion : bool; + fusion_debug : bool; +} + +let flag_optimize = "optimize" +let flag_const_propagation = "const_propagation" +let flag_copy_propagation = "copy_propagation" +let flag_local_dce = "local_dce" +let flag_fusion = "fusion" +let flag_ignore = "ignore" +let flag_dot_debug = "dot_debug" +let flag_full_debug = "full_debug" +let flag_user_var_fusion = "user_var_fusion" +let flag_fusion_debug = "fusion_debug" + +let all_flags = + List.fold_left (fun acc flag -> + flag :: ("no_" ^ flag) :: acc + ) [] [flag_optimize;flag_const_propagation;flag_copy_propagation;flag_local_dce;flag_fusion;flag_ignore;flag_dot_debug;flag_user_var_fusion] + +let has_analyzer_option meta s = + try + let rec loop ml = match ml with + | (Meta.Analyzer,el,_) :: ml -> + if List.exists (fun (e,p) -> + match e with + | EConst(Ident s2) when s = s2 -> true + | _ -> false + ) el then + true + else + loop ml + | _ :: ml -> + loop ml + | [] -> + false + in + loop meta + with Not_found -> + false + +let is_ignored meta = + has_analyzer_option meta flag_ignore + +let get_base_config com = + { + optimize = Common.raw_defined com "analyzer-optimize"; + const_propagation = not (Common.raw_defined com "analyzer-no-const-propagation"); + copy_propagation = not (Common.raw_defined com "analyzer-no-copy-propagation"); + local_dce = not (Common.raw_defined com "analyzer-no-local-dce"); + fusion = not (Common.raw_defined com "analyzer-no-fusion"); + purity_inference = not (Common.raw_defined com "analyzer-no-purity-inference"); + debug_kind = DebugNone; + detail_times = Common.raw_defined com "analyzer-times"; + user_var_fusion = (match com.platform with Flash | Java -> false | _ -> true) && (Common.raw_defined com "analyzer-user-var-fusion" || (not com.debug && not (Common.raw_defined com "analyzer-no-user-var-fusion"))); + fusion_debug = false; + } + +let update_config_from_meta com config meta = + List.fold_left (fun config meta -> match meta with + | (Meta.Analyzer,el,_) -> + List.fold_left (fun config e -> match fst e with + | EConst (Ident s) -> + begin match s with + | "optimize" -> { config with optimize = true } + | "no_optimize" -> { config with optimize = false } + | "const_propagation" -> { config with const_propagation = true } + | "no_const_propagation" -> { config with const_propagation = false } + | "copy_propagation" -> { config with copy_propagation = true } + | "no_copy_propagation" -> { config with copy_propagation = false } + | "local_dce" -> { config with local_dce = true } + | "no_local_dce" -> { config with local_dce = false } + | "fusion" -> { config with fusion = true } + | "no_fusion" -> { config with fusion = false } + | "user_var_fusion" -> { config with user_var_fusion = true } + | "no_user_var_fusion" -> { config with user_var_fusion = false } + | "dot_debug" -> { config with debug_kind = DebugDot } + | "full_debug" -> { config with debug_kind = DebugFull } + | "fusion_debug" -> { config with fusion_debug = true } + | "as_var" -> config + | _ -> + com.warning (StringError.string_error s all_flags ("Unrecognized analyzer option: " ^ s)) (pos e); + config + end + | _ -> + let s = Ast.s_expr e in + com.warning (StringError.string_error s all_flags ("Unrecognized analyzer option: " ^ s)) (pos e); + config + ) config el + | (Meta.HasUntyped,_,_) -> + {config with optimize = false} + | _ -> + config + ) config meta + +let get_class_config com c = + let config = get_base_config com in + update_config_from_meta com config c.cl_meta + +let get_field_config com c cf = + let config = get_class_config com c in + update_config_from_meta com config cf.cf_meta \ No newline at end of file diff --git a/src/optimization/analyzerTexpr.ml b/src/optimization/analyzerTexpr.ml new file mode 100644 index 00000000..8a4f7814 --- /dev/null +++ b/src/optimization/analyzerTexpr.ml @@ -0,0 +1,1132 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Ast +open Type +open Common +open OptimizerTexpr +open Globals + +let s_expr_pretty e = s_expr_pretty false "" false (s_type (print_context())) e + +let rec is_true_expr e1 = match e1.eexpr with + | TConst(TBool true) -> true + | TParenthesis e1 -> is_true_expr e1 + | _ -> false + +let map_values ?(allow_control_flow=true) f e = + let branching = ref false in + let efinal = ref None in + let f e = + if !branching then + f e + else begin + efinal := Some e; + mk (TConst TNull) e.etype e.epos + end + in + let rec loop complex e = match e.eexpr with + | TIf(e1,e2,Some e3) -> + branching := true; + let e2 = loop true e2 in + let e3 = loop true e3 in + {e with eexpr = TIf(e1,e2,Some e3)} + | TSwitch(e1,cases,edef) -> + branching := true; + let cases = List.map (fun (el,e) -> el,loop true e) cases in + let edef = Option.map (loop true) edef in + {e with eexpr = TSwitch(e1,cases,edef)} + | TBlock [e1] -> + loop complex e1 + | TBlock el -> + begin match List.rev el with + | e1 :: el -> + let e1 = loop true e1 in + let e = {e with eexpr = TBlock (List.rev (e1 :: el))} in + {e with eexpr = TMeta((Meta.MergeBlock,[],e.epos),e)} + | [] -> + f e + end + | TTry(e1,catches) -> + branching := true; + let e1 = loop true e1 in + let catches = List.map (fun (v,e) -> v,loop true e) catches in + {e with eexpr = TTry(e1,catches)} + | TMeta(m,e1) -> + {e with eexpr = TMeta(m,loop complex e1)} + | TParenthesis e1 -> + {e with eexpr = TParenthesis (loop complex e1)} + | TBreak | TContinue | TThrow _ | TReturn _ -> + if not allow_control_flow then raise Exit; + e + | _ -> + if not complex then raise Exit; + f e + in + let e = loop false e in + e,!efinal + +let can_throw e = + let rec loop e = match e.eexpr with + | TConst _ | TLocal _ | TTypeExpr _ | TFunction _ | TBlock _ -> () + | TCall _ | TNew _ | TThrow _ | TCast(_,Some _) -> raise Exit + | TField _ | TArray _ -> raise Exit (* sigh *) + | _ -> Type.iter loop e + in + try + loop e; false + with Exit -> + true + +let rec can_be_inlined e = match e.eexpr with + | TConst _ -> true + | TParenthesis e1 | TMeta(_,e1) -> can_be_inlined e1 + | _ -> false + +let target_handles_unops com = match com.platform with + | Lua | Python -> false + | _ -> true + +let target_handles_assign_ops com = match com.platform with + (* Technically PHP can handle assign ops, but unfortunately x += y is not always + equivalent to x = x + y in case y has side-effects. *) + | Lua | Php -> false + | Cpp when not (Common.defined com Define.Cppia) -> false + | _ -> true + +let target_handles_side_effect_order com = match com.platform with + | Cpp -> Common.defined com Define.Cppia + | Php -> false + | _ -> true + +let rec can_be_used_as_value com e = + let rec loop e = match e.eexpr with + | TBlock [e] -> loop e + | TBlock _ | TSwitch _ | TTry _ -> raise Exit + | TCall({eexpr = TConst (TString "phi")},_) -> raise Exit + (* | TCall _ | TNew _ when (match com.platform with Cpp | Php -> true | _ -> false) -> raise Exit *) + | TReturn _ | TThrow _ | TBreak | TContinue -> raise Exit + | TUnop((Increment | Decrement),_,_) when not (target_handles_unops com) -> raise Exit + | TNew _ when com.platform = Php && not (Common.is_php7 com) -> raise Exit + | TFunction _ -> () + | _ -> Type.iter loop e + in + try + begin match com.platform,e.eexpr with + | (Cs | Cpp | Java | Flash | Lua),TConst TNull -> raise Exit + | _ -> () + end; + loop e; + true + with Exit -> + false + +let wrap_meta s e = + mk (TMeta((Meta.Custom s,[],e.epos),e)) e.etype e.epos + +let is_really_unbound v = match v.v_name with + | "`trace" | "__int__" -> false + | _ -> is_unbound v + +let r = Str.regexp "^\\([A-Za-z0-9_]\\)+$" +let is_unbound_call_that_might_have_side_effects v el = match v.v_name,el with + | "__js__",[{eexpr = TConst (TString s)}] when Str.string_match r s 0 -> false + | _ -> true + +let is_ref_type = function + | TType({t_path = ["cs"],("Ref" | "Out")},_) -> true + | TType({t_path = path},_) when path = Genphp7.ref_type_path -> true + | TType({t_path = ["cpp"],("Reference")},_) -> true + | TAbstract({a_path=["hl";"types"],"Ref"},_) -> true + | _ -> false + +let rec is_asvar_type t = + let check meta = + AnalyzerConfig.has_analyzer_option meta "as_var" + in + match t with + | TInst(c,_) -> check c.cl_meta + | TEnum(en,_) -> check en.e_meta + | TType(t,tl) -> check t.t_meta || (is_asvar_type (apply_params t.t_params tl t.t_type)) + | TAbstract(a,_) -> check a.a_meta + | TLazy f -> is_asvar_type (!f()) + | TMono r -> + (match !r with + | Some t -> is_asvar_type t + | _ -> false) + | _ -> + false + +let type_change_ok com t1 t2 = + if t1 == t2 then + true + else begin + let rec map t = match t with + | TMono r -> (match !r with None -> t_dynamic | Some t -> map t) + | _ -> Type.map map t + in + let t1 = map t1 in + let t2 = map t2 in + let rec is_nullable_or_whatever = function + | TMono r -> + (match !r with None -> false | Some t -> is_nullable_or_whatever t) + | TType ({ t_path = ([],"Null") },[_]) -> + true + | TLazy f -> + is_nullable_or_whatever (!f()) + | TType (t,tl) -> + is_nullable_or_whatever (apply_params t.t_params tl t.t_type) + | TFun _ -> + false + | TInst ({ cl_kind = KTypeParameter _ },_) -> + false + | TAbstract (a,_) when Meta.has Meta.CoreType a.a_meta -> + not (Meta.has Meta.NotNull a.a_meta) + | TAbstract (a,tl) -> + not (Meta.has Meta.NotNull a.a_meta) && is_nullable_or_whatever (apply_params a.a_params tl a.a_this) + | _ -> + true + in + (* Check equality again to cover cases where TMono became t_dynamic *) + t1 == t2 || match follow t1,follow t2 with + | TDynamic _,_ | _,TDynamic _ -> false + | _ -> + if com.config.pf_static && is_nullable_or_whatever t1 <> is_nullable_or_whatever t2 then false + else type_iseq t1 t2 + end + +let dynarray_map f d = + DynArray.iteri (fun i e -> DynArray.unsafe_set d i (f e)) d + +let dynarray_mapi f d = + DynArray.iteri (fun i e -> DynArray.unsafe_set d i (f i e)) d + +(* + This module rewrites some expressions to reduce the amount of special cases for subsequent analysis. After analysis + it restores some of these expressions back to their original form. + + The following expressions are removed from the AST after `apply` has run: + - OpBoolAnd and OpBoolOr binary operations are rewritten to TIf + - OpAssignOp on a variable is rewritten to OpAssign + - Prefix increment/decrement operations are rewritten to OpAssign + - Postfix increment/decrement operations are rewritten to a TBlock with OpAssign and OpAdd/OpSub + - `do {} while(true)` is rewritten to `while(true) {}` + - TWhile expressions are rewritten to `while (true)` with appropriate conditional TBreak + - TFor is rewritten to TWhile +*) +module TexprFilter = struct + let apply com e = + let rec loop e = match e.eexpr with + | TBinop(OpBoolAnd | OpBoolOr as op,e1,e2) -> + let e_then = e2 in + let e_if,e_else = if op = OpBoolOr then + mk (TUnop(Not,Prefix,e1)) com.basic.tbool e.epos,mk (TConst (TBool(true))) com.basic.tbool e.epos + else + e1,mk (TConst (TBool(false))) com.basic.tbool e.epos + in + loop (mk (TIf(e_if,e_then,Some e_else)) e.etype e.epos) + | TBinop(OpAssignOp op,({eexpr = TLocal _} as e1),e2) -> + let e = {e with eexpr = TBinop(op,e1,e2)} in + loop {e with eexpr = TBinop(OpAssign,e1,e)} + | TUnop((Increment | Decrement as op),flag,({eexpr = TLocal _} as e1)) -> + let e_one = mk (TConst (TInt (Int32.of_int 1))) com.basic.tint e1.epos in + let e = {e with eexpr = TBinop(OpAssignOp (if op = Increment then OpAdd else OpSub),e1,e_one)} in + let e = if flag = Prefix then + e + else + mk (TBlock [ + {e with eexpr = TBinop(OpAssignOp (if op = Increment then OpAdd else OpSub),e1,e_one)}; + {e with eexpr = TBinop((if op = Increment then OpSub else OpAdd),e1,e_one)}; + ]) e.etype e.epos + in + loop e + | TWhile(e1,e2,DoWhile) when is_true_expr e1 -> + loop {e with eexpr = TWhile(e1,e2,NormalWhile)} + | TWhile(e1,e2,flag) when not (is_true_expr e1) -> + let p = e.epos in + let e_break = mk TBreak t_dynamic p in + let e_not = mk (TUnop(Not,Prefix,Codegen.mk_parent e1)) e1.etype e1.epos in + let e_if eo = mk (TIf(e_not,e_break,eo)) com.basic.tvoid p in + let rec map_continue e = match e.eexpr with + | TContinue -> + Texpr.duplicate_tvars (e_if (Some e)) + | TWhile _ | TFor _ -> + e + | _ -> + Type.map_expr map_continue e + in + let e2 = if flag = NormalWhile then e2 else map_continue e2 in + let e_if = e_if None in + let e_block = if flag = NormalWhile then Type.concat e_if e2 else Type.concat e2 e_if in + let e_true = mk (TConst (TBool true)) com.basic.tbool p in + let e = mk (TWhile(Codegen.mk_parent e_true,e_block,NormalWhile)) e.etype p in + loop e + | TFor(v,e1,e2) -> + let e = Codegen.for_remap com v e1 e2 e.epos in + loop e + | _ -> + Type.map_expr loop e + in + loop e +end + +module VarLazifier = struct + let apply com e = + let rec loop var_inits e = match e.eexpr with + | TVar(v,Some e1) when (Meta.has (Meta.Custom ":extractorVariable") v.v_meta) -> + let var_inits,e1 = loop var_inits e1 in + let var_inits = PMap.add v.v_id e1 var_inits in + var_inits,{e with eexpr = TVar(v,None)} + | TLocal v -> + begin try + let e_init = PMap.find v.v_id var_inits in + let e = {e with eexpr = TBinop(OpAssign,e,e_init)} in + let e = {e with eexpr = TParenthesis e} in + let var_inits = PMap.remove v.v_id var_inits in + var_inits,e + with Not_found -> + var_inits,e + end + | TIf(e1,e2,eo) -> + let var_inits,e1 = loop var_inits e1 in + let _,e2 = loop var_inits e2 in + let eo = match eo with None -> None | Some e -> Some (snd (loop var_inits e)) in + var_inits,{e with eexpr = TIf(e1,e2,eo)} + | TSwitch(e1,cases,edef) -> + let var_inits,e1 = loop var_inits e1 in + let cases = List.map (fun (el,e) -> + let _,e = loop var_inits e in + el,e + ) cases in + let edef = match edef with None -> None | Some e -> Some (snd (loop var_inits e)) in + var_inits,{e with eexpr = TSwitch(e1,cases,edef)} + | _ -> + Texpr.foldmap loop var_inits e + in + snd (loop PMap.empty e) +end + +(* + An InterferenceReport represents in which way a given code may be influenced and + how it might influence other code itself. It keeps track of read and write operations + for both variable and fields, as well as a generic state read and write. +*) +module InterferenceReport = struct + type interference_report = { + ir_var_reads : (int,bool) Hashtbl.t; + ir_var_writes : (int,bool) Hashtbl.t; + ir_field_reads : (string,bool) Hashtbl.t; + ir_field_writes : (string,bool) Hashtbl.t; + mutable ir_state_read : bool; + mutable ir_state_write : bool; + } + + let create () = { + ir_var_reads = Hashtbl.create 0; + ir_var_writes = Hashtbl.create 0; + ir_field_reads = Hashtbl.create 0; + ir_field_writes = Hashtbl.create 0; + ir_state_read = false; + ir_state_write = false; + } + + let set_var_read ir v = Hashtbl.replace ir.ir_var_reads v.v_id true + let set_var_write ir v = Hashtbl.replace ir.ir_var_writes v.v_id true + let set_field_read ir s = Hashtbl.replace ir.ir_field_reads s true + let set_field_write ir s = Hashtbl.replace ir.ir_field_writes s true + let set_state_read ir = ir.ir_state_read <- true + let set_state_write ir = ir.ir_state_write <- true + + let has_var_read ir v = Hashtbl.mem ir.ir_var_reads v.v_id + let has_var_write ir v = Hashtbl.mem ir.ir_var_writes v.v_id + let has_field_read ir s = Hashtbl.mem ir.ir_field_reads s + let has_field_write ir s = Hashtbl.mem ir.ir_field_writes s + let has_state_read ir = ir.ir_state_read + let has_state_write ir = ir.ir_state_write + let has_any_field_read ir = Hashtbl.length ir.ir_field_reads > 0 + let has_any_field_write ir = Hashtbl.length ir.ir_field_writes > 0 + let has_any_var_read ir = Hashtbl.length ir.ir_var_reads > 0 + let has_any_var_write ir = Hashtbl.length ir.ir_var_writes > 0 + + let from_texpr e = + let ir = create () in + let rec loop e = match e.eexpr with + (* vars *) + | TLocal v -> + set_var_read ir v; + if v.v_capture then set_state_read ir; + | TBinop(OpAssign,{eexpr = TLocal v},e2) -> + set_var_write ir v; + if v.v_capture then set_state_write ir; + loop e2 + | TBinop(OpAssignOp _,{eexpr = TLocal v},e2) -> + set_var_read ir v; + set_var_write ir v; + if v.v_capture then begin + set_state_read ir; + set_state_write ir; + end; + loop e2 + | TUnop((Increment | Decrement),_,{eexpr = TLocal v}) -> + set_var_read ir v; + set_var_write ir v; + (* fields *) + | TField(e1,fa) -> + loop e1; + if not (is_read_only_field_access e1 fa) then set_field_read ir (field_name fa); + | TBinop(OpAssign,{eexpr = TField(e1,fa)},e2) -> + set_field_write ir (field_name fa); + loop e1; + loop e2; + | TBinop(OpAssignOp _,{eexpr = TField(e1,fa)},e2) -> + let name = field_name fa in + set_field_read ir name; + set_field_write ir name; + loop e1; + loop e2; + | TUnop((Increment | Decrement),_,{eexpr = TField(e1,fa)}) -> + let name = field_name fa in + set_field_read ir name; + set_field_write ir name; + loop e1 + (* array *) + | TArray(e1,e2) -> + set_state_read ir; + loop e1; + loop e2; + | TBinop(OpAssign,{eexpr = TArray(e1,e2)},e3) -> + set_state_write ir; + loop e1; + loop e2; + loop e3; + | TBinop(OpAssignOp _,{eexpr = TArray(e1,e2)},e3) -> + set_state_read ir; + set_state_write ir; + loop e1; + loop e2; + loop e3; + | TUnop((Increment | Decrement),_,{eexpr = TArray(e1,e2)}) -> + set_state_read ir; + set_state_write ir; + loop e1; + loop e2; + (* state *) + | TCall({eexpr = TLocal v},el) when not (is_unbound_call_that_might_have_side_effects v el) -> + List.iter loop el + | TNew(c,_,el) when (match c.cl_constructor with Some cf when PurityState.is_pure c cf -> true | _ -> false) -> + set_state_read ir; + List.iter loop el; + | TCall({eexpr = TField(e1,FEnum _)},el) -> + loop e1; + List.iter loop el; + | TCall({eexpr = TField(e1,fa)},el) when PurityState.is_pure_field_access fa -> + set_state_read ir; + loop e1; + List.iter loop el + | TCall(e1,el) -> + set_state_read ir; + set_state_write ir; + loop e1; + List.iter loop el + | TNew(_,_,el) -> + set_state_read ir; + set_state_write ir; + List.iter loop el + | TBinop(OpAssign,e1,e2) -> + set_state_write ir; + loop e1; + loop e2; + | TBinop(OpAssignOp _,e1,e2) -> + set_state_read ir; + set_state_write ir; + loop e1; + loop e2; + | TUnop((Increment | Decrement),_,e1) -> + set_state_read ir; + set_state_write ir; + loop e1 + | _ -> + Type.iter loop e + in + loop e; + ir + + let to_string ir = + let s_hashtbl f h = + String.concat ", " (Hashtbl.fold (fun k _ acc -> (f k) :: acc) h []) + in + Type.Printer.s_record_fields "\t" [ + "ir_var_reads",s_hashtbl string_of_int ir.ir_var_reads; + "ir_var_writes",s_hashtbl string_of_int ir.ir_var_writes; + "ir_field_reads",s_hashtbl (fun x -> x) ir.ir_field_reads; + "ir_field_writes",s_hashtbl (fun x -> x) ir.ir_field_writes; + "ir_state_read",string_of_bool ir.ir_state_read; + "ir_state_write",string_of_bool ir.ir_state_write; + ] + end + +class fusion_state = object(self) + val mutable _changed = false + val var_reads = Hashtbl.create 0 + val var_writes = Hashtbl.create 0 + + method private change map v delta = + Hashtbl.replace map v.v_id ((try Hashtbl.find map v.v_id with Not_found -> 0) + delta); + + method inc_reads (v : tvar) : unit = self#change var_reads v 1 + method dec_reads (v : tvar) : unit = self#change var_reads v (-1) + method inc_writes (v : tvar) : unit = self#change var_writes v 1 + method dec_writes (v : tvar) : unit = self#change var_writes v (-1) + + method get_reads (v : tvar) = try Hashtbl.find var_reads v.v_id with Not_found -> 0 + method get_writes (v : tvar) = try Hashtbl.find var_writes v.v_id with Not_found -> 0 + + method change_writes (v : tvar) delta = self#change var_writes v delta + + method changed = _changed <- true + method reset = _changed <- false + method did_change = _changed + + method infer_from_texpr (e : texpr) = + let rec loop e = match e.eexpr with + | TLocal v -> + self#inc_reads v; + | TBinop(OpAssign,{eexpr = TLocal v},e2) -> + self#inc_writes v; + loop e2 + | _ -> + Type.iter loop e + in + loop e +end + +(* + Fusion tries to join expressions together in order to make the output "look nicer". To that end, + several transformations occur: + + - `var x; x = e;` is transformed to `var x = e;` + - `var x; if(e1) x = e2 else x = e3` is transformed to `var x = e1 ? e2 : e3` on targets that + deal well with that. + - `var x = e;` is transformed to `e` if `x` is unused. + - Some block-level increment/decrement unary operators are put back into value places and the + transformation of their postfix variant is reversed. + - `x = x op y` is transformed (back) to `x op= y` on targets that deal well with that. + + Most importantly, any `var v = e;` might be fused into expressions that follow it in the same + block if there is no interference. +*) +module Fusion = struct + open AnalyzerConfig + open InterferenceReport + + let is_assign_op = function + | OpAdd + | OpMult + | OpDiv + | OpSub + | OpAnd + | OpOr + | OpXor + | OpShl + | OpShr + | OpUShr + | OpMod -> + true + | OpAssign + | OpEq + | OpNotEq + | OpGt + | OpGte + | OpLt + | OpLte + | OpBoolAnd + | OpBoolOr + | OpAssignOp _ + | OpInterval + | OpArrow -> + false + + let use_assign_op com op e1 e2 = + is_assign_op op && target_handles_assign_ops com && Texpr.equal e1 e2 && not (has_side_effect e1) && match com.platform with + | Cs when is_null e1.etype || is_null e2.etype -> false (* C# hates OpAssignOp on Null *) + | _ -> true + + let apply com config e = + let state = new fusion_state in + state#infer_from_texpr e; + (* Handles block-level expressions, e.g. by removing side-effect-free ones and recursing into compound constructs like + array or object declarations. The resulting element list is reversed. *) + let rec block_element acc el = match el with + | {eexpr = TBinop((OpAssign | OpAssignOp _),_,_) | TUnop((Increment | Decrement),_,_)} as e1 :: el -> + block_element (e1 :: acc) el + | {eexpr = TLocal _} as e1 :: el when not config.local_dce -> + block_element (e1 :: acc) el + | {eexpr = TLocal v} :: el -> + state#dec_reads v; + block_element acc el + (* no-side-effect *) + | {eexpr = TEnumParameter _ | TFunction _ | TConst _ | TTypeExpr _} :: el -> + block_element acc el + | {eexpr = TMeta((Meta.Pure,_,_),_)} :: el -> + block_element acc el + | {eexpr = TCall({eexpr = TField(e1,fa)},el1)} :: el2 when PurityState.is_pure_field_access fa && config.local_dce -> + block_element acc (e1 :: el1 @ el2) + | {eexpr = TNew(c,tl,el1)} :: el2 when (match c.cl_constructor with Some cf when PurityState.is_pure c cf -> true | _ -> false) && config.local_dce -> + block_element acc (el1 @ el2) + (* no-side-effect composites *) + | {eexpr = TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) | TField(e1,_) | TUnop(_,_,e1)} :: el -> + block_element acc (e1 :: el) + | {eexpr = TArray(e1,e2) | TBinop(_,e1,e2)} :: el -> + block_element acc (e1 :: e2 :: el) + | {eexpr = TArrayDecl el1 | TCall({eexpr = TField(_,FEnum _)},el1)} :: el2 -> (* TODO: check e1 of FEnum *) + block_element acc (el1 @ el2) + | {eexpr = TObjectDecl fl} :: el -> + block_element acc ((List.map snd fl) @ el) + | {eexpr = TIf(e1,{eexpr = TBlock []},(Some {eexpr = TBlock []} | None))} :: el -> + block_element acc (e1 :: el) + | {eexpr = TBlock [e1]} :: el -> + block_element acc (e1 :: el) + | {eexpr = TBlock []} :: el -> + block_element acc el + | e1 :: el -> + block_element (e1 :: acc) el + | [] -> + acc + in + let can_be_fused v e = + let num_uses = state#get_reads v in + let num_writes = state#get_writes v in + let can_be_used_as_value = can_be_used_as_value com e in + let is_compiler_generated = Meta.has Meta.CompilerGenerated v.v_meta in + let has_type_params = match v.v_extra with Some (tl,_) when tl <> [] -> true | _ -> false in + let b = num_uses <= 1 && + num_writes = 0 && + can_be_used_as_value && + not (is_asvar_type v.v_type) && + (is_compiler_generated || config.optimize && config.fusion && config.user_var_fusion && not has_type_params) + in + if config.fusion_debug then begin + print_endline (Printf.sprintf "FUSION\n\tvar %s<%i> = %s" v.v_name v.v_id (s_expr_pretty e)); + print_endline (Printf.sprintf "\tcan_be_fused:%b: num_uses:%i <= 1 && num_writes:%i = 0 && can_be_used_as_value:%b && (is_compiler_generated:%b || config.optimize:%b && config.fusion:%b && config.user_var_fusion:%b)" + b num_uses num_writes can_be_used_as_value is_compiler_generated config.optimize config.fusion config.user_var_fusion) + end; + b + in + let rec fuse acc el = match el with + | ({eexpr = TVar(v1,None)} as e1) :: {eexpr = TBinop(OpAssign,{eexpr = TLocal v2},e2)} :: el when v1 == v2 -> + state#changed; + let e1 = {e1 with eexpr = TVar(v1,Some e2)} in + state#dec_writes v1; + fuse (e1 :: acc) el + | ({eexpr = TVar(v1,None)} as e1) :: ({eexpr = TIf(eif,_,Some _)} as e2) :: el + when + can_be_used_as_value com e2 && + not (ExtType.is_void e2.etype) && + (match com.platform with + | Php when not (Common.is_php7 com) -> false + | Cpp when not (Common.defined com Define.Cppia) -> false + | _ -> true) + -> + begin try + let i = ref 0 in + let check_assign e = match e.eexpr with + | TBinop(OpAssign,{eexpr = TLocal v2},e2) when v1 == v2 -> incr i; e2 + | _ -> raise Exit + in + let e,_ = map_values ~allow_control_flow:false check_assign e2 in + let e1 = {e1 with eexpr = TVar(v1,Some e)} in + state#changed; + state#change_writes v1 (- !i); + fuse (e1 :: acc) el + with Exit -> + fuse (e1 :: acc) (e2 :: el) + end + | {eexpr = TVar(v1,Some e1)} :: el when config.optimize && config.local_dce && state#get_reads v1 = 0 && state#get_writes v1 = 0 -> + fuse acc (e1 :: el) + | ({eexpr = TVar(v1,Some e1)} as ev) :: el when can_be_fused v1 e1 -> + let found = ref false in + let blocked = ref false in + let ir = InterferenceReport.from_texpr e1 in + if config.fusion_debug then print_endline (Printf.sprintf "\tInterferenceReport: %s\n\t%s" + (InterferenceReport.to_string ir) (Type.s_expr_pretty true "\t" false (s_type (print_context())) (mk (TBlock el) t_dynamic null_pos))); + (* This function walks the AST in order of evaluation and tries to find an occurrence of v1. If successful, that occurrence is + replaced with e1. If there's an interference "on the way" the replacement is canceled. *) + let rec replace e = + let explore e = + let old = !blocked in + blocked := true; + let e = replace e in + blocked := old; + e + in + let handle_el el = + (* This mess deals with the fact that the order of evaluation is undefined for call + arguments on these targets. Even if we find a replacement, we pretend that we + didn't in order to find possible interferences in later call arguments. *) + let temp_found = false in + let really_found = ref !found in + let el = List.map (fun e -> + found := temp_found; + let e = replace e in + if !found then really_found := true; + e + ) el in + found := !really_found; + el + in + let handle_el = if not (target_handles_side_effect_order com) then handle_el else List.map replace in + let handle_call e2 el = match com.platform with + | Neko -> + (* Neko has this reversed at the moment (issue #4787) *) + let el = List.map replace el in + let e2 = replace e2 in + e2,el + | Php | Cpp when not (Common.defined com Define.Cppia) && not (Common.is_php7 com) -> + let is_php_safe e1 = + let rec loop e = match e.eexpr with + | TCall _ -> raise Exit + | TCast(e1,_) | TParenthesis e1 | TMeta(_,e1) -> loop e1 + | _ -> () + in + try loop e1; true with Exit -> false + in + (* PHP5 doesn't like call()() expressions. *) + let e2 = if com.platform = Php && not (is_php_safe e1) then explore e2 else replace e2 in + let el = handle_el el in + e2,el + | _ -> + let e2 = replace e2 in + let el = List.map replace el in + e2,el + in + if !found then e else match e.eexpr with + | TWhile _ | TTry _ -> + raise Exit + | TFunction _ -> + e + | TIf(e1,e2,eo) -> + let e1 = replace e1 in + if not !found && (has_state_write ir || has_any_field_write ir || has_any_var_write ir) then raise Exit; + let e2 = replace e2 in + let eo = Option.map replace eo in + {e with eexpr = TIf(e1,e2,eo)} + | TSwitch(e1,cases,edef) -> + let e1 = match com.platform with + | Lua | Python -> explore e1 + | _ -> replace e1 + in + if not !found then raise Exit; + {e with eexpr = TSwitch(e1,cases,edef)} + (* locals *) + | TLocal v2 when v1 == v2 && not !blocked -> + found := true; + if type_change_ok com v1.v_type e1.etype then e1 else mk (TCast(e1,None)) v1.v_type e.epos + | TLocal v -> + if has_var_write ir v || ((v.v_capture || is_ref_type v.v_type) && (has_state_write ir)) then raise Exit; + e + | TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) -> + let e2 = replace e2 in + if not !found && has_var_read ir v then raise Exit; + {e with eexpr = TBinop(OpAssign,e1,e2)} + | TBinop(OpAssignOp _ as op,({eexpr = TLocal v} as e1),e2) -> + let e2 = replace e2 in + if not !found && (has_var_read ir v || has_var_write ir v) then raise Exit; + {e with eexpr = TBinop(op,e1,e2)} + | TUnop((Increment | Decrement),_,{eexpr = TLocal v}) when has_var_read ir v || has_var_write ir v -> + raise Exit + (* fields *) + | TField(e1,fa) -> + let e1 = replace e1 in + if not !found && not (is_read_only_field_access e1 fa) && (has_field_write ir (field_name fa) || has_state_write ir) then raise Exit; + {e with eexpr = TField(e1,fa)} + | TBinop(OpAssign,({eexpr = TField(e1,fa)} as ef),e2) -> + let e1 = replace e1 in + let e2 = replace e2 in + if not !found && (has_field_read ir (field_name fa) || has_state_read ir) then raise Exit; + {e with eexpr = TBinop(OpAssign,{ef with eexpr = TField(e1,fa)},e2)} + | TBinop(OpAssignOp _ as op,({eexpr = TField(e1,fa)} as ef),e2) -> + let e1 = replace e1 in + let s = field_name fa in + if not !found && (has_field_write ir s || has_state_write ir) then raise Exit; + let e2 = replace e2 in + if not !found && (has_field_read ir s || has_state_read ir) then raise Exit; + {e with eexpr = TBinop(op,{ef with eexpr = TField(e1,fa)},e2)} + | TUnop((Increment | Decrement),_,{eexpr = TField(e1,fa)}) when has_field_read ir (field_name fa) || has_state_read ir + || has_field_write ir (field_name fa) || has_state_write ir -> + raise Exit + (* state *) + | TCall({eexpr = TLocal v},el) when not (is_unbound_call_that_might_have_side_effects v el) -> + e + | TNew(c,tl,el) when (match c.cl_constructor with Some cf when PurityState.is_pure c cf -> true | _ -> false) -> + let el = handle_el el in + if not !found && (has_state_write ir || has_any_field_write ir) then raise Exit; + {e with eexpr = TNew(c,tl,el)} + | TNew(c,tl,el) -> + let el = handle_el el in + if not !found && (has_state_write ir || has_state_read ir || has_any_field_read ir || has_any_field_write ir) then raise Exit; + {e with eexpr = TNew(c,tl,el)} + | TCall({eexpr = TField(_,FEnum _)} as ef,el) -> + let el = List.map replace el in + {e with eexpr = TCall(ef,el)} + | TCall({eexpr = TField(_,fa)} as ef,el) when PurityState.is_pure_field_access fa -> + let ef,el = handle_call ef el in + if not !found && (has_state_write ir || has_any_field_write ir) then raise Exit; + {e with eexpr = TCall(ef,el)} + | TCall(e1,el) -> + let e1,el = match e1.eexpr with + | TLocal v when is_really_unbound v -> e1,el + | _ -> handle_call e1 el + in + if not !found && (((has_state_read ir || has_any_field_read ir)) || has_state_write ir || has_any_field_write ir) then raise Exit; + {e with eexpr = TCall(e1,el)} + | TObjectDecl fl -> + let el = handle_el (List.map snd fl) in + if not !found && (has_state_write ir || has_any_field_write ir) then raise Exit; + {e with eexpr = TObjectDecl (List.map2 (fun (s,_) e -> s,e) fl el)} + | TArrayDecl el -> + let el = handle_el el in + (*if not !found && (has_state_write ir || has_any_field_write ir) then raise Exit;*) + {e with eexpr = TArrayDecl el} + | TBinop(OpAssign,({eexpr = TArray(e1,e2)} as ea),e3) -> + let e1 = replace e1 in + let e2 = replace e2 in + let e3 = replace e3 in + if not !found && has_state_read ir then raise Exit; + {e with eexpr = TBinop(OpAssign,{ea with eexpr = TArray(e1,e2)},e3)} + | TBinop(op,e1,e2) when (match com.platform with Cpp | Php when not (Common.is_php7 com) -> true | _ -> false) -> + let e1 = replace e1 in + let temp_found = !found in + found := false; + let e2 = replace e2 in + found := !found || temp_found; + {e with eexpr = TBinop(op,e1,e2)} + | TArray(e1,e2) -> + let e1 = replace e1 in + let e2 = replace e2 in + if not !found && has_state_write ir then raise Exit; + {e with eexpr = TArray(e1,e2)} + | _ -> + Type.map_expr replace e + in + begin try + let rec loop acc el = match el with + | e :: el -> + let e = replace e in + if !found then (List.rev (e :: acc)) @ el + else loop (e :: acc) el + | [] -> + List.rev acc + in + let el = loop [] el in + if not !found then raise Exit; + state#changed; + state#dec_reads v1; + if config.fusion_debug then print_endline (Printf.sprintf "YES: %s" (s_expr_pretty (mk (TBlock el) t_dynamic null_pos))); + fuse acc el + with Exit -> + if config.fusion_debug then print_endline (Printf.sprintf "NO: %s" (Printexc.get_backtrace())); + fuse (ev :: acc) el + end + | {eexpr = TUnop((Increment | Decrement as op,Prefix,({eexpr = TLocal v} as ev)))} as e1 :: e2 :: el -> + begin try + let e2,f = match e2.eexpr with + | TReturn (Some e2) -> e2,(fun e -> {e2 with eexpr = TReturn (Some e)}) + | TBinop(OpAssign,e21,e22) -> e22,(fun e -> {e2 with eexpr = TBinop(OpAssign,e21,e)}) + | TVar(v,Some e2) -> e2,(fun e -> {e2 with eexpr = TVar(v,Some e)}) + | _ -> raise Exit + in + let ops_match op1 op2 = match op1,op2 with + | Increment,OpSub + | Decrement,OpAdd -> + true + | _ -> + false + in + begin match e2.eexpr with + | TBinop(op2,{eexpr = TLocal v2},{eexpr = TConst (TInt i32)}) when v == v2 && Int32.to_int i32 = 1 && ops_match op op2 -> + state#changed; + state#dec_reads v2; + let e = (f {e1 with eexpr = TUnop(op,Postfix,ev)}) in + fuse (e :: acc) el + | TLocal v2 when v == v2 -> + state#changed; + state#dec_reads v2; + let e = (f {e1 with eexpr = TUnop(op,Prefix,ev)}) in + fuse (e :: acc) el + | _ -> + raise Exit + end + with Exit -> + fuse (e1 :: acc) (e2 :: el) + end + | {eexpr = TBinop(OpAssign,e1,{eexpr = TBinop(op,e2,e3)})} as e :: el when use_assign_op com op e1 e2 -> + let rec loop e = match e.eexpr with + | TLocal v -> state#dec_reads v; + | _ -> Type.iter loop e + in + loop e1; + state#changed; + fuse acc ({e with eexpr = TBinop(OpAssignOp op,e1,e3)} :: el) + | {eexpr = TBinop(OpAssignOp _,e1,_)} as eop :: ({eexpr = TVar(v,Some e2)} as evar) :: el when Texpr.equal e1 e2 -> + state#changed; + fuse ({evar with eexpr = TVar(v,Some eop)} :: acc) el + | e1 :: el -> + fuse (e1 :: acc) el + | [] -> + acc + in + let rec loop e = match e.eexpr with + | TBlock el -> + let el = List.rev_map loop el in + let el = block_element [] el in + (* fuse flips element order, but block_element doesn't care and flips it back *) + let el = fuse [] el in + let el = block_element [] el in + let rec fuse_loop el = + state#reset; + let el = fuse [] el in + let el = block_element [] el in + if state#did_change then fuse_loop el else el + in + let el = fuse_loop el in + {e with eexpr = TBlock el} + | TCall({eexpr = TLocal v},_) when is_really_unbound v -> + e + | _ -> + Type.map_expr loop e + in + loop e +end + +module Cleanup = struct + let apply com e = + let if_or_op e e1 e2 e3 = match (Texpr.skip e1).eexpr,(Texpr.skip e3).eexpr with + | TUnop(Not,Prefix,e1),TConst (TBool true) -> optimize_binop {e with eexpr = TBinop(OpBoolOr,e1,e2)} OpBoolOr e1 e2 + | _,TConst (TBool false) -> optimize_binop {e with eexpr = TBinop(OpBoolAnd,e1,e2)} OpBoolAnd e1 e2 + | _,TBlock [] -> {e with eexpr = TIf(e1,e2,None)} + | _ -> match (Texpr.skip e2).eexpr with + | TBlock [] when com.platform <> Cs -> + let e1' = mk (TUnop(Not,Prefix,e1)) e1.etype e1.epos in + let e1' = optimize_unop e1' Not Prefix e1 in + {e with eexpr = TIf(e1',e3,None)} + | _ -> + {e with eexpr = TIf(e1,e2,Some e3)} + in + let rec loop e = match e.eexpr with + | TIf(e1,e2,Some e3) -> + let e1 = loop e1 in + let e2 = loop e2 in + let e3 = loop e3 in + if_or_op e e1 e2 e3; + | TUnop((Increment | Decrement),_,e1) when (match (Texpr.skip e1).eexpr with TConst _ -> true | _ -> false) -> + loop e1 + | TCall({eexpr = TLocal v},_) when is_really_unbound v -> + e + | TBlock el -> + let el = List.map (fun e -> + let e = loop e in + match e.eexpr with + | TIf _ -> {e with etype = com.basic.tvoid} + | _ -> e + ) el in + {e with eexpr = TBlock el} + | TWhile(e1,e2,NormalWhile) -> + let e1 = loop e1 in + let e2 = loop e2 in + begin match e2.eexpr with + | TBlock ({eexpr = TIf(e1,({eexpr = TBlock[{eexpr = TBreak}]} as eb),None)} :: el2) -> + let e1 = Texpr.skip e1 in + let e1 = match e1.eexpr with TUnop(_,_,e1) -> e1 | _ -> {e1 with eexpr = TUnop(Not,Prefix,e1)} in + {e with eexpr = TWhile(e1,{eb with eexpr = TBlock el2},NormalWhile)} + | TBlock el -> + let rec loop2 el = match el with + | {eexpr = TBreak | TContinue | TReturn _ | TThrow _} as e :: el -> + [e] + | e :: el -> + e :: (loop2 el) + | [] -> + [] + in + let el = loop2 el in + {e with eexpr = TWhile(e1,{e2 with eexpr = TBlock el},NormalWhile)} + | _ -> + {e with eexpr = TWhile(e1,e2,NormalWhile)} + end + | TField({eexpr = TTypeExpr _},_) -> + e + | TTypeExpr (TClassDecl c) -> + List.iter (fun cf -> if not (Meta.has Meta.MaybeUsed cf.cf_meta) then cf.cf_meta <- (Meta.MaybeUsed,[],cf.cf_pos) :: cf.cf_meta;) c.cl_ordered_statics; + e + | _ -> + Type.map_expr loop e + in + loop e +end + +module Purity = struct + open PurityState + + type purity_node = { + pn_class : tclass; + pn_field : tclass_field; + mutable pn_purity : PurityState.t; + mutable pn_dependents : purity_node list; + } + + exception Purity_conflict of purity_node * pos + + let node_lut = Hashtbl.create 0 + + let get_field_id c cf = Printf.sprintf "%s.%s" (s_type_path c.cl_path) cf.cf_name + + let get_node c cf = + try + Hashtbl.find node_lut (get_field_id c cf) + with Not_found -> + let node = { + pn_class = c; + pn_field = cf; + pn_purity = PurityState.get_purity c cf; + pn_dependents = [] + } in + Hashtbl.replace node_lut (get_field_id c cf) node; + node + + let rec taint node = match node.pn_purity with + | Impure -> () + | ExpectPure p -> raise (Purity_conflict(node,p)); + | MaybePure | Pure -> + node.pn_purity <- Impure; + List.iter taint node.pn_dependents; + let rec loop c = match c.cl_super with + | None -> () + | Some(c,_) -> + begin try + let cf = PMap.find node.pn_field.cf_name c.cl_fields in + taint (get_node c cf); + with Not_found -> + () + end; + loop c + in + loop node.pn_class + + let taint_raise node = + taint node; + raise Exit + + let apply_to_field com is_ctor c cf = + let node = get_node c cf in + let check_field c cf = + let node' = get_node c cf in + match node'.pn_purity with + | Pure | ExpectPure _ -> () + | Impure -> taint_raise node; + | MaybePure -> node'.pn_dependents <- node :: node'.pn_dependents + in + let rec check_write e1 = + begin match e1.eexpr with + | TLocal v -> + if is_ref_type v.v_type then taint_raise node; (* Writing to a ref type means impurity. *) + () (* Writing to locals does not violate purity. *) + | TField({eexpr = TConst TThis},_) when is_ctor -> + () (* A constructor can write to its own fields without violating purity. *) + | _ -> + taint_raise node + end + and loop e = match e.eexpr with + | TMeta((Meta.Pure,_,_),_) -> + () + | TThrow _ -> + taint_raise node; + | TBinop((OpAssign | OpAssignOp _),e1,e2) -> + check_write e1; + loop e2; + | TUnop((Increment | Decrement),_,e1) -> + check_write e1; + | TCall({eexpr = TField(_,FStatic(c,cf))},el) -> + List.iter loop el; + check_field c cf; + | TNew(c,_,el) -> + List.iter loop el; + begin match c.cl_constructor with + | Some cf -> check_field c cf + | None -> taint_raise node + end + | TCall({eexpr = TConst TSuper},el) -> + begin match c.cl_super with + | Some({cl_constructor = Some cf} as c,_) -> + check_field c cf; + List.iter loop el + | _ -> + taint_raise node (* Can that even happen? *) + end + | TCall({eexpr = TLocal v},el) when not (is_unbound_call_that_might_have_side_effects v el) -> + List.iter loop el; + | TCall _ -> + taint_raise node + | _ -> + Type.iter loop e + in + match cf.cf_kind with + | Method MethDynamic | Var _ -> + taint node; + | _ -> + match cf.cf_expr with + | None -> + if not (is_pure c cf) then taint node + (* TODO: The function code check shouldn't be here I guess. *) + | Some _ when (Meta.has Meta.Extern cf.cf_meta || Meta.has Meta.FunctionCode cf.cf_meta || Meta.has (Meta.Custom ":hlNative") cf.cf_meta || Meta.has (Meta.Custom ":hlNative") c.cl_meta) -> + if not (is_pure c cf) then taint node + | Some e -> + try + begin match node.pn_purity with + | Impure -> taint_raise node + | Pure -> raise Exit + | _ -> loop e + end + with Exit -> + () + + let apply_to_class com c = + List.iter (apply_to_field com false c) c.cl_ordered_fields; + List.iter (apply_to_field com false c) c.cl_ordered_statics; + (match c.cl_constructor with Some cf -> apply_to_field com true c cf | None -> ()) + + let infer com = + Hashtbl.clear node_lut; + List.iter (fun mt -> match mt with + | TClassDecl c -> + begin try + apply_to_class com c + with Purity_conflict(impure,p) -> + com.error "Impure field overrides/implements field which was explicitly marked as @:pure" impure.pn_field.cf_pos; + Error.error "Pure field is here" p; + end + | _ -> () + ) com.types; + Hashtbl.fold (fun _ node acc -> + match node.pn_purity with + | Pure | MaybePure -> + node.pn_field.cf_meta <- (Meta.Pure,[EConst(Ident "true"),node.pn_field.cf_pos],node.pn_field.cf_pos) :: node.pn_field.cf_meta; + node.pn_field :: acc + | _ -> + acc + ) node_lut []; +end diff --git a/src/optimization/analyzerTexprTransformer.ml b/src/optimization/analyzerTexprTransformer.ml new file mode 100644 index 00000000..7a3edb4d --- /dev/null +++ b/src/optimization/analyzerTexprTransformer.ml @@ -0,0 +1,745 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Globals +open Ast +open Type +open Common +open AnalyzerConfig +open AnalyzerTypes +open AnalyzerTypes.BasicBlock +open AnalyzerTypes.Graph +open AnalyzerTexpr +open OptimizerTexpr + +(* + Transforms an expression to a graph, and a graph back to an expression. This module relies on TexprFilter being + run first. + + The created graph is intact and can immediately be transformed back to an expression, or used for analysis first. +*) + +let rec func ctx bb tf t p = + let g = ctx.graph in + let create_node kind t p = + let bb = Graph.create_node g kind t p in + bb.bb_loop_groups <- ctx.loop_stack; + bb + in + let bb_root = create_node (BKFunctionBegin tf) tf.tf_expr.etype tf.tf_expr.epos in + let bb_exit = create_node BKFunctionEnd tf.tf_expr.etype tf.tf_expr.epos in + add_function g tf t p bb_root; + add_cfg_edge bb bb_root CFGFunction; + let make_block_meta b = + let e = mk (TConst (TInt (Int32.of_int b.bb_id))) ctx.com.basic.tint b.bb_pos in + wrap_meta ":block" e + in + let bb_breaks = ref [] in + let bb_continue = ref None in + let b_try_stack = ref [] in + let begin_loop bb_loop_pre bb_continue' = + let old = !bb_breaks,!bb_continue in + bb_breaks := []; + bb_continue := Some bb_continue'; + let id = ctx.loop_counter in + g.g_loops <- IntMap.add id bb_loop_pre g.g_loops; + ctx.loop_stack <- id :: ctx.loop_stack; + bb_continue'.bb_loop_groups <- id :: bb_continue'.bb_loop_groups; + ctx.loop_counter <- id + 1; + (fun () -> + let breaks = !bb_breaks in + bb_breaks := fst old; + bb_continue := snd old; + ctx.loop_stack <- List.tl ctx.loop_stack; + breaks; + ) + in + let begin_try b = + b_try_stack := b :: !b_try_stack; + (fun () -> + b_try_stack := List.tl !b_try_stack + ) + in + let add_terminator bb e = + add_texpr bb e; + close_node g bb; + g.g_unreachable + in + let check_unbound_call v el = + if v.v_name = "$ref" then begin match el with + | [{eexpr = TLocal v}] -> v.v_capture <- true + | _ -> () + end; + if is_unbound_call_that_might_have_side_effects v el then ctx.has_unbound <- true; + in + let no_void t p = + if ExtType.is_void (follow t) then Error.error "Cannot use Void as value" p + in + let push_name s = + ctx.name_stack <- s :: ctx.name_stack; + (fun () -> ctx.name_stack <- List.tl ctx.name_stack) + in + let rec value' bb e = match e.eexpr with + | TLocal v -> + bb,e + | TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) -> + block_element bb e,e1 + | TBlock [e1] -> + value bb e1 + | TBlock _ | TIf _ | TSwitch _ | TTry _ -> + bind_to_temp bb false e + | TCall({eexpr = TLocal v},el) when is_really_unbound v -> + check_unbound_call v el; + bb,e + | TCall(e1,el) -> + call bb e e1 el + | TBinop(OpAssignOp op,({eexpr = TArray(e1,e2)} as ea),e3) -> + array_assign_op bb op e ea e1 e2 e3 + | TBinop(OpAssignOp op,({eexpr = TField(e1,fa)} as ef),e2) -> + field_assign_op bb op e ef e1 fa e2 + | TBinop((OpAssign | OpAssignOp _) as op,e1,e2) -> + let bb,e1 = value bb e1 in + let bb,e2 = value bb e2 in + bb,{e with eexpr = TBinop(op,e1,e2)} + | TBinop(op,e1,e2) -> + let bb,e1,e2 = match ordered_value_list bb [e1;e2] with + | bb,[e1;e2] -> bb,e1,e2 + | _ -> assert false + in + bb,{e with eexpr = TBinop(op,e1,e2)} + | TUnop(op,flag,e1) -> + let bb,e1 = value bb e1 in + bb,{e with eexpr = TUnop(op,flag,e1)} + | TArrayDecl el -> + let bb,el = ordered_value_list bb el in + bb,{e with eexpr = TArrayDecl el} + | TObjectDecl fl -> + let el = List.map snd fl in + let bb,el = ordered_value_list bb el in + bb,{e with eexpr = TObjectDecl (List.map2 (fun (s,_) e -> s,e) fl el)} + | TField({eexpr = TTypeExpr _},fa) -> + bb,e + | TField(e1,fa) -> + let bb,e1 = value bb e1 in + bb,{e with eexpr = TField(e1,fa)} + | TArray(e1,e2) -> + let bb,e1,e2 = match ordered_value_list bb [e1;e2] with + | bb,[e1;e2] -> bb,e1,e2 + | _ -> assert false + in + bb,{e with eexpr = TArray(e1,e2)} + | TMeta(m,e1) -> + let bb,e1 = value bb e1 in + bb,{e with eexpr = TMeta(m,e1)} + | TParenthesis e1 -> + let bb,e1 = value bb e1 in + bb,{e with eexpr = TParenthesis e1} + | TCast(e1,mto) -> + let bb,e1 = value bb e1 in + bb,{e with eexpr = TCast(e1,mto)} + | TNew(c,tl,el) -> + let bb,el = ordered_value_list bb el in + bb,{e with eexpr = TNew(c,tl,el)} + | TEnumParameter(e1,ef,ei) -> + let bb,e1 = value bb e1 in + bb,{e with eexpr = TEnumParameter(e1,ef,ei)} + | TFunction tf -> + let bb_func,bb_func_end = func ctx bb tf e.etype e.epos in + let e_fun = mk (TConst (TString "fun")) t_dynamic p in + let econst = mk (TConst (TInt (Int32.of_int bb_func.bb_id))) ctx.com.basic.tint e.epos in + let ec = mk (TCall(e_fun,[econst])) t_dynamic p in + let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in + add_cfg_edge bb bb_next CFGGoto; + set_syntax_edge bb (SEMerge bb_next); + close_node g bb; + add_cfg_edge bb_func_end bb_next CFGGoto; + bb_next,ec + (*| TTypeExpr(TClassDecl {cl_kind = KAbstractImpl a}) when not (Meta.has Meta.RuntimeValue a.a_meta) -> + error "Cannot use abstract as value" e.epos*) + | TConst _ | TTypeExpr _ -> + bb,e + | TThrow _ | TReturn _ | TBreak | TContinue -> + let bb = block_element bb e in + bb,mk (TConst TNull) t_dynamic e.epos + | TVar _ | TFor _ | TWhile _ -> + Error.error "Cannot use this expression as value" e.epos + and value bb e = + let bb,e = value' bb e in + no_void e.etype e.epos; + bb,e + and ordered_value_list bb el = + let might_be_affected,collect_modified_locals = create_affection_checker() in + let rec can_be_optimized e = match e.eexpr with + | TBinop _ | TArray _ | TCall _ -> true + | TParenthesis e1 -> can_be_optimized e1 + | _ -> false + in + let _,el = List.fold_left (fun (had_side_effect,acc) e -> + if had_side_effect then + (true,(might_be_affected e || has_side_effect e,can_be_optimized e,e) :: acc) + else begin + let had_side_effect = has_side_effect e in + if had_side_effect then collect_modified_locals e; + let opt = can_be_optimized e in + (had_side_effect || opt,(false,opt,e) :: acc) + end + ) (false,[]) (List.rev el) in + let bb,values = List.fold_left (fun (bb,acc) (aff,opt,e) -> + let bb,value = if aff || opt then bind_to_temp bb aff e else value bb e in + bb,(value :: acc) + ) (bb,[]) el in + bb,List.rev values + and bind_to_temp ?(v=None) bb sequential e = + let is_probably_not_affected e e1 fa = match fa with + | FAnon cf | FInstance (_,_,cf) | FStatic (_,cf) | FClosure (_,cf) when cf.cf_kind = Method MethNormal -> true + | FStatic(_,{cf_kind = Method MethDynamic}) -> false + | FEnum _ -> true + | FDynamic ("cca" | "__Index" | "__s") -> true (* This is quite retarded, but we have to deal with this somehow... *) + | _ -> match follow e.etype,follow e1.etype with + | TFun _,TInst _ -> false + | TFun _,_ -> true (* We don't know what's going on here, don't create a temp var (see #5082). *) + | _ -> false + in + let rec loop fl e = match e.eexpr with + | TField(e1,fa) when is_probably_not_affected e e1 fa -> + loop ((fun e' -> {e with eexpr = TField(e',fa)}) :: fl) e1 + | TField(e1,fa) -> + let fa = match fa with + | FInstance(c,tl,({cf_kind = Method _ } as cf)) -> FClosure(Some(c,tl),cf) + | _ -> fa + in + fl,{e with eexpr = TField(e1,fa)} + | _ -> + fl,e + in + let fl,e = loop [] e in + let rec loop e = match e.eexpr with + | TLocal v -> v.v_name + | TArray(e1,_) | TField(e1,_) | TParenthesis e1 | TCast(e1,None) | TMeta(_,e1) -> loop e1 + | _ -> match ctx.name_stack with + | s :: _ -> s + | [] -> ctx.temp_var_name + in + let v = match v with Some v -> v | None -> alloc_var (loop e) e.etype e.epos in + begin match ctx.com.platform with + | Globals.Cpp when sequential && not (Common.defined ctx.com Define.Cppia) -> () + | _ -> v.v_meta <- [Meta.CompilerGenerated,[],e.epos]; + end; + let bb = declare_var_and_assign bb v e e.epos in + let e = {e with eexpr = TLocal v} in + let e = List.fold_left (fun e f -> f e) e (List.rev fl) in + bb,e + and declare_var_and_assign bb v e p = + (* TODO: this section shouldn't be here because it can be handled as part of the normal value processing *) + let rec loop bb e = match e.eexpr with + | TParenthesis e1 -> + loop bb e1 + | TBlock el -> + let rec loop2 bb el = match el with + | [e] -> + bb,e + | e1 :: el -> + let bb = block_element bb e1 in + if bb == g.g_unreachable then raise Exit; + loop2 bb el + | [] -> + assert false + in + let bb,e = loop2 bb el in + loop bb e + | _ -> + bb,e + in + let generate bb e = + no_void v.v_type p; + let ev = mk (TLocal v) v.v_type p in + let was_assigned = ref false in + let assign e = + if not !was_assigned then begin + was_assigned := true; + add_texpr bb (mk (TVar(v,None)) ctx.com.basic.tvoid ev.epos); + end; + mk (TBinop(OpAssign,ev,e)) ev.etype ev.epos + in + let close = push_name v.v_name in + let bb = try + block_element_plus bb (map_values assign e) (fun e -> mk (TVar(v,Some e)) ctx.com.basic.tvoid ev.epos) + with Exit -> + let bb,e = value bb e in + add_texpr bb (mk (TVar(v,Some e)) ctx.com.basic.tvoid ev.epos); + bb + in + close(); + bb + in + try + let bb,e = loop bb e in + generate bb e + with Exit -> + g.g_unreachable + and block_element_plus bb (e,efinal) f = + let bb = block_element bb e in + let bb = match efinal with + | None -> bb + | Some e -> block_element bb (f e) + in + bb + and block_element_value bb e f = + let e,efinal = map_values f e in + block_element_plus bb (e,efinal) f + and call bb e e1 el = + let bb = ref bb in + let check e t = match e.eexpr with + | TLocal v when is_ref_type t -> + v.v_capture <- true; + e + | _ -> + if is_asvar_type t then begin + let v = alloc_var "tmp" t e.epos in + let bb',e = bind_to_temp ~v:(Some v) !bb false e in + bb := bb'; + e + end else + e + in + let el = Codegen.UnificationCallback.check_call check el e1.etype in + let bb,el = ordered_value_list !bb (e1 :: el) in + match el with + | e1 :: el -> bb,{e with eexpr = TCall(e1,el)} + | _ -> assert false + and array_assign_op bb op e ea e1 e2 e3 = + let bb,e1 = bind_to_temp bb false e1 in + let bb,e2 = bind_to_temp bb false e2 in + let ea = {ea with eexpr = TArray(e1,e2)} in + let bb,e4 = bind_to_temp bb false ea in + let bb,e3 = bind_to_temp bb false e3 in + let eop = {e with eexpr = TBinop(op,e4,e3)} in + add_texpr bb {e with eexpr = TBinop(OpAssign,ea,eop)}; + bb,ea + and field_assign_op bb op e ef e1 fa e2 = + let bb,e1 = bind_to_temp bb false e1 in + let ef = {ef with eexpr = TField(e1,fa)} in + let bb,e3 = bind_to_temp bb false ef in + let bb,e2 = bind_to_temp bb false e2 in + let eop = {e with eexpr = TBinop(op,e3,e2)} in + add_texpr bb {e with eexpr = TBinop(OpAssign,ef,eop)}; + bb,ef + and block_element bb e = match e.eexpr with + (* variables *) + | TVar(v,None) -> + add_texpr bb e; + bb + | TVar(v,Some e1) -> + declare_var_and_assign bb v e1 e.epos + | TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) -> + let assign e = + mk (TBinop(OpAssign,e1,e)) e.etype e.epos + in + let close = push_name v.v_name in + let bb = try + block_element_value bb e2 assign + with Exit -> + let bb,e2 = value bb e2 in + add_texpr bb {e with eexpr = TBinop(OpAssign,e1,e2)}; + bb + in + close(); + bb + (* branching *) + | TMeta((Meta.MergeBlock,_,_),{eexpr = TBlock el}) -> + block_el bb el + | TBlock el -> + let bb_sub = create_node BKSub e.etype e.epos in + add_cfg_edge bb bb_sub CFGGoto; + close_node g bb; + let bb_sub_next = block_el bb_sub el in + if bb_sub_next != g.g_unreachable then begin + let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in + set_syntax_edge bb (SESubBlock(bb_sub,bb_next)); + add_cfg_edge bb_sub_next bb_next CFGGoto; + close_node g bb_sub_next; + bb_next; + end else begin + set_syntax_edge bb (SEMerge bb_sub); + close_node g bb_sub_next; + bb_sub_next + end + | TIf(e1,e2,None) -> + let bb,e1 = bind_to_temp bb false e1 in + let bb_then = create_node BKConditional e2.etype e2.epos in + add_texpr bb (wrap_meta ":cond-branch" e1); + add_cfg_edge bb bb_then (CFGCondBranch (mk (TConst (TBool true)) ctx.com.basic.tbool e2.epos)); + let bb_then_next = block bb_then e2 in + let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in + set_syntax_edge bb (SEIfThen(bb_then,bb_next,e.epos)); + add_cfg_edge bb bb_next CFGCondElse; + close_node g bb; + add_cfg_edge bb_then_next bb_next CFGGoto; + close_node g bb_then_next; + bb_next + | TIf(e1,e2,Some e3) -> + let bb,e1 = bind_to_temp bb false e1 in + let bb_then = create_node BKConditional e2.etype e2.epos in + let bb_else = create_node BKConditional e3.etype e3.epos in + add_texpr bb (wrap_meta ":cond-branch" e1); + add_cfg_edge bb bb_then (CFGCondBranch (mk (TConst (TBool true)) ctx.com.basic.tbool e2.epos)); + add_cfg_edge bb bb_else CFGCondElse; + close_node g bb; + let bb_then_next = block bb_then e2 in + let bb_else_next = block bb_else e3 in + if bb_then_next == g.g_unreachable && bb_else_next == g.g_unreachable then begin + set_syntax_edge bb (SEIfThenElse(bb_then,bb_else,g.g_unreachable,e.etype,e.epos)); + g.g_unreachable + end else begin + let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in + set_syntax_edge bb (SEIfThenElse(bb_then,bb_else,bb_next,e.etype,e.epos)); + add_cfg_edge bb_then_next bb_next CFGGoto; + add_cfg_edge bb_else_next bb_next CFGGoto; + close_node g bb_then_next; + close_node g bb_else_next; + bb_next + end + | TSwitch(e1,cases,edef) -> + let is_exhaustive = edef <> None || is_exhaustive e1 in + let bb,e1 = bind_to_temp bb false e1 in + add_texpr bb (wrap_meta ":cond-branch" e1); + let reachable = ref [] in + let make_case e = + let bb_case = create_node BKConditional e.etype e.epos in + let bb_case_next = block bb_case e in + if bb_case_next != g.g_unreachable then + reachable := bb_case_next :: !reachable; + close_node g bb_case_next; + bb_case + in + let cases = List.map (fun (el,e) -> + let bb_case = make_case e in + List.iter (fun e -> add_cfg_edge bb bb_case (CFGCondBranch e)) el; + el,bb_case + ) cases in + let def = match edef with + | None -> + None + | Some e -> + let bb_case = make_case e in + add_cfg_edge bb bb_case (CFGCondElse); + Some (bb_case) + in + if is_exhaustive && !reachable = [] then begin + set_syntax_edge bb (SESwitch(cases,def,g.g_unreachable,e.epos)); + close_node g bb; + g.g_unreachable; + end else begin + let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in + if not is_exhaustive then add_cfg_edge bb bb_next CFGGoto; + List.iter (fun bb -> add_cfg_edge bb bb_next CFGGoto) !reachable; + set_syntax_edge bb (SESwitch(cases,def,bb_next,e.epos)); + close_node g bb; + bb_next + end + | TWhile(e1,e2,NormalWhile) -> + let bb_loop_pre = create_node BKNormal e1.etype e1.epos in + add_cfg_edge bb bb_loop_pre CFGGoto; + set_syntax_edge bb (SEMerge bb_loop_pre); + close_node g bb; + let bb_loop_head = create_node BKLoopHead e1.etype e1.epos in + add_cfg_edge bb_loop_pre bb_loop_head CFGGoto; + let close = begin_loop bb bb_loop_head in + let bb_loop_body = create_node BKNormal e2.etype e2.epos in + let bb_loop_body_next = block bb_loop_body e2 in + let bb_breaks = close() in + let bb_next = if bb_breaks = [] then begin + (* The loop appears to be infinite, let's assume that something within it throws. + Otherwise DCE's mark-pass won't see its body and removes everything. *) + add_cfg_edge bb_loop_body_next bb_exit CFGMaybeThrow; + g.g_unreachable + end else + create_node BKNormal bb.bb_type bb.bb_pos + in + List.iter (fun bb -> add_cfg_edge bb bb_next CFGGoto) bb_breaks; + set_syntax_edge bb_loop_pre (SEWhile(bb_loop_head,bb_loop_body,bb_next)); + close_node g bb_loop_pre; + add_texpr bb_loop_pre {e with eexpr = TWhile(e1,make_block_meta bb_loop_body,NormalWhile)}; + add_cfg_edge bb_loop_body_next bb_loop_head CFGGoto; + add_cfg_edge bb_loop_head bb_loop_body CFGGoto; + close_node g bb_loop_body_next; + close_node g bb_loop_head; + bb_next; + | TTry(e1,catches) -> + let bb_try = create_node BKNormal e1.etype e1.epos in + let bb_exc = create_node BKException t_dynamic e.epos in + add_cfg_edge bb bb_try CFGGoto; + let close = begin_try bb_exc in + let bb_try_next = block bb_try e1 in + close(); + (* We always want to keep catch-blocks, so let's add a pseudo CFG edge if it's unreachable. *) + if bb_exc.bb_incoming = [] then add_cfg_edge (if bb_try_next == g.g_unreachable then bb_try else bb_try_next) bb_exc CFGMaybeThrow; + let is_reachable = ref (not (bb_try_next == g.g_unreachable)) in + let catches = List.map (fun (v,e) -> + let bb_catch = create_node (BKCatch v) e.etype e.epos in + add_cfg_edge bb_exc bb_catch CFGGoto; + let bb_catch_next = block bb_catch e in + is_reachable := !is_reachable || (not (bb_catch_next == g.g_unreachable)); + v,bb_catch,bb_catch_next + ) catches in + let bb_next = if !is_reachable then create_node BKNormal bb.bb_type bb.bb_pos else g.g_unreachable in + let catches = List.map (fun (v,bb_catch,bb_catch_next) -> + if bb_catch_next != g.g_unreachable then add_cfg_edge bb_catch_next bb_next CFGGoto; + close_node g bb_catch_next; + v,bb_catch + ) catches in + set_syntax_edge bb (SETry(bb_try,bb_exc,catches,bb_next,e.epos)); + if bb_try_next != g.g_unreachable then add_cfg_edge bb_try_next bb_next CFGGoto; + close_node g bb_try_next; + close_node g bb_exc; + close_node g bb; + bb_next + (* control flow *) + | TReturn None -> + add_cfg_edge bb bb_exit CFGGoto; + add_terminator bb e + | TReturn (Some e1) when ExtType.is_void (follow e1.etype) -> + let bb = block_element bb e1 in + block_element bb (mk (TReturn None) t_dynamic e.epos) + | TReturn (Some e1) -> + begin try + let mk_return e1 = mk (TReturn (Some e1)) t_dynamic e.epos in + block_element_value bb e1 mk_return + with Exit -> + let bb,e1 = value bb e1 in + add_cfg_edge bb bb_exit CFGGoto; + add_terminator bb {e with eexpr = TReturn(Some e1)}; + end + | TBreak -> + bb_breaks := bb :: !bb_breaks; + add_terminator bb e + | TContinue -> + begin match !bb_continue with + | Some bb_continue -> add_cfg_edge bb bb_continue CFGGoto + | _ -> assert false + end; + add_terminator bb e + | TThrow e1 -> + begin try + let mk_throw e1 = + mk (TThrow e1) t_dynamic e.epos + in + block_element_value bb e1 mk_throw + with Exit -> + let bb,e1 = value bb e1 in + begin match !b_try_stack with + | [] -> add_cfg_edge bb bb_exit CFGGoto + | _ -> List.iter (fun bb_exc -> add_cfg_edge bb bb_exc CFGGoto) !b_try_stack; + end; + add_terminator bb {e with eexpr = TThrow e1}; + end + (* side_effects *) + | TCall({eexpr = TLocal v},el) when is_really_unbound v -> + check_unbound_call v el; + add_texpr bb e; + bb + | TCall(e1,el) -> + let bb,e = call bb e e1 el in + add_texpr bb e; + bb + | TNew(c,tl,el) -> + let bb,el = ordered_value_list bb el in + add_texpr bb {e with eexpr = TNew(c,tl,el)}; + bb + | TCast(e1,Some mt) -> + let b,e1 = value bb e1 in + add_texpr bb {e with eexpr = TCast(e1,Some mt)}; + bb + | TBinop(OpAssignOp op,({eexpr = TArray(e1,e2)} as ea),e3) -> + let bb,_ = array_assign_op bb op e ea e1 e2 e3 in + bb + | TBinop(OpAssignOp op,({eexpr = TField(e1,fa)} as ef),e2) -> + let bb,_ = field_assign_op bb op e ef e1 fa e2 in + bb + | TBinop(OpAssign,({eexpr = TArray(e1,e2)} as ea),e3) -> + let bb,e1,e2,e3 = match ordered_value_list bb [e1;e2;e3] with + | bb,[e1;e2;e3] -> bb,e1,e2,e3 + | _ -> assert false + in + add_texpr bb {e with eexpr = TBinop(OpAssign,{ea with eexpr = TArray(e1,e2)},e3)}; + bb + | TBinop((OpAssign | OpAssignOp _ as op),e1,e2) -> + let bb,e1 = value bb e1 in + let bb,e2 = value bb e2 in + add_texpr bb {e with eexpr = TBinop(op,e1,e2)}; + bb + | TUnop((Increment | Decrement as op),flag,e1) -> + let bb,e1 = value bb e1 in + add_texpr bb {e with eexpr = TUnop(op,flag,e1)}; + bb + | TLocal _ when not ctx.config.AnalyzerConfig.local_dce -> + add_texpr bb e; + bb + (* no-side-effect *) + | TEnumParameter _ | TFunction _ | TConst _ | TTypeExpr _ | TLocal _ -> + bb + (* no-side-effect composites *) + | TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) | TField(e1,_) | TUnop(_,_,e1) -> + block_element bb e1 + | TArray(e1,e2) | TBinop(_,e1,e2) -> + let bb = block_element bb e1 in + block_element bb e2 + | TArrayDecl el -> + block_el bb el + | TObjectDecl fl -> + block_el bb (List.map snd fl) + | TFor _ | TWhile(_,_,DoWhile) -> + assert false + and block_el bb el = + match !b_try_stack with + | [] -> + let rec loop bb el = match el with + | [] -> bb + | e :: el -> + let bb = block_element bb e in + if bb == g.g_unreachable then bb else loop bb el + in + loop bb el + | bbl -> + let rec loop bb el = match el with + | [] -> bb + | e :: el -> + let bb = if not (can_throw e) then + block_element bb e + else begin + let bb' = create_node BKNormal e.etype e.epos in + add_cfg_edge bb bb' CFGGoto; + List.iter (fun bb_exc -> add_cfg_edge bb bb_exc CFGMaybeThrow) bbl; + set_syntax_edge bb (SEMerge bb'); + close_node g bb; + block_element bb' e + end in + if bb == g.g_unreachable then bb else loop bb el + in + loop bb el + and block bb e = + let el = match e.eexpr with + | TBlock el -> el + | _ -> [e] + in + block_el bb el + in + let bb_last = block bb_root tf.tf_expr in + close_node g bb_last; + add_cfg_edge bb_last bb_exit CFGGoto; (* implied return *) + close_node g bb_exit; + bb_root,bb_exit + +let from_tfunction ctx tf t p = + let g = ctx.graph in + let bb_func,bb_exit = func ctx g.g_root tf t p in + ctx.entry <- bb_func; + close_node g g.g_root; + g.g_exit <- bb_exit; + set_syntax_edge bb_exit SEEnd + +let rec block_to_texpr_el ctx bb = + if bb.bb_dominator == ctx.graph.g_unreachable then + [] + else begin + let block bb = block_to_texpr ctx bb in + let rec loop bb se = + let el = List.rev (DynArray.to_list bb.bb_el) in + match el,se with + | el,SESubBlock(bb_sub,bb_next) -> + Some bb_next,(block bb_sub) :: el + | el,SEMerge bb_next -> + Some bb_next,el + | el,(SEEnd | SENone) -> + None,el + | {eexpr = TWhile(e1,_,flag)} as e :: el,(SEWhile(_,bb_body,bb_next)) -> + let e2 = block bb_body in + Some bb_next,{e with eexpr = TWhile(e1,e2,flag)} :: el + | el,SETry(bb_try,_,bbl,bb_next,p) -> + Some bb_next,(mk (TTry(block bb_try,List.map (fun (v,bb) -> v,block bb) bbl)) ctx.com.basic.tvoid p) :: el + | e1 :: el,se -> + let e1 = Texpr.skip e1 in + let bb_next,e1_def,t,p = match se with + | SEIfThen(bb_then,bb_next,p) -> Some bb_next,TIf(e1,block bb_then,None),ctx.com.basic.tvoid,p + | SEIfThenElse(bb_then,bb_else,bb_next,t,p) -> Some bb_next,TIf(e1,block bb_then,Some (block bb_else)),t,p + | SESwitch(bbl,bo,bb_next,p) -> Some bb_next,TSwitch(e1,List.map (fun (el,bb) -> el,block bb) bbl,Option.map block bo),ctx.com.basic.tvoid,p + | _ -> abort (Printf.sprintf "Invalid node exit: %s" (s_expr_pretty e1)) bb.bb_pos + in + bb_next,(mk e1_def t p) :: el + | [],_ -> + None,[] + in + let bb_next,el = loop bb bb.bb_syntax_edge in + let el = match bb_next with + | None -> el + | Some bb -> (block_to_texpr_el ctx bb) @ el + in + el + end + +and block_to_texpr ctx bb = + assert(bb.bb_closed); + let el = block_to_texpr_el ctx bb in + let e = mk (TBlock (List.rev el)) bb.bb_type bb.bb_pos in + e + +and func ctx i = + let bb,t,p,tf = Hashtbl.find ctx.graph.g_functions i in + let e = block_to_texpr ctx bb in + let rec loop e = match e.eexpr with + | TLocal v when not (is_unbound v) -> + {e with eexpr = TLocal (get_var_origin ctx.graph v)} + | TVar(v,eo) when not (is_unbound v) -> + let eo = Option.map loop eo in + let v' = get_var_origin ctx.graph v in + {e with eexpr = TVar(v',eo)} + | TBinop(OpAssign,e1,({eexpr = TBinop(op,e2,e3)} as e4)) when target_handles_assign_ops ctx.com -> + let e1 = loop e1 in + let e2 = loop e2 in + let e3 = loop e3 in + let is_valid_assign_op = function + | OpAdd | OpMult | OpDiv | OpSub | OpAnd + | OpOr | OpXor | OpShl | OpShr | OpUShr | OpMod -> + true + | OpAssignOp _ | OpInterval | OpArrow | OpAssign | OpEq + | OpNotEq | OpGt | OpGte | OpLt | OpLte | OpBoolAnd | OpBoolOr -> + false + in + begin match e1.eexpr,e2.eexpr with + | TLocal v1,TLocal v2 when v1 == v2 && not v1.v_capture && is_valid_assign_op op -> + begin match op,e3.eexpr with + | OpAdd,TConst (TInt i32) when Int32.to_int i32 = 1 && target_handles_assign_ops ctx.com -> {e with eexpr = TUnop(Increment,Prefix,e1)} + | OpSub,TConst (TInt i32) when Int32.to_int i32 = 1 && target_handles_assign_ops ctx.com -> {e with eexpr = TUnop(Decrement,Prefix,e1)} + | _ -> {e with eexpr = TBinop(OpAssignOp op,e1,e3)} + end + | _ -> + {e with eexpr = TBinop(OpAssign,e1,{e4 with eexpr = TBinop(op,e2,e3)})} + end + | TCall({eexpr = TConst (TString "fun")},[{eexpr = TConst (TInt i32)}]) -> + func ctx (Int32.to_int i32) + | TCall({eexpr = TLocal v},_) when is_really_unbound v -> + e + | _ -> + Type.map_expr loop e + in + let e = loop e in + mk (TFunction {tf with tf_expr = e}) t p + +let to_texpr ctx = + func ctx ctx.entry.bb_id \ No newline at end of file diff --git a/src/optimization/analyzerTypes.ml b/src/optimization/analyzerTypes.ml new file mode 100644 index 00000000..04d70995 --- /dev/null +++ b/src/optimization/analyzerTypes.ml @@ -0,0 +1,526 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Globals +open Ast +open Type +open Common + +(* + A BasicBlock represents a node in the control flow. It has expression elements similar to TBlock in the AST, + but also holds additional information related to control flow and variables. + + Basic blocks are created whenever it is relevant for control flow. They differ from TBlock in that only their + final element can be a control flow expression (the terminator). As a consequence, a given TBlock is split up + into several basic blocks when control flow expressions are encountered. +*) +module BasicBlock = struct + type block_kind = + | BKRoot (* The unique root block of the graph *) + | BKNormal (* A normal block *) + | BKFunctionBegin of tfunc (* Entry block of a function *) + | BKFunctionEnd (* Exit block of a function *) + | BKSub (* A sub block *) + | BKConditional (* A "then", "else" or "case" block *) + | BKLoopHead (* Header block of a loop *) + | BKException (* Relay block for exceptions *) + | BKUnreachable (* The unique unreachable block *) + | BKCatch of tvar (* A catch block *) + + type cfg_edge_Flag = + | FlagExecutable (* Used by constant propagation to handle live edges *) + | FlagDce (* Used by DCE to keep track of handled edges *) + | FlagCopyPropagation (* Used by copy propagation to track handled eges *) + + type cfg_edge_kind = + | CFGGoto (* An unconditional branch *) + | CFGFunction (* Link to a function *) + | CFGMaybeThrow (* The block may or may not throw an exception *) + | CFGCondBranch of texpr (* A conditional branch *) + | CFGCondElse (* A conditional alternative (else,default) *) + + and cfg_edge = { + cfg_from : t; (* The source block *) + cfg_to : t; (* The target block *) + cfg_kind : cfg_edge_kind; (* The edge kind *) + mutable cfg_flags : cfg_edge_Flag list; (* Edge flags *) + } + + and syntax_edge = + | SEIfThen of t * t * pos (* `if` with "then" and "next" *) + | SEIfThenElse of t * t * t * Type.t * pos (* `if` with "then", "else" and "next" *) + | SESwitch of (texpr list * t) list * t option * t * pos (* `switch` with cases, "default" and "next" *) + | SETry of t * t * (tvar * t) list * t * pos (* `try` with "exc", catches and "next" *) + | SEWhile of t * t * t (* `while` with "head", "body" and "next" *) + | SESubBlock of t * t (* "sub" with "next" *) + | SEMerge of t (* Merge to same block *) + | SEEnd (* End of syntax *) + | SENone (* No syntax exit *) + + and t = { + bb_id : int; (* The unique ID of the block *) + bb_type : Type.t; (* The block type *) + bb_pos : pos; (* The block position *) + bb_kind : block_kind; (* The block kind *) + mutable bb_closed : bool; (* Whether or not the block has been closed *) + (* elements *) + bb_el : texpr DynArray.t; (* The block expressions *) + bb_phi : texpr DynArray.t; (* SSA-phi expressions *) + (* relations *) + mutable bb_outgoing : cfg_edge list; (* Outgoing edges *) + mutable bb_incoming : cfg_edge list; (* Incoming edges *) + mutable bb_dominator : t; (* The block's dominator *) + mutable bb_dominated : t list; (* The dominated blocks *) + mutable bb_df : t list; (* The dominance frontier *) + mutable bb_syntax_edge : syntax_edge; (* The syntactic edge *) + mutable bb_loop_groups : int list; (* The loop groups this block belongs to *) + mutable bb_scopes : int list; (* The scopes this block belongs to *) + (* variables *) + mutable bb_var_writes : tvar list; (* List of assigned variables *) + } + + let s_block_kind = function + | BKRoot -> "BKRoot" + | BKNormal -> "BKNormal" + | BKFunctionBegin _ -> "BKFunctionBegin" + | BKFunctionEnd -> "BKFunctionEnd" + | BKSub -> "BKSub" + | BKConditional -> "BKConditional" + | BKLoopHead -> "BKLoopHead" + | BKException -> "BKException" + | BKUnreachable -> "BKUnreachable" + | BKCatch _ -> "BKCatch" + + let s_cfg_edge_kind = function + | CFGGoto -> "CFGGoto" + | CFGFunction -> "CFGFunction" + | CFGMaybeThrow -> "CFGMaybeThrow" + | CFGCondBranch e -> "CFGCondBranch " ^ (s_expr_pretty false "" false (s_type (print_context())) e) + | CFGCondElse -> "CFGCondElse" + + let has_flag edge flag = + List.mem flag edge.cfg_flags + + (* expressions *) + + let add_texpr bb e = + DynArray.add bb.bb_el e + + let get_texpr bb is_phi i = + DynArray.get (if is_phi then bb.bb_phi else bb.bb_el) i + + (* edges *) + + let set_syntax_edge bb se = + bb.bb_syntax_edge <- se + + let add_cfg_edge bb_from bb_to kind = + if bb_from.bb_kind <> BKUnreachable then begin + let edge = { cfg_from = bb_from; cfg_to = bb_to; cfg_kind = kind; cfg_flags = [] } in + bb_from.bb_outgoing <- edge :: bb_from.bb_outgoing; + bb_to.bb_incoming <- edge :: bb_to.bb_incoming; + end + + let _create id kind t p = + let rec bb = { + bb_kind = kind; + bb_id = id; + bb_type = t; + bb_pos = p; + bb_closed = false; + bb_el = DynArray.create(); + bb_phi = DynArray.create(); + bb_outgoing = []; + bb_incoming = []; + bb_dominator = bb; + bb_dominated = []; + bb_df = []; + bb_syntax_edge = SENone; + bb_loop_groups = []; + bb_var_writes = []; + bb_scopes = []; + } in + bb + + let in_scope bb bb' = match bb'.bb_scopes with + | [] -> abort (Printf.sprintf "Scope-less block (kind: %s)" (s_block_kind bb'.bb_kind)) bb'.bb_pos + | scope :: _ -> List.mem scope bb.bb_scopes +end + +(* + A Graph contains all relevant information for a given method. It is built from the field expression + and then refined in subsequent modules such as Ssa. +*) +module Graph = struct + open BasicBlock + + type texpr_lookup = BasicBlock.t * bool * int + type tfunc_info = BasicBlock.t * Type.t * pos * tfunc + type var_write = BasicBlock.t list + type 'a itbl = (int,'a) Hashtbl.t + + type var_info = { + vi_var : tvar; (* The variable itself *) + vi_extra : tvar_extra; (* The original v_extra *) + vi_bb_declare : BasicBlock.t; (* The block where this variable was declared *) + mutable vi_origin : tvar; (* The origin variable of this variable *) + mutable vi_writes : var_write; (* A list of blocks that assign to this variable *) + mutable vi_value : texpr_lookup option; (* The value of this variable, if known *) + mutable vi_ssa_edges : texpr_lookup list; (* The expressions this variable influences *) + mutable vi_reaching_def : tvar option; (* The current reaching definition variable of this variable *) + } + + type t = { + mutable g_root : BasicBlock.t; (* The unique root block *) + mutable g_exit : BasicBlock.t; (* The unique exit block *) + mutable g_unreachable : BasicBlock.t; (* The unique unreachable block *) + mutable g_functions : tfunc_info itbl; (* A map of functions, indexed by their block IDs *) + mutable g_nodes : BasicBlock.t list; (* A list of all blocks *) + g_var_infos : var_info DynArray.t; (* A map of variable information *) + mutable g_loops : BasicBlock.t IntMap.t; (* A map containing loop information *) + } + + (* variables *) + + let create_var_info g bb v = + let vi = { + vi_var = v; + vi_extra = v.v_extra; + vi_bb_declare = bb; + vi_origin = v; + vi_writes = []; + vi_value = None; + vi_ssa_edges = []; + vi_reaching_def = None; + } in + DynArray.add g.g_var_infos vi; + let i = DynArray.length g.g_var_infos - 1 in + v.v_extra <- Some([],Some (mk (TConst (TInt (Int32.of_int i))) t_dynamic null_pos)) + + let get_var_info g v = match v.v_extra with + | Some(_,Some {eexpr = TConst (TInt i32)}) -> DynArray.get g.g_var_infos (Int32.to_int i32) + | _ -> + prerr_endline "Unbound variable, please report this"; + prerr_endline (Printer.s_tvar v); + assert false + + let declare_var g v bb = + create_var_info g bb v + + let add_var_def g bb v = + if bb.bb_id > 0 then begin + bb.bb_var_writes <- v :: bb.bb_var_writes; + let vi = get_var_info g v in + vi.vi_writes <- bb :: vi.vi_writes; + end + + let set_var_value g v bb is_phi i = + (get_var_info g v).vi_value <- Some (bb,is_phi,i) + + let get_var_value g v = + let value = (get_var_info g v).vi_value in + let bb,is_phi,i = match value with + | None -> raise Not_found + | Some l -> l + in + match (get_texpr bb is_phi i).eexpr with + | TVar(_,Some e) | TBinop(OpAssign,_,e) -> e + | _ -> assert false + + let add_var_origin g v v_origin = + (get_var_info g v).vi_origin <- v_origin + + let get_var_origin g v = + (get_var_info g v).vi_origin + + let add_ssa_edge g v bb is_phi i = + let vi = get_var_info g v in + vi.vi_ssa_edges <- (bb,is_phi,i) :: vi.vi_ssa_edges + + (* nodes *) + + let add_function g tf t p bb = + Hashtbl.add g.g_functions bb.bb_id (bb,t,p,tf) + + let alloc_id = + let r = ref 1 in + (fun () -> + incr r; + !r + ) + + let create_node g kind t p = + let bb = BasicBlock._create (alloc_id()) kind t p in + g.g_nodes <- bb :: g.g_nodes; + bb + + let close_node g bb = + if bb.bb_id > 0 then begin + assert(not bb.bb_closed); + bb.bb_closed <- true + end + + let iter_dom_tree_from g bb f = + let rec loop bb = + f bb; + List.iter loop bb.bb_dominated + in + loop bb + + let iter_dom_tree g f = + iter_dom_tree_from g g.g_root f + + let iter_edges_from g bb f = + iter_dom_tree_from g bb (fun bb -> List.iter f bb.bb_outgoing) + + let iter_edges g f = + iter_dom_tree g (fun bb -> List.iter f bb.bb_outgoing) + + (* graph *) + + let create t p = + let bb_root = BasicBlock._create 1 BKRoot t p; in + let bb_unreachable = BasicBlock._create 0 BKUnreachable t_dynamic null_pos in + { + g_root = bb_root; + g_exit = bb_unreachable; + g_unreachable = bb_unreachable; + g_functions = Hashtbl.create 0; + g_nodes = [bb_root]; + g_var_infos = DynArray.create(); + g_loops = IntMap.empty; + } + + let check_integrity g = + List.iter (fun bb -> + List.iter (fun edge -> + if edge.cfg_to = g.g_unreachable then + prerr_endline (Printf.sprintf "Outgoing edge from %i to the unreachable block" bb.bb_id) + else if not (List.memq edge edge.cfg_to.bb_incoming) then + prerr_endline (Printf.sprintf "Outgoing edge %i -> %i has no matching incoming edge" edge.cfg_from.bb_id edge.cfg_to.bb_id) + ) bb.bb_outgoing; + List.iter (fun edge -> + if edge.cfg_from == g.g_unreachable then + prerr_endline (Printf.sprintf "Incoming edge to %i from the unreachable block" bb.bb_id) + else if not (List.memq edge edge.cfg_from.bb_outgoing) then + prerr_endline (Printf.sprintf "Incoming edge %i <- %i has no matching outgoing edge" edge.cfg_to.bb_id edge.cfg_from.bb_id) + ) bb.bb_incoming + ) g.g_nodes + + (* inference *) + + type dom_bb_info = { + bb : BasicBlock.t; + parent : dom_bb_info; + mutable idom : dom_bb_info; + mutable semi : int; + mutable label : dom_bb_info; + mutable ancestor : dom_bb_info; + mutable bucket : dom_bb_info list; + } + + (* Infers the immediate dominators for all reachable blocks. This function can be run multiple times + in case an update is necessary. *) + let infer_immediate_dominators g = + let info = Hashtbl.create 0 in + let nodes = DynArray.create () in + let get_info i = Hashtbl.find info i in + let add_info bb bb_parent = + let rec bbi = { + bb = bb; + parent = bbi; + idom = bbi; + semi = DynArray.length nodes; + label = bbi; + ancestor = bbi; + bucket = []; + } in + let bbi = if bb == bb_parent then bbi else {bbi with parent = get_info bb_parent.bb_id} in + Hashtbl.add info bb.bb_id bbi; + DynArray.add nodes bbi; + in + let rec loop bb_parent bb = + bb.bb_dominated <- []; + add_info bb bb_parent; + List.iter (fun edge -> + let bb_to = edge.cfg_to in + if not (Hashtbl.mem info bb_to.bb_id) then + loop bb bb_to + ) bb.bb_outgoing + in + loop g.g_root g.g_root; + let compress bbi = + let rec loop l bbi = + if bbi.ancestor == bbi then l else loop (bbi :: l) bbi.ancestor + in + let worklist = loop [bbi] bbi.ancestor in + match worklist with + | a :: worklist -> + ignore(List.fold_left (fun (a,min_semi) bbi_desc -> + let bbi = bbi_desc.label in + if bbi.semi > min_semi then begin + bbi_desc.label <- a.label; + (bbi_desc,min_semi) + end else + (bbi_desc,bbi.semi) + ) (a,a.label.semi) worklist) + | [] -> + assert false + in + let eval v = + let bbi = get_info v in + if bbi.ancestor != bbi then begin + compress bbi; + bbi.label + end else + bbi + in + let rec loop nodes' = match nodes' with + | [_] -> () + | [] -> assert false + | w :: nodes' -> + let semi = List.fold_left (fun acc v -> + min acc (eval v.cfg_from.bb_id).semi) w.semi w.bb.bb_incoming + in + w.semi <- semi; + let bbi = DynArray.get nodes semi in + bbi.bucket <- w :: bbi.bucket; + let bbi_p = w.parent in + w.ancestor <- bbi_p; + List.iter (fun v -> + let u = eval v.bb.bb_id in + if u.semi < v.semi then + v.idom <- u + else + v.idom <- bbi_p + ) bbi_p.bucket; + bbi_p.bucket <- []; + loop nodes' + in + let l = DynArray.to_list nodes in + loop (List.rev l); + List.iter (fun w -> + if w.idom != (DynArray.get nodes w.semi) then w.idom <- w.idom.idom + ) (List.tl l); + DynArray.iter (fun bbi -> + if bbi.idom != bbi then begin + let bb = bbi.bb in + let bb' = bbi.idom.bb in + if bb != bb' then begin + bb.bb_dominator <- bb'; + bb'.bb_dominated <- bb :: bb'.bb_dominated + end + end + ) nodes + + (* Infers the dominance frontier for all reachable blocks. This function should only be run once. *) + let infer_dominance_frontier g = + iter_edges g (fun edge -> + let rec loop bb = + if bb != g.g_unreachable && bb != edge.cfg_to && bb != edge.cfg_to.bb_dominator then begin + if edge.cfg_to != g.g_exit then bb.bb_df <- edge.cfg_to :: bb.bb_df; + if bb.bb_dominator != bb then loop bb.bb_dominator + end + in + loop edge.cfg_from + ) + + (* Infers variable declarations and definitions. This function should only be run once. *) + let infer_var_writes g = + iter_dom_tree g (fun bb -> + begin match bb.bb_kind with + | BKCatch v -> + declare_var g v bb; + add_var_def g bb v + | BKFunctionBegin tf -> + List.iter (fun (v,_) -> + declare_var g v bb; + add_var_def g bb v + ) tf.tf_args; + | _ -> + () + end; + DynArray.iter (fun e -> match e.eexpr with + | TVar(v,eo) when not (is_unbound v) -> + declare_var g v bb; + if eo <> None then add_var_def g bb v; + | TBinop(OpAssign,{eexpr = TLocal v},_) when not (is_unbound v) -> + add_var_def g bb v + | _ -> + () + ) bb.bb_el + ) + + (* Infers the scopes of all reachable blocks. This function can be run multiple times + in case an update is necessary *) + let infer_scopes g = + let next_scope_id = ref 0 in + let next_scope scopes = + incr next_scope_id; + !next_scope_id :: scopes + in + let rec loop scopes bb = + bb.bb_scopes <- scopes; + begin match bb.bb_syntax_edge with + | SEIfThen(bb_then,bb_next,_) -> + loop (next_scope scopes) bb_then; + loop scopes bb_next + | SEIfThenElse(bb_then,bb_else,bb_next,_,_) -> + loop (next_scope scopes) bb_then; + loop (next_scope scopes) bb_else; + loop scopes bb_next + | SESwitch(cases,bbo,bb_next,_) -> + List.iter (fun (_,bb_case) -> loop (next_scope scopes) bb_case) cases; + (match bbo with None -> () | Some bb -> loop (next_scope scopes) bb); + loop scopes bb_next; + | SETry(bb_try,bb_exc,catches,bb_next,_) -> + let scopes' = next_scope scopes in + loop scopes' bb_try; + loop scopes' bb_exc; + List.iter (fun (_,bb_catch) -> loop (next_scope scopes) bb_catch) catches; + loop scopes bb_next + | SEWhile(bb_head,bb_body,bb_next) -> + let scopes' = next_scope scopes in + loop scopes' bb_head; + loop scopes' bb_body; + loop scopes bb_next; + | SESubBlock(bb_sub,bb_next) -> + loop (next_scope scopes) bb_sub; + loop scopes bb_next + | SEMerge bb -> + loop scopes bb + | SEEnd | SENone -> + () + end + in + Hashtbl.iter (fun _ (bb,_,_,_) -> loop [0] bb) g.g_functions +end + +type analyzer_context = { + com : Common.context; + config : AnalyzerConfig.t; + graph : Graph.t; + temp_var_name : string; + mutable entry : BasicBlock.t; + mutable has_unbound : bool; + mutable loop_counter : int; + mutable loop_stack : int list; + mutable debug_exprs : (string * texpr) list; + mutable name_stack : string list; +} \ No newline at end of file diff --git a/dce.ml b/src/optimization/dce.ml similarity index 76% rename from dce.ml rename to src/optimization/dce.ml index ca34d26b..40f757dc 100644 --- a/dce.ml +++ b/src/optimization/dce.ml @@ -1,28 +1,26 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Ast open Common open Type +open Globals type dce = { com : context; @@ -30,6 +28,7 @@ type dce = { std_dirs : string list; debug : bool; follow_expr : dce -> texpr -> unit; + dependent_types : (string list * string,module_type list) Hashtbl.t; mutable curclass : tclass; mutable added_fields : (tclass * tclass_field * bool) list; mutable marked_fields : tclass_field list; @@ -57,6 +56,7 @@ let keep_whole_class dce c = || super_forces_keep c || (match c with | { cl_path = ([],("Math"|"Array"))} when dce.com.platform = Js -> false + | { cl_path = ([],("Math"|"Array"|"String"))} when dce.com.platform = Lua -> false | { cl_extern = true } | { cl_path = ["flash";"_Boot"],"RealBoot" } -> true | { cl_path = [],"String" } @@ -88,7 +88,7 @@ let rec check_feature dce s = and check_and_add_feature dce s = check_feature dce s; - Common.add_feature dce.com s; + Hashtbl.replace dce.curclass.cl_module.m_extra.m_features s true (* mark a field as kept *) and mark_field dce c cf stat = @@ -101,23 +101,24 @@ and mark_field dce c cf stat = end in if cf.cf_name = "new" then begin - let rec loop c = match c.cl_super with - | None -> () - | Some (csup,_) -> - begin match csup.cl_constructor with - | None -> () + let rec loop c = + begin match c.cl_constructor with | Some cf -> add cf - end; - loop csup + | None -> () + end; + match c.cl_super with + | Some(csup,_) -> loop csup + | None -> () in loop c - end; - if not (PMap.mem cf.cf_name (if stat then c.cl_statics else c.cl_fields)) then begin - match c.cl_super with - | None -> add cf - | Some (c,_) -> mark_field dce c cf stat - end else - add cf + end else begin + if not (PMap.mem cf.cf_name (if stat then c.cl_statics else c.cl_fields)) then begin + match c.cl_super with + | None -> add cf + | Some (c,_) -> mark_field dce c cf stat + end else + add cf + end let rec update_marked_class_fields dce c = (* mark all :?used fields as surely :used now *) @@ -141,7 +142,11 @@ end let rec mark_enum dce e = if not (Meta.has Meta.Used e.e_meta) then begin e.e_meta <- (Meta.Used,[],e.e_pos) :: e.e_meta; - check_and_add_feature dce "has_enum"; + + (* do not generate has_enum feature for @:fakeEnum enums since they are not really enums *) + if not (Meta.has Meta.FakeEnum e.e_meta) then + check_and_add_feature dce "has_enum"; + check_feature dce (Printf.sprintf "%s.*" (s_type_path e.e_path)); PMap.iter (fun _ ef -> mark_t dce ef.ef_pos ef.ef_type) e.e_constrs; end @@ -173,8 +178,8 @@ and mark_t dce p t = List.iter (mark_t dce p) pl | TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta -> begin try - mark_t dce p (snd (Codegen.AbstractCast.find_multitype_specialization dce.com a pl p)) - with Typecore.Error _ -> + mark_t dce p (snd (Typecore.AbstractCast.find_multitype_specialization dce.com a pl p)) + with Error.Error _ -> () end | TAbstract(a,pl) -> @@ -201,6 +206,13 @@ let mark_mt dce mt = match mt with (* find all dependent fields by checking implementing/subclassing types *) let rec mark_dependent_fields dce csup n stat = + let dependent = try + Hashtbl.find dce.dependent_types csup.cl_path + with Not_found -> + let cl = List.filter (fun mt -> match mt with TClassDecl c -> is_parent csup c | _ -> false) dce.com.types in + Hashtbl.add dce.dependent_types csup.cl_path cl; + cl + in List.iter (fun mt -> match mt with | TClassDecl c when is_parent csup c -> let rec loop c = @@ -220,7 +232,7 @@ let rec mark_dependent_fields dce csup n stat = in loop c | _ -> () - ) dce.com.types + ) dependent (* expr and field evaluation *) @@ -305,6 +317,27 @@ and mark_directly_used_mt mt = | _ -> () +and mark_directly_used_t com p t = + match follow t with + | TInst({cl_kind = KNormal} as c,pl) -> + mark_directly_used_class c; + List.iter (mark_directly_used_t com p) pl + | TEnum(e,pl) -> + mark_directly_used_enum e; + List.iter (mark_directly_used_t com p) pl + | TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta -> + begin try (* this is copy-pasted from mark_t *) + mark_directly_used_t com p (snd (Typecore.AbstractCast.find_multitype_specialization com a pl p)) + with Error.Error _ -> + () + end + | TAbstract(a,pl) -> + List.iter (mark_directly_used_t com p) pl; + if not (Meta.has Meta.CoreType a.a_meta) then + mark_directly_used_t com p (Abstract.get_underlying_type a pl) + | _ -> + () + and check_dynamic_write dce fa = let n = field_name fa in check_and_add_feature dce ("dynamic_write"); @@ -339,6 +372,70 @@ and is_const_string e = match e.eexpr with | TConst(TString(_)) -> true | _ -> false +and expr_field dce e fa is_call_expr = + let do_default = fun () -> + let n = field_name fa in + (match fa with + | FAnon cf -> + if Meta.has Meta.Optional cf.cf_meta then begin + check_and_add_feature dce "anon_optional_read"; + check_and_add_feature dce ("anon_optional_read." ^ n); + end else begin + check_and_add_feature dce "anon_read"; + check_and_add_feature dce ("anon_read." ^ n); + end + | FDynamic _ -> + check_and_add_feature dce "dynamic_read"; + check_and_add_feature dce ("dynamic_read." ^ n); + | _ -> ()); + begin match follow e.etype with + | TInst(c,_) -> + mark_class dce c; + field dce c n false; + | TAnon a -> + (match !(a.a_status) with + | Statics c -> + mark_class dce c; + field dce c n true; + | _ -> ()) + + + | _ -> () + end + in + let mark_instance_field_access c cf = + if (not is_call_expr && dce.com.platform = Python) then begin + if c.cl_path = ([], "Array") then begin + check_and_add_feature dce "closure_Array"; + check_and_add_feature dce ("python.internal.ArrayImpl." ^ cf.cf_name); + check_and_add_feature dce ("python.internal.ArrayImpl") + end + else if c.cl_path = ([], "String") then begin + check_and_add_feature dce "closure_String"; + check_and_add_feature dce ("python.internal.StringImpl." ^ cf.cf_name); + check_and_add_feature dce ("python.internal.StringImpl") + end + end; + in + begin match fa with + | FStatic(c,cf) -> + mark_class dce c; + mark_field dce c cf true; + | FInstance(c,_,cf) -> + (*mark_instance_field_access c cf;*) + mark_class dce c; + mark_field dce c cf false + | FClosure (Some(c, _), cf) -> + mark_instance_field_access c cf; + do_default() + | FClosure _ -> + do_default() + | _ -> + do_default() + end; + expr dce e; + + and expr dce e = mark_t dce e.epos e.etype; match e.eexpr with @@ -365,7 +462,10 @@ and expr dce e = | TTry(e, vl) -> expr dce e; List.iter (fun (v,e) -> - if v.v_type != t_dynamic then check_feature dce "typed_catch"; + if v.v_type != t_dynamic then begin + check_feature dce "typed_catch"; + mark_directly_used_t dce.com v.v_pos v.v_type; + end; expr dce e; mark_t dce e.epos v.v_type; ) vl; @@ -403,11 +503,19 @@ and expr dce e = | TCall ({eexpr = TConst TSuper} as e,el) -> mark_t dce e.epos e.etype; List.iter (expr dce) el; + | TUnop((Increment | Decrement),_,({eexpr = TArray _} as e1)) -> + check_and_add_feature dce "array_write"; + check_and_add_feature dce "array_read"; + expr dce e1; | TBinop(OpAdd,e1,e2) when is_dynamic e1.etype || is_dynamic e2.etype -> check_and_add_feature dce "add_dynamic"; expr dce e1; expr dce e2; - | TBinop( (OpAdd | (OpAssignOp OpAdd)),e1,e2) when ((is_string e1.etype || is_string e2.etype) && not ( is_const_string e1 && is_const_string e2)) -> + | TBinop( (OpAdd | (OpAssignOp OpAdd)) as op,e1,e2) when ((is_string e1.etype || is_string e2.etype) && not ( is_const_string e1 && is_const_string e2)) -> + + (* add array_write if we're doing += to an array element, since this pattern comes before the array_write one *) + (match op, e1 with (OpAssignOp _, {eexpr = TArray({etype = t},_)}) when is_array t -> check_and_add_feature dce "array_write" | _ -> ()); + check_and_add_feature dce "unsafe_string_concat"; expr dce e1; expr dce e2; @@ -461,59 +569,44 @@ and expr dce e = check_and_add_feature dce "binop_%"; expr dce e1; expr dce e2; - | TBinop(OpUShr,e1,e2) -> + | TBinop((OpUShr | OpAssignOp OpUShr),e1,e2) -> check_and_add_feature dce "binop_>>>"; expr dce e1; expr dce e2; + | TCall(({ eexpr = TField(ef, fa) } as e2), el ) -> + mark_t dce e2.epos e2.etype; + expr_field dce ef fa true; + List.iter (expr dce) el; | TField(e,fa) -> - begin match fa with - | FStatic(c,cf) -> - mark_class dce c; - mark_field dce c cf true; - | FInstance(c,_,cf) -> - mark_class dce c; - mark_field dce c cf false; - | _ -> - - let n = field_name fa in - (match fa with - | FAnon cf -> - if Meta.has Meta.Optional cf.cf_meta then begin - check_and_add_feature dce "anon_optional_read"; - check_and_add_feature dce ("anon_optional_read." ^ n); - end else begin - check_and_add_feature dce "anon_read"; - check_and_add_feature dce ("anon_read." ^ n); - end - | FDynamic _ -> - check_and_add_feature dce "dynamic_read"; - check_and_add_feature dce ("dynamic_read." ^ n); - | _ -> ()); - begin match follow e.etype with - | TInst(c,_) -> - mark_class dce c; - field dce c n false; - | TAnon a -> - (match !(a.a_status) with - | Statics c -> - mark_class dce c; - field dce c n true; - | _ -> ()) - - - | _ -> () - end; - end; - expr dce e; + expr_field dce e fa false; | TThrow e -> check_and_add_feature dce "has_throw"; - to_string dce e.etype; - expr dce e + expr dce e; + (* + TODO: Simon, save me! \o + This is a hack needed to keep toString field of the actual exception objects + that are thrown, but are wrapped into HaxeError before DCE comes into play. + *) + let e = (match e.eexpr with + | TNew({cl_path=(["js";"_Boot"],"HaxeError")}, _, [eoriginal]) -> eoriginal + | _ -> e + ) in + to_string dce e.etype | _ -> Type.iter (expr dce) e let fix_accessors com = List.iter (fun mt -> match mt with + (* filter empty abstract implementation classes (issue #1885). *) + | TClassDecl({cl_kind = KAbstractImpl _} as c) when c.cl_ordered_statics = [] && c.cl_ordered_fields = [] && not (Meta.has Meta.Used c.cl_meta) -> + c.cl_extern <- true + | TClassDecl({cl_kind = KAbstractImpl a} as c) when Meta.has Meta.Enum a.a_meta -> + let is_runtime_field cf = + not (Meta.has Meta.Enum cf.cf_meta) + in + (* also filter abstract implementation classes that have only @:enum fields (issue #2858) *) + if not (List.exists is_runtime_field c.cl_ordered_statics) then + c.cl_extern <- true | (TClassDecl c) -> let rec has_accessor c n stat = PMap.mem n (if stat then c.cl_statics else c.cl_fields) @@ -540,7 +633,8 @@ let run com main full = let dce = { com = com; full = full; - std_dirs = if full then [] else List.map Common.unique_full_path com.std_path; + dependent_types = Hashtbl.create 0; + std_dirs = if full then [] else List.map Path.unique_full_path com.std_path; debug = Common.defined com Define.DceDebug; added_fields = []; follow_expr = expr; @@ -552,7 +646,7 @@ let run com main full = curclass = null_class; } in begin match main with - | Some {eexpr = TCall({eexpr = TField(e,(FStatic(c,cf)))},_)} -> + | Some {eexpr = TCall({eexpr = TField(e,(FStatic(c,cf)))},_)} | Some {eexpr = TBlock ({ eexpr = TCall({eexpr = TField(e,(FStatic(c,cf)))},_)} :: _)} -> cf.cf_meta <- (Meta.Keep,[],cf.cf_pos) :: cf.cf_meta | _ -> () @@ -579,7 +673,7 @@ let run com main full = begin match c.cl_init with | Some e when keep_class || Meta.has Meta.KeepInit c.cl_meta -> (* create a fake field to deal with our internal logic (issue #3286) *) - let cf = mk_field "__init__" e.etype e.epos in + let cf = mk_field "__init__" e.etype e.epos null_pos in cf.cf_expr <- Some e; loop true cf | _ -> @@ -714,7 +808,9 @@ let run com main full = | _ -> () ) com.types; - (* mark extern classes as really used if they are extended by non-extern ones *) + (* + Mark extern classes as really used if they are extended by non-extern ones. + *) List.iter (function | TClassDecl ({cl_extern = false; cl_super = Some ({cl_extern = true} as csup, _)}) -> mark_directly_used_class csup @@ -730,6 +826,4 @@ let run com main full = | x :: l -> x :: remove_meta m l in List.iter (fun cf -> cf.cf_meta <- remove_meta Meta.Used cf.cf_meta) dce.marked_fields; - List.iter (fun cf -> cf.cf_meta <- remove_meta Meta.MaybeUsed cf.cf_meta) dce.marked_maybe_fields; - - + List.iter (fun cf -> cf.cf_meta <- remove_meta Meta.MaybeUsed cf.cf_meta) dce.marked_maybe_fields diff --git a/filters.ml b/src/optimization/filters.ml similarity index 70% rename from filters.ml rename to src/optimization/filters.ml index a8d557e4..9d1bbea9 100644 --- a/filters.ml +++ b/src/optimization/filters.ml @@ -1,107 +1,31 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + open Ast open Common open Type open Typecore +open Error +open Globals (* PASS 1 begin *) -let rec verify_ast e = match e.eexpr with - | TField(_) -> - () - | TTypeExpr(TClassDecl {cl_kind = KAbstractImpl a}) when not (Meta.has Meta.RuntimeValue a.a_meta) -> - error "Cannot use abstract as value" e.epos - | _ -> - Type.iter verify_ast e - -(* - Wraps implicit blocks in TIf, TFor, TWhile, TFunction and TTry with real ones -*) -let rec blockify_ast e = - match e.eexpr with - | TIf(e1,e2,eo) -> - {e with eexpr = TIf(blockify_ast e1,mk_block (blockify_ast e2),match eo with None -> None | Some e -> Some (mk_block (blockify_ast e)))} - | TFor(v,e1,e2) -> - {e with eexpr = TFor(v,blockify_ast e1,mk_block (blockify_ast e2))} - | TWhile(e1,e2,flag) -> - {e with eexpr = TWhile(blockify_ast e1,mk_block (blockify_ast e2),flag)} - | TFunction tf -> - {e with eexpr = TFunction {tf with tf_expr = mk_block (blockify_ast tf.tf_expr)}} - | TTry(e1,cl) -> - {e with eexpr = TTry(mk_block (blockify_ast e1),List.map (fun (v,e) -> v,mk_block (blockify_ast e)) cl)} - | TSwitch(e1,cases,def) -> - let e1 = blockify_ast e1 in - let cases = List.map (fun (el,e) -> - el,mk_block (blockify_ast e) - ) cases in - let def = match def with None -> None | Some e -> Some (mk_block (blockify_ast e)) in - {e with eexpr = TSwitch(e1,cases,def)} - | _ -> - Type.map_expr blockify_ast e - -(* - Pushes complex right-hand side expression inwards. - - return { exprs; value; } -> { exprs; return value; } - x = { exprs; value; } -> { exprs; x = value; } - var x = { exprs; value; } -> { var x; exprs; x = value; } -*) -let promote_complex_rhs com e = - let rec is_complex e = match e.eexpr with - | TBlock _ | TSwitch _ | TIf _ | TTry _ | TCast(_,Some _) -> true - | TBinop(_,e1,e2) -> is_complex e1 || is_complex e2 - | TParenthesis e | TMeta(_,e) | TCast(e, None) | TField(e,_) -> is_complex e - | _ -> false - in - let rec loop f e = match e.eexpr with - | TBlock(el) -> - begin match List.rev el with - | elast :: el -> {e with eexpr = TBlock(block (List.rev ((loop f elast) :: el)))} - | [] -> e - end - | TSwitch(es,cases,edef) -> - {e with eexpr = TSwitch(es,List.map (fun (el,e) -> List.map find el,loop f e) cases,match edef with None -> None | Some e -> Some (loop f e)); } - | TIf(eif,ethen,eelse) -> - {e with eexpr = TIf(find eif, loop f ethen, match eelse with None -> None | Some e -> Some (loop f e)); } - | TTry(e1,el) -> - {e with eexpr = TTry(loop f e1, List.map (fun (el,e) -> el,loop f e) el); } - | TParenthesis e1 when not (Common.defined com Define.As3) -> - {e with eexpr = TParenthesis(loop f e1)} - | TMeta(m,e1) -> - { e with eexpr = TMeta(m,loop f e1)} - | TReturn _ | TThrow _ -> - find e - | TContinue | TBreak -> - e - | _ -> - f (find e) - and block el = - let r = ref [] in - List.iter (fun e -> - match e.eexpr with - | TVar(v,eo) -> - begin match eo with - | Some e when is_complex e -> - let e = find e in - r := (loop (fun e -> mk (TBinop(OpAssign,mk (TLocal v) v.v_type e.epos,e)) v.v_type e.epos) e) - :: ((mk (TVar (v,None)) com.basic.tvoid e.epos)) - :: !r - | Some e -> - r := (mk (TVar (v,Some (find e))) com.basic.tvoid e.epos) :: !r - | None -> r := (mk (TVar (v,None)) com.basic.tvoid e.epos) :: !r - end - | TReturn (Some e1) when (match follow e1.etype with TAbstract({a_path=[],"Void"},_) -> true | _ -> false) -> - r := ({e with eexpr = TReturn None}) :: e1 :: !r - | _ -> r := (find e) :: !r - ) el; - List.rev !r - and find e = match e.eexpr with - | TReturn (Some e1) -> loop (fun er -> {e with eexpr = TReturn (Some er)}) e1 - | TBinop(OpAssign | OpAssignOp _ as op, ({eexpr = TLocal _ | TField _ | TArray _} as e1), e2) -> loop (fun er -> {e with eexpr = TBinop(op, e1, er)}) e2 - | TBlock(el) -> {e with eexpr = TBlock (block el)} - | _ -> Type.map_expr find e - in - find e - (* Adds final returns to functions as required by some platforms *) let rec add_final_return e = let rec loop e t = @@ -112,7 +36,7 @@ let rec add_final_return e = | TAbstract ({ a_path = [],"Bool" },_) -> TBool false | _ -> TNull ) in - { eexpr = TReturn (Some { eexpr = TConst c; epos = p; etype = t }); etype = t; epos = p } + { eexpr = TReturn (Some { eexpr = TConst c; epos = p; etype = t }); etype = t_dynamic; epos = p } in match e.eexpr with | TBlock el -> @@ -134,7 +58,7 @@ let rec add_final_return e = | TFunction f -> let f = (match follow f.tf_type with | TAbstract ({ a_path = [],"Void" },[]) -> f - | t -> { f with tf_expr = loop f.tf_expr t } + | _ -> { f with tf_expr = loop f.tf_expr f.tf_type } ) in { e with eexpr = TFunction f } | _ -> e @@ -151,8 +75,15 @@ let rec wrap_js_exceptions com e = | TThrow eerr when not (is_error eerr.etype) -> let terr = List.find (fun mt -> match mt with TClassDecl {cl_path = ["js";"_Boot"],"HaxeError"} -> true | _ -> false) com.types in let cerr = match terr with TClassDecl c -> c | _ -> assert false in - let ewrap = { eerr with eexpr = TNew (cerr,[],[eerr]) } in - { e with eexpr = TThrow ewrap } + (match eerr.etype with + | TDynamic _ -> + let eterr = Codegen.ExprBuilder.make_static_this cerr e.epos in + let ewrap = Codegen.fcall eterr "wrap" [eerr] t_dynamic e.epos in + { e with eexpr = TThrow ewrap } + | _ -> + let ewrap = { eerr with eexpr = TNew (cerr,[],[eerr]); etype = TInst (cerr,[]) } in + { e with eexpr = TThrow ewrap } + ) | _ -> Type.map_expr loop e in @@ -176,17 +107,20 @@ let check_local_vars_init e = ) !vars declared; in let declared = ref [] in + let outside_vars = ref IntMap.empty in let rec loop vars e = match e.eexpr with | TLocal v -> let init = (try PMap.find v.v_id !vars with Not_found -> true) in - if not init then begin + if not init && not (IntMap.mem v.v_id !outside_vars) then begin if v.v_name = "this" then error "Missing this = value" e.epos else error ("Local variable " ^ v.v_name ^ " used without being initialized") e.epos end | TVar (v,eo) -> begin match eo with + | None when Meta.has Meta.InlineConstructorVariable v.v_meta -> + () | None -> declared := v.v_id :: !declared; vars := PMap.add v.v_id false !vars @@ -264,6 +198,14 @@ let check_local_vars_init e = | TThrow e | TReturn (Some e) -> loop vars e; vars := PMap.map (fun _ -> true) !vars + | TFunction tf -> + let old = !outside_vars in + (* Mark all known variables as "outside" so we can ignore their initialization state within the function. + We cannot use `vars` directly because we still care about initializations the function might make. + *) + PMap.iter (fun i _ -> outside_vars := IntMap.add i true !outside_vars) !vars; + loop vars tf.tf_expr; + outside_vars := old; | _ -> Type.iter (loop vars) e in @@ -389,7 +331,7 @@ let captured_vars com e = in let mk_var v used = - let v2 = alloc_var v.v_name (PMap.find v.v_id used) in + let v2 = alloc_var v.v_name (PMap.find v.v_id used) v.v_pos in v2.v_meta <- v.v_meta; v2 in @@ -454,12 +396,27 @@ let captured_vars com e = will not be overwritten in next loop iteration *) if com.config.pf_capture_policy = CPLoopVars then + (* We don't want to duplicate any variable declarations, so let's make copies (issue #3902). *) + let new_vars = List.map (fun v -> v.v_id,alloc_var v.v_name v.v_type v.v_pos) vars in + let rec loop e = match e.eexpr with + | TLocal v -> + begin try + let v' = List.assoc v.v_id new_vars in + v'.v_capture <- true; + {e with eexpr = TLocal v'} + with Not_found -> + e + end + | _ -> + Type.map_expr loop e + in + let e = loop e in mk (TCall ( Codegen.mk_parent (mk (TFunction { - tf_args = List.map (fun v -> v, None) vars; + tf_args = List.map (fun (_,v) -> v, None) new_vars; tf_type = e.etype; tf_expr = mk_block (mk (TReturn (Some e)) e.etype e.epos); - }) (TFun (List.map (fun v -> v.v_name,false,v.v_type) vars,e.etype)) e.epos), + }) (TFun (List.map (fun (_,v) -> v.v_name,false,v.v_type) new_vars,e.etype)) e.epos), List.map (fun v -> mk (TLocal v) v.v_type e.epos) vars) ) e.etype e.epos else @@ -569,64 +526,17 @@ let captured_vars com e = (* RENAME LOCAL VARS *) let rename_local_vars ctx e = - let cfg = ctx.com.config in - let all_scope = (not cfg.pf_captured_scope) || (not cfg.pf_locals_scope) in - let vars = ref PMap.empty in - let all_vars = ref PMap.empty in - let vtemp = alloc_var "~" t_dynamic in - let rebuild_vars = ref false in - let rebuild m = - PMap.fold (fun v acc -> PMap.add v.v_name v acc) m PMap.empty + let vars = ref [] in + let declare v = + vars := v :: !vars in - let save() = - let old = !vars in - if cfg.pf_unique_locals || not cfg.pf_locals_scope then (fun() -> ()) else (fun() -> vars := if !rebuild_vars then rebuild old else old) + let reserved = ref StringMap.empty in + let reserve name = + reserved := StringMap.add name true !reserved in - let rename vars v = - let count = ref 1 in - while PMap.mem (v.v_name ^ string_of_int !count) vars do - incr count; - done; - v.v_name <- v.v_name ^ string_of_int !count; - in - let declare v p = - (match follow v.v_type with - | TAbstract ({a_path = [],"Void"},_) -> error "Arguments and variables of type Void are not allowed" p - | _ -> ()); - (* chop escape char for all local variables generated *) - if is_gen_local v then v.v_name <- "_g" ^ String.sub v.v_name 1 (String.length v.v_name - 1); - let look_vars = (if not cfg.pf_captured_scope && v.v_capture then !all_vars else !vars) in - (try - let v2 = PMap.find v.v_name look_vars in - (* - block_vars will create some wrapper-functions that are declaring - the same variable twice. In that case do not perform a rename since - we are sure it's actually the same variable - *) - if v == v2 then raise Not_found; - rename look_vars v; - with Not_found -> - ()); - vars := PMap.add v.v_name v !vars; - if all_scope then all_vars := PMap.add v.v_name v !all_vars; - in - (* - This is quite a rare case, when a local variable would otherwise prevent - accessing a type because it masks the type value or the package name. - *) let check t = match (t_infos t).mt_path with - | [], name | name :: _, _ -> - let vars = if cfg.pf_locals_scope then vars else all_vars in - (try - let v = PMap.find name !vars in - if v == vtemp then raise Not_found; (* ignore *) - rename (!vars) v; - rebuild_vars := true; - vars := PMap.add v.v_name v !vars - with Not_found -> - ()); - vars := PMap.add name vtemp !vars + | [], name | name :: _, _ -> reserve name in let check_type t = match follow t with @@ -636,70 +546,62 @@ let rename_local_vars ctx e = | TAbstract (a,_) -> check (TAbstractDecl a) | TMono _ | TLazy _ | TAnon _ | TDynamic _ | TFun _ -> () in - let rec loop e = - match e.eexpr with - | TVar (v,eo) -> - if not cfg.pf_locals_scope then declare v e.epos; - (match eo with None -> () | Some e -> loop e); - if cfg.pf_locals_scope then declare v e.epos; - | TFunction tf -> - let old = save() in - List.iter (fun (v,_) -> declare v e.epos) tf.tf_args; - loop tf.tf_expr; - old() - | TBlock el -> - let old = save() in - (* we have to look ahead for vars on these targets (issue #3344) *) - begin match ctx.com.platform with - | Js -> - let rec check_var e = match e.eexpr with - | TVar (v,eo) -> - (match eo with None -> () | Some e -> loop e); - declare v e.epos - | TBlock _ -> - () - | _ -> - Type.iter check_var e - in - List.iter check_var el - | _ -> - () - end; - List.iter loop el; - old() - | TFor (v,it,e1) -> - loop it; - let old = save() in - declare v e.epos; - loop e1; - old() - | TTry (e,catchs) -> - loop e; + let rec collect e = match e.eexpr with + | TVar(v,eo) -> + declare v; + (match eo with None -> () | Some e -> collect e) + | TFor(v,e1,e2) -> + declare v; + collect e1; + collect e2; + | TTry(e1,catches) -> + collect e1; List.iter (fun (v,e) -> - let old = save() in - declare v e.epos; + declare v; check_type v.v_type; - loop e; - old() - ) catchs; + collect e + ) catches + | TFunction tf -> + List.iter (fun (v,_) -> declare v) tf.tf_args; + collect tf.tf_expr | TTypeExpr t -> check t | TNew (c,_,_) -> - Type.iter loop e; + Type.iter collect e; check (TClassDecl c); | TCast (e,Some t) -> - loop e; + collect e; check t; | TConst TSuper -> check_type e.etype | _ -> - Type.iter loop e + Type.iter collect e in - declare (alloc_var "this" t_dynamic) Ast.null_pos; (* force renaming of 'this' vars in abstract *) + (* Pass 1: Collect used identifiers and variables. *) + reserve "this"; + if ctx.com.platform = Java then reserve "_"; begin match ctx.curclass.cl_path with - | s :: _,_ | [],s -> declare (alloc_var s t_dynamic) Ast.null_pos + | s :: _,_ | [],s -> reserve s end; - loop e; + collect e; + (* Pass 2: Check and rename variables. *) + let count_table = Hashtbl.create 0 in + let maybe_rename v = + (* chop escape char for all local variables generated *) + if is_gen_local v then v.v_name <- "_g" ^ String.sub v.v_name 1 (String.length v.v_name - 1); + let name = ref v.v_name in + let count = ref (try Hashtbl.find count_table v.v_name with Not_found -> 0) in + while StringMap.mem !name !reserved do + incr count; + name := v.v_name ^ (string_of_int !count); + done; + reserve !name; + Hashtbl.replace count_table v.v_name !count; + if not (Meta.has Meta.RealPath v.v_meta) then + v.v_meta <- (Meta.RealPath,[EConst (String v.v_name),e.epos],e.epos) :: v.v_meta; + v.v_name <- !name; + in + List.iter maybe_rename (List.rev !vars); e let check_unification ctx e t = @@ -770,7 +672,7 @@ let rec is_removable_class c = | _ -> false) || List.exists (fun (_,t) -> match follow t with | TInst(c,_) -> - Codegen.has_ctor_constraint c + has_ctor_constraint c || Meta.has Meta.Const c.cl_meta | _ -> false ) c.cl_params) @@ -792,12 +694,12 @@ let remove_extern_fields ctx t = match t with | TClassDecl c -> if not (Common.defined ctx.com Define.DocGen) then begin c.cl_ordered_fields <- List.filter (fun f -> - let b = Codegen.is_removable_field ctx f in + let b = is_removable_field ctx f in if b then c.cl_fields <- PMap.remove f.cf_name c.cl_fields; not b ) c.cl_ordered_fields; c.cl_ordered_statics <- List.filter (fun f -> - let b = Codegen.is_removable_field ctx f in + let b = is_removable_field ctx f in if b then c.cl_statics <- PMap.remove f.cf_name c.cl_statics; not b ) c.cl_ordered_statics; @@ -890,7 +792,7 @@ let add_rtti ctx t = in match t with | TClassDecl c when has_rtti c && not (PMap.mem "__rtti" c.cl_statics) -> - let f = mk_field "__rtti" ctx.t.tstring c.cl_pos in + let f = mk_field "__rtti" ctx.t.tstring c.cl_pos null_pos in let str = Genxml.gen_type_string ctx.com t in f.cf_expr <- Some (mk (TConst (TString str)) f.cf_type c.cl_pos); c.cl_ordered_statics <- f :: c.cl_ordered_statics; @@ -904,7 +806,7 @@ let add_field_inits ctx t = let apply c = let ethis = mk (TConst TThis) (TInst (c,List.map snd c.cl_params)) c.cl_pos in (* TODO: we have to find a variable name which is not used in any of the functions *) - let v = alloc_var "_g" ethis.etype in + let v = alloc_var "_g" ethis.etype ethis.epos in let need_this = ref false in let inits,fields = List.fold_left (fun (inits,fields) cf -> match cf.cf_kind,cf.cf_expr with @@ -950,7 +852,7 @@ let add_field_inits ctx t = eassign; ) inits in let el = if !need_this then (mk (TVar((v, Some ethis))) ethis.etype ethis.epos) :: el else el in - match c.cl_constructor with + let cf = match c.cl_constructor with | None -> let ct = TFun([],ctx.com.basic.tvoid) in let ce = mk (TFunction { @@ -958,17 +860,29 @@ let add_field_inits ctx t = tf_type = ctx.com.basic.tvoid; tf_expr = mk (TBlock el) ctx.com.basic.tvoid c.cl_pos; }) ct c.cl_pos in - let ctor = mk_field "new" ct c.cl_pos in + let ctor = mk_field "new" ct c.cl_pos null_pos in ctor.cf_kind <- Method MethNormal; - c.cl_constructor <- Some { ctor with cf_expr = Some ce }; + { ctor with cf_expr = Some ce } | Some cf -> match cf.cf_expr with | Some { eexpr = TFunction f } -> let bl = match f.tf_expr with {eexpr = TBlock b } -> b | x -> [x] in let ce = mk (TFunction {f with tf_expr = mk (TBlock (el @ bl)) ctx.com.basic.tvoid c.cl_pos }) cf.cf_type cf.cf_pos in - c.cl_constructor <- Some {cf with cf_expr = Some ce } + {cf with cf_expr = Some ce }; | _ -> assert false + in + let config = AnalyzerConfig.get_field_config ctx.com c cf in + Analyzer.Run.run_on_field ctx config c cf; + (match cf.cf_expr with + | Some e -> + (* This seems a bit expensive, but hopefully constructor expressions aren't that massive. *) + let e = rename_local_vars ctx e in + let e = Optimizer.sanitize ctx.com e in + cf.cf_expr <- Some e + | _ -> + ()); + c.cl_constructor <- Some cf in match t with | TClassDecl c -> @@ -982,10 +896,77 @@ let add_meta_field ctx t = match t with (match Codegen.build_metadata ctx.com t with | None -> () | Some e -> - let f = mk_field "__meta__" t_dynamic c.cl_pos in + add_feature ctx.com "has_metadata"; + let f = mk_field "__meta__" t_dynamic c.cl_pos null_pos in f.cf_expr <- Some e; - c.cl_ordered_statics <- f :: c.cl_ordered_statics; - c.cl_statics <- PMap.add f.cf_name f c.cl_statics) + let can_deal_with_interface_metadata () = match ctx.com.platform with + | Flash when Common.defined ctx.com Define.As3 -> false + | Php when not (Common.is_php7 ctx.com) -> false + | _ -> true + in + if c.cl_interface && not (can_deal_with_interface_metadata()) then begin + (* borrowed from gencommon, but I did wash my hands afterwards *) + let path = fst c.cl_path,snd c.cl_path ^ "_HxMeta" in + let ncls = mk_class c.cl_module path c.cl_pos null_pos in + let cf = mk_field "__meta__" e.etype e.epos null_pos in + cf.cf_expr <- Some e; + ncls.cl_statics <- PMap.add "__meta__" cf ncls.cl_statics; + ncls.cl_ordered_statics <- cf :: ncls.cl_ordered_statics; + ctx.com.types <- (TClassDecl ncls) :: ctx.com.types; + c.cl_meta <- (Meta.Custom ":hasMetadata",[],e.epos) :: c.cl_meta + end else begin + c.cl_ordered_statics <- f :: c.cl_ordered_statics; + c.cl_statics <- PMap.add f.cf_name f c.cl_statics + end) + | _ -> + () + +(* + C# events have special semantics: + if we have an @:event var field, there should also be add_ and remove_ methods, + this filter checks for their existence and also adds some metadata for analyzer and C# generator +*) +let check_cs_events com t = match t with + | TClassDecl cl when not cl.cl_extern -> + let check fields f = + match f.cf_kind with + | Var { v_read = AccNormal; v_write = AccNormal } when Meta.has Meta.Event f.cf_meta -> + if f.cf_public then error "@:event fields must be private" f.cf_pos; + + (* prevent generating reflect helpers for the event in gencommon *) + f.cf_meta <- (Meta.SkipReflection, [], f.cf_pos) :: f.cf_meta; + + (* type for both add and remove methods *) + let tmeth = (tfun [f.cf_type] com.basic.tvoid) in + + let process_event_method name = + let m = try PMap.find name fields with Not_found -> error ("Missing event method: " ^ name) f.cf_pos in + + (* check method signature *) + begin + try + type_eq EqStrict m.cf_type tmeth + with Unify_error el -> + List.iter (fun e -> com.error (unify_error_msg (print_context()) e) m.cf_pos) el + end; + + (* + add @:pure(false) to prevent purity inference, because empty add/remove methods + have special meaning here and they are always impure + *) + m.cf_meta <- (Meta.Pure,[EConst(Ident "false"),f.cf_pos],f.cf_pos) :: (Meta.Custom ":cs_event_impl",[],f.cf_pos) :: m.cf_meta; + + (* add @:keep to event methods if the event is kept *) + if Meta.has Meta.Keep f.cf_meta && not (Meta.has Meta.Keep m.cf_meta) then + m.cf_meta <- (Meta.Keep,[],f.cf_pos) :: m.cf_meta; + in + process_event_method ("add_" ^ f.cf_name); + process_event_method ("remove_" ^ f.cf_name) + | _ -> + () + in + List.iter (check cl.cl_fields) cl.cl_ordered_fields; + List.iter (check cl.cl_statics) cl.cl_ordered_statics | _ -> () @@ -1050,10 +1031,10 @@ let run_expression_filters ctx filters t = ctx.curclass <- c; let rec process_field f = (match f.cf_expr with - | Some e when not (Codegen.is_removable_field ctx f) -> - Codegen.AbstractCast.cast_stack := f :: !Codegen.AbstractCast.cast_stack; + | Some e when not (is_removable_field ctx f) -> + AbstractCast.cast_stack := f :: !AbstractCast.cast_stack; f.cf_expr <- Some (run e); - Codegen.AbstractCast.cast_stack := List.tl !Codegen.AbstractCast.cast_stack; + AbstractCast.cast_stack := List.tl !AbstractCast.cast_stack; | _ -> ()); List.iter process_field f.cf_overloads in @@ -1097,76 +1078,39 @@ let iter_expressions fl mt = () let run com tctx main = - begin match com.display with - | DMUsage | DMPosition -> - Codegen.detect_usage com; - | _ -> - () - end; - if not (Common.defined com Define.NoDeprecationWarnings) then - Codegen.DeprecationCheck.run com; - let use_static_analyzer = Common.defined com Define.Analyzer in - (* this part will be a bit messy until we make the analyzer the default *) let new_types = List.filter (fun t -> not (is_cached t)) com.types in - if use_static_analyzer then begin - (* PASS 1: general expression filters *) - let filters = [ - Codegen.UnificationCallback.run (check_unification tctx); - Codegen.AbstractCast.handle_abstract_casts tctx; - Optimizer.inline_constructors tctx; - Optimizer.reduce_expression tctx; - blockify_ast; - captured_vars com; - ] in - List.iter (run_expression_filters tctx filters) new_types; - Analyzer.Run.run_on_types tctx new_types; - List.iter (iter_expressions [verify_ast]) new_types; - let filters = [ - Optimizer.sanitize com; - if com.config.pf_add_final_return then add_final_return else (fun e -> e); - if com.platform = Js then wrap_js_exceptions com else (fun e -> e); - rename_local_vars tctx; - ] in - List.iter (run_expression_filters tctx filters) new_types; - end else begin - (* PASS 1: general expression filters *) - let filters = [ - Codegen.UnificationCallback.run (check_unification tctx); - Codegen.AbstractCast.handle_abstract_casts tctx; - blockify_ast; - check_local_vars_init; - ( if (Common.defined com Define.NoSimplify) || (Common.defined com Define.Cppia) || - ( match com.platform with Cpp -> false | _ -> true ) then - fun e -> e - else - fun e -> - let save = save_locals tctx in - let timer = timer "analyzer-simplify-apply" in - let e = try snd (Analyzer.Simplifier.apply com e) with Exit -> e in - timer(); - save(); - e ); - if com.foptimize then (fun e -> Optimizer.reduce_expression tctx (Optimizer.inline_constructors tctx e)) else Optimizer.sanitize com; - captured_vars com; - promote_complex_rhs com; - if com.config.pf_add_final_return then add_final_return else (fun e -> e); - if com.platform = Js then wrap_js_exceptions com else (fun e -> e); - rename_local_vars tctx; - ] in - List.iter (run_expression_filters tctx filters) new_types; - List.iter (iter_expressions [verify_ast]) new_types; - end; + (* PASS 1: general expression filters *) + let filters = [ + AbstractCast.handle_abstract_casts tctx; + Optimizer.inline_constructors tctx; + check_local_vars_init; + Optimizer.reduce_expression tctx; + captured_vars com; + ] in + List.iter (run_expression_filters tctx filters) new_types; + (* PASS 1.5: pre-analyzer type filters *) + List.iter (fun t -> + if com.platform = Cs then check_cs_events tctx.com t; + ) new_types; + if com.platform <> Cross then Analyzer.Run.run_on_types tctx new_types; + let filters = [ + Optimizer.sanitize com; + if com.config.pf_add_final_return then add_final_return else (fun e -> e); + if com.platform = Js then wrap_js_exceptions com else (fun e -> e); + rename_local_vars tctx; + ] in + List.iter (run_expression_filters tctx filters) new_types; next_compilation(); - List.iter (fun f -> f()) (List.rev com.filters); (* macros onGenerate etc. *) + List.iter (fun f -> f()) (List.rev com.callbacks.before_dce); (* macros onGenerate etc. *) List.iter (save_class_state tctx) new_types; + (* PASS 2: type filters pre-DCE *) List.iter (fun t -> remove_generic_base tctx t; remove_extern_fields tctx t; + Codegen.update_cache_dependencies t; + (* check @:remove metadata before DCE so it is ignored there (issue #2923) *) + check_remove_metadata tctx t; ) com.types; - (* update cache dependencies before DCE is run *) - Codegen.update_cache_dependencies com; - (* check @:remove metadata before DCE so it is ignored there (issue #2923) *) - List.iter (check_remove_metadata tctx) com.types; (* DCE *) let dce_mode = if Common.defined com Define.As3 then "no" @@ -1179,26 +1123,13 @@ let run com tctx main = | "no" -> Dce.fix_accessors com | _ -> failwith ("Unknown DCE mode " ^ dce_mode) end; - (* always filter empty abstract implementation classes (issue #1885) *) - List.iter (fun mt -> match mt with - | TClassDecl({cl_kind = KAbstractImpl _} as c) when c.cl_ordered_statics = [] && c.cl_ordered_fields = [] && not (Meta.has Meta.Used c.cl_meta) -> - c.cl_extern <- true - | TClassDecl({cl_kind = KAbstractImpl a} as c) when Meta.has Meta.Enum a.a_meta -> - let is_runtime_field cf = - not (Meta.has Meta.Enum cf.cf_meta) - in - (* also filter abstract implementation classes that have only @:enum fields (issue #2858) *) - if not (List.exists is_runtime_field c.cl_ordered_statics) then - c.cl_extern <- true - | _ -> () - ) com.types; - (* PASS 3: type filters *) + (* PASS 3: type filters post-DCE *) let type_filters = [ check_private_path; apply_native_paths; add_rtti; (match com.platform with | Java | Cs -> (fun _ _ -> ()) | _ -> add_field_inits); - add_meta_field; + (match com.platform with Hl -> (fun _ _ -> ()) | _ -> add_meta_field); check_void_field; (match com.platform with | Cpp -> promote_first_interface_to_super | _ -> (fun _ _ -> ()) ); commit_features; diff --git a/optimizer.ml b/src/optimization/optimizer.ml similarity index 67% rename from optimizer.ml rename to src/optimization/optimizer.ml index 5cdd3336..51f1e185 100644 --- a/optimizer.ml +++ b/src/optimization/optimizer.ml @@ -1,100 +1,85 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Ast open Type open Common open Typecore +open OptimizerTexpr +open Error +open Globals (* ---------------------------------------------------------------------- *) (* API OPTIMIZATIONS *) -(* tells if an expression causes side effects. This does not account for potential null accesses (fields/arrays/ops) *) -let has_side_effect e = - let rec loop e = - match e.eexpr with - | TConst _ | TLocal _ | TTypeExpr _ | TFunction _ -> () - | TCall ({ eexpr = TField(_,FStatic({ cl_path = ([],"Std") },{ cf_name = "string" })) },args) -> Type.iter loop e - | TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit - | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit - | TArray _ | TEnumParameter _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ | TFor _ - | TField _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TBlock _ | TObjectDecl _ | TVar _ -> Type.iter loop e - in - try - loop e; false - with Exit -> - true - let mk_untyped_call name p params = { - eexpr = TCall({ eexpr = TLocal(alloc_unbound_var name t_dynamic); etype = t_dynamic; epos = p }, params); + eexpr = TCall({ eexpr = TLocal(alloc_unbound_var name t_dynamic p); etype = t_dynamic; epos = p }, params); etype = t_dynamic; epos = p; } -let api_inline ctx c field params p = +let api_inline2 com c field params p = match c.cl_path, field, params with - | ([],"Type"),"enumIndex",[{ eexpr = TField (_,FEnum (en,f)) }] -> (match ctx.com.platform with + | ([],"Type"),"enumIndex",[{ eexpr = TField (_,FEnum (en,f)) }] -> (match com.platform with | Cs when en.e_extern && not (Meta.has Meta.HxGen en.e_meta) -> (* We don't want to optimize enums from external sources; as they might change unexpectedly *) (* and since native C# enums don't have the concept of index - they have rather a value, *) (* which can't be mapped to a native API - this kind of substitution is dangerous *) None | _ -> - Some (mk (TConst (TInt (Int32.of_int f.ef_index))) ctx.t.tint p)) + Some (mk (TConst (TInt (Int32.of_int f.ef_index))) com.basic.tint p)) | ([],"Type"),"enumIndex",[{ eexpr = TCall({ eexpr = TField (_,FEnum (en,f)) },pl) }] when List.for_all (fun e -> not (has_side_effect e)) pl -> - (match ctx.com.platform with + (match com.platform with | Cs when en.e_extern && not (Meta.has Meta.HxGen en.e_meta) -> (* see comment above *) None | _ -> - Some (mk (TConst (TInt (Int32.of_int f.ef_index))) ctx.t.tint p)) + Some (mk (TConst (TInt (Int32.of_int f.ef_index))) com.basic.tint p)) | ([],"Std"),"int",[{ eexpr = TConst (TInt _) } as e] -> Some { e with epos = p } | ([],"String"),"fromCharCode",[{ eexpr = TConst (TInt i) }] when i > 0l && i < 128l -> - Some (mk (TConst (TString (String.make 1 (char_of_int (Int32.to_int i))))) ctx.t.tstring p) + Some (mk (TConst (TString (String.make 1 (char_of_int (Int32.to_int i))))) com.basic.tstring p) + | ([],"Std"),"string",[{ eexpr = TCast ({ eexpr = TConst c } as e, None)}] | ([],"Std"),"string",[{ eexpr = TConst c } as e] -> (match c with | TString s -> Some { e with epos = p } | TInt i -> - Some { eexpr = TConst (TString (Int32.to_string i)); epos = p; etype = ctx.t.tstring } + Some { eexpr = TConst (TString (Int32.to_string i)); epos = p; etype = com.basic.tstring } | TBool b -> - Some { eexpr = TConst (TString (if b then "true" else "false")); epos = p; etype = ctx.t.tstring } + Some { eexpr = TConst (TString (if b then "true" else "false")); epos = p; etype = com.basic.tstring } | _ -> None) | ([],"Std"),"string",[{ eexpr = TIf (_,{ eexpr = TConst (TString _)},Some { eexpr = TConst (TString _) }) } as e] -> Some e - | ([],"Std"),"string",[{ eexpr = TLocal _ | TField({ eexpr = TLocal _ },_) } as v] when ctx.com.platform = Js || ctx.com.platform = Flash -> - let pos = v.epos in + | ([],"Std"),"string",[{ eexpr = TLocal v | TField({ eexpr = TLocal v },_) } as ev] when (com.platform = Js || com.platform = Flash) && not (Meta.has Meta.CompilerGenerated v.v_meta) -> + let pos = ev.epos in let stringv() = - let to_str = mk (TBinop (Ast.OpAdd, mk (TConst (TString "")) ctx.t.tstring pos, v)) ctx.t.tstring pos in - if ctx.com.platform = Js || is_nullable v.etype then - let chk_null = mk (TBinop (Ast.OpEq, v, mk (TConst TNull) t_dynamic pos)) ctx.t.tbool pos in - mk (TIf (chk_null, mk (TConst (TString "null")) ctx.t.tstring pos, Some to_str)) ctx.t.tstring pos + let to_str = mk (TBinop (Ast.OpAdd, mk (TConst (TString "")) com.basic.tstring pos, ev)) com.basic.tstring pos in + if com.platform = Js || is_nullable ev.etype then + let chk_null = mk (TBinop (Ast.OpEq, ev, mk (TConst TNull) t_dynamic pos)) com.basic.tbool pos in + mk (TIf (chk_null, mk (TConst (TString "null")) com.basic.tstring pos, Some to_str)) com.basic.tstring pos else to_str in - (match follow v.etype with + (match follow ev.etype with | TInst ({ cl_path = [],"String" }, []) -> Some (stringv()) | TAbstract ({ a_path = [],"Float" }, []) -> @@ -107,12 +92,49 @@ let api_inline ctx c field params p = Some (stringv()) | _ -> None) + | ([],"Std"),"int",[{ eexpr = TConst (TFloat f) }] -> + let f = float_of_string f in + (match classify_float f with + | FP_infinite | FP_nan -> + None + | _ when f <= Int32.to_float Int32.min_int -. 1. || f >= Int32.to_float Int32.max_int +. 1. -> + None (* out range, keep platform-specific behavior *) + | _ -> + Some { eexpr = TConst (TInt (Int32.of_float f)); etype = com.basic.tint; epos = p }) + | ([],"Math"),"ceil",[{ eexpr = TConst (TFloat f) }] -> + let f = float_of_string f in + (match classify_float f with + | FP_infinite | FP_nan -> + None + | _ when f <= Int32.to_float Int32.min_int -. 1. || f >= Int32.to_float Int32.max_int -> + None (* out range, keep platform-specific behavior *) + | _ -> + Some { eexpr = TConst (TInt (Int32.of_float (ceil f))); etype = com.basic.tint; epos = p }) + | ([],"Math"),"floor",[{ eexpr = TConst (TFloat f) }] -> + let f = float_of_string f in + (match classify_float f with + | FP_infinite | FP_nan -> + None + | _ when f <= Int32.to_float Int32.min_int || f >= Int32.to_float Int32.max_int +. 1. -> + None (* out range, keep platform-specific behavior *) + | _ -> + Some { eexpr = TConst (TInt (Int32.of_float (floor f))); etype = com.basic.tint; epos = p }) + | (["cs"],"Lib"),("fixed" | "checked" | "unsafe"),[e] -> + Some (mk_untyped_call ("__" ^ field ^ "__") p [e]) + | (["cs"],"Lib"),("lock"),[obj;block] -> + Some (mk_untyped_call ("__lock__") p [obj;mk_block block]) + | (["java"],"Lib"),("lock"),[obj;block] -> + Some (mk_untyped_call ("__lock__") p [obj;mk_block block]) + | _ -> + None + +let api_inline ctx c field params p = match c.cl_path, field, params with | ([],"Std"),"is",[o;t] | (["js"],"Boot"),"__instanceof",[o;t] when ctx.com.platform = Js -> let mk_local ctx n t pos = mk (TLocal (try PMap.find n ctx.locals with _ -> - let v = add_local ctx n t in + let v = add_local ctx n t p in v.v_meta <- [Meta.Unbound,[],p]; v )) t pos in @@ -139,10 +161,11 @@ let api_inline ctx c field params p = | TTypeExpr (TAbstractDecl ({ a_path = [],"Bool" })) -> Some (typeof "boolean") | TTypeExpr (TAbstractDecl ({ a_path = [],"Float" })) -> Some (typeof "number") | TTypeExpr (TAbstractDecl ({ a_path = [],"Int" })) when is_trivial o -> - (* generate (o|0) === o check *) + (* generate typeof(o) == "number" && (o|0) === o check *) let teq = mk_local ctx "__strict_eq__" (tfun [tint; tint] tbool) p in let lhs = mk (TBinop (Ast.OpOr, o, mk (TConst (TInt Int32.zero)) tint p)) tint p in - Some (mk (TCall (teq, [lhs; o])) tbool p) + let jscheck = mk (TCall (teq, [lhs; o])) tbool p in + Some(mk (TBinop (Ast.OpBoolAnd, typeof "number", jscheck)) tbool p) | TTypeExpr (TClassDecl ({ cl_path = [],"Array" })) -> (* generate (o instanceof Array) && o.__enum__ == null check *) let iof = mk_local ctx "__instanceof__" (tfun [o.etype;t.etype] tbool) p in @@ -153,21 +176,6 @@ let api_inline ctx c field params p = Some (mk (TBinop (Ast.OpBoolAnd, iof, not_enum)) tbool p) | _ -> None) - | ([],"Std"),"int",[{ eexpr = TConst (TFloat f) }] -> - let f = float_of_string f in - (match classify_float f with - | FP_infinite | FP_nan -> - None - | _ when f <= Int32.to_float Int32.min_int -. 1. || f >= Int32.to_float Int32.max_int +. 1. -> - None (* out range, keep platform-specific behavior *) - | _ -> - Some { eexpr = TConst (TInt (Int32.of_float f)); etype = ctx.t.tint; epos = p }) - | (["cs"],"Lib"),("fixed" | "checked" | "unsafe"),[e] -> - Some (mk_untyped_call ("__" ^ field ^ "__") p [e]) - | (["cs"],"Lib"),("lock"),[obj;block] -> - Some (mk_untyped_call ("__lock__") p [obj;mk_block block]) - | (["java"],"Lib"),("lock"),[obj;block] -> - Some (mk_untyped_call ("__lock__") p [obj;mk_block block]) | (["cs" | "java"],"Lib"),("nativeArray"),[{ eexpr = TArrayDecl args } as edecl; _] | (["haxe";"ds";"_Vector"],"Vector_Impl_"),("fromArrayCopy"),[{ eexpr = TArrayDecl args } as edecl] -> (try let platf = match ctx.com.platform with @@ -194,7 +202,7 @@ let api_inline ctx c field params p = with | Exit -> None) | _ -> - None + api_inline2 ctx.com c field params p (* ---------------------------------------------------------------------- *) (* INLINING *) @@ -202,6 +210,8 @@ let api_inline ctx c field params p = type in_local = { i_var : tvar; i_subst : tvar; + i_outside : bool; + i_abstract_this : bool; mutable i_captured : bool; mutable i_write : bool; mutable i_read : int; @@ -249,17 +259,19 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f try Hashtbl.find locals v.v_id with Not_found -> - let v' = alloc_var v.v_name v.v_type in + let v' = alloc_var v.v_name v.v_type v.v_pos in if Meta.has Meta.Unbound v.v_meta then v'.v_meta <- [Meta.Unbound,[],p]; let i = { i_var = v; i_subst = v'; + i_outside = false; + i_abstract_this = Meta.has Meta.This v.v_meta; i_captured = false; i_write = false; i_force_temp = false; i_read = 0; } in - i.i_subst.v_meta <- v.v_meta; + i.i_subst.v_meta <- List.filter (fun (m,_,_) -> m <> Meta.This) v.v_meta; Hashtbl.add locals v.v_id i; Hashtbl.add locals i.i_subst.v_id i; i @@ -274,6 +286,8 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f { i_var = v; i_subst = v; + i_outside = true; + i_abstract_this = Meta.has Meta.This v.v_meta; i_captured = false; i_write = false; i_force_temp = false; @@ -297,7 +311,7 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f if we cast from Dynamic, create a local var as well to do the cast once and allow DCE to perform properly. *) - if v.v_type != t_dynamic && follow e.etype == t_dynamic then (local v).i_write <- true; + let e = if follow v.v_type != t_dynamic && follow e.etype == t_dynamic then mk (TCast(e,None)) v.v_type e.epos else e in (match e.eexpr, opt with | TConst TNull , Some c -> mk (TConst c) v.v_type e.epos (* @@ -316,12 +330,22 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f Build the expr/var subst list *) let ethis = (match ethis.eexpr with TConst TSuper -> { ethis with eexpr = TConst TThis } | _ -> ethis) in - let vthis = alloc_var "_this" ethis.etype in + let vthis = alloc_var "_this" ethis.etype ethis.epos in + let might_be_affected,collect_modified_locals = create_affection_checker() in + let had_side_effect = ref false in let inlined_vars = List.map2 (fun e (v,_) -> let l = local v in - if has_side_effect e then l.i_force_temp <- true; (* force tmp var *) + if has_side_effect e then begin + collect_modified_locals e; + had_side_effect := true; + l.i_force_temp <- true; + end; + if l.i_abstract_this then l.i_subst.v_extra <- Some ([],Some e); l, e ) (ethis :: loop params f.tf_args true) ((vthis,None) :: f.tf_args) in + List.iter (fun (l,e) -> + if might_be_affected e then l.i_force_temp <- true; + ) inlined_vars; let inlined_vars = List.rev inlined_vars in (* here, we try to eliminate final returns from the expression tree. @@ -349,9 +373,9 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f l.i_read <- l.i_read + (if !in_loop then 2 else 1); (* never inline a function which contain a delayed macro because its bound to its variables and not the calling method *) - if v.v_name = "__dollar__delay_call" then cancel_inlining := true; + if v.v_name = "$__delayed_call__" then cancel_inlining := true; let e = { e with eexpr = TLocal l.i_subst } in - if Meta.has Meta.This v.v_meta then mk (TCast(e,None)) v.v_type e.epos else e + if l.i_abstract_this then mk (TCast(e,None)) v.v_type e.epos else e | TConst TThis -> let l = read_local vthis in l.i_read <- l.i_read + (if !in_loop then 2 else 1); @@ -382,7 +406,7 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f in_loop := old; { e with eexpr = TWhile (cond,eloop,flag) } | TSwitch (e1,cases,def) when term -> - let term = term && def <> None in + let term = term && (def <> None || is_exhaustive e1) in let cases = List.map (fun (el,e) -> let el = List.map (map false) el in el, map term e @@ -398,10 +422,18 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f | TBlock l -> let old = save_locals ctx in let t = ref e.etype in - let has_return e = - let rec loop e = match e.eexpr with - | TReturn _ -> raise Exit - | _ -> Type.iter loop e + let rec has_term_return e = + let rec loop e = + let r = match e.eexpr with + | TReturn _ -> true + | TIf (_,_,None) | TSwitch (_,_,None) | TFor _ | TWhile (_,_,NormalWhile) -> false (* we might not enter this code at all *) + | TTry (a, catches) -> List.for_all has_term_return (a :: List.map snd catches) + | TIf (cond,a,Some b) -> has_term_return cond || (has_term_return a && has_term_return b) + | TSwitch (cond,cases,Some def) -> has_term_return cond || List.for_all has_term_return (def :: List.map snd cases) + | TBinop (OpBoolAnd,a,b) -> has_term_return a && has_term_return b + | _ -> Type.iter loop e; false + in + if r then raise Exit in try loop e; false with Exit -> true in @@ -414,7 +446,7 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f let e = map term e in if term then t := e.etype; [e] - | ({ eexpr = TIf (cond,e1,None) } as e) :: l when term && has_return e1 -> + | ({ eexpr = TIf (cond,e1,None) } as e) :: l when term && has_term_return e1 -> loop [{ e with eexpr = TIf (cond,e1,Some (mk (TBlock l) e.etype e.epos)); epos = punion e.epos (match List.rev l with e :: _ -> e.epos | [] -> assert false) }] | e :: l -> let e = map false e in @@ -440,20 +472,14 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f l.i_write <- true; let e2 = map false e2 in {e with eexpr = TBinop(op,{e1 with eexpr = TLocal l.i_subst},e2)} -(* | TCall({eexpr = TLocal v} as e1,el) -> - let el = List.map (map false) el in - let l = read_local v in - let edef() = {e with eexpr = TCall({e1 with eexpr = TLocal l.i_subst},el)} in - begin try - begin match List.assq l inlined_vars with - | {eexpr = TField(_, (FStatic(_,cf) | FInstance(_,_,cf)))} as e' when cf.cf_kind = Method MethInline -> - make_call ctx e' el e.etype e.epos + | TObjectDecl fl -> + let fl = List.map (fun (s,e) -> s,map false e) fl in + begin match follow e.etype with + | TAnon an when (match !(an.a_status) with Const -> true | _ -> false) -> + {e with eexpr = TObjectDecl fl; etype = TAnon { an with a_status = ref Closed}} | _ -> - edef() - end - with Not_found -> - edef() - end *) + {e with eexpr = TObjectDecl fl} + end | TFunction f -> (match f.tf_args with [] -> () | _ -> has_vars := true); let old = save_locals ctx and old_fun = !in_local_fun in @@ -463,8 +489,20 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f in_local_fun := old_fun; old(); { e with eexpr = TFunction { tf_args = args; tf_expr = expr; tf_type = f.tf_type } } + | TCall({eexpr = TConst TSuper; etype = t},el) -> + begin match follow t with + | TInst({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction tf})} as cf)},_) -> + begin match type_inline ctx cf tf ethis el ctx.t.tvoid None po true with + | Some e -> map term e + | None -> error "Could not inline super constructor call" po + end + | _ -> error "Cannot inline function containing super" po + end | TConst TSuper -> error "Cannot inline function containing super" po + | TMeta(m,e1) -> + let e1 = map term e1 in + {e with eexpr = TMeta(m,e1)} | _ -> Type.map_expr (map false) e in @@ -496,24 +534,28 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f let force = ref force in let vars = List.fold_left (fun acc (i,e) -> let flag = not i.i_force_temp && (match e.eexpr with - | TLocal v when Meta.has Meta.This v.v_meta -> true + | TLocal _ when i.i_abstract_this -> true | TLocal _ | TConst _ -> not i.i_write | TFunction _ -> if i.i_write then error "Cannot modify a closure parameter inside inline method" p; true | _ -> not i.i_write && i.i_read <= 1 ) in let flag = flag && (not i.i_captured || is_constant e) in (* force inlining if we modify 'this' *) - if i.i_write && (Meta.has Meta.This i.i_var.v_meta) then force := true; + if i.i_write && i.i_abstract_this then force := true; (* force inlining of 'this' variable if it is written *) - let flag = if not flag && (Meta.has Meta.This i.i_var.v_meta) && i.i_write then begin + let flag = if not flag && i.i_abstract_this && i.i_write then begin if not (is_writable e) then error "Cannot modify the abstract value, store it into a local first" p; true end else flag in if flag then begin subst := PMap.add i.i_subst.v_id e !subst; acc - end else + end else begin + (* mark the replacement local for the analyzer *) + if i.i_read <= 1 && not i.i_write then + i.i_subst.v_meta <- (Meta.CompilerGenerated,[],p) :: i.i_subst.v_meta; (i.i_subst,Some e) :: acc + end ) [] inlined_vars in let subst = !subst in let rec inline_params e = @@ -529,7 +571,7 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f This could be fixed with better post process code cleanup (planed) *) - if !cancel_inlining || (not (Common.defined ctx.com Define.Analyzer) && Common.platform ctx.com Js && not !force && (init <> None || !has_vars)) then + if !cancel_inlining then None else let wrap e = @@ -549,7 +591,10 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f in let e = (match e.eexpr, init with | _, None when not !has_return_value -> - {e with etype = tret} + begin match e.eexpr with + | TBlock _ -> {e with etype = tret} + | _ -> mk (TBlock [e]) tret e.epos + end | TBlock [e] , None -> wrap e | _ , None -> wrap e | TBlock l, Some vl -> @@ -560,15 +605,25 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f mk (TBlock (el_v @ [e])) tret e.epos ) in let inline_meta e meta = match meta with - | Meta.Deprecated,_,_ -> mk (TMeta(meta,e)) e.etype e.epos + | (Meta.Deprecated | Meta.Pure),_,_ -> mk (TMeta(meta,e)) e.etype e.epos | _ -> e in let e = List.fold_left inline_meta e cf.cf_meta in + let e = Display.Diagnostics.secure_generated_code ctx e in + if Meta.has (Meta.Custom ":inlineDebug") ctx.meta then begin + let se t = s_expr_pretty true t true (s_type (print_context())) in + print_endline (Printf.sprintf "Inline %s:\n\tArgs: %s\n\tExpr: %s\n\tResult: %s" + cf.cf_name + (String.concat "" (List.map (fun (i,e) -> Printf.sprintf "\n\t\t%s<%i> = %s" (i.i_subst.v_name) (i.i_subst.v_id) (se "\t\t" e)) inlined_vars)) + (se "\t" f.tf_expr) + (se "\t" e) + ); + end; (* we need to replace type-parameters that were used in the expression *) if not has_params then Some e else - let mt = map_type cf.cf_type in + let mt = map_type cf.cf_type in let unify_func () = unify_raise ctx mt (TFun (List.map (fun e -> "",false,e.etype) params,tret)) p in (match follow ethis.etype with | TAnon a -> (match !(a.a_status) with @@ -588,7 +643,7 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f let map_var v = if not (Hashtbl.mem vars v.v_id) then begin Hashtbl.add vars v.v_id (); - v.v_type <- map_type v.v_type; + if not (read_local v).i_outside then v.v_type <- map_type v.v_type; end; v in @@ -607,12 +662,12 @@ let rec optimize_for_loop ctx (i,pi) e1 e2 p = TField (e,try quick_field e.etype n with Not_found -> assert false) in let gen_int_iter pt f_get f_length = - let i = add_local ctx i pt in - let index = gen_local ctx t_int in + let i = add_local ctx i pt pi in + let index = gen_local ctx t_int pi in let arr, avars = (match e1.eexpr with | TLocal _ -> e1, None | _ -> - let atmp = gen_local ctx e1.etype in + let atmp = gen_local ctx e1.etype e1.epos in mk (TLocal atmp) e1.etype e1.epos, (Some (atmp,Some e1)) ) in let iexpr = mk (TLocal index) t_int p in @@ -645,11 +700,11 @@ let rec optimize_for_loop ctx (i,pi) e1 e2 p = | TNew ({ cl_path = ([],"IntIterator") },[],[i1;i2]) , _ -> let max = (match i1.eexpr , i2.eexpr with | TConst (TInt a), TConst (TInt b) when Int32.compare b a < 0 -> error "Range operator can't iterate backwards" p - | _, TConst _ | _ , TLocal _ -> None - | _ -> Some (gen_local ctx t_int) + | _, TConst _ -> None + | _ -> Some (gen_local ctx t_int e1.epos) ) in - let tmp = gen_local ctx t_int in - let i = add_local ctx i t_int in + let tmp = gen_local ctx t_int pi in + let i = add_local ctx i t_int pi in let rec check e = match e.eexpr with | TBinop (OpAssign,{ eexpr = TLocal l },_) @@ -707,7 +762,7 @@ let rec optimize_for_loop ctx (i,pi) e1 e2 p = Ast.map_expr loop e in ignore(loop e2); - let v = add_local ctx i pt in + let v = add_local ctx i pt p in let e2 = type_expr ctx e2 NoValue in let cost = (List.length el) * !num_expr in let max_cost = try @@ -767,8 +822,8 @@ let rec optimize_for_loop ctx (i,pi) e1 e2 p = end | _ , TInst ({ cl_kind = KGenericInstance ({ cl_path = ["haxe";"ds"],"GenericStack" },[t]) } as c,[]) -> let tcell = (try (PMap.find "head" c.cl_fields).cf_type with Not_found -> assert false) in - let i = add_local ctx i t in - let cell = gen_local ctx tcell in + let i = add_local ctx i t p in + let cell = gen_local ctx tcell p in let cexpr = mk (TLocal cell) tcell p in let e2 = type_expr ctx e2 NoValue in let evar = mk (TVar (i,Some (mk (mk_field cexpr "elt") t p))) t_void pi in @@ -792,7 +847,7 @@ let optimize_for_loop_iterator ctx v e1 e2 p = let c,tl = (match follow e1.etype with TInst (c,pl) -> c,pl | _ -> raise Exit) in let _, _, fhasnext = (try raw_class_field (fun cf -> apply_params c.cl_params tl cf.cf_type) c tl "hasNext" with Not_found -> raise Exit) in if fhasnext.cf_kind <> Method MethInline then raise Exit; - let tmp = gen_local ctx e1.etype in + let tmp = gen_local ctx e1.etype e1.epos in let eit = mk (TLocal tmp) e1.etype p in let ehasnext = make_call ctx (mk (TField (eit,FInstance (c, tl, fhasnext))) (TFun([],ctx.t.tbool)) p) [] ctx.t.tbool p in let enext = mk (TVar (v,Some (make_call ctx (mk (TField (eit,quick_field_dynamic eit.etype "next")) (TFun ([],v.v_type)) p) [] v.v_type p))) ctx.t.tvoid p in @@ -839,8 +894,8 @@ let standard_precedence op = let rec need_parent e = match e.eexpr with - | TConst _ | TLocal _ | TArray _ | TField _ | TEnumParameter _ | TParenthesis _ | TMeta _ | TCall _ | TNew _ | TTypeExpr _ | TObjectDecl _ | TArrayDecl _ -> false - | TCast (e,None) -> need_parent e + | TConst _ | TLocal _ | TArray _ | TField _ | TEnumParameter _ | TParenthesis _ | TCall _ | TNew _ | TTypeExpr _ | TObjectDecl _ | TArrayDecl _ -> false + | TCast (e,None) | TMeta(_,e) -> need_parent e | TCast _ | TThrow _ | TReturn _ | TTry _ | TSwitch _ | TFor _ | TIf _ | TWhile _ | TBinop _ | TContinue | TBreak | TBlock _ | TVar _ | TFunction _ | TUnop _ -> true @@ -895,7 +950,7 @@ let sanitize_expr com e = match ee.eexpr with | TBinop (op2,_,_) -> if left then not (swap op2 op) else swap op op2 | TIf _ -> if left then not (swap (OpAssignOp OpAssign) op) else swap op (OpAssignOp OpAssign) - | TCast (e,None) -> loop e left + | TCast (e,None) | TMeta (_,e) -> loop e left | _ -> false in let e1 = if loop e1 true then parent e1 else e1 in @@ -905,7 +960,7 @@ let sanitize_expr com e = let rec loop ee = match ee.eexpr with | TBinop _ | TIf _ | TUnop _ -> parent e1 - | TCast (e,None) -> loop e + | TCast (e,None) | TMeta (_, e) -> loop e | _ -> e1 in { e with eexpr = TUnop (op,mode,loop e1)} @@ -986,191 +1041,58 @@ let rec sanitize com e = (* ---------------------------------------------------------------------- *) (* REDUCE *) -let optimize_binop e op e1 e2 = - let is_float t = - match follow t with - | TAbstract({ a_path = [],"Float" },_) -> true - | _ -> false - in - let is_numeric t = - match follow t with - | TAbstract({ a_path = [],("Float"|"Int") },_) -> true - | _ -> false - in - let check_float op f1 f2 = - let f = op f1 f2 in - let fstr = float_repres f in - if (match classify_float f with FP_nan | FP_infinite -> false | _ -> float_of_string fstr = f) then { e with eexpr = TConst (TFloat fstr) } else e - in - (match e1.eexpr, e2.eexpr with - | TConst (TInt 0l) , _ when op = OpAdd && is_numeric e2.etype -> e2 - | TConst (TInt 1l) , _ when op = OpMult -> e2 - | TConst (TFloat v) , _ when op = OpAdd && float_of_string v = 0. && is_float e2.etype -> e2 - | TConst (TFloat v) , _ when op = OpMult && float_of_string v = 1. && is_float e2.etype -> e2 - | _ , TConst (TInt 0l) when (match op with OpAdd -> is_numeric e1.etype | OpSub | OpShr | OpShl -> true | _ -> false) -> e1 (* bits operations might cause overflow *) - | _ , TConst (TInt 1l) when op = OpMult -> e1 - | _ , TConst (TFloat v) when (match op with OpAdd | OpSub -> float_of_string v = 0. && is_float e1.etype | _ -> false) -> e1 (* bits operations might cause overflow *) - | _ , TConst (TFloat v) when op = OpMult && float_of_string v = 1. && is_float e1.etype -> e1 - | TConst TNull, TConst TNull -> - (match op with - | OpEq -> { e with eexpr = TConst (TBool true) } - | OpNotEq -> { e with eexpr = TConst (TBool false) } - | _ -> e) - | TFunction _, TConst TNull -> - (match op with - | OpEq -> { e with eexpr = TConst (TBool false) } - | OpNotEq -> { e with eexpr = TConst (TBool true) } - | _ -> e) - | TConst TNull, TFunction _ -> - (match op with - | OpEq -> { e with eexpr = TConst (TBool false) } - | OpNotEq -> { e with eexpr = TConst (TBool true) } - | _ -> e) - | TConst (TInt a), TConst (TInt b) -> - let opt f = try { e with eexpr = TConst (TInt (f a b)) } with Exit -> e in - let check_overflow f = - opt (fun a b -> - let v = f (Int64.of_int32 a) (Int64.of_int32 b) in - let iv = Int64.to_int32 v in - if Int64.compare (Int64.of_int32 iv) v <> 0 then raise Exit; - iv - ) - in - let ebool t = - { e with eexpr = TConst (TBool (t (Int32.compare a b) 0)) } - in - (match op with - | OpAdd -> check_overflow Int64.add - | OpSub -> check_overflow Int64.sub - | OpMult -> check_overflow Int64.mul - | OpDiv -> check_float ( /. ) (Int32.to_float a) (Int32.to_float b) - | OpAnd -> opt Int32.logand - | OpOr -> opt Int32.logor - | OpXor -> opt Int32.logxor - | OpShl -> opt (fun a b -> Int32.shift_left a (Int32.to_int b)) - | OpShr -> opt (fun a b -> Int32.shift_right a (Int32.to_int b)) - | OpUShr -> opt (fun a b -> Int32.shift_right_logical a (Int32.to_int b)) - | OpEq -> ebool (=) - | OpNotEq -> ebool (<>) - | OpGt -> ebool (>) - | OpGte -> ebool (>=) - | OpLt -> ebool (<) - | OpLte -> ebool (<=) - | _ -> e) - | TConst ((TFloat _ | TInt _) as ca), TConst ((TFloat _ | TInt _) as cb) -> - let fa = (match ca with - | TFloat a -> float_of_string a - | TInt a -> Int32.to_float a - | _ -> assert false - ) in - let fb = (match cb with - | TFloat b -> float_of_string b - | TInt b -> Int32.to_float b - | _ -> assert false - ) in - let fop op = check_float op fa fb in - let ebool t = - { e with eexpr = TConst (TBool (t (compare fa fb) 0)) } - in - (match op with - | OpAdd -> fop (+.) - | OpDiv -> fop (/.) - | OpSub -> fop (-.) - | OpMult -> fop ( *. ) - | OpEq -> ebool (=) - | OpNotEq -> ebool (<>) - | OpGt -> ebool (>) - | OpGte -> ebool (>=) - | OpLt -> ebool (<) - | OpLte -> ebool (<=) - | _ -> e) - | TConst (TBool a), TConst (TBool b) -> - let ebool f = - { e with eexpr = TConst (TBool (f a b)) } - in - (match op with - | OpEq -> ebool (=) - | OpNotEq -> ebool (<>) - | OpBoolAnd -> ebool (&&) - | OpBoolOr -> ebool (||) - | _ -> e) - | TConst a, TConst b when op = OpEq || op = OpNotEq -> - let ebool b = - { e with eexpr = TConst (TBool (if op = OpEq then b else not b)) } - in - (match a, b with - | TInt a, TFloat b | TFloat b, TInt a -> ebool (Int32.to_float a = float_of_string b) - | _ -> ebool (a = b)) - | TConst (TBool a), _ -> - (match op with - | OpBoolAnd -> if a then e2 else { e with eexpr = TConst (TBool false) } - | OpBoolOr -> if a then { e with eexpr = TConst (TBool true) } else e2 - | _ -> e) - | _ , TConst (TBool a) -> - (match op with - | OpBoolAnd when a -> e1 - | OpBoolOr when not a -> e1 - | _ -> e) - | TField (_,FEnum (e1,f1)), TField (_,FEnum (e2,f2)) when e1 == e2 -> - (match op with - | OpEq -> { e with eexpr = TConst (TBool (f1 == f2)) } - | OpNotEq -> { e with eexpr = TConst (TBool (f1 != f2)) } - | _ -> e) - | _, TCall ({ eexpr = TField (_,FEnum _) },_) | TCall ({ eexpr = TField (_,FEnum _) },_), _ -> - (match op with - | OpAssign -> e - | _ -> - error "You cannot directly compare enums with arguments. Use either 'switch' or 'Type.enumEq'" e.epos) - | _ -> - e) - -let optimize_unop e op flag esub = - match op, esub.eexpr with - | Not, (TConst (TBool f) | TParenthesis({eexpr = TConst (TBool f)})) -> { e with eexpr = TConst (TBool (not f)) } - | Neg, TConst (TInt i) -> { e with eexpr = TConst (TInt (Int32.neg i)) } - | NegBits, TConst (TInt i) -> { e with eexpr = TConst (TInt (Int32.lognot i)) } - | Neg, TConst (TFloat f) -> - let v = 0. -. float_of_string f in - let vstr = float_repres v in - if float_of_string vstr = v then - { e with eexpr = TConst (TFloat vstr) } - else - e - | _ -> e - -let rec reduce_loop ctx e = - let e = Type.map_expr (reduce_loop ctx) e in - sanitize_expr ctx.com (match e.eexpr with +let reduce_control_flow ctx e = match e.eexpr with | TIf ({ eexpr = TConst (TBool t) },e1,e2) -> (if t then e1 else match e2 with None -> { e with eexpr = TBlock [] } | Some e -> e) | TWhile ({ eexpr = TConst (TBool false) },sub,flag) -> (match flag with | NormalWhile -> { e with eexpr = TBlock [] } (* erase sub *) | DoWhile -> e) (* we cant remove while since sub can contain continue/break *) + | TSwitch (e1,cases,def) -> + let e = match Texpr.skip e1 with + | {eexpr = TConst ct} as e1 -> + let rec loop cases = match cases with + | (el,e) :: cases -> + if List.exists (Texpr.equal e1) el then e + else loop cases + | [] -> + begin match def with + | None -> e + | Some e -> e + end + in + loop cases + | _ -> + e + in + e | TBinop (op,e1,e2) -> optimize_binop e op e1 e2 | TUnop (op,flag,esub) -> optimize_unop e op flag esub + | TCall ({ eexpr = TField (o,FClosure (c,cf)) } as f,el) -> + let fmode = (match c with None -> FAnon cf | Some (c,tl) -> FInstance (c,tl,cf)) in + { e with eexpr = TCall ({ f with eexpr = TField (o,fmode) },el) } + | _ -> + e + +let rec reduce_loop ctx e = + let e = Type.map_expr (reduce_loop ctx) e in + sanitize_expr ctx.com (match e.eexpr with | TCall ({ eexpr = TField ({ eexpr = TTypeExpr (TClassDecl c) },field) },params) -> (match api_inline ctx c (field_name field) params e.epos with | None -> reduce_expr ctx e | Some e -> reduce_loop ctx e) | TCall ({ eexpr = TFunction func } as ef,el) -> - let cf = mk_field "" ef.etype e.epos in + let cf = mk_field "" ef.etype e.epos null_pos in let ethis = mk (TConst TThis) t_dynamic e.epos in let rt = (match follow ef.etype with TFun (_,rt) -> rt | _ -> assert false) in let inl = (try type_inline ctx cf func ethis el rt None e.epos ~self_calling_closure:true false with Error (Custom _,_) -> None) in (match inl with | None -> reduce_expr ctx e | Some e -> reduce_loop ctx e) - | TCall ({ eexpr = TField (o,FClosure (c,cf)) } as f,el) -> - let fmode = (match c with None -> FAnon cf | Some (c,tl) -> FInstance (c,tl,cf)) in - { e with eexpr = TCall ({ f with eexpr = TField (o,fmode) },el) } - | TSwitch (e1,[[{eexpr = TConst (TBool true)}],{eexpr = TConst (TBool true)}],Some ({eexpr = TConst (TBool false)})) -> - (* introduced by extractors in some cases *) - e1 | _ -> - reduce_expr ctx e) + reduce_expr ctx (reduce_control_flow ctx e)) let reduce_expression ctx e = if ctx.com.foptimize then reduce_loop ctx e else e @@ -1179,11 +1101,14 @@ let rec make_constant_expression ctx ?(concat_strings=false) e = let e = reduce_loop ctx e in match e.eexpr with | TConst _ -> Some e - | TBinop ((OpAdd|OpSub|OpMult|OpDiv|OpMod) as op,e1,e2) -> (match make_constant_expression ctx e1,make_constant_expression ctx e2 with + | TBinop ((OpAdd|OpSub|OpMult|OpDiv|OpMod|OpShl|OpShr|OpUShr|OpOr|OpAnd|OpXor) as op,e1,e2) -> (match make_constant_expression ctx e1,make_constant_expression ctx e2 with | Some ({eexpr = TConst (TString s1)}), Some ({eexpr = TConst (TString s2)}) when concat_strings -> Some (mk (TConst (TString (s1 ^ s2))) ctx.com.basic.tstring (punion e1.epos e2.epos)) | Some e1, Some e2 -> Some (mk (TBinop(op, e1, e2)) e.etype e.epos) | _ -> None) + | TUnop((Neg | NegBits) as op,Prefix,e1) -> (match make_constant_expression ctx e1 with + | Some e1 -> Some (mk (TUnop(op,Prefix,e1)) e.etype e.epos) + | None -> None) | TCast (e1, None) -> (match make_constant_expression ctx e1 with | None -> None @@ -1200,7 +1125,8 @@ let rec make_constant_expression ctx ?(concat_strings=false) e = end | TTypeExpr _ -> Some e (* try to inline static function calls *) - | TCall ({ etype = TFun(_,ret); eexpr = TField (_,FStatic (c,cf)) },el) -> + (* Disabled for now, see #4254. *) +(* | TCall ({ etype = TFun(_,ret); eexpr = TField (_,FStatic (c,cf)) },el) -> (try let func = match cf.cf_expr with Some ({eexpr = TFunction func}) -> func | _ -> raise Not_found in let ethis = mk (TConst TThis) t_dynamic e.epos in @@ -1208,7 +1134,7 @@ let rec make_constant_expression ctx ?(concat_strings=false) e = (match inl with | None -> None | Some e -> make_constant_expression ctx e) - with Not_found -> None) + with Not_found -> None) *) | _ -> None (* ---------------------------------------------------------------------- *) @@ -1224,14 +1150,20 @@ let rec make_constant_expression ctx ?(concat_strings=false) e = We replace the variables by their fields lists, and the corresponding fields accesses as well *) -type inline_kind = - | IKCtor of tfunc * tclass_field * tclass * t list * texpr list * texpr list - | IKArray of texpr list * t - | IKStructure of (string * texpr) list - | IKNone +type inline_info_kind = + | IKCtor of tclass_field * bool + | IKStructure + | IKArray of int + +type inline_info = { + ii_var : tvar; + ii_expr : texpr; + ii_kind : inline_info_kind; + mutable ii_fields : (string,tvar) PMap.t; +} let inline_constructors ctx e = - let vars = ref PMap.empty in + let vars = ref IntMap.empty in let is_valid_ident s = try if String.length s = 0 then raise Exit; @@ -1249,220 +1181,227 @@ let inline_constructors ctx e = with Exit -> false in - let rec get_inline_ctor_info e = match e.eexpr with - | TNew ({ cl_constructor = Some ({ cf_kind = Method MethInline; cf_expr = Some { eexpr = TFunction f } } as cst) } as c,tl,pl) -> - IKCtor (f,cst,c,tl,pl,[]) - | TObjectDecl [] | TArrayDecl [] -> - IKNone - | TArrayDecl el -> - begin match follow e.etype with - | TInst({cl_path = [],"Array"},[t]) -> - IKArray(el,t) + let cancel v p = + try + let ii = IntMap.find v.v_id !vars in + vars := IntMap.remove v.v_id !vars; + v.v_id <- -v.v_id; + begin match ii.ii_kind with + | IKCtor(cf,true) -> + display_error ctx "Extern constructor could not be inlined" p; + error "Variable is used here" p; | _ -> - IKNone - end - | TObjectDecl fl -> - if (List.exists (fun (s,_) -> not (is_valid_ident s)) fl) then - IKNone - else - IKStructure fl - | TCast(e,None) | TParenthesis e -> - get_inline_ctor_info e - | TBlock el -> - begin match List.rev el with - | e :: el -> - begin match get_inline_ctor_info e with - | IKCtor(f,cst,c,tl,pl,e_init) -> - IKCtor(f,cst,c,tl,pl,(List.rev el) @ e_init) - | _ -> - IKNone - end - | [] -> - IKNone - end - | _ -> - IKNone - in - let check_field v s e t = - let (a,b,fields,c,d) = PMap.find (-v.v_id) !vars in - if not (List.exists (fun (s2,_,_) -> s = s2) fields) then - vars := PMap.add (-v.v_id) (a,b,(s,e,t) :: fields,c,d) !vars + () + end; + with Not_found -> + () in - let cancel v = + let add v e kind = + let ii = { + ii_var = v; + ii_fields = PMap.empty; + ii_expr = e; + ii_kind = kind + } in v.v_id <- -v.v_id; - (* error if the constructor is extern *) - (match PMap.find v.v_id !vars with - | _,_,_,true,p -> - display_error ctx "Extern constructor could not be inlined" p; - error "Variable is used here" e.epos - | _ -> ()); - vars := PMap.remove v.v_id !vars; + vars := IntMap.add v.v_id ii !vars; in - let rec skip_to_var e = match e.eexpr with - | TLocal v when v.v_id < 0 -> Some v - (* | TCast(e1,None) | TMeta(_,e1) | TParenthesis(e1) -> skip_to_var e1 *) - | _ -> None + let get_field_var v s = + let ii = IntMap.find v.v_id !vars in + PMap.find s ii.ii_fields in - let rec find_locals e = - match e.eexpr with - | TVar (v,eo) -> - Type.iter find_locals e; - begin match eo with - | Some n -> - begin match get_inline_ctor_info n with - | IKCtor (f,cst,c,tl,pl,el_init) when type_iseq v.v_type n.etype -> - (* inline the constructor *) - (match (try type_inline ctx cst f (mk (TLocal v) (TInst (c,tl)) n.epos) pl ctx.t.tvoid None n.epos true with Error (Custom _,_) -> None) with - | None -> () - | Some ecst -> - let assigns = ref [] in - (* add field inits here because the filter has not run yet (issue #2336) *) - List.iter (fun cf -> match cf.cf_kind,cf.cf_expr with - | Var _,Some e -> assigns := (cf.cf_name,e,cf.cf_type) :: !assigns - | _ -> () - ) c.cl_ordered_fields; - (* make sure we only have v.field = expr calls *) - let rec get_assigns e = - match e.eexpr with - | TBlock el -> - List.iter get_assigns el - | TBinop (OpAssign, { eexpr = TField ({ eexpr = TLocal vv },FInstance(_,_,cf)); etype = t }, e) when v == vv -> - assigns := (cf.cf_name,e,t) :: !assigns - | _ -> - raise Exit - in - try - get_assigns ecst; - (* mark variable as candidate for inlining *) - vars := PMap.add v.v_id (v,el_init,List.rev !assigns,c.cl_extern || Meta.has Meta.Extern cst.cf_meta,n.epos) !vars; - v.v_id <- -v.v_id; (* mark *) - (* recurse with the constructor code which will be inlined here *) - find_locals ecst - with Exit -> - ()) - | IKArray (el,t) -> - vars := PMap.add v.v_id (v,[],ExtList.List.mapi (fun i e -> string_of_int i,e,t) el, false, n.epos) !vars; - v.v_id <- -v.v_id; - | IKStructure fl -> - vars := PMap.add v.v_id (v,[],List.map (fun (s,e) -> s,e,e.etype) fl, false, n.epos) !vars; - v.v_id <- -v.v_id; - | _ -> + let add_field_var v s t = + let ii = IntMap.find v.v_id !vars in + let v' = alloc_var (Printf.sprintf "%s_%s" v.v_name s) t v.v_pos in + v'.v_meta <- (Meta.InlineConstructorVariable,[],v.v_pos) :: v'.v_meta; + ii.ii_fields <- PMap.add s v' ii.ii_fields; + v' + in + let int_field_name i = + if i < 0 then "n" ^ (string_of_int (-i)) + else (string_of_int i) + in + let rec find_locals e = match e.eexpr with + | TVar(v,Some e1) -> + find_locals e1; + let rec loop el_init e1 = match e1.eexpr with + | TBlock el -> + begin match List.rev el with + | e1 :: el -> + loop (el @ el_init) e1 + | [] -> () end - | _ -> () - end - | TField(e1, (FInstance(_, _, {cf_kind = Var _; cf_name = s}) | FAnon({cf_kind = Var _; cf_name = s}))) -> - (match skip_to_var e1 with None -> find_locals e1 | Some _ -> ()) - | TArray (e1,{eexpr = TConst (TInt i)}) -> - begin match skip_to_var e1 with - | None -> find_locals e1 - | Some v -> - let (_,_,fields,_,_) = PMap.find (-v.v_id) !vars in - let i = Int32.to_int i in - if i < 0 || i >= List.length fields then cancel v - end - | TBinop((OpAssign | OpAssignOp _),e1,e2) -> - begin match e1.eexpr with - | TArray ({eexpr = TLocal v},{eexpr = TConst (TInt i)}) when v.v_id < 0 -> - check_field v (Int32.to_string i) e2 e2.etype - | TField({eexpr = TLocal v}, (FInstance(_, _, {cf_kind = Var _; cf_name = s}) | FAnon({cf_kind = Var _; cf_name = s}))) when v.v_id < 0 -> - check_field v s e2 e2.etype + | TNew({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction tf})} as cf)} as c,tl,pl) when type_iseq v.v_type e1.etype -> + begin match type_inline ctx cf tf (mk (TLocal v) (TInst (c,tl)) e1.epos) pl ctx.t.tvoid None e1.epos true with + | Some e -> + (* add field inits here because the filter has not run yet (issue #2336) *) + let ev = mk (TLocal v) v.v_type e.epos in + let el_init = List.fold_left (fun acc cf -> match cf.cf_kind,cf.cf_expr with + | Var _,Some e -> + let ef = mk (TField(ev,FInstance(c,tl,cf))) cf.cf_type e.epos in + let e = mk (TBinop(OpAssign,ef,e)) cf.cf_type e.epos in + e :: acc + | _ -> acc + ) el_init c.cl_ordered_fields in + let e' = match el_init with + | [] -> e + | _ -> mk (TBlock (List.rev (e :: el_init))) e.etype e.epos + in + add v e' (IKCtor(cf,c.cl_extern || Meta.has Meta.Extern cf.cf_meta)); + find_locals e + | None -> + () + end + | TObjectDecl fl when fl <> [] -> + begin try + let ev = mk (TLocal v) v.v_type e.epos in + let el = List.fold_left (fun acc (s,e) -> + if not (is_valid_ident s) then raise Exit; + let ef = mk (TField(ev,FDynamic s)) e.etype e.epos in + let e = mk (TBinop(OpAssign,ef,e)) e.etype e.epos in + e :: acc + ) el_init fl in + let e = mk (TBlock (List.rev el)) ctx.t.tvoid e.epos in + add v e IKStructure + with Exit -> + () + end + | TArrayDecl el -> + let ev = mk (TLocal v) v.v_type e.epos in + let el,_ = List.fold_left (fun (acc,i) e -> + let ef = mk (TField(ev,FDynamic (string_of_int i))) e.etype e.epos in + let e = mk (TBinop(OpAssign,ef,e)) e.etype e.epos in + e :: acc,i + 1 + ) (el_init,0) el in + let e = mk (TBlock (List.rev el)) ctx.t.tvoid e.epos in + add v e (IKArray (List.length el)) + | TCast(e1,None) | TParenthesis e1 -> + loop el_init e1 | _ -> - find_locals e1 - end; + () + in + loop [] e1 + | TBinop(OpAssign,({eexpr = TField({eexpr = TLocal v},fa)} as e1),e2) when v.v_id < 0 -> + let s = field_name fa in + (try ignore(get_field_var v s) with Not_found -> ignore(add_field_var v s e1.etype)); find_locals e2 + | TField({eexpr = TLocal v},fa) when v.v_id < 0 -> + begin match extract_field fa with + | Some ({cf_kind = Var _} as cf) -> + (* Arrays are not supposed to have public var fields, besides "length" (which we handle when inlining), + however, its inlined methods may generate access to private implementation fields (such as internal + native array), in this case we have to cancel inlining. + *) + if cf.cf_name <> "length" then + begin match (IntMap.find v.v_id !vars).ii_kind with + | IKArray _ -> cancel v e.epos + | _ -> (try ignore(get_field_var v cf.cf_name) with Not_found -> ignore(add_field_var v cf.cf_name e.etype)); + end + | _ -> cancel v e.epos + end + | TArray({eexpr = TLocal v},{eexpr = TConst (TInt i)}) when v.v_id < 0 -> + let i = Int32.to_int i in + begin try + let ii = IntMap.find v.v_id !vars in + let l = match ii.ii_kind with + | IKArray l -> l + | _ -> raise Not_found + in + if i < 0 || i >= l then raise Not_found; + with Not_found -> + cancel v e.epos + end | TLocal v when v.v_id < 0 -> - cancel v + cancel v e.epos; | _ -> Type.iter find_locals e in find_locals e; - let vars = !vars in - if PMap.is_empty vars then - e - else begin - let vfields = PMap.map (fun (v,el_init,assigns,_,_) -> - (List.fold_left (fun (acc,map) (name,e,t) -> - let vf = alloc_var (v.v_name ^ "_" ^ name) t in - ((vf,e) :: acc, PMap.add name vf map) - ) ([],PMap.empty) assigns),el_init - ) vars in - let el_b = ref [] in - let append e = el_b := e :: !el_b in - let inline_field c cf v = - let (_, vars),el_init = PMap.find (-v.v_id) vfields in - (try - let v = PMap.find cf.cf_name vars in - mk (TLocal v) v.v_type e.epos - with Not_found -> - if (c.cl_path = ([],"Array") && cf.cf_name = "length") then begin - (* this can only occur for inlined array declarations, so we can use the statically known length here (issue #2568)*) - let l = PMap.fold (fun _ i -> i + 1) vars 0 in - mk (TConst (TInt (Int32.of_int l))) ctx.t.tint e.epos - end else - (* the variable was not set in the constructor, assume null *) - mk (TConst TNull) e.etype e.epos) - in - let inline_anon_field cf v = - let (_, vars),_ = PMap.find (-v.v_id) vfields in - (try - let v = PMap.find cf.cf_name vars in - mk (TLocal v) v.v_type e.epos - with Not_found -> - (* this could happen in untyped code, assume null *) - mk (TConst TNull) e.etype e.epos) - in - let inline_array_access i v = - let (_, vars),_ = PMap.find (-v.v_id) vfields in - (try - let v = PMap.find (Int32.to_string i) vars in - mk (TLocal v) v.v_type e.epos - with Not_found -> - (* probably out-of-bounds, assume null *) - mk (TConst TNull) e.etype e.epos) - in - let rec subst e = - match e.eexpr with + (* Pass 2 *) + let inline v p = + try + let ii = IntMap.find v.v_id !vars in + let el = PMap.fold (fun v acc -> (mk (TVar(v,None)) ctx.t.tvoid p) :: acc) ii.ii_fields [] in + let e = {ii.ii_expr with eexpr = TBlock (el @ [ii.ii_expr])} in + Some e + with Not_found -> + None + in + let assign_or_declare v name e2 t p = + try + let v = get_field_var v name in + let e1 = mk (TLocal v) t p in + mk (TBinop(OpAssign,e1,e2)) e1.etype p + with Not_found -> + let v = add_field_var v name t in + mk (TVar(v,Some e2)) ctx.t.tvoid e.epos + in + let use_local_or_null v name t p = + try + let v' = get_field_var v name in + mk (TLocal v') t p + with Not_found -> try + if name <> "length" then raise Not_found; + let ii = IntMap.find v.v_id !vars in + begin match ii.ii_kind with + | IKArray l -> mk (TConst (TInt (Int32.of_int l))) ctx.t.tint p + | _ -> raise Not_found + end + with Not_found -> + mk (TConst TNull) t p + in + let flatten e = + let el = ref [] in + let rec loop e = match e.eexpr with | TBlock el -> - let old = !el_b in - el_b := []; - List.iter (fun e -> append (subst e)) el; - let n = !el_b in - el_b := old; - {e with eexpr = TBlock (List.rev n)} - | TVar (v,Some e) when v.v_id < 0 -> - let (vars, _),el_init = PMap.find (-v.v_id) vfields in - List.iter (fun e -> - append (subst e) - ) el_init; - let (v_first,e_first),vars = match vars with - | v :: vl -> v,vl - | [] -> assert false - in - List.iter (fun (v,e) -> append (mk (TVar(v,Some (subst e))) ctx.t.tvoid e.epos)) (List.rev vars); - mk (TVar (v_first, Some (subst e_first))) ctx.t.tvoid e.epos - | TField (e1,FInstance (c,_,cf)) -> - begin match skip_to_var e1 with - | None -> Type.map_expr subst e - | Some v -> inline_field c cf v - end - | TArray (e1,{eexpr = TConst (TInt i)}) -> - begin match skip_to_var e1 with - | None -> Type.map_expr subst e - | Some v -> inline_array_access i v - end - | TField (e1,FAnon(cf)) -> - begin match skip_to_var e1 with - | None -> Type.map_expr subst e - | Some v -> inline_anon_field cf v - end + List.iter loop el | _ -> - Type.map_expr subst e + el := e :: !el in - let e = (try subst e with Not_found -> assert false) in - PMap.iter (fun _ (v,_,_,_,_) -> v.v_id <- -v.v_id) vars; - e - end + loop e; + let e = mk (TBlock (List.rev !el)) e.etype e.epos in + mk (TMeta((Meta.MergeBlock,[],e.epos),e)) e.etype e.epos + in + let rec loop e = match e.eexpr with + | TVar(v,_) when v.v_id < 0 -> + begin match inline v e.epos with + | Some e -> + let e = flatten e in + loop e + | None -> + cancel v e.epos; + e + end + | TBinop(OpAssign,({eexpr = TField({eexpr = TLocal v},fa)} as e1),e2) when v.v_id < 0 -> + let e2 = loop e2 in + assign_or_declare v (field_name fa) e2 e1.etype e.epos + | TField({eexpr = TLocal v},fa) when v.v_id < 0 -> + use_local_or_null v (field_name fa) e.etype e.epos + | TBinop(OpAssign,({eexpr = TArray({eexpr = TLocal v},{eexpr = TConst (TInt i)})} as e1),e2) when v.v_id < 0 -> + let e2 = loop e2 in + let name = int_field_name (Int32.to_int i) in + assign_or_declare v name e2 e1.etype e.epos + | TArray({eexpr = TLocal v},{eexpr = TConst (TInt i)}) when v.v_id < 0 -> + use_local_or_null v (int_field_name (Int32.to_int i)) e.etype e.epos + | TBlock el -> + let rec block acc el = match el with + | e1 :: el -> + begin match loop e1 with + | {eexpr = TMeta((Meta.MergeBlock,_,_),{eexpr = TBlock el2})} -> + let acc = block acc el2 in + block acc el + | e -> block (e :: acc) el + end + | [] -> + acc + in + let el = block [] el in + mk (TBlock (List.rev el)) e.etype e.epos + | _ -> + Type.map_expr loop e + in + loop e (* ---------------------------------------------------------------------- *) (* COMPLETION *) @@ -1508,10 +1447,10 @@ let optimize_completion_expr e = ()); map e | EVars vl -> - let vl = List.map (fun (v,t,e) -> + let vl = List.map (fun ((v,pv),t,e) -> let e = (match e with None -> None | Some e -> Some (loop e)) in - decl v t e; - (v,t,e) + decl v (Option.map fst t) e; + ((v,pv),t,e) ) vl in (EVars vl,p) | EBlock el -> @@ -1520,7 +1459,7 @@ let optimize_completion_expr e = let el = List.fold_left (fun acc e -> typing_side_effect := false; let e = loop e in - if !typing_side_effect then begin told := true; e :: acc end else acc + if !typing_side_effect || Display.is_display_position (pos e) then begin told := true; e :: acc end else acc ) [] el in old(); typing_side_effect := !told; @@ -1531,7 +1470,7 @@ let optimize_completion_expr e = | Some name -> decl name None (Some e)); let old = save() in - List.iter (fun (n,_,t,e) -> decl n t e) f.f_args; + List.iter (fun ((n,_),_,_,t,e) -> decl n (Option.map fst t) e) f.f_args; let e = map e in old(); e @@ -1540,7 +1479,7 @@ let optimize_completion_expr e = let old = save() in let etmp = (EConst (Ident "$tmp"),p) in decl n None (Some (EBlock [ - (EVars ["$tmp",None,None],p); + (EVars [("$tmp",null_pos),None,None],p); (EFor ((EIn (id,it),p),(EBinop (OpAssign,etmp,(EConst (Ident n),p)),p)),p); etmp ],p)); @@ -1552,9 +1491,9 @@ let optimize_completion_expr e = map e | ESwitch (e,cases,def) -> let e = loop e in - let cases = List.map (fun (el,eg,eo) -> match eo with + let cases = List.map (fun (el,eg,eo,p) -> match eo with | None -> - el,eg,eo + el,eg,eo,p | Some e -> let el = List.map loop el in let old = save() in @@ -1570,22 +1509,22 @@ let optimize_completion_expr e = ) el; let e = loop e in old(); - el, eg, Some e + el, eg, Some e, p ) cases in let def = match def with | None -> None - | Some None -> Some None - | Some (Some e) -> Some (Some (loop e)) + | Some (None,p) -> Some (None,p) + | Some (Some e,p) -> Some (Some (loop e),p) in (ESwitch (e,cases,def),p) | ETry (et,cl) -> let et = loop et in - let cl = List.map (fun (n,t,e) -> + let cl = List.map (fun ((n,pn),(t,pt),e,p) -> let old = save() in decl n (Some t) None; let e = loop e in old(); - n, t, e + (n,pn), (t,pt), e, p ) cl in (ETry (et,cl),p) | EDisplay (s,call) -> @@ -1598,14 +1537,14 @@ let optimize_completion_expr e = let p = snd e in (try (match PMap.find n locals.r with - | Some t , _ -> (ECheckType ((EConst (Ident "null"),p),t),p) + | Some t , _ -> (ECheckType ((EConst (Ident "null"),p),(t,p)),p) | _, Some (id,e,lc) -> let name = (try PMap.find id (!tmp_hlocals) with Not_found -> let e = subst_locals lc e in let name = "$tmp_" ^ string_of_int id in - tmp_locals := (name,None,Some e) :: !tmp_locals; + tmp_locals := ((name,null_pos),None,Some e) :: !tmp_locals; tmp_hlocals := PMap.add id name !tmp_hlocals; name ) in @@ -1617,7 +1556,10 @@ let optimize_completion_expr e = (* not found locals are most likely to be member/static vars *) e) | EFunction (_,f) -> - Ast.map_expr (subst_locals { r = PMap.foldi (fun n i acc -> if List.exists (fun (a,_,_,_) -> a = n) f.f_args then acc else PMap.add n i acc) locals.r PMap.empty }) e + Ast.map_expr (subst_locals { r = PMap.foldi (fun n i acc -> if List.exists (fun ((a,_),_,_,_,_) -> a = n) f.f_args then acc else PMap.add n i acc) locals.r PMap.empty }) e + | EObjectDecl [] -> + (* this probably comes from { | completion so we need some context} *) + raise Exit | _ -> Ast.map_expr (subst_locals locals) e in diff --git a/src/optimization/optimizerTexpr.ml b/src/optimization/optimizerTexpr.ml new file mode 100644 index 00000000..ae703076 --- /dev/null +++ b/src/optimization/optimizerTexpr.ml @@ -0,0 +1,306 @@ +open Ast +open Type +open Error +open Globals + +(* + PurityState represents whether or not something has a side-effect. Unless otherwise stated + by using `@:pure` (equivalent to `@:pure(true)`) or `@:pure(false)`, fields are originally + supposed to be "maybe pure". Once all types and fields are known, this is refined by + AnalyzerTexpr.Purity. + + There's a special case for fields that override a parent class field or implement an + interface field: If the overridden/implemented field is explicitly marked as pure, + the type loader marks the overriding/implementing as "expected pure". If during purity + inference this assumption does not hold, an error is shown. +*) +module PurityState = struct + type t = + | Pure + | Impure + | MaybePure + | ExpectPure of pos + + let get_purity_from_meta meta = + try + begin match Meta.get Meta.Pure meta with + | (_,[EConst(Ident s),p],_) -> + begin match s with + | "true" -> Pure + | "false" -> Impure + | "expect" -> ExpectPure p + | _ -> error ("Unsupported purity value " ^ s ^ ", expected true or false") p + end + | (_,[],_) -> + Pure + | (_,_,p) -> + error "Unsupported purity value" p + end + with Not_found -> + MaybePure + + let get_purity c cf = match get_purity_from_meta cf.cf_meta with + | Pure -> Pure + | Impure -> Impure + | ExpectPure p -> ExpectPure p + | _ -> get_purity_from_meta c.cl_meta + + let is_pure c cf = get_purity c cf = Pure + + let is_pure_field_access fa = match fa with + | FInstance(c,_,cf) | FClosure(Some(c,_),cf) | FStatic(c,cf) -> is_pure c cf + | FAnon cf | FClosure(None,cf) -> (get_purity_from_meta cf.cf_meta = Pure) + | FEnum _ -> true + | FDynamic _ -> false + + let to_string = function + | Pure -> "pure" + | Impure -> "impure" + | MaybePure -> "maybe" + | ExpectPure _ -> "expect" +end + +(* tells if an expression causes side effects. This does not account for potential null accesses (fields/arrays/ops) *) +let has_side_effect e = + let rec loop e = + match e.eexpr with + | TConst _ | TLocal _ | TTypeExpr _ | TFunction _ -> () + | TCall({eexpr = TField(e1,fa)},el) when PurityState.is_pure_field_access fa -> loop e1; List.iter loop el + | TNew(c,_,el) when (match c.cl_constructor with Some cf when PurityState.is_pure c cf -> true | _ -> false) -> List.iter loop el + | TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit + | TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit + | TArray _ | TEnumParameter _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ | TFor _ + | TField _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TBlock _ | TObjectDecl _ | TVar _ -> Type.iter loop e + in + try + loop e; false + with Exit -> + true + +let rec is_exhaustive e1 = match e1.eexpr with + | TMeta((Meta.Exhaustive,_,_),_) -> true + | TMeta(_, e1) | TParenthesis e1 -> is_exhaustive e1 + | _ -> false + + +let is_read_only_field_access e fa = match fa with + | FEnum _ -> + true + | FDynamic _ -> + false + | FAnon {cf_kind = Var {v_write = AccNo}} when (match e.eexpr with TLocal v when is_unbound v -> true | _ -> false) -> true + | FInstance (c,_,cf) | FStatic (c,cf) | FClosure (Some(c,_),cf) -> + begin match cf.cf_kind with + | Method MethDynamic -> false + | Method _ -> true + | Var {v_write = AccNever} when not c.cl_interface -> true + | _ -> false + end + | FAnon cf | FClosure(None,cf) -> + begin match cf.cf_kind with + | Method MethDynamic -> false + | Method _ -> true + | _ -> false + end + +let create_affection_checker () = + let modified_locals = Hashtbl.create 0 in + let rec might_be_affected e = + let rec loop e = match e.eexpr with + | TConst _ | TFunction _ | TTypeExpr _ -> () + | TLocal v when Hashtbl.mem modified_locals v.v_id -> raise Exit + | TField(e1,fa) when not (is_read_only_field_access e1 fa) -> raise Exit + | TCall _ | TNew _ -> raise Exit + | _ -> Type.iter loop e + in + try + loop e; + false + with Exit -> + true + in + let rec collect_modified_locals e = match e.eexpr with + | TUnop((Increment | Decrement),_,{eexpr = TLocal v}) -> + Hashtbl.add modified_locals v.v_id true + | TBinop((OpAssign | OpAssignOp _),{eexpr = TLocal v},e2) -> + collect_modified_locals e2; + Hashtbl.add modified_locals v.v_id true + | _ -> + Type.iter collect_modified_locals e + in + might_be_affected,collect_modified_locals + +let optimize_binop e op e1 e2 = + let is_float t = + match follow t with + | TAbstract({ a_path = [],"Float" },_) -> true + | _ -> false + in + let is_numeric t = + match follow t with + | TAbstract({ a_path = [],("Float"|"Int") },_) -> true + | _ -> false + in + let check_float op f1 f2 = + let f = op f1 f2 in + let fstr = Common.float_repres f in + if (match classify_float f with FP_nan | FP_infinite -> false | _ -> float_of_string fstr = f) then { e with eexpr = TConst (TFloat fstr) } else e + in + (match e1.eexpr, e2.eexpr with + | TConst (TInt 0l) , _ when op = OpAdd && is_numeric e2.etype -> e2 + | TConst (TInt 1l) , _ when op = OpMult -> e2 + | TConst (TFloat v) , _ when op = OpAdd && float_of_string v = 0. && is_float e2.etype -> e2 + | TConst (TFloat v) , _ when op = OpMult && float_of_string v = 1. && is_float e2.etype -> e2 + | _ , TConst (TInt 0l) when (match op with OpAdd -> is_numeric e1.etype | OpSub | OpShr | OpShl -> true | _ -> false) -> e1 (* bits operations might cause overflow *) + | _ , TConst (TInt 1l) when op = OpMult -> e1 + | _ , TConst (TFloat v) when (match op with OpAdd | OpSub -> float_of_string v = 0. && is_float e1.etype | _ -> false) -> e1 (* bits operations might cause overflow *) + | _ , TConst (TFloat v) when op = OpMult && float_of_string v = 1. && is_float e1.etype -> e1 + | TConst TNull, TConst TNull -> + (match op with + | OpEq -> { e with eexpr = TConst (TBool true) } + | OpNotEq -> { e with eexpr = TConst (TBool false) } + | _ -> e) + | TFunction _, TConst TNull -> + (match op with + | OpEq -> { e with eexpr = TConst (TBool false) } + | OpNotEq -> { e with eexpr = TConst (TBool true) } + | _ -> e) + | TConst TNull, TFunction _ -> + (match op with + | OpEq -> { e with eexpr = TConst (TBool false) } + | OpNotEq -> { e with eexpr = TConst (TBool true) } + | _ -> e) + | TConst (TInt a), TConst (TInt b) -> + let opt f = try { e with eexpr = TConst (TInt (f a b)) } with Exit -> e in + let check_overflow f = + opt (fun a b -> + let v = f (Int64.of_int32 a) (Int64.of_int32 b) in + let iv = Int64.to_int32 v in + if Int64.compare (Int64.of_int32 iv) v <> 0 then raise Exit; + iv + ) + in + let ebool t = + { e with eexpr = TConst (TBool (t (Int32.compare a b) 0)) } + in + (match op with + | OpAdd -> check_overflow Int64.add + | OpSub -> check_overflow Int64.sub + | OpMult -> check_overflow Int64.mul + | OpDiv -> check_float ( /. ) (Int32.to_float a) (Int32.to_float b) + | OpAnd -> opt Int32.logand + | OpOr -> opt Int32.logor + | OpXor -> opt Int32.logxor + | OpShl -> opt (fun a b -> Int32.shift_left a (Int32.to_int b)) + | OpShr -> opt (fun a b -> Int32.shift_right a (Int32.to_int b)) + | OpUShr -> opt (fun a b -> Int32.shift_right_logical a (Int32.to_int b)) + | OpEq -> ebool (=) + | OpNotEq -> ebool (<>) + | OpGt -> ebool (>) + | OpGte -> ebool (>=) + | OpLt -> ebool (<) + | OpLte -> ebool (<=) + | _ -> e) + | TConst ((TFloat _ | TInt _) as ca), TConst ((TFloat _ | TInt _) as cb) -> + let fa = (match ca with + | TFloat a -> float_of_string a + | TInt a -> Int32.to_float a + | _ -> assert false + ) in + let fb = (match cb with + | TFloat b -> float_of_string b + | TInt b -> Int32.to_float b + | _ -> assert false + ) in + let fop op = check_float op fa fb in + let ebool t = + { e with eexpr = TConst (TBool (t (compare fa fb) 0)) } + in + (match op with + | OpAdd -> fop (+.) + | OpDiv -> fop (/.) + | OpSub -> fop (-.) + | OpMult -> fop ( *. ) + | OpEq -> ebool (=) + | OpNotEq -> ebool (<>) + | OpGt -> ebool (>) + | OpGte -> ebool (>=) + | OpLt -> ebool (<) + | OpLte -> ebool (<=) + | _ -> e) + | TConst (TString ""),TConst (TString s) | TConst (TString s),TConst (TString "") when op = OpAdd -> + {e with eexpr = TConst (TString s)} + | TConst (TBool a), TConst (TBool b) -> + let ebool f = + { e with eexpr = TConst (TBool (f a b)) } + in + (match op with + | OpEq -> ebool (=) + | OpNotEq -> ebool (<>) + | OpBoolAnd -> ebool (&&) + | OpBoolOr -> ebool (||) + | _ -> e) + | TConst a, TConst b when op = OpEq || op = OpNotEq -> + let ebool b = + { e with eexpr = TConst (TBool (if op = OpEq then b else not b)) } + in + (match a, b with + | TInt a, TFloat b | TFloat b, TInt a -> ebool (Int32.to_float a = float_of_string b) + | _ -> ebool (a = b)) + | TConst (TBool a), _ -> + (match op with + | OpBoolAnd -> if a then e2 else { e with eexpr = TConst (TBool false) } + | OpBoolOr -> if a then { e with eexpr = TConst (TBool true) } else e2 + | _ -> e) + | _ , TConst (TBool a) -> + (match op with + | OpBoolAnd when a -> e1 + | OpBoolOr when not a -> e1 + | _ -> e) + | TField (_,FEnum (e1,f1)), TField (_,FEnum (e2,f2)) when e1 == e2 -> + (match op with + | OpEq -> { e with eexpr = TConst (TBool (f1 == f2)) } + | OpNotEq -> { e with eexpr = TConst (TBool (f1 != f2)) } + | _ -> e) + | _, TCall ({ eexpr = TField (_,FEnum _) },_) | TCall ({ eexpr = TField (_,FEnum _) },_), _ -> + (match op with + | OpAssign -> e + | _ -> + error "You cannot directly compare enums with arguments. Use either 'switch' or 'Type.enumEq'" e.epos) + | _ -> + e) + +let optimize_unop e op flag esub = + let is_int t = match follow t with + | TAbstract({a_path = [],"Int"},_) -> true + | _ -> false + in + match op, esub.eexpr with + | Not, (TConst (TBool f) | TParenthesis({eexpr = TConst (TBool f)})) -> { e with eexpr = TConst (TBool (not f)) } + | Not, (TBinop(op,e1,e2) | TParenthesis({eexpr = TBinop(op,e1,e2)})) -> + begin + let is_int = is_int e1.etype && is_int e2.etype in + try + let op = match is_int, op with + | true, OpGt -> OpLte + | true, OpGte -> OpLt + | true, OpLt -> OpGte + | true, OpLte -> OpGt + | _, OpEq -> OpNotEq + | _, OpNotEq -> OpEq + | _ -> raise Exit + in + {e with eexpr = TBinop(op,e1,e2)} + with Exit -> + e + end + | Neg, TConst (TInt i) -> { e with eexpr = TConst (TInt (Int32.neg i)) } + | NegBits, TConst (TInt i) -> { e with eexpr = TConst (TInt (Int32.lognot i)) } + | Neg, TConst (TFloat f) -> + let v = 0. -. float_of_string f in + let vstr = Common.float_repres v in + if float_of_string vstr = v then + { e with eexpr = TConst (TFloat vstr) } + else + e + | _ -> e \ No newline at end of file diff --git a/src/path.ml b/src/path.ml new file mode 100644 index 00000000..a3b75cfa --- /dev/null +++ b/src/path.ml @@ -0,0 +1,148 @@ +let get_path_parts f = + (* + this function is quite weird: it tries to determine whether the given + argument is a .hx file path with slashes or a dotted module path and + based on that it returns path "parts", which are basically a list of + either folders or packages (which are folders too) appended by the module name + + TODO: i started doubting my sanity while writing this comment, let's somehow + refactor this stuff so it doesn't mix up file and module paths and doesn't introduce + the weird "path part" entity. + *) + let l = String.length f in + if l > 3 && (String.sub f (l-3) 3) = ".hx" then + let f = String.sub f 0 (l-3) in (* strip the .hx *) + ExtString.String.nsplit (String.concat "/" (ExtString.String.nsplit f "\\")) "/" (* TODO: wouldn't it be faster to Str.split here? *) + else + ExtString.String.nsplit f "." + +let parse_path f = + let cl = get_path_parts f in + let error msg = + let msg = "Could not process argument " ^ f ^ "\n" ^ msg in + failwith msg + in + let invalid_char x = + for i = 1 to String.length x - 1 do + match x.[i] with + | 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' -> () + | c -> error ("invalid character: " ^ (String.make 1 c)) + done + in + let rec loop = function + | [] -> + error "empty part" + | [x] -> + invalid_char x; + [],x + | x :: l -> + if String.length x = 0 then + error "empty part" + else if x.[0] < 'a' || x.[0] > 'z' then + error "Package name must start with a lower case character"; + invalid_char x; + let path,name = loop l in + x :: path,name + in + loop cl + +let starts_uppercase x = + x.[0] = '_' || (x.[0] >= 'A' && x.[0] <= 'Z') + +let check_uppercase x = + if String.length x = 0 then + failwith "empty part" + else if not (starts_uppercase x) then + failwith "Class name must start with uppercase character" + +let parse_type_path s = + let pack,name = parse_path s in + check_uppercase name; + pack,name + +let path_regex = Str.regexp "[/\\]+" +let normalize_path path = + let rec normalize acc m = + match m with + | [] -> + List.rev acc + | Str.Text "." :: Str.Delim _ :: tl when acc = [] -> + normalize [] tl + | Str.Text ".." :: Str.Delim _ :: tl -> + (match acc with + | [] -> raise Exit + | _ :: acc -> normalize acc tl) + | Str.Text t :: Str.Delim _ :: tl -> + normalize (t :: acc) tl + | Str.Delim _ :: tl -> + normalize ("" :: acc) tl + | Str.Text t :: [] -> + List.rev (t :: acc) + | Str.Text _ :: Str.Text _ :: _ -> + assert false + in + String.concat "/" (normalize [] (Str.full_split path_regex path)) + +let path_sep = if Globals.is_windows then "\\" else "/" + +(** Returns absolute path. Doesn't fix path case on Windows. *) +let get_full_path f = try Extc.get_full_path f with _ -> f + +(** Returns absolute path (on Windows ensures proper case with drive letter upper-cased) + Use for returning positions from IDE support functions *) +let get_real_path = + if Globals.is_windows then + (fun p -> try Extc.get_real_path p with _ -> p) + else + get_full_path + +(** Returns absolute path guaranteed to be the same for different letter case. + Use where equality comparison is required, lowercases the path on Windows *) +let unique_full_path = + if Globals.is_windows then + (fun f -> String.lowercase (get_full_path f)) + else + get_full_path + +let add_trailing_slash p = + let l = String.length p in + if l = 0 then + "./" + else match p.[l-1] with + | '\\' | '/' -> p + | _ -> p ^ "/" + +let rec remove_trailing_slash p = + let l = String.length p in + if l = 0 then + "./" + else match p.[l-1] with + | '\\' | '/' -> remove_trailing_slash (String.sub p 0 (l - 1)) + | _ -> p + +open Globals + +let find_directories target recursive paths = + let target_dirs = List.map platform_name platforms in + let rec loop acc dir = + try + let entries = Sys.readdir dir in + Array.fold_left (fun acc file -> + match file with + | "." | ".." -> + acc + | _ when Sys.is_directory (dir ^ file) && file.[0] >= 'a' && file.[0] <= 'z' -> + if List.mem file target_dirs && file <> target then + acc + else begin + let full = (dir ^ file) in + if recursive then loop (full :: acc) (full ^ "/") + else full :: acc + end + | _ -> + acc + ) acc entries; + with Sys_error _ -> + acc + in + List.fold_left (fun acc dir -> loop acc dir) [] paths \ No newline at end of file diff --git a/src/server.ml b/src/server.ml new file mode 100644 index 00000000..c1ef7f05 --- /dev/null +++ b/src/server.ml @@ -0,0 +1,637 @@ +open Printf +open Globals +open Ast +open Common +open Common.DisplayMode +open Type +open DisplayOutput + +exception Dirty of module_def + +let measure_times = ref false +let prompt = ref false +let start_time = ref (get_time()) + +let is_debug_run() = + try Sys.getenv "HAXEDEBUG" = "1" with _ -> false + +type context = { + com : Common.context; + mutable flush : unit -> unit; + mutable setup : unit -> unit; + mutable messages : string list; + mutable has_next : bool; + mutable has_error : bool; +} + +let report_times print = + let tot = ref 0. in + Hashtbl.iter (fun _ t -> tot := !tot +. t.total) Common.htimers; + if !tot > 0. then begin + let buckets = Hashtbl.create 0 in + let add id time calls = + try + let time',calls' = Hashtbl.find buckets id in + Hashtbl.replace buckets id (time' +. time,calls' + calls) + with Not_found -> + Hashtbl.add buckets id (time,calls) + in + Hashtbl.iter (fun _ t -> + let rec loop acc ids = match ids with + | id :: ids -> + add (List.rev (id :: acc)) t.total t.calls; + loop (id :: acc) ids + | [] -> + () + in + loop [] t.id + ) Common.htimers; + let max_name = ref 0 in + let max_calls = ref 0 in + let timers = Hashtbl.fold (fun id t acc -> + let name,indent = match List.rev id with + | [] -> assert false + | name :: l -> name,(String.make (List.length l * 2) ' ') + in + let name,info = try + let i = String.rindex name '.' in + String.sub name (i + 1) (String.length name - i - 1),String.sub name 0 i + with Not_found -> + name,"" + in + let name = indent ^ name in + if String.length name > !max_name then max_name := String.length name; + if snd t > !max_calls then max_calls := snd t; + (id,name,info,t) :: acc + ) buckets [] in + let max_calls = String.length (string_of_int !max_calls) in + print (Printf.sprintf "%-*s | %7s | %% | %*s | info" !max_name "name" "time(s)" max_calls "#"); + let sep = String.make (!max_name + max_calls + 21) '-' in + print sep; + let timers = List.sort (fun (id1,_,_,_) (id2,_,_,_) -> compare id1 id2) timers in + let print_timer id name info (time,calls) = + print (Printf.sprintf "%-*s | %7.3f | %3.0f | %*i | %s" !max_name name time (time *. 100. /. !tot) max_calls calls info) + in + List.iter (fun (id,name,info,t) -> print_timer id name info t) timers; + print sep; + print_timer ["total"] "total" "" (!tot,0) + end + +let default_flush ctx = + List.iter prerr_endline (List.rev ctx.messages); + if ctx.has_error && !prompt then begin + print_endline "Press enter to exit..."; + ignore(read_line()); + end; + if ctx.has_error then exit 1 + +let create_context params = + let ctx = { + com = Common.create version s_version params; + flush = (fun()->()); + setup = (fun()->()); + messages = []; + has_next = false; + has_error = false; + } in + ctx.flush <- (fun() -> default_flush ctx); + ctx + +let parse_hxml_data data = + let lines = Str.split (Str.regexp "[\r\n]+") data in + List.concat (List.map (fun l -> + let l = unquote (ExtString.String.strip l) in + if l = "" || l.[0] = '#' then + [] + else if l.[0] = '-' then + try + let a, b = ExtString.String.split l " " in + [unquote a; unquote (ExtString.String.strip b)] + with + _ -> [l] + else + [l] + ) lines) + +let parse_hxml file = + let ch = IO.input_channel (try open_in_bin file with _ -> raise Not_found) in + let data = IO.read_all ch in + IO.close_in ch; + parse_hxml_data data + +let ssend sock str = + let rec loop pos len = + if len = 0 then + () + else + let s = Unix.send sock str pos len [] in + loop (pos + s) (len - s) + in + loop 0 (String.length str) + +let rec wait_loop process_params verbose accept = + Sys.catch_break false; + let has_parse_error = ref false in + let cs = CompilationServer.create () in + let sign_string com = + let sign = get_signature com in + let sign_id = + try + CompilationServer.get_sign cs sign; + with Not_found -> + let i = CompilationServer.add_sign cs sign in + print_endline (Printf.sprintf "Found context %s:\n%s" i (dump_context com)); + i + in + Printf.sprintf "%2s,%3s: " sign_id (short_platform_name com.platform) + in + MacroContext.macro_enable_cache := true; + let current_stdin = ref None in + Typeload.parse_hook := (fun com2 file p -> + let ffile = Path.unique_full_path file in + let is_display_file = ffile = (!Parser.resume_display).pfile in + + match is_display_file, !current_stdin with + | true, Some stdin when Common.defined com2 Define.DisplayStdin -> + Typeload.parse_file_from_string com2 file p stdin + | _ -> + let sign = get_signature com2 in + let ftime = file_time ffile in + let fkey = (ffile,sign) in + try + let time, data = CompilationServer.find_file cs fkey in + if time <> ftime then raise Not_found; + data + with Not_found -> + has_parse_error := false; + let data = Typeload.parse_file com2 file p in + let info,is_unusual = if !has_parse_error then "not cached, has parse error",true + else if is_display_file then "not cached, is display file",true + else begin try + (* We assume that when not in display mode it's okay to cache stuff that has #if display + checks. The reasoning is that non-display mode has more information than display mode. *) + if not com2.display.dms_display then raise Not_found; + let ident = Hashtbl.find Parser.special_identifier_files ffile in + Printf.sprintf "not cached, using \"%s\" define" ident,true + with Not_found -> + CompilationServer.cache_file cs fkey (ftime,data); + "cached",false + end in + if verbose && is_unusual then print_endline (Printf.sprintf "%sparsed %s (%s)" (sign_string com2) ffile info); + data + ); + let check_module_shadowing com paths m = + List.iter (fun (path,_) -> + let file = (path ^ (snd m.m_path)) ^ ".hx" in + if Sys.file_exists file then begin + let time = file_time file in + if time > m.m_extra.m_time then begin + if verbose then print_endline (Printf.sprintf "%smodule path might have changed: %s\n\twas: %2.0f %s\n\tnow: %2.0f %s" + (sign_string com) (s_type_path m.m_path) m.m_extra.m_time m.m_extra.m_file time file); + raise Not_found + end + end + ) paths + in + let delays = ref [] in + let changed_directories = Hashtbl.create 0 in + let arguments = Hashtbl.create 0 in + let stat dir = + (Unix.stat (Path.remove_trailing_slash dir)).Unix.st_mtime + in + let get_changed_directories (ctx : Typecore.typer) = + let t = Common.timer ["server";"module cache";"changed dirs"] in + let com = ctx.Typecore.com in + let sign = get_signature com in + let dirs = try + (* First, check if we already have determined changed directories for current compilation. *) + Hashtbl.find changed_directories sign + with Not_found -> + let dirs = try + (* Next, get all directories from the cache and filter the ones that haven't changed. *) + let all_dirs = CompilationServer.find_directories cs sign in + List.fold_left (fun acc (dir,time) -> + try + let time' = stat dir in + if !time < time' then begin + time := time'; + let sub_dirs = Path.find_directories (platform_name com.platform) false [dir] in + List.iter (fun dir -> + if not (CompilationServer.has_directory cs sign dir) then begin + let time = stat dir in + if verbose then print_endline (Printf.sprintf "%sadded directory %s" (sign_string com) dir); + CompilationServer.add_directory cs sign (dir,ref time) + end; + ) sub_dirs; + (dir,time') :: acc + end else + acc + with Unix.Unix_error _ -> + CompilationServer.remove_directory cs sign dir; + if verbose then print_endline (Printf.sprintf "%sremoved directory %s" (sign_string com) dir); + acc + ) [] all_dirs + with Not_found -> + (* There were no directories in the cache, so this must be a new context. Let's add + an empty list to make sure no crazy recursion happens. *) + CompilationServer.add_directories cs sign []; + (* Register the delay that is going to populate the cache dirs. *) + delays := (fun () -> + let dirs = ref [] in + let add_dir path = + try + let time = stat path in + dirs := (path,ref time) :: !dirs + with Unix.Unix_error _ -> + () + in + List.iter add_dir com.class_path; + List.iter add_dir (Path.find_directories (platform_name com.platform) true com.class_path); + if verbose then print_endline (Printf.sprintf "%sfound %i directories" (sign_string com) (List.length !dirs)); + CompilationServer.add_directories cs sign !dirs + ) :: !delays; + (* Returning [] should be fine here because it's a new context, so we won't do any + shadowing checks anyway. *) + [] + in + Hashtbl.add changed_directories sign dirs; + dirs + in + t(); + dirs + in + let compilation_step = ref 0 in + let compilation_mark = ref 0 in + let mark_loop = ref 0 in + Typeload.type_module_hook := (fun (ctx:Typecore.typer) mpath p -> + let t = Common.timer ["server";"module cache"] in + let com2 = ctx.Typecore.com in + let sign = get_signature com2 in + let content_changed m file = + let ffile = Path.unique_full_path file in + let fkey = (ffile,sign) in + try + let _, old_data = CompilationServer.find_file cs fkey in + (* We must use the module path here because the file path is absolute and would cause + positions in the parsed declarations to differ. *) + let new_data = Typeload.parse_module ctx m.m_path p in + snd old_data <> snd new_data + with Not_found -> + true + in + incr mark_loop; + let mark = !mark_loop in + let start_mark = !compilation_mark in + let rec check m = + let check_module_path () = + let directories = get_changed_directories ctx in + match m.m_extra.m_kind with + | MFake | MSub | MImport -> () (* don't get classpath *) + | MExtern -> + (* if we have a file then this will override our extern type *) + let has_file = (try check_module_shadowing com2 directories m; true with Not_found -> false) in + if has_file then begin + if verbose then print_endline ("A file is masking the library file " ^ s_type_path m.m_path); + raise Not_found; + end; + let rec loop = function + | [] -> + if verbose then print_endline ("No library file was found for " ^ s_type_path m.m_path); + raise Not_found (* no extern registration *) + | load :: l -> + match load m.m_path p with + | None -> loop l + | Some (file,_) -> + if Path.unique_full_path file <> m.m_extra.m_file then begin + if verbose then print_endline ("Library file was changed for " ^ s_type_path m.m_path); + raise Not_found; + end + in + loop com2.load_extern_type + | MCode -> check_module_shadowing com2 directories m + | MMacro when ctx.Typecore.in_macro -> check_module_shadowing com2 directories m + | MMacro -> + let _, mctx = MacroContext.get_macro_context ctx p in + check_module_shadowing mctx.Typecore.com (get_changed_directories mctx) m + in + let has_policy policy = List.mem policy m.m_extra.m_check_policy in + let check_file () = + if file_time m.m_extra.m_file <> m.m_extra.m_time then begin + if has_policy CheckFileContentModification && not (content_changed m m.m_extra.m_file) then begin + if verbose then print_endline (Printf.sprintf "%s%s changed time not but content, reusing" (sign_string com2) m.m_extra.m_file) + end else begin + if verbose then print_endline (Printf.sprintf "%s%s not cached (%s)" (sign_string com2) (s_type_path m.m_path) (if m.m_extra.m_time = -1. then "macro-in-macro" else "modified")); + if m.m_extra.m_kind = MFake then Hashtbl.remove Typecore.fake_modules m.m_extra.m_file; + raise Not_found; + end + end + in + let check_dependencies () = + PMap.iter (fun _ m2 -> match check m2 with + | None -> () + | Some m -> raise (Dirty m) + ) m.m_extra.m_deps; + in + begin match m.m_extra.m_dirty with + | Some m -> + Some m + | None -> + if m.m_extra.m_mark = mark then + None + else try + if m.m_extra.m_mark <= start_mark then begin + if not (has_policy NoCheckShadowing) then check_module_path(); + if not (has_policy NoCheckFileTimeModification) then check_file(); + end; + m.m_extra.m_mark <- mark; + if not (has_policy NoCheckDependencies) then check_dependencies(); + None + with + | Not_found -> + m.m_extra.m_dirty <- Some m; + Some m + | Dirty m' -> + m.m_extra.m_dirty <- Some m'; + Some m' + end + in + let rec add_modules tabs m0 m = + if m.m_extra.m_added < !compilation_step then begin + (match m0.m_extra.m_kind, m.m_extra.m_kind with + | MCode, MMacro | MMacro, MCode -> + (* this was just a dependency to check : do not add to the context *) + PMap.iter (Hashtbl.replace com2.resources) m.m_extra.m_binded_res; + | _ -> + (*if verbose then print_endline (Printf.sprintf "%s%sreusing %s" (sign_string com2) tabs (s_type_path m.m_path));*) + m.m_extra.m_added <- !compilation_step; + List.iter (fun t -> + match t with + | TClassDecl c -> c.cl_restore() + | TEnumDecl e -> + let rec loop acc = function + | [] -> () + | (Meta.RealPath,[Ast.EConst (Ast.String path),_],_) :: l -> + e.e_path <- Ast.parse_path path; + e.e_meta <- (List.rev acc) @ l; + | x :: l -> loop (x::acc) l + in + loop [] e.e_meta + | TAbstractDecl a -> + a.a_meta <- List.filter (fun (m,_,_) -> m <> Meta.ValueUsed) a.a_meta + | _ -> () + ) m.m_types; + if m.m_extra.m_kind <> MSub then Typeload.add_module ctx m p; + PMap.iter (Hashtbl.replace com2.resources) m.m_extra.m_binded_res; + if ctx.Typecore.in_macro || com2.display.dms_full_typing then + PMap.iter (fun _ m2 -> add_modules (tabs ^ " ") m0 m2) m.m_extra.m_deps; + List.iter (MacroContext.call_init_macro ctx) m.m_extra.m_macro_calls + ) + end + in + try + let m = CompilationServer.find_module cs (mpath,sign) in + let tcheck = Common.timer ["server";"module cache";"check"] in + begin match check m with + | None -> () + | Some m' -> + if verbose then print_endline (Printf.sprintf "%sskipping %s%s" (sign_string com2) (s_type_path m.m_path) (if m == m' then "" else Printf.sprintf "(%s)" (s_type_path m'.m_path))); + tcheck(); + raise Not_found; + end; + tcheck(); + let tadd = Common.timer ["server";"module cache";"add modules"] in + add_modules "" m m; + tadd(); + t(); + Some m + with Not_found -> + t(); + None + ); + let run_count = ref 0 in + while true do + let read, write, close = accept() in + let rec cache_context com = + let cache_module m = + CompilationServer.cache_module cs (m.m_path,m.m_extra.m_sign) m; + (*if verbose then print_endline (Printf.sprintf "%scached %s" (sign_string com) (s_type_path m.m_path));*) + in + if com.display.dms_full_typing then begin + List.iter cache_module com.modules; + if verbose then print_endline ("Cached " ^ string_of_int (List.length com.modules) ^ " modules"); + end; + match com.get_macros() with + | None -> () + | Some com -> cache_context com + in + let create params = + let ctx = create_context params in + ctx.flush <- (fun() -> + incr compilation_step; + compilation_mark := !mark_loop; + List.iter (fun s -> write (s ^ "\n"); if verbose then print_endline ("> " ^ s)) (List.rev ctx.messages); + if ctx.has_error then begin + measure_times := false; + write "\x02\n" + end else cache_context ctx.com; + ); + ctx.setup <- (fun() -> + let sign = get_signature ctx.com in + if verbose then begin + let defines = PMap.foldi (fun k v acc -> (k ^ "=" ^ v) :: acc) ctx.com.defines [] in + print_endline ("Defines " ^ (String.concat "," (List.sort compare defines))); + print_endline ("Using signature " ^ Digest.to_hex sign); + print_endline ("Display position: " ^ (Printer.s_pos !Parser.resume_display)); + end; + Parser.display_error := (fun e p -> has_parse_error := true; ctx.com.error (Parser.error_msg e) p); + if ctx.com.display.dms_display then begin + let file = (!Parser.resume_display).pfile in + let fkey = (file,sign) in + (* force parsing again : if the completion point have been changed *) + CompilationServer.remove_file cs fkey; + CompilationServer.taint_modules cs file; + end; + try + if (Hashtbl.find arguments sign) <> ctx.com.class_path then begin + if verbose then print_endline (Printf.sprintf "%sclass paths changed, resetting directories" (sign_string ctx.com)); + Hashtbl.replace arguments sign ctx.com.class_path; + CompilationServer.clear_directories cs sign; + end; + with Not_found -> + Hashtbl.add arguments sign ctx.com.class_path; + () + ); + ctx.com.print <- (fun str -> write ("\x01" ^ String.concat "\x01" (ExtString.String.nsplit str "\n") ^ "\n")); + ctx + in + (try + let s = read() in + let t0 = get_time() in + let hxml = + try + let idx = String.index s '\001' in + current_stdin := Some (String.sub s (idx + 1) ((String.length s) - idx - 1)); + (String.sub s 0 idx) + with Not_found -> + s + in + let data = parse_hxml_data hxml in + if verbose then print_endline ("Processing Arguments [" ^ String.concat "," data ^ "]"); + (try + Hashtbl.clear changed_directories; + Common.display_default := DMNone; + Parser.resume_display := null_pos; + Typeload.return_partial_type := false; + measure_times := false; + close_times(); + stats.s_files_parsed := 0; + stats.s_classes_built := 0; + stats.s_methods_typed := 0; + stats.s_macros_called := 0; + Hashtbl.clear Common.htimers; + let _ = Common.timer ["other"] in + incr compilation_step; + compilation_mark := !mark_loop; + start_time := get_time(); + process_params create data; + close_times(); + if !measure_times then report_times (fun s -> write (s ^ "\n")) + with + | Completion str -> + if verbose then print_endline ("Completion Response =\n" ^ str); + write str + | Arg.Bad msg -> + prerr_endline ("Error: " ^ msg); + ); + let fl = !delays in + delays := []; + List.iter (fun f -> f()) fl; + if verbose then begin + print_endline (Printf.sprintf "Stats = %d files, %d classes, %d methods, %d macros" !(stats.s_files_parsed) !(stats.s_classes_built) !(stats.s_methods_typed) !(stats.s_macros_called)); + print_endline (Printf.sprintf "Time spent : %.3fs" (get_time() -. t0)); + end; + with Unix.Unix_error _ -> + if verbose then print_endline "Connection Aborted" + | e -> + let estr = Printexc.to_string e in + if verbose then print_endline ("Uncaught Error : " ^ estr); + (try write estr with _ -> ()); + if is_debug_run() then print_endline (Printexc.get_backtrace()); + ); + close(); + current_stdin := None; + (* prevent too much fragmentation by doing some compactions every X run *) + incr run_count; + if !run_count mod 10 = 0 then begin + let t0 = get_time() in + Gc.compact(); + if verbose then begin + let stat = Gc.quick_stat() in + let size = (float_of_int stat.Gc.heap_words) *. 4. in + print_endline (Printf.sprintf "Compacted memory %.3fs %.1fMB" (get_time() -. t0) (size /. (1024. *. 1024.))); + end + end else Gc.minor(); + done + +and init_wait_stdio() = + set_binary_mode_in stdin true; + set_binary_mode_out stderr true; + + let chin = IO.input_channel stdin in + let cherr = IO.output_channel stderr in + + let berr = Buffer.create 0 in + let read = fun () -> + let len = IO.read_i32 chin in + IO.really_nread chin len + in + let write = Buffer.add_string berr in + let close = fun() -> + IO.write_i32 cherr (Buffer.length berr); + IO.nwrite cherr (Buffer.contents berr); + IO.flush cherr + in + fun() -> + Buffer.clear berr; + read, write, close + +and init_wait_socket verbose host port = + let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in + (try Unix.setsockopt sock Unix.SO_REUSEADDR true with _ -> ()); + (try Unix.bind sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with _ -> failwith ("Couldn't wait on " ^ host ^ ":" ^ string_of_int port)); + if verbose then print_endline ("Waiting on " ^ host ^ ":" ^ string_of_int port); + Unix.listen sock 10; + let bufsize = 1024 in + let tmp = String.create bufsize in + let accept() = ( + let sin, _ = Unix.accept sock in + Unix.set_nonblock sin; + if verbose then print_endline "Client connected"; + let b = Buffer.create 0 in + let rec read_loop count = + try + let r = Unix.recv sin tmp 0 bufsize [] in + if r = 0 then + failwith "Incomplete request" + else begin + if verbose then Printf.printf "Reading %d bytes\n" r; + Buffer.add_substring b tmp 0 r; + if tmp.[r-1] = '\000' then + Buffer.sub b 0 (Buffer.length b - 1) + else + read_loop 0 + end + with Unix.Unix_error((Unix.EWOULDBLOCK|Unix.EAGAIN),_,_) -> + if count = 100 then + failwith "Aborting inactive connection" + else begin + if verbose then print_endline "Waiting for data..."; + ignore(Unix.select [] [] [] 0.05); (* wait a bit *) + read_loop (count + 1); + end + in + let read = fun() -> (let s = read_loop 0 in Unix.clear_nonblock sin; s) in + let write = ssend sin in + let close() = Unix.close sin in + read, write, close + ) in + accept + +and do_connect host port args = + let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in + (try Unix.connect sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with _ -> failwith ("Couldn't connect on " ^ host ^ ":" ^ string_of_int port)); + let args = ("--cwd " ^ Unix.getcwd()) :: args in + ssend sock (String.concat "" (List.map (fun a -> a ^ "\n") args) ^ "\000"); + let has_error = ref false in + let rec print line = + match (if line = "" then '\x00' else line.[0]) with + | '\x01' -> + print_string (String.concat "\n" (List.tl (ExtString.String.nsplit line "\x01"))); + flush stdout + | '\x02' -> + has_error := true; + | _ -> + prerr_endline line; + in + let buf = Buffer.create 0 in + let process() = + let lines = ExtString.String.nsplit (Buffer.contents buf) "\n" in + (* the last line ends with \n *) + let lines = (match List.rev lines with "" :: l -> List.rev l | _ -> lines) in + List.iter print lines; + in + let tmp = String.create 1024 in + let rec loop() = + let b = Unix.recv sock tmp 0 1024 [] in + Buffer.add_substring buf tmp 0 b; + if b > 0 then begin + if String.get tmp (b - 1) = '\n' then begin + process(); + Buffer.reset buf; + end; + loop(); + end + in + loop(); + process(); + if !has_error then exit 1 \ No newline at end of file diff --git a/src/syntax/ast.ml b/src/syntax/ast.ml new file mode 100644 index 00000000..08e11efc --- /dev/null +++ b/src/syntax/ast.ml @@ -0,0 +1,869 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Globals + +type keyword = + | Function + | Class + | Var + | If + | Else + | While + | Do + | For + | Break + | Continue + | Return + | Extends + | Implements + | Import + | Switch + | Case + | Default + | Static + | Public + | Private + | Try + | Catch + | New + | This + | Throw + | Extern + | Enum + | In + | Interface + | Untyped + | Cast + | Override + | Typedef + | Dynamic + | Package + | Inline + | Using + | Null + | True + | False + | Abstract + | Macro + +type binop = + | OpAdd + | OpMult + | OpDiv + | OpSub + | OpAssign + | OpEq + | OpNotEq + | OpGt + | OpGte + | OpLt + | OpLte + | OpAnd + | OpOr + | OpXor + | OpBoolAnd + | OpBoolOr + | OpShl + | OpShr + | OpUShr + | OpMod + | OpAssignOp of binop + | OpInterval + | OpArrow + +type unop = + | Increment + | Decrement + | Not + | Neg + | NegBits + +type constant = + | Int of string + | Float of string + | String of string + | Ident of string + | Regexp of string * string + +type token = + | Eof + | Const of constant + | Kwd of keyword + | Comment of string + | CommentLine of string + | Binop of binop + | Unop of unop + | Semicolon + | Comma + | BrOpen + | BrClose + | BkOpen + | BkClose + | POpen + | PClose + | Dot + | DblDot + | Arrow + | IntInterval of string + | Sharp of string + | Question + | At + | Dollar of string + +type unop_flag = + | Prefix + | Postfix + +type while_flag = + | NormalWhile + | DoWhile + +type type_path = { + tpackage : string list; + tname : string; + tparams : type_param_or_const list; + tsub : string option; +} + +and placed_type_path = type_path * pos + +and type_param_or_const = + | TPType of type_hint + | TPExpr of expr + +and complex_type = + | CTPath of type_path + | CTFunction of type_hint list * type_hint + | CTAnonymous of class_field list + | CTParent of type_hint + | CTExtend of placed_type_path list * class_field list + | CTOptional of type_hint + +and type_hint = complex_type * pos + +and func = { + f_params : type_param list; + f_args : (placed_name * bool * metadata * type_hint option * expr option) list; + f_type : type_hint option; + f_expr : expr option; +} + +and placed_name = string * pos + +and expr_def = + | EConst of constant + | EArray of expr * expr + | EBinop of binop * expr * expr + | EField of expr * string + | EParenthesis of expr + | EObjectDecl of (placed_name * expr) list + | EArrayDecl of expr list + | ECall of expr * expr list + | ENew of placed_type_path * expr list + | EUnop of unop * unop_flag * expr + | EVars of (placed_name * type_hint option * expr option) list + | EFunction of string option * func + | EBlock of expr list + | EFor of expr * expr + | EIn of expr * expr + | EIf of expr * expr * expr option + | EWhile of expr * expr * while_flag + | ESwitch of expr * (expr list * expr option * expr option * pos) list * (expr option * pos) option + | ETry of expr * (placed_name * type_hint * expr * pos) list + | EReturn of expr option + | EBreak + | EContinue + | EUntyped of expr + | EThrow of expr + | ECast of expr * type_hint option + | EDisplay of expr * bool + | EDisplayNew of placed_type_path + | ETernary of expr * expr * expr + | ECheckType of expr * type_hint + | EMeta of metadata_entry * expr + +and expr = expr_def * pos + +and type_param = { + tp_name : placed_name; + tp_params : type_param list; + tp_constraints : type_hint list; + tp_meta : metadata; +} + +and documentation = string option + +and metadata_entry = (Meta.strict_meta * expr list * pos) +and metadata = metadata_entry list + +and access = + | APublic + | APrivate + | AStatic + | AOverride + | ADynamic + | AInline + | AMacro + +and class_field_kind = + | FVar of type_hint option * expr option + | FFun of func + | FProp of placed_name * placed_name * type_hint option * expr option + +and class_field = { + cff_name : placed_name; + cff_doc : documentation; + cff_pos : pos; + mutable cff_meta : metadata; + mutable cff_access : access list; + mutable cff_kind : class_field_kind; +} + +type enum_flag = + | EPrivate + | EExtern + +type class_flag = + | HInterface + | HExtern + | HPrivate + | HExtends of placed_type_path + | HImplements of placed_type_path + +type abstract_flag = + | APrivAbstract + | AFromType of type_hint + | AToType of type_hint + | AIsType of type_hint + | AExtern + +type enum_constructor = { + ec_name : placed_name; + ec_doc : documentation; + ec_meta : metadata; + ec_args : (string * bool * type_hint) list; + ec_pos : pos; + ec_params : type_param list; + ec_type : type_hint option; +} + +type ('a,'b) definition = { + d_name : placed_name; + d_doc : documentation; + d_params : type_param list; + d_meta : metadata; + d_flags : 'a list; + d_data : 'b; +} + +type import_mode = + | INormal + | IAsName of string + | IAll + +type import = placed_name list * import_mode + +type type_def = + | EClass of (class_flag, class_field list) definition + | EEnum of (enum_flag, enum_constructor list) definition + | ETypedef of (enum_flag, type_hint) definition + | EAbstract of (abstract_flag, class_field list) definition + | EImport of import + | EUsing of placed_name list + +type type_decl = type_def * pos + +type package = string list * type_decl list + +let is_lower_ident i = + let rec loop p = + match String.unsafe_get i p with + | 'a'..'z' -> true + | '_' -> if p + 1 < String.length i then loop (p + 1) else true + | _ -> false + in + loop 0 + +let pos = snd + +let rec is_postfix (e,_) op = match op with + | Increment | Decrement | Not -> true + | Neg | NegBits -> false + +let is_prefix = function + | Increment | Decrement -> true + | Not | Neg | NegBits -> true + +let base_class_name = snd + +let punion p p2 = + { + pfile = p.pfile; + pmin = min p.pmin p2.pmin; + pmax = max p.pmax p2.pmax; + } + +let rec punion_el el = match el with + | [] -> + null_pos + | (_,p) :: [] -> + p + | (_,p) :: el -> + punion p (punion_el el) + +let parse_path s = + match List.rev (ExtString.String.nsplit s ".") with + | [] -> failwith "Invalid empty path" + | x :: l -> List.rev l, x + +let s_escape ?(hex=true) s = + let b = Buffer.create (String.length s) in + for i = 0 to (String.length s) - 1 do + match s.[i] with + | '\n' -> Buffer.add_string b "\\n" + | '\t' -> Buffer.add_string b "\\t" + | '\r' -> Buffer.add_string b "\\r" + | '"' -> Buffer.add_string b "\\\"" + | '\\' -> Buffer.add_string b "\\\\" + | c when int_of_char c < 32 && hex -> Buffer.add_string b (Printf.sprintf "\\x%.2X" (int_of_char c)) + | c -> Buffer.add_char b c + done; + Buffer.contents b + +let s_constant = function + | Int s -> s + | Float s -> s + | String s -> "\"" ^ s_escape s ^ "\"" + | Ident s -> s + | Regexp (r,o) -> "~/" ^ r ^ "/" + +let s_access = function + | APublic -> "public" + | APrivate -> "private" + | AStatic -> "static" + | AOverride -> "override" + | ADynamic -> "dynamic" + | AInline -> "inline" + | AMacro -> "macro" + +let s_keyword = function + | Function -> "function" + | Class -> "class" + | Static -> "static" + | Var -> "var" + | If -> "if" + | Else -> "else" + | While -> "while" + | Do -> "do" + | For -> "for" + | Break -> "break" + | Return -> "return" + | Continue -> "continue" + | Extends -> "extends" + | Implements -> "implements" + | Import -> "import" + | Switch -> "switch" + | Case -> "case" + | Default -> "default" + | Private -> "private" + | Public -> "public" + | Try -> "try" + | Catch -> "catch" + | New -> "new" + | This -> "this" + | Throw -> "throw" + | Extern -> "extern" + | Enum -> "enum" + | In -> "in" + | Interface -> "interface" + | Untyped -> "untyped" + | Cast -> "cast" + | Override -> "override" + | Typedef -> "typedef" + | Dynamic -> "dynamic" + | Package -> "package" + | Inline -> "inline" + | Using -> "using" + | Null -> "null" + | True -> "true" + | False -> "false" + | Abstract -> "abstract" + | Macro -> "macro" + +let rec s_binop = function + | OpAdd -> "+" + | OpMult -> "*" + | OpDiv -> "/" + | OpSub -> "-" + | OpAssign -> "=" + | OpEq -> "==" + | OpNotEq -> "!=" + | OpGte -> ">=" + | OpLte -> "<=" + | OpGt -> ">" + | OpLt -> "<" + | OpAnd -> "&" + | OpOr -> "|" + | OpXor -> "^" + | OpBoolAnd -> "&&" + | OpBoolOr -> "||" + | OpShr -> ">>" + | OpUShr -> ">>>" + | OpShl -> "<<" + | OpMod -> "%" + | OpAssignOp op -> s_binop op ^ "=" + | OpInterval -> "..." + | OpArrow -> "=>" + +let s_unop = function + | Increment -> "++" + | Decrement -> "--" + | Not -> "!" + | Neg -> "-" + | NegBits -> "~" + +let s_token = function + | Eof -> "" + | Const c -> s_constant c + | Kwd k -> s_keyword k + | Comment s -> "/*"^s^"*/" + | CommentLine s -> "//"^s + | Binop o -> s_binop o + | Unop o -> s_unop o + | Semicolon -> ";" + | Comma -> "," + | BkOpen -> "[" + | BkClose -> "]" + | BrOpen -> "{" + | BrClose -> "}" + | POpen -> "(" + | PClose -> ")" + | Dot -> "." + | DblDot -> ":" + | Arrow -> "->" + | IntInterval s -> s ^ "..." + | Sharp s -> "#" ^ s + | Question -> "?" + | At -> "@" + | Dollar v -> "$" ^ v + +exception Invalid_escape_sequence of char * int + +let unescape s = + let b = Buffer.create 0 in + let rec loop esc i = + if i = String.length s then + () + else + let c = s.[i] in + let fail () = raise (Invalid_escape_sequence(c,i)) in + if esc then begin + let inext = ref (i + 1) in + (match c with + | 'n' -> Buffer.add_char b '\n' + | 'r' -> Buffer.add_char b '\r' + | 't' -> Buffer.add_char b '\t' + | '"' | '\'' | '\\' -> Buffer.add_char b c + | '0'..'3' -> + let c = (try char_of_int (int_of_string ("0o" ^ String.sub s i 3)) with _ -> fail()) in + Buffer.add_char b c; + inext := !inext + 2; + | 'x' -> + let c = (try char_of_int (int_of_string ("0x" ^ String.sub s (i+1) 2)) with _ -> fail()) in + Buffer.add_char b c; + inext := !inext + 2; + | 'u' -> + let (u, a) = + try + (int_of_string ("0x" ^ String.sub s (i+1) 4), 4) + with _ -> try + assert (s.[i+1] = '{'); + let l = String.index_from s (i+3) '}' - (i+2) in + let u = int_of_string ("0x" ^ String.sub s (i+2) l) in + assert (u <= 0x10FFFF); + (u, l+2) + with _ -> + fail() + in + let ub = UTF8.Buf.create 0 in + UTF8.Buf.add_char ub (UChar.uchar_of_int u); + Buffer.add_string b (UTF8.Buf.contents ub); + inext := !inext + a; + | _ -> + fail()); + loop false !inext; + end else + match c with + | '\\' -> loop true (i + 1) + | c -> + Buffer.add_char b c; + loop false (i + 1) + in + loop false 0; + Buffer.contents b + +let map_expr loop (e,p) = + let opt f o = + match o with None -> None | Some v -> Some (f v) + in + let rec tparam = function + | TPType t -> TPType (type_hint t) + | TPExpr e -> TPExpr (loop e) + and cfield f = + { f with cff_kind = (match f.cff_kind with + | FVar (t,e) -> + let t = opt type_hint t in + let e = opt loop e in + FVar (t,e) + | FFun f -> FFun (func f) + | FProp (get,set,t,e) -> + let t = opt type_hint t in + let e = opt loop e in + FProp (get,set,t,e)) + } + and type_hint (t,p) = (match t with + | CTPath t -> CTPath { t with tparams = List.map tparam t.tparams } + | CTFunction (cl,c) -> + let cl = List.map type_hint cl in + let c = type_hint c in + CTFunction (cl,c) + | CTAnonymous fl -> CTAnonymous (List.map cfield fl) + | CTParent t -> CTParent (type_hint t) + | CTExtend (tl,fl) -> + let tl = List.map tpath tl in + let fl = List.map cfield fl in + CTExtend (tl,fl) + | CTOptional t -> CTOptional (type_hint t)),p + and tparamdecl t = + let constraints = List.map type_hint t.tp_constraints in + let params = List.map tparamdecl t.tp_params in + { tp_name = t.tp_name; tp_constraints = constraints; tp_params = params; tp_meta = t.tp_meta } + and func f = + let params = List.map tparamdecl f.f_params in + let args = List.map (fun (n,o,m,t,e) -> + let t = opt type_hint t in + let e = opt loop e in + n,o,m,t,e + ) f.f_args in + let t = opt type_hint f.f_type in + let e = opt loop f.f_expr in + { + f_params = params; + f_args = args; + f_type = t; + f_expr = e; + } + and tpath (t,p) = { t with tparams = List.map tparam t.tparams },p + in + let e = (match e with + | EConst _ -> e + | EArray (e1,e2) -> + let e1 = loop e1 in + let e2 = loop e2 in + EArray (e1,e2) + | EBinop (op,e1,e2) -> + let e1 = loop e1 in + let e2 = loop e2 in + EBinop (op,e1,e2) + | EField (e,f) -> EField (loop e, f) + | EParenthesis e -> EParenthesis (loop e) + | EObjectDecl fl -> EObjectDecl (List.map (fun ((f,p),e) -> (f,p),loop e) fl) + | EArrayDecl el -> EArrayDecl (List.map loop el) + | ECall (e,el) -> + let e = loop e in + let el = List.map loop el in + ECall (e,el) + | ENew (t,el) -> + let t = tpath t in + let el = List.map loop el in + ENew (t,el) + | EUnop (op,f,e) -> EUnop (op,f,loop e) + | EVars vl -> + EVars (List.map (fun (n,t,eo) -> + let t = opt type_hint t in + let eo = opt loop eo in + n,t,eo + ) vl) + | EFunction (n,f) -> EFunction (n,func f) + | EBlock el -> EBlock (List.map loop el) + | EFor (e1,e2) -> + let e1 = loop e1 in + let e2 = loop e2 in + EFor (e1,e2) + | EIn (e1,e2) -> + let e1 = loop e1 in + let e2 = loop e2 in + EIn (e1,e2) + | EIf (e,e1,e2) -> + let e = loop e in + let e1 = loop e1 in + let e2 = opt loop e2 in + EIf (e,e1,e2) + | EWhile (econd,e,f) -> + let econd = loop econd in + let e = loop e in + EWhile (econd,e,f) + | ESwitch (e,cases,def) -> + let e = loop e in + let cases = List.map (fun (el,eg,e,p) -> + let el = List.map loop el in + let eg = opt loop eg in + let e = opt loop e in + el,eg,e,p + ) cases in + let def = opt (fun (eo,p) -> opt loop eo,p) def in + ESwitch (e, cases, def) + | ETry (e,catches) -> + let e = loop e in + let catches = List.map (fun (n,t,e,p) -> n,type_hint t,loop e,p) catches in + ETry (e,catches) + | EReturn e -> EReturn (opt loop e) + | EBreak -> EBreak + | EContinue -> EContinue + | EUntyped e -> EUntyped (loop e) + | EThrow e -> EThrow (loop e) + | ECast (e,t) -> + let e = loop e in + let t = opt type_hint t in + ECast (e,t) + | EDisplay (e,f) -> EDisplay (loop e,f) + | EDisplayNew t -> EDisplayNew (tpath t) + | ETernary (e1,e2,e3) -> + let e1 = loop e1 in + let e2 = loop e2 in + let e3 = loop e3 in + ETernary (e1,e2,e3) + | ECheckType (e,t) -> + let e = loop e in + let t = type_hint t in + ECheckType (e,t) + | EMeta (m,e) -> EMeta(m, loop e) + ) in + (e,p) + +let iter_expr loop (e,p) = + let opt eo = match eo with None -> () | Some e -> loop e in + let exprs = List.iter loop in + match e with + | EConst _ | EContinue | EBreak | EDisplayNew _ | EReturn None -> () + | EParenthesis e1 | EField(e1,_) | EUnop(_,_,e1) | EReturn(Some e1) | EThrow e1 | EMeta(_,e1) + | ECheckType(e1,_) | EDisplay(e1,_) | ECast(e1,_) | EUntyped e1 -> loop e1; + | EArray(e1,e2) | EBinop(_,e1,e2) | EIn(e1,e2) | EFor(e1,e2) | EWhile(e1,e2,_) | EIf(e1,e2,None) -> loop e1; loop e2; + | ETernary(e1,e2,e3) | EIf(e1,e2,Some e3) -> loop e1; loop e2; loop e3; + | EArrayDecl el | ENew(_,el) | EBlock el -> List.iter loop el + | ECall(e1,el) -> loop e1; exprs el; + | EObjectDecl fl -> List.iter (fun (_,e) -> loop e) fl; + | ETry(e1,catches) -> + loop e1; + List.iter (fun (_,_,e,_) -> loop e) catches + | ESwitch(e1,cases,def) -> + loop e1; + List.iter (fun (el,eg,e,_) -> + exprs el; + opt eg; + opt e; + ) cases; + (match def with None -> () | Some (e,_) -> opt e); + | EFunction(_,f) -> + List.iter (fun (_,_,_,_,eo) -> opt eo) f.f_args; + opt f.f_expr + | EVars vl -> List.iter (fun (_,_,eo) -> opt eo) vl + +let s_expr e = + let rec s_expr_inner tabs (e,_) = + match e with + | EConst c -> s_constant c + | EArray (e1,e2) -> s_expr_inner tabs e1 ^ "[" ^ s_expr_inner tabs e2 ^ "]" + | EBinop (op,e1,e2) -> s_expr_inner tabs e1 ^ " " ^ s_binop op ^ " " ^ s_expr_inner tabs e2 + | EField (e,f) -> s_expr_inner tabs e ^ "." ^ f + | EParenthesis e -> "(" ^ (s_expr_inner tabs e) ^ ")" + | EObjectDecl fl -> "{ " ^ (String.concat ", " (List.map (fun ((n,_),e) -> n ^ " : " ^ (s_expr_inner tabs e)) fl)) ^ " }" + | EArrayDecl el -> "[" ^ s_expr_list tabs el ", " ^ "]" + | ECall (e,el) -> s_expr_inner tabs e ^ "(" ^ s_expr_list tabs el ", " ^ ")" + | ENew (t,el) -> "new " ^ s_complex_type_path tabs t ^ "(" ^ s_expr_list tabs el ", " ^ ")" + | EUnop (op,Postfix,e) -> s_expr_inner tabs e ^ s_unop op + | EUnop (op,Prefix,e) -> s_unop op ^ s_expr_inner tabs e + | EFunction (Some n,f) -> "function " ^ n ^ s_func tabs f + | EFunction (None,f) -> "function" ^ s_func tabs f + | EVars vl -> "var " ^ String.concat ", " (List.map (s_var tabs) vl) + | EBlock [] -> "{ }" + | EBlock el -> s_block tabs el "{" "\n" "}" + | EFor (e1,e2) -> "for (" ^ s_expr_inner tabs e1 ^ ") " ^ s_expr_inner tabs e2 + | EIn (e1,e2) -> s_expr_inner tabs e1 ^ " in " ^ s_expr_inner tabs e2 + | EIf (e,e1,None) -> "if (" ^ s_expr_inner tabs e ^ ") " ^ s_expr_inner tabs e1 + | EIf (e,e1,Some e2) -> "if (" ^ s_expr_inner tabs e ^ ") " ^ s_expr_inner tabs e1 ^ " else " ^ s_expr_inner tabs e2 + | EWhile (econd,e,NormalWhile) -> "while (" ^ s_expr_inner tabs econd ^ ") " ^ s_expr_inner tabs e + | EWhile (econd,e,DoWhile) -> "do " ^ s_expr_inner tabs e ^ " while (" ^ s_expr_inner tabs econd ^ ")" + | ESwitch (e,cases,def) -> "switch " ^ s_expr_inner tabs e ^ " {\n\t" ^ tabs ^ String.concat ("\n\t" ^ tabs) (List.map (s_case tabs) cases) ^ + (match def with None -> "" | Some (def,_) -> "\n\t" ^ tabs ^ "default:" ^ + (match def with None -> "" | Some def -> s_expr_omit_block tabs def)) ^ "\n" ^ tabs ^ "}" + | ETry (e,catches) -> "try " ^ s_expr_inner tabs e ^ String.concat "" (List.map (s_catch tabs) catches) + | EReturn e -> "return" ^ s_opt_expr tabs e " " + | EBreak -> "break" + | EContinue -> "continue" + | EUntyped e -> "untyped " ^ s_expr_inner tabs e + | EThrow e -> "throw " ^ s_expr_inner tabs e + | ECast (e,Some (t,_)) -> "cast (" ^ s_expr_inner tabs e ^ ", " ^ s_complex_type tabs t ^ ")" + | ECast (e,None) -> "cast " ^ s_expr_inner tabs e + | ETernary (e1,e2,e3) -> s_expr_inner tabs e1 ^ " ? " ^ s_expr_inner tabs e2 ^ " : " ^ s_expr_inner tabs e3 + | ECheckType (e,(t,_)) -> "(" ^ s_expr_inner tabs e ^ " : " ^ s_complex_type tabs t ^ ")" + | EMeta (m,e) -> s_metadata tabs m ^ " " ^ s_expr_inner tabs e + | EDisplay (e1,iscall) -> Printf.sprintf "#DISPLAY(%s, %b)" (s_expr_inner tabs e1) iscall + | EDisplayNew tp -> Printf.sprintf "#DISPLAY_NEW(%s)" (s_complex_type_path tabs tp) + and s_expr_list tabs el sep = + (String.concat sep (List.map (s_expr_inner tabs) el)) + and s_complex_type_path tabs (t,_) = + Printf.sprintf "%s%s%s" + (s_type_path (t.tpackage,t.tname)) + (Option.map_default (fun s -> "." ^ s) "" t.tsub) + (s_type_param_or_consts tabs t.tparams) + and s_type_param_or_consts tabs pl = + if List.length pl > 0 + then "<" ^ (String.concat "," (List.map (s_type_param_or_const tabs) pl)) ^ ">" + else "" + and s_type_param_or_const tabs p = + match p with + | TPType (t,_) -> s_complex_type tabs t + | TPExpr e -> s_expr_inner tabs e + and s_complex_type tabs ct = + match ct with + | CTPath t -> s_complex_type_path tabs (t,null_pos) + | CTFunction (cl,(c,_)) -> if List.length cl > 0 then String.concat " -> " (List.map (fun (t,_) -> s_complex_type tabs t) cl) else "Void" ^ " -> " ^ s_complex_type tabs c + | CTAnonymous fl -> "{ " ^ String.concat "; " (List.map (s_class_field tabs) fl) ^ "}"; + | CTParent(t,_) -> "(" ^ s_complex_type tabs t ^ ")" + | CTOptional(t,_) -> "?" ^ s_complex_type tabs t + | CTExtend (tl, fl) -> "{> " ^ String.concat " >, " (List.map (s_complex_type_path tabs) tl) ^ ", " ^ String.concat ", " (List.map (s_class_field tabs) fl) ^ " }" + and s_class_field tabs f = + match f.cff_doc with + | Some s -> "/**\n\t" ^ tabs ^ s ^ "\n**/\n" + | None -> "" ^ + if List.length f.cff_meta > 0 then String.concat ("\n" ^ tabs) (List.map (s_metadata tabs) f.cff_meta) else "" ^ + if List.length f.cff_access > 0 then String.concat " " (List.map s_access f.cff_access) else "" ^ + match f.cff_kind with + | FVar (t,e) -> "var " ^ (fst f.cff_name) ^ s_opt_type_hint tabs t " : " ^ s_opt_expr tabs e " = " + | FProp ((get,_),(set,_),t,e) -> "var " ^ (fst f.cff_name) ^ "(" ^ get ^ "," ^ set ^ ")" ^ s_opt_type_hint tabs t " : " ^ s_opt_expr tabs e " = " + | FFun func -> "function " ^ (fst f.cff_name) ^ s_func tabs func + and s_metadata tabs (s,e,_) = + "@" ^ Meta.to_string s ^ if List.length e > 0 then "(" ^ s_expr_list tabs e ", " ^ ")" else "" + and s_opt_expr tabs e pre = + match e with + | Some s -> pre ^ s_expr_inner tabs s + | None -> "" + and s_opt_type_hint tabs t pre = + match t with + | Some(t,_) -> pre ^ s_complex_type tabs t + | None -> "" + and s_func tabs f = + s_type_param_list tabs f.f_params ^ + "(" ^ String.concat ", " (List.map (s_func_arg tabs) f.f_args) ^ ")" ^ + s_opt_type_hint tabs f.f_type ":" ^ + s_opt_expr tabs f.f_expr " " + and s_type_param tabs t = + fst (t.tp_name) ^ s_type_param_list tabs t.tp_params ^ + if List.length t.tp_constraints > 0 then ":(" ^ String.concat ", " (List.map ((fun (t,_) -> s_complex_type tabs t)) t.tp_constraints) ^ ")" else "" + and s_type_param_list tabs tl = + if List.length tl > 0 then "<" ^ String.concat ", " (List.map (s_type_param tabs) tl) ^ ">" else "" + and s_func_arg tabs ((n,_),o,_,t,e) = + if o then "?" else "" ^ n ^ s_opt_type_hint tabs t ":" ^ s_opt_expr tabs e " = " + and s_var tabs ((n,_),t,e) = + n ^ (s_opt_type_hint tabs t ":") ^ s_opt_expr tabs e " = " + and s_case tabs (el,e1,e2,_) = + "case " ^ s_expr_list tabs el ", " ^ + (match e1 with None -> ":" | Some e -> " if (" ^ s_expr_inner tabs e ^ "):") ^ + (match e2 with None -> "" | Some e -> s_expr_omit_block tabs e) + and s_catch tabs ((n,_),(t,_),e,_) = + " catch(" ^ n ^ ":" ^ s_complex_type tabs t ^ ") " ^ s_expr_inner tabs e + and s_block tabs el opn nl cls = + opn ^ "\n\t" ^ tabs ^ (s_expr_list (tabs ^ "\t") el (";\n\t" ^ tabs)) ^ ";" ^ nl ^ tabs ^ cls + and s_expr_omit_block tabs e = + match e with + | (EBlock [],_) -> "" + | (EBlock el,_) -> s_block (tabs ^ "\t") el "" "" "" + | _ -> s_expr_inner (tabs ^ "\t") e ^ ";" + in s_expr_inner "" e + +let get_value_meta meta = + try + begin match Meta.get Meta.Value meta with + | (_,[EObjectDecl values,_],_) -> List.fold_left (fun acc ((s,_),e) -> PMap.add s e acc) PMap.empty values + | _ -> raise Not_found + end + with Not_found -> + PMap.empty + +(* Type path related functions *) + +let rec string_list_of_expr_path_raise (e,p) = + match e with + | EConst (Ident i) -> [i] + | EField (e,f) -> f :: string_list_of_expr_path_raise e + | _ -> raise Exit + +let expr_of_type_path (sl,s) p = + match sl with + | [] -> (EConst(Ident s),p) + | s1 :: sl -> + let e1 = (EConst(Ident s1),p) in + let e = List.fold_left (fun e s -> (EField(e,s),p)) e1 sl in + EField(e,s),p + +let match_path recursive sl sl_pattern = + let rec loop sl1 sl2 = match sl1,sl2 with + | [],[] -> + true + (* always recurse into types of package paths *) + | (s1 :: s11 :: _),[s2] when is_lower_ident s2 && not (is_lower_ident s11)-> + s1 = s2 + | [_],[""] -> + true + | _,([] | [""]) -> + recursive + | [],_ -> + false + | (s1 :: sl1),(s2 :: sl2) -> + s1 = s2 && loop sl1 sl2 + in + loop sl sl_pattern + +let full_dot_path mpath tpath = + if mpath = tpath then + (fst tpath) @ [snd tpath] + else + (fst mpath) @ [snd mpath;snd tpath] + +let safe_for_all2 f a b = + try List.for_all2 f a b with _ -> false + +let rec remove_duplicates f l = match l with + | [] -> [] + | x :: l -> x :: (remove_duplicates f (List.filter (fun x' -> f x x') l)) + +module Expr = struct + let ensure_block e = match fst e with + | EBlock _ -> e + | _ -> (EBlock [e],pos e) + + let field_assoc name fl = + let rec loop fl = match fl with + | ((name',_),e) :: fl -> if name' = name then e else loop fl + | [] -> raise Not_found + in + loop fl +end diff --git a/lexer.mll b/src/syntax/lexer.mll similarity index 85% rename from lexer.mll rename to src/syntax/lexer.mll index 7ce94570..c4077c0d 100644 --- a/lexer.mll +++ b/src/syntax/lexer.mll @@ -1,28 +1,26 @@ (* - * Copyright (C)2005-2012 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) { open Lexing open Ast +open Globals type error_msg = | Invalid_character of char @@ -30,7 +28,7 @@ type error_msg = | Unterminated_regexp | Unclosed_comment | Unclosed_code - | Invalid_escape + | Invalid_escape of char | Invalid_option exception Error of error_msg * pos @@ -42,7 +40,7 @@ let error_msg = function | Unterminated_regexp -> "Unterminated regular expression" | Unclosed_comment -> "Unclosed comment" | Unclosed_code -> "Unclosed code string" - | Invalid_escape -> "Invalid escape sequence" + | Invalid_escape c -> Printf.sprintf "Invalid escape sequence \\%s" (Char.escaped c) | Invalid_option -> "Invalid regular expression option" type lexer_file = { @@ -52,6 +50,8 @@ type lexer_file = { mutable llines : (int * int) list; mutable lalines : (int * int) array; mutable lstrings : int list; + mutable llast : int; + mutable llastindex : int; } let make_file file = @@ -62,6 +62,8 @@ let make_file file = llines = [0,1]; lalines = [|0,1|]; lstrings = []; + llast = max_int; + llastindex = 0; } @@ -137,18 +139,27 @@ let find_line p f = if f.lmaxline <> f.lline then begin f.lmaxline <- f.lline; f.lalines <- Array.of_list (List.rev f.llines); + f.llast <- max_int; + f.llastindex <- 0; end; let rec loop min max = let med = (min + max) lsr 1 in let lp, line = Array.unsafe_get f.lalines med in - if med = min then + if med = min then begin + f.llast <- p; + f.llastindex <- med; line, p - lp - else if lp > p then + end else if lp > p then loop min med else loop med max in - loop 0 (Array.length f.lalines) + if p >= f.llast then begin + let lp, line = Array.unsafe_get f.lalines f.llastindex in + let lp2 = if f.llastindex = Array.length f.lalines - 1 then max_int else fst(Array.unsafe_get f.lalines (f.llastindex + 1)) in + if p >= lp && p < lp2 then line, p - lp else loop 0 (Array.length f.lalines) + end else + loop 0 (Array.length f.lalines) (* resolve a position within a non-haxe file by counting newlines *) let resolve_pos file = @@ -185,13 +196,17 @@ let get_error_line p = let l, _ = find_pos p in l +let get_pos_coords p = + let file = find_file p.pfile in + let l1, p1 = find_line p.pmin file in + let l2, p2 = find_line p.pmax file in + l1, p1, l2, p2 + let get_error_pos printer p = if p.pmin = -1 then "(unknown)" else - let file = find_file p.pfile in - let l1, p1 = find_line p.pmin file in - let l2, p2 = find_line p.pmax file in + let l1, p1, l2, p2 = get_pos_coords p in if l1 = l2 then begin let s = (if p1 = p2 then Printf.sprintf " %d" p1 else Printf.sprintf "s %d-%d" p1 p2) in Printf.sprintf "%s character%s" (printer p.pfile l1) s @@ -258,6 +273,8 @@ and token = parse | "*=" { mk lexbuf (Binop (OpAssignOp OpMult)) } | "/=" { mk lexbuf (Binop (OpAssignOp OpDiv)) } | "<<=" { mk lexbuf (Binop (OpAssignOp OpShl)) } + | "||=" { mk lexbuf (Binop (OpAssignOp OpBoolOr)) } + | "&&=" { mk lexbuf (Binop (OpAssignOp OpBoolAnd)) } (*//| ">>=" { mk lexbuf (Binop (OpAssignOp OpShr)) } *) (*//| ">>>=" { mk lexbuf (Binop (OpAssignOp OpUShr)) } *) | "==" { mk lexbuf (Binop OpEq) } @@ -304,14 +321,14 @@ and token = parse reset(); let pmin = lexeme_start lexbuf in let pmax = (try string lexbuf with Exit -> error Unterminated_string pmin) in - let str = (try unescape (contents()) with Exit -> error Invalid_escape pmin) in + let str = (try unescape (contents()) with Invalid_escape_sequence(c,i) -> error (Invalid_escape c) (pmin + i)) in mk_tok (Const (String str)) pmin pmax; } | "'" { reset(); let pmin = lexeme_start lexbuf in let pmax = (try string2 lexbuf with Exit -> error Unterminated_string pmin) in - let str = (try unescape (contents()) with Exit -> error Invalid_escape pmin) in + let str = (try unescape (contents()) with Invalid_escape_sequence(c,i) -> error (Invalid_escape c) (pmin + i)) in let t = mk_tok (Const (String str)) pmin pmax in fast_add_fmt_string (snd t); t diff --git a/parser.ml b/src/syntax/parser.ml similarity index 70% rename from parser.ml rename to src/syntax/parser.ml index e45e9def..fd5097a1 100644 --- a/parser.ml +++ b/src/syntax/parser.ml @@ -1,26 +1,24 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Ast +open Globals type error_msg = | Unexpected of token @@ -47,6 +45,8 @@ let error_msg = function let error m p = raise (Error (m,p)) let display_error : (error_msg -> pos -> unit) ref = ref (fun _ _ -> assert false) +let special_identifier_files = Hashtbl.create 0 + let quoted_ident_prefix = "@$__hx__" let quote_ident s = @@ -74,7 +74,6 @@ let unquote_ident f = let cache = ref (DynArray.create()) let last_doc = ref None let use_doc = ref false -let use_parser_resume = ref true let resume_display = ref null_pos let in_macro = ref false @@ -92,12 +91,15 @@ let type_path sl in_import = match sl with | n :: l when n.[0] >= 'A' && n.[0] <= 'Z' -> raise (TypePath (List.rev l,Some (n,false),in_import)); | _ -> raise (TypePath (List.rev sl,None,in_import)) +let is_resuming_file file = + Path.unique_full_path file = !resume_display.pfile + let is_resuming p = let p2 = !resume_display in - p.pmax = p2.pmin && !use_parser_resume && Common.unique_full_path p.pfile = p2.pfile + p.pmax = p2.pmin && is_resuming_file p.pfile let set_resume p = - resume_display := { p with pfile = Common.unique_full_path p.pfile } + resume_display := { p with pfile = Path.unique_full_path p.pfile } let is_dollar_ident e = match fst e with | EConst (Ident n) when n.[0] = '$' -> @@ -141,18 +143,27 @@ let rec make_binop op e ((v,p2) as e2) = EBinop (op,e,e2) , punion (pos e) (pos e2) let rec make_unop op ((v,p2) as e) p1 = + let neg s = + if s.[0] = '-' then String.sub s 1 (String.length s - 1) else "-" ^ s + in match v with | EBinop (bop,e,e2) -> EBinop (bop, make_unop op e p1 , e2) , (punion p1 p2) | ETernary (e1,e2,e3) -> ETernary (make_unop op e1 p1 , e2, e3), punion p1 p2 - | _ -> - EUnop (op,Prefix,e), punion p1 p2 + | EConst (Int i) when op = Neg -> EConst (Int (neg i)),punion p1 p2 + | EConst (Float j) when op = Neg -> EConst (Float (neg j)),punion p1 p2 + | _ -> EUnop (op,Prefix,e), punion p1 p2 let rec make_meta name params ((v,p2) as e) p1 = match v with + | EBinop ((OpAssign | OpAssignOp _),_,_) -> EMeta((name,params,p1),e),punion p1 p2 | EBinop (bop,e,e2) -> EBinop (bop, make_meta name params e p1 , e2) , (punion p1 p2) | ETernary (e1,e2,e3) -> ETernary (make_meta name params e1 p1 , e2, e3), punion p1 p2 - | _ -> - EMeta((name,params,p1),e),punion p1 p2 + | _ -> EMeta((name,params,p1),e),punion p1 p2 + +let make_is e (t,p_t) p p_is = + let e_is = EField((EConst(Ident "Std"),null_pos),"is"),p_is in + let e2 = expr_of_type_path (t.tpackage,t.tname) p_t in + ECall(e_is,[e;e2]),p let reify in_macro = let cur_pos = ref None in @@ -205,6 +216,9 @@ let reify in_macro = else (EConst (String s),p) in + let to_placed_name (s,p) = + to_string s p + in let to_array f a p = (EArrayDecl (List.map (fun s -> f s p) a),p) in @@ -220,7 +234,7 @@ let reify in_macro = (EConst (Ident (if o then "true" else "false")),p) in let to_obj fields p = - (EObjectDecl fields,p) + (EObjectDecl (List.map (fun (s,e) -> (s,null_pos),e) fields),p) in let rec to_tparam t p = let n, v = (match t with @@ -228,11 +242,25 @@ let reify in_macro = | TPExpr e -> "TPExpr", to_expr e p ) in mk_enum "TypeParam" n [v] p - and to_tpath t p = + and to_tpath (t,_) p = let len = String.length t.tname in - if t.tpackage = [] && len > 1 && t.tname.[0] = '$' then - (EConst (Ident (String.sub t.tname 1 (len - 1))),p) - else begin + if t.tpackage = [] && len > 1 && t.tname.[0] = '$' then begin + let name = String.sub t.tname 1 (len - 1) in + let ei = (EConst (Ident name),p) in + match t.tparams with + | [] -> ei + | _ -> + (* `macro : $TP` conveys the intent to use TP and overwrite the + type parameters. *) + let ea = to_array to_tparam t.tparams p in + let fields = [ + ("pack", (EField(ei,"pack"),p)); + ("name", (EField(ei,"name"),p)); + ("sub", (EField(ei,"sub"),p)); + ("params", ea); + ] in + to_obj fields p + end else begin let fields = [ ("pack", to_array to_string t.tpackage p); ("name", to_string t.tname p); @@ -242,27 +270,30 @@ let reify in_macro = end and to_ctype t p = let ct n vl = mk_enum "ComplexType" n vl p in - match t with - | CTPath { tpackage = []; tparams = []; tsub = None; tname = n } when n.[0] = '$' -> + match fst t with + | CTPath ({ tpackage = []; tparams = []; tsub = None; tname = n }) when n.[0] = '$' -> to_string n p - | CTPath t -> ct "TPath" [to_tpath t p] - | CTFunction (args,ret) -> ct "TFunction" [to_array to_ctype args p; to_ctype ret p] + | CTPath t -> ct "TPath" [to_tpath (t,p) p] + | CTFunction (args,ret) -> ct "TFunction" [to_array to_type_hint args p; to_type_hint ret p] | CTAnonymous fields -> ct "TAnonymous" [to_array to_cfield fields p] - | CTParent t -> ct "TParent" [to_ctype t p] + | CTParent t -> ct "TParent" [to_type_hint t p] | CTExtend (tl,fields) -> ct "TExtend" [to_array to_tpath tl p; to_array to_cfield fields p] - | CTOptional t -> ct "TOptional" [to_ctype t p] + | CTOptional t -> ct "TOptional" [to_type_hint t p] + and to_type_hint (t,p) _ = + (* to_obj ["type",to_ctype t p;"pos",to_pos p] p *) + to_ctype (t,p) p and to_fun f p = - let farg (n,o,t,e) p = + let farg ((n,_),o,_,t,e) p = let fields = [ "name", to_string n p; "opt", to_bool o p; - "type", to_opt to_ctype t p; + "type", to_opt to_type_hint t p; ] in to_obj (match e with None -> fields | Some e -> fields @ ["value",to_expr e p]) p in let rec fparam t p = let fields = [ - "name", to_string t.tp_name p; + "name", to_placed_name t.tp_name; "constraints", to_array to_ctype t.tp_constraints p; "params", to_array fparam t.tp_params p; ] in @@ -270,7 +301,7 @@ let reify in_macro = in let fields = [ ("args",to_array farg f.f_args p); - ("ret",to_opt to_ctype f.f_type p); + ("ret",to_opt to_type_hint f.f_type p); ("expr",to_opt to_expr f.f_expr p); ("params",to_array fparam f.f_params p); ] in @@ -291,14 +322,14 @@ let reify in_macro = in let to_kind k = let n, vl = (match k with - | FVar (ct,e) -> "FVar", [to_opt to_ctype ct p;to_opt to_expr e p] + | FVar (ct,e) -> "FVar", [to_opt to_type_hint ct p;to_opt to_expr e p] | FFun f -> "FFun", [to_fun f p] - | FProp (get,set,t,e) -> "FProp", [to_string get p; to_string set p; to_opt to_ctype t p; to_opt to_expr e p] + | FProp (get,set,t,e) -> "FProp", [to_placed_name get; to_placed_name set; to_opt to_type_hint t p; to_opt to_expr e p] ) in mk_enum "FieldType" n vl p in let fields = [ - Some ("name", to_string f.cff_name p); + Some ("name", to_placed_name f.cff_name); (match f.cff_doc with None -> None | Some s -> Some ("doc", to_string s p)); (match f.cff_access with [] -> None | l -> Some ("access", to_array to_access l p)); Some ("kind", to_kind f.cff_kind); @@ -310,7 +341,7 @@ let reify in_macro = and to_meta m p = to_array (fun (m,el,p) _ -> let fields = [ - "name", to_string (fst (Common.MetaInfo.to_string m)) p; + "name", to_string (Meta.to_string m) p; "params", to_expr_array el p; "pos", to_pos p; ] in @@ -325,7 +356,7 @@ let reify in_macro = let pmin = (EConst (Int (string_of_int p.pmin)),p) in let pmax = (EConst (Int (string_of_int p.pmax)),p) in if in_macro then - (EUntyped (ECall ((EConst (Ident "__dollar__mk_pos"),p),[file;pmin;pmax]),p),p) + (EUntyped (ECall ((EConst (Ident "$__mk_pos__"),p),[file;pmin;pmax]),p),p) else to_obj [("file",file);("min",pmin);("max",pmax)] p and to_expr_array a p = match a with @@ -339,7 +370,7 @@ let reify in_macro = in let loop e = to_expr e (snd e) in match fst e with - | EConst (Ident n) when n.[0] = '$' && String.length n > 1 -> + | EConst (Ident n) when n.[0] = '$' && String.length n > 1 && n <> "$__mk_pos__" -> to_string n p | EConst c -> expr "EConst" [to_const c p] @@ -352,7 +383,7 @@ let reify in_macro = | EParenthesis e -> expr "EParenthesis" [loop e] | EObjectDecl fl -> - expr "EObjectDecl" [to_array (fun (f,e) -> to_obj [("field",to_string f p);("expr",loop e)]) fl p] + expr "EObjectDecl" [to_array (fun ((f,_),e) -> to_obj [("field",to_string f p);("expr",loop e)]) fl p] | EArrayDecl el -> expr "EArrayDecl" [to_expr_array el p] | ECall (e,el) -> @@ -369,10 +400,11 @@ let reify in_macro = ) [] p in expr "EUnop" [op;to_bool (flag = Postfix) p;loop e] | EVars vl -> - expr "EVars" [to_array (fun (v,t,e) p -> + expr "EVars" [to_array (fun ((n,pn),th,e) p -> let fields = [ - "name", to_string v p; - "type", to_opt to_ctype t p; + (* "name", to_obj ["name",to_string n pn;"pos",to_pos pn] p; *) + "name", to_string n pn; + "type", to_opt to_type_hint th p; "expr", to_opt to_expr e p; ] in to_obj fields p @@ -403,12 +435,12 @@ let reify in_macro = | EWhile (e1,e2,flag) -> expr "EWhile" [loop e1;loop e2;to_bool (flag = NormalWhile) p] | ESwitch (e1,cases,def) -> - let scase (el,eg,e) p = + let scase (el,eg,e,_) p = to_obj [("values",to_expr_array el p);"guard",to_opt to_expr eg p;"expr",to_opt to_expr e p] p in - expr "ESwitch" [loop e1;to_array scase cases p;to_opt (to_opt to_expr) def p] + expr "ESwitch" [loop e1;to_array scase cases p;to_opt (fun (e,_) -> to_opt to_expr e) def p] | ETry (e1,catches) -> - let scatch (n,t,e) p = + let scatch ((n,_),t,e,_) p = to_obj [("name",to_string n p);("type",to_ctype t p);("expr",loop e)] p in expr "ETry" [loop e1;to_array scatch catches p] @@ -423,7 +455,7 @@ let reify in_macro = | EThrow e -> expr "EThrow" [loop e] | ECast (e,ct) -> - expr "ECast" [loop e; to_opt to_ctype ct p] + expr "ECast" [loop e; to_opt to_type_hint ct p] | EDisplay (e,flag) -> expr "EDisplay" [loop e; to_bool flag p] | EDisplayNew t -> @@ -431,7 +463,7 @@ let reify in_macro = | ETernary (e1,e2,e3) -> expr "ETernary" [loop e1;loop e2;loop e3] | ECheckType (e1,ct) -> - expr "ECheckType" [loop e1; to_ctype ct p] + expr "ECheckType" [loop e1; to_type_hint ct p] | EMeta ((m,ml,p),e1) -> match m, ml with | Meta.Dollar ("" | "e"), _ -> @@ -443,9 +475,9 @@ let reify in_macro = (* TODO: can $v and $i be implemented better? *) | Meta.Dollar "v", _ -> begin match fst e1 with - | EParenthesis (ECheckType (e2, CTPath{tname="String";tpackage=[]}),_) -> expr "EConst" [mk_enum "Constant" "CString" [e2] (pos e2)] - | EParenthesis (ECheckType (e2, CTPath{tname="Int";tpackage=[]}),_) -> expr "EConst" [mk_enum "Constant" "CInt" [e2] (pos e2)] - | EParenthesis (ECheckType (e2, CTPath{tname="Float";tpackage=[]}),_) -> expr "EConst" [mk_enum "Constant" "CFloat" [e2] (pos e2)] + | EParenthesis (ECheckType (e2, (CTPath{tname="String";tpackage=[]},_)),_) -> expr "EConst" [mk_enum "Constant" "CString" [e2] (pos e2)] + | EParenthesis (ECheckType (e2, (CTPath{tname="Int";tpackage=[]},_)),_) -> expr "EConst" [mk_enum "Constant" "CInt" [e2] (pos e2)] + | EParenthesis (ECheckType (e2, (CTPath{tname="Float";tpackage=[]},_)),_) -> expr "EConst" [mk_enum "Constant" "CFloat" [e2] (pos e2)] | _ -> (ECall ((EField ((EField ((EField ((EConst (Ident "haxe"),p),"macro"),p),"Context"),p),"makeExpr"),p),[e; to_pos (pos e)]),p) end | Meta.Dollar "i", _ -> @@ -459,10 +491,10 @@ let reify in_macro = cur_pos := old; e | _ -> - expr "EMeta" [to_obj [("name",to_string (fst (Common.MetaInfo.to_string m)) p);("params",to_expr_array ml p);("pos",to_pos p)] p;loop e1] + expr "EMeta" [to_obj [("name",to_string (Meta.to_string m) p);("params",to_expr_array ml p);("pos",to_pos p)] p;loop e1] and to_tparam_decl p t = to_obj [ - "name", to_string t.tp_name p; + "name", to_placed_name t.tp_name; "params", (EArrayDecl (List.map (to_tparam_decl p) t.tp_params),p); "constraints", (EArrayDecl (List.map (fun t -> to_ctype t p) t.tp_constraints),p) ] p @@ -473,12 +505,17 @@ let reify in_macro = List.iter (function | HExtern | HPrivate -> () | HInterface -> interf := true; - | HExtends t -> ext := Some (to_tpath t p) - | HImplements i -> impl := (to_tpath i p) :: !impl + | HExtends t -> ext := (match !ext with + | None -> Some (to_tpath t p) + | Some _ -> begin + impl := (to_tpath t p) :: !impl; + !ext + end) + | HImplements i-> impl := (to_tpath i p) :: !impl ) d.d_flags; to_obj [ "pack", (EArrayDecl [],p); - "name", to_string d.d_name p; + "name", to_string (fst d.d_name) (pos d.d_name); "pos", to_pos p; "meta", to_meta d.d_meta p; "params", (EArrayDecl (List.map (to_tparam_decl p) d.d_params),p); @@ -490,6 +527,10 @@ let reify in_macro = in (fun e -> to_expr e (snd e)), to_ctype, to_type_def +let next_token s = match Stream.peek s with + | Some tk -> tk + | _ -> last_token s + let popt f = parser | [< v = f >] -> Some v | [< >] -> None @@ -525,15 +566,11 @@ let lower_ident_or_macro = parser | [< '(Kwd Macro,_) >] -> "macro" | [< '(Kwd Extern,_) >] -> "extern" -let any_enum_ident = parser - | [< i = ident >] -> i - | [< '(Kwd k,p) when Filename.basename p.pfile = "StdTypes.hx" >] -> s_keyword k, p - let property_ident = parser - | [< i, _ = ident >] -> i - | [< '(Kwd Dynamic,_) >] -> "dynamic" - | [< '(Kwd Default,_) >] -> "default" - | [< '(Kwd Null,_) >] -> "null" + | [< i,p = ident >] -> i,p + | [< '(Kwd Dynamic,p) >] -> "dynamic",p + | [< '(Kwd Default,p) >] -> "default",p + | [< '(Kwd Null,p) >] -> "null",p let get_doc s = (* do the peek first to make sure we fetch the doc *) @@ -561,6 +598,16 @@ let semicolon s = let pos = snd (last_token s) in if do_resume() then pos else error Missing_semicolon pos +let encloses_resume p = + p.pmin <= !resume_display.pmin && p.pmax >= !resume_display.pmax + +let would_skip_resume p1 s = + match Stream.npeek 1 s with + | [ (_,p2) ] -> + is_resuming_file p2.pfile && encloses_resume (punion p1 p2) + | _ -> + false + let rec parse_file s = last_doc := None; match s with parser @@ -591,7 +638,7 @@ and parse_type_decls pack acc s = and parse_type_decl s = match s with parser | [< '(Kwd Import,p1) >] -> parse_import s p1 - | [< '(Kwd Using,p1); t = parse_type_path; p2 = semicolon >] -> EUsing t, punion p1 p2 + | [< '(Kwd Using,p1) >] -> parse_using s p1 | [< doc = get_doc; meta = parse_meta; c = parse_common_flags; s >] -> match s with parser | [< n , p1 = parse_enum_flags; name = type_name; tl = parse_constraint_params; '(BrOpen,_); l = plist parse_enum; '(BrClose,p2) >] -> @@ -623,9 +670,9 @@ and parse_type_decl s = d_params = tl; d_flags = List.map snd c; d_data = t; - }, punion p1 p2) + }, punion p1 (pos t)) | [< '(Kwd Abstract,p1); name = type_name; tl = parse_constraint_params; st = parse_abstract_subtype; sl = plist parse_abstract_relations; '(BrOpen,_); fl, p2 = parse_class_fields false p1 >] -> - let flags = List.map (fun (_,c) -> match c with EPrivate -> APrivAbstract | EExtern -> error (Custom "extern abstract not allowed") p1) c in + let flags = List.map (fun (_,c) -> match c with EPrivate -> APrivAbstract | EExtern -> AExtern) c in let flags = (match st with None -> flags | Some t -> AIsType t :: flags) in (EAbstract { d_name = name; @@ -637,9 +684,9 @@ and parse_type_decl s = },punion p1 p2) and parse_class doc meta cflags need_name s = - let opt_name = if need_name then type_name else (fun s -> match popt type_name s with None -> "" | Some n -> n) in + let opt_name = if need_name then type_name else (fun s -> match popt type_name s with None -> "",null_pos | Some n -> n) in match s with parser - | [< n , p1 = parse_class_flags; name = opt_name; tl = parse_constraint_params; hl = psep Comma parse_class_herit; '(BrOpen,_); fl, p2 = parse_class_fields (not need_name) p1 >] -> + | [< n , p1 = parse_class_flags; name = opt_name; tl = parse_constraint_params; hl = plist parse_class_herit; '(BrOpen,_); fl, p2 = parse_class_fields (not need_name) p1 >] -> (EClass { d_name = name; d_doc = doc; @@ -682,10 +729,34 @@ and parse_import s p1 = in let p2, path, mode = (match s with parser | [< '(Const (Ident name),p) >] -> loop [name,p] - | [< >] -> serror() + | [< >] -> if would_skip_resume p1 s then p1, [], INormal else serror() ) in (EImport (path,mode),punion p1 p2) +and parse_using s p1 = + let rec loop acc = + match s with parser + | [< '(Dot,p) >] -> + begin match s with parser + | [< '(Const (Ident k),p) >] -> + loop ((k,p) :: acc) + | [< '(Kwd Macro,p) >] -> + loop (("macro",p) :: acc) + | [< '(Kwd Extern,p) >] -> + loop (("extern",p) :: acc) + | [< >] -> + if is_resuming p then type_path (List.map fst acc) false; + serror() + end + | [< '(Semicolon,p2) >] -> + p2,List.rev acc + in + let p2, path = (match s with parser + | [< '(Const (Ident name),p) >] -> loop [name,p] + | [< >] -> if would_skip_resume p1 s then p1, [] else serror() + ) in + (EUsing path,punion p1 p2) + and parse_abstract_relations s = match s with parser | [< '(Const (Ident "to"),_); t = parse_complex_type >] -> AToType t @@ -702,7 +773,7 @@ and parse_class_fields tdecl p1 s = let l = parse_class_field_resume tdecl s in let p2 = (match s with parser | [< '(BrClose,p2) >] -> p2 - | [< >] -> if do_resume() then p1 else serror() + | [< >] -> if do_resume() then pos (last_token s) else serror() ) in l, p2 @@ -797,19 +868,24 @@ and parse_meta_params pname s = match s with parser | [< >] -> [] and parse_meta_entry = parser - [< '(At,_); name,p = meta_name; params = parse_meta_params p; s >] -> (name,params,p) + [< '(At,p1); s >] -> + match s with parser + | [< name,p = meta_name p1; params = parse_meta_params p; s >] -> (name,params,p) + | [< >] -> + if is_resuming p1 then (Meta.Last,[],p1) else serror() and parse_meta = parser | [< entry = parse_meta_entry; s >] -> entry :: parse_meta s | [< >] -> [] -and meta_name = parser - | [< '(Const (Ident i),p) >] -> (Meta.Custom i), p - | [< '(Kwd k,p) >] -> (Meta.Custom (s_keyword k)),p - | [< '(DblDot,_); s >] -> match s with parser - | [< '(Const (Ident i),p) >] -> (Common.MetaInfo.parse i), p - | [< '(Kwd k,p) >] -> (Common.MetaInfo.parse (s_keyword k)),p +and meta_name p1 = parser + | [< '(Const (Ident i),p) when p.pmin = p1.pmax >] -> (Meta.Custom i), p + | [< '(Kwd k,p) when p.pmin = p1.pmax >] -> (Meta.Custom (s_keyword k)),p + | [< '(DblDot,p) when p.pmin = p1.pmax; s >] -> match s with parser + | [< '(Const (Ident i),p1) when p1.pmin = p.pmax >] -> (Meta.parse i),punion p p1 + | [< '(Kwd k,p1) when p1.pmin = p.pmax >] -> (Meta.parse (s_keyword k)),punion p p1 + | [< >] -> if is_resuming p then Meta.Last,p else raise Stream.Failure and parse_enum_flags = parser | [< '(Kwd Enum,p) >] -> [] , p @@ -818,8 +894,15 @@ and parse_class_flags = parser | [< '(Kwd Class,p) >] -> [] , p | [< '(Kwd Interface,p) >] -> [HInterface] , p +and parse_complex_type_at p = parser + | [< t = parse_complex_type >] -> t + | [< >] -> if is_resuming p then CTPath { tpackage = []; tname = ""; tparams = []; tsub = None },p else serror() + and parse_type_hint = parser - | [< '(DblDot,_); t = parse_complex_type >] -> t + | [< '(DblDot,p1); t = parse_complex_type_at p1 >] -> t + +and parse_type_hint_with_pos s = match s with parser + | [< '(DblDot,p1); t = parse_complex_type_at p1 >] -> t and parse_type_opt = parser | [< t = parse_type_hint >] -> Some t @@ -834,59 +917,59 @@ and parse_structural_extension = parser t and parse_complex_type_inner = parser - | [< '(POpen,_); t = parse_complex_type; '(PClose,_) >] -> CTParent t + | [< '(POpen,p1); t = parse_complex_type; '(PClose,p2) >] -> CTParent t,punion p1 p2 | [< '(BrOpen,p1); s >] -> (match s with parser - | [< l = parse_type_anonymous false >] -> CTAnonymous l + | [< l,p2 = parse_type_anonymous false >] -> CTAnonymous l,punion p1 p2 | [< t = parse_structural_extension; s>] -> let tl = t :: plist parse_structural_extension s in (match s with parser - | [< l = parse_type_anonymous false >] -> CTExtend (tl,l) - | [< l, _ = parse_class_fields true p1 >] -> CTExtend (tl,l)) - | [< l, _ = parse_class_fields true p1 >] -> CTAnonymous l + | [< l,p2 = parse_type_anonymous false >] -> CTExtend (tl,l),punion p1 p2 + | [< l,p2 = parse_class_fields true p1 >] -> CTExtend (tl,l),punion p1 p2) + | [< l,p2 = parse_class_fields true p1 >] -> CTAnonymous l,punion p1 p2 | [< >] -> serror()) - | [< '(Question,_); t = parse_complex_type_inner >] -> - CTOptional t - | [< t = parse_type_path >] -> - CTPath t + | [< '(Question,p1); t,p2 = parse_complex_type_inner >] -> + CTOptional (t,p2),punion p1 p2 + | [< t,p = parse_type_path >] -> + CTPath t,p -and parse_type_path s = parse_type_path1 [] s +and parse_type_path s = parse_type_path1 None [] s -and parse_type_path1 pack = parser - | [< name, p = dollar_ident_macro pack; s >] -> +and parse_type_path1 p0 pack = parser + | [< name, p1 = dollar_ident_macro pack; s >] -> if is_lower_ident name then (match s with parser | [< '(Dot,p) >] -> if is_resuming p then raise (TypePath (List.rev (name :: pack),None,false)) else - parse_type_path1 (name :: pack) s + parse_type_path1 (match p0 with None -> Some p1 | Some _ -> p0) (name :: pack) s | [< '(Semicolon,_) >] -> - error (Custom "Type name should start with an uppercase letter") p + error (Custom "Type name should start with an uppercase letter") p1 | [< >] -> serror()) else - let sub = (match s with parser + let sub,p2 = (match s with parser | [< '(Dot,p); s >] -> (if is_resuming p then raise (TypePath (List.rev pack,Some (name,false),false)) else match s with parser - | [< '(Const (Ident name),_) when not (is_lower_ident name) >] -> Some name + | [< '(Const (Ident name),p2) when not (is_lower_ident name) >] -> Some name,p2 | [< '(Binop OpOr,_) when do_resume() >] -> set_resume p; raise (TypePath (List.rev pack,Some (name,false),false)) | [< >] -> serror()) - | [< >] -> None + | [< >] -> None,p1 ) in - let params = (match s with parser - | [< '(Binop OpLt,_); l = psep Comma parse_type_path_or_const; '(Binop OpGt,_) >] -> l - | [< >] -> [] + let params,p2 = (match s with parser + | [< '(Binop OpLt,_); l = psep Comma parse_type_path_or_const; '(Binop OpGt,p2) >] -> l,p2 + | [< >] -> [],p2 ) in { tpackage = List.rev pack; tname = name; tparams = params; tsub = sub; - } + },punion (match p0 with None -> p1 | Some p -> p) p2 | [< '(Binop OpOr,_) when do_resume() >] -> raise (TypePath (List.rev pack,None,false)) @@ -895,8 +978,8 @@ and type_name = parser if is_lower_ident name then error (Custom "Type name should start with an uppercase letter") p else - name - | [< '(Dollar name,_) >] -> "$" ^ name + name,p + | [< '(Dollar name,p) >] -> "$" ^ name,p and parse_type_path_or_const = parser (* we can't allow (expr) here *) @@ -906,22 +989,23 @@ and parse_type_path_or_const = parser | [< e = expr >] -> TPExpr e | [< >] -> serror() -and parse_complex_type_next t = parser - | [< '(Arrow,_); t2 = parse_complex_type >] -> +and parse_complex_type_next (t : type_hint) = parser + | [< '(Arrow,_); t2,p2 = parse_complex_type >] -> (match t2 with | CTFunction (args,r) -> - CTFunction (t :: args,r) + CTFunction (t :: args,r),punion (pos t) p2 | _ -> - CTFunction ([t] , t2)) + CTFunction ([t] , (t2,p2)),punion (pos t) p2) | [< >] -> t and parse_type_anonymous opt = parser | [< '(Question,_) when not opt; s >] -> parse_type_anonymous true s - | [< name, p1 = ident; t = parse_type_hint; s >] -> - let next p2 acc = + | [< name, p1 = ident; t = parse_type_hint_with_pos; s >] -> + let p2 = pos (last_token s) in + let next acc = { - cff_name = name; - cff_meta = if opt then [Meta.Optional,[],p1] else []; + cff_name = name,p1; + cff_meta = if opt then [Meta.Optional,[],null_pos] else []; cff_access = []; cff_doc = None; cff_kind = FVar (Some t,None); @@ -929,11 +1013,11 @@ and parse_type_anonymous opt = parser } :: acc in match s with parser - | [< '(BrClose,p2) >] -> next p2 [] + | [< '(BrClose,p2) >] -> next [],p2 | [< '(Comma,p2) >] -> (match s with parser - | [< '(BrClose,_) >] -> next p2 [] - | [< l = parse_type_anonymous false >] -> next p2 l + | [< '(BrClose,p2) >] -> next [],p2 + | [< l,p2 = parse_type_anonymous false >] -> next l,punion p1 p2 | [< >] -> serror()); | [< >] -> serror() @@ -941,18 +1025,18 @@ and parse_enum s = let doc = get_doc s in let meta = parse_meta s in match s with parser - | [< name, p1 = any_enum_ident; params = parse_constraint_params; s >] -> + | [< name, p1 = ident; params = parse_constraint_params; s >] -> let args = (match s with parser | [< '(POpen,_); l = psep Comma parse_enum_param; '(PClose,_) >] -> l | [< >] -> [] ) in - let t = parse_type_opt s in + let t = popt parse_type_hint_with_pos s in let p2 = (match s with parser | [< p = semicolon >] -> p | [< >] -> serror() ) in { - ec_name = name; + ec_name = name,p1; ec_doc = doc; ec_meta = meta; ec_args = args; @@ -962,37 +1046,37 @@ and parse_enum s = } and parse_enum_param = parser - | [< '(Question,_); name, _ = ident; t = parse_type_hint >] -> (name,true,t) - | [< name, _ = ident; t = parse_type_hint >] -> (name,false,t) + | [< '(Question,_); name, _ = ident; t = parse_type_hint_with_pos >] -> (name,true,t) + | [< name, _ = ident; t = parse_type_hint_with_pos >] -> (name,false,t) and parse_class_field s = let doc = get_doc s in match s with parser | [< meta = parse_meta; al = parse_cf_rights true []; s >] -> let name, pos, k = (match s with parser - | [< '(Kwd Var,p1); name, _ = dollar_ident; s >] -> + | [< '(Kwd Var,p1); name = dollar_ident; s >] -> (match s with parser | [< '(POpen,_); i1 = property_ident; '(Comma,_); i2 = property_ident; '(PClose,_) >] -> - let t = parse_type_opt s in + let t = popt parse_type_hint_with_pos s in let e , p2 = (match s with parser | [< '(Binop OpAssign,_); e = toplevel_expr; p2 = semicolon >] -> Some e , p2 - | [< '(Semicolon,p2) >] -> None , p2 + | [< p2 = semicolon >] -> None , p2 | [< >] -> serror() ) in name, punion p1 p2, FProp (i1,i2,t, e) - | [< t = parse_type_opt; s >] -> + | [< t = popt parse_type_hint_with_pos; s >] -> let e , p2 = (match s with parser | [< '(Binop OpAssign,_); e = toplevel_expr; p2 = semicolon >] -> Some e , p2 - | [< '(Semicolon,p2) >] -> None , p2 + | [< p2 = semicolon >] -> None , p2 | [< >] -> serror() ) in name, punion p1 p2, FVar (t,e)) - | [< '(Kwd Function,p1); name = parse_fun_name; pl = parse_constraint_params; '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = parse_type_opt; s >] -> + | [< '(Kwd Function,p1); name = parse_fun_name; pl = parse_constraint_params; '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = popt parse_type_hint_with_pos; s >] -> let e, p2 = (match s with parser | [< e = toplevel_expr; s >] -> (try ignore(semicolon s) with Error (Missing_semicolon,p) -> !display_error Missing_semicolon p); Some e, pos e - | [< '(Semicolon,p) >] -> None, p + | [< p = semicolon >] -> None, p | [< >] -> serror() ) in let f = { @@ -1025,12 +1109,14 @@ and parse_cf_rights allow_static l = parser | [< >] -> l and parse_fun_name = parser - | [< name,_ = dollar_ident >] -> name - | [< '(Kwd New,_) >] -> "new" + | [< name,p = dollar_ident >] -> name,p + | [< '(Kwd New,p) >] -> "new",p -and parse_fun_param = parser - | [< '(Question,_); name, _ = dollar_ident; t = parse_type_opt; c = parse_fun_param_value >] -> (name,true,t,c) - | [< name, _ = dollar_ident; t = parse_type_opt; c = parse_fun_param_value >] -> (name,false,t,c) +and parse_fun_param s = + let meta = parse_meta s in + match s with parser + | [< '(Question,_); name, pn = dollar_ident; t = popt parse_type_hint_with_pos; c = parse_fun_param_value >] -> ((name,pn),true,meta,t,c) + | [< name, pn = dollar_ident; t = popt parse_type_hint_with_pos; c = parse_fun_param_value >] -> ((name,pn),false,meta,t,c) and parse_fun_param_value = parser | [< '(Binop OpAssign,_); e = toplevel_expr >] -> Some e @@ -1045,7 +1131,7 @@ and parse_constraint_params = parser | [< >] -> [] and parse_constraint_param = parser - | [< name = type_name; s >] -> + | [< meta = parse_meta; name = type_name; s >] -> let params = (match s with parser | [< >] -> [] ) in @@ -1061,15 +1147,20 @@ and parse_constraint_param = parser tp_name = name; tp_params = params; tp_constraints = ctl; + tp_meta = meta; } +and parse_type_path_or_resume p1 s = match s with parser + | [< t = parse_type_path >] -> t + | [< >] -> if would_skip_resume p1 s then { tpackage = []; tname = ""; tparams = []; tsub = None },null_pos else raise Stream.Failure + and parse_class_herit = parser - | [< '(Kwd Extends,_); t = parse_type_path >] -> HExtends t - | [< '(Kwd Implements,_); t = parse_type_path >] -> HImplements t + | [< '(Kwd Extends,p1); t = parse_type_path_or_resume p1 >] -> HExtends t + | [< '(Kwd Implements,p1); t = parse_type_path_or_resume p1 >] -> HImplements t and block1 = parser - | [< name,p = dollar_ident; s >] -> block2 name (Ident name) p s - | [< '(Const (String name),p); s >] -> block2 (quote_ident name) (String name) p s + | [< name,p = dollar_ident; s >] -> block2 (name,p) (Ident name) p s + | [< '(Const (String name),p); s >] -> block2 (quote_ident name,p) (String name) p s | [< b = block [] >] -> EBlock b and block2 name ident p s = @@ -1087,20 +1178,23 @@ and block2 name ident p s = EBlock (block [e] s) and block acc s = + fst (block_with_pos acc null_pos s) + +and block_with_pos acc p s = try (* because of inner recursion, we can't put Display handling in errors below *) let e = try parse_block_elt s with Display e -> display (EBlock (List.rev (e :: acc)),snd e) in - block (e :: acc) s + block_with_pos (e :: acc) (pos e) s with | Stream.Failure -> - List.rev acc + List.rev acc,p | Stream.Error _ -> - let tk , pos = (match Stream.peek s with None -> last_token s | Some t -> t) in + let tk , pos = next_token s in (!display_error) (Unexpected tk) pos; - block acc s + block_with_pos acc pos s | Error (e,p) -> (!display_error) e p; - block acc s + block_with_pos acc p s and parse_block_elt = parser | [< '(Kwd Var,p1); vl = parse_var_decls p1; p2 = semicolon >] -> @@ -1111,8 +1205,8 @@ and parse_block_elt = parser and parse_obj_decl = parser | [< '(Comma,_); s >] -> (match s with parser - | [< name, _ = ident; '(DblDot,_); e = expr; l = parse_obj_decl >] -> (name,e) :: l - | [< '(Const (String name),_); '(DblDot,_); e = expr; l = parse_obj_decl >] -> (quote_ident name,e) :: l + | [< name,p = ident; '(DblDot,_); e = expr; l = parse_obj_decl >] -> ((name,p),e) :: l + | [< '(Const (String name),p); '(DblDot,_); e = expr; l = parse_obj_decl >] -> ((quote_ident name,p),e) :: l | [< >] -> []) | [< >] -> [] @@ -1125,7 +1219,7 @@ and parse_array_decl = parser [] and parse_var_decl_head = parser - | [< name, _ = dollar_ident; t = parse_type_opt >] -> (name,t) + | [< name, p = dollar_ident; t = popt parse_type_hint_with_pos >] -> (name,t,p) and parse_var_assignment = parser | [< '(Binop OpAssign,p1); s >] -> @@ -1135,27 +1229,30 @@ and parse_var_assignment = parser end | [< >] -> None +and parse_var_assignment_resume vl name pn t s = + try + let eo = parse_var_assignment s in + ((name,pn),t,eo) + with Display e -> + let v = ((name,pn),t,Some e) in + let e = (EVars(List.rev (v :: vl)),punion pn (pos e)) in + display e + and parse_var_decls_next vl = parser - | [< '(Comma,p1); name,t = parse_var_decl_head; s >] -> - begin try - let eo = parse_var_assignment s in - parse_var_decls_next ((name,t,eo) :: vl) s - with Display e -> - let v = (name,t,Some e) in - let e = (EVars(List.rev (v :: vl)),punion p1 (pos e)) in - display e - end + | [< '(Comma,p1); name,t,pn = parse_var_decl_head; s >] -> + let v_decl = parse_var_assignment_resume vl name pn t s in + parse_var_decls_next (v_decl :: vl) s | [< >] -> vl and parse_var_decls p1 = parser - | [< name,t = parse_var_decl_head; s >] -> - let eo = parse_var_assignment s in - List.rev (parse_var_decls_next [name,t,eo] s) + | [< name,t,pn = parse_var_decl_head; s >] -> + let v_decl = parse_var_assignment_resume [] name pn t s in + List.rev (parse_var_decls_next [v_decl] s) | [< s >] -> error (Custom "Missing variable identifier") p1 and parse_var_decl = parser - | [< name,t = parse_var_decl_head; eo = parse_var_assignment >] -> (name,t,eo) + | [< name,t,pn = parse_var_decl_head; v_decl = parse_var_assignment_resume [] name pn t >] -> v_decl and inline_function = parser | [< '(Kwd Inline,_); '(Kwd Function,p1) >] -> true, p1 @@ -1164,23 +1261,23 @@ and inline_function = parser and reify_expr e = let to_expr,_,_ = reify !in_macro in let e = to_expr e in - (ECheckType (e,(CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = None; tparams = [] })),pos e) + (ECheckType (e,(CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = None; tparams = [] },null_pos)),pos e) and parse_macro_expr p = parser | [< '(DblDot,_); t = parse_complex_type >] -> let _, to_type, _ = reify !in_macro in let t = to_type t p in - (ECheckType (t,(CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some "ComplexType"; tparams = [] })),p) + (ECheckType (t,(CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some "ComplexType"; tparams = [] },null_pos)),p) | [< '(Kwd Var,p1); vl = psep Comma parse_var_decl >] -> reify_expr (EVars vl,p1) | [< d = parse_class None [] [] false >] -> let _,_,to_type = reify !in_macro in - (ECheckType (to_type d,(CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some "TypeDefinition"; tparams = [] })),p) + (ECheckType (to_type d,(CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some "TypeDefinition"; tparams = [] },null_pos)),p) | [< e = secure_expr >] -> reify_expr e and parse_function p1 inl = parser - | [< name = popt dollar_ident; pl = parse_constraint_params; '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = parse_type_opt; s >] -> + | [< name = popt dollar_ident; pl = parse_constraint_params; '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = popt parse_type_hint_with_pos; s >] -> let make e = let f = { f_params = pl; @@ -1197,15 +1294,32 @@ and parse_function p1 inl = parser and expr = parser | [< (name,params,p) = parse_meta_entry; s >] -> - (try + begin try make_meta name params (secure_expr s) p - with Display e -> - display (make_meta name params e p)) - | [< '(BrOpen,p1); b = block1; '(BrClose,p2); s >] -> - let e = (b,punion p1 p2) in - (match b with - | EObjectDecl _ -> expr_next e s - | _ -> e) + with + | Display e -> + display (make_meta name params e p) + | Stream.Failure | Stream.Error _ when Path.unique_full_path p.pfile = (!resume_display).pfile -> + let e = EConst (Ident "null"),p in + display (make_meta name params e p) + end + | [< '(BrOpen,p1); s >] -> + if is_resuming p1 then display (EDisplay ((EObjectDecl [],p1),false),p1); + (match s with parser + | [< '(Binop OpOr,p2) when do_resume() >] -> + set_resume p1; + display (EDisplay ((EObjectDecl [],p1),false),p1); + | [< b = block1; s >] -> + let p2 = match s with parser + | [< '(BrClose,p2) >] -> p2 + | [< >] -> + (* Ignore missing } if we are resuming and "guess" the last position. *) + if do_resume() then pos (next_token s) else serror() + in + let e = (b,punion p1 p2) in + (match b with + | EObjectDecl _ -> expr_next e s + | _ -> e)) | [< '(Kwd Macro,p); s >] -> parse_macro_expr p s | [< '(Kwd Var,p1); v = parse_var_decl >] -> (EVars [v],p1) @@ -1218,36 +1332,36 @@ and expr = parser (match s with parser | [< '(POpen,pp); e = expr; s >] -> (match s with parser - | [< '(Comma,_); t = parse_complex_type; '(PClose,p2); s >] -> expr_next (ECast (e,Some t),punion p1 p2) s - | [< t = parse_type_hint; '(PClose,p2); s >] -> - let ep = EParenthesis (ECheckType(e,t),punion p1 p2), punion p1 p2 in + | [< '(Comma,pc); t = parse_complex_type; '(PClose,p2); s >] -> expr_next (ECast (e,Some t),punion p1 p2) s + | [< t,pt = parse_type_hint_with_pos; '(PClose,p2); s >] -> + let ep = EParenthesis (ECheckType(e,(t,pt)),punion p1 p2), punion p1 p2 in expr_next (ECast (ep,None),punion p1 (pos ep)) s + | [< '(Const (Ident "is"),p_is); t = parse_type_path; '(PClose,p2); >] -> + let e_is = make_is e t (punion p1 p2) p_is in + expr_next (ECast (e_is,None),punion p1 (pos e_is)) s | [< '(PClose,p2); s >] -> let ep = expr_next (EParenthesis(e),punion pp p2) s in expr_next (ECast (ep,None),punion p1 (pos ep)) s | [< >] -> serror()) | [< e = secure_expr >] -> expr_next (ECast (e,None),punion p1 (pos e)) s) | [< '(Kwd Throw,p); e = expr >] -> (EThrow e,p) - | [< '(Kwd New,p1); t = parse_type_path; '(POpen,p); s >] -> - if is_resuming p then display (EDisplayNew t,punion p1 p); - (match s with parser - | [< al = psep Comma expr; '(PClose,p2); s >] -> expr_next (ENew (t,al),punion p1 p2) s - | [< >] -> serror()) + | [< '(Kwd New,p1); t = parse_type_path; s >] -> + begin match s with parser + | [< '(POpen,po); e = parse_call_params (fun el p2 -> (ENew(t,el)),punion p1 p2) po >] -> expr_next e s + | [< >] -> + if do_resume() then (ENew(t,[]),punion p1 (pos t)) + else serror() + end | [< '(POpen,p1); e = expr; s >] -> (match s with parser | [< '(PClose,p2); s >] -> expr_next (EParenthesis e, punion p1 p2) s - | [< t = parse_type_hint; '(PClose,p2); s >] -> expr_next (EParenthesis (ECheckType(e,t),punion p1 p2), punion p1 p2) s + | [< t,pt = parse_type_hint_with_pos; '(PClose,p2); s >] -> expr_next (EParenthesis (ECheckType(e,(t,pt)),punion p1 p2), punion p1 p2) s + | [< '(Const (Ident "is"),p_is); t = parse_type_path; '(PClose,p2); >] -> expr_next (make_is e t (punion p1 p2) p_is) s | [< >] -> serror()) | [< '(BkOpen,p1); l = parse_array_decl; '(BkClose,p2); s >] -> expr_next (EArrayDecl l, punion p1 p2) s | [< '(Kwd Function,p1); e = parse_function p1 false; >] -> e | [< '(Unop op,p1) when is_prefix op; e = expr >] -> make_unop op e p1 | [< '(Binop OpSub,p1); e = expr >] -> - let neg s = - if s.[0] = '-' then String.sub s 1 (String.length s - 1) else "-" ^ s - in - (match make_unop Neg e p1 with - | EUnop (Neg,Prefix,(EConst (Int i),pc)),p -> EConst (Int (neg i)),p - | EUnop (Neg,Prefix,(EConst (Float j),pc)),p -> EConst (Float (neg j)),p - | e -> e) + make_unop Neg e p1 (*/* removed unary + : this cause too much syntax errors go unnoticed, such as "a + + 1" (missing 'b') without adding anything to the language | [< '(Binop OpAdd,p1); s >] -> @@ -1285,7 +1399,7 @@ and expr = parser Display e -> display (EWhile (cond,e,NormalWhile),punion p1 (pos e))) | [< '(Kwd Do,p1); e = expr; '(Kwd While,_); '(POpen,_); cond = expr; '(PClose,_); s >] -> (EWhile (cond,e,DoWhile),punion p1 (pos e)) | [< '(Kwd Switch,p1); e = expr; '(BrOpen,_); cases , def = parse_switch_cases e []; '(BrClose,p2); s >] -> (ESwitch (e,cases,def),punion p1 p2) - | [< '(Kwd Try,p1); e = expr; cl = plist (parse_catch e); >] -> (ETry (e,cl),p1) + | [< '(Kwd Try,p1); e = expr; cl,p2 = parse_catches e [] (pos e) >] -> (ETry (e,cl),punion p1 p2) | [< '(IntInterval i,p1); e2 = expr >] -> make_binop OpInterval (EConst (Int i),p1) e2 | [< '(Kwd Untyped,p1); e = expr >] -> (EUntyped e,punion p1 (pos e)) | [< '(Dollar v,p); s >] -> expr_next (EConst (Ident ("$"^v)),p) s @@ -1293,12 +1407,13 @@ and expr = parser and expr_next e1 = parser | [< '(BrOpen,p1) when is_dollar_ident e1; eparam = expr; '(BrClose,p2); s >] -> (match fst e1 with - | EConst(Ident n) -> expr_next (EMeta((Common.MetaInfo.from_string n,[],snd e1),eparam), punion p1 p2) s + | EConst(Ident n) -> expr_next (EMeta((Meta.from_string n,[],snd e1),eparam), punion p1 p2) s | _ -> assert false) | [< '(Dot,p); s >] -> if is_resuming p then display (EDisplay (e1,false),p); (match s with parser | [< '(Kwd Macro,p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,"macro") , punion (pos e1) p2) s + | [< '(Kwd Extern,p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,"extern") , punion (pos e1) p2) s | [< '(Kwd New,p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,"new") , punion (pos e1) p2) s | [< '(Const (Ident f),p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,f) , punion (pos e1) p2) s | [< '(Dollar v,p2); s >] -> expr_next (EField (e1,"$"^v) , punion (pos e1) p2) s @@ -1310,14 +1425,7 @@ and expr_next e1 = parser match e1 with | (EConst (Int v),p2) when p2.pmax = p.pmin -> expr_next (EConst (Float (v ^ ".")),punion p p2) s | _ -> serror()) - | [< '(POpen,p1); s >] -> - if is_resuming p1 then display (EDisplay (e1,true),p1); - (match s with parser - | [< '(Binop OpOr,p2) when do_resume() >] -> - set_resume p1; - display (EDisplay (e1,true),p1) (* help for debug display mode *) - | [< params = parse_call_params e1; '(PClose,p2); s >] -> expr_next (ECall (e1,params) , punion (pos e1) p2) s - | [< >] -> serror()) + | [< '(POpen,p1); e = parse_call_params (fun el p2 -> (ECall(e1,el)),punion (pos e1) p2) p1; s >] -> expr_next e s | [< '(BkOpen,_); e2 = expr; '(BkClose,p2); s >] -> expr_next (EArray (e1,e2), punion (pos e1) p2) s | [< '(Binop OpGt,p1); s >] -> @@ -1355,10 +1463,10 @@ and parse_guard = parser and parse_switch_cases eswitch cases = parser | [< '(Kwd Default,p1); '(DblDot,_); s >] -> - let b = (try block [] s with Display e -> display (ESwitch (eswitch,cases,Some (Some e)),punion (pos eswitch) (pos e))) in + let b,p2 = (try block_with_pos [] p1 s with Display e -> display (ESwitch (eswitch,cases,Some (Some e,punion p1 (pos e))),punion (pos eswitch) (pos e))) in let b = match b with - | [] -> None - | _ -> Some ((EBlock b,p1)) + | [] -> None,p1 + | _ -> let p = punion p1 p2 in Some ((EBlock b,p)),p in let l , def = parse_switch_cases eswitch cases s in (match def with None -> () | Some _ -> error Duplicate_default p1); @@ -1367,45 +1475,64 @@ and parse_switch_cases eswitch cases = parser (match el with | [] -> error (Custom "case without a pattern is not allowed") p1 | _ -> - let b = (try block [] s with Display e -> display (ESwitch (eswitch,List.rev ((el,eg,Some e) :: cases),None),punion (pos eswitch) (pos e))) in - let b = match b with - | [] -> None - | _ -> Some ((EBlock b,p1)) + let b,p2 = (try block_with_pos [] p1 s with Display e -> display (ESwitch (eswitch,List.rev ((el,eg,Some e,punion p1 (pos e)) :: cases),None),punion (pos eswitch) (pos e))) in + let b,p = match b with + | [] -> + let p2 = match eg with Some e -> pos e | None -> match List.rev el with (_,p) :: _ -> p | [] -> p1 in + None,punion p1 p2 + | _ -> let p = punion p1 p2 in Some ((EBlock b,p)),p in - parse_switch_cases eswitch ((el,eg,b) :: cases) s + parse_switch_cases eswitch ((el,eg,b,p) :: cases) s ) | [< >] -> List.rev cases , None and parse_catch etry = parser - | [< '(Kwd Catch,p); '(POpen,_); name, _ = dollar_ident; s >] -> + | [< '(Kwd Catch,p); '(POpen,_); name, pn = dollar_ident; s >] -> match s with parser - | [< t = parse_type_hint; '(PClose,_); s >] -> + | [< t,pt = parse_type_hint_with_pos; '(PClose,_); s >] -> (try - (name,t,secure_expr s) + let e = secure_expr s in + ((name,pn),(t,pt),e,punion p (pos e)),(pos e) with - Display e -> display (ETry (etry,[name,t,e]),punion (pos etry) (pos e))) + Display e -> display (ETry (etry,[(name,pn),(t,pt),e,(pos e)]),punion (pos etry) (pos e))) | [< '(_,p) >] -> error Missing_type p -and parse_call_params ec s = - let e = (try +and parse_catches etry catches pmax = parser + | [< (catch,pmax) = parse_catch etry; s >] -> parse_catches etry (catch :: catches) pmax s + | [< >] -> List.rev catches,pmax + +and parse_call_params f p1 s = + let make_display_call el p2 = + let e = f el p2 in + display (EDisplay(e,true),pos e) + in + if is_resuming p1 then make_display_call [] p1; + let rec parse_next_param acc p1 = + let e = try + expr s + with + | Stream.Error _ | Stream.Failure as exc -> + let p2 = pos (next_token s) in + if encloses_resume (punion p1 p2) then make_display_call (List.rev acc) p2 + else raise exc + | Display e -> + display (f (List.rev (e :: acc)) (pos e)) + in match s with parser - | [< e = expr >] -> Some e - | [< >] -> None - with Display e -> - display (ECall (ec,[e]),punion (pos ec) (pos e)) - ) in - let rec loop acc = - try - match s with parser - | [< '(Comma,_); e = expr >] -> loop (e::acc) - | [< >] -> List.rev acc - with Display e -> - display (ECall (ec,List.rev (e::acc)),punion (pos ec) (pos e)) + | [< '(PClose,p2) >] -> f (List.rev (e :: acc)) p2 + | [< '(Comma,p2) >] -> parse_next_param (e :: acc) p2 + | [< '(Semicolon,p2) >] -> if encloses_resume (punion p1 p2) then make_display_call (List.rev acc) p2 else serror() + | [< >] -> + let p2 = pos (next_token s) in + if encloses_resume (punion p1 p2) then make_display_call (List.rev (e :: acc)) p2 else serror() in - match e with - | None -> [] - | Some e -> loop [e] + match s with parser + | [< '(PClose,p2) >] -> f [] p2 + | [< '(Binop OpOr,p2) when do_resume() >] -> + set_resume p1; + make_display_call [] p2 + | [< >] -> parse_next_param [] p1 and parse_macro_cond allow_op s = match s with parser @@ -1426,6 +1553,7 @@ and parse_macro_cond allow_op s = tk, make_unop op e p and parse_macro_ident allow_op t p s = + if t = "display" then Hashtbl.replace special_identifier_files (Path.unique_full_path p.pfile) t; let e = (EConst (Ident t),p) in if not allow_op then None, e @@ -1551,7 +1679,7 @@ let parse ctx code = | _ -> error Unimplemented (snd tk)) | Sharp "line" -> let line = (match next_token() with - | (Const (Int s),_) -> int_of_string s + | (Const (Int s),p) -> (try int_of_string s with _ -> error (Custom ("Could not parse ridiculous line number " ^ s)) p) | (t,p) -> error (Unexpected t) p ) in !(Lexer.cur).Lexer.lline <- line - 1; @@ -1562,7 +1690,7 @@ let parse ctx code = and enter_macro p = let tk, e = parse_macro_cond false sraw in let tk = (match tk with None -> Lexer.token code | Some tk -> tk) in - if is_true (eval ctx e) || (match fst e with EConst (Ident "macro") when Common.unique_full_path p.pfile = (!resume_display).pfile -> true | _ -> false) then begin + if is_true (eval ctx e) || (match fst e with EConst (Ident "macro") when Path.unique_full_path p.pfile = (!resume_display).pfile -> true | _ -> false) then begin mstack := p :: !mstack; tk end else @@ -1611,3 +1739,39 @@ let parse ctx code = Lexer.restore old; cache := old_cache; raise e + +let parse_string com s p error inlined = + let old = Lexer.save() in + let old_file = (try Some (Hashtbl.find Lexer.all_files p.pfile) with Not_found -> None) in + let old_display = !resume_display in + let old_de = !display_error in + let restore() = + (match old_file with + | None -> () + | Some f -> Hashtbl.replace Lexer.all_files p.pfile f); + if not inlined then resume_display := old_display; + Lexer.restore old; + display_error := old_de + in + Lexer.init p.pfile true; + display_error := (fun e p -> raise (Error (e,p))); + if not inlined then resume_display := null_pos; + let pack, decls = try + parse com (Lexing.from_string s) + with Error (e,pe) -> + restore(); + error (error_msg e) (if inlined then pe else p) + | Lexer.Error (e,pe) -> + restore(); + error (Lexer.error_msg e) (if inlined then pe else p) + in + restore(); + pack,decls + +let parse_expr_string com s p error inl = + let head = "class X{static function main() " in + let head = (if p.pmin > String.length head then head ^ String.make (p.pmin - String.length head) ' ' else head) in + let rec loop e = let e = Ast.map_expr loop e in (fst e,p) in + match parse_string com (head ^ s ^ ";}") p error inl with + | _,[EClass { d_data = [{ cff_name = "main",null_pos; cff_kind = FFun { f_expr = Some e } }]},_] -> if inl then e else loop e + | _ -> raise Exit diff --git a/src/typing/abstract.ml b/src/typing/abstract.ml new file mode 100644 index 00000000..63eb912a --- /dev/null +++ b/src/typing/abstract.ml @@ -0,0 +1,67 @@ +open Meta +open Type +open Error + +let find_to ab pl b = + if follow b == t_dynamic then + List.find (fun (t,_) -> follow t == t_dynamic) ab.a_to_field + else if List.exists (unify_to ab pl ~allow_transitive_cast:false b) ab.a_to then + raise Not_found (* legacy compatibility *) + else + List.find (unify_to_field ab pl b) ab.a_to_field + +let find_from ab pl a b = + if follow a == t_dynamic then + List.find (fun (t,_) -> follow t == t_dynamic) ab.a_from_field + else if List.exists (unify_from ab pl a ~allow_transitive_cast:false b) ab.a_from then + raise Not_found (* legacy compatibility *) + else + List.find (unify_from_field ab pl a b) ab.a_from_field + +let underlying_type_stack = ref [] + +let rec get_underlying_type a pl = + let maybe_recurse t = + underlying_type_stack := (TAbstract(a,pl)) :: !underlying_type_stack; + let rec loop t = match t with + | TMono r -> + (match !r with + | Some t -> loop t + | _ -> t) + | TLazy f -> + loop (!f()) + | TType({t_path=([],"Null")} as tn,[t1]) -> + TType(tn,[loop t1]) + | TType (t,tl) -> + loop (apply_params t.t_params tl t.t_type) + | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> + if List.exists (fast_eq t) !underlying_type_stack then begin + let pctx = print_context() in + let s = String.concat " -> " (List.map (fun t -> s_type pctx t) (List.rev (t :: !underlying_type_stack))) in + underlying_type_stack := []; + error ("Abstract chain detected: " ^ s) a.a_pos + end; + get_underlying_type a tl + | _ -> + t + in + let t = loop t in + underlying_type_stack := List.tl !underlying_type_stack; + t + in + try + if not (Meta.has Meta.MultiType a.a_meta) then raise Not_found; + let m = mk_mono() in + let _ = find_to a pl m in + maybe_recurse (follow m) + with Not_found -> + if Meta.has Meta.CoreType a.a_meta then + t_dynamic + else + maybe_recurse (apply_params a.a_params pl a.a_this) + +let rec follow_with_abstracts t = match follow t with + | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> + follow_with_abstracts (get_underlying_type a tl) + | t -> + t \ No newline at end of file diff --git a/src/typing/error.ml b/src/typing/error.ml new file mode 100644 index 00000000..8e8447d2 --- /dev/null +++ b/src/typing/error.ml @@ -0,0 +1,94 @@ +open Globals +open Type + +type call_error = + | Not_enough_arguments of (string * bool * t) list + | Too_many_arguments + | Could_not_unify of error_msg + | Cannot_skip_non_nullable of string + +and error_msg = + | Module_not_found of path + | Type_not_found of path * string + | Unify of unify_error list + | Custom of string + | Unknown_ident of string + | Stack of error_msg * error_msg + | Call_error of call_error + | No_constructor of module_type + +exception Fatal_error of string * Globals.pos +exception Error of error_msg * Globals.pos + +let string_source t = match follow t with + | TInst(c,_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_fields + | TAnon a -> PMap.fold (fun cf acc -> cf.cf_name :: acc) a.a_fields [] + | TAbstract({a_impl = Some c},_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_statics + | _ -> [] + +let short_type ctx t = + let tstr = s_type ctx t in + if String.length tstr > 150 then String.sub tstr 0 147 ^ "..." else tstr + +let unify_error_msg ctx = function + | Cannot_unify (t1,t2) -> + s_type ctx t1 ^ " should be " ^ s_type ctx t2 + | Invalid_field_type s -> + "Invalid type for field " ^ s ^ " :" + | Has_no_field (t,n) -> + StringError.string_error n (string_source t) (short_type ctx t ^ " has no field " ^ n) + | Has_no_runtime_field (t,n) -> + s_type ctx t ^ "." ^ n ^ " is not accessible at runtime" + | Has_extra_field (t,n) -> + short_type ctx t ^ " has extra field " ^ n + | Invalid_kind (f,a,b) -> + (match a, b with + | Var va, Var vb -> + let name, stra, strb = if va.v_read = vb.v_read then + "setter", s_access false va.v_write, s_access false vb.v_write + else if va.v_write = vb.v_write then + "getter", s_access true va.v_read, s_access true vb.v_read + else + "access", "(" ^ s_access true va.v_read ^ "," ^ s_access false va.v_write ^ ")", "(" ^ s_access true vb.v_read ^ "," ^ s_access false vb.v_write ^ ")" + in + "Inconsistent " ^ name ^ " for field " ^ f ^ " : " ^ stra ^ " should be " ^ strb + | _ -> + "Field " ^ f ^ " is " ^ s_kind a ^ " but should be " ^ s_kind b) + | Invalid_visibility n -> + "The field " ^ n ^ " is not public" + | Not_matching_optional n -> + "Optional attribute of parameter " ^ n ^ " differs" + | Cant_force_optional -> + "Optional parameters can't be forced" + | Invariant_parameter _ -> + "Type parameters are invariant" + | Constraint_failure name -> + "Constraint check failure for " ^ name + | Missing_overload (cf, t) -> + cf.cf_name ^ " has no overload for " ^ s_type ctx t + | Unify_custom msg -> + msg + +let rec error_msg = function + | Module_not_found m -> "Type not found : " ^ s_type_path m + | Type_not_found (m,t) -> "Module " ^ s_type_path m ^ " does not define type " ^ t + | Unify l -> + let ctx = print_context() in + String.concat "\n" (List.map (unify_error_msg ctx) l) + | Unknown_ident s -> "Unknown identifier : " ^ s + | Custom s -> s + | Stack (m1,m2) -> error_msg m1 ^ "\n" ^ error_msg m2 + | Call_error err -> s_call_error err + | No_constructor mt -> (s_type_path (t_infos mt).mt_path ^ " does not have a constructor") + +and s_call_error = function + | Not_enough_arguments tl -> + let pctx = print_context() in + "Not enough arguments, expected " ^ (String.concat ", " (List.map (fun (n,_,t) -> n ^ ":" ^ (short_type pctx t)) tl)) + | Too_many_arguments -> "Too many arguments" + | Could_not_unify err -> error_msg err + | Cannot_skip_non_nullable s -> "Cannot skip non-nullable argument " ^ s + +let error msg p = raise (Error (Custom msg,p)) + +let raise_error err p = raise (Error(err,p)) \ No newline at end of file diff --git a/src/typing/matcher.ml b/src/typing/matcher.ml new file mode 100644 index 00000000..f3de28e8 --- /dev/null +++ b/src/typing/matcher.ml @@ -0,0 +1,1441 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Globals +open Ast +open Type +open Common +open Error + +exception Internal_match_failure + +let s_type = s_type (print_context()) +let s_expr_pretty = s_expr_pretty false "" false s_type + +let fake_tuple_type = TInst(mk_class null_module ([],"-Tuple") null_pos null_pos, []) + +let tuple_type tl = + tfun tl fake_tuple_type + +let make_offset_list left right middle other = + (ExtList.List.make left other) @ [middle] @ (ExtList.List.make right other) + +let type_field_access ctx ?(resume=false) e name = + Typer.acc_get ctx (Typer.type_field ~resume ctx e name e.epos Typer.MGet) e.epos + +let unapply_type_parameters params monos = + List.iter2 (fun (_,t1) t2 -> match t2,follow t2 with TMono m1,TMono m2 when m1 == m2 -> Type.unify t1 t2 | _ -> ()) params monos + +let get_general_module_type ctx mt p = + let rec loop = function + | TClassDecl _ -> "Class" + | TEnumDecl _ -> "Enum" + | TAbstractDecl a when Meta.has Meta.RuntimeValue a.a_meta -> "Class" + | TTypeDecl t -> + begin match follow (monomorphs t.t_params t.t_type) with + | TInst(c,_) -> loop (TClassDecl c) + | TEnum(en,_) -> loop (TEnumDecl en) + | TAbstract(a,_) -> loop (TAbstractDecl a) + | _ -> error "Cannot use this type as a value" p + end + | _ -> error "Cannot use this type as a value" p + in + Typeload.load_instance ctx ({tname=loop mt;tpackage=[];tsub=None;tparams=[]},null_pos) true p + +module Constructor = struct + type t = + | ConConst of tconstant + | ConEnum of tenum * tenum_field + | ConStatic of tclass * tclass_field + | ConTypeExpr of module_type + | ConFields of string list + | ConArray of int + + let to_string con = match con with + | ConConst ct -> s_const ct + | ConEnum(en,ef) -> ef.ef_name + | ConStatic(c,cf) -> Printf.sprintf "%s.%s" (s_type_path (match c.cl_kind with KAbstractImpl a -> a.a_path | _ -> c.cl_path)) cf.cf_name + | ConTypeExpr mt -> s_type_path (t_infos mt).mt_path + | ConFields fields -> Printf.sprintf "{ %s }" (String.concat ", " fields) + | ConArray i -> Printf.sprintf "" i + + let equal con1 con2 = match con1,con2 with + | ConConst ct1,ConConst ct2 -> ct1 = ct2 + | ConEnum(en1,ef1),ConEnum(en2,ef2) -> en1 == en2 && ef1 == ef2 + | ConStatic(c1,cf1),ConStatic(c2,cf2) -> c1 == c2 && cf1 == cf2 + | ConTypeExpr mt1,ConTypeExpr mt2 -> mt1 == mt2 + | ConFields _,ConFields _ -> true + | ConArray i1,ConArray i2 -> i1 = i2 + | _ -> false + + let arity con = match con with + | ConEnum (_,{ef_type = TFun(args,_)}) -> List.length args + | ConEnum _ -> 0 + | ConConst _ -> 0 + | ConFields fields -> List.length fields + | ConArray i -> i + | ConTypeExpr _ -> 0 + | ConStatic _ -> 0 + + let compare con1 con2 = match con1,con2 with + | ConConst ct1,ConConst ct2 -> compare ct1 ct2 + | ConEnum(en1,ef1),ConEnum(en2,ef2) -> compare ef1.ef_index ef2.ef_index + | ConStatic(c1,cf1),ConStatic(c2,cf2) -> compare cf1.cf_name cf2.cf_name + | ConTypeExpr mt1,ConTypeExpr mt2 -> compare (t_infos mt1).mt_path (t_infos mt2).mt_path + | ConFields _,ConFields _ -> 0 + | ConArray i1,ConArray i2 -> i1 - i2 + | _ -> -1 (* Could assert... *) + + open Typecore + + let to_texpr ctx match_debug p con = match con with + | ConEnum(en,ef) -> + if Meta.has Meta.FakeEnum en.e_meta then begin + let e_mt = !type_module_type_ref ctx (TEnumDecl en) None p in + mk (TField(e_mt,FEnum(en,ef))) ef.ef_type p + end else if match_debug then mk (TConst (TString ef.ef_name)) ctx.t.tstring p + else mk (TConst (TInt (Int32.of_int ef.ef_index))) ctx.t.tint p + | ConConst ct -> Codegen.ExprBuilder.make_const_texpr ctx.com ct p + | ConArray i -> Codegen.ExprBuilder.make_int ctx.com i p + | ConTypeExpr mt -> Typer.type_module_type ctx mt None p + | ConStatic(c,cf) -> Codegen.ExprBuilder.make_static_field c cf p + | ConFields _ -> error "Something went wrong" p + + let hash = Hashtbl.hash +end + +module Pattern = struct + open Typecore + open Constructor + + type t = + | PatConstructor of Constructor.t * pattern list + | PatVariable of tvar + | PatAny + | PatBind of tvar * pattern + | PatOr of pattern * pattern + | PatTuple of pattern list + | PatExtractor of tvar * texpr * pattern + + and pattern = t * pos + + type pattern_context = { + ctx : typer; + or_locals : (string, tvar * pos) PMap.t option; + mutable current_locals : (string, tvar * pos) PMap.t; + mutable in_reification : bool; + } + + exception Bad_pattern of string + + let rec to_string pat = match fst pat with + | PatConstructor(con,patterns) -> Printf.sprintf "%s(%s)" (Constructor.to_string con) (String.concat ", " (List.map to_string patterns)) + | PatVariable v -> Printf.sprintf "%s<%i>" v.v_name v.v_id + | PatAny -> "_" + | PatBind(v,pat1) -> Printf.sprintf "%s = %s" v.v_name (to_string pat1) + | PatOr(pat1,pat2) -> Printf.sprintf "(%s) | (%s)" (to_string pat1) (to_string pat2) + | PatTuple pl -> Printf.sprintf "[%s]" (String.concat ", " (List.map to_string pl)) + | PatExtractor(v,e,pat1) -> Printf.sprintf "%s => %s" (s_expr_pretty e) (to_string pat1) + + let unify_type_pattern ctx mt t p = + let tcl = get_general_module_type ctx mt p in + match tcl with + | TAbstract(a,_) -> unify ctx (TAbstract(a,[mk_mono()])) t p + | _ -> assert false + + let rec make pctx t e = + let ctx = pctx.ctx in + let p = pos e in + let fail () = + error ("Unrecognized pattern: " ^ (Ast.s_expr e)) p + in + let unify_expected t' = + unify ctx t' t p + in + let verror name p = + error (Printf.sprintf "Variable %s must appear exactly once in each sub-pattern" name) p + in + let add_local name p = + let is_wildcard_local = name = "_" in + if not is_wildcard_local && PMap.mem name pctx.current_locals then error (Printf.sprintf "Variable %s is bound multiple times" name) p; + match pctx.or_locals with + | Some map when not is_wildcard_local -> + let v,p = try PMap.find name map with Not_found -> verror name p in + unify ctx t v.v_type p; + pctx.current_locals <- PMap.add name (v,p) pctx.current_locals; + v + | _ -> + let v = alloc_var name t p in + pctx.current_locals <- PMap.add name (v,p) pctx.current_locals; + ctx.locals <- PMap.add name v ctx.locals; + v + in + let check_expr e = + let rec loop e = match e.eexpr with + | TField(_,FEnum(en,ef)) -> + (* Let the unification afterwards fail so we don't recover. *) + (* (match follow ef.ef_type with TFun _ -> raise Exit | _ -> ()); *) + PatConstructor(ConEnum(en,ef),[]) + | TField(_,FStatic(c,({cf_kind = Var {v_write = AccNever}} as cf))) -> + PatConstructor(ConStatic(c,cf),[]) + | TConst ct -> + PatConstructor(ConConst ct,[]) + | TCast(e1,None) -> + loop e1 + | TField _ -> + raise (Bad_pattern "Only inline or read-only (default, never) fields can be used as a pattern") + | _ -> + raise Exit + in + loop e + in + let try_typing e = + let old = ctx.untyped in + ctx.untyped <- true; + let e = try type_expr ctx e (WithType t) with exc -> ctx.untyped <- old; raise exc in + ctx.untyped <- old; + match e.eexpr with + | TTypeExpr mt -> + unify_type_pattern ctx mt t e.epos; + PatConstructor(ConTypeExpr mt,[]) + | _ -> + let pat = check_expr e in + begin try + Type.unify e.etype t + with (Unify_error l) -> + (* Hack: Allow matching the underlying type against its abstract. *) + begin match follow e.etype with + | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) && type_iseq t (Abstract.get_underlying_type a tl) -> () + | _ -> raise_or_display ctx l p + end + end; + pat + in + let handle_ident s p = + let save = + let old = ctx.locals in + ctx.locals <- (try PMap.add "this" (PMap.find "this" old) PMap.empty with Not_found -> PMap.empty); + (fun () -> + ctx.locals <- old; + ) + in + try + let pat = try_typing (EConst (Ident s),p) in + save(); + pat + with + | Exit | Bad_pattern _ -> + begin try + let mt = module_type_of_type t in + let e_mt = Typer.type_module_type ctx mt None p in + let e = type_field_access ctx ~resume:true e_mt s in + let pat = check_expr e in + save(); + pat + with _ -> + save(); + if not (is_lower_ident s) && (match s.[0] with '`' | '_' -> false | _ -> true) then begin + display_error ctx "Capture variables must be lower-case" p; + end; + let v = add_local s p in + PatVariable v + end + | exc -> + save(); + raise exc + in + let rec loop e = match fst e with + | EParenthesis e1 | ECast(e1,None) -> + loop e1 + | ECheckType(e, (CTPath({tpackage=["haxe";"macro"]; tname="Expr"}),_)) -> + let old = pctx.in_reification in + pctx.in_reification <- true; + let e = loop e in + pctx.in_reification <- old; + e + | EConst((Ident ("false" | "true") | Int _ | String _ | Float _) as ct) -> + let e = Codegen.type_constant ctx.com ct p in + unify_expected e.etype; + let ct = match e.eexpr with TConst ct -> ct | _ -> assert false in + PatConstructor(ConConst ct,[]) + | EConst (Ident i) -> + begin match i with + | "_" -> + begin match follow t with + | TFun(ta,tr) when tr == fake_tuple_type -> + PatTuple(List.map (fun (_,_,t) -> (PatAny,pos e)) ta) + | _ -> + PatAny + end + | _ -> + handle_ident i (pos e) + end + | EVars([(s,p),None,None]) -> + let v = add_local s p in + PatVariable v + | ECall(e1,el) -> + let t = tfun (List.map (fun _ -> mk_mono()) el) t in + let e1 = type_expr ctx e1 (WithType t) in + begin match e1.eexpr,follow e1.etype with + | TField(_, FEnum(en,ef)),TFun(_,TEnum(_,tl)) -> + let monos = List.map (fun _ -> mk_mono()) ef.ef_params in + let map t = apply_params en.e_params tl (apply_params ef.ef_params monos t) in + (* We cannot use e1.etype here because it has applied type parameters (issue #1310). *) + let args = match follow (map ef.ef_type) with + | TFun(args,r) -> + unify_expected r; + args + | _ -> assert false + in + let rec loop el tl = match el,tl with + | [EConst (Ident "_"),p],(_,_,t) :: tl -> + (* Allow using final _ to match "multiple" arguments *) + (PatAny,p) :: (match tl with [] -> [] | _ -> loop el tl) + | e :: el,(_,_,t) :: tl -> + make pctx t e :: loop el tl + | [],(_,true,t) :: tl -> + (PatAny,pos e) :: loop [] tl + | [],[] -> + [] + | [],_ -> + error "Not enough arguments" p + | _,[] -> + error "Too many arguments" p + in + let patterns = loop el args in + (* We want to change the original monomorphs back to type parameters, but we don't want to do that + if they are bound to other monomorphs (issue #4578). *) + unapply_type_parameters ef.ef_params monos; + PatConstructor(ConEnum(en,ef),patterns) + | _ -> + fail() + end + | EField _ -> + begin try + try_typing e + with + | Exit -> fail() + | Bad_pattern s -> error s p + end + | EArrayDecl el -> + begin match follow t with + | TFun(tl,tr) when tr == fake_tuple_type -> + let rec loop el tl = match el,tl with + | e :: el,(_,_,t) :: tl -> + let pat = make pctx t e in + pat :: loop el tl + | [],[] -> [] + | [],_ -> error "Not enough arguments" p + | (_,p) :: _,[] -> error "Too many arguments" p + in + let patterns = loop el tl in + PatTuple patterns + | TInst({cl_path=[],"Array"},[t2]) | (TDynamic _ as t2) -> + let patterns = ExtList.List.mapi (fun i e -> + make pctx t2 e + ) el in + PatConstructor(ConArray (List.length patterns),patterns) + | _ -> + fail() + end + | EObjectDecl fl -> + let known_fields = match follow t with + | TAnon an -> + PMap.fold (fun cf acc -> (cf,cf.cf_type) :: acc) an.a_fields [] + | TInst(c,tl) -> + let rec loop fields c tl = + let fields = List.fold_left (fun acc cf -> (cf,apply_params c.cl_params tl cf.cf_type) :: acc) fields c.cl_ordered_fields in + match c.cl_super with + | None -> fields + | Some (csup,tlsup) -> loop fields csup (List.map (apply_params c.cl_params tl) tlsup) + in + loop [] c tl + | TAbstract({a_impl = Some c} as a,tl) -> + let fields = List.fold_left (fun acc cf -> + if Meta.has Meta.Impl cf.cf_meta then + (cf,apply_params a.a_params tl cf.cf_type) :: acc + else + acc + ) [] c.cl_ordered_statics in + fields + | _ -> + error (Printf.sprintf "Cannot field-match against %s" (s_type t)) (pos e) + in + let is_matchable cf = + match cf.cf_kind with Method _ -> false | _ -> true + in + let patterns,fields = List.fold_left (fun (patterns,fields) (cf,t) -> + try + if pctx.in_reification && cf.cf_name = "pos" then raise Not_found; + let e1 = Expr.field_assoc cf.cf_name fl in + make pctx t e1 :: patterns,cf.cf_name :: fields + with Not_found -> + if is_matchable cf then + (PatAny,cf.cf_pos) :: patterns,cf.cf_name :: fields + else + patterns,fields + ) ([],[]) known_fields in + List.iter (fun ((s,_),e) -> if not (List.mem s fields) then error (Printf.sprintf "%s has no field %s" (s_type t) s) (pos e)) fl; + PatConstructor(ConFields fields,patterns) + | EBinop(OpOr,e1,e2) -> + let pctx1 = {pctx with current_locals = PMap.empty} in + let pat1 = make pctx1 t e1 in + let pctx2 = {pctx with current_locals = PMap.empty; or_locals = Some (pctx1.current_locals)} in + let pat2 = make pctx2 t e2 in + PMap.iter (fun name (v,p) -> + if not (PMap.mem name pctx2.current_locals) then verror name p; + pctx.current_locals <- PMap.add name (v,p) pctx.current_locals + ) pctx1.current_locals; + PatOr(pat1,pat2) + | EBinop(OpAssign,(EConst (Ident s),p),e2) -> + let pat = make pctx t e2 in + let v = add_local s p in + PatBind(v,pat) + | EBinop(OpArrow,e1,e2) -> + let v = add_local "_" null_pos in + let e1 = type_expr ctx e1 Value in + v.v_name <- "tmp"; + let pat = make pctx e1.etype e2 in + PatExtractor(v,e1,pat) + | EDisplay(e,iscall) -> + let pat = loop e in + let _ = if iscall then Typer.handle_signature_display ctx e (WithType t) + else Typer.handle_display ctx e (WithType t) in + pat + | _ -> + fail() + in + let pat = loop e in + pat,p + + let make ctx t e = + let pctx = { + ctx = ctx; + current_locals = PMap.empty; + or_locals = None; + in_reification = false; + } in + make pctx t e +end + +module Case = struct + open Typecore + + type t = { + case_guard : texpr option; + case_expr : texpr option; + case_pos : pos; + } + + let make ctx t el eg eo_ast with_type p = + let rec collapse_case el = match el with + | e :: [] -> + e + | e :: el -> + let e2 = collapse_case el in + EBinop(OpOr,e,e2),punion (pos e) (pos e2) + | [] -> + assert false + in + let e = collapse_case el in + let monos = List.map (fun _ -> mk_mono()) ctx.type_params in + let map = apply_params ctx.type_params monos in + let save = save_locals ctx in + let old_types = PMap.fold (fun v acc -> + let t_old = v.v_type in + v.v_type <- map v.v_type; + (v,t_old) :: acc + ) ctx.locals [] in + let old_ret = ctx.ret in + ctx.ret <- map ctx.ret; + let pat = Pattern.make ctx (map t) e in + unapply_type_parameters ctx.type_params monos; + let eg = match eg with + | None -> None + | Some e -> Some (type_expr ctx e Value) + in + let eo = match eo_ast,with_type with + | None,WithType t -> + unify ctx ctx.t.tvoid t (pos e); + None + | None,_ -> + None + | Some e,WithType t -> + let e = type_expr ctx e (WithType (map t)) in + let e = AbstractCast.cast_or_unify ctx (map t) e e.epos in + Some e + | Some e,_ -> + let e = type_expr ctx e with_type in + Some e + in + ctx.ret <- old_ret; + List.iter (fun (v,t) -> v.v_type <- t) old_types; + save(); + if ctx.is_display_file && Display.is_display_position p then begin match eo,eo_ast with + | Some e,Some e_ast -> ignore(Typer.display_expr ctx e_ast e with_type p) + | None,None -> ignore(Typer.display_expr ctx (EBlock [],p) (mk (TBlock []) ctx.t.tvoid p) with_type p) + | _ -> assert false + end; + { + case_guard = eg; + case_expr = eo; + case_pos = p; + },[],pat +end + +module Decision_tree = struct + open Case + + type subject = texpr + + type type_finiteness = + | Infinite (* type has inifite constructors (e.g. Int, String) *) + | CompileTimeFinite (* type is considered finite only at compile-time but has inifite possible run-time values (enum abstracts) *) + | RunTimeFinite (* type is truly finite (Bool, enums) *) + + type t = + | Leaf of Case.t + | Switch of subject * (Constructor.t * bool * dt) list * dt + | Bind of (tvar * pos * texpr) list * dt + | Guard of texpr * dt * dt + | GuardNull of texpr * dt * dt + | Fail + + and dt = { + dt_t : t; + dt_i : int; + dt_pos : pos; + mutable dt_goto_target : bool; + } + + let s_case_expr tabs case = match case.case_expr with + | None -> "" + | Some e -> Type.s_expr_pretty false tabs false s_type e + + let rec to_string tabs dt = match dt.dt_t with + | Leaf case -> + s_case_expr tabs case + | Switch(e,cases,dt) -> + let s_case (con,b,dt) = + Printf.sprintf "\n\t%scase %s%s: %s" tabs (Constructor.to_string con) (if b then "(unguarded) " else "") (to_string (tabs ^ "\t") dt) + in + let s_cases = String.concat "" (List.map s_case cases) in + let s_default = to_string (tabs ^ "\t") dt in + Printf.sprintf "switch (%s) {%s\n%s\tdefault: %s\n%s}" (Type.s_expr_pretty false tabs false s_type e) s_cases tabs s_default tabs + | Bind(bl,dt) -> + (String.concat "" (List.map (fun (v,_,e) -> if v.v_name = "_" then "" else Printf.sprintf "%s<%i> = %s; " v.v_name v.v_id (s_expr_pretty e)) bl)) ^ + to_string tabs dt + | Guard(e,dt1,dt2) -> + Printf.sprintf "if (%s) {\n\t%s%s\n%s} else {\n\t%s%s\n%s}" (s_expr_pretty e) tabs (to_string (tabs ^ "\t") dt1) tabs tabs (to_string (tabs ^ "\t") dt2) tabs + | GuardNull(e,dt1,dt2) -> + Printf.sprintf "if (%s == null) {\n\t%s%s\n%s} else {\n\t%s%s\n%s}" (s_expr_pretty e) tabs (to_string (tabs ^ "\t") dt1) tabs tabs (to_string (tabs ^ "\t") dt2) tabs + | Fail -> + "" + + let equal_dt dt1 dt2 = dt1.dt_i = dt2.dt_i + + let equal dt1 dt2 = match dt1,dt2 with + | Leaf case1,Leaf case2 -> + case1 == case2 + | Switch(subject1,cases1,dt1),Switch(subject2,cases2,dt2) -> + subject1 == subject2 && + safe_for_all2 (fun (con1,b1,dt1) (con2,b2,dt2) -> Constructor.equal con1 con2 && b1 = b2 && equal_dt dt1 dt2) cases1 cases2 && + equal_dt dt1 dt2 + | Bind(l1,dt1),Bind(l2,dt2) -> + safe_for_all2 (fun (v1,_,e1) (v2,_,e2) -> v1 == v2 && e1 == e2) l1 l2 && + equal_dt dt1 dt2 + | Fail,Fail -> + true + | (Guard(e1,dt11,dt12),Guard(e2,dt21,dt22)) | (GuardNull(e1,dt11,dt12),GuardNull(e2,dt21,dt22)) -> + e1 == e2 && equal_dt dt11 dt21 && equal_dt dt12 dt22 + | _ -> + false + + let hash = Hashtbl.hash +end + +module ConTable = Hashtbl.Make(Constructor) + +(* + Implements checks for useless patterns based on http://moscova.inria.fr/~maranget/papers/warn/index.html. +*) +module Useless = struct + open Pattern + open Constructor + open Case + + type useless = + | False + | Pos of pos + | True + + (* U part *) + + let specialize is_tuple con pM = + let rec loop acc pM = match pM with + | patterns :: pM -> + begin match patterns with + | (PatConstructor(con',patterns1),_) :: patterns2 when not is_tuple && Constructor.equal con con' -> + loop ((patterns1 @ patterns2) :: acc) pM + | (PatTuple patterns1,_) :: patterns2 when is_tuple -> + loop ((patterns1 @ patterns2) :: acc) pM + | (PatAny,p) :: patterns2 -> + let patterns1 = ExtList.List.make (arity con) (PatAny,p) in + loop ((patterns1 @ patterns2) :: acc) pM + | (PatBind(_,pat1),_) :: patterns2 -> + loop acc ((pat1 :: patterns2) :: pM) + | _ -> + loop acc pM + end + | [] -> + List.rev acc + in + loop [] pM + + let default pM = + let rec loop acc pM = match pM with + | patterns :: pM -> + begin match patterns with + | ((PatConstructor _ | PatTuple _),_) :: _ -> + loop acc pM + | ((PatVariable _ | PatAny),_) :: patterns -> + loop (patterns :: acc) pM + | _ -> + loop acc pM + end + | [] -> + List.rev acc + in + loop [] pM + + let rec u pM q = + match q,pM with + | [],[] -> true + | [],_ -> false + | (q1 :: ql),_ -> + let rec loop pat = match fst pat with + | PatConstructor(con,patterns) -> + let s = specialize false con pM in + u s (patterns @ ql) + | PatTuple patterns -> + let s = specialize true (ConConst TNull) pM in + u s (patterns @ ql) + | (PatVariable _ | PatAny) -> + let d = default pM in + u d ql + | PatOr(pat1,pat2) -> + u pM (pat1 :: ql) || u pM (pat2 :: ql) + | PatBind(_,pat1) -> + loop pat1 + | PatExtractor _ -> + true (* ? *) + in + loop q1 + + (* U' part *) + + let transfer_column source target = + let source,target = List.fold_left2 (fun (source,target) patterns1 patterns2 -> match patterns1 with + | pat :: patterns -> patterns :: source,(pat :: patterns2) :: target + | [] -> source,target + ) ([],[]) source target in + List.rev source,List.rev target + + let copy p = List.map (fun _ -> []) p + + let rec specialize' is_tuple con pM qM rM = + let arity = arity con in + let rec loop pAcc qAcc rAcc pM qM rM = match pM,qM,rM with + | p1 :: pM,q1 :: qM,r1 :: rM -> + let rec loop2 p1 = match p1 with + | (PatConstructor(con',patterns1),_) :: patterns2 when not is_tuple && Constructor.equal con con' -> + loop ((patterns1 @ patterns2) :: pAcc) (q1 :: qAcc) (r1 :: rAcc) pM qM rM + | (PatTuple patterns1,_) :: patterns2 when is_tuple -> + loop ((patterns1 @ patterns2) :: pAcc) (q1 :: qAcc) (r1 :: rAcc) pM qM rM + | ((PatVariable _ | PatAny),p) :: patterns2 -> + let patterns1 = ExtList.List.make arity (PatAny,p) in + loop ((patterns1 @ patterns2) :: pAcc) (q1 :: qAcc) (r1 :: rAcc) pM qM rM + | ((PatOr(pat1,pat2)),_) :: patterns2 -> + loop pAcc qAcc rAcc (((pat1 :: patterns2) :: (pat2 :: patterns2) :: pM)) (q1 :: q1 :: qM) (r1 :: r1 :: rM) + | (PatBind(_,pat1),_) :: patterns2 -> + loop2 (pat1 :: patterns2) + | _ -> + loop pAcc qAcc rAcc pM qM rM + in + loop2 p1 + | [],_,_ -> + List.rev pAcc,List.rev qAcc,List.rev rAcc + | _ -> + assert false + in + loop [] [] [] pM qM rM + + let combine et1 et2 = match fst et1,fst et2 with + | True,True -> True + | False,False -> False + | True,False -> Pos (pos et2) + | False,True -> Pos (pos et1) + | True,Pos _ -> fst et2 + | Pos _,True -> fst et1 + | False,Pos _ -> Pos (pos et1) + | Pos _,_ -> fst et1 + + let rec u' pM qM rM p q r = + match p with + | [] -> + begin match r with + | [] -> if u qM q then True else False + | _ -> + snd (List.fold_left (fun (i,et) pat -> match fst pat with + | PatOr(pat1,pat2) -> + let process_row i l q = + let rec loop acc k l = match l with + | x :: l when i = k -> x,(List.rev acc) @ l @ q + | x :: l -> loop (x :: acc) (k + 1) l + | [] -> assert false + in + loop [] 0 l + in + let col,mat = List.fold_left2 (fun (col,mat) r q -> + let x,l = process_row i r q in + ([x] :: col,l :: mat) + ) ([],[]) rM qM in + let col,mat = List.rev col,List.rev mat in + let _,r = process_row i r q in + let et1 = u' col mat (copy mat) [pat1] r [] in + let qM = (mat @ [r]) in + let et2 = u' (col @ [[pat1]]) qM (copy qM) [pat2] r [] in + let et3 = combine (et1,pos pat1) (et2,pos pat2) in + let p = punion (pos pat1) (pos pat2) in + let et = combine (et,p) (et3,p) in + (i + 1,et) + | _ -> assert false + ) (0,True) r) + end + | (pat :: pl) -> + let rec loop pat = match fst pat with + | PatConstructor(con,patterns) -> + let pM,qM,rM = specialize' false con pM qM rM in + u' pM qM rM (patterns @ pl) q r + | PatTuple patterns -> + let pM,qM,rM = specialize' true (ConConst TNull) pM qM rM in + u' pM qM rM (patterns @ pl) q r + | PatAny | PatVariable _ -> + let pM,qM = transfer_column pM qM in + u' pM qM rM pl (pat :: q) r + | PatOr _ -> + let pM,rM = transfer_column pM rM in + u' pM qM rM pl q (pat :: r) + | PatBind(_,pat1) -> + loop pat1 + | PatExtractor _ -> + True + in + loop pat + + (* Sane part *) + + let check_case com p (case,bindings,patterns) = + let p = List.map (fun (_,_,patterns) -> patterns) p in + match u' p (copy p) (copy p) patterns [] [] with + | False -> com.warning "This case is unused" case.case_pos + | Pos p -> com.warning "This pattern is unused" p + | True -> () + + let check com cases = + ignore(List.fold_left (fun acc (case,bindings,patterns) -> + check_case com acc (case,bindings,patterns); + if case.case_guard = None then acc @ [case,bindings,patterns] else acc + ) [] cases) +end + +module DtTable = Hashtbl.Make(Decision_tree) + +module Compile = struct + open Typecore + open Decision_tree + open Case + open Constructor + open Pattern + + exception Extractor + + type matcher_context = { + ctx : typer; + dt_table : dt DtTable.t; + match_pos : pos; + match_debug : bool; + mutable dt_count : int; + } + + let rec hashcons mctx dt p = + try + DtTable.find mctx.dt_table dt + with Not_found -> + let dti = {dt_t = dt; dt_i = mctx.dt_count; dt_pos = p; dt_goto_target = false } in + DtTable.add mctx.dt_table dt dti; + mctx.dt_count <- mctx.dt_count + 1; + dti + + let leaf mctx case = hashcons mctx (Leaf case) case.case_pos + let fail mctx p = hashcons mctx Fail p + let switch mctx subject cases default = hashcons mctx (Switch(subject,cases,default)) subject.epos + let bind mctx bindings dt = hashcons mctx (Bind(bindings,dt)) dt.dt_pos + let guard mctx e dt1 dt2 = hashcons mctx (Guard(e,dt1,dt2)) (punion dt1.dt_pos dt2.dt_pos) + let guard_null mctx e dt1 dt2 = hashcons mctx (GuardNull(e,dt1,dt2)) (punion dt1.dt_pos dt2.dt_pos) + + let rec get_sub_subjects mctx e con = + match con with + | ConEnum(en,ef) -> + let tl = List.map (fun _ -> mk_mono()) en.e_params in + let t_en = TEnum(en,tl) in + let e = if not (type_iseq t_en e.etype) then mk (TCast(e,None)) t_en e.epos else e in + begin match follow ef.ef_type with + | TFun(args,_) -> + ExtList.List.mapi (fun i (_,_,t) -> mk (TEnumParameter(e,ef,i)) (apply_params en.e_params tl (monomorphs ef.ef_params t)) e.epos) args + | _ -> + [] + end + | ConFields sl -> + List.map (type_field_access mctx.ctx e) sl + | ConArray 0 -> [] + | ConArray i -> + let t = match follow e.etype with TInst({cl_path=[],"Array"},[t]) -> t | TDynamic _ as t -> t | _ -> assert false in + ExtList.List.init i (fun i -> + let ei = Codegen.ExprBuilder.make_int mctx.ctx.com i e.epos in + mk (TArray(e,ei)) t e.epos + ) + | ConConst _ | ConTypeExpr _ | ConStatic _ -> + [] + + let specialize subject con cases = + let arity = arity con in + let rec loop acc cases = match cases with + | (case,bindings,patterns) :: cases -> + begin match patterns with + | (PatConstructor(con',patterns1),_) :: patterns2 when Constructor.equal con con' -> + loop ((case,bindings,patterns1 @ patterns2) :: acc) cases + | (PatVariable v,p) :: patterns2 -> + let patterns1 = ExtList.List.make arity (PatAny,p) in + loop ((case,((v,p,subject) :: bindings),patterns1 @ patterns2) :: acc) cases + | ((PatAny,_)) as pat :: patterns2 -> + let patterns1 = ExtList.List.make arity pat in + loop ((case,bindings,patterns1 @ patterns2) :: acc) cases + | ((PatBind(v,pat),p)) :: patterns -> + loop acc ((case,((v,p,subject) :: bindings),pat :: patterns) :: cases) + | _ -> + loop acc cases + end + | [] -> + List.rev acc + in + loop [] cases + + let default subject cases = + let rec loop acc cases = match cases with + | (case,bindings,patterns) :: cases -> + begin match patterns with + | (PatConstructor _,_) :: _ -> + loop acc cases + | (PatVariable v,p) :: patterns -> + loop ((case,((v,p,subject) :: bindings),patterns) :: acc) cases + | (PatAny,_) :: patterns -> + loop ((case,bindings,patterns) :: acc) cases + | (PatBind(v,pat),p) :: patterns -> + loop acc ((case,((v,p,subject) :: bindings),pat :: patterns) :: cases) + | _ -> + loop acc cases + end + | [] -> + List.rev acc + in + loop [] cases + + let rec is_wildcard_pattern pat = match fst pat with + | PatVariable _ | PatAny -> true + | _ -> false + + let rec expand cases = + let changed,cases = List.fold_left (fun (changed,acc) (case,bindings,patterns) -> + let rec loop f patterns = match patterns with + | (PatOr(pat1,pat2),_) :: patterns -> + true,(case,bindings,f pat2 :: patterns) :: (case,bindings,f pat1 :: patterns) :: acc + | (PatBind(v,pat1),p) :: patterns -> + loop (fun pat2 -> f (PatBind(v,pat2),p)) (pat1 :: patterns) + | (PatTuple patterns1,_) :: patterns2 -> + loop f (patterns1 @ patterns2) + | pat :: patterns -> + changed,(case,bindings,f pat :: patterns) :: acc + | [] -> + changed,((case,bindings,patterns) :: acc) + in + loop (fun pat -> pat) patterns + ) (false,[]) cases in + let cases = List.rev cases in + if changed then expand cases else cases + + let s_subjects subjects = + String.concat " " (List.map s_expr_pretty subjects) + + let s_case (case,bindings,patterns) = + let s_bindings = String.concat ", " (List.map (fun (v,_,e) -> Printf.sprintf "%s<%i> = %s" v.v_name v.v_id (s_expr_pretty e)) bindings) in + let s_patterns = String.concat " " (List.map Pattern.to_string patterns) in + let s_expr = match case.case_expr with None -> "" | Some e -> Type.s_expr_pretty false "\t\t" false s_type e in + let s_guard = match case.case_guard with None -> "" | Some e -> Type.s_expr_pretty false "\t\t" false s_type e in + Printf.sprintf "\n\t\tbindings: %s\n\t\tpatterns: %s\n\t\tguard: %s\n\t\texpr: %s" s_bindings s_patterns s_guard s_expr + + let s_cases cases = + String.concat "\n" (List.map s_case cases) + + let select_column subjects cases = + let rec loop i patterns = match patterns with + | ((PatVariable _ | PatAny | PatExtractor _),_) :: patterns -> loop (i + 1) patterns + | [] -> 0 + | _ -> i + in + let _,_,patterns = List.hd cases in + let i = loop 0 patterns in + let subjects,cases = if i = 0 then + subjects,cases + else begin + let rec sort i cur acc l = match l with + | x :: l -> + if i = cur then x :: acc @ l + else sort i (cur + 1) (x :: acc) l + | [] -> + acc + in + let subjects = sort i 0 [] subjects in + let cases = List.map (fun (case,bindings,patterns) -> + let patterns = sort i 0 [] patterns in + case,bindings,patterns + ) cases in + subjects,cases + end in + subjects,cases + + let rec compile mctx subjects cases = match cases with + | [] -> + fail mctx (match subjects with e :: _ -> e.epos | _ -> mctx.match_pos); + | (_,_,patterns) as case :: cases when List.for_all is_wildcard_pattern patterns -> + compile_leaf mctx subjects case cases + | _ -> + let cases = expand cases in + let subjects,cases = select_column subjects cases in + let cases = expand cases in (* TODO: is this really necessary? *) + try + compile_switch mctx subjects cases + with Extractor -> + compile_extractors mctx subjects cases + + and compile_leaf mctx subjects (case,bindings,patterns) cases = + if mctx.match_debug then print_endline (Printf.sprintf "compile_leaf:\n\tsubjects: %s\n\tcase: %s\n\tcases: %s" (s_subjects subjects) (s_case (case,bindings,patterns)) (s_cases cases)); + let dt = leaf mctx case in + let dt = match case.case_guard with + | None -> + dt + | Some e -> + let dt2 = compile mctx subjects cases in + guard mctx e dt dt2 + in + let rec loop patterns el = match patterns,el with + | [PatAny,_],_ -> + [] + | (PatVariable v,p) :: patterns,e :: el -> + (v,p,e) :: loop patterns el + | _ :: patterns,_ :: el -> + loop patterns el + | [],[] -> + [] + | [],e :: _ -> + error "Invalid match: Not enough patterns" e.epos + | (_,p) :: _,[] -> + error "Invalid match: Too many patterns" p + in + let bindings = bindings @ loop patterns subjects in + if bindings = [] then dt else bind mctx bindings dt + + and compile_switch mctx subjects cases = + let subject,subjects = match subjects with + | [] -> raise Internal_match_failure + | subject :: subjects -> subject,subjects + in + let get_column_sigma cases = + let sigma = ConTable.create 0 in + let unguarded = ConTable.create 0 in + let null = ref [] in + List.iter (fun (case,bindings,patterns) -> + let rec loop pat = match fst pat with + | PatConstructor(ConConst TNull,_) -> + null := (case,bindings,List.tl patterns) :: !null; + | PatConstructor(con,_) -> + if case.case_guard = None then ConTable.replace unguarded con true; + ConTable.replace sigma con true; + | PatBind(_,pat) -> loop pat + | PatVariable _ | PatAny -> () + | PatExtractor _ -> raise Extractor + | _ -> error ("Unexpected pattern: " ^ (Pattern.to_string pat)) case.case_pos; + in + loop (List.hd patterns) + ) cases; + let sigma = ConTable.fold (fun con _ acc -> (con,ConTable.mem unguarded con) :: acc) sigma [] in + sigma,List.rev !null + in + let sigma,null = get_column_sigma cases in + if mctx.match_debug then print_endline (Printf.sprintf "compile_switch:\n\tsubject: %s\n\ttsubjects: %s\n\tcases: %s" (s_expr_pretty subject) (s_subjects subjects) (s_cases cases)); + let switch_cases = List.map (fun (con,unguarded) -> + let subjects = get_sub_subjects mctx subject con @ subjects in + let spec = specialize subject con cases in + let dt = compile mctx subjects spec in + con,unguarded,dt + ) sigma in + let default = default subject cases in + let switch_default = compile mctx subjects default in + let dt = if switch_cases = [] then switch_default else switch mctx subject switch_cases switch_default in + let null_guard dt_null = + guard_null mctx subject dt_null dt + in + match null with + | [] -> + if is_explicit_null subject.etype then null_guard switch_default else dt + | cases -> + let dt_null = compile mctx subjects (cases @ default) in + null_guard dt_null + + and compile_extractors mctx subjects cases = + let subject,subjects = match subjects with + | [] -> raise Internal_match_failure + | subject :: subjects -> subject,subjects + in + if mctx.match_debug then print_endline (Printf.sprintf "compile_extractor:\n\tsubject: %s\n\ttsubjects: %s\n\tcases: %s" (s_expr_pretty subject) (s_subjects subjects) (s_cases cases)); + let num_extractors,extractors = List.fold_left (fun (i,extractors) (_,_,patterns) -> + let rec loop bindings pat = match pat with + | (PatExtractor(v,e1,pat),_) -> i + 1,Some (v,e1,pat,bindings) :: extractors + | (PatBind(v,pat1),_) -> loop (v :: bindings) pat1 + | _ -> i,None :: extractors + in + loop [] (List.hd patterns) + ) (0,[]) cases in + let pat_any = (PatAny,null_pos) in + let _,_,ex_subjects,cases,bindings = List.fold_left2 (fun (left,right,subjects,cases,ex_bindings) (case,bindings,patterns) extractor -> match extractor,patterns with + | Some(v,e1,pat,vars), _ :: patterns -> + let patterns = make_offset_list (left + 1) (right - 1) pat pat_any @ patterns in + let rec loop e = match e.eexpr with + | TLocal v' when v' == v -> subject + | _ -> Type.map_expr loop e + in + let e1 = loop e1 in + let bindings = List.map (fun v -> v,subject.epos,subject) vars @ bindings in + let v,ex_bindings = try + let v,_,_ = List.find (fun (_,_,e2) -> Texpr.equal e1 e2) ex_bindings in + v,ex_bindings + with Not_found -> + let v = alloc_var "_hx_tmp" e1.etype e1.epos in + v.v_meta <- (Meta.Custom ":extractorVariable",[],v.v_pos) :: v.v_meta; + v,(v,e1.epos,e1) :: ex_bindings + in + let ev = mk (TLocal v) v.v_type e1.epos in + (left + 1, right - 1,ev :: subjects,((case,bindings,patterns) :: cases),ex_bindings) + | None,pat :: patterns -> + let patterns = make_offset_list 0 num_extractors pat pat_any @ patterns in + (left,right,subjects,((case,bindings,patterns) :: cases),ex_bindings) + | _,[] -> + assert false + ) (0,num_extractors,[],[],[]) cases (List.rev extractors) in + let dt = compile mctx ((subject :: List.rev ex_subjects) @ subjects) (List.rev cases) in + bind mctx bindings dt + + let compile ctx match_debug subjects cases p = + let mctx = { + ctx = ctx; + match_debug = match_debug; + dt_table = DtTable.create 7; + match_pos = p; + dt_count = 0; + } in + let subjects,vars = List.fold_left (fun (subjects,vars) e -> match e.eexpr with + | TConst _ | TLocal _ -> + (e :: subjects,vars) + | _ -> + let v = gen_local ctx e.etype e.epos in + let ev = mk (TLocal v) e.etype e.epos in + (ev :: subjects,(v,e.epos,e) :: vars) + ) ([],[]) subjects in + let dt = compile mctx subjects cases in + Useless.check mctx.ctx.com cases; + match vars with + | [] -> dt + | _ -> bind mctx vars dt +end + +module TexprConverter = struct + open Typecore + open Decision_tree + open Constructor + open Case + + type match_kind = + | SKValue + | SKEnum + | SKFakeEnum + | SKLength + + exception Not_exhaustive + + let s_subject s e = + let rec loop s e = match e.eexpr with + | TField(e1,fa) -> + loop (Printf.sprintf "{ %s: %s }" (field_name fa) s) e1 + | TEnumParameter(e1,ef,i) -> + let arity = match follow ef.ef_type with TFun(args,_) -> List.length args | _ -> assert false in + let l = make_offset_list i (arity - i - 1) s "_" in + loop (Printf.sprintf "%s(%s)" ef.ef_name (String.concat ", " l)) e1 + | _ -> + s + in + loop s e + + let s_match_kind = function + | SKValue -> "value" + | SKEnum -> "enum" + | SKFakeEnum -> "fakeEnum" + | SKLength -> "length" + + let unify_constructor ctx params t con = + match con with + | ConEnum(en,ef) -> + let t_ef = match follow ef.ef_type with TFun(_,t) -> t | _ -> ef.ef_type in + let t_ef = apply_params ctx.type_params params (monomorphs en.e_params (monomorphs ef.ef_params t_ef)) in + let monos = List.map (fun t -> match follow t with + | TInst({cl_kind = KTypeParameter _},_) -> mk_mono() + | _ -> t + ) params in + let rec duplicate_monos t = match follow t with + | TMono _ -> mk_mono() + | _ -> Type.map duplicate_monos t + in + let t_e = apply_params ctx.type_params monos (duplicate_monos t) in + begin try + Type.unify t_ef t_e; + Some(con,monos) + with Unify_error _ -> + None + end + | _ -> + Some(con,params) + + let all_ctors ctx e cases = + let infer_type() = match cases with + | [] -> e,e.etype,false + | (con,_,_) :: _ -> + let fail() = + (* error "Could not determine switch kind, make sure the type is known" e.epos; *) + t_dynamic + in + let t = match con with + | ConEnum(en,_) -> TEnum(en,List.map snd en.e_params) + | ConArray _ -> ctx.t.tarray t_dynamic + | ConConst ct -> + begin match ct with + | TString _ -> ctx.t.tstring + | TInt _ -> ctx.t.tint + | TFloat _ -> ctx.t.tfloat + | TBool _ -> ctx.t.tbool + | _ -> fail() + end + | ConStatic({cl_kind = KAbstractImpl a},_) -> (TAbstract(a,List.map snd a.a_params)) + | ConTypeExpr mt -> get_general_module_type ctx mt e.epos + | ConFields _ | ConStatic _ -> fail() + in + mk (TCast(e,None)) t e.epos,t,true + in + let e,t,inferred = match follow e.etype with + | TDynamic _ | TMono _ -> + infer_type() + | _ -> + e,e.etype,false + in + let h = ConTable.create 0 in + let add constructor = + ConTable.replace h constructor true + in + let rec loop t = match follow t with + | TAbstract({a_path = [],"Bool"},_) -> + add (ConConst(TBool true)); + add (ConConst(TBool false)); + SKValue,RunTimeFinite + | TAbstract({a_impl = Some c} as a,pl) when Meta.has Meta.Enum a.a_meta -> + List.iter (fun cf -> + ignore(follow cf.cf_type); + if Meta.has Meta.Impl cf.cf_meta && Meta.has Meta.Enum cf.cf_meta then match cf.cf_expr with + | Some {eexpr = TConst ct | TCast ({eexpr = TConst ct},None)} -> + if ct != TNull then add (ConConst ct) + | _ -> add (ConStatic(c,cf)) + ) c.cl_ordered_statics; + SKValue,CompileTimeFinite + | TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) -> + loop (Abstract.get_underlying_type a pl) + | TInst({cl_path=[],"String"},_) + | TInst({cl_kind = KTypeParameter _ },_) -> + SKValue,Infinite + | TInst({cl_path=[],"Array"},_) -> + SKLength,Infinite + | TEnum(en,pl) -> + PMap.iter (fun _ ef -> add (ConEnum(en,ef))) en.e_constrs; + if Meta.has Meta.FakeEnum en.e_meta then + SKFakeEnum,CompileTimeFinite + else + SKEnum,RunTimeFinite + | TAnon _ -> + SKValue,CompileTimeFinite + | TInst(_,_) -> + SKValue,CompileTimeFinite + | _ -> + SKValue,Infinite + in + let kind,finiteness = loop t in + let compatible_kind con = match con with + | ConEnum _ -> kind = SKEnum || kind = SKFakeEnum + | ConArray _ -> kind = SKLength + | _ -> kind = SKValue + in + List.iter (fun (con,unguarded,dt) -> + if not (compatible_kind con) then error "Incompatible pattern" dt.dt_pos; + if unguarded then ConTable.remove h con + ) cases; + let unmatched = ConTable.fold (fun con _ acc -> con :: acc) h [] in + e,unmatched,kind,finiteness + + let report_not_exhaustive e_subject unmatched = + let sl = match follow e_subject.etype with + | TAbstract({a_impl = Some c} as a,tl) when Meta.has Meta.Enum a.a_meta -> + List.map (fun (con,_) -> match con with + | ConConst ct1 -> + let cf = List.find (fun cf -> + match cf.cf_expr with + | Some ({eexpr = TConst ct2 | TCast({eexpr = TConst ct2},None)}) -> ct1 = ct2 + | _ -> false + ) c.cl_ordered_statics in + cf.cf_name + | _ -> + Constructor.to_string con + ) unmatched + | _ -> + List.map (fun (con,_) -> Constructor.to_string con) unmatched + in + let s = match unmatched with + | [] -> "_" + | _ -> String.concat " | " (List.sort Pervasives.compare sl) + in + error (Printf.sprintf "Unmatched patterns: %s" (s_subject s e_subject)) e_subject.epos + + let to_texpr ctx t_switch match_debug with_type dt = + let com = ctx.com in + let p = dt.dt_pos in + let c_type = match follow (Typeload.load_instance ctx ({ tpackage = ["std"]; tname="Type"; tparams=[]; tsub = None},null_pos) true p) with TInst(c,_) -> c | t -> assert false in + let mk_index_call e = + if not ctx.in_macro && not ctx.com.display.DisplayMode.dms_full_typing then + (* If we are in display mode there's a chance that these fields don't exist. Let's just use a + (correctly typed) neutral value because it doesn't actually matter. *) + mk (TConst (TInt (Int32.of_int 0))) ctx.t.tint e.epos + else + let cf = PMap.find "enumIndex" c_type.cl_statics in + make_static_call ctx c_type cf (fun t -> t) [e] com.basic.tint e.epos + in + let mk_name_call e = + if not ctx.in_macro && not ctx.com.display.DisplayMode.dms_full_typing then + mk (TConst (TString "")) ctx.t.tstring e.epos + else + let cf = PMap.find "enumConstructor" c_type.cl_statics in + make_static_call ctx c_type cf (fun t -> t) [e] com.basic.tstring e.epos + in + let rec loop toplevel params dt = match dt.dt_t with + | Leaf case -> + begin match case.case_expr with + | Some e -> e + | None -> mk (TBlock []) ctx.t.tvoid case.case_pos + end + | Switch(_,[ConFields _,_,dt],_) -> (* TODO: Can we improve this by making it more general? *) + loop false params dt + | Switch(e_subject,cases,default) -> + let e_subject,unmatched,kind,finiteness = all_ctors ctx e_subject cases in + let unmatched = ExtList.List.filter_map (unify_constructor ctx params e_subject.etype) unmatched in + let loop toplevel params dt = + try Some (loop toplevel params dt) + with Not_exhaustive -> match with_type,finiteness with + | NoValue,Infinite -> None + | _,CompileTimeFinite when unmatched = [] -> None + | _ when ctx.com.display.DisplayMode.dms_error_policy = DisplayMode.EPIgnore -> None + | _ -> report_not_exhaustive e_subject unmatched + in + let cases = ExtList.List.filter_map (fun (con,_,dt) -> match unify_constructor ctx params e_subject.etype con with + | Some(_,params) -> Some (con,dt,params) + | None -> None + ) cases in + let group cases = + let h = DtTable.create 0 in + List.iter (fun (con,dt,params) -> + let l,_,_ = try DtTable.find h dt.dt_t with Not_found -> [],dt,params in + DtTable.replace h dt.dt_t (con :: l,dt,params) + ) cases; + DtTable.fold (fun _ (cons,dt,params) acc -> (cons,dt,params) :: acc) h [] + in + let cases = group cases in + let cases = List.sort (fun (cons1,_,_) (cons2,_,_) -> match cons1,cons2 with + | (con1 :: _),con2 :: _ -> Constructor.compare con1 con2 + | _ -> -1 + ) cases in + let e_default = match unmatched,finiteness with + | [],RunTimeFinite -> + None + | _ -> + loop false params default + in + let cases = ExtList.List.filter_map (fun (cons,dt,params) -> + let eo = loop false params dt in + begin match eo with + | None -> None + | Some e -> Some (List.map (Constructor.to_texpr ctx match_debug dt.dt_pos) (List.sort Constructor.compare cons),e) + end + ) cases in + let e_subject = match kind with + | SKValue | SKFakeEnum -> e_subject + | SKEnum -> if match_debug then mk_name_call e_subject else mk_index_call e_subject + | SKLength -> type_field_access ctx e_subject "length" + in + begin match cases with + | [_,e2] when e_default = None && (match finiteness with RunTimeFinite -> true | _ -> false) -> + e2 + | [[e1],e2] when (with_type = NoValue || e_default <> None) && ctx.com.platform <> Java (* TODO: problem with TestJava.hx:285 *) -> + let e_op = mk (TBinop(OpEq,e_subject,e1)) ctx.t.tbool e_subject.epos in + mk (TIf(e_op,e2,e_default)) t_switch dt.dt_pos + | _ -> + let e_subject = match finiteness with + | RunTimeFinite | CompileTimeFinite when e_default = None -> + let meta = (Meta.Exhaustive,[],dt.dt_pos) in + mk (TMeta(meta,e_subject)) e_subject.etype e_subject.epos + | _ -> + e_subject + in + mk (TSwitch(e_subject,cases,e_default)) t_switch dt.dt_pos + end + | Guard(e,dt1,dt2) -> + let e_then = loop false params dt1 in + begin try + let e_else = loop false params dt2 in + mk (TIf(e,e_then,Some e_else)) t_switch (punion e_then.epos e_else.epos) + with Not_exhaustive when with_type = NoValue -> + mk (TIf(e,e_then,None)) ctx.t.tvoid (punion e.epos e_then.epos) + end + | GuardNull(e,dt1,dt2) -> + let e_null = Codegen.ExprBuilder.make_null e.etype e.epos in + let f = try + let e_then = loop false params dt1 in + (fun () -> + let e_else = loop false params dt2 in + let e_op = mk (TBinop(OpEq,e,e_null)) ctx.t.tbool e.epos in + mk (TIf(e_op,e_then,Some e_else)) t_switch (punion e_then.epos e_else.epos) + ) + with Not_exhaustive -> + if toplevel then (fun () -> loop false params dt2) + else if ctx.com.display.DisplayMode.dms_error_policy = DisplayMode.EPIgnore then (fun () -> mk (TConst TNull) (mk_mono()) dt2.dt_pos) + else report_not_exhaustive e [ConConst TNull,dt.dt_pos] + in + f() + | Bind(bl,dt) -> + let el = List.rev_map (fun (v,p,e) -> + mk (TVar(v,Some e)) com.basic.tvoid p + ) bl in + let e = loop toplevel params dt in + mk (TBlock (el @ [e])) e.etype dt.dt_pos + | Fail -> + raise Not_exhaustive + in + let params = List.map snd ctx.type_params in + let e = loop true params dt in + Texpr.duplicate_tvars e +end + +module Match = struct + open Typecore + + let match_expr ctx e cases def with_type p = + let match_debug = Meta.has (Meta.Custom ":matchDebug") ctx.curfield.cf_meta in + let rec loop e = match fst e with + | EArrayDecl el when (match el with [(EFor _ | EWhile _),_] -> false | _ -> true) -> + let el = List.map (fun e -> type_expr ctx e Value) el in + let t = tuple_type (List.map (fun e -> e.etype) el) in + t,el + | EParenthesis e1 -> + loop e1 + | _ -> + let e = type_expr ctx e Value in + e.etype,[e] + in + let t,subjects = loop e in + let subjects = List.rev subjects in + let cases = match def with + | None -> cases + | Some (eo,p) -> cases @ [[EConst (Ident "_"),p],None,eo,p] + in + let tmono,with_type = match with_type with + | WithType t -> (match follow t with TMono _ -> Some t,Value | _ -> None,with_type) + | _ -> None,with_type + in + let cases = List.map (fun (el,eg,eo,p) -> + let case,bindings,pat = Case.make ctx t el eg eo with_type p in + case,bindings,[pat] + ) cases in + let infer_switch_type () = + match with_type with + | NoValue -> mk_mono() + | Value -> + let el = List.map (fun (case,_,_) -> match case.Case.case_expr with Some e -> e | None -> mk (TBlock []) ctx.t.tvoid p) cases in + unify_min ctx el + | WithType t -> t + in + if match_debug then begin + print_endline "CASES BEGIN"; + List.iter (fun (case,_,patterns) -> + print_endline (String.concat "" (List.map (Pattern.to_string) patterns)); + ) cases; + print_endline "CASES END"; + end; + let dt = Compile.compile ctx match_debug subjects cases p in + if match_debug then begin + print_endline "DECISION TREE BEGIN"; + print_endline (Decision_tree.to_string "" dt); + print_endline "DECISION TREE END"; + end; + let e = try + let t_switch = infer_switch_type() in + (match tmono with Some t -> unify ctx t_switch t p | _ -> ()); + TexprConverter.to_texpr ctx t_switch match_debug with_type dt + with TexprConverter.Not_exhaustive -> + error "Unmatched patterns: _" p; + in + if match_debug then begin + print_endline "TEXPR BEGIN"; + print_endline (s_expr_pretty e); + print_endline "TEXPR END"; + end; + {e with epos = p} +end +;; +Typecore.match_expr_ref := Match.match_expr \ No newline at end of file diff --git a/src/typing/overloads.ml b/src/typing/overloads.ml new file mode 100644 index 00000000..4cc8d5ca --- /dev/null +++ b/src/typing/overloads.ml @@ -0,0 +1,261 @@ +open Type + +let same_overload_args ?(get_vmtype) t1 t2 f1 f2 = + let get_vmtype = match get_vmtype with + | None -> (fun f -> f) + | Some f -> f + in + if List.length f1.cf_params <> List.length f2.cf_params then + false + else + let rec follow_skip_null t = match t with + | TMono r -> + (match !r with + | Some t -> follow_skip_null t + | _ -> t) + | TLazy f -> + follow_skip_null (!f()) + | TType ({ t_path = [],"Null" } as t, [p]) -> + TType(t,[follow p]) + | TType (t,tl) -> + follow_skip_null (apply_params t.t_params tl t.t_type) + | _ -> t + in + let same_arg t1 t2 = + let t1 = get_vmtype (follow_skip_null t1) in + let t2 = get_vmtype (follow_skip_null t2) in + match t1, t2 with + | TType _, TType _ -> type_iseq t1 t2 + | TType _, _ + | _, TType _ -> false + | _ -> type_iseq t1 t2 + in + + match follow (apply_params f1.cf_params (List.map (fun (_,t) -> t) f2.cf_params) t1), follow t2 with + | TFun(a1,_), TFun(a2,_) -> + (try + List.for_all2 (fun (_,_,t1) (_,_,t2) -> + same_arg t1 t2) a1 a2 + with | Invalid_argument("List.for_all2") -> + false) + | _ -> assert false + + +(** retrieves all overloads from class c and field i, as (Type.t * tclass_field) list *) +let rec get_overloads c i = + let ret = try + let f = PMap.find i c.cl_fields in + match f.cf_kind with + | Var _ -> + (* @:libType may generate classes that have a variable field in a superclass of an overloaded method *) + [] + | Method _ -> + (f.cf_type, f) :: (List.map (fun f -> f.cf_type, f) f.cf_overloads) + with | Not_found -> [] + in + let rsup = match c.cl_super with + | None when c.cl_interface -> + let ifaces = List.concat (List.map (fun (c,tl) -> + List.map (fun (t,f) -> apply_params c.cl_params tl t, f) (get_overloads c i) + ) c.cl_implements) in + ret @ ifaces + | None -> ret + | Some (c,tl) -> + ret @ ( List.map (fun (t,f) -> apply_params c.cl_params tl t, f) (get_overloads c i) ) + in + ret @ (List.filter (fun (t,f) -> not (List.exists (fun (t2,f2) -> same_overload_args t t2 f f2) ret)) rsup) + +(** Overload resolution **) +module Resolution = +struct + let rec simplify_t t = match t with + | TAbstract(a,_) when Meta.has Meta.CoreType a.a_meta -> + t + | TInst _ | TEnum _ -> + t + | TAbstract(a,tl) -> simplify_t (Abstract.get_underlying_type a tl) + | TType(({ t_path = [],"Null" } as t), [t2]) -> (match simplify_t t2 with + | (TAbstract(a,_) as t2) when Meta.has Meta.CoreType a.a_meta -> + TType(t, [simplify_t t2]) + | (TEnum _ as t2) -> + TType(t, [simplify_t t2]) + | t2 -> t2) + | TType(t, tl) -> + simplify_t (apply_params t.t_params tl t.t_type) + | TMono r -> (match !r with + | Some t -> simplify_t t + | None -> t_dynamic) + | TAnon _ -> t_dynamic + | TDynamic _ -> t + | TLazy f -> simplify_t (!f()) + | TFun _ -> t + + (* rate type parameters *) + let rate_tp tlfun tlarg = + let acc = ref 0 in + List.iter2 (fun f a -> if not (type_iseq f a) then incr acc) tlfun tlarg; + !acc + + (** + The rate function returns an ( int * int ) type. + The smaller the int, the best rated the caller argument is in comparison with the callee. + + The first int refers to how many "conversions" would be necessary to convert from the callee to the caller type, and + the second refers to the type parameters. + **) + let rec rate_conv cacc tfun targ = + match simplify_t tfun, simplify_t targ with + | TInst({ cl_interface = true } as cf, tlf), TInst(ca, tla) -> + (* breadth-first *) + let stack = ref [0,ca,tla] in + let cur = ref (0, ca,tla) in + let rec loop () = + match !stack with + | [] -> (let acc, ca, tla = !cur in match ca.cl_super with + | None -> raise Not_found + | Some (sup,tls) -> + cur := (acc+1,sup,List.map (apply_params ca.cl_params tla) tls); + stack := [!cur]; + loop()) + | (acc,ca,tla) :: _ when ca == cf -> + acc,tla + | (acc,ca,tla) :: s -> + stack := s @ List.map (fun (c,tl) -> (acc+1,c,List.map (apply_params ca.cl_params tla) tl)) ca.cl_implements; + loop() + in + let acc, tla = loop() in + (cacc + acc, rate_tp tlf tla) + | TInst(cf,tlf), TInst(ca,tla) -> + let rec loop acc ca tla = + if cf == ca then + acc, tla + else match ca.cl_super with + | None -> raise Not_found + | Some(sup,stl) -> + loop (acc+1) sup (List.map (apply_params ca.cl_params tla) stl) + in + let acc, tla = loop 0 ca tla in + (cacc + acc, rate_tp tlf tla) + | TEnum(ef,tlf), TEnum(ea, tla) -> + if ef != ea then raise Not_found; + (cacc, rate_tp tlf tla) + | TDynamic _, TDynamic _ -> + (cacc, 0) + | TDynamic _, _ -> + (max_int, 0) (* a function with dynamic will always be worst of all *) + | TAbstract(a, _), TDynamic _ when Meta.has Meta.CoreType a.a_meta -> + (cacc + 2, 0) (* a dynamic to a basic type will have an "unboxing" penalty *) + | _, TDynamic _ -> + (cacc + 1, 0) + | TAbstract(af,tlf), TAbstract(aa,tla) -> + (if af == aa then + (cacc, rate_tp tlf tla) + else + let ret = ref None in + if List.exists (fun t -> try + ret := Some (rate_conv (cacc+1) (apply_params af.a_params tlf t) targ); + true + with | Not_found -> + false + ) af.a_from then + Option.get !ret + else + if List.exists (fun t -> try + ret := Some (rate_conv (cacc+1) tfun (apply_params aa.a_params tla t)); + true + with | Not_found -> + false + ) aa.a_to then + Option.get !ret + else + raise Not_found) + | TType({ t_path = [], "Null" }, [tf]), TType({ t_path = [], "Null" }, [ta]) -> + rate_conv (cacc+0) tf ta + | TType({ t_path = [], "Null" }, [tf]), ta -> + rate_conv (cacc+1) tf ta + | tf, TType({ t_path = [], "Null" }, [ta]) -> + rate_conv (cacc+1) tf ta + | TFun _, TFun _ -> (* unify will make sure they are compatible *) + cacc,0 + | tfun,targ -> + raise Not_found + + let is_best arg1 arg2 = + (List.for_all2 (fun v1 v2 -> + v1 <= v2) + arg1 arg2) && (List.exists2 (fun v1 v2 -> + v1 < v2) + arg1 arg2) + + let rec rm_duplicates acc ret = match ret with + | [] -> acc + | ( el, t, _ ) :: ret when List.exists (fun (_,t2,_) -> type_iseq t t2) acc -> + rm_duplicates acc ret + | r :: ret -> + rm_duplicates (r :: acc) ret + + let s_options rated = + String.concat ",\n" (List.map (fun ((elist,t,_),rate) -> + "( " ^ (String.concat "," (List.map (fun(e,_) -> s_expr (s_type (print_context())) e) elist)) ^ " ) => " ^ + "( " ^ (String.concat "," (List.map (fun (i,i2) -> string_of_int i ^ ":" ^ string_of_int i2) rate)) ^ " ) => " ^ (s_type (print_context()) t) + ) rated) + + let count_optionals elist = + List.fold_left (fun acc (_,is_optional) -> if is_optional then acc + 1 else acc) 0 elist + + let rec fewer_optionals acc compatible = match acc, compatible with + | _, [] -> acc + | [], c :: comp -> fewer_optionals [c] comp + | (elist_acc, _, _) :: _, ((elist, _, _) as cur) :: comp -> + let acc_opt = count_optionals elist_acc in + let comp_opt = count_optionals elist in + if acc_opt = comp_opt then + fewer_optionals (cur :: acc) comp + else if acc_opt < comp_opt then + fewer_optionals acc comp + else + fewer_optionals [cur] comp + + let reduce_compatible compatible = match fewer_optionals [] (rm_duplicates [] compatible) with + | [] -> [] + | [v] -> [v] + | compatible -> + (* convert compatible into ( rate * compatible_type ) list *) + let rec mk_rate acc elist args = match elist, args with + | [], [] -> acc + | (_,true) :: elist, _ :: args -> mk_rate acc elist args + | (e,false) :: elist, (n,o,t) :: args -> + (* if the argument is an implicit cast, we need to start with a penalty *) + (* The penalty should be higher than any other implicit cast - other than Dynamic *) + (* since Dynamic has a penalty of max_int, we'll impose max_int - 1 to it *) + (match e.eexpr with + | TMeta( (Meta.ImplicitCast,_,_), _) -> + mk_rate ((max_int - 1, 0) :: acc) elist args + | _ -> + mk_rate (rate_conv 0 t e.etype :: acc) elist args) + | _ -> assert false + in + + let rated = ref [] in + List.iter (function + | (elist,TFun(args,ret),d) -> (try + rated := ( (elist,TFun(args,ret),d), mk_rate [] elist args ) :: !rated + with | Not_found -> ()) + | _ -> assert false + ) compatible; + + let rec loop best rem = match best, rem with + | _, [] -> best + | [], r1 :: rem -> loop [r1] rem + | (bover, bargs) :: b1, (rover, rargs) :: rem -> + if is_best bargs rargs then + loop best rem + else if is_best rargs bargs then + loop (loop b1 [rover,rargs]) rem + else (* equally specific *) + loop ( (rover,rargs) :: best ) rem + in + + let r = loop [] !rated in + List.map fst r +end \ No newline at end of file diff --git a/type.ml b/src/typing/type.ml similarity index 65% rename from type.ml rename to src/typing/type.ml index 541c9768..b1c17609 100644 --- a/type.ml +++ b/src/typing/type.ml @@ -1,26 +1,24 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Ast +open Globals type path = string list * string @@ -48,6 +46,12 @@ and method_kind = | MethDynamic | MethMacro +type module_check_policy = + | NoCheckFileTimeModification + | CheckFileContentModification + | NoCheckDependencies + | NoCheckShadowing + type t = | TMono of t option ref | TEnum of tenum * tparams @@ -72,13 +76,16 @@ and tconstant = | TThis | TSuper +and tvar_extra = (type_params * texpr option) option + and tvar = { mutable v_id : int; mutable v_name : string; mutable v_type : t; mutable v_capture : bool; - mutable v_extra : (type_params * texpr option) option; + mutable v_extra : tvar_extra; mutable v_meta : metadata; + v_pos : pos; } and tfunc = { @@ -141,7 +148,7 @@ and tfield_access = and texpr = { eexpr : texpr_expr; etype : t; - epos : Ast.pos; + epos : pos; } and tclass_field = { @@ -149,18 +156,19 @@ and tclass_field = { mutable cf_type : t; mutable cf_public : bool; cf_pos : pos; + cf_name_pos : pos; mutable cf_doc : Ast.documentation; mutable cf_meta : metadata; mutable cf_kind : field_kind; mutable cf_params : type_params; mutable cf_expr : texpr option; + mutable cf_expr_unoptimized : tfunc option; mutable cf_overloads : tclass_field list; } and tclass_kind = | KNormal | KTypeParameter of t list - | KExtension of tclass * tparams | KExpr of Ast.expr | KGeneric | KGenericInstance of tclass * tparams @@ -173,7 +181,8 @@ and metadata = Ast.metadata and tinfos = { mt_path : path; mt_module : module_def; - mt_pos : Ast.pos; + mt_pos : pos; + mt_name_pos : pos; mt_private : bool; mt_doc : Ast.documentation; mutable mt_meta : metadata; @@ -183,7 +192,8 @@ and tinfos = { and tclass = { mutable cl_path : path; mutable cl_module : module_def; - mutable cl_pos : Ast.pos; + mutable cl_pos : pos; + mutable cl_name_pos : pos; mutable cl_private : bool; mutable cl_doc : Ast.documentation; mutable cl_meta : metadata; @@ -204,14 +214,15 @@ and tclass = { mutable cl_init : texpr option; mutable cl_overrides : tclass_field list; - mutable cl_build : unit -> bool; + mutable cl_build : unit -> build_state; mutable cl_restore : unit -> unit; } and tenum_field = { ef_name : string; ef_type : t; - ef_pos : Ast.pos; + ef_pos : pos; + ef_name_pos : pos; ef_doc : Ast.documentation; ef_index : int; ef_params : type_params; @@ -221,7 +232,8 @@ and tenum_field = { and tenum = { mutable e_path : path; e_module : module_def; - e_pos : Ast.pos; + e_pos : pos; + e_name_pos : pos; e_private : bool; e_doc : Ast.documentation; mutable e_meta : metadata; @@ -236,7 +248,8 @@ and tenum = { and tdef = { t_path : path; t_module : module_def; - t_pos : Ast.pos; + t_pos : pos; + t_name_pos : pos; t_private : bool; t_doc : Ast.documentation; mutable t_meta : metadata; @@ -248,7 +261,8 @@ and tdef = { and tabstract = { mutable a_path : path; a_module : module_def; - a_pos : Ast.pos; + a_pos : pos; + a_name_pos : pos; a_private : bool; a_doc : Ast.documentation; mutable a_meta : metadata; @@ -263,6 +277,7 @@ and tabstract = { mutable a_to : t list; mutable a_to_field : (t * tclass_field) list; mutable a_array : tclass_field list; + mutable a_resolve : tclass_field option; } and module_type = @@ -281,8 +296,9 @@ and module_def = { and module_def_extra = { m_file : string; m_sign : string; + mutable m_check_policy : module_check_policy list; mutable m_time : float; - mutable m_dirty : bool; + mutable m_dirty : module_def option; mutable m_added : int; mutable m_mark : int; mutable m_deps : (int,module_def) PMap.t; @@ -300,30 +316,21 @@ and module_kind = | MFake | MSub | MExtern + | MImport -and dt = - | DTSwitch of texpr * (texpr * dt) list * dt option - | DTBind of ((tvar * pos) * texpr) list * dt - | DTGoto of int - | DTExpr of texpr - | DTGuard of texpr * dt * dt option - -and decision_tree = { - dt_dt_lookup : dt array; - dt_first : int; - dt_type : t; - dt_var_init : (tvar * texpr option) list; - dt_is_complex : bool; -} +and build_state = + | Built + | Building + | BuildMacro of (unit -> unit) list ref (* ======= General utility ======= *) let alloc_var = let uid = ref 0 in - (fun n t -> incr uid; { v_name = n; v_type = t; v_id = !uid; v_capture = false; v_extra = None; v_meta = [] }) + (fun n t p -> incr uid; { v_name = n; v_type = t; v_id = !uid; v_capture = false; v_extra = None; v_meta = []; v_pos = p }) -let alloc_unbound_var n t = - let v = alloc_var n t in +let alloc_unbound_var n t p = + let v = alloc_var n t p in v.v_meta <- [Meta.Unbound,[],null_pos]; v @@ -338,6 +345,9 @@ let mk_block e = | TBlock _ -> e | _ -> mk (TBlock [e]) e.etype e.epos +let is_unbound v = + Meta.has Meta.Unbound v.v_meta + let mk_cast e t p = mk (TCast(e,None)) t p let null t p = mk (TConst TNull) t p @@ -346,15 +356,25 @@ let mk_mono() = TMono (ref None) let rec t_dynamic = TDynamic t_dynamic +let not_opened = ref Closed +let mk_anon fl = TAnon { a_fields = fl; a_status = not_opened; } + +(* We use this for display purposes because otherwise we never see the Dynamic type that + is defined in StdTypes.hx. This is set each time a typer is created, but this is fine + because Dynamic is the same in all contexts. If this ever changes we'll have to review + how we handle this. *) +let t_dynamic_def = ref t_dynamic + let tfun pl r = TFun (List.map (fun t -> "",false,t) pl,r) let fun_args l = List.map (fun (a,c,t) -> a, c <> None, t) l -let mk_class m path pos = +let mk_class m path pos name_pos = { cl_path = path; cl_module = m; cl_pos = pos; + cl_name_pos = name_pos; cl_doc = None; cl_meta = []; cl_private = false; @@ -373,15 +393,15 @@ let mk_class m path pos = cl_constructor = None; cl_init = None; cl_overrides = []; - cl_build = (fun() -> true); + cl_build = (fun() -> Built); cl_restore = (fun() -> ()); } -let module_extra file sign time kind = +let module_extra file sign time kind policy = { m_file = file; m_sign = sign; - m_dirty = false; + m_dirty = None; m_added = 0; m_mark = 0; m_time = time; @@ -392,18 +412,21 @@ let module_extra file sign time kind = m_macro_calls = []; m_if_feature = []; m_features = Hashtbl.create 0; + m_check_policy = policy; } -let mk_field name t p = { +let mk_field name t p name_pos = { cf_name = name; cf_type = t; cf_pos = p; + cf_name_pos = name_pos; cf_doc = None; cf_meta = []; cf_public = true; cf_kind = Var { v_read = AccNormal; v_write = AccNormal }; cf_expr = None; + cf_expr_unoptimized = None; cf_params = []; cf_overloads = []; } @@ -412,20 +435,21 @@ let null_module = { m_id = alloc_mid(); m_path = [] , ""; m_types = []; - m_extra = module_extra "" "" 0. MFake; + m_extra = module_extra "" "" 0. MFake []; } let null_class = - let c = mk_class null_module ([],"") Ast.null_pos in + let c = mk_class null_module ([],"") null_pos null_pos in c.cl_private <- true; c -let null_field = mk_field "" t_dynamic Ast.null_pos +let null_field = mk_field "" t_dynamic null_pos null_pos let null_abstract = { a_path = ([],""); a_module = null_module; a_pos = null_pos; + a_name_pos = null_pos; a_private = true; a_doc = None; a_meta = []; @@ -439,6 +463,7 @@ let null_abstract = { a_to = []; a_to_field = []; a_array = []; + a_resolve = None; } let add_dependency m mdep = @@ -487,7 +512,7 @@ let map loop t = a.a_fields <- fields; t | _ -> - TAnon { + TAnon { a_fields = fields; a_status = a.a_status; } @@ -499,6 +524,22 @@ let map loop t = | TDynamic t2 -> if t == t2 then t else TDynamic (loop t2) +let dup t = + let monos = ref [] in + let rec loop t = + match t with + | TMono { contents = None } -> + (try + List.assq t !monos + with Not_found -> + let m = mk_mono() in + monos := (t,m) :: !monos; + m) + | _ -> + map loop t + in + loop t + (* substitute parameters with other types *) let apply_params cparams params t = match cparams with @@ -557,7 +598,7 @@ let apply_params cparams params t = a.a_fields <- fields; t | _ -> - TAnon { + TAnon { a_fields = fields; a_status = a.a_status; } @@ -675,6 +716,37 @@ let type_of_module_type = function | TTypeDecl t -> TType (t,List.map snd t.t_params) | TAbstractDecl a -> TAbstract (a,List.map snd a.a_params) +let rec module_type_of_type = function + | TInst(c,_) -> TClassDecl c + | TEnum(en,_) -> TEnumDecl en + | TType(t,_) -> TTypeDecl t + | TAbstract(a,_) -> TAbstractDecl a + | TLazy f -> module_type_of_type (!f()) + | TMono r -> + (match !r with + | Some t -> module_type_of_type t + | _ -> raise Exit) + | _ -> + raise Exit + +let tconst_to_const = function + | TInt i -> Int (Int32.to_string i) + | TFloat s -> Float s + | TString s -> String s + | TBool b -> Ident (if b then "true" else "false") + | TNull -> Ident "null" + | TThis -> Ident "this" + | TSuper -> Ident "super" + +let has_ctor_constraint c = match c.cl_kind with + | KTypeParameter tl -> + List.exists (fun t -> match follow t with + | TAnon a when PMap.mem "new" a.a_fields -> true + | TAbstract({a_path=["haxe"],"Constructible"},_) -> true + | _ -> false + ) tl; + | _ -> false + (* ======= Field utility ======= *) let field_name f = @@ -819,6 +891,12 @@ let rec s_type_kind t = | TDynamic t2 -> "TDynamic" | TLazy _ -> "TLazy" +let s_module_type_kind = function + | TClassDecl c -> "TClassDecl(" ^ (s_type_path c.cl_path) ^ ")" + | TEnumDecl en -> "TEnumDecl(" ^ (s_type_path en.e_path) ^ ")" + | TAbstractDecl a -> "TAbstractDecl(" ^ (s_type_path a.a_path) ^ ")" + | TTypeDecl t -> "TTypeDecl(" ^ (s_type_path t.t_path) ^ ")" + let rec s_type ctx t = match t with | TMono r -> @@ -826,15 +904,15 @@ let rec s_type ctx t = | None -> Printf.sprintf "Unknown<%d>" (try List.assq t (!ctx) with Not_found -> let n = List.length !ctx in ctx := (t,n) :: !ctx; n) | Some t -> s_type ctx t) | TEnum (e,tl) -> - Ast.s_type_path e.e_path ^ s_type_params ctx tl + s_type_path e.e_path ^ s_type_params ctx tl | TInst (c,tl) -> (match c.cl_kind with | KExpr e -> Ast.s_expr e - | _ -> Ast.s_type_path c.cl_path ^ s_type_params ctx tl) + | _ -> s_type_path c.cl_path ^ s_type_params ctx tl) | TType (t,tl) -> - Ast.s_type_path t.t_path ^ s_type_params ctx tl + s_type_path t.t_path ^ s_type_params ctx tl | TAbstract (a,tl) -> - Ast.s_type_path a.a_path ^ s_type_params ctx tl + s_type_path a.a_path ^ s_type_params ctx tl | TFun ([],t) -> "Void -> " ^ s_fun ctx t false | TFun (l,t) -> @@ -1004,67 +1082,55 @@ let rec s_expr s_type e = ) in sprintf "(%s : %s)" str (s_type e.etype) -and s_dt tabs tree = - let s_type = s_type (print_context()) in - tabs ^ match tree with - | DTSwitch (st,cl,dto) -> - "switch(" ^ (s_expr s_type st) ^ ") { \n" ^ tabs - ^ (String.concat ("\n" ^ tabs) (List.map (fun (c,dt) -> - "case " ^ (s_expr s_type c) ^ ":\n" ^ (s_dt (tabs ^ "\t") dt) - ) cl)) - ^ (match dto with None -> "" | Some dt -> tabs ^ "default: " ^ (s_dt (tabs ^ "\t") dt)) - ^ "\n" ^ (if String.length tabs = 0 then "" else (String.sub tabs 0 (String.length tabs - 1))) ^ "}" - | DTBind (bl, dt) -> "bind " ^ (String.concat "," (List.map (fun ((v,_),st) -> v.v_name ^ "(" ^ (string_of_int v.v_id) ^ ") =" ^ (s_expr s_type st)) bl)) ^ "\n" ^ (s_dt tabs dt) - | DTGoto i -> - "goto " ^ (string_of_int i) - | DTExpr e -> s_expr s_type e - | DTGuard (e,dt1,dt2) -> "if(" ^ (s_expr s_type e) ^ ") " ^ (s_dt tabs dt1) ^ (match dt2 with None -> "" | Some dt -> " else " ^ (s_dt tabs dt)) - -let rec s_expr_pretty tabs s_type e = +let rec s_expr_pretty print_var_ids tabs top_level s_type e = let sprintf = Printf.sprintf in - let loop = s_expr_pretty tabs s_type in - let slist f l = String.concat "," (List.map f l) in + let loop = s_expr_pretty print_var_ids tabs false s_type in + let slist c f l = String.concat c (List.map f l) in + let clist f l = slist ", " f l in + let local v = if print_var_ids then sprintf "%s<%i>" v.v_name v.v_id else v.v_name in match e.eexpr with | TConst c -> s_const c - | TLocal v -> v.v_name + | TLocal v -> local v | TArray (e1,e2) -> sprintf "%s[%s]" (loop e1) (loop e2) | TBinop (op,e1,e2) -> sprintf "%s %s %s" (loop e1) (s_binop op) (loop e2) | TEnumParameter (e1,_,i) -> sprintf "%s[%i]" (loop e1) i | TField (e1,s) -> sprintf "%s.%s" (loop e1) (field_name s) | TTypeExpr mt -> (s_type_path (t_path mt)) | TParenthesis e1 -> sprintf "(%s)" (loop e1) - | TObjectDecl fl -> sprintf "{%s}" (slist (fun (f,e) -> sprintf "%s : %s" f (loop e)) fl) - | TArrayDecl el -> sprintf "[%s]" (slist loop el) - | TCall (e1,el) -> sprintf "%s(%s)" (loop e1) (slist loop el) + | TObjectDecl fl -> sprintf "{%s}" (clist (fun (f,e) -> sprintf "%s : %s" f (loop e)) fl) + | TArrayDecl el -> sprintf "[%s]" (clist loop el) + | TCall (e1,el) -> sprintf "%s(%s)" (loop e1) (clist loop el) | TNew (c,pl,el) -> - sprintf "new %s(%s)" (s_type_path c.cl_path) (slist loop el) + sprintf "new %s(%s)" (s_type_path c.cl_path) (clist loop el) | TUnop (op,f,e) -> (match f with | Prefix -> sprintf "%s %s" (s_unop op) (loop e) | Postfix -> sprintf "%s %s" (loop e) (s_unop op)) | TFunction f -> - let args = slist (fun (v,o) -> sprintf "%s:%s%s" v.v_name (s_type v.v_type) (match o with None -> "" | Some c -> " = " ^ s_const c)) f.tf_args in - sprintf "function(%s) = %s" args (loop f.tf_expr) + let args = clist (fun (v,o) -> sprintf "%s:%s%s" (local v) (s_type v.v_type) (match o with None -> "" | Some c -> " = " ^ s_const c)) f.tf_args in + sprintf "%s(%s) %s" (if top_level then "" else "function") args (loop f.tf_expr) | TVar (v,eo) -> - sprintf "var %s" (sprintf "%s%s" v.v_name (match eo with None -> "" | Some e -> " = " ^ loop e)) + sprintf "var %s" (sprintf "%s%s" (local v) (match eo with None -> "" | Some e -> " = " ^ loop e)) | TBlock el -> let ntabs = tabs ^ "\t" in - let s = sprintf "{\n%s" (String.concat "" (List.map (fun e -> sprintf "%s%s;\n" ntabs (s_expr_pretty ntabs s_type e)) el)) in - s ^ tabs ^ "}" + let s = sprintf "{\n%s" (String.concat "" (List.map (fun e -> sprintf "%s%s;\n" ntabs (s_expr_pretty print_var_ids ntabs top_level s_type e)) el)) in + (match el with + | [] -> "{}" + | _ -> s ^ tabs ^ "}") | TFor (v,econd,e) -> - sprintf "for (%s in %s) %s" v.v_name (loop econd) (loop e) + sprintf "for (%s in %s) %s" (local v) (loop econd) (loop e) | TIf (e,e1,e2) -> - sprintf "if (%s)%s%s" (loop e) (loop e1) (match e2 with None -> "" | Some e -> " else " ^ loop e) + sprintf "if (%s) %s%s" (loop e) (loop e1) (match e2 with None -> "" | Some e -> " else " ^ loop e) | TWhile (econd,e,flag) -> (match flag with | NormalWhile -> sprintf "while (%s) %s" (loop econd) (loop e) | DoWhile -> sprintf "do (%s) while(%s)" (loop e) (loop econd)) | TSwitch (e,cases,def) -> let ntabs = tabs ^ "\t" in - let s = sprintf "switch (%s) {\n%s%s" (loop e) (slist (fun (cl,e) -> sprintf "%scase %s: %s\n" ntabs (slist loop cl) (s_expr_pretty ntabs s_type e)) cases) (match def with None -> "" | Some e -> ntabs ^ "default: " ^ (s_expr_pretty ntabs s_type e) ^ "\n") in + let s = sprintf "switch (%s) {\n%s%s" (loop e) (slist "" (fun (cl,e) -> sprintf "%scase %s: %s;\n" ntabs (clist loop cl) (s_expr_pretty print_var_ids ntabs top_level s_type e)) cases) (match def with None -> "" | Some e -> ntabs ^ "default: " ^ (s_expr_pretty print_var_ids ntabs top_level s_type e) ^ "\n") in s ^ tabs ^ "}" | TTry (e,cl) -> - sprintf "try %s%s" (loop e) (slist (fun (v,e) -> sprintf "catch( %s : %s ) %s" v.v_name (s_type v.v_type) (loop e)) cl) + sprintf "try %s%s" (loop e) (clist (fun (v,e) -> sprintf " catch (%s:%s) %s" (local v) (s_type v.v_type) (loop e)) cl) | TReturn None -> "return" | TReturn (Some e) -> @@ -1100,12 +1166,12 @@ let rec s_expr_ast print_var_ids tabs s_type e = sprintf "[%s:%s]%s" s st (tag_args (tabs ^ extra_tabs) sl) in let var_id v = if print_var_ids then v.v_id else 0 in - let const c = sprintf "[Const %s:%s]" (s_const c) (s_type e.etype) in + let const c t = tag "Const" ~t [s_const c] in let local v = sprintf "[Local %s(%i):%s]" v.v_name (var_id v) (s_type v.v_type) in let var v sl = sprintf "[Var %s(%i):%s]%s" v.v_name (var_id v) (s_type v.v_type) (tag_args tabs sl) in let module_type mt = sprintf "[TypeExpr %s:%s]" (s_type_path (t_path mt)) (s_type e.etype) in match e.eexpr with - | TConst c -> const c + | TConst c -> const c (Some e.etype) | TLocal v -> local v | TArray (e1,e2) -> tag "Array" [loop e1; loop e2] | TBinop (op,e1,e2) -> tag "Binop" [loop e1; s_binop op; loop e2] @@ -1129,7 +1195,7 @@ let rec s_expr_ast print_var_ids tabs s_type e = | TNew (c,tl,el) -> tag "New" ((s_type (TInst(c,tl))) :: (List.map loop el)) | TFunction f -> let arg (v,cto) = - tag "Arg" ~t:(Some v.v_type) ~extra_tabs:"\t" (match cto with None -> [local v] | Some ct -> [local v;const ct]) + tag "Arg" ~t:(Some v.v_type) ~extra_tabs:"\t" (match cto with None -> [local v] | Some ct -> [local v;const ct None]) in tag "Function" ((List.map arg f.tf_args) @ [loop f.tf_expr]) | TVar (v,eo) -> var v (match eo with None -> [] | Some e -> [loop e]) @@ -1176,8 +1242,6 @@ let s_class_kind = function "KNormal" | KTypeParameter tl -> Printf.sprintf "KTypeParameter [%s]" (s_types tl) - | KExtension(c,tl) -> - Printf.sprintf "KExtension %s<%s>" (s_type_path c.cl_path) (s_types tl) | KExpr _ -> "KExpr" | KGeneric -> @@ -1191,6 +1255,227 @@ let s_class_kind = function | KAbstractImpl a -> Printf.sprintf "KAbstractImpl %s" (s_type_path a.a_path) +module Printer = struct + + let s_type = + s_type (print_context()) + + let s_pair s1 s2 = + Printf.sprintf "(%s,%s)" s1 s2 + + let s_record_field name value = + Printf.sprintf "%s = %s;" name value + + let s_pos p = + Printf.sprintf "%s: %i-%i" p.pfile p.pmin p.pmax + + let s_record_fields tabs fields = + let sl = List.map (fun (name,value) -> s_record_field name value) fields in + Printf.sprintf "{\n%s\t%s\n%s}" tabs (String.concat ("\n\t" ^ tabs) sl) tabs + + let s_list sep f l = + "[" ^ (String.concat sep (List.map f l)) ^ "]" + + let s_opt f o = match o with + | None -> "None" + | Some v -> f v + + let s_pmap fk fv pm = + "{" ^ (String.concat ", " (PMap.foldi (fun k v acc -> (Printf.sprintf "%s = %s" (fk k) (fv v)) :: acc) pm [])) ^ "}" + + let s_doc = s_opt (fun s -> s) + + let s_metadata_entry (s,el,_) = + Printf.sprintf "@%s%s" (Meta.to_string s) (match el with [] -> "" | el -> "(" ^ (String.concat ", " (List.map Ast.s_expr el)) ^ ")") + + let s_metadata metadata = + s_list " " s_metadata_entry metadata + + let s_type_param (s,t) = match follow t with + | TInst({cl_kind = KTypeParameter tl1},tl2) -> + begin match tl1 with + | [] -> s + | _ -> Printf.sprintf "%s:%s" s (String.concat ", " (List.map s_type tl1)) + end + | _ -> assert false + + let s_type_params tl = + s_list ", " s_type_param tl + + let s_tclass_field tabs cf = + s_record_fields tabs [ + "cf_name",cf.cf_name; + "cf_doc",s_doc cf.cf_doc; + "cf_type",s_type_kind (follow cf.cf_type); + "cf_public",string_of_bool cf.cf_public; + "cf_pos",s_pos cf.cf_pos; + "cf_name_pos",s_pos cf.cf_name_pos; + "cf_meta",s_metadata cf.cf_meta; + "cf_kind",s_kind cf.cf_kind; + "cf_params",s_type_params cf.cf_params; + "cf_expr",s_opt (s_expr_ast true "\t\t" s_type) cf.cf_expr; + ] + + let s_tclass tabs c = + s_record_fields tabs [ + "cl_path",s_type_path c.cl_path; + "cl_module",s_type_path c.cl_module.m_path; + "cl_pos",s_pos c.cl_pos; + "cl_name_pos",s_pos c.cl_name_pos; + "cl_private",string_of_bool c.cl_private; + "cl_doc",s_doc c.cl_doc; + "cl_meta",s_metadata c.cl_meta; + "cl_params",s_type_params c.cl_params; + "cl_kind",s_class_kind c.cl_kind; + "cl_extern",string_of_bool c.cl_extern; + "cl_interface",string_of_bool c.cl_interface; + "cl_super",s_opt (fun (c,tl) -> s_type (TInst(c,tl))) c.cl_super; + "cl_implements",s_list ", " (fun (c,tl) -> s_type (TInst(c,tl))) c.cl_implements; + "cl_dynamic",s_opt s_type c.cl_dynamic; + "cl_array_access",s_opt s_type c.cl_array_access; + "cl_overrides",s_list "," (fun cf -> cf.cf_name) c.cl_overrides; + "cl_init",s_opt (s_expr_ast true "" s_type) c.cl_init; + "cl_constructor",s_opt (s_tclass_field (tabs ^ "\t")) c.cl_constructor; + "cl_ordered_fields",s_list "\n\t" (s_tclass_field (tabs ^ "\t")) c.cl_ordered_fields; + "cl_ordered_statics",s_list "\n\t" (s_tclass_field (tabs ^ "\t")) c.cl_ordered_statics; + ] + + let s_tdef tabs t = + s_record_fields tabs [ + "t_path",s_type_path t.t_path; + "t_module",s_type_path t.t_module.m_path; + "t_pos",s_pos t.t_pos; + "t_name_pos",s_pos t.t_name_pos; + "t_private",string_of_bool t.t_private; + "t_doc",s_doc t.t_doc; + "t_meta",s_metadata t.t_meta; + "t_params",s_type_params t.t_params; + "t_type",s_type_kind t.t_type + ] + + let s_tenum_field tabs ef = + s_record_fields tabs [ + "ef_name",ef.ef_name; + "ef_doc",s_doc ef.ef_doc; + "ef_pos",s_pos ef.ef_pos; + "ef_name_pos",s_pos ef.ef_name_pos; + "ef_type",s_type_kind ef.ef_type; + "ef_index",string_of_int ef.ef_index; + "ef_params",s_type_params ef.ef_params; + "ef_meta",s_metadata ef.ef_meta + ] + + let s_tenum tabs en = + s_record_fields tabs [ + "e_path",s_type_path en.e_path; + "e_module",s_type_path en.e_module.m_path; + "e_pos",s_pos en.e_pos; + "e_name_pos",s_pos en.e_name_pos; + "e_private",string_of_bool en.e_private; + "d_doc",s_doc en.e_doc; + "e_meta",s_metadata en.e_meta; + "e_params",s_type_params en.e_params; + "e_type",s_tdef "\t" en.e_type; + "e_extern",string_of_bool en.e_extern; + "e_constrs",s_list "\n\t" (s_tenum_field (tabs ^ "\t")) (PMap.fold (fun ef acc -> ef :: acc) en.e_constrs []); + "e_names",String.concat ", " en.e_names + ] + + let s_tabstract tabs a = + s_record_fields tabs [ + "a_path",s_type_path a.a_path; + "a_modules",s_type_path a.a_module.m_path; + "a_pos",s_pos a.a_pos; + "a_name_pos",s_pos a.a_name_pos; + "a_private",string_of_bool a.a_private; + "a_doc",s_doc a.a_doc; + "a_meta",s_metadata a.a_meta; + "a_params",s_type_params a.a_params; + "a_ops",s_list ", " (fun (op,cf) -> Printf.sprintf "%s: %s" (s_binop op) cf.cf_name) a.a_ops; + "a_unops",s_list ", " (fun (op,flag,cf) -> Printf.sprintf "%s (%s): %s" (s_unop op) (if flag = Postfix then "postfix" else "prefix") cf.cf_name) a.a_unops; + "a_impl",s_opt (fun c -> s_type_path c.cl_path) a.a_impl; + "a_this",s_type_kind a.a_this; + "a_from",s_list ", " s_type_kind a.a_from; + "a_to",s_list ", " s_type_kind a.a_to; + "a_from_field",s_list ", " (fun (t,cf) -> Printf.sprintf "%s: %s" (s_type_kind t) cf.cf_name) a.a_from_field; + "a_to_field",s_list ", " (fun (t,cf) -> Printf.sprintf "%s: %s" (s_type_kind t) cf.cf_name) a.a_to_field; + "a_array",s_list ", " (fun cf -> cf.cf_name) a.a_array; + "a_resolve",s_opt (fun cf -> cf.cf_name) a.a_resolve; + ] + + let s_tvar_extra (tl,eo) = + Printf.sprintf "Some(%s, %s)" (s_type_params tl) (s_opt (s_expr_ast true "" s_type) eo) + + let s_tvar v = + s_record_fields "" [ + "v_id",string_of_int v.v_id; + "v_name",v.v_name; + "v_type",s_type v.v_type; + "v_capture",string_of_bool v.v_capture; + "v_extra",s_opt s_tvar_extra v.v_extra; + "v_meta",s_metadata v.v_meta; + ] + + let s_module_kind = function + | MCode -> "MCode" + | MMacro -> "MMacro" + | MFake -> "MFake" + | MSub -> "MSub" + | MExtern -> "MExtern" + | MImport -> "MImport" + + let s_module_def_extra tabs me = + s_record_fields tabs [ + "m_file",me.m_file; + "m_sign",me.m_sign; + "m_time",string_of_float me.m_time; + "m_dirty",s_opt (fun m -> s_type_path m.m_path) me.m_dirty; + "m_added",string_of_int me.m_added; + "m_mark",string_of_int me.m_mark; + "m_deps",s_pmap string_of_int (fun m -> snd m.m_path) me.m_deps; + "m_processed",string_of_int me.m_processed; + "m_kind",s_module_kind me.m_kind; + "m_binded_res",""; (* TODO *) + "m_macro_calls",String.concat ", " me.m_macro_calls; + "m_if_feature",""; (* TODO *) + "m_features",""; (* TODO *) + ] + + let s_module_def m = + s_record_fields "" [ + "m_id",string_of_int m.m_id; + "m_path",s_type_path m.m_path; + "m_extra",s_module_def_extra "\t" m.m_extra + ] + + let s_type_path tp = + s_record_fields "" [ + "tpackage",s_list "." (fun s -> s) tp.tpackage; + "tname",tp.tname; + "tparams",""; + "tsub",s_opt (fun s -> s) tp.tsub; + ] + + let s_class_flag = function + | HInterface -> "HInterface" + | HExtern -> "HExtern" + | HPrivate -> "HPrivate" + | HExtends tp -> "HExtends " ^ (s_type_path (fst tp)) + | HImplements tp -> "HImplements " ^ (s_type_path (fst tp)) + + let s_placed f (x,p) = + s_pair (f x) (s_pos p) + + let s_class_field cff = + s_record_fields "" [ + "cff_name",s_placed (fun s -> s) cff.cff_name; + "cff_doc",s_opt (fun s -> s) cff.cff_doc; + "cff_pos",s_pos cff.cff_pos; + "cff_meta",s_metadata cff.cff_meta; + "cff_access",s_list ", " Ast.s_access cff.cff_access; + ] +end + (* ======= Unification ======= *) let rec link e a b = @@ -1227,6 +1512,11 @@ let rec link e a b = true end +let link_dynamic a b = match follow a,follow b with + | TMono r,TDynamic _ -> r := Some b + | TDynamic _,TMono r -> r := Some a + | _ -> () + let rec fast_eq a b = if a == b then true @@ -1322,8 +1612,8 @@ let unify_kind k1 k2 = | MethDynamic -> direct_access v.v_read && direct_access v.v_write | MethMacro -> false | MethNormal | MethInline -> - match v.v_write with - | AccNo | AccNever -> true + match v.v_read,v.v_write with + | AccNormal,(AccNo | AccNever) -> true | _ -> false) | Method m1, Method m2 -> match m1,m2 with @@ -1343,7 +1633,7 @@ type eq_kind = let rec type_eq param a b = let can_follow t = match param with | EqCoreType -> false - | EqDoNotFollowNull -> not (is_null t) + | EqDoNotFollowNull -> not (is_explicit_null t) | _ -> true in if a == b then @@ -1402,10 +1692,17 @@ let rec type_eq param a b = try let f2 = PMap.find n a2.a_fields in if f1.cf_kind <> f2.cf_kind && (param = EqStrict || param = EqCoreType || not (unify_kind f1.cf_kind f2.cf_kind)) then error [invalid_kind n f1.cf_kind f2.cf_kind]; - try - type_eq param f1.cf_type f2.cf_type - with - Unify_error l -> error (invalid_field n :: l) + let a = f1.cf_type and b = f2.cf_type in + if not (List.exists (fun (a2,b2) -> fast_eq a a2 && fast_eq b b2) (!eq_stack)) then begin + eq_stack := (a,b) :: !eq_stack; + try + type_eq param a b; + eq_stack := List.tl !eq_stack; + with + Unify_error l -> + eq_stack := List.tl !eq_stack; + error (invalid_field n :: l) + end; with Not_found -> if is_closed a2 then error [has_no_field b n]; @@ -1436,6 +1733,13 @@ let type_iseq a b = with Unify_error _ -> false +let type_iseq_strict a b = + try + type_eq EqDoNotFollowNull a b; + true + with Unify_error _ -> + false + let unify_stack = ref [] let abstract_cast_stack = ref [] let unify_new_monos = ref [] @@ -1508,7 +1812,12 @@ let rec unify a b = loop cs (List.map (apply_params c.cl_params tl) tls) ) c.cl_implements || (match c.cl_kind with - | KTypeParameter pl -> List.exists (fun t -> match follow t with TInst (cs,tls) -> loop cs (List.map (apply_params c.cl_params tl) tls) | _ -> false) pl + | KTypeParameter pl -> List.exists (fun t -> + match follow t with + | TInst (cs,tls) -> loop cs (List.map (apply_params c.cl_params tl) tls) + | TAbstract(aa,tl) -> List.exists (unify_to aa tl b) aa.a_to + | _ -> false + ) pl | _ -> false) in if not (loop c1 tl1) then error [cannot_unify a b] @@ -1552,20 +1861,48 @@ let rec unify a b = let ft = apply_params c.cl_params tl ft in if not (unify_kind f1.cf_kind f2.cf_kind) then error [invalid_kind n f1.cf_kind f2.cf_kind]; if f2.cf_public && not f1.cf_public then error [invalid_visibility n]; - let old_monos = !unify_new_monos in - unify_new_monos := !monos @ !unify_new_monos; - if not (List.exists (fun (a2,b2) -> fast_eq b2 f2.cf_type && fast_eq_mono !unify_new_monos ft a2) (!unify_stack)) then begin - unify_stack := (ft,f2.cf_type) :: !unify_stack; - (try + + (match f2.cf_kind with + | Var { v_read = AccNo } | Var { v_read = AccNever } -> + (* we will do a recursive unification, so let's check for possible recursion *) + let old_monos = !unify_new_monos in + unify_new_monos := !monos @ !unify_new_monos; + if not (List.exists (fun (a2,b2) -> fast_eq b2 f2.cf_type && fast_eq_mono !unify_new_monos ft a2) (!unify_stack)) then begin + unify_stack := (ft,f2.cf_type) :: !unify_stack; + (try + unify_with_access ft f2 + with + Unify_error l -> + unify_new_monos := old_monos; + unify_stack := List.tl !unify_stack; + error (invalid_field n :: l)); + unify_stack := List.tl !unify_stack; + end; + unify_new_monos := old_monos; + | Method MethNormal | Method MethInline | Var { v_write = AccNo } | Var { v_write = AccNever } -> + (* same as before, but unification is reversed (read-only var) *) + let old_monos = !unify_new_monos in + unify_new_monos := !monos @ !unify_new_monos; + if not (List.exists (fun (a2,b2) -> fast_eq b2 ft && fast_eq_mono !unify_new_monos f2.cf_type a2) (!unify_stack)) then begin + unify_stack := (f2.cf_type,ft) :: !unify_stack; + (try + unify_with_access ft f2 + with + Unify_error l -> + unify_new_monos := old_monos; + unify_stack := List.tl !unify_stack; + error (invalid_field n :: l)); + unify_stack := List.tl !unify_stack; + end; + unify_new_monos := old_monos; + | _ -> + (* will use fast_eq, which have its own stack *) + try unify_with_access ft f2 with Unify_error l -> - unify_new_monos := old_monos; - unify_stack := List.tl !unify_stack; error (invalid_field n :: l)); - unify_stack := List.tl !unify_stack; - end; - unify_new_monos := old_monos; + List.iter (fun f2o -> if not (List.exists (fun f1o -> type_iseq f1o.cf_type f2o.cf_type) (f1 :: f1.cf_overloads)) then error [Missing_overload (f1, f2o.cf_type)] @@ -1599,6 +1936,21 @@ let rec unify a b = () | TFun _, TAbstract ({ a_path = ["haxe"],"Function" },[]) -> () + | TInst(c,tl),TAbstract({a_path = ["haxe"],"Constructible"},[t1]) -> + begin try + begin match c.cl_kind with + | KTypeParameter tl -> + (* type parameters require an equal Constructible constraint *) + if not (List.exists (fun t -> match follow t with TAbstract({a_path = ["haxe"],"Constructible"},[t2]) -> type_iseq t1 t2 | _ -> false) tl) then error [cannot_unify a b] + | _ -> + let _,t,cf = class_field c tl "new" in + if not cf.cf_public then error [invalid_visibility "new"]; + begin try unify t1 t + with Unify_error l -> error (cannot_unify a b :: l) end + end + with Not_found -> + error [has_no_field a "new"] + end | TDynamic t , _ -> if t == a then () @@ -1842,73 +2194,8 @@ and unify_with_access t1 f2 = (* read/write *) | _ -> with_variance (type_eq EqBothDynamic) t1 f2.cf_type -module Abstract = struct - open Ast - - let find_to ab pl b = - if follow b == t_dynamic then - List.find (fun (t,_) -> follow t == t_dynamic) ab.a_to_field - else if List.exists (unify_to ab pl ~allow_transitive_cast:false b) ab.a_to then - raise Not_found (* legacy compatibility *) - else - List.find (unify_to_field ab pl b) ab.a_to_field - - let find_from ab pl a b = - if follow a == t_dynamic then - List.find (fun (t,_) -> follow t == t_dynamic) ab.a_from_field - else if List.exists (unify_from ab pl a ~allow_transitive_cast:false b) ab.a_from then - raise Not_found (* legacy compatibility *) - else - List.find (unify_from_field ab pl a b) ab.a_from_field - - let underlying_type_stack = ref [] - - let rec get_underlying_type a pl = - let maybe_recurse t = - underlying_type_stack := a :: !underlying_type_stack; - let t = match follow t with - | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> - if List.mem a !underlying_type_stack then begin - let s = String.concat " -> " (List.map (fun a -> s_type_path a.a_path) (List.rev (a :: !underlying_type_stack))) in - raise (Error("Abstract chain detected: " ^ s,a.a_pos)) - end; - get_underlying_type a tl - | _ -> - t - in - underlying_type_stack := List.tl !underlying_type_stack; - t - in - try - if not (Meta.has Meta.MultiType a.a_meta) then raise Not_found; - let m = mk_mono() in - let _ = find_to a pl m in - maybe_recurse (follow m) - with Not_found -> - if Meta.has Meta.CoreType a.a_meta then - t_dynamic - else - maybe_recurse (apply_params a.a_params pl a.a_this) - - let rec follow_with_abstracts t = match follow t with - | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> - follow_with_abstracts (get_underlying_type a tl) - | t -> - t -end - (* ======= Mapping and iterating ======= *) -let iter_dt f dt = match dt with - | DTBind(_,dt) -> f dt - | DTSwitch(_,cl,dto) -> - List.iter (fun (_,dt) -> f dt) cl; - (match dto with None -> () | Some dt -> f dt) - | DTGuard(_,dt1,dt2) -> - f dt1; - (match dt2 with None -> () | Some dt -> f dt) - | DTGoto _ | DTExpr _ -> () - let iter f e = match e.eexpr with | TConst _ @@ -1997,7 +2284,8 @@ let map_expr f e = | TObjectDecl el -> { e with eexpr = TObjectDecl (List.map (fun (v,e) -> v, f e) el) } | TCall (e1,el) -> - { e with eexpr = TCall (f e1, List.map f el) } + let e1 = f e1 in + { e with eexpr = TCall (e1, List.map f el) } | TVar (v,eo) -> { e with eexpr = TVar (v, match eo with None -> None | Some e -> Some (f e)) } | TFunction fu -> @@ -2111,5 +2399,421 @@ let map_expr_type f ft fv e = | TMeta (m,e1) -> {e with eexpr = TMeta(m, f e1); etype = ft e.etype } -let print_if b e = - if b then print_endline (s_expr_pretty "" (s_type (print_context())) e) \ No newline at end of file +let resolve_typedef t = + match t with + | TClassDecl _ | TEnumDecl _ | TAbstractDecl _ -> t + | TTypeDecl td -> + match follow td.t_type with + | TEnum (e,_) -> TEnumDecl e + | TInst (c,_) -> TClassDecl c + | TAbstract (a,_) -> TAbstractDecl a + | _ -> t + +module TExprToExpr = struct + let tpath p mp pl = + if snd mp = snd p then + CTPath { + tpackage = fst p; + tname = snd p; + tparams = List.map (fun t -> TPType t) pl; + tsub = None; + } + else CTPath { + tpackage = fst mp; + tname = snd mp; + tparams = List.map (fun t -> TPType t) pl; + tsub = Some (snd p); + } + + let rec convert_type = function + | TMono r -> + (match !r with + | None -> raise Exit + | Some t -> convert_type t) + | TInst ({cl_private = true; cl_path=_,name},tl) + | TEnum ({e_private = true; e_path=_,name},tl) + | TType ({t_private = true; t_path=_,name},tl) + | TAbstract ({a_private = true; a_path=_,name},tl) -> + CTPath { + tpackage = []; + tname = name; + tparams = List.map (fun t -> TPType (convert_type' t)) tl; + tsub = None; + } + | TEnum (e,pl) -> + tpath e.e_path e.e_module.m_path (List.map convert_type' pl) + | TInst({cl_kind = KTypeParameter _} as c,pl) -> + tpath ([],snd c.cl_path) ([],snd c.cl_path) (List.map convert_type' pl) + | TInst (c,pl) -> + tpath c.cl_path c.cl_module.m_path (List.map convert_type' pl) + | TType (t,pl) as tf -> + (* recurse on type-type *) + if (snd t.t_path).[0] = '#' then convert_type (follow tf) else tpath t.t_path t.t_module.m_path (List.map convert_type' pl) + | TAbstract (a,pl) -> + tpath a.a_path a.a_module.m_path (List.map convert_type' pl) + | TFun (args,ret) -> + CTFunction (List.map (fun (_,_,t) -> convert_type' t) args, (convert_type' ret)) + | TAnon a -> + begin match !(a.a_status) with + | Statics c -> tpath ([],"Class") ([],"Class") [tpath c.cl_path c.cl_path [],null_pos] + | EnumStatics e -> tpath ([],"Enum") ([],"Enum") [tpath e.e_path e.e_path [],null_pos] + | _ -> + CTAnonymous (PMap.foldi (fun _ f acc -> + { + cff_name = f.cf_name,null_pos; + cff_kind = FVar (mk_type_hint f.cf_type null_pos,None); + cff_pos = f.cf_pos; + cff_doc = f.cf_doc; + cff_meta = f.cf_meta; + cff_access = []; + } :: acc + ) a.a_fields []) + end + | (TDynamic t2) as t -> + tpath ([],"Dynamic") ([],"Dynamic") (if t == t_dynamic then [] else [convert_type' t2]) + | TLazy f -> + convert_type ((!f)()) + + and convert_type' t = + convert_type t,null_pos + + and mk_type_hint t p = + match follow t with + | TMono _ -> None + | _ -> (try Some (convert_type t,p) with Exit -> None) + + let rec convert_expr e = + let full_type_path t = + let mp,p = match t with + | TClassDecl c -> c.cl_module.m_path,c.cl_path + | TEnumDecl en -> en.e_module.m_path,en.e_path + | TAbstractDecl a -> a.a_module.m_path,a.a_path + | TTypeDecl t -> t.t_module.m_path,t.t_path + in + if snd mp = snd p then p else (fst mp) @ [snd mp],snd p + in + let mk_path = expr_of_type_path in + let mk_ident = function + | "`trace" -> Ident "trace" + | n -> Ident n + in + let eopt = function None -> None | Some e -> Some (convert_expr e) in + ((match e.eexpr with + | TConst c -> + EConst (tconst_to_const c) + | TLocal v -> EConst (mk_ident v.v_name) + | TArray (e1,e2) -> EArray (convert_expr e1,convert_expr e2) + | TBinop (op,e1,e2) -> EBinop (op, convert_expr e1, convert_expr e2) + | TField (e,f) -> EField (convert_expr e, field_name f) + | TTypeExpr t -> fst (mk_path (full_type_path t) e.epos) + | TParenthesis e -> EParenthesis (convert_expr e) + | TObjectDecl fl -> EObjectDecl (List.map (fun (f,e) -> (f,null_pos), convert_expr e) fl) + | TArrayDecl el -> EArrayDecl (List.map convert_expr el) + | TCall (e,el) -> ECall (convert_expr e,List.map convert_expr el) + | TNew (c,pl,el) -> ENew ((match (try convert_type (TInst (c,pl)) with Exit -> convert_type (TInst (c,[]))) with CTPath p -> p,null_pos | _ -> assert false),List.map convert_expr el) + | TUnop (op,p,e) -> EUnop (op,p,convert_expr e) + | TFunction f -> + let arg (v,c) = (v.v_name,v.v_pos), false, v.v_meta, mk_type_hint v.v_type null_pos, (match c with None -> None | Some c -> Some (EConst (tconst_to_const c),e.epos)) in + EFunction (None,{ f_params = []; f_args = List.map arg f.tf_args; f_type = mk_type_hint f.tf_type null_pos; f_expr = Some (convert_expr f.tf_expr) }) + | TVar (v,eo) -> + EVars ([(v.v_name,v.v_pos), mk_type_hint v.v_type v.v_pos, eopt eo]) + | TBlock el -> EBlock (List.map convert_expr el) + | TFor (v,it,e) -> + let ein = (EIn ((EConst (Ident v.v_name),it.epos),convert_expr it),it.epos) in + EFor (ein,convert_expr e) + | TIf (e,e1,e2) -> EIf (convert_expr e,convert_expr e1,eopt e2) + | TWhile (e1,e2,flag) -> EWhile (convert_expr e1, convert_expr e2, flag) + | TSwitch (e,cases,def) -> + let cases = List.map (fun (vl,e) -> + List.map convert_expr vl,None,(match e.eexpr with TBlock [] -> None | _ -> Some (convert_expr e)),e.epos + ) cases in + let def = match eopt def with None -> None | Some (EBlock [],_) -> Some (None,null_pos) | Some e -> Some (Some e,pos e) in + ESwitch (convert_expr e,cases,def) + | TEnumParameter _ -> + (* these are considered complex, so the AST is handled in TMeta(Meta.Ast) *) + assert false + | TTry (e,catches) -> + let e1 = convert_expr e in + let catches = List.map (fun (v,e) -> + let ct = try convert_type v.v_type,null_pos with Exit -> assert false in + let e = convert_expr e in + (v.v_name,v.v_pos),ct,e,(pos e) + ) catches in + ETry (e1,catches) + | TReturn e -> EReturn (eopt e) + | TBreak -> EBreak + | TContinue -> EContinue + | TThrow e -> EThrow (convert_expr e) + | TCast (e,t) -> + let t = (match t with + | None -> None + | Some t -> + let t = (match t with TClassDecl c -> TInst (c,[]) | TEnumDecl e -> TEnum (e,[]) | TTypeDecl t -> TType (t,[]) | TAbstractDecl a -> TAbstract (a,[])) in + Some (try convert_type t,null_pos with Exit -> assert false) + ) in + ECast (convert_expr e,t) + | TMeta ((Meta.Ast,[e1,_],_),_) -> e1 + | TMeta (m,e) -> EMeta(m,convert_expr e)) + ,e.epos) + +end + +module Texpr = struct + let equal_fa fa1 fa2 = match fa1,fa2 with + | FStatic(c1,cf1),FStatic(c2,cf2) -> c1 == c2 && cf1 == cf2 + | FInstance(c1,tl1,cf1),FInstance(c2,tl2,cf2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && cf1 == cf2 + (* TODO: This is technically not correct but unfortunately the compiler makes a distinct tclass_field for each anon field access. *) + | FAnon cf1,FAnon cf2 -> cf1.cf_name = cf2.cf_name + | FDynamic s1,FDynamic s2 -> s1 = s2 + | FClosure(None,cf1),FClosure(None,cf2) -> cf1 == cf2 + | FClosure(Some(c1,tl1),cf1),FClosure(Some(c2,tl2),cf2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && cf1 == cf2 + | FEnum(en1,ef1),FEnum(en2,ef2) -> en1 == en2 && ef1 == ef2 + | _ -> false + + let rec equal e1 e2 = match e1.eexpr,e2.eexpr with + | TConst ct1,TConst ct2 -> ct1 = ct2 + | TLocal v1,TLocal v2 -> v1 == v2 + | TArray(eb1,ei1),TArray(eb2,ei2) -> equal eb1 eb2 && equal ei1 ei2 + | TBinop(op1,lhs1,rhs1),TBinop(op2,lhs2,rhs2) -> op1 = op2 && equal lhs1 lhs2 && equal rhs1 rhs2 + | TField(e1,fa1),TField(e2,fa2) -> equal e1 e2 && equal_fa fa1 fa2 + | TTypeExpr mt1,TTypeExpr mt2 -> mt1 == mt2 + | TParenthesis e1,TParenthesis e2 -> equal e1 e2 + | TObjectDecl fl1,TObjectDecl fl2 -> safe_for_all2 (fun (s1,e1) (s2,e2) -> s1 = s2 && equal e1 e2) fl1 fl2 + | (TArrayDecl el1,TArrayDecl el2) | (TBlock el1,TBlock el2) -> safe_for_all2 equal el1 el2 + | TCall(e1,el1),TCall(e2,el2) -> equal e1 e2 && safe_for_all2 equal el1 el2 + | TNew(c1,tl1,el1),TNew(c2,tl2,el2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && safe_for_all2 equal el1 el2 + | TUnop(op1,flag1,e1),TUnop(op2,flag2,e2) -> op1 = op2 && flag1 = flag2 && equal e1 e2 + | TFunction tf1,TFunction tf2 -> tf1 == tf2 + | TVar(v1,None),TVar(v2,None) -> v1 == v2 + | TVar(v1,Some e1),TVar(v2,Some e2) -> v1 == v2 && equal e1 e2 + | TFor(v1,ec1,eb1),TFor(v2,ec2,eb2) -> v1 == v2 && equal ec1 ec2 && equal eb1 eb2 + | TIf(e1,ethen1,None),TIf(e2,ethen2,None) -> equal e1 e2 && equal ethen1 ethen2 + | TIf(e1,ethen1,Some eelse1),TIf(e2,ethen2,Some eelse2) -> equal e1 e2 && equal ethen1 ethen2 && equal eelse1 eelse2 + | TWhile(e1,eb1,flag1),TWhile(e2,eb2,flag2) -> equal e1 e2 && equal eb2 eb2 && flag1 = flag2 + | TSwitch(e1,cases1,eo1),TSwitch(e2,cases2,eo2) -> + equal e1 e2 && + safe_for_all2 (fun (el1,e1) (el2,e2) -> safe_for_all2 equal el1 el2 && equal e1 e2) cases1 cases2 && + (match eo1,eo2 with None,None -> true | Some e1,Some e2 -> equal e1 e2 | _ -> false) + | TTry(e1,catches1),TTry(e2,catches2) -> equal e1 e2 && safe_for_all2 (fun (v1,e1) (v2,e2) -> v1 == v2 && equal e1 e2) catches1 catches2 + | TReturn None,TReturn None -> true + | TReturn(Some e1),TReturn(Some e2) -> equal e1 e2 + | TThrow e1,TThrow e2 -> equal e1 e2 + | TCast(e1,None),TCast(e2,None) -> equal e1 e2 + | TCast(e1,Some mt1),TCast(e2,Some mt2) -> equal e1 e2 && mt1 == mt2 + | TMeta((m1,el1,_),e1),TMeta((m2,el2,_),e2) -> m1 = m2 && safe_for_all2 (fun e1 e2 -> (* TODO: cheating? *) (Ast.s_expr e1) = (Ast.s_expr e2)) el1 el2 && equal e1 e2 + | (TBreak,TBreak) | (TContinue,TContinue) -> true + | TEnumParameter(e1,ef1,i1),TEnumParameter(e2,ef2,i2) -> equal e1 e2 && ef1 == ef2 && i1 = i2 + | _ -> false + + let duplicate_tvars e = + let vars = Hashtbl.create 0 in + let copy_var v = + let v2 = alloc_var v.v_name v.v_type v.v_pos in + v2.v_meta <- v.v_meta; + Hashtbl.add vars v.v_id v2; + v2; + in + let rec build_expr e = + match e.eexpr with + | TVar (v,eo) -> + let v2 = copy_var v in + {e with eexpr = TVar(v2, Option.map build_expr eo)} + | TFor (v,e1,e2) -> + let v2 = copy_var v in + {e with eexpr = TFor(v2, build_expr e1, build_expr e2)} + | TTry (e1,cl) -> + let cl = List.map (fun (v,e) -> + let v2 = copy_var v in + v2, build_expr e + ) cl in + {e with eexpr = TTry(build_expr e1, cl)} + | TFunction f -> + let args = List.map (fun (v,c) -> copy_var v, c) f.tf_args in + let f = { + tf_args = args; + tf_type = f.tf_type; + tf_expr = build_expr f.tf_expr; + } in + {e with eexpr = TFunction f} + | TLocal v -> + (try + let v2 = Hashtbl.find vars v.v_id in + {e with eexpr = TLocal v2} + with _ -> + e) + | _ -> + map_expr build_expr e + in + build_expr e + + let rec skip e = match e.eexpr with + | TParenthesis e1 | TMeta(_,e1) | TBlock [e1] | TCast(e1,None) -> skip e1 + | _ -> e + + let foldmap_list f acc el = + let rec loop acc el acc2 = (match el with + | [] -> acc,(List.rev acc2) + | e1 :: el -> + let acc,e1 = f acc e1 in + loop acc el (e1 :: acc2)) + in loop acc el [] + + let foldmap_opt f acc eo = match eo with + | Some(e) -> let acc,e = f acc e in acc,Some(e) + | None -> acc,eo + + let foldmap_pairs f acc pairs = + let acc,pairs = List.fold_left + (fun (acc,el) (v,e) -> let acc,e = f acc e in (acc,(v,e) :: el)) + (acc,[]) + pairs + in acc,(List.rev pairs) + + let foldmap f acc e = + begin match e.eexpr with + | TConst _ + | TLocal _ + | TBreak + | TContinue + | TTypeExpr _ -> + acc,e + | TArray (e1,e2) -> + let acc,e1 = f acc e1 in + let acc,e2 = f acc e2 in + acc,{ e with eexpr = TArray (e1, e2) } + | TBinop (op,e1,e2) -> + let acc,e1 = f acc e1 in + let acc,e2 = f acc e2 in + acc,{ e with eexpr = TBinop (op,e1,e2) } + | TFor (v,e1,e2) -> + let acc,e1 = f acc e1 in + let acc,e2 = f acc e2 in + acc,{ e with eexpr = TFor (v,e1,e2) } + | TWhile (e1,e2,flag) -> + let acc,e1 = f acc e1 in + let acc,e2 = f acc e2 in + acc,{ e with eexpr = TWhile (e1,e2,flag) } + | TThrow e1 -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TThrow (e1) } + | TEnumParameter (e1,ef,i) -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TEnumParameter(e1,ef,i) } + | TField (e1,v) -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TField (e1,v) } + | TParenthesis e1 -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TParenthesis (e1) } + | TUnop (op,pre,e1) -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TUnop (op,pre,e1) } + | TArrayDecl el -> + let acc,el = foldmap_list f acc el in + acc,{ e with eexpr = TArrayDecl el } + | TNew (t,pl,el) -> + let acc,el = foldmap_list f acc el in + acc,{ e with eexpr = TNew (t,pl,el) } + | TBlock el -> + let acc,el = foldmap_list f acc el in + acc,{ e with eexpr = TBlock (el) } + | TObjectDecl el -> + let acc,el = foldmap_pairs f acc el in + acc,{ e with eexpr = TObjectDecl el } + | TCall (e1,el) -> + let acc,e1 = f acc e1 in + let acc,el = foldmap_list f acc el in + acc,{ e with eexpr = TCall (e1,el) } + | TVar (v,eo) -> + let acc,eo = foldmap_opt f acc eo in + acc,{ e with eexpr = TVar (v, eo) } + | TFunction fu -> + let acc,e1 = f acc fu.tf_expr in + acc,{ e with eexpr = TFunction { fu with tf_expr = e1 } } + | TIf (ec,e1,eo) -> + let acc,ec = f acc ec in + let acc,e1 = f acc e1 in + let acc,eo = foldmap_opt f acc eo in + acc,{ e with eexpr = TIf (ec,e1,eo)} + | TSwitch (e1,cases,def) -> + let acc,e1 = f acc e1 in + let acc,cases = List.fold_left (fun (acc,cases) (el,e2) -> + let acc,el = foldmap_list f acc el in + let acc,e2 = f acc e2 in + acc,((el,e2) :: cases) + ) (acc,[]) cases in + let acc,def = foldmap_opt f acc def in + acc,{ e with eexpr = TSwitch (e1, cases, def) } + | TTry (e1,catches) -> + let acc,e1 = f acc e1 in + let acc,catches = foldmap_pairs f acc catches in + acc,{ e with eexpr = TTry (e1, catches) } + | TReturn eo -> + let acc,eo = foldmap_opt f acc eo in + acc,{ e with eexpr = TReturn eo } + | TCast (e1,t) -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TCast (e1,t) } + | TMeta (m,e1) -> + let acc,e1 = f acc e1 in + acc,{ e with eexpr = TMeta(m,e1)} + end +end + +module ExtType = struct + let is_void = function + | TAbstract({a_path=[],"Void"},_) -> true + | _ -> false +end + +module StringError = struct + (* Source: http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#OCaml *) + let levenshtein a b = + let x = Array.init (String.length a) (fun i -> a.[i]) in + let y = Array.init (String.length b) (fun i -> b.[i]) in + let minimum (x:int) y z = + let m' (a:int) b = if a < b then a else b in + m' (m' x y) z + in + let init_matrix n m = + let init_col = Array.init m in + Array.init n (function + | 0 -> init_col (function j -> j) + | i -> init_col (function 0 -> i | _ -> 0) + ) + in + match Array.length x, Array.length y with + | 0, n -> n + | m, 0 -> m + | m, n -> + let matrix = init_matrix (m + 1) (n + 1) in + for i = 1 to m do + let s = matrix.(i) and t = matrix.(i - 1) in + for j = 1 to n do + let cost = abs (compare x.(i - 1) y.(j - 1)) in + s.(j) <- minimum (t.(j) + 1) (s.(j - 1) + 1) (t.(j - 1) + cost) + done + done; + matrix.(m).(n) + + let filter_similar f cl = + let rec loop sl = match sl with + | (x,i) :: sl when f x i -> x :: loop sl + | _ -> [] + in + loop cl + + let string_error_raise s sl msg = + if sl = [] then msg else + let cl = List.map (fun s2 -> s2,levenshtein s s2) sl in + let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in + let cl = filter_similar (fun s2 i -> i <= (min (String.length s) (String.length s2)) / 3) cl in + match cl with + | [] -> raise Not_found + | [s] -> Printf.sprintf "%s (Suggestion: %s)" msg s + | sl -> Printf.sprintf "%s (Suggestions: %s)" msg (String.concat ", " sl) + + let string_error s sl msg = + try string_error_raise s sl msg + with Not_found -> msg +end diff --git a/src/typing/typecore.ml b/src/typing/typecore.ml new file mode 100644 index 00000000..8bdff33f --- /dev/null +++ b/src/typing/typecore.ml @@ -0,0 +1,730 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Globals +open Ast +open Common +open Type +open Error + +type with_type = + | NoValue + | Value + | WithType of t + +type type_patch = { + mutable tp_type : complex_type option; + mutable tp_remove : bool; + mutable tp_meta : metadata; +} + +type current_fun = + | FunMember + | FunStatic + | FunConstructor + | FunMemberAbstract + | FunMemberClassLocal + | FunMemberAbstractLocal + +type macro_mode = + | MExpr + | MBuild + | MMacroType + | MDisplay + +type typer_pass = + | PBuildModule (* build the module structure and setup module type parameters *) + | PBuildClass (* build the class structure *) + | PTypeField (* type the class field, allow access to types structures *) + | PCheckConstraint (* perform late constraint checks with inferred types *) + | PForce (* usually ensure that lazy have been evaluated *) + | PFinal (* not used, only mark for finalize *) + +type typer_module = { + curmod : module_def; + mutable module_types : (module_type * pos) list; + mutable module_using : (tclass * pos) list; + mutable module_globals : (string, (module_type * string * pos)) PMap.t; + mutable wildcard_packages : (string list * pos) list; + mutable module_imports : import list; +} + +type typer_globals = { + types_module : (path, path) Hashtbl.t; + modules : (path , module_def) Hashtbl.t; + mutable delayed : (typer_pass * (unit -> unit) list) list; + mutable debug_delayed : (typer_pass * ((unit -> unit) * string * typer) list) list; + doinline : bool; + mutable core_api : typer option; + mutable macros : ((unit -> unit) * typer) option; + mutable std : module_def; + mutable hook_generate : (unit -> unit) list; + type_patches : (path, (string * bool, type_patch) Hashtbl.t * type_patch) Hashtbl.t; + mutable global_metadata : (string list * metadata_entry * (bool * bool * bool)) list; + mutable module_check_policies : (string list * module_check_policy list * bool) list; + mutable get_build_infos : unit -> (module_type * t list * class_field list) option; + delayed_macros : (unit -> unit) DynArray.t; + mutable global_using : (tclass * pos) list; + (* api *) + do_inherit : typer -> Type.tclass -> pos -> (bool * placed_type_path) -> bool; + do_create : Common.context -> typer; + do_macro : typer -> macro_mode -> path -> string -> expr list -> pos -> expr option; + do_load_module : typer -> path -> pos -> module_def; + do_optimize : typer -> texpr -> texpr; + do_build_instance : typer -> module_type -> pos -> ((string * t) list * path * (t list -> t)); + do_format_string : typer -> string -> pos -> Ast.expr; + do_finalize : typer -> unit; + do_generate : typer -> (texpr option * module_type list * module_def list); +} + +and typer = { + (* shared *) + com : context; + t : basic_types; + g : typer_globals; + mutable meta : metadata; + mutable this_stack : texpr list; + mutable with_type_stack : with_type list; + mutable call_argument_stack : expr list list; + (* variable *) + mutable pass : typer_pass; + (* per-module *) + mutable m : typer_module; + mutable is_display_file : bool; + (* per-class *) + mutable curclass : tclass; + mutable tthis : t; + mutable type_params : (string * t) list; + (* per-function *) + mutable curfield : tclass_field; + mutable untyped : bool; + mutable in_loop : bool; + mutable in_display : bool; + mutable in_macro : bool; + mutable macro_depth : int; + mutable curfun : current_fun; + mutable ret : t; + mutable locals : (string, tvar) PMap.t; + mutable opened : anon_status ref list; + mutable vthis : tvar option; + mutable in_call_args : bool; + (* events *) + mutable on_error : typer -> string -> pos -> unit; +} +exception Forbid_package of (string * path * pos) * pos list * string + +exception WithTypeError of error_msg * pos + +let make_call_ref : (typer -> texpr -> texpr list -> t -> pos -> texpr) ref = ref (fun _ _ _ _ _ -> assert false) +let type_expr_ref : (typer -> expr -> with_type -> texpr) ref = ref (fun _ _ _ -> assert false) +let type_module_type_ref : (typer -> module_type -> t list option -> pos -> texpr) ref = ref (fun _ _ _ _ -> assert false) +let unify_min_ref : (typer -> texpr list -> t) ref = ref (fun _ _ -> assert false) +let match_expr_ref : (typer -> expr -> (expr list * expr option * expr option * pos) list -> (expr option * pos) option -> with_type -> pos -> texpr) ref = ref (fun _ _ _ _ _ _ -> assert false) +let get_pattern_locals_ref : (typer -> expr -> Type.t -> (string, tvar * pos) PMap.t) ref = ref (fun _ _ _ -> assert false) +let get_constructor_ref : (typer -> tclass -> t list -> pos -> (t * tclass_field)) ref = ref (fun _ _ _ _ -> assert false) +let cast_or_unify_ref : (typer -> t -> texpr -> pos -> texpr) ref = ref (fun _ _ _ _ -> assert false) +let find_array_access_raise_ref : (typer -> tabstract -> tparams -> texpr -> texpr option -> pos -> (tclass_field * t * t * texpr * texpr option)) ref = ref (fun _ _ _ _ _ _ -> assert false) +let analyzer_run_on_expr_ref : (Common.context -> texpr -> texpr) ref = ref (fun _ _ -> assert false) +let merge_core_doc_ref : (typer -> tclass -> unit) ref = ref (fun _ _ -> assert false) + +let pass_name = function + | PBuildModule -> "build-module" + | PBuildClass -> "build-class" + | PTypeField -> "type-field" + | PCheckConstraint -> "check-constraint" + | PForce -> "force" + | PFinal -> "final" + +let display_error ctx msg p = match ctx.com.display.DisplayMode.dms_error_policy with + | DisplayMode.EPShow | DisplayMode.EPIgnore -> ctx.on_error ctx msg p + | DisplayMode.EPCollect -> add_diagnostics_message ctx.com msg p DisplayTypes.DiagnosticsSeverity.Error + +let make_call ctx e el t p = (!make_call_ref) ctx e el t p + +let type_expr ctx e with_type = (!type_expr_ref) ctx e with_type + +let unify_min ctx el = (!unify_min_ref) ctx el + +let match_expr ctx e cases def with_type p = !match_expr_ref ctx e cases def with_type p + +let make_static_this c p = + let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in + mk (TTypeExpr (TClassDecl c)) ta p + +let make_static_field_access c cf t p = + let ethis = make_static_this c p in + mk (TField (ethis,(FStatic (c,cf)))) t p + +let make_static_call ctx c cf map args t p = + let monos = List.map (fun _ -> mk_mono()) cf.cf_params in + let map t = map (apply_params cf.cf_params monos t) in + let ef = make_static_field_access c cf (map cf.cf_type) p in + make_call ctx ef args (map t) p + +let raise_or_display ctx l p = + if ctx.untyped then () + else if ctx.in_call_args then raise (WithTypeError(Unify l,p)) + else display_error ctx (error_msg (Unify l)) p + +let raise_or_display_message ctx msg p = + if ctx.in_call_args then raise (WithTypeError (Custom msg,p)) + else display_error ctx msg p + +let unify ctx t1 t2 p = + try + Type.unify t1 t2 + with + Unify_error l -> + raise_or_display ctx l p + +let unify_raise ctx t1 t2 p = + try + Type.unify t1 t2 + with + Unify_error l -> + (* no untyped check *) + raise (Error (Unify l,p)) + +let save_locals ctx = + let locals = ctx.locals in + (fun() -> ctx.locals <- locals) + +let add_local ctx n t p = + let v = alloc_var n t p in + ctx.locals <- PMap.add n v ctx.locals; + v + +let add_unbound_local ctx n t p = + let v = add_local ctx n t p in + v.v_meta <- (Meta.Unbound,[],null_pos) :: v.v_meta; + v + +let gen_local_prefix = "`" + +let gen_local ctx t p = + (* ensure that our generated local does not mask an existing one *) + let rec loop n = + let nv = (if n = 0 then gen_local_prefix else gen_local_prefix ^ string_of_int n) in + if PMap.mem nv ctx.locals then + loop (n+1) + else + nv + in + add_local ctx (loop 0) t p + +let is_gen_local v = + String.unsafe_get v.v_name 0 = String.unsafe_get gen_local_prefix 0 + +let delay ctx p f = + let rec loop = function + | [] -> [p,[f]] + | (p2,l) :: rest -> + if p2 = p then + (p, f :: l) :: rest + else if p2 < p then + (p2,l) :: loop rest + else + (p,[f]) :: (p2,l) :: rest + in + ctx.g.delayed <- loop ctx.g.delayed + +let delay_late ctx p f = + let rec loop = function + | [] -> [p,[f]] + | (p2,l) :: rest -> + if p2 <= p then + (p2,l) :: loop rest + else + (p,[f]) :: (p2,l) :: rest + in + ctx.g.delayed <- loop ctx.g.delayed + +let rec flush_pass ctx p (where:string) = + match ctx.g.delayed with + | (p2,l) :: rest when p2 <= p -> + (match l with + | [] -> + ctx.g.delayed <- rest; + | f :: l -> + ctx.g.delayed <- (p2,l) :: rest; + f()); + flush_pass ctx p where + | _ -> + () + +let make_pass ctx f = f + +let init_class_done ctx = + ctx.pass <- PTypeField + +let exc_protect ctx f (where:string) = + let rec r = ref (fun() -> + try + f r + with + | Error (m,p) -> + raise (Fatal_error ((error_msg m),p)) + ) in + r + +let fake_modules = Hashtbl.create 0 +let create_fake_module ctx file = + let file = Path.unique_full_path file in + let mdep = (try Hashtbl.find fake_modules file with Not_found -> + let mdep = { + m_id = alloc_mid(); + m_path = (["$DEP"],file); + m_types = []; + m_extra = module_extra file (Common.get_signature ctx.com) (file_time file) MFake []; + } in + Hashtbl.add fake_modules file mdep; + mdep + ) in + Hashtbl.replace ctx.g.modules mdep.m_path mdep; + mdep + +let push_this ctx e = match e.eexpr with + | TConst ((TInt _ | TFloat _ | TString _ | TBool _) as ct) -> + (EConst (tconst_to_const ct),e.epos),fun () -> () + | _ -> + ctx.this_stack <- e :: ctx.this_stack; + let er = EMeta((Meta.This,[],e.epos), (EConst(Ident "this"),e.epos)),e.epos in + er,fun () -> ctx.this_stack <- List.tl ctx.this_stack + +let is_removable_field ctx f = + Meta.has Meta.Extern f.cf_meta || Meta.has Meta.Generic f.cf_meta + || (match f.cf_kind with + | Var {v_read = AccRequire (s,_)} -> true + | Method MethMacro -> not ctx.in_macro + | _ -> false) + +(* -------------------------------------------------------------------------- *) +(* ABSTRACT CASTS *) + +module AbstractCast = struct + + let cast_stack = ref [] + + let make_static_call ctx c cf a pl args t p = + if cf.cf_kind = Method MethMacro then begin + match args with + | [e] -> + let e,f = push_this ctx e in + ctx.with_type_stack <- (WithType t) :: ctx.with_type_stack; + let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name [e] p with + | Some e -> type_expr ctx e Value + | None -> type_expr ctx (EConst (Ident "null"),p) Value + in + ctx.with_type_stack <- List.tl ctx.with_type_stack; + f(); + e + | _ -> assert false + end else + make_static_call ctx c cf (apply_params a.a_params pl) args t p + + let do_check_cast ctx tleft eright p = + let recurse cf f = + if cf == ctx.curfield || List.mem cf !cast_stack then error "Recursive implicit cast" p; + cast_stack := cf :: !cast_stack; + let r = f() in + cast_stack := List.tl !cast_stack; + r + in + let find a tl f = + let tcf,cf = f() in + if (Meta.has Meta.MultiType a.a_meta) then + mk_cast eright tleft p + else match a.a_impl with + | Some c -> recurse cf (fun () -> + let ret = make_static_call ctx c cf a tl [eright] tleft p in + { ret with eexpr = TMeta( (Meta.ImplicitCast,[],ret.epos), ret) } + ) + | None -> assert false + in + if type_iseq tleft eright.etype then + eright + else begin + let rec loop tleft tright = match follow tleft,follow tright with + | TAbstract(a1,tl1),TAbstract(a2,tl2) -> + begin try find a2 tl2 (fun () -> Abstract.find_to a2 tl2 tleft) + with Not_found -> try find a1 tl1 (fun () -> Abstract.find_from a1 tl1 eright.etype tleft) + with Not_found -> raise Not_found + end + | TAbstract(a,tl),_ -> + begin try find a tl (fun () -> Abstract.find_from a tl eright.etype tleft) + with Not_found -> + let rec loop2 tcl = match tcl with + | tc :: tcl -> + if not (type_iseq tc tleft) then loop (apply_params a.a_params tl tc) tright + else loop2 tcl + | [] -> raise Not_found + in + loop2 a.a_from + end + | _,TAbstract(a,tl) -> + begin try find a tl (fun () -> Abstract.find_to a tl tleft) + with Not_found -> + let rec loop2 tcl = match tcl with + | tc :: tcl -> + if not (type_iseq tc tright) then loop tleft (apply_params a.a_params tl tc) + else loop2 tcl + | [] -> raise Not_found + in + loop2 a.a_to + end + | _ -> + raise Not_found + in + loop tleft eright.etype + end + + let cast_or_unify_raise ctx tleft eright p = + try + (* can't do that anymore because this might miss macro calls (#4315) *) + (* if ctx.com.display <> DMNone then raise Not_found; *) + do_check_cast ctx tleft eright p + with Not_found -> + unify_raise ctx eright.etype tleft p; + eright + + let cast_or_unify ctx tleft eright p = + try + cast_or_unify_raise ctx tleft eright p + with Error (Unify l,p) -> + raise_or_display ctx l p; + eright + + let find_array_access_raise ctx a pl e1 e2o p = + let is_set = e2o <> None in + let ta = apply_params a.a_params pl a.a_this in + let rec loop cfl = match cfl with + | [] -> raise Not_found + | cf :: cfl -> + let monos = List.map (fun _ -> mk_mono()) cf.cf_params in + let map t = apply_params a.a_params pl (apply_params cf.cf_params monos t) in + let check_constraints () = + List.iter2 (fun m (name,t) -> match follow t with + | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] -> + List.iter (fun tc -> match follow m with TMono _ -> raise (Unify_error []) | _ -> Type.unify m (map tc) ) constr + | _ -> () + ) monos cf.cf_params; + in + match follow (map cf.cf_type) with + | TFun([(_,_,tab);(_,_,ta1);(_,_,ta2)],r) as tf when is_set -> + begin try + Type.unify tab ta; + let e1 = cast_or_unify_raise ctx ta1 e1 p in + let e2o = match e2o with None -> None | Some e2 -> Some (cast_or_unify_raise ctx ta2 e2 p) in + check_constraints(); + cf,tf,r,e1,e2o + with Unify_error _ | Error (Unify _,_) -> + loop cfl + end + | TFun([(_,_,tab);(_,_,ta1)],r) as tf when not is_set -> + begin try + Type.unify tab ta; + let e1 = cast_or_unify_raise ctx ta1 e1 p in + check_constraints(); + cf,tf,r,e1,None + with Unify_error _ | Error (Unify _,_) -> + loop cfl + end + | _ -> loop cfl + in + loop a.a_array + + let find_array_access ctx a tl e1 e2o p = + try find_array_access_raise ctx a tl e1 e2o p + with Not_found -> match e2o with + | None -> + error (Printf.sprintf "No @:arrayAccess function accepts argument of %s" (s_type (print_context()) e1.etype)) p + | Some e2 -> + error (Printf.sprintf "No @:arrayAccess function accepts arguments of %s and %s" (s_type (print_context()) e1.etype) (s_type (print_context()) e2.etype)) p + + let find_multitype_specialization com a pl p = + let m = mk_mono() in + let tl = match Meta.get Meta.MultiType a.a_meta with + | _,[],_ -> pl + | _,el,_ -> + let relevant = Hashtbl.create 0 in + List.iter (fun e -> + let rec loop f e = match fst e with + | EConst(Ident s) -> + Hashtbl.replace relevant s f + | EMeta((Meta.Custom ":followWithAbstracts",_,_),e1) -> + loop Abstract.follow_with_abstracts e1; + | _ -> + error "Type parameter expected" (pos e) + in + loop (fun t -> t) e + ) el; + let tl = List.map2 (fun (n,_) t -> + try + (Hashtbl.find relevant n) t + with Not_found -> + if not (has_mono t) then t + else t_dynamic + ) a.a_params pl in + if com.platform = Globals.Js && a.a_path = ([],"Map") then begin match tl with + | t1 :: _ -> + let rec loop stack t = + if List.exists (fun t2 -> fast_eq t t2) stack then + t + else begin + let stack = t :: stack in + match follow t with + | TAbstract ({ a_path = [],"Class" },_) -> + error (Printf.sprintf "Cannot use %s as key type to Map because Class is not comparable" (s_type (print_context()) t1)) p; + | TEnum(en,tl) -> + PMap.iter (fun _ ef -> ignore(loop stack ef.ef_type)) en.e_constrs; + Type.map (loop stack) t + | t -> + Type.map (loop stack) t + end + in + ignore(loop [] t1) + | _ -> assert false + end; + tl + in + let _,cf = + try + Abstract.find_to a tl m + with Not_found -> + let at = apply_params a.a_params pl a.a_this in + let st = s_type (print_context()) at in + if has_mono at then + error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p + else + error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p; + in + cf, follow m + + let handle_abstract_casts ctx e = + let rec loop ctx e = match e.eexpr with + | TNew({cl_kind = KAbstractImpl a} as c,pl,el) -> + if not (Meta.has Meta.MultiType a.a_meta) then begin + (* This must have been a @:generic expansion with a { new } constraint (issue #4364). In this case + let's construct the underlying type. *) + match Abstract.get_underlying_type a pl with + | TInst(c,tl) as t -> {e with eexpr = TNew(c,tl,el); etype = t} + | _ -> error ("Cannot construct " ^ (s_type (print_context()) (TAbstract(a,pl)))) e.epos + end else begin + (* a TNew of an abstract implementation is only generated if it is a multi type abstract *) + let cf,m = find_multitype_specialization ctx.com a pl e.epos in + let e = make_static_call ctx c cf a pl ((mk (TConst TNull) (TAbstract(a,pl)) e.epos) :: el) m e.epos in + {e with etype = m} + end + | TCall({eexpr = TField(_,FStatic({cl_path=[],"Std"},{cf_name = "string"}))},[e1]) when (match follow e1.etype with TAbstract({a_impl = Some _},_) -> true | _ -> false) -> + begin match follow e1.etype with + | TAbstract({a_impl = Some c} as a,tl) -> + begin try + let cf = PMap.find "toString" c.cl_statics in + make_static_call ctx c cf a tl [e1] ctx.t.tstring e.epos + with Not_found -> + e + end + | _ -> + assert false + end + | TCall(e1, el) -> + begin try + let rec find_abstract e t = match follow t,e.eexpr with + | TAbstract(a,pl),_ when Meta.has Meta.MultiType a.a_meta -> a,pl,e + | _,TCast(e1,None) -> find_abstract e1 e1.etype + | _,TLocal {v_extra = Some(_,Some e')} -> + begin match follow e'.etype with + | TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta -> a,pl,mk (TCast(e,None)) e'.etype e.epos + | _ -> raise Not_found + end + | _ -> raise Not_found + in + let rec find_field e1 = + match e1.eexpr with + | TCast(e2,None) -> + {e1 with eexpr = TCast(find_field e2,None)} + | TField(e2,fa) -> + let a,pl,e2 = find_abstract e2 e2.etype in + let m = Abstract.get_underlying_type a pl in + let fname = field_name fa in + let el = List.map (loop ctx) el in + begin try + let fa = quick_field m fname in + let get_fun_type t = match follow t with + | TFun(_,tr) as tf -> tf,tr + | _ -> raise Not_found + in + let tf,tr = match fa with + | FStatic(_,cf) -> get_fun_type cf.cf_type + | FInstance(c,tl,cf) -> get_fun_type (apply_params c.cl_params tl cf.cf_type) + | FAnon cf -> get_fun_type cf.cf_type + | _ -> raise Not_found + in + let ef = mk (TField({e2 with etype = m},fa)) tf e2.epos in + let ecall = make_call ctx ef el tr e.epos in + if not (type_iseq ecall.etype e.etype) then + mk (TCast(ecall,None)) e.etype e.epos + else + ecall + with Not_found -> + (* quick_field raises Not_found if m is an abstract, we have to replicate the 'using' call here *) + match follow m with + | TAbstract({a_impl = Some c} as a,pl) -> + let cf = PMap.find fname c.cl_statics in + make_static_call ctx c cf a pl (e2 :: el) e.etype e.epos + | _ -> raise Not_found + end + | _ -> + raise Not_found + in + find_field e1 + with Not_found -> + Type.map_expr (loop ctx) e + end + | _ -> + Type.map_expr (loop ctx) e + in + loop ctx e +end + +(* -------------- debug functions to activate when debugging typer passes ------------------------------- *) +(*/* + +let delay_tabs = ref "" + +let context_ident ctx = + if Common.defined ctx.com Common.Define.CoreApi then + " core " + else if Common.defined ctx.com Common.Define.Macro then + "macro " + else + " out " + +let debug ctx str = + if Common.raw_defined ctx.com "cdebug" then prerr_endline (context_ident ctx ^ !delay_tabs ^ str) + +let init_class_done ctx = + debug ctx ("init_class_done " ^ s_type_path ctx.curclass.cl_path); + init_class_done ctx + +let ctx_pos ctx = + let inf = s_type_path ctx.m.curmod.m_path in + let inf = (match snd ctx.curclass.cl_path with "" -> inf | n when n = snd ctx.m.curmod.m_path -> inf | n -> inf ^ "." ^ n) in + let inf = (match ctx.curfield.cf_name with "" -> inf | n -> inf ^ ":" ^ n) in + inf + +let pass_infos ctx p = + let inf = pass_name p ^ " (" ^ ctx_pos ctx ^ ")" in + let inf = if ctx.pass > p then inf ^ " ??CURPASS=" ^ pass_name ctx.pass else inf in + inf + +let delay ctx p f = + let inf = pass_infos ctx p in + let rec loop = function + | [] -> [p,[f,inf,ctx]] + | (p2,l) :: rest -> + if p2 = p then + (p, (f,inf,ctx) :: l) :: rest + else if p2 < p then + (p2,l) :: loop rest + else + (p,[f,inf,ctx]) :: (p2,l) :: rest + in + ctx.g.debug_delayed <- loop ctx.g.debug_delayed; + debug ctx ("add " ^ inf) + +let pending_passes ctx = + let rec loop acc = function + | (p,l) :: pl when p < ctx.pass -> loop (acc @ l) pl + | _ -> acc + in + match loop [] ctx.g.debug_delayed with + | [] -> "" + | l -> " ??PENDING[" ^ String.concat ";" (List.map (fun (_,i,_) -> i) l) ^ "]" + +let display_error ctx msg p = + debug ctx ("ERROR " ^ msg); + display_error ctx msg p + +let make_pass ?inf ctx f = + let inf = (match inf with None -> pass_infos ctx ctx.pass | Some inf -> inf) in + (fun v -> + debug ctx ("run " ^ inf ^ pending_passes ctx); + let old = !delay_tabs in + delay_tabs := !delay_tabs ^ "\t"; + let t = (try + f v + with + | Fatal_error (e,p) -> + delay_tabs := old; + raise (Fatal_error (e,p)) + | exc when not (Common.raw_defined ctx.com "stack") -> + debug ctx ("FATAL " ^ Printexc.to_string exc); + delay_tabs := old; + raise exc + ) in + delay_tabs := old; + t + ) + +let rec flush_pass ctx p where = + let rec loop() = + match ctx.g.debug_delayed with + | (p2,l) :: rest when p2 <= p -> + (match l with + | [] -> + ctx.g.debug_delayed <- rest + | (f,inf,ctx2) :: l -> + ctx.g.debug_delayed <- (p2,l) :: rest; + match p2 with + | PTypeField | PBuildClass -> f() + | _ -> (make_pass ~inf ctx f)()); + loop() + | _ -> + () + in + match ctx.g.debug_delayed with + | (p2,_) :: _ when p2 <= p -> + let old = !delay_tabs in + debug ctx ("flush " ^ pass_name p ^ "(" ^ where ^ ")"); + delay_tabs := !delay_tabs ^ "\t"; + loop(); + delay_tabs := old; + debug ctx "flush-done"; + | _ -> + () + +let make_where ctx where = + where ^ " (" ^ ctx_pos ctx ^ ")" + +let exc_protect ctx f (where:string) = + let f = make_pass ~inf:(make_where ctx where) ctx f in + let rec r = ref (fun() -> + try + f r + with + | Error (m,p) -> + raise (Fatal_error (error_msg m,p)) + ) in + r + +*/*) +(* --------------------------------------------------- *) + + diff --git a/src/typing/typeload.ml b/src/typing/typeload.ml new file mode 100644 index 00000000..838c68ff --- /dev/null +++ b/src/typing/typeload.ml @@ -0,0 +1,4189 @@ +(* + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + *) + +open Ast +open Common +open Common.DisplayMode +open Type +open Typecore +open Error +open Globals + +exception Build_canceled of build_state + +let locate_macro_error = ref true + +let transform_abstract_field com this_t a_t a f = + let stat = List.mem AStatic f.cff_access in + let p = f.cff_pos in + match f.cff_kind with + | FProp ((("get" | "never"),_),(("set" | "never"),_),_,_) when not stat -> + (* TODO: hack to avoid issues with abstract property generation on As3 *) + if Common.defined com Define.As3 then f.cff_meta <- (Meta.Extern,[],null_pos) :: f.cff_meta; + { f with cff_access = AStatic :: f.cff_access; cff_meta = (Meta.Impl,[],null_pos) :: f.cff_meta } + | FProp _ when not stat -> + error "Member property accessors must be get/set or never" p; + | FFun fu when fst f.cff_name = "new" && not stat -> + let init p = (EVars [("this",null_pos),Some this_t,None],p) in + let cast e = (ECast(e,None)),pos e in + let ret p = (EReturn (Some (cast (EConst (Ident "this"),p))),p) in + let meta = (Meta.Impl,[],null_pos) :: f.cff_meta in + let meta = if Meta.has Meta.MultiType a.a_meta then begin + if List.mem AInline f.cff_access then error "MultiType constructors cannot be inline" f.cff_pos; + if fu.f_expr <> None then error "MultiType constructors cannot have a body" f.cff_pos; + (Meta.Extern,[],null_pos) :: meta + end else + meta + in + (* We don't want the generated expression positions to shadow the real code. *) + let p = { p with pmax = p.pmin } in + let fu = { + fu with + f_expr = (match fu.f_expr with + | None -> if Meta.has Meta.MultiType a.a_meta then Some (EConst (Ident "null"),p) else None + | Some (EBlock el,_) -> Some (EBlock (init p :: el @ [ret p]),p) + | Some e -> Some (EBlock [init p;e;ret p],p) + ); + f_type = Some a_t; + } in + { f with cff_name = "_new",pos f.cff_name; cff_access = AStatic :: f.cff_access; cff_kind = FFun fu; cff_meta = meta } + | FFun fu when not stat -> + if Meta.has Meta.From f.cff_meta then error "@:from cast functions must be static" f.cff_pos; + let fu = { fu with f_args = (if List.mem AMacro f.cff_access then fu.f_args else (("this",null_pos),false,[],Some this_t,None) :: fu.f_args) } in + { f with cff_kind = FFun fu; cff_access = AStatic :: f.cff_access; cff_meta = (Meta.Impl,[],null_pos) :: f.cff_meta } + | _ -> + f + +let get_policy ctx mpath = + let sl1 = full_dot_path mpath mpath in + List.fold_left (fun acc (sl2,policy,recursive) -> if match_path recursive sl1 sl2 then policy @ acc else acc) [] ctx.g.module_check_policies + +let make_module ctx mpath file loadp = + let m = { + m_id = alloc_mid(); + m_path = mpath; + m_types = []; + m_extra = module_extra (Path.unique_full_path file) (Common.get_signature ctx.com) (file_time file) (if ctx.in_macro then MMacro else MCode) (get_policy ctx mpath); + } in + m + +(* + Build module structure : should be atomic - no type loading is possible +*) +let module_pass_1 ctx m tdecls loadp = + let com = ctx.com in + let decls = ref [] in + let make_path name priv = + if List.exists (fun (t,_) -> snd (t_path t) = name) !decls then error ("Type name " ^ name ^ " is already defined in this module") loadp; + if priv then (fst m.m_path @ ["_" ^ snd m.m_path], name) else (fst m.m_path, name) + in + let pt = ref None in + let rec make_decl acc decl = + let p = snd decl in + let acc = (match fst decl with + | EImport _ | EUsing _ -> + (match !pt with + | None -> acc + | Some _ -> error "import and using may not appear after a type declaration" p) + | EClass d -> + let name = fst d.d_name in + if String.length name > 0 && name.[0] = '$' then error "Type names starting with a dollar are not allowed" p; + pt := Some p; + let priv = List.mem HPrivate d.d_flags in + let path = make_path name priv in + let c = mk_class m path p (pos d.d_name) in + (* we shouldn't load any other type until we propertly set cl_build *) + c.cl_build <- (fun() -> error (s_type_path c.cl_path ^ " is not ready to be accessed, separate your type declarations in several files") p); + c.cl_module <- m; + c.cl_private <- priv; + c.cl_doc <- d.d_doc; + c.cl_meta <- d.d_meta; + decls := (TClassDecl c, decl) :: !decls; + acc + | EEnum d -> + let name = fst d.d_name in + if String.length name > 0 && name.[0] = '$' then error "Type names starting with a dollar are not allowed" p; + pt := Some p; + let priv = List.mem EPrivate d.d_flags in + let path = make_path name priv in + let e = { + e_path = path; + e_module = m; + e_pos = p; + e_name_pos = (pos d.d_name); + e_doc = d.d_doc; + e_meta = d.d_meta; + e_params = []; + e_private = priv; + e_extern = List.mem EExtern d.d_flags; + e_constrs = PMap.empty; + e_names = []; + e_type = { + t_path = [], "Enum<" ^ (s_type_path path) ^ ">"; + t_module = m; + t_doc = None; + t_pos = p; + t_name_pos = null_pos; + t_type = mk_mono(); + t_private = true; + t_params = []; + t_meta = []; + }; + } in + decls := (TEnumDecl e, decl) :: !decls; + acc + | ETypedef d -> + let name = fst d.d_name in + if String.length name > 0 && name.[0] = '$' then error "Type names starting with a dollar are not allowed" p; + pt := Some p; + let priv = List.mem EPrivate d.d_flags in + let path = make_path name priv in + let t = { + t_path = path; + t_module = m; + t_pos = p; + t_name_pos = pos d.d_name; + t_doc = d.d_doc; + t_private = priv; + t_params = []; + t_type = mk_mono(); + t_meta = d.d_meta; + } in + (* failsafe in case the typedef is not initialized (see #3933) *) + delay ctx PBuildModule (fun () -> + match t.t_type with + | TMono r -> (match !r with None -> r := Some com.basic.tvoid | _ -> ()) + | _ -> () + ); + decls := (TTypeDecl t, decl) :: !decls; + acc + | EAbstract d -> + let name = fst d.d_name in + if String.length name > 0 && name.[0] = '$' then error "Type names starting with a dollar are not allowed" p; + let priv = List.mem APrivAbstract d.d_flags in + let path = make_path name priv in + let a = { + a_path = path; + a_private = priv; + a_module = m; + a_pos = p; + a_name_pos = pos d.d_name; + a_doc = d.d_doc; + a_params = []; + a_meta = d.d_meta; + a_from = []; + a_to = []; + a_from_field = []; + a_to_field = []; + a_ops = []; + a_unops = []; + a_impl = None; + a_array = []; + a_this = mk_mono(); + a_resolve = None; + } in + decls := (TAbstractDecl a, decl) :: !decls; + match d.d_data with + | [] when Meta.has Meta.CoreType a.a_meta -> + a.a_this <- t_dynamic; + acc + | fields -> + let a_t = + let params = List.map (fun t -> TPType (CTPath { tname = fst t.tp_name; tparams = []; tsub = None; tpackage = [] },null_pos)) d.d_params in + CTPath { tpackage = []; tname = fst d.d_name; tparams = params; tsub = None },null_pos + in + let rec loop = function + | [] -> a_t + | AIsType t :: _ -> t + | _ :: l -> loop l + in + let this_t = loop d.d_flags in + let fields = List.map (transform_abstract_field com this_t a_t a) fields in + let meta = ref [] in + if has_meta Meta.Dce a.a_meta then meta := (Meta.Dce,[],null_pos) :: !meta; + let acc = make_decl acc (EClass { d_name = (fst d.d_name) ^ "_Impl_",snd d.d_name; d_flags = [HPrivate]; d_data = fields; d_doc = None; d_params = []; d_meta = !meta },p) in + (match !decls with + | (TClassDecl c,_) :: _ -> + List.iter (fun m -> match m with + | ((Meta.Build | Meta.CoreApi | Meta.Allow | Meta.Access | Meta.Enum | Meta.Dce | Meta.Native | Meta.JsRequire | Meta.PythonImport | Meta.Expose | Meta.Deprecated | Meta.PhpConstants | Meta.PhpGlobal),_,_) -> + c.cl_meta <- m :: c.cl_meta; + | _ -> + () + ) a.a_meta; + a.a_impl <- Some c; + c.cl_kind <- KAbstractImpl a; + c.cl_meta <- (Meta.Final,[],null_pos) :: c.cl_meta + | _ -> assert false); + acc + ) in + decl :: acc + in + let tdecls = List.fold_left make_decl [] tdecls in + let decls = List.rev !decls in + decls, List.rev tdecls + +let parse_file_from_lexbuf com file p lexbuf = + let t = Common.timer ["parsing"] in + Lexer.init file true; + incr stats.s_files_parsed; + let data = (try Parser.parse com lexbuf with e -> t(); raise e) in + begin match !display_default with + | DMModuleSymbols filter when filter <> None || Display.is_display_file file -> + let ds = Display.DocumentSymbols.collect_module_symbols data in + com.shared.shared_display_information.document_symbols <- (file,ds) :: com.shared.shared_display_information.document_symbols; + | _ -> + () + end; + t(); + Common.log com ("Parsed " ^ file); + data + +let parse_file_from_string com file p string = + parse_file_from_lexbuf com file p (Lexing.from_string string) + +let current_stdin = ref None (* TODO: we're supposed to clear this at some point *) + +let parse_file com file p = + let use_stdin = (Common.defined com Define.DisplayStdin) && Display.is_display_file file in + if use_stdin then + let s = + match !current_stdin with + | Some s -> + s + | None -> + let s = Std.input_all stdin in + close_in stdin; + current_stdin := Some s; + s + in + parse_file_from_string com file p s + else + let ch = try open_in_bin file with _ -> error ("Could not open " ^ file) p in + Std.finally (fun() -> close_in ch) (parse_file_from_lexbuf com file p) (Lexing.from_channel ch) + +let parse_hook = ref parse_file +let type_module_hook = ref (fun _ _ _ -> None) +let type_function_params_rec = ref (fun _ _ _ _ -> assert false) +let return_partial_type = ref false + +let type_function_arg ctx t e opt p = + if opt then + let e = (match e with None -> Some (EConst (Ident "null"),p) | _ -> e) in + ctx.t.tnull t, e + else + let t = match e with Some (EConst (Ident "null"),p) -> ctx.t.tnull t | _ -> t in + t, e + +let type_var_field ctx t e stat do_display p = + if stat then ctx.curfun <- FunStatic else ctx.curfun <- FunMember; + let e = if do_display then Display.ExprPreprocessing.process_expr ctx.com e else e in + let e = type_expr ctx e (WithType t) in + let e = (!cast_or_unify_ref) ctx t e p in + match t with + | TType ({ t_path = ([],"UInt") },[]) | TAbstract ({ a_path = ([],"UInt") },[]) when stat -> { e with etype = t } + | _ -> e + +let apply_macro ctx mode path el p = + let cpath, meth = (match List.rev (ExtString.String.nsplit path ".") with + | meth :: name :: pack -> (List.rev pack,name), meth + | _ -> error "Invalid macro path" p + ) in + ctx.g.do_macro ctx mode cpath meth el p + +(** since load_type_def and load_instance are used in PASS2, they should not access the structure of a type **) + +(* + load a type or a subtype definition +*) +let rec load_type_def ctx p t = + let no_pack = t.tpackage = [] in + let tname = (match t.tsub with None -> t.tname | Some n -> n) in + if tname = "" then raise (Display.DisplayToplevel (Display.ToplevelCollector.run ctx true)); + try + if t.tsub <> None then raise Not_found; + let path_matches t2 = + let tp = t_path t2 in + tp = (t.tpackage,tname) || (no_pack && snd tp = tname) + in + try + List.find path_matches ctx.m.curmod.m_types + with Not_found -> + let t,pi = List.find (fun (t2,pi) -> path_matches t2) ctx.m.module_types in + Display.ImportHandling.mark_import_position ctx.com pi; + t + with + Not_found -> + let next() = + let t, m = (try + t, ctx.g.do_load_module ctx (t.tpackage,t.tname) p + with Error (Module_not_found _,p2) as e when p == p2 -> + match t.tpackage with + | "std" :: l -> + let t = { t with tpackage = l } in + t, ctx.g.do_load_module ctx (t.tpackage,t.tname) p + | _ -> raise e + ) in + let tpath = (t.tpackage,tname) in + try + List.find (fun t -> not (t_infos t).mt_private && t_path t = tpath) m.m_types + with + Not_found -> raise (Error (Type_not_found (m.m_path,tname),p)) + in + (* lookup in wildcard imported packages *) + try + if not no_pack then raise Exit; + let rec loop l = match l with + | [] -> raise Exit + | (wp,pi) :: l -> + try + let t = load_type_def ctx p { t with tpackage = wp } in + Display.ImportHandling.mark_import_position ctx.com pi; + t + with + | Error (Module_not_found _,p2) + | Error (Type_not_found _,p2) when p == p2 -> loop l + in + loop ctx.m.wildcard_packages + with Exit -> + (* lookup in our own package - and its upper packages *) + let rec loop = function + | [] -> raise Exit + | (_ :: lnext) as l -> + try + load_type_def ctx p { t with tpackage = List.rev l } + with + | Error (Module_not_found _,p2) + | Error (Type_not_found _,p2) when p == p2 -> loop lnext + in + try + if not no_pack then raise Exit; + (match fst ctx.m.curmod.m_path with + | [] -> raise Exit + | x :: _ -> + (* this can occur due to haxe remoting : a module can be + already defined in the "js" package and is not allowed + to access the js classes *) + try + (match PMap.find x ctx.com.package_rules with + | Forbidden -> raise Exit + | _ -> ()) + with Not_found -> ()); + loop (List.rev (fst ctx.m.curmod.m_path)); + with + Exit -> next() + +let resolve_position_by_path ctx path p = + let mt = load_type_def ctx p path in + let p = (t_infos mt).mt_pos in + raise (Display.DisplayPosition [p]) + +let check_param_constraints ctx types t pl c p = + match follow t with + | TMono _ -> () + | _ -> + let ctl = (match c.cl_kind with KTypeParameter l -> l | _ -> []) in + List.iter (fun ti -> + let ti = apply_params types pl ti in + let ti = (match follow ti with + | TInst ({ cl_kind = KGeneric } as c,pl) -> + (* if we solve a generic contraint, let's substitute with the actual generic instance before unifying *) + let _,_, f = ctx.g.do_build_instance ctx (TClassDecl c) p in + f pl + | _ -> ti + ) in + try + unify_raise ctx t ti p + with Error(Unify l,p) -> + if not ctx.untyped then display_error ctx (error_msg (Unify (Constraint_failure (s_type_path c.cl_path) :: l))) p; + ) ctl + +let requires_value_meta com co = + Common.defined com Define.DocGen || (match co with + | None -> false + | Some c -> c.cl_extern || Meta.has Meta.Rtti c.cl_meta) + +let generate_value_meta com co cf args = + if requires_value_meta com co then begin + let values = List.fold_left (fun acc ((name,p),_,_,_,eo) -> match eo with Some e -> ((name,p),e) :: acc | _ -> acc) [] args in + match values with + | [] -> () + | _ -> cf.cf_meta <- ((Meta.Value,[EObjectDecl values,cf.cf_pos],null_pos) :: cf.cf_meta) + end + +let pselect p1 p2 = + if p1 = null_pos then p2 else p1 + +(* build an instance from a full type *) +let rec load_instance ?(allow_display=false) ctx (t,pn) allow_no_params p = + let p = pselect pn p in + let t = try + if t.tpackage <> [] || t.tsub <> None then raise Not_found; + let pt = List.assoc t.tname ctx.type_params in + if t.tparams <> [] then error ("Class type parameter " ^ t.tname ^ " can't have parameters") p; + pt + with Not_found -> + let mt = load_type_def ctx p t in + let is_generic,is_generic_build = match mt with + | TClassDecl {cl_kind = KGeneric} -> true,false + | TClassDecl {cl_kind = KGenericBuild _} -> false,true + | _ -> false,false + in + let types , path , f = ctx.g.do_build_instance ctx mt p in + let is_rest = is_generic_build && (match types with ["Rest",_] -> true | _ -> false) in + if allow_no_params && t.tparams = [] && not is_rest then begin + let pl = ref [] in + pl := List.map (fun (name,t) -> + match follow t with + | TInst (c,_) -> + let t = mk_mono() in + if c.cl_kind <> KTypeParameter [] || is_generic then delay ctx PCheckConstraint (fun() -> check_param_constraints ctx types t (!pl) c p); + t; + | _ -> assert false + ) types; + f (!pl) + end else if path = ([],"Dynamic") then + match t.tparams with + | [] -> t_dynamic + | [TPType t] -> TDynamic (load_complex_type ctx true p t) + | _ -> error "Too many parameters for Dynamic" p + else begin + if not is_rest && ctx.com.display.dms_error_policy <> EPIgnore && List.length types <> List.length t.tparams then error ("Invalid number of type parameters for " ^ s_type_path path) p; + let tparams = List.map (fun t -> + match t with + | TPExpr e -> + let name = (match fst e with + | EConst (String s) -> "S" ^ s + | EConst (Int i) -> "I" ^ i + | EConst (Float f) -> "F" ^ f + | _ -> "Expr" + ) in + let c = mk_class null_module ([],name) p (pos e) in + c.cl_kind <- KExpr e; + TInst (c,[]) + | TPType t -> load_complex_type ctx true p t + ) t.tparams in + let rec loop tl1 tl2 is_rest = match tl1,tl2 with + | t :: tl1,(name,t2) :: tl2 -> + let check_const c = + let is_expression = (match t with TInst ({ cl_kind = KExpr _ },_) -> true | _ -> false) in + let expects_expression = name = "Const" || Meta.has Meta.Const c.cl_meta in + let accepts_expression = name = "Rest" in + if is_expression then begin + if not expects_expression && not accepts_expression then + error "Constant value unexpected here" p + end else if expects_expression then + error "Type parameter is expected to be a constant value" p + in + let is_rest = is_rest || name = "Rest" && is_generic_build in + let t = match follow t2 with + | TInst ({ cl_kind = KTypeParameter [] } as c, []) when not is_generic -> + check_const c; + t + | TInst (c,[]) -> + check_const c; + let r = exc_protect ctx (fun r -> + r := (fun() -> t); + delay ctx PCheckConstraint (fun() -> check_param_constraints ctx types t tparams c p); + t + ) "constraint" in + delay ctx PForce (fun () -> ignore(!r())); + TLazy r + | _ -> assert false + in + t :: loop tl1 tl2 is_rest + | [],[] -> + [] + | [],["Rest",_] when is_generic_build -> + [] + | [],(_,t) :: tl when ctx.com.display.dms_error_policy = EPIgnore -> + t :: loop [] tl is_rest + | [],_ -> + error ("Not enough type parameters for " ^ s_type_path path) p + | t :: tl,[] -> + if is_rest then + t :: loop tl [] true + else + error ("Too many parameters for " ^ s_type_path path) p + in + let params = loop tparams types false in + f params + end + in + if allow_display then Display.DisplayEmitter.check_display_type ctx t pn; + t + +(* + build an instance from a complex type +*) +and load_complex_type ctx allow_display p (t,pn) = + let p = pselect pn p in + match t with + | CTParent t -> load_complex_type ctx allow_display p t + | CTPath t -> load_instance ~allow_display ctx (t,pn) false p + | CTOptional _ -> error "Optional type not allowed here" p + | CTExtend (tl,l) -> + (match load_complex_type ctx allow_display p (CTAnonymous l,p) with + | TAnon a as ta -> + let is_redefined cf1 a2 = + try + let cf2 = PMap.find cf1.cf_name a2.a_fields in + let st = s_type (print_context()) in + if not (type_iseq cf1.cf_type cf2.cf_type) then begin + display_error ctx ("Cannot redefine field " ^ cf1.cf_name ^ " with different type") p; + display_error ctx ("First type was " ^ (st cf1.cf_type)) cf1.cf_pos; + error ("Second type was " ^ (st cf2.cf_type)) cf2.cf_pos + end else + true + with Not_found -> + false + in + let mk_extension t = + match follow t with + | TInst ({cl_kind = KTypeParameter _},_) -> + error "Cannot structurally extend type parameters" p + | TMono _ -> + error "Loop found in cascading signatures definitions. Please change order/import" p + | TAnon a2 -> + PMap.iter (fun _ cf -> ignore(is_redefined cf a2)) a.a_fields; + TAnon { a_fields = (PMap.foldi PMap.add a.a_fields a2.a_fields); a_status = ref (Extend [t]); } + | _ -> error "Can only extend structures" p + in + let loop t = match follow t with + | TAnon a2 -> + PMap.iter (fun f cf -> + if not (is_redefined cf a) then + a.a_fields <- PMap.add f cf a.a_fields + ) a2.a_fields + | _ -> + error "Can only extend structures" p + in + let il = List.map (fun (t,_) -> load_instance ctx ~allow_display (t,pn) false p) tl in + let tr = ref None in + let t = TMono tr in + let r = exc_protect ctx (fun r -> + r := (fun _ -> t); + tr := Some (match il with + | [i] -> + mk_extension i + | _ -> + List.iter loop il; + a.a_status := Extend il; + ta); + t + ) "constraint" in + delay ctx PForce (fun () -> ignore(!r())); + TLazy r + | _ -> assert false) + | CTAnonymous l -> + let rec loop acc f = + let n = fst f.cff_name in + let p = f.cff_pos in + if PMap.mem n acc then error ("Duplicate field declaration : " ^ n) p; + let topt = function + | None -> error ("Explicit type required for field " ^ n) p + | Some t -> load_complex_type ctx allow_display p t + in + if n = "new" then ctx.com.warning "Structures with new are deprecated, use haxe.Constraints.Constructible instead" p; + let no_expr = function + | None -> () + | Some (_,p) -> error "Expression not allowed here" p + in + let pub = ref true in + let dyn = ref false in + let params = ref [] in + List.iter (fun a -> + match a with + | APublic -> () + | APrivate -> pub := false; + | ADynamic when (match f.cff_kind with FFun _ -> true | _ -> false) -> dyn := true + | AStatic | AOverride | AInline | ADynamic | AMacro -> error ("Invalid access " ^ Ast.s_access a) p + ) f.cff_access; + let t , access = (match f.cff_kind with + | FVar (Some (CTPath({tpackage=[];tname="Void"}),_), _) | FProp (_,_,Some (CTPath({tpackage=[];tname="Void"}),_),_) -> + error "Fields of type Void are not allowed in structures" p + | FVar (t, e) -> + no_expr e; + topt t, Var { v_read = AccNormal; v_write = AccNormal } + | FFun fd -> + params := (!type_function_params_rec) ctx fd (fst f.cff_name) p; + no_expr fd.f_expr; + let old = ctx.type_params in + ctx.type_params <- !params @ old; + let args = List.map (fun ((name,_),o,_,t,e) -> no_expr e; name, o, topt t) fd.f_args in + let t = TFun (args,topt fd.f_type), Method (if !dyn then MethDynamic else MethNormal) in + ctx.type_params <- old; + t + | FProp (i1,i2,t,e) -> + no_expr e; + let access (m,_) get = + match m with + | "null" -> AccNo + | "never" -> AccNever + | "default" -> AccNormal + | "dynamic" -> AccCall + | "get" when get -> AccCall + | "set" when not get -> AccCall + | x when get && x = "get_" ^ n -> AccCall + | x when not get && x = "set_" ^ n -> AccCall + | _ -> + error "Custom property access is no longer supported in Haxe 3" f.cff_pos; + in + let t = (match t with None -> error "Type required for structure property" p | Some t -> t) in + load_complex_type ctx allow_display p t, Var { v_read = access i1 true; v_write = access i2 false } + ) in + let t = if Meta.has Meta.Optional f.cff_meta then ctx.t.tnull t else t in + let cf = { + cf_name = n; + cf_type = t; + cf_pos = p; + cf_name_pos = (pos f.cff_name); + cf_public = !pub; + cf_kind = access; + cf_params = !params; + cf_expr = None; + cf_expr_unoptimized = None; + cf_doc = f.cff_doc; + cf_meta = f.cff_meta; + cf_overloads = []; + } in + init_meta_overloads ctx None cf; + if ctx.is_display_file then begin + Display.DisplayEmitter.check_display_metadata ctx cf.cf_meta; + Display.DisplayEmitter.maybe_display_field ctx (cf.cf_name_pos) cf; + end; + PMap.add n cf acc + in + mk_anon (List.fold_left loop PMap.empty l) + | CTFunction (args,r) -> + match args with + | [CTPath { tpackage = []; tparams = []; tname = "Void" },_] -> + TFun ([],load_complex_type ctx allow_display p r) + | _ -> + TFun (List.map (fun t -> + let t, opt = (match fst t with CTOptional t -> t, true | _ -> t,false) in + "",opt,load_complex_type ctx allow_display p t + ) args,load_complex_type ctx allow_display p r) + +and init_meta_overloads ctx co cf = + let overloads = ref [] in + let filter_meta m = match m with + | ((Meta.Overload | Meta.Value),_,_) -> false + | _ -> true + in + let cf_meta = List.filter filter_meta cf.cf_meta in + cf.cf_meta <- List.filter (fun m -> + match m with + | (Meta.Overload,[(EFunction (fname,f),p)],_) -> + if fname <> None then error "Function name must not be part of @:overload" p; + (match f.f_expr with Some (EBlock [], _) -> () | _ -> error "Overload must only declare an empty method body {}" p); + let old = ctx.type_params in + (match cf.cf_params with + | [] -> () + | l -> ctx.type_params <- List.filter (fun t -> not (List.mem t l)) ctx.type_params); + let params = (!type_function_params_rec) ctx f cf.cf_name p in + ctx.type_params <- params @ ctx.type_params; + let topt = function None -> error "Explicit type required" p | Some t -> load_complex_type ctx true p t in + let args = List.map (fun ((a,_),opt,_,t,_) -> a,opt,topt t) f.f_args in + let cf = { cf with cf_type = TFun (args,topt f.f_type); cf_params = params; cf_meta = cf_meta} in + generate_value_meta ctx.com co cf f.f_args; + overloads := cf :: !overloads; + ctx.type_params <- old; + false + | (Meta.Overload,[],_) when ctx.com.config.pf_overload -> + let topt (n,_,t) = match t with | TMono t when !t = None -> error ("Explicit type required for overload functions\nFor function argument '" ^ n ^ "'") cf.cf_pos | _ -> () in + (match follow cf.cf_type with + | TFun (args,_) -> List.iter topt args + | _ -> () (* could be a variable *)); + true + | (Meta.Overload,[],p) -> + error "This platform does not support this kind of overload declaration. Try @:overload(function()... {}) instead" p + | (Meta.Overload,_,p) -> + error "Invalid @:overload metadata format" p + | _ -> + true + ) cf.cf_meta; + cf.cf_overloads <- (List.rev !overloads) + +let hide_params ctx = + let old_m = ctx.m in + let old_type_params = ctx.type_params in + let old_deps = ctx.g.std.m_extra.m_deps in + ctx.m <- { + curmod = ctx.g.std; + module_types = []; + module_using = []; + module_globals = PMap.empty; + wildcard_packages = []; + module_imports = []; + }; + ctx.type_params <- []; + (fun() -> + ctx.m <- old_m; + ctx.type_params <- old_type_params; + (* restore dependencies that might be have been wronly inserted *) + ctx.g.std.m_extra.m_deps <- old_deps; + ) + +(* + load a type while ignoring the current imports or local types +*) +let load_core_type ctx name = + let show = hide_params ctx in + let t = load_instance ctx ({ tpackage = []; tname = name; tparams = []; tsub = None; },null_pos) false null_pos in + show(); + add_dependency ctx.m.curmod (match t with + | TInst (c,_) -> c.cl_module + | TType (t,_) -> t.t_module + | TAbstract (a,_) -> a.a_module + | TEnum (e,_) -> e.e_module + | _ -> assert false); + t + +let t_iterator ctx = + let show = hide_params ctx in + match load_type_def ctx null_pos { tpackage = []; tname = "Iterator"; tparams = []; tsub = None } with + | TTypeDecl t -> + show(); + add_dependency ctx.m.curmod t.t_module; + if List.length t.t_params <> 1 then assert false; + let pt = mk_mono() in + apply_params t.t_params [pt] t.t_type, pt + | _ -> + assert false + +(* + load either a type t or Null if not defined +*) +let load_type_hint ?(opt=false) ctx pcur t = + let t = match t with + | None -> mk_mono() + | Some (t,p) -> + try + load_complex_type ctx true pcur (t,p) + with Error(Module_not_found(([],name)),p) as exc -> + if Display.Diagnostics.is_diagnostics_run ctx then Display.ToplevelCollector.handle_unresolved_identifier ctx name p true; + (* Default to Dynamic in display mode *) + if ctx.com.display.dms_display then t_dynamic else raise exc + in + if opt then ctx.t.tnull t else t + +(* ---------------------------------------------------------------------- *) +(* Structure check *) + +let valid_redefinition ctx f1 t1 f2 t2 = (* child, parent *) + let valid t1 t2 = + Type.unify t1 t2; + if is_null t1 <> is_null t2 || ((follow t1) == t_dynamic && (follow t2) != t_dynamic) then raise (Unify_error [Cannot_unify (t1,t2)]); + in + let open OptimizerTexpr in + begin match PurityState.get_purity_from_meta f2.cf_meta,PurityState.get_purity_from_meta f1.cf_meta with + | PurityState.Pure,PurityState.MaybePure -> f1.cf_meta <- (Meta.Pure,[EConst(Ident "expect"),f2.cf_pos],null_pos) :: f1.cf_meta + | PurityState.ExpectPure p,PurityState.MaybePure -> f1.cf_meta <- (Meta.Pure,[EConst(Ident "expect"),p],null_pos) :: f1.cf_meta + | _ -> () + end; + let t1, t2 = (match f1.cf_params, f2.cf_params with + | [], [] -> t1, t2 + | l1, l2 when List.length l1 = List.length l2 -> + let to_check = ref [] in + let monos = List.map2 (fun (name,p1) (_,p2) -> + (match follow p1, follow p2 with + | TInst ({ cl_kind = KTypeParameter ct1 } as c1,pl1), TInst ({ cl_kind = KTypeParameter ct2 } as c2,pl2) -> + (match ct1, ct2 with + | [], [] -> () + | _, _ when List.length ct1 = List.length ct2 -> + (* if same constraints, they are the same type *) + let check monos = + List.iter2 (fun t1 t2 -> + try + let t1 = apply_params l1 monos (apply_params c1.cl_params pl1 t1) in + let t2 = apply_params l2 monos (apply_params c2.cl_params pl2 t2) in + type_eq EqStrict t1 t2 + with Unify_error l -> + raise (Unify_error (Unify_custom "Constraints differ" :: l)) + ) ct1 ct2 + in + to_check := check :: !to_check; + | _ -> + raise (Unify_error [Unify_custom "Different number of constraints"])) + | _ -> ()); + TInst (mk_class null_module ([],name) null_pos null_pos,[]) + ) l1 l2 in + List.iter (fun f -> f monos) !to_check; + apply_params l1 monos t1, apply_params l2 monos t2 + | _ -> + (* ignore type params, will create other errors later *) + t1, t2 + ) in + match f1.cf_kind,f2.cf_kind with + | Method m1, Method m2 when not (m1 = MethDynamic) && not (m2 = MethDynamic) -> + begin match follow t1, follow t2 with + | TFun (args1,r1) , TFun (args2,r2) -> ( + if not (List.length args1 = List.length args2) then raise (Unify_error [Unify_custom "Different number of function arguments"]); + try + List.iter2 (fun (n,o1,a1) (_,o2,a2) -> + if o1 <> o2 then raise (Unify_error [Not_matching_optional n]); + (try valid a2 a1 with Unify_error _ -> raise (Unify_error [Cannot_unify(a1,a2)])) + ) args1 args2; + valid r1 r2 + with Unify_error l -> + raise (Unify_error (Cannot_unify (t1,t2) :: l))) + | _ -> + assert false + end + | _,(Var { v_write = AccNo | AccNever }) -> + (* write variance *) + valid t1 t2 + | _,(Var { v_read = AccNo | AccNever }) -> + (* read variance *) + valid t2 t1 + | _ , _ -> + (* in case args differs, or if an interface var *) + type_eq EqStrict t1 t2; + if is_null t1 <> is_null t2 then raise (Unify_error [Cannot_unify (t1,t2)]) + +let copy_meta meta_src meta_target sl = + let meta = ref meta_target in + List.iter (fun (m,e,p) -> + if List.mem m sl then meta := (m,e,p) :: !meta + ) meta_src; + !meta + +let check_overriding ctx c = + match c.cl_super with + | None -> + (match c.cl_overrides with + | [] -> () + | i :: _ -> + display_error ctx ("Field " ^ i.cf_name ^ " is declared 'override' but doesn't override any field") i.cf_pos) + | _ when c.cl_extern && Meta.has Meta.CsNative c.cl_meta -> () (* -net-lib specific: do not check overrides on extern CsNative classes *) + | Some (csup,params) -> + PMap.iter (fun i f -> + let p = f.cf_pos in + let check_field f get_super_field is_overload = try + (if is_overload && not (Meta.has Meta.Overload f.cf_meta) then + display_error ctx ("Missing @:overload declaration for field " ^ i) p); + let t, f2 = get_super_field csup i in + (* allow to define fields that are not defined for this platform version in superclass *) + (match f2.cf_kind with + | Var { v_read = AccRequire _ } -> raise Not_found; + | _ -> ()); + if ctx.com.config.pf_overload && (Meta.has Meta.Overload f2.cf_meta && not (Meta.has Meta.Overload f.cf_meta)) then + display_error ctx ("Field " ^ i ^ " should be declared with @:overload since it was already declared as @:overload in superclass") p + else if not (List.memq f c.cl_overrides) then + display_error ctx ("Field " ^ i ^ " should be declared with 'override' since it is inherited from superclass " ^ s_type_path csup.cl_path) p + else if not f.cf_public && f2.cf_public then + display_error ctx ("Field " ^ i ^ " has less visibility (public/private) than superclass one") p + else (match f.cf_kind, f2.cf_kind with + | _, Method MethInline -> + display_error ctx ("Field " ^ i ^ " is inlined and cannot be overridden") p + | a, b when a = b -> () + | Method MethInline, Method MethNormal -> + () (* allow to redefine a method as inlined *) + | _ -> + display_error ctx ("Field " ^ i ^ " has different property access than in superclass") p); + if has_meta Meta.Final f2.cf_meta then display_error ctx ("Cannot override @:final method " ^ i) p; + try + let t = apply_params csup.cl_params params t in + valid_redefinition ctx f f.cf_type f2 t + with + Unify_error l -> + display_error ctx ("Field " ^ i ^ " overloads parent class with different or incomplete type") p; + display_error ctx ("Base field is defined here") f2.cf_pos; + display_error ctx (error_msg (Unify l)) p; + with + Not_found -> + if List.memq f c.cl_overrides then + let msg = if is_overload then + ("Field " ^ i ^ " is declared 'override' but no compatible overload was found") + else + ("Field " ^ i ^ " is declared 'override' but doesn't override any field") + in + display_error ctx msg p + in + if ctx.com.config.pf_overload && Meta.has Meta.Overload f.cf_meta then begin + let overloads = Overloads.get_overloads csup i in + List.iter (fun (t,f2) -> + (* check if any super class fields are vars *) + match f2.cf_kind with + | Var _ -> + display_error ctx ("A variable named '" ^ f2.cf_name ^ "' was already declared in a superclass") f.cf_pos + | _ -> () + ) overloads; + List.iter (fun f -> + (* find the exact field being overridden *) + check_field f (fun csup i -> + List.find (fun (t,f2) -> + Overloads.same_overload_args f.cf_type (apply_params csup.cl_params params t) f f2 + ) overloads + ) true + ) (f :: f.cf_overloads) + end else + check_field f (fun csup i -> + let _, t, f2 = raw_class_field (fun f -> f.cf_type) csup params i in + t, f2) false + ) c.cl_fields + +let class_field_no_interf c i = + try + let f = PMap.find i c.cl_fields in + f.cf_type , f + with Not_found -> + match c.cl_super with + | None -> + raise Not_found + | Some (c,tl) -> + (* rec over class_field *) + let _, t , f = raw_class_field (fun f -> f.cf_type) c tl i in + apply_params c.cl_params tl t , f + +let rec return_flow ctx e = + let error() = + display_error ctx (Printf.sprintf "Missing return: %s" (s_type (print_context()) ctx.ret)) e.epos; raise Exit + in + let return_flow = return_flow ctx in + let rec uncond e = match e.eexpr with + | TIf _ | TWhile _ | TSwitch _ | TTry _ | TFunction _ -> () + | TReturn _ | TThrow _ -> raise Exit + | _ -> Type.iter uncond e + in + let has_unconditional_flow e = try uncond e; false with Exit -> true in + match e.eexpr with + | TReturn _ | TThrow _ -> () + | TParenthesis e | TMeta(_,e) -> + return_flow e + | TBlock el -> + let rec loop = function + | [] -> error() + | [e] -> return_flow e + | e :: _ when has_unconditional_flow e -> () + | _ :: l -> loop l + in + loop el + | TIf (_,e1,Some e2) -> + return_flow e1; + return_flow e2; + | TSwitch (v,cases,Some e) -> + List.iter (fun (_,e) -> return_flow e) cases; + return_flow e + | TSwitch ({eexpr = TMeta((Meta.Exhaustive,_,_),_)},cases,None) -> + List.iter (fun (_,e) -> return_flow e) cases; + | TTry (e,cases) -> + return_flow e; + List.iter (fun (_,e) -> return_flow e) cases; + | TWhile({eexpr = (TConst (TBool true))},e,_) -> + (* a special case for "inifite" while loops that have no break *) + let rec loop e = match e.eexpr with + (* ignore nested loops to not accidentally get one of its breaks *) + | TWhile _ | TFor _ -> () + | TBreak -> error() + | _ -> Type.iter loop e + in + loop e + | _ -> + error() + +(* ---------------------------------------------------------------------- *) +(* PASS 1 & 2 : Module and Class Structure *) + +let is_generic_parameter ctx c = + (* first check field parameters, then class parameters *) + try + ignore (List.assoc (snd c.cl_path) ctx.curfield.cf_params); + Meta.has Meta.Generic ctx.curfield.cf_meta + with Not_found -> try + ignore(List.assoc (snd c.cl_path) ctx.type_params); + (match ctx.curclass.cl_kind with | KGeneric -> true | _ -> false); + with Not_found -> + false + +let type_function_arg_value ctx t c do_display = + match c with + | None -> None + | Some e -> + let p = pos e in + let e = if do_display then Display.ExprPreprocessing.process_expr ctx.com e else e in + let e = ctx.g.do_optimize ctx (type_expr ctx e (WithType t)) in + unify ctx e.etype t p; + let rec loop e = match e.eexpr with + | TConst c -> Some c + | TCast(e,None) -> loop e + | _ -> + if not ctx.com.display.dms_display || ctx.com.display.dms_inline && ctx.com.display.dms_error_policy = EPCollect then + display_error ctx "Parameter default value should be constant" p; + None + in + loop e + +(**** strict meta ****) +let get_native_repr md pos = + let path, meta = match md with + | TClassDecl cl -> cl.cl_path, cl.cl_meta + | TEnumDecl e -> e.e_path, e.e_meta + | TTypeDecl t -> t.t_path, t.t_meta + | TAbstractDecl a -> a.a_path, a.a_meta + in + let rec loop acc = function + | (Meta.JavaCanonical,[EConst(String pack),_; EConst(String name),_],_) :: _ -> + ExtString.String.nsplit pack ".", name + | (Meta.Native,[EConst(String name),_],_) :: meta -> + loop (Ast.parse_path name) meta + | _ :: meta -> + loop acc meta + | [] -> + acc + in + let pack, name = loop path meta in + match pack with + | [] -> + (EConst(Ident(name)), pos) + | hd :: tl -> + let rec loop pack expr = match pack with + | hd :: tl -> + loop tl (EField(expr,hd),pos) + | [] -> + (EField(expr,name),pos) + in + loop tl (EConst(Ident(hd)),pos) + +let rec process_meta_argument ?(toplevel=true) ctx expr = match expr.eexpr with + | TField(e,f) -> + (EField(process_meta_argument ~toplevel:false ctx e,field_name f),expr.epos) + | TConst(TInt i) -> + (EConst(Int (Int32.to_string i)), expr.epos) + | TConst(TFloat f) -> + (EConst(Float f), expr.epos) + | TConst(TString s) -> + (EConst(String s), expr.epos) + | TConst TNull -> + (EConst(Ident "null"), expr.epos) + | TConst(TBool b) -> + (EConst(Ident (string_of_bool b)), expr.epos) + | TCast(e,_) | TMeta(_,e) | TParenthesis(e) -> + process_meta_argument ~toplevel ctx e + | TTypeExpr md when toplevel -> + let p = expr.epos in + if ctx.com.platform = Cs then + (ECall( (EConst(Ident "typeof"), p), [get_native_repr md expr.epos] ), p) + else + (EField(get_native_repr md expr.epos, "class"), p) + | TTypeExpr md -> + get_native_repr md expr.epos + | _ -> + display_error ctx "This expression is too complex to be a strict metadata argument" expr.epos; + (EConst(Ident "null"), expr.epos) + +let make_meta ctx texpr extra = + match texpr.eexpr with + | TNew(c,_,el) -> + ECall(get_native_repr (TClassDecl c) texpr.epos, (List.map (process_meta_argument ctx) el) @ extra), texpr.epos + | TTypeExpr(md) -> + ECall(get_native_repr md texpr.epos, extra), texpr.epos + | _ -> + display_error ctx "Unexpected expression" texpr.epos; assert false + +let field_to_type_path ctx e = + let rec loop e pack name = match e with + | EField(e,f),p when Char.lowercase (String.get f 0) <> String.get f 0 -> (match name with + | [] | _ :: [] -> + loop e pack (f :: name) + | _ -> (* too many name paths *) + display_error ctx ("Unexpected " ^ f) p; + raise Exit) + | EField(e,f),_ -> + loop e (f :: pack) name + | EConst(Ident f),_ -> + let pack, name, sub = match name with + | [] -> + let fchar = String.get f 0 in + if Char.uppercase fchar = fchar then + pack, f, None + else begin + display_error ctx "A class name must start with an uppercase character" (snd e); + raise Exit + end + | [name] -> + f :: pack, name, None + | [name; sub] -> + f :: pack, name, Some sub + | _ -> + assert false + in + { tpackage=pack; tname=name; tparams=[]; tsub=sub } + | _,pos -> + display_error ctx "Unexpected expression when building strict meta" pos; + raise Exit + in + loop e [] [] + +let handle_fields ctx fields_to_check with_type_expr = + List.map (fun ((name,_),expr) -> + let pos = snd expr in + let field = (EField(with_type_expr,name), pos) in + let fieldexpr = (EConst(Ident name),pos) in + let left_side = match ctx.com.platform with + | Cs -> field + | Java -> (ECall(field,[]),pos) + | _ -> assert false + in + + let left = type_expr ctx left_side NoValue in + let right = type_expr ctx expr (WithType left.etype) in + unify ctx left.etype right.etype (snd expr); + (EBinop(Ast.OpAssign,fieldexpr,process_meta_argument ctx right), pos) + ) fields_to_check + +let get_strict_meta ctx params pos = + let pf = ctx.com.platform in + let changed_expr, fields_to_check, ctype = match params with + | [ECall(ef, el),p] -> + (* check last argument *) + let el, fields = match List.rev el with + | (EObjectDecl(decl),_) :: el -> + List.rev el, decl + | _ -> + el, [] + in + let tpath = field_to_type_path ctx ef in + if pf = Cs then + (ENew((tpath,snd ef), el), p), fields, CTPath tpath + else + ef, fields, CTPath tpath + | [EConst(Ident i),p as expr] -> + let tpath = { tpackage=[]; tname=i; tparams=[]; tsub=None } in + if pf = Cs then + (ENew((tpath,p), []), p), [], CTPath tpath + else + expr, [], CTPath tpath + | [ (EField(_),p as field) ] -> + let tpath = field_to_type_path ctx field in + if pf = Cs then + (ENew((tpath,p), []), p), [], CTPath tpath + else + field, [], CTPath tpath + | _ -> + display_error ctx "A @:strict metadata must contain exactly one parameter. Please check the documentation for more information" pos; + raise Exit + in + let texpr = type_expr ctx changed_expr NoValue in + let with_type_expr = (ECheckType( (EConst (Ident "null"), pos), (ctype,null_pos) ), pos) in + let extra = handle_fields ctx fields_to_check with_type_expr in + Meta.Meta, [make_meta ctx texpr extra], pos + +let check_strict_meta ctx metas = + let pf = ctx.com.platform in + match pf with + | Cs | Java -> + let ret = ref [] in + List.iter (function + | Meta.Strict,params,pos -> (try + ret := get_strict_meta ctx params pos :: !ret + with | Exit -> ()) + | _ -> () + ) metas; + !ret + | _ -> [] + +(**** end of strict meta handling *****) + +let add_constructor ctx c force_constructor p = + match c.cl_constructor, c.cl_super with + | None, Some ({ cl_constructor = Some cfsup } as csup,cparams) when not c.cl_extern -> + let cf = { + cfsup with + cf_pos = p; + cf_meta = List.filter (fun (m,_,_) -> m = Meta.CompilerGenerated) cfsup.cf_meta; + cf_doc = None; + cf_expr = None; + } in + let r = exc_protect ctx (fun r -> + let t = mk_mono() in + r := (fun() -> t); + let ctx = { ctx with + curfield = cf; + pass = PTypeField; + } in + ignore (follow cfsup.cf_type); (* make sure it's typed *) + (if ctx.com.config.pf_overload then List.iter (fun cf -> ignore (follow cf.cf_type)) cf.cf_overloads); + let map_arg (v,def) = + (* + let's optimize a bit the output by not always copying the default value + into the inherited constructor when it's not necessary for the platform + *) + match ctx.com.platform, def with + | _, Some _ when not ctx.com.config.pf_static -> v, (Some TNull) + | Flash, Some (TString _) -> v, (Some TNull) + | Cpp, Some (TString _) -> v, def + | Cpp, Some _ -> { v with v_type = ctx.t.tnull v.v_type }, (Some TNull) + | _ -> v, def + in + let args = (match cfsup.cf_expr with + | Some { eexpr = TFunction f } -> + List.map map_arg f.tf_args + | _ -> + let values = get_value_meta cfsup.cf_meta in + match follow cfsup.cf_type with + | TFun (args,_) -> + List.map (fun (n,o,t) -> + let def = try type_function_arg_value ctx t (Some (PMap.find n values)) false with Not_found -> if o then Some TNull else None in + map_arg (alloc_var n (if o then ctx.t.tnull t else t) p,def) (* TODO: var pos *) + ) args + | _ -> assert false + ) in + let p = c.cl_pos in + let vars = List.map (fun (v,def) -> alloc_var v.v_name (apply_params csup.cl_params cparams v.v_type) v.v_pos, def) args in + let super_call = mk (TCall (mk (TConst TSuper) (TInst (csup,cparams)) p,List.map (fun (v,_) -> mk (TLocal v) v.v_type p) vars)) ctx.t.tvoid p in + let constr = mk (TFunction { + tf_args = vars; + tf_type = ctx.t.tvoid; + tf_expr = super_call; + }) (TFun (List.map (fun (v,c) -> v.v_name, c <> None, v.v_type) vars,ctx.t.tvoid)) p in + cf.cf_expr <- Some constr; + cf.cf_type <- t; + unify ctx t constr.etype p; + t + ) "add_constructor" in + cf.cf_type <- TLazy r; + c.cl_constructor <- Some cf; + delay ctx PForce (fun() -> ignore((!r)())); + | None,_ when force_constructor -> + let constr = mk (TFunction { + tf_args = []; + tf_type = ctx.t.tvoid; + tf_expr = mk (TBlock []) ctx.t.tvoid p; + }) (tfun [] ctx.t.tvoid) p in + let cf = mk_field "new" constr.etype p null_pos in + cf.cf_expr <- Some constr; + cf.cf_type <- constr.etype; + cf.cf_meta <- [Meta.CompilerGenerated,[],null_pos]; + cf.cf_kind <- Method MethNormal; + c.cl_constructor <- Some cf; + | _ -> + (* nothing to do *) + () + +let check_struct_init_constructor ctx c p = match c.cl_constructor with + | Some _ -> + () + | None -> + let params = List.map snd c.cl_params in + let ethis = mk (TConst TThis) (TInst(c,params)) p in + let args,el,tl = List.fold_left (fun (args,el,tl) cf -> match cf.cf_kind with + | Var _ -> + let opt = Meta.has Meta.Optional cf.cf_meta in + let t = if opt then ctx.t.tnull cf.cf_type else cf.cf_type in + let v = alloc_var cf.cf_name t p in + let ef = mk (TField(ethis,FInstance(c,params,cf))) t p in + let ev = mk (TLocal v) v.v_type p in + let e = mk (TBinop(OpAssign,ef,ev)) ev.etype p in + (v,None) :: args,e :: el,(cf.cf_name,opt,t) :: tl + | Method _ -> + args,el,tl + ) ([],[],[]) (List.rev c.cl_ordered_fields) in + let tf = { + tf_args = args; + tf_type = ctx.t.tvoid; + tf_expr = mk (TBlock el) ctx.t.tvoid p + } in + let e = mk (TFunction tf) (TFun(tl,ctx.t.tvoid)) p in + let cf = mk_field "new" e.etype p null_pos in + cf.cf_expr <- Some e; + cf.cf_type <- e.etype; + cf.cf_meta <- [Meta.CompilerGenerated,[],null_pos]; + cf.cf_kind <- Method MethNormal; + c.cl_constructor <- Some cf + +module Inheritance = struct + let check_extends ctx c t p = match follow t with + | TInst ({ cl_path = [],"Array"; cl_extern = basic_extern },_) + | TInst ({ cl_path = [],"String"; cl_extern = basic_extern },_) + | TInst ({ cl_path = [],"Date"; cl_extern = basic_extern },_) + | TInst ({ cl_path = [],"Xml"; cl_extern = basic_extern },_) when not (c.cl_extern && basic_extern) -> + error "Cannot extend basic class" p; + | TInst (csup,params) -> + if is_parent c csup then error "Recursive class" p; + begin match csup.cl_kind with + | KTypeParameter _ when not (is_generic_parameter ctx csup) -> error "Cannot extend non-generic type parameters" p + | _ -> csup,params + end + | _ -> error "Should extend by using a class" p + + let rec check_interface ctx c intf params = + let p = c.cl_pos in + let rec check_field i f = + (if ctx.com.config.pf_overload then + List.iter (function + | f2 when f != f2 -> + check_field i f2 + | _ -> ()) f.cf_overloads); + let is_overload = ref false in + try + let t2, f2 = class_field_no_interf c i in + let t2, f2 = + if ctx.com.config.pf_overload && (f2.cf_overloads <> [] || Meta.has Meta.Overload f2.cf_meta) then + let overloads = Overloads.get_overloads c i in + is_overload := true; + let t = (apply_params intf.cl_params params f.cf_type) in + List.find (fun (t1,f1) -> Overloads.same_overload_args t t1 f f1) overloads + else + t2, f2 + in + if ctx.com.display.dms_collect_data then begin + let h = ctx.com.display_information in + h.interface_field_implementations <- (intf,f,c,Some f2) :: h.interface_field_implementations; + end; + ignore(follow f2.cf_type); (* force evaluation *) + let p = (match f2.cf_expr with None -> p | Some e -> e.epos) in + let mkind = function + | MethNormal | MethInline -> 0 + | MethDynamic -> 1 + | MethMacro -> 2 + in + if f.cf_public && not f2.cf_public && not (Meta.has Meta.CompilerGenerated f.cf_meta) then + display_error ctx ("Field " ^ i ^ " should be public as requested by " ^ s_type_path intf.cl_path) p + else if not (unify_kind f2.cf_kind f.cf_kind) || not (match f.cf_kind, f2.cf_kind with Var _ , Var _ -> true | Method m1, Method m2 -> mkind m1 = mkind m2 | _ -> false) then + display_error ctx ("Field " ^ i ^ " has different property access than in " ^ s_type_path intf.cl_path ^ " (" ^ s_kind f2.cf_kind ^ " should be " ^ s_kind f.cf_kind ^ ")") p + else try + valid_redefinition ctx f2 t2 f (apply_params intf.cl_params params f.cf_type) + with + Unify_error l -> + if not (Meta.has Meta.CsNative c.cl_meta && c.cl_extern) then begin + display_error ctx ("Field " ^ i ^ " has different type than in " ^ s_type_path intf.cl_path) p; + display_error ctx ("Interface field is defined here") f.cf_pos; + display_error ctx (error_msg (Unify l)) p; + end + with + | Not_found when not c.cl_interface -> + let msg = if !is_overload then + let ctx = print_context() in + let args = match follow f.cf_type with | TFun(args,_) -> String.concat ", " (List.map (fun (n,o,t) -> (if o then "?" else "") ^ n ^ " : " ^ (s_type ctx t)) args) | _ -> assert false in + "No suitable overload for " ^ i ^ "( " ^ args ^ " ), as needed by " ^ s_type_path intf.cl_path ^ " was found" + else + ("Field " ^ i ^ " needed by " ^ s_type_path intf.cl_path ^ " is missing") + in + display_error ctx msg p + | Not_found -> () + in + PMap.iter check_field intf.cl_fields; + List.iter (fun (i2,p2) -> + check_interface ctx c i2 (List.map (apply_params intf.cl_params params) p2) + ) intf.cl_implements + + let check_interfaces ctx c = + match c.cl_path with + | "Proxy" :: _ , _ -> () + | _ when c.cl_extern && Meta.has Meta.CsNative c.cl_meta -> () + | _ -> + List.iter (fun (intf,params) -> check_interface ctx c intf params) c.cl_implements + + let set_heritance ctx c herits p = + let is_lib = Meta.has Meta.LibType c.cl_meta in + let ctx = { ctx with curclass = c; type_params = c.cl_params; } in + let old_meta = c.cl_meta in + let process_meta csup = + List.iter (fun m -> + match m with + | Meta.Final, _, _ -> if not (Meta.has Meta.Hack c.cl_meta || (match c.cl_kind with KTypeParameter _ -> true | _ -> false)) then error "Cannot extend a final class" p; + | Meta.AutoBuild, el, p -> c.cl_meta <- (Meta.Build,el,null_pos) :: m :: c.cl_meta + | _ -> () + ) csup.cl_meta + in + let check_cancel_build csup = + match csup.cl_build() with + | Built -> () + | state -> + (* for macros reason, our super class is not yet built - see #2177 *) + (* let's reset our build and delay it until we are done *) + c.cl_meta <- old_meta; + raise (Build_canceled state) + in + let has_interf = ref false in + (* + resolve imports before calling build_inheritance, since it requires full paths. + that means that typedefs are not working, but that's a fair limitation + *) + let resolve_imports (t,p) = + match t.tpackage with + | _ :: _ -> t,p + | [] -> + try + let path_matches lt = snd (t_path lt) = t.tname in + let lt = try + List.find path_matches ctx.m.curmod.m_types + with Not_found -> + let t,pi = List.find (fun (lt,_) -> path_matches lt) ctx.m.module_types in + Display.ImportHandling.mark_import_position ctx.com pi; + t + in + { t with tpackage = fst (t_path lt) },p + with + Not_found -> t,p + in + let herits = ExtList.List.filter_map (function + | HExtends t -> Some(true,resolve_imports t) + | HImplements t -> Some(false,resolve_imports t) + | t -> None + ) herits in + let herits = List.filter (ctx.g.do_inherit ctx c p) herits in + (* Pass 1: Check and set relations *) + let check_herit t is_extends = + if is_extends then begin + if c.cl_super <> None then error "Cannot extend several classes" p; + let csup,params = check_extends ctx c t p in + if c.cl_interface then begin + if not csup.cl_interface then error "Cannot extend by using a class" p; + c.cl_implements <- (csup,params) :: c.cl_implements; + if not !has_interf then begin + if not is_lib then delay ctx PForce (fun() -> check_interfaces ctx c); + has_interf := true; + end + end else begin + if csup.cl_interface then error "Cannot extend by using an interface" p; + c.cl_super <- Some (csup,params) + end; + (fun () -> + check_cancel_build csup; + process_meta csup; + ) + end else begin match follow t with + | TInst ({ cl_path = [],"ArrayAccess"; cl_extern = true; },[t]) -> + if c.cl_array_access <> None then error "Duplicate array access" p; + c.cl_array_access <- Some t; + (fun () -> ()) + | TInst (intf,params) -> + if is_parent c intf then error "Recursive class" p; + if c.cl_interface then error "Interfaces cannot implement another interface (use extends instead)" p; + if not intf.cl_interface then error "You can only implement an interface" p; + c.cl_implements <- (intf, params) :: c.cl_implements; + if not !has_interf && not is_lib && not (Meta.has (Meta.Custom "$do_not_check_interf") c.cl_meta) then begin + delay ctx PForce (fun() -> check_interfaces ctx c); + has_interf := true; + end; + (fun () -> + check_cancel_build intf; + process_meta intf; + ) + | TDynamic t -> + if c.cl_dynamic <> None then error "Cannot have several dynamics" p; + c.cl_dynamic <- Some t; + (fun () -> ()) + | _ -> + error "Should implement by using an interface" p + end + in + let fl = ExtList.List.filter_map (fun (is_extends,t) -> + try + let t = load_instance ~allow_display:true ctx t false p in + Some (check_herit t is_extends) + with Error(Module_not_found(([],name)),p) when ctx.com.display.dms_display -> + if Display.Diagnostics.is_diagnostics_run ctx then Display.ToplevelCollector.handle_unresolved_identifier ctx name p true; + None + ) herits in + fl +end + +let rec type_type_param ?(enum_constructor=false) ctx path get_params p tp = + let n = fst tp.tp_name in + let c = mk_class ctx.m.curmod (fst path @ [snd path],n) (pos tp.tp_name) (pos tp.tp_name) in + c.cl_params <- type_type_params ctx c.cl_path get_params p tp.tp_params; + c.cl_kind <- KTypeParameter []; + c.cl_meta <- tp.Ast.tp_meta; + if enum_constructor then c.cl_meta <- (Meta.EnumConstructorParam,[],null_pos) :: c.cl_meta; + let t = TInst (c,List.map snd c.cl_params) in + if ctx.is_display_file && Display.is_display_position (pos tp.tp_name) then + Display.DisplayEmitter.display_type ctx.com.display t (pos tp.tp_name); + match tp.tp_constraints with + | [] -> + n, t + | _ -> + let r = exc_protect ctx (fun r -> + r := (fun _ -> t); + let ctx = { ctx with type_params = ctx.type_params @ get_params() } in + let constr = List.map (load_complex_type ctx true p) tp.tp_constraints in + (* check against direct recursion *) + let rec loop t = + match follow t with + | TInst (c2,_) when c == c2 -> error "Recursive constraint parameter is not allowed" p + | TInst ({ cl_kind = KTypeParameter cl },_) -> + List.iter loop cl + | _ -> + () + in + List.iter loop constr; + c.cl_kind <- KTypeParameter constr; + t + ) "constraint" in + delay ctx PForce (fun () -> ignore(!r())); + n, TLazy r + +and type_type_params ?(enum_constructor=false) ctx path get_params p tpl = + let names = ref [] in + List.map (fun tp -> + if List.exists (fun name -> name = fst tp.tp_name) !names then display_error ctx ("Duplicate type parameter name: " ^ fst tp.tp_name) (pos tp.tp_name); + names := (fst tp.tp_name) :: !names; + type_type_param ~enum_constructor ctx path get_params p tp + ) tpl + +let type_function_params ctx fd fname p = + let params = ref [] in + params := type_type_params ctx ([],fname) (fun() -> !params) p fd.f_params; + !params + +let type_function ctx args ret fmode f do_display p = + let locals = save_locals ctx in + let fargs = List.map2 (fun (n,c,t) ((_,pn),_,m,_,_) -> + if n.[0] = '$' then error "Function argument names starting with a dollar are not allowed" p; + let c = type_function_arg_value ctx t c do_display in + let v,c = add_local ctx n t pn, c in + v.v_meta <- m; + if do_display && Display.is_display_position pn then + Display.DisplayEmitter.display_variable ctx.com.display v pn; + if n = "this" then v.v_meta <- (Meta.This,[],null_pos) :: v.v_meta; + v,c + ) args f.f_args in + let old_ret = ctx.ret in + let old_fun = ctx.curfun in + let old_opened = ctx.opened in + ctx.curfun <- fmode; + ctx.ret <- ret; + ctx.opened <- []; + let e = match f.f_expr with None -> error "Function body required" p | Some e -> e in + let e = if not do_display then + type_expr ctx e NoValue + else begin + let e = Display.ExprPreprocessing.process_expr ctx.com e in + try + if Common.defined ctx.com Define.NoCOpt then raise Exit; + type_expr ctx (Optimizer.optimize_completion_expr e) NoValue + with + | Parser.TypePath (_,None,_) | Exit -> + type_expr ctx e NoValue + | Display.DisplayType (t,_,_) | Display.DisplaySignatures ([(t,_)],_) when (match follow t with TMono _ -> true | _ -> false) -> + type_expr ctx (if ctx.com.display.dms_kind = DMToplevel then Display.ExprPreprocessing.find_enclosing ctx.com e else e) NoValue + end in + let e = match e.eexpr with + | TMeta((Meta.MergeBlock,_,_), ({eexpr = TBlock el} as e1)) -> e1 + | _ -> e + in + let has_return e = + let rec loop e = + match e.eexpr with + | TReturn (Some _) -> raise Exit + | TFunction _ -> () + | _ -> Type.iter loop e + in + try loop e; false with Exit -> true + in + begin match follow ret with + | TAbstract({a_path=[],"Void"},_) -> () + (* We have to check for the presence of return expressions here because + in the case of Dynamic ctx.ret is still a monomorph. If we indeed + don't have a return expression we can link the monomorph to Void. We + can _not_ use type_iseq to avoid the Void check above because that + would turn Dynamic returns to Void returns. *) + | TMono t when not (has_return e) -> ignore(link t ret ctx.t.tvoid) + | _ when ctx.com.display.dms_error_policy = EPIgnore -> () + | _ -> (try return_flow ctx e with Exit -> ()) + end; + let rec loop e = + match e.eexpr with + | TCall ({ eexpr = TConst TSuper },_) -> raise Exit + | TFunction _ -> () + | _ -> Type.iter loop e + in + let has_super_constr() = + match ctx.curclass.cl_super with + | None -> + None + | Some (csup,tl) -> + try + let _,cf = get_constructor (fun f->f.cf_type) csup in + Some (Meta.has Meta.CompilerGenerated cf.cf_meta,TInst(csup,tl)) + with Not_found -> + None + in + let e = if fmode <> FunConstructor then + e + else match has_super_constr() with + | Some (was_forced,t_super) -> + (try + loop e; + if was_forced then + let e_super = mk (TConst TSuper) t_super e.epos in + let e_super_call = mk (TCall(e_super,[])) ctx.t.tvoid e.epos in + concat e_super_call e + else begin + display_error ctx "Missing super constructor call" p; + e + end + with + Exit -> e); + | None -> + e + in + locals(); + let e = match ctx.curfun, ctx.vthis with + | (FunMember|FunConstructor), Some v -> + let ev = mk (TVar (v,Some (mk (TConst TThis) ctx.tthis p))) ctx.t.tvoid p in + (match e.eexpr with + | TBlock l -> { e with eexpr = TBlock (ev::l) } + | _ -> mk (TBlock [ev;e]) e.etype p) + | _ -> e + in + List.iter (fun r -> r := Closed) ctx.opened; + ctx.ret <- old_ret; + ctx.curfun <- old_fun; + ctx.opened <- old_opened; + e , fargs + +let load_core_class ctx c = + let ctx2 = (match ctx.g.core_api with + | None -> + let com2 = Common.clone ctx.com in + com2.defines <- PMap.empty; + Common.define com2 Define.CoreApi; + Common.define com2 Define.Sys; + if ctx.in_macro then Common.define com2 Define.Macro; + com2.class_path <- ctx.com.std_path; + let ctx2 = ctx.g.do_create com2 in + ctx.g.core_api <- Some ctx2; + ctx2 + | Some c -> + c + ) in + let tpath = match c.cl_kind with + | KAbstractImpl a -> { tpackage = fst a.a_path; tname = snd a.a_path; tparams = []; tsub = None; } + | _ -> { tpackage = fst c.cl_path; tname = snd c.cl_path; tparams = []; tsub = None; } + in + let t = load_instance ctx2 (tpath,c.cl_pos) true c.cl_pos in + flush_pass ctx2 PFinal "core_final"; + match t with + | TInst (ccore,_) | TAbstract({a_impl = Some ccore}, _) -> + ccore + | _ -> + assert false + +let init_core_api ctx c = + let ccore = load_core_class ctx c in + begin try + List.iter2 (fun (n1,t1) (n2,t2) -> match follow t1, follow t2 with + | TInst({cl_kind = KTypeParameter l1},_),TInst({cl_kind = KTypeParameter l2},_) -> + begin try + List.iter2 (fun t1 t2 -> type_eq EqCoreType t2 t1) l1 l2 + with + | Invalid_argument _ -> + error "Type parameters must have the same number of constraints as core type" c.cl_pos + | Unify_error l -> + display_error ctx ("Type parameter " ^ n2 ^ " has different constraint than in core type") c.cl_pos; + display_error ctx (error_msg (Unify l)) c.cl_pos + end + | t1,t2 -> + Printf.printf "%s %s" (s_type (print_context()) t1) (s_type (print_context()) t2); + assert false + ) ccore.cl_params c.cl_params; + with Invalid_argument _ -> + error "Class must have the same number of type parameters as core type" c.cl_pos + end; + (match c.cl_doc with + | None -> c.cl_doc <- ccore.cl_doc + | Some _ -> ()); + let compare_fields f f2 = + let p = (match f2.cf_expr with None -> c.cl_pos | Some e -> e.epos) in + (try + type_eq EqCoreType (apply_params ccore.cl_params (List.map snd c.cl_params) f.cf_type) f2.cf_type + with Unify_error l -> + display_error ctx ("Field " ^ f.cf_name ^ " has different type than in core type") p; + display_error ctx (error_msg (Unify l)) p); + if f2.cf_public <> f.cf_public then error ("Field " ^ f.cf_name ^ " has different visibility than core type") p; + (match f2.cf_doc with + | None -> f2.cf_doc <- f.cf_doc + | Some _ -> ()); + if f2.cf_kind <> f.cf_kind then begin + match f2.cf_kind, f.cf_kind with + | Method MethInline, Method MethNormal -> () (* allow to add 'inline' *) + | Method MethNormal, Method MethInline -> () (* allow to disable 'inline' *) + | _ -> + error ("Field " ^ f.cf_name ^ " has different property access than core type") p; + end; + (match follow f.cf_type, follow f2.cf_type with + | TFun (pl1,_), TFun (pl2,_) -> + if List.length pl1 != List.length pl2 then error "Argument count mismatch" p; + List.iter2 (fun (n1,_,_) (n2,_,_) -> + if n1 <> n2 then error ("Method parameter name '" ^ n2 ^ "' should be '" ^ n1 ^ "'") p; + ) pl1 pl2; + | _ -> ()); + in + let check_fields fcore fl = + PMap.iter (fun i f -> + if not f.cf_public then () else + let f2 = try PMap.find f.cf_name fl with Not_found -> error ("Missing field " ^ i ^ " required by core type") c.cl_pos in + compare_fields f f2; + ) fcore; + PMap.iter (fun i f -> + let p = (match f.cf_expr with None -> c.cl_pos | Some e -> e.epos) in + if f.cf_public && not (Meta.has Meta.Hack f.cf_meta) && not (PMap.mem f.cf_name fcore) && not (List.memq f c.cl_overrides) then error ("Public field " ^ i ^ " is not part of core type") p; + ) fl; + in + check_fields ccore.cl_fields c.cl_fields; + check_fields ccore.cl_statics c.cl_statics; + (match ccore.cl_constructor, c.cl_constructor with + | None, None -> () + | Some { cf_public = false }, _ -> () + | Some f, Some f2 -> compare_fields f f2 + | None, Some { cf_public = false } -> () + | _ -> error "Constructor differs from core type" c.cl_pos) + +let check_global_metadata ctx meta f_add mpath tpath so = + let sl1 = full_dot_path mpath tpath in + let sl1,field_mode = match so with None -> sl1,false | Some s -> sl1 @ [s],true in + List.iter (fun (sl2,m,(recursive,to_types,to_fields)) -> + let add = ((field_mode && to_fields) || (not field_mode && to_types)) && (match_path recursive sl1 sl2) in + if add then f_add m + ) ctx.g.global_metadata; + if ctx.is_display_file then Display.DisplayEmitter.check_display_metadata ctx meta + +let patch_class ctx c fields = + let path = match c.cl_kind with + | KAbstractImpl a -> a.a_path + | _ -> c.cl_path + in + let h = (try Some (Hashtbl.find ctx.g.type_patches path) with Not_found -> None) in + match h with + | None -> fields + | Some (h,hcl) -> + c.cl_meta <- c.cl_meta @ hcl.tp_meta; + let rec loop acc = function + | [] -> acc + | f :: l -> + (* patch arguments types *) + (match f.cff_kind with + | FFun ff -> + let param (((n,pn),opt,m,_,e) as p) = + try + let t2 = (try Hashtbl.find h (("$" ^ (fst f.cff_name) ^ "__" ^ n),false) with Not_found -> Hashtbl.find h (("$" ^ n),false)) in + (n,pn), opt, m, (match t2.tp_type with None -> None | Some t -> Some (t,null_pos)), e + with Not_found -> + p + in + f.cff_kind <- FFun { ff with f_args = List.map param ff.f_args } + | _ -> ()); + (* other patches *) + match (try Some (Hashtbl.find h (fst f.cff_name,List.mem AStatic f.cff_access)) with Not_found -> None) with + | None -> loop (f :: acc) l + | Some { tp_remove = true } -> loop acc l + | Some p -> + f.cff_meta <- f.cff_meta @ p.tp_meta; + (match p.tp_type with + | None -> () + | Some t -> + f.cff_kind <- match f.cff_kind with + | FVar (_,e) -> FVar (Some (t,null_pos),e) + | FProp (get,set,_,eo) -> FProp (get,set,Some (t,null_pos),eo) + | FFun f -> FFun { f with f_type = Some (t,null_pos) }); + loop (f :: acc) l + in + List.rev (loop [] fields) + +let string_list_of_expr_path (e,p) = + try string_list_of_expr_path_raise (e,p) + with Exit -> error "Invalid path" p + +let build_enum_abstract ctx c a fields p = + List.iter (fun field -> + match field.cff_kind with + | FVar(ct,eo) when not (List.mem AStatic field.cff_access) -> + field.cff_access <- [AStatic; if (List.mem APrivate field.cff_access) then APrivate else APublic]; + field.cff_meta <- (Meta.Enum,[],null_pos) :: (Meta.Impl,[],null_pos) :: field.cff_meta; + let ct = match ct with + | Some _ -> ct + | None -> Some (TExprToExpr.convert_type (TAbstract(a,List.map snd a.a_params)),null_pos) + in + begin match eo with + | None -> + if not c.cl_extern then error "Value required" field.cff_pos + else field.cff_kind <- FProp(("default",null_pos),("never",null_pos),ct,None) + | Some e -> + field.cff_access <- AInline :: field.cff_access; + let e = (ECast(e,None),(pos e)) in + field.cff_kind <- FVar(ct,Some e) + end + | _ -> + () + ) fields; + EVars [("",null_pos),Some (CTAnonymous fields,p),None],p + +let is_java_native_function meta = try + match Meta.get Meta.Native meta with + | (Meta.Native,[],_) -> true + | _ -> false + with | Not_found -> false + +let build_module_def ctx mt meta fvars context_init fbuild = + let loop (f_build,f_enum) = function + | Meta.Build,args,p -> (fun () -> + let epath, el = (match args with + | [ECall (epath,el),p] -> epath, el + | _ -> error "Invalid build parameters" p + ) in + let s = try String.concat "." (List.rev (string_list_of_expr_path epath)) with Error (_,p) -> error "Build call parameter must be a class path" p in + if ctx.in_macro then error "You cannot use @:build inside a macro : make sure that your type is not used in macro" p; + let old = ctx.g.get_build_infos in + ctx.g.get_build_infos <- (fun() -> Some (mt, List.map snd (t_infos mt).mt_params, fvars())); + context_init(); + let r = try apply_macro ctx MBuild s el p with e -> ctx.g.get_build_infos <- old; raise e in + ctx.g.get_build_infos <- old; + (match r with + | None -> error "Build failure" p + | Some e -> fbuild e) + ) :: f_build,f_enum + | Meta.Enum,_,p -> f_build,Some (fun () -> + begin match mt with + | TClassDecl ({cl_kind = KAbstractImpl a} as c) -> + context_init(); + let e = build_enum_abstract ctx c a (fvars()) p in + fbuild e; + | _ -> + () + end + ) + | _ -> + f_build,f_enum + in + (* let errors go through to prevent resume if build fails *) + let f_build,f_enum = List.fold_left loop ([],None) meta in + List.iter (fun f -> f()) (List.rev f_build); + (match f_enum with None -> () | Some f -> f()) + +module ClassInitializer = struct + type class_init_ctx = { + tclass : tclass; (* I don't trust ctx.curclass because it's mutable. *) + is_lib : bool; + is_native : bool; + is_core_api : bool; + is_class_debug : bool; + extends_public : bool; + abstract : tabstract option; + context_init : unit -> unit; + mutable delayed_expr : (typer * (unit -> t) ref option) list; + mutable force_constructor : bool; + } + + type field_kind = + | FKNormal + | FKConstructor + | FKInit + + type field_init_ctx = { + is_inline : bool; + is_static : bool; + is_override : bool; + is_extern : bool; + is_macro : bool; + is_abstract_member : bool; + is_display_field : bool; + is_field_debug : bool; + field_kind : field_kind; + mutable do_bind : bool; + mutable do_add : bool; + } + + let dump_class_context cctx = + Printer.s_record_fields "" [ + "tclass",Printer.s_tclass "\t" cctx.tclass; + "is_lib",string_of_bool cctx.is_lib; + "is_native",string_of_bool cctx.is_native; + "is_core_api",string_of_bool cctx.is_core_api; + "is_class_debug",string_of_bool cctx.is_class_debug; + "extends_public",string_of_bool cctx.extends_public; + "abstract",Printer.s_opt (Printer.s_tabstract "\t") cctx.abstract; + "force_constructor",string_of_bool cctx.force_constructor; + ] + + let s_field_kind = function + | FKNormal -> "FKNormal" + | FKConstructor -> "FKConstructor" + | FKInit -> "FKInit" + + let dump_field_context fctx = + Printer.s_record_fields "" [ + "is_inline",string_of_bool fctx.is_inline; + "is_static",string_of_bool fctx.is_static; + "is_override",string_of_bool fctx.is_override; + "is_extern",string_of_bool fctx.is_extern; + "is_macro",string_of_bool fctx.is_macro; + "is_abstract_member",string_of_bool fctx.is_abstract_member; + "is_display_field",string_of_bool fctx.is_display_field; + "is_field_debug",string_of_bool fctx.is_field_debug; + "field_kind",s_field_kind fctx.field_kind; + "do_bind",string_of_bool fctx.do_bind; + "do_add",string_of_bool fctx.do_add; + ] + + let create_class_context ctx c context_init p = + locate_macro_error := true; + incr stats.s_classes_built; + let abstract = match c.cl_kind with + | KAbstractImpl a -> Some a + | _ -> None + in + let ctx = { + ctx with + curclass = c; + type_params = c.cl_params; + pass = PBuildClass; + tthis = (match abstract with + | Some a -> + (match a.a_this with + | TMono r when !r = None -> TAbstract (a,List.map snd c.cl_params) + | t -> t) + | None -> TInst (c,List.map snd c.cl_params)); + on_error = (fun ctx msg ep -> + ctx.com.error msg ep; + (* macros expressions might reference other code, let's recall which class we are actually compiling *) + if !locate_macro_error && (ep.pfile <> c.cl_pos.pfile || ep.pmax < c.cl_pos.pmin || ep.pmin > c.cl_pos.pmax) then ctx.com.error "Defined in this class" c.cl_pos + ); + } in + (* a lib type will skip most checks *) + let is_lib = Meta.has Meta.LibType c.cl_meta in + if is_lib && not c.cl_extern then ctx.com.error "@:libType can only be used in extern classes" c.cl_pos; + (* a native type will skip one check: the static vs non-static field *) + let is_native = Meta.has Meta.JavaNative c.cl_meta || Meta.has Meta.CsNative c.cl_meta in + if Meta.has Meta.Macro c.cl_meta then display_error ctx "Macro classes are no longer allowed in haxe 3" c.cl_pos; + let rec extends_public c = + Meta.has Meta.PublicFields c.cl_meta || + match c.cl_super with + | None -> false + | Some (c,_) -> extends_public c + in + let cctx = { + tclass = c; + is_lib = is_lib; + is_native = is_native; + is_core_api = Meta.has Meta.CoreApi c.cl_meta; + is_class_debug = false; + extends_public = extends_public c; + abstract = abstract; + context_init = context_init; + force_constructor = false; + delayed_expr = []; + } in + ctx,cctx + + let create_field_context (ctx,cctx) c cff = + let ctx = { + ctx with + pass = PBuildClass; (* will be set later to PTypeExpr *) + } in + let is_static = List.mem AStatic cff.cff_access in + let is_extern = Meta.has Meta.Extern cff.cff_meta || c.cl_extern in + let allow_inline = cctx.abstract <> None || match cff.cff_kind with + | FFun _ -> ctx.g.doinline || is_extern + | _ -> true + in + let is_inline = allow_inline && List.mem AInline cff.cff_access in + let is_override = List.mem AOverride cff.cff_access in + let is_macro = List.mem AMacro cff.cff_access in + let field_kind = match fst cff.cff_name with + | "new" -> FKConstructor + | "__init__" when is_static -> FKInit + | _ -> FKNormal + in + let fctx = { + is_inline = is_inline; + is_static = is_static; + is_override = is_override; + is_macro = is_macro; + is_extern = is_extern; + is_display_field = ctx.is_display_file && Display.is_display_position cff.cff_pos; + is_field_debug = cctx.is_class_debug; + is_abstract_member = cctx.abstract <> None && Meta.has Meta.Impl cff.cff_meta; + field_kind = field_kind; + do_bind = (((not c.cl_extern || is_inline) && not c.cl_interface) || field_kind = FKInit); + do_add = true; + } in + ctx,fctx + + let is_public (ctx,cctx) access parent = + let c = cctx.tclass in + if List.mem APrivate access then + false + else if List.mem APublic access then + true + else match parent with + | Some { cf_public = p } -> p + | _ -> c.cl_extern || c.cl_interface || cctx.extends_public + + let rec get_parent c name = + match c.cl_super with + | None -> None + | Some (csup,_) -> + try + Some (PMap.find name csup.cl_fields) + with + Not_found -> get_parent csup name + + let add_field c cf is_static = + if is_static then begin + c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics; + c.cl_ordered_statics <- cf :: c.cl_ordered_statics; + end else begin + c.cl_fields <- PMap.add cf.cf_name cf c.cl_fields; + c.cl_ordered_fields <- cf :: c.cl_ordered_fields; + end + + let type_opt (ctx,cctx) p t = + let c = cctx.tclass in + match t with + | None when c.cl_extern || c.cl_interface -> + display_error ctx "Type required for extern classes and interfaces" p; + t_dynamic + | None when cctx.is_core_api -> + display_error ctx "Type required for core api classes" p; + t_dynamic + | _ -> + load_type_hint ctx p t + + let build_fields (ctx,cctx) c fields = + let fields = ref fields in + let get_fields() = !fields in + let pending = ref [] in + c.cl_build <- (fun() -> BuildMacro pending); + build_module_def ctx (TClassDecl c) c.cl_meta get_fields cctx.context_init (fun (e,p) -> + match e with + | EVars [_,Some (CTAnonymous f,p),None] -> + let f = List.map (fun f -> + let f = match cctx.abstract with + | Some a -> + let a_t = TExprToExpr.convert_type' (TAbstract(a,List.map snd a.a_params)) in + let this_t = TExprToExpr.convert_type' a.a_this in (* TODO: better pos? *) + transform_abstract_field ctx.com this_t a_t a f + | None -> + f + in + if List.mem AMacro f.cff_access then + (match ctx.g.macros with + | Some (_,mctx) when Hashtbl.mem mctx.g.types_module c.cl_path -> + (* assume that if we had already a macro with the same name, it has not been changed during the @:build operation *) + if not (List.exists (fun f2 -> f2.cff_name = f.cff_name && List.mem AMacro f2.cff_access) (!fields)) then + error "Class build macro cannot return a macro function when the class has already been compiled into the macro context" p + | _ -> ()); + f + ) f in + fields := f + | _ -> error "Class build macro must return a single variable with anonymous fields" p + ); + c.cl_build <- (fun() -> Building); + List.iter (fun f -> f()) !pending; + !fields + + let bind_type (ctx,cctx,fctx) cf r p = + let c = cctx.tclass in + let rec is_full_type t = + match t with + | TFun (args,ret) -> is_full_type ret && List.for_all (fun (_,_,t) -> is_full_type t) args + | TMono r -> (match !r with None -> false | Some t -> is_full_type t) + | TAbstract _ | TInst _ | TEnum _ | TLazy _ | TDynamic _ | TAnon _ | TType _ -> true + in + let force_macro () = + (* force macro system loading of this class in order to get completion *) + delay ctx PTypeField (fun() -> try ignore(ctx.g.do_macro ctx MDisplay c.cl_path cf.cf_name [] p) with Exit | Error _ -> ()) + in + let handle_display_field () = + if fctx.is_macro && not ctx.in_macro then + force_macro() + else begin + cf.cf_type <- TLazy r; + cctx.delayed_expr <- (ctx,Some r) :: cctx.delayed_expr; + end + in + if ctx.com.display.dms_full_typing then begin + if fctx.is_macro && not ctx.in_macro then + () + else begin + cf.cf_type <- TLazy r; + (* is_lib ? *) + cctx.delayed_expr <- (ctx,Some r) :: cctx.delayed_expr; + end + end else if ctx.com.display.dms_force_macro_typing && fctx.is_macro && not ctx.in_macro then + force_macro() + else begin + if fctx.is_display_field then begin + handle_display_field() + end else begin + if not (is_full_type cf.cf_type) then begin + cctx.delayed_expr <- (ctx, None) :: cctx.delayed_expr; + cf.cf_type <- TLazy r; + end; + end + end + + let bind_var (ctx,cctx,fctx) cf e = + let c = cctx.tclass in + let p = cf.cf_pos in + let rec get_declared f = function + | None -> None + | Some (c,a) when PMap.exists f c.cl_fields -> + Some (c,a) + | Some (c,_) -> + let ret = get_declared f c.cl_super in + match ret with + | Some r -> Some r + | None -> + let rec loop ifaces = match ifaces with + | [] -> None + | i :: ifaces -> match get_declared f (Some i) with + | Some r -> Some r + | None -> loop ifaces + in + loop c.cl_implements + in + if not fctx.is_static && not cctx.is_lib then begin match get_declared cf.cf_name c.cl_super with + | None -> () + | Some (csup,_) -> + (* this can happen on -net-lib generated classes if a combination of explicit interfaces and variables with the same name happens *) + if not (csup.cl_interface && Meta.has Meta.CsNative c.cl_meta) then + error ("Redefinition of variable " ^ cf.cf_name ^ " in subclass is not allowed. Previously declared at " ^ (s_type_path csup.cl_path) ) p + end; + let t = cf.cf_type in + + match e with + | None -> + if fctx.is_display_field then Display.DisplayEmitter.maybe_display_field ctx (cf.cf_name_pos) cf; + | Some e -> + if requires_value_meta ctx.com (Some c) then cf.cf_meta <- ((Meta.Value,[e],null_pos) :: cf.cf_meta); + let check_cast e = + (* insert cast to keep explicit field type (issue #1901) *) + if type_iseq e.etype cf.cf_type then + e + else begin match e.eexpr,follow cf.cf_type with + | TConst (TInt i),TAbstract({a_path=[],"Float"},_) -> + (* turn int constant to float constant if expected type is float *) + {e with eexpr = TConst (TFloat (Int32.to_string i))} + | _ -> + mk_cast e cf.cf_type e.epos + end + in + let r = exc_protect ctx (fun r -> + (* type constant init fields (issue #1956) *) + if not !return_partial_type || (match fst e with EConst _ -> true | _ -> false) then begin + r := (fun() -> t); + cctx.context_init(); + if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.in_macro then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ cf.cf_name); + let e = type_var_field ctx t e fctx.is_static fctx.is_display_field p in + let maybe_run_analyzer e = match e.eexpr with + | TConst _ | TLocal _ | TFunction _ -> e + | _ -> !analyzer_run_on_expr_ref ctx.com e + in + let require_constant_expression e msg = + if ctx.com.display.dms_display && ctx.com.display.dms_error_policy <> EPCollect then + e + else match Optimizer.make_constant_expression ctx (maybe_run_analyzer e) with + | Some e -> e + | None -> display_error ctx msg p; e + in + let e = (match cf.cf_kind with + | Var v when c.cl_extern || Meta.has Meta.Extern cf.cf_meta -> + if not fctx.is_static then begin + display_error ctx "Extern non-static variables may not be initialized" p; + e + end else if not fctx.is_inline then begin + display_error ctx "Extern non-inline variables may not be initialized" p; + e + end else require_constant_expression e "Extern variable initialization must be a constant value" + | Var v when is_extern_field cf -> + (* disallow initialization of non-physical fields (issue #1958) *) + display_error ctx "This field cannot be initialized because it is not a real variable" p; e + | Var v when not fctx.is_static -> + let e = if ctx.com.display.dms_display && ctx.com.display.dms_error_policy <> EPCollect then + e + else match Optimizer.make_constant_expression ctx (maybe_run_analyzer e) with + | Some e -> e + | None -> + let rec has_this e = match e.eexpr with + | TConst TThis -> + display_error ctx "Cannot access this or other member field in variable initialization" e.epos; + | TLocal v when (match ctx.vthis with Some v2 -> v == v2 | None -> false) -> + display_error ctx "Cannot access this or other member field in variable initialization" e.epos; + | _ -> + Type.iter has_this e + in + has_this e; + e + in + e + | Var v when v.v_read = AccInline -> + let e = require_constant_expression e "Inline variable initialization must be a constant value" in + begin match c.cl_kind with + | KAbstractImpl a when Meta.has Meta.Enum cf.cf_meta && Meta.has Meta.Enum a.a_meta -> + unify ctx t (TAbstract(a,(List.map (fun _ -> mk_mono()) a.a_params))) p; + begin match e.eexpr with + | TCast(e1,None) -> unify ctx e1.etype a.a_this e1.epos + | _ -> assert false + end + | _ -> + () + end; + e + | _ -> + e + ) in + let e = check_cast e in + cf.cf_expr <- Some e; + cf.cf_type <- t; + if fctx.is_display_field then Display.DisplayEmitter.maybe_display_field ctx (cf.cf_name_pos) cf; + end; + t + ) "bind_var" in + if not fctx.is_static then cctx.force_constructor <- true; + bind_type (ctx,cctx,fctx) cf r (snd e) + + let create_variable (ctx,cctx,fctx) c f t eo p = + if not fctx.is_static && cctx.abstract <> None then error (fst f.cff_name ^ ": Cannot declare member variable in abstract") p; + if fctx.is_inline && not fctx.is_static then error (fst f.cff_name ^ ": Inline variable must be static") p; + if fctx.is_inline && eo = None then error (fst f.cff_name ^ ": Inline variable must be initialized") p; + + let t = (match t with + | None when not fctx.is_static && eo = None -> + error ("Type required for member variable " ^ fst f.cff_name) p; + | None -> + mk_mono() + | Some t -> + (* TODO is_lib: only load complex type if needed *) + let old = ctx.type_params in + if fctx.is_static then ctx.type_params <- (match cctx.abstract with + | Some a -> a.a_params + | _ -> [] + ); + let t = load_complex_type ctx true p t in + if fctx.is_static then ctx.type_params <- old; + t + ) in + let cf = { + cf_name = fst f.cff_name; + cf_doc = f.cff_doc; + cf_meta = f.cff_meta; + cf_type = t; + cf_pos = f.cff_pos; + cf_name_pos = pos f.cff_name; + cf_kind = Var (if fctx.is_inline then { v_read = AccInline ; v_write = AccNever } else { v_read = AccNormal; v_write = AccNormal }); + cf_expr = None; + cf_expr_unoptimized = None; + cf_public = is_public (ctx,cctx) f.cff_access None; + cf_params = []; + cf_overloads = []; + } in + ctx.curfield <- cf; + bind_var (ctx,cctx,fctx) cf eo; + cf + + let check_abstract (ctx,cctx,fctx) c cf fd t ret p = + match cctx.abstract with + | Some a -> + let m = mk_mono() in + let ta = TAbstract(a, List.map (fun _ -> mk_mono()) a.a_params) in + let tthis = if fctx.is_abstract_member || Meta.has Meta.To cf.cf_meta then monomorphs a.a_params a.a_this else a.a_this in + let allows_no_expr = ref (Meta.has Meta.CoreType a.a_meta) in + let rec loop ml = match ml with + | (Meta.From,_,_) :: _ -> + let r = fun () -> + (* the return type of a from-function must be the abstract, not the underlying type *) + if not fctx.is_macro then (try type_eq EqStrict ret ta with Unify_error l -> error (error_msg (Unify l)) p); + match t with + | TFun([_,_,t],_) -> t + | _ -> error (cf.cf_name ^ ": @:from cast functions must accept exactly one argument") p + in + a.a_from_field <- (TLazy (ref r),cf) :: a.a_from_field; + | (Meta.To,_,_) :: _ -> + if fctx.is_macro then error (cf.cf_name ^ ": Macro cast functions are not supported") p; + (* TODO: this doesn't seem quite right... *) + if not (Meta.has Meta.Impl cf.cf_meta) then cf.cf_meta <- (Meta.Impl,[],null_pos) :: cf.cf_meta; + let resolve_m args = + (try unify_raise ctx t (tfun (tthis :: args) m) cf.cf_pos with Error (Unify l,p) -> error (error_msg (Unify l)) p); + match follow m with + | TMono _ when (match t with TFun(_,r) -> r == t_dynamic | _ -> false) -> t_dynamic + | m -> m + in + let r = exc_protect ctx (fun r -> + let args = if Meta.has Meta.MultiType a.a_meta then begin + let ctor = try + PMap.find "_new" c.cl_statics + with Not_found -> + error "Constructor of multi-type abstract must be defined before the individual @:to-functions are" cf.cf_pos + in + (* delay ctx PFinal (fun () -> unify ctx m tthis f.cff_pos); *) + let args = match follow (monomorphs a.a_params ctor.cf_type) with + | TFun(args,_) -> List.map (fun (_,_,t) -> t) args + | _ -> assert false + in + args + end else + [] + in + let t = resolve_m args in + r := (fun() -> t); + t + ) "@:to" in + delay ctx PForce (fun() -> ignore ((!r)())); + a.a_to_field <- (TLazy r, cf) :: a.a_to_field + | ((Meta.ArrayAccess,_,_) | (Meta.Op,[(EArrayDecl _),_],_)) :: _ -> + if fctx.is_macro then error (cf.cf_name ^ ": Macro array-access functions are not supported") p; + a.a_array <- cf :: a.a_array; + | (Meta.Op,[EBinop(op,_,_),_],_) :: _ -> + if fctx.is_macro then error (cf.cf_name ^ ": Macro operator functions are not supported") p; + let targ = if fctx.is_abstract_member then tthis else ta in + let left_eq,right_eq = match follow t with + | TFun([(_,_,t1);(_,_,t2)],_) -> + type_iseq targ t1,type_iseq targ t2 + | _ -> + if fctx.is_abstract_member then + error (cf.cf_name ^ ": Member @:op functions must accept exactly one argument") cf.cf_pos + else + error (cf.cf_name ^ ": Static @:op functions must accept exactly two arguments") cf.cf_pos + in + if not (left_eq || right_eq) then error (cf.cf_name ^ ": The left or right argument type must be " ^ (s_type (print_context()) targ)) cf.cf_pos; + if right_eq && Meta.has Meta.Commutative cf.cf_meta then error (cf.cf_name ^ ": @:commutative is only allowed if the right argument is not " ^ (s_type (print_context()) targ)) cf.cf_pos; + a.a_ops <- (op,cf) :: a.a_ops; + allows_no_expr := true; + | (Meta.Op,[EUnop(op,flag,_),_],_) :: _ -> + if fctx.is_macro then error (cf.cf_name ^ ": Macro operator functions are not supported") p; + let targ = if fctx.is_abstract_member then tthis else ta in + (try type_eq EqStrict t (tfun [targ] (mk_mono())) with Unify_error l -> raise (Error ((Unify l),cf.cf_pos))); + a.a_unops <- (op,flag,cf) :: a.a_unops; + allows_no_expr := true; + | (Meta.Impl,_,_) :: ml when cf.cf_name <> "_new" && not fctx.is_macro -> + begin match follow t with + | TFun((_,_,t1) :: _, _) when type_iseq tthis t1 -> + () + | _ -> + display_error ctx ("First argument of implementation function must be " ^ (s_type (print_context()) tthis)) cf.cf_pos + end; + loop ml + | ((Meta.Resolve,_,_) | (Meta.Op,[EField _,_],_)) :: _ -> + if a.a_resolve <> None then error "Multiple resolve methods are not supported" cf.cf_pos; + let targ = if fctx.is_abstract_member then tthis else ta in + begin match follow t with + | TFun([(_,_,t1);(_,_,t2)],_) -> + if not fctx.is_macro then begin + if not (type_iseq targ t1) then error ("First argument type must be " ^ (s_type (print_context()) targ)) cf.cf_pos; + if not (type_iseq ctx.t.tstring t2) then error ("Second argument type must be String") cf.cf_pos + end + | _ -> + error ("Field type of resolve must be " ^ (s_type (print_context()) targ) ^ " -> String -> T") cf.cf_pos + end; + a.a_resolve <- Some cf; + | _ :: ml -> + loop ml + | [] -> + () + in + loop cf.cf_meta; + let check_bind () = + if fd.f_expr = None then begin + if fctx.is_inline then error (cf.cf_name ^ ": Inline functions must have an expression") cf.cf_pos; + begin match fd.f_type with + | None -> error (cf.cf_name ^ ": Functions without expressions must have an explicit return type") cf.cf_pos + | Some _ -> () + end; + cf.cf_meta <- (Meta.NoExpr,[],null_pos) :: cf.cf_meta; + fctx.do_bind <- false; + if not (Meta.has Meta.CoreType a.a_meta) then fctx.do_add <- false; + end + in + if cf.cf_name = "_new" && Meta.has Meta.MultiType a.a_meta then fctx.do_bind <- false; + if !allows_no_expr then check_bind() + | _ -> + () + + let create_method (ctx,cctx,fctx) c f fd p = + let params = type_function_params ctx fd (fst f.cff_name) p in + if Meta.has Meta.Generic f.cff_meta then begin + if params = [] then error (fst f.cff_name ^ ": Generic functions must have type parameters") p; + end; + let fd = if fctx.is_macro && not ctx.in_macro && not fctx.is_static then + (* remove display of first argument which will contain the "this" expression *) + { fd with f_args = match fd.f_args with [] -> [] | _ :: l -> l } + else + fd + in + let fd = if not fctx.is_macro then + fd + else begin + if ctx.in_macro then begin + (* a class with a macro cannot be extern in macro context (issue #2015) *) + c.cl_extern <- false; + let texpr = CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = None } in + (* ExprOf type parameter might contain platform-specific type, let's replace it by Expr *) + let no_expr_of (t,p) = match t with + | CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some ("ExprOf"); tparams = [TPType _] } + | CTPath { tpackage = []; tname = ("ExprOf"); tsub = None; tparams = [TPType _] } -> Some (texpr,p) + | t -> Some (t,p) + in + { + f_params = fd.f_params; + f_type = (match fd.f_type with None -> Some (texpr,null_pos) | Some t -> no_expr_of t); + f_args = List.map (fun (a,o,m,t,e) -> a,o,m,(match t with None -> Some (texpr,null_pos) | Some t -> no_expr_of t),e) fd.f_args; + f_expr = fd.f_expr; + } + end else + let tdyn = Some (CTPath { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None },null_pos) in + let to_dyn p t = match t with + | { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some ("ExprOf"); tparams = [TPType t] } -> Some t + | { tpackage = []; tname = ("ExprOf"); tsub = None; tparams = [TPType t] } -> Some t + | { tpackage = ["haxe"]; tname = ("PosInfos"); tsub = None; tparams = [] } -> error "haxe.PosInfos is not allowed on macro functions, use Context.currentPos() instead" p + | _ -> tdyn + in + { + f_params = fd.f_params; + f_type = (match fd.f_type with Some (CTPath t,p) -> to_dyn p t | _ -> tdyn); + f_args = List.map (fun (a,o,m,t,_) -> a,o,m,(match t with Some (CTPath t,p) -> to_dyn p t | _ -> tdyn),None) fd.f_args; + f_expr = None; + } + end in + begin match c.cl_interface,fctx.field_kind with + | true,FKConstructor -> + error "An interface cannot have a constructor" p; + | true,_ -> + if not fctx.is_static && fd.f_expr <> None then error (fst f.cff_name ^ ": An interface method cannot have a body") p; + if fctx.is_inline && c.cl_interface then error (fst f.cff_name ^ ": You can't declare inline methods in interfaces") p; + | false,FKConstructor -> + if fctx.is_static then error "A constructor must not be static" p; + begin match fd.f_type with + | None | Some (CTPath { tpackage = []; tname = "Void" },_) -> () + | _ -> error "A class constructor can't have a return value" p; + end + | false,_ -> + () + end; + let parent = (if not fctx.is_static then get_parent c (fst f.cff_name) else None) in + let dynamic = List.mem ADynamic f.cff_access || (match parent with Some { cf_kind = Method MethDynamic } -> true | _ -> false) in + if fctx.is_inline && dynamic then error (fst f.cff_name ^ ": You can't have both 'inline' and 'dynamic'") p; + ctx.type_params <- (match cctx.abstract with + | Some a when fctx.is_abstract_member -> + params @ a.a_params + | _ -> + if fctx.is_static then params else params @ ctx.type_params); + (* TODO is_lib: avoid forcing the return type to be typed *) + let ret = if fctx.field_kind = FKConstructor then ctx.t.tvoid else type_opt (ctx,cctx) p fd.f_type in + let rec loop args = match args with + | ((name,p),opt,m,t,ct) :: args -> + (* TODO is_lib: avoid forcing the field to be typed *) + let t, ct = type_function_arg ctx (type_opt (ctx,cctx) p t) ct opt p in + delay ctx PTypeField (fun() -> match follow t with + | TAbstract({a_path = ["haxe";"extern"],"Rest"},_) -> + if not c.cl_extern then error "Rest argument are only supported for extern methods" p; + if opt then error "Rest argument cannot be optional" p; + begin match ct with None -> () | Some (_,p) -> error "Rest argument cannot have default value" p end; + if args <> [] then error "Rest should only be used for the last function argument" p; + | _ -> + () + ); + (name, ct, t) :: (loop args) + | [] -> + [] + in + let args = loop fd.f_args in + let t = TFun (fun_args args,ret) in + let cf = { + cf_name = fst f.cff_name; + cf_doc = f.cff_doc; + cf_meta = f.cff_meta; + cf_type = t; + cf_pos = f.cff_pos; + cf_name_pos = pos f.cff_name; + cf_kind = Method (if fctx.is_macro then MethMacro else if fctx.is_inline then MethInline else if dynamic then MethDynamic else MethNormal); + cf_expr = None; + cf_expr_unoptimized = None; + cf_public = is_public (ctx,cctx) f.cff_access parent; + cf_params = params; + cf_overloads = []; + } in + cf.cf_meta <- List.map (fun (m,el,p) -> match m,el with + | Meta.AstSource,[] -> (m,(match fd.f_expr with None -> [] | Some e -> [e]),p) + | _ -> m,el,p + ) cf.cf_meta; + generate_value_meta ctx.com (Some c) cf fd.f_args; + check_abstract (ctx,cctx,fctx) c cf fd t ret p; + init_meta_overloads ctx (Some c) cf; + ctx.curfield <- cf; + let r = exc_protect ctx (fun r -> + if not !return_partial_type then begin + r := (fun() -> t); + cctx.context_init(); + incr stats.s_methods_typed; + if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.in_macro then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ fst f.cff_name); + let fmode = (match cctx.abstract with + | Some _ -> + (match args with + | ("this",_,_) :: _ -> FunMemberAbstract + | _ when fst f.cff_name = "_new" -> FunMemberAbstract + | _ -> FunStatic) + | None -> + if fctx.field_kind = FKConstructor then FunConstructor else if fctx.is_static then FunStatic else FunMember + ) in + match ctx.com.platform with + | Java when is_java_native_function cf.cf_meta -> + if fd.f_expr <> None then + ctx.com.warning "@:native function definitions shouldn't include an expression. This behaviour is deprecated." cf.cf_pos; + cf.cf_expr <- None; + cf.cf_type <- t + | _ -> + let e , fargs = type_function ctx args ret fmode fd fctx.is_display_field p in + let tf = { + tf_args = fargs; + tf_type = ret; + tf_expr = e; + } in + if fctx.field_kind = FKInit then + (match e.eexpr with + | TBlock [] | TBlock [{ eexpr = TConst _ }] | TConst _ | TObjectDecl [] -> () + | _ -> c.cl_init <- Some e); + cf.cf_expr <- Some (mk (TFunction tf) t p); + cf.cf_type <- t; + if fctx.is_display_field then Display.DisplayEmitter.maybe_display_field ctx (cf.cf_name_pos) cf; + end; + t + ) "type_fun" in + if fctx.do_bind then bind_type (ctx,cctx,fctx) cf r (match fd.f_expr with Some e -> snd e | None -> f.cff_pos); + cf + + let create_property (ctx,cctx,fctx) c f (get,set,t,eo) p = + let name = fst f.cff_name in + (match cctx.abstract with + | Some a when fctx.is_abstract_member -> + ctx.type_params <- a.a_params; + | _ -> ()); + (* TODO is_lib: lazify load_complex_type *) + let ret = (match t, eo with + | None, None -> error (name ^ ": Property must either define a type or a default value") p; + | None, _ -> mk_mono() + | Some t, _ -> load_complex_type ctx true p t + ) in + let t_get,t_set = match cctx.abstract with + | Some a when fctx.is_abstract_member -> + if Meta.has Meta.IsVar f.cff_meta then error (name ^ ": Abstract properties cannot be real variables") f.cff_pos; + let ta = apply_params a.a_params (List.map snd a.a_params) a.a_this in + tfun [ta] ret, tfun [ta;ret] ret + | _ -> tfun [] ret, TFun(["value",false,ret],ret) + in + let find_accessor m = + (* on pf_overload platforms, the getter/setter may have been defined as an overloaded function; get all overloads *) + if ctx.com.config.pf_overload then + if fctx.is_static then + let f = PMap.find m c.cl_statics in + (f.cf_type, f) :: (List.map (fun f -> f.cf_type, f) f.cf_overloads) + else + Overloads.get_overloads c m + else + [ if fctx.is_static then + let f = PMap.find m c.cl_statics in + f.cf_type, f + else match class_field c (List.map snd c.cl_params) m with + | _, t,f -> t,f ] + in + let check_method m t req_name = + if ctx.com.display.dms_error_policy = EPIgnore then () else + try + let overloads = find_accessor m in + (* choose the correct overload if and only if there is more than one overload found *) + let rec get_overload overl = match overl with + | [tf] -> tf + | (t2,f2) :: overl -> + if type_iseq t t2 then + (t2,f2) + else + get_overload overl + | [] -> + if c.cl_interface then + raise Not_found + else + raise (Error (Custom + (Printf.sprintf "No overloaded method named %s was compatible with the property %s with expected type %s" m (name) (s_type (print_context()) t) + ), p)) + in + let t2, f2 = get_overload overloads in + (* accessors must be public on As3 (issue #1872) *) + if Common.defined ctx.com Define.As3 then f2.cf_meta <- (Meta.Public,[],null_pos) :: f2.cf_meta; + (match f2.cf_kind with + | Method MethMacro -> + display_error ctx (f2.cf_name ^ ": Macro methods cannot be used as property accessor") p; + display_error ctx (f2.cf_name ^ ": Accessor method is here") f2.cf_pos; + | _ -> ()); + unify_raise ctx t2 t f2.cf_pos; + if (fctx.is_abstract_member && not (Meta.has Meta.Impl f2.cf_meta)) || (Meta.has Meta.Impl f2.cf_meta && not (fctx.is_abstract_member)) then + display_error ctx "Mixing abstract implementation and static properties/accessors is not allowed" f2.cf_pos; + (match req_name with None -> () | Some n -> display_error ctx ("Please use " ^ n ^ " to name your property access method") f2.cf_pos); + f2.cf_meta <- List.fold_left (fun acc ((m,_,_) as meta) -> match m with + | Meta.Deprecated -> meta :: acc + | _ -> acc + ) f2.cf_meta f.cff_meta; + with + | Error (Unify l,p) -> raise (Error (Stack (Custom ("In method " ^ m ^ " required by property " ^ name),Unify l),p)) + | Not_found -> + if req_name <> None then display_error ctx (name ^ ": Custom property accessor is no longer supported, please use get/set") p else + if c.cl_interface then begin + let cf = mk_field m t p null_pos in + cf.cf_meta <- [Meta.CompilerGenerated,[],null_pos]; + cf.cf_kind <- Method MethNormal; + c.cl_fields <- PMap.add cf.cf_name cf c.cl_fields; + c.cl_ordered_fields <- cf :: c.cl_ordered_fields; + end else if not c.cl_extern then begin + try + let _, _, f2 = (if not fctx.is_static then let f = PMap.find m c.cl_statics in None, f.cf_type, f else class_field c (List.map snd c.cl_params) m) in + display_error ctx (Printf.sprintf "Method %s is no valid accessor for %s because it is %sstatic" m (name) (if fctx.is_static then "not " else "")) f2.cf_pos + with Not_found -> + display_error ctx ("Method " ^ m ^ " required by property " ^ name ^ " is missing") p + end + in + let display_accessor m p = + try + let cf = match find_accessor m with [_,cf] -> cf | _ -> raise Not_found in + Display.DisplayEmitter.display_field ctx.com.display cf p + with Not_found -> + () + in + let get = (match get with + | "null",_ -> AccNo + | "dynamic",_ -> AccCall + | "never",_ -> AccNever + | "default",_ -> AccNormal + | get,pget -> + let get = if get = "get" then "get_" ^ name else get in + if fctx.is_display_field && Display.is_display_position pget then delay ctx PTypeField (fun () -> display_accessor get pget); + if not cctx.is_lib then delay ctx PTypeField (fun() -> check_method get t_get (if get <> "get" && get <> "get_" ^ name then Some ("get_" ^ name) else None)); + AccCall + ) in + let set = (match set with + | "null",_ -> + (* standard flash library read-only variables can't be accessed for writing, even in subclasses *) + if c.cl_extern && (match c.cl_path with "flash" :: _ , _ -> true | _ -> false) && ctx.com.platform = Flash then + AccNever + else + AccNo + | "never",_ -> AccNever + | "dynamic",_ -> AccCall + | "default",_ -> AccNormal + | set,pset -> + let set = if set = "set" then "set_" ^ name else set in + if fctx.is_display_field && Display.is_display_position pset then delay ctx PTypeField (fun () -> display_accessor set pset); + if not cctx.is_lib then delay ctx PTypeField (fun() -> check_method set t_set (if set <> "set" && set <> "set_" ^ name then Some ("set_" ^ name) else None)); + AccCall + ) in + if set = AccNormal && (match get with AccCall -> true | _ -> false) then error (name ^ ": Unsupported property combination") p; + let cf = { + cf_name = name; + cf_doc = f.cff_doc; + cf_meta = f.cff_meta; + cf_pos = f.cff_pos; + cf_name_pos = pos f.cff_name; + cf_kind = Var { v_read = get; v_write = set }; + cf_expr = None; + cf_expr_unoptimized = None; + cf_type = ret; + cf_public = is_public (ctx,cctx) f.cff_access None; + cf_params = []; + cf_overloads = []; + } in + ctx.curfield <- cf; + bind_var (ctx,cctx,fctx) cf eo; + cf + + let init_field (ctx,cctx,fctx) f = + let c = cctx.tclass in + let name = fst f.cff_name in + check_global_metadata ctx f.cff_meta (fun m -> f.cff_meta <- m :: f.cff_meta) c.cl_module.m_path c.cl_path (Some name); + let p = f.cff_pos in + if name.[0] = '$' then display_error ctx "Field names starting with a dollar are not allowed" p; + List.iter (fun acc -> + match (acc, f.cff_kind) with + | APublic, _ | APrivate, _ | AStatic, _ -> () + | ADynamic, FFun _ | AOverride, FFun _ | AMacro, FFun _ | AInline, FFun _ | AInline, FVar _ -> () + | _, FVar _ -> error ("Invalid accessor '" ^ Ast.s_access acc ^ "' for variable " ^ name) p + | _, FProp _ -> error ("Invalid accessor '" ^ Ast.s_access acc ^ "' for property " ^ name) p + ) f.cff_access; + if fctx.is_override then (match c.cl_super with None -> error ("Invalid override on field '" ^ name ^ "': class has no super class") p | _ -> ()); + match f.cff_kind with + | FVar (t,e) -> + create_variable (ctx,cctx,fctx) c f t e p + | FFun fd -> + create_method (ctx,cctx,fctx) c f fd p + | FProp (get,set,t,eo) -> + create_property (ctx,cctx,fctx) c f (get,set,t,eo) p + + let check_overloads ctx c = + (* check if field with same signature was declared more than once *) + List.iter (fun f -> + if Meta.has Meta.Overload f.cf_meta then + List.iter (fun f2 -> + try + ignore (List.find (fun f3 -> f3 != f2 && Overloads.same_overload_args f2.cf_type f3.cf_type f2 f3) (f :: f.cf_overloads)); + display_error ctx ("Another overloaded field of same signature was already declared : " ^ f2.cf_name) f2.cf_pos + with | Not_found -> () + ) (f :: f.cf_overloads)) (c.cl_ordered_fields @ c.cl_ordered_statics) + + let init_class ctx c p context_init herits fields = + let ctx,cctx = create_class_context ctx c context_init p in + if cctx.is_class_debug then print_endline ("Created class context: " ^ dump_class_context cctx); + let fields = patch_class ctx c fields in + let fields = build_fields (ctx,cctx) c fields in + if cctx.is_core_api && ctx.com.display.dms_check_core_api then delay ctx PForce (fun() -> init_core_api ctx c); + if not cctx.is_lib then begin + (match c.cl_super with None -> () | Some _ -> delay_late ctx PForce (fun() -> check_overriding ctx c)); + if ctx.com.config.pf_overload then delay ctx PForce (fun() -> check_overloads ctx c) + end; + let rec has_field f = function + | None -> false + | Some (c,_) -> + PMap.exists f c.cl_fields || has_field f c.cl_super || List.exists (fun i -> has_field f (Some i)) c.cl_implements + in + let rec check_require = function + | [] -> None + | (Meta.Require,conds,_) :: l -> + let rec loop = function + | [] -> check_require l + | e :: l -> + let sc = match fst e with + | EConst (Ident s) -> s + | EBinop ((OpEq|OpNotEq|OpGt|OpGte|OpLt|OpLte) as op,(EConst (Ident s),_),(EConst ((Int _ | Float _ | String _) as c),_)) -> s ^ s_binop op ^ s_constant c + | _ -> "" + in + if not (Parser.is_true (Parser.eval ctx.com e)) then + Some (sc,(match List.rev l with (EConst (String msg),_) :: _ -> Some msg | _ -> None)) + else + loop l + in + loop conds + | _ :: l -> + check_require l + in + let rec check_if_feature = function + | [] -> [] + | (Meta.IfFeature,el,_) :: _ -> List.map (fun (e,p) -> match e with EConst (String s) -> s | _ -> error "String expected" p) el + | _ :: l -> check_if_feature l + in + let cl_if_feature = check_if_feature c.cl_meta in + let cl_req = check_require c.cl_meta in + List.iter (fun f -> + let p = f.cff_pos in + try + let ctx,fctx = create_field_context (ctx,cctx) c f in + if fctx.is_field_debug then print_endline ("Created field context: " ^ dump_field_context fctx); + let cf = init_field (ctx,cctx,fctx) f in + if fctx.is_field_debug then print_endline ("Created field: " ^ Printer.s_tclass_field "" cf); + if fctx.is_static && c.cl_interface && fctx.field_kind <> FKInit && not cctx.is_lib then error "You can't declare static fields in interfaces" p; + let set_feature s = + ctx.m.curmod.m_extra.m_if_feature <- (s,(c,cf,fctx.is_static)) :: ctx.m.curmod.m_extra.m_if_feature + in + List.iter set_feature cl_if_feature; + List.iter set_feature (check_if_feature cf.cf_meta); + let req = check_require f.cff_meta in + let req = (match req with None -> if fctx.is_static || fctx.field_kind = FKConstructor then cl_req else None | _ -> req) in + (match req with + | None -> () + | Some r -> cf.cf_kind <- Var { v_read = AccRequire (fst r, snd r); v_write = AccRequire (fst r, snd r) }); + begin match fctx.field_kind with + | FKConstructor -> + begin match c.cl_constructor with + | None -> + c.cl_constructor <- Some cf + | Some ctor when ctx.com.config.pf_overload -> + if Meta.has Meta.Overload cf.cf_meta && Meta.has Meta.Overload ctor.cf_meta then + ctor.cf_overloads <- cf :: ctor.cf_overloads + else + display_error ctx ("If using overloaded constructors, all constructors must be declared with @:overload") (if Meta.has Meta.Overload cf.cf_meta then ctor.cf_pos else cf.cf_pos) + | Some ctor -> + display_error ctx "Duplicate constructor" p + end + | FKInit -> + () + | FKNormal -> + let dup = if fctx.is_static then PMap.exists cf.cf_name c.cl_fields || has_field cf.cf_name c.cl_super else PMap.exists cf.cf_name c.cl_statics in + if not cctx.is_native && not c.cl_extern && dup then error ("Same field name can't be use for both static and instance : " ^ cf.cf_name) p; + if List.mem AOverride f.cff_access then c.cl_overrides <- cf :: c.cl_overrides; + let is_var f = match cf.cf_kind with | Var _ -> true | _ -> false in + if PMap.mem cf.cf_name (if fctx.is_static then c.cl_statics else c.cl_fields) then + if ctx.com.config.pf_overload && Meta.has Meta.Overload cf.cf_meta && not (is_var f) then + let mainf = PMap.find cf.cf_name (if fctx.is_static then c.cl_statics else c.cl_fields) in + if is_var mainf then display_error ctx "Cannot declare a variable with same name as a method" mainf.cf_pos; + (if not (Meta.has Meta.Overload mainf.cf_meta) then display_error ctx ("Overloaded methods must have @:overload metadata") mainf.cf_pos); + mainf.cf_overloads <- cf :: mainf.cf_overloads + else + display_error ctx ("Duplicate class field declaration : " ^ cf.cf_name) p + else + if fctx.do_add then add_field c cf (fctx.is_static || fctx.is_macro && ctx.in_macro) + end + with Error (Custom str,p2) when p = p2 -> + display_error ctx str p + ) fields; + (match cctx.abstract with + | Some a -> + a.a_to_field <- List.rev a.a_to_field; + a.a_from_field <- List.rev a.a_from_field; + a.a_ops <- List.rev a.a_ops; + a.a_unops <- List.rev a.a_unops; + a.a_array <- List.rev a.a_array; + | None -> ()); + c.cl_ordered_statics <- List.rev c.cl_ordered_statics; + c.cl_ordered_fields <- List.rev c.cl_ordered_fields; + (* + make sure a default contructor with same access as super one will be added to the class structure at some point. + *) + (* add_constructor does not deal with overloads correctly *) + if not ctx.com.config.pf_overload then add_constructor ctx c cctx.force_constructor p; + if Meta.has Meta.StructInit c.cl_meta then check_struct_init_constructor ctx c p; + (* check overloaded constructors *) + (if ctx.com.config.pf_overload && not cctx.is_lib then match c.cl_constructor with + | Some ctor -> + delay ctx PTypeField (fun() -> + List.iter (fun f -> + try + (* TODO: consider making a broader check, and treat some types, like TAnon and type parameters as Dynamic *) + ignore(List.find (fun f2 -> f != f2 && Overloads.same_overload_args f.cf_type f2.cf_type f f2) (ctor :: ctor.cf_overloads)); + display_error ctx ("Another overloaded field of same signature was already declared : " ^ f.cf_name) f.cf_pos; + with Not_found -> () + ) (ctor :: ctor.cf_overloads) + ) + | _ -> ()); + (* push delays in reverse order so they will be run in correct order *) + List.iter (fun (ctx,r) -> + init_class_done ctx; + (match r with + | None -> () + | Some r -> delay ctx PTypeField (fun() -> ignore((!r)()))) + ) cctx.delayed_expr +end + +let check_module_types ctx m p t = + let t = t_infos t in + try + let m2 = Hashtbl.find ctx.g.types_module t.mt_path in + if m.m_path <> m2 && String.lowercase (s_type_path m2) = String.lowercase (s_type_path m.m_path) then error ("Module " ^ s_type_path m2 ^ " is loaded with a different case than " ^ s_type_path m.m_path) p; + error ("Type name " ^ s_type_path t.mt_path ^ " is redefined from module " ^ s_type_path m2) p + with + Not_found -> + Hashtbl.add ctx.g.types_module t.mt_path m.m_path + +let add_module ctx m p = + List.iter (check_module_types ctx m p) m.m_types; + Hashtbl.add ctx.g.modules m.m_path m + +let handle_path_display ctx path p = + let open Display.ImportHandling in + match Display.ImportHandling.convert_import_to_something_usable !Parser.resume_display path,ctx.com.display.dms_kind with + | (IDKPackage sl,_),_ -> + raise (Parser.TypePath(sl,None,true)) + | (IDKModule(sl,s),_),DMPosition -> + (* We assume that we want to go to the module file, not a specific type + which might not even exist anyway. *) + let mt = ctx.g.do_load_module ctx (sl,s) p in + let p = { pfile = mt.m_extra.m_file; pmin = 0; pmax = 0} in + raise (Display.DisplayPosition [p]) + | (IDKModule(sl,s),_),_ -> + (* TODO: wait till nadako requests @type display for these, then implement it somehow *) + raise (Parser.TypePath(sl,Some(s,false),true)) + | (IDKSubType(sl,sm,st),p),DMPosition -> + resolve_position_by_path ctx { tpackage = sl; tname = sm; tparams = []; tsub = Some st} p + | (IDKSubType(sl,sm,st),_),_ -> + raise (Parser.TypePath(sl @ [sm],Some(st,false),true)) + | ((IDKSubTypeField(sl,sm,st,sf) | IDKModuleField(sl,(sm as st),sf)),p),_ -> + let m = ctx.g.do_load_module ctx (sl,sm) p in + List.iter (fun t -> match t with + | TClassDecl c when snd c.cl_path = st -> + ignore(c.cl_build()); + let cf = PMap.find sf c.cl_statics in + Display.DisplayEmitter.display_field ctx.com.display cf p + | _ -> + () + ) m.m_types; + | (IDK,_),_ -> + () + +(* + In this pass, we can access load and access other modules types, but we cannot follow them or access their structure + since they have not been setup. We also build a context_init list that will be evaluated the first time we evaluate + an expression into the context +*) +let init_module_type ctx context_init do_init (decl,p) = + let get_type name = + try List.find (fun t -> snd (t_infos t).mt_path = name) ctx.m.curmod.m_types with Not_found -> assert false + in + let check_path_display path p = match ctx.com.display.dms_kind with + (* We cannot use ctx.is_display_file because the import could come from an import.hx file. *) + | DMDiagnostics b when (b && not (ExtString.String.ends_with p.pfile "import.hx")) || Display.is_display_file p.pfile -> + Display.ImportHandling.add_import_position ctx.com p path; + | DMStatistics | DMUsage _ -> + Display.ImportHandling.add_import_position ctx.com p path; + | _ -> + if Display.is_display_file p.pfile then handle_path_display ctx path p + in + match decl with + | EImport (path,mode) -> + ctx.m.module_imports <- (path,mode) :: ctx.m.module_imports; + check_path_display path p; + let rec loop acc = function + | x :: l when is_lower_ident (fst x) -> loop (x::acc) l + | rest -> List.rev acc, rest + in + let pack, rest = loop [] path in + (match rest with + | [] -> + (match mode with + | IAll -> + ctx.m.wildcard_packages <- (List.map fst pack,p) :: ctx.m.wildcard_packages + | _ -> + (match List.rev path with + | [] -> raise (Display.DisplayToplevel (Display.ToplevelCollector.run ctx true)); + | (_,p) :: _ -> error "Module name must start with an uppercase letter" p)) + | (tname,p2) :: rest -> + let p1 = (match pack with [] -> p2 | (_,p1) :: _ -> p1) in + let p_type = punion p1 p2 in + let md = ctx.g.do_load_module ctx (List.map fst pack,tname) p_type in + let types = md.m_types in + let no_private (t,_) = not (t_infos t).mt_private in + let chk_private t p = if (t_infos t).mt_private then error "You can't import a private type" p in + let has_name name t = snd (t_infos t).mt_path = name in + let get_type tname = + let t = (try List.find (has_name tname) types with Not_found -> error (StringError.string_error tname (List.map (fun mt -> snd (t_infos mt).mt_path) types) ("Module " ^ s_type_path md.m_path ^ " does not define type " ^ tname)) p_type) in + chk_private t p_type; + t + in + let rebind t name = + if not (name.[0] >= 'A' && name.[0] <= 'Z') then + error "Type aliases must start with an uppercase letter" p; + let _, _, f = ctx.g.do_build_instance ctx t p_type in + (* create a temp private typedef, does not register it in module *) + TTypeDecl { + t_path = (fst md.m_path @ ["_" ^ snd md.m_path],name); + t_module = md; + t_pos = p; + t_name_pos = null_pos; + t_private = true; + t_doc = None; + t_meta = []; + t_params = (t_infos t).mt_params; + t_type = f (List.map snd (t_infos t).mt_params); + } + in + let add_static_init t name s = + let name = (match name with None -> s | Some n -> n) in + match resolve_typedef t with + | TClassDecl c -> + ignore(c.cl_build()); + ignore(PMap.find s c.cl_statics); + ctx.m.module_globals <- PMap.add name (TClassDecl c,s,p) ctx.m.module_globals + | TEnumDecl e -> + ignore(PMap.find s e.e_constrs); + ctx.m.module_globals <- PMap.add name (TEnumDecl e,s,p) ctx.m.module_globals + | _ -> + raise Not_found + in + (match mode with + | INormal | IAsName _ -> + let name = (match mode with IAsName n -> Some n | _ -> None) in + (match rest with + | [] -> + (match name with + | None -> + ctx.m.module_types <- List.filter no_private (List.map (fun t -> t,p) types) @ ctx.m.module_types + | Some newname -> + ctx.m.module_types <- (rebind (get_type tname) newname,p) :: ctx.m.module_types); + | [tsub,p2] -> + let pu = punion p1 p2 in + (try + let tsub = List.find (has_name tsub) types in + chk_private tsub pu; + ctx.m.module_types <- ((match name with None -> tsub | Some n -> rebind tsub n),p) :: ctx.m.module_types + with Not_found -> + (* this might be a static property, wait later to check *) + let tmain = get_type tname in + context_init := (fun() -> + try + add_static_init tmain name tsub + with Not_found -> + error (s_type_path (t_infos tmain).mt_path ^ " has no field or subtype " ^ tsub) p + ) :: !context_init) + | (tsub,p2) :: (fname,p3) :: rest -> + (match rest with + | [] -> () + | (n,p) :: _ -> error ("Unexpected " ^ n) p); + let tsub = get_type tsub in + context_init := (fun() -> + try + add_static_init tsub name fname + with Not_found -> + error (s_type_path (t_infos tsub).mt_path ^ " has no field " ^ fname) (punion p p3) + ) :: !context_init; + ) + | IAll -> + let t = (match rest with + | [] -> get_type tname + | [tsub,_] -> get_type tsub + | _ :: (n,p) :: _ -> error ("Unexpected " ^ n) p + ) in + context_init := (fun() -> + match resolve_typedef t with + | TClassDecl c + | TAbstractDecl {a_impl = Some c} -> + ignore(c.cl_build()); + PMap.iter (fun _ cf -> if not (has_meta Meta.NoImportGlobal cf.cf_meta) then ctx.m.module_globals <- PMap.add cf.cf_name (TClassDecl c,cf.cf_name,p) ctx.m.module_globals) c.cl_statics + | TEnumDecl e -> + PMap.iter (fun _ c -> if not (has_meta Meta.NoImportGlobal c.ef_meta) then ctx.m.module_globals <- PMap.add c.ef_name (TEnumDecl e,c.ef_name,p) ctx.m.module_globals) e.e_constrs + | _ -> + error "No statics to import from this type" p + ) :: !context_init + )) + | EUsing path -> + check_path_display path p; + let t = match List.rev path with + | (s1,_) :: (s2,_) :: sl -> + if is_lower_ident s2 then { tpackage = (List.rev (s2 :: List.map fst sl)); tname = s1; tsub = None; tparams = [] } + else { tpackage = List.rev (List.map fst sl); tname = s2; tsub = Some s1; tparams = [] } + | (s1,_) :: sl -> + { tpackage = List.rev (List.map fst sl); tname = s1; tsub = None; tparams = [] } + | [] -> + raise (Display.DisplayToplevel (Display.ToplevelCollector.run ctx true)); + in + (* do the import first *) + let types = (match t.tsub with + | None -> + let md = ctx.g.do_load_module ctx (t.tpackage,t.tname) p in + let types = List.filter (fun t -> not (t_infos t).mt_private) md.m_types in + ctx.m.module_types <- (List.map (fun t -> t,p) types) @ ctx.m.module_types; + types + | Some _ -> + let t = load_type_def ctx p t in + ctx.m.module_types <- (t,p) :: ctx.m.module_types; + [t] + ) in + (* delay the using since we need to resolve typedefs *) + let filter_classes types = + let rec loop acc types = match types with + | td :: l -> + (match resolve_typedef td with + | TClassDecl c | TAbstractDecl({a_impl = Some c}) -> + loop ((c,p) :: acc) l + | td -> + loop acc l) + | [] -> + acc + in + loop [] types + in + context_init := (fun() -> ctx.m.module_using <- filter_classes types @ ctx.m.module_using) :: !context_init + | EClass d -> + let c = (match get_type (fst d.d_name) with TClassDecl c -> c | _ -> assert false) in + if ctx.is_display_file && Display.is_display_position (pos d.d_name) then + Display.DisplayEmitter.display_module_type ctx.com.display (match c.cl_kind with KAbstractImpl a -> TAbstractDecl a | _ -> TClassDecl c) (pos d.d_name); + check_global_metadata ctx c.cl_meta (fun m -> c.cl_meta <- m :: c.cl_meta) c.cl_module.m_path c.cl_path None; + let herits = d.d_flags in + c.cl_extern <- List.mem HExtern herits; + c.cl_interface <- List.mem HInterface herits; + let build() = + let fl = Inheritance.set_heritance ctx c herits p in + let rec build() = + c.cl_build <- (fun()-> Building); + try + List.iter (fun f -> f()) fl; + ClassInitializer.init_class ctx c p do_init d.d_flags d.d_data; + c.cl_build <- (fun()-> Built); + List.iter (fun (_,t) -> ignore(follow t)) c.cl_params; + Built; + with Build_canceled state -> + c.cl_build <- make_pass ctx build; + let rebuild() = + delay_late ctx PBuildClass (fun() -> ignore(c.cl_build())); + in + (match state with + | Built -> assert false + | Building -> rebuild() + | BuildMacro f -> f := rebuild :: !f); + state + | exn -> + c.cl_build <- (fun()-> Built); + raise exn + in + build() + in + ctx.pass <- PBuildClass; + ctx.curclass <- c; + c.cl_build <- make_pass ctx build; + ctx.pass <- PBuildModule; + ctx.curclass <- null_class; + delay ctx PBuildClass (fun() -> ignore(c.cl_build())); + if (ctx.com.platform = Java || ctx.com.platform = Cs) && not c.cl_extern then + delay ctx PTypeField (fun () -> + let metas = check_strict_meta ctx c.cl_meta in + if metas <> [] then c.cl_meta <- metas @ c.cl_meta; + let rec run_field cf = + let metas = check_strict_meta ctx cf.cf_meta in + if metas <> [] then cf.cf_meta <- metas @ cf.cf_meta; + List.iter run_field cf.cf_overloads + in + List.iter run_field c.cl_ordered_statics; + List.iter run_field c.cl_ordered_fields; + match c.cl_constructor with + | Some f -> run_field f + | _ -> () + ); + | EEnum d -> + let e = (match get_type (fst d.d_name) with TEnumDecl e -> e | _ -> assert false) in + if ctx.is_display_file && Display.is_display_position (pos d.d_name) then + Display.DisplayEmitter.display_module_type ctx.com.display (TEnumDecl e) (pos d.d_name); + let ctx = { ctx with type_params = e.e_params } in + let h = (try Some (Hashtbl.find ctx.g.type_patches e.e_path) with Not_found -> None) in + check_global_metadata ctx e.e_meta (fun m -> e.e_meta <- m :: e.e_meta) e.e_module.m_path e.e_path None; + (match h with + | None -> () + | Some (h,hcl) -> + Hashtbl.iter (fun _ _ -> error "Field type patch not supported for enums" e.e_pos) h; + e.e_meta <- e.e_meta @ hcl.tp_meta); + let constructs = ref d.d_data in + let get_constructs() = + List.map (fun c -> + { + cff_name = c.ec_name; + cff_doc = c.ec_doc; + cff_meta = c.ec_meta; + cff_pos = c.ec_pos; + cff_access = []; + cff_kind = (match c.ec_args, c.ec_params with + | [], [] -> FVar (c.ec_type,None) + | _ -> FFun { f_params = c.ec_params; f_type = c.ec_type; f_expr = None; f_args = List.map (fun (n,o,t) -> (n,null_pos),o,[],Some t,None) c.ec_args }); + } + ) (!constructs) + in + let init () = List.iter (fun f -> f()) !context_init in + build_module_def ctx (TEnumDecl e) e.e_meta get_constructs init (fun (e,p) -> + match e with + | EVars [_,Some (CTAnonymous fields,p),None] -> + constructs := List.map (fun f -> + let args, params, t = (match f.cff_kind with + | FVar (t,None) -> [], [], t + | FFun { f_params = pl; f_type = t; f_expr = (None|Some (EBlock [],_)); f_args = al } -> + let al = List.map (fun ((n,_),o,_,t,_) -> match t with None -> error "Missing function parameter type" f.cff_pos | Some t -> n,o,t) al in + al, pl, t + | _ -> + error "Invalid enum constructor in @:build result" p + ) in + { + ec_name = f.cff_name; + ec_doc = f.cff_doc; + ec_meta = f.cff_meta; + ec_pos = f.cff_pos; + ec_args = args; + ec_params = params; + ec_type = t; + } + ) fields + | _ -> error "Enum build macro must return a single variable with anonymous object fields" p + ); + let et = TEnum (e,List.map snd e.e_params) in + let names = ref [] in + let index = ref 0 in + let is_flat = ref true in + let fields = ref PMap.empty in + List.iter (fun c -> + let p = c.ec_pos in + let params = ref [] in + params := type_type_params ~enum_constructor:true ctx ([],fst c.ec_name) (fun() -> !params) c.ec_pos c.ec_params; + let params = !params in + let ctx = { ctx with type_params = params @ ctx.type_params } in + let rt = (match c.ec_type with + | None -> et + | Some t -> + let t = load_complex_type ctx true p t in + (match follow t with + | TEnum (te,_) when te == e -> + () + | _ -> + error "Explicit enum type must be of the same enum type" p); + t + ) in + let t = (match c.ec_args with + | [] -> rt + | l -> + is_flat := false; + let pnames = ref PMap.empty in + TFun (List.map (fun (s,opt,(t,tp)) -> + (match t with CTPath({tpackage=[];tname="Void"}) -> error "Arguments of type Void are not allowed in enum constructors" c.ec_pos | _ -> ()); + if PMap.mem s (!pnames) then error ("Duplicate parameter '" ^ s ^ "' in enum constructor " ^ fst c.ec_name) p; + pnames := PMap.add s () (!pnames); + s, opt, load_type_hint ~opt ctx p (Some (t,tp)) + ) l, rt) + ) in + if PMap.mem (fst c.ec_name) e.e_constrs then error ("Duplicate constructor " ^ fst c.ec_name) p; + let f = { + ef_name = fst c.ec_name; + ef_type = t; + ef_pos = p; + ef_name_pos = snd c.ec_name; + ef_doc = c.ec_doc; + ef_index = !index; + ef_params = params; + ef_meta = c.ec_meta; + } in + let cf = { + cf_name = f.ef_name; + cf_public = true; + cf_type = f.ef_type; + cf_kind = (match follow f.ef_type with + | TFun _ -> Method MethNormal + | _ -> Var { v_read = AccNormal; v_write = AccNo } + ); + cf_pos = p; + cf_name_pos = f.ef_name_pos; + cf_doc = f.ef_doc; + cf_meta = no_meta; + cf_expr = None; + cf_expr_unoptimized = None; + cf_params = f.ef_params; + cf_overloads = []; + } in + if ctx.is_display_file && Display.is_display_position p then + Display.DisplayEmitter.display_enum_field ctx.com.display f p; + e.e_constrs <- PMap.add f.ef_name f e.e_constrs; + fields := PMap.add cf.cf_name cf !fields; + incr index; + names := (fst c.ec_name) :: !names; + ) (!constructs); + e.e_names <- List.rev !names; + e.e_extern <- e.e_extern; + e.e_type.t_params <- e.e_params; + e.e_type.t_type <- TAnon { + a_fields = !fields; + a_status = ref (EnumStatics e); + }; + if !is_flat then e.e_meta <- (Meta.FlatEnum,[],null_pos) :: e.e_meta; + + if (ctx.com.platform = Java || ctx.com.platform = Cs) && not e.e_extern then + delay ctx PTypeField (fun () -> + let metas = check_strict_meta ctx e.e_meta in + e.e_meta <- metas @ e.e_meta; + PMap.iter (fun _ ef -> + let metas = check_strict_meta ctx ef.ef_meta in + if metas <> [] then ef.ef_meta <- metas @ ef.ef_meta + ) e.e_constrs + ); + | ETypedef d -> + let t = (match get_type (fst d.d_name) with TTypeDecl t -> t | _ -> assert false) in + if ctx.is_display_file && Display.is_display_position (pos d.d_name) then + Display.DisplayEmitter.display_module_type ctx.com.display (TTypeDecl t) (pos d.d_name); + check_global_metadata ctx t.t_meta (fun m -> t.t_meta <- m :: t.t_meta) t.t_module.m_path t.t_path None; + let ctx = { ctx with type_params = t.t_params } in + let tt = load_complex_type ctx true p d.d_data in + let tt = (match fst d.d_data with + | CTExtend _ -> tt + | CTPath { tpackage = ["haxe";"macro"]; tname = "MacroType" } -> + (* we need to follow MacroType immediately since it might define other module types that we will load afterwards *) + if t.t_type == follow tt then error "Recursive typedef is not allowed" p; + tt + | _ -> + if (Meta.has Meta.Eager d.d_meta) then + follow tt + else begin + let f r = + if t.t_type == follow tt then error "Recursive typedef is not allowed" p; + r := (fun() -> tt); + tt + in + let r = exc_protect ctx f "typedef_rec_check" in + delay ctx PForce (fun () -> ignore(!r())); + TLazy r + end + ) in + (match t.t_type with + | TMono r -> + (match !r with + | None -> r := Some tt; + | Some _ -> assert false); + | _ -> assert false); + if ctx.com.platform = Cs && t.t_meta <> [] then + delay ctx PTypeField (fun () -> + let metas = check_strict_meta ctx t.t_meta in + if metas <> [] then t.t_meta <- metas @ t.t_meta; + ); + | EAbstract d -> + let a = (match get_type (fst d.d_name) with TAbstractDecl a -> a | _ -> assert false) in + if ctx.is_display_file && Display.is_display_position (pos d.d_name) then + Display.DisplayEmitter.display_module_type ctx.com.display (TAbstractDecl a) (pos d.d_name); + check_global_metadata ctx a.a_meta (fun m -> a.a_meta <- m :: a.a_meta) a.a_module.m_path a.a_path None; + let ctx = { ctx with type_params = a.a_params } in + let is_type = ref false in + let load_type t from = + let t = load_complex_type ctx true p t in + let t = if not (Meta.has Meta.CoreType a.a_meta) then begin + if !is_type then begin + let r = exc_protect ctx (fun r -> + r := (fun() -> t); + let at = monomorphs a.a_params a.a_this in + (try (if from then Type.unify t at else Type.unify at t) with Unify_error _ -> error "You can only declare from/to with compatible types" p); + t + ) "constraint" in + delay ctx PForce (fun () -> ignore(!r())); + TLazy r + end else + error "Missing underlying type declaration or @:coreType declaration" p; + end else begin + if Meta.has Meta.Callable a.a_meta then + error "@:coreType abstracts cannot be @:callable" p; + t + end in + t + in + List.iter (function + | AFromType t -> a.a_from <- (load_type t true) :: a.a_from + | AToType t -> a.a_to <- (load_type t false) :: a.a_to + | AIsType t -> + if a.a_impl = None then error "Abstracts with underlying type must have an implementation" a.a_pos; + if Meta.has Meta.CoreType a.a_meta then error "@:coreType abstracts cannot have an underlying type" p; + let at = load_complex_type ctx true p t in + delay ctx PForce (fun () -> + begin match follow at with + | TAbstract(a2,_) when a == a2 -> error "Abstract underlying type cannot be recursive" a.a_pos + | _ -> () + end; + ); + a.a_this <- at; + is_type := true; + | AExtern -> + (match a.a_impl with Some c -> c.cl_extern <- true | None -> (* Hmmmm.... *) ()) + | APrivAbstract -> () + ) d.d_flags; + if not !is_type then begin + if Meta.has Meta.CoreType a.a_meta then + a.a_this <- TAbstract(a,List.map snd a.a_params) + else + error "Abstract is missing underlying type declaration" a.a_pos + end + +let module_pass_2 ctx m decls tdecls p = + (* here is an additional PASS 1 phase, which define the type parameters for all module types. + Constraints are handled lazily (no other type is loaded) because they might be recursive anyway *) + List.iter (fun d -> + match d with + | (TClassDecl c, (EClass d, p)) -> + c.cl_params <- type_type_params ctx c.cl_path (fun() -> c.cl_params) p d.d_params; + if Meta.has Meta.Generic c.cl_meta && c.cl_params <> [] then c.cl_kind <- KGeneric; + if Meta.has Meta.GenericBuild c.cl_meta then begin + if ctx.in_macro then error "@:genericBuild cannot be used in macros" c.cl_pos; + c.cl_kind <- KGenericBuild d.d_data; + end; + if c.cl_path = (["haxe";"macro"],"MacroType") then c.cl_kind <- KMacroType; + | (TEnumDecl e, (EEnum d, p)) -> + e.e_params <- type_type_params ctx e.e_path (fun() -> e.e_params) p d.d_params; + | (TTypeDecl t, (ETypedef d, p)) -> + t.t_params <- type_type_params ctx t.t_path (fun() -> t.t_params) p d.d_params; + | (TAbstractDecl a, (EAbstract d, p)) -> + a.a_params <- type_type_params ctx a.a_path (fun() -> a.a_params) p d.d_params; + | _ -> + assert false + ) decls; + (* setup module types *) + let context_init = ref [] in + let do_init() = + match !context_init with + | [] -> () + | l -> context_init := []; List.iter (fun f -> f()) (List.rev l) + in + List.iter (init_module_type ctx context_init do_init) tdecls + +(* + Creates a module context for [m] and types [tdecls] using it. +*) +let type_types_into_module ctx m tdecls p = + let decls, tdecls = module_pass_1 ctx m tdecls p in + let types = List.map fst decls in + List.iter (check_module_types ctx m p) types; + m.m_types <- m.m_types @ types; + (* define the per-module context for the next pass *) + let ctx = { + com = ctx.com; + g = ctx.g; + t = ctx.t; + m = { + curmod = m; + module_types = List.map (fun t -> t,null_pos) ctx.g.std.m_types; + module_using = []; + module_globals = PMap.empty; + wildcard_packages = []; + module_imports = []; + }; + is_display_file = (ctx.com.display.dms_display && Display.is_display_file m.m_extra.m_file); + meta = []; + this_stack = []; + with_type_stack = []; + call_argument_stack = []; + pass = PBuildModule; + on_error = (fun ctx msg p -> ctx.com.error msg p); + macro_depth = ctx.macro_depth; + curclass = null_class; + curfield = null_field; + tthis = ctx.tthis; + ret = ctx.ret; + locals = PMap.empty; + type_params = []; + curfun = FunStatic; + untyped = false; + in_macro = ctx.in_macro; + in_display = false; + in_loop = false; + opened = []; + in_call_args = false; + vthis = None; + } in + if ctx.g.std != null_module then begin + add_dependency m ctx.g.std; + (* this will ensure both String and (indirectly) Array which are basic types which might be referenced *) + ignore(load_core_type ctx "String"); + end; + module_pass_2 ctx m decls tdecls p; + ctx + +let handle_import_hx ctx m decls p = + let path_split = List.tl (List.rev (Path.get_path_parts m.m_extra.m_file)) in + let join l = String.concat Path.path_sep (List.rev ("import.hx" :: l)) in + let rec loop path pack = match path,pack with + | _,[] -> [join path] + | (p :: path),(_ :: pack) -> (join (p :: path)) :: (loop path pack) + | _ -> [] + in + let candidates = loop path_split (fst m.m_path) in + let make_import_module path r = + Hashtbl.replace ctx.com.parser_cache path r; + (* We use the file path as module name to make it unique. This may or may not be a good idea... *) + let m_import = make_module ctx ([],path) path p in + m_import.m_extra.m_kind <- MImport; + add_module ctx m_import p; + m_import + in + List.fold_left (fun acc path -> + let decls = try + let r = Hashtbl.find ctx.com.parser_cache path in + let mimport = Hashtbl.find ctx.g.modules ([],path) in + if mimport.m_extra.m_kind <> MFake then add_dependency m mimport; + r + with Not_found -> + if Sys.file_exists path then begin + let _,r = parse_file ctx.com path p in + List.iter (fun (d,p) -> match d with EImport _ | EUsing _ -> () | _ -> error "Only import and using is allowed in import.hx files" p) r; + add_dependency m (make_import_module path r); + r + end else begin + let r = [] in + (* Add empty decls so we don't check the file system all the time. *) + (make_import_module path r).m_extra.m_kind <- MFake; + r + end + in + decls @ acc + ) decls candidates + +(* + Creates a new module and types [tdecls] into it. +*) +let type_module ctx mpath file ?(is_extern=false) tdecls p = + let m = make_module ctx mpath file p in + Hashtbl.add ctx.g.modules m.m_path m; + let tdecls = handle_import_hx ctx m tdecls p in + let ctx = type_types_into_module ctx m tdecls p in + if is_extern then m.m_extra.m_kind <- MExtern; + begin if ctx.is_display_file then match ctx.com.display.dms_kind with + | DMResolve s -> + resolve_position_by_path ctx {tname = s; tpackage = []; tsub = None; tparams = []} p + | _ -> + () + end; + m + +let resolve_module_file com m remap p = + let forbid = ref false in + let compose_path no_rename = + (match m with + | [] , name -> name + | x :: l , name -> + let x = (try + match PMap.find x com.package_rules with + | Forbidden -> forbid := true; x + | Directory d -> if no_rename then x else d + | Remap d -> remap := d :: l; d + with Not_found -> x + ) in + String.concat "/" (x :: l) ^ "/" ^ name + ) ^ ".hx" + in + let file = try + Common.find_file com (compose_path false) + with Not_found -> + Common.find_file com (compose_path true) + in + let file = (match String.lowercase (snd m) with + | "con" | "aux" | "prn" | "nul" | "com1" | "com2" | "com3" | "lpt1" | "lpt2" | "lpt3" when Sys.os_type = "Win32" -> + (* these names are reserved by the OS - old DOS legacy, such files cannot be easily created but are reported as visible *) + if (try (Unix.stat file).Unix.st_size with _ -> 0) > 0 then file else raise Not_found + | _ -> file + ) in + (* if we try to load a std.xxxx class and resolve a real std file, the package name is not valid, ignore *) + (match fst m with + | "std" :: _ -> + let file = Path.unique_full_path file in + if List.exists (fun path -> ExtString.String.starts_with file (try Path.unique_full_path path with _ -> path)) com.std_path then raise Not_found; + | _ -> ()); + if !forbid then begin + let _, decls = (!parse_hook) com file p in + let rec loop decls = match decls with + | ((EImport _,_) | (EUsing _,_)) :: decls -> loop decls + | (EClass d,_) :: _ -> d.d_meta + | (EEnum d,_) :: _ -> d.d_meta + | (EAbstract d,_) :: _ -> d.d_meta + | (ETypedef d,_) :: _ -> d.d_meta + | [] -> [] + in + let meta = loop decls in + if not (Meta.has Meta.NoPackageRestrict meta) then begin + let x = (match fst m with [] -> assert false | x :: _ -> x) in + raise (Forbid_package ((x,m,p),[],if Common.defined com Define.Macro then "macro" else platform_name com.platform)); + end; + end; + file + +let parse_module ctx m p = + let remap = ref (fst m) in + let file = resolve_module_file ctx.com m remap p in + let pack, decls = (!parse_hook) ctx.com file p in + if pack <> !remap then begin + let spack m = if m = [] then "" else String.concat "." m in + if p == null_pos then + display_error ctx ("Invalid commandline class : " ^ s_type_path m ^ " should be " ^ s_type_path (pack,snd m)) p + else + display_error ctx ("Invalid package : " ^ spack (fst m) ^ " should be " ^ spack pack) p + end; + file, if !remap <> fst m then + (* build typedefs to redirect to real package *) + List.rev (List.fold_left (fun acc (t,p) -> + let build f d = + let priv = List.mem f d.d_flags in + (ETypedef { + d_name = d.d_name; + d_doc = None; + d_meta = []; + d_params = d.d_params; + d_flags = if priv then [EPrivate] else []; + d_data = CTPath (if priv then { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; } else + { + tpackage = !remap; + tname = fst d.d_name; + tparams = List.map (fun tp -> + TPType (CTPath { tpackage = []; tname = fst tp.tp_name; tparams = []; tsub = None; },null_pos) + ) d.d_params; + tsub = None; + }),null_pos; + },p) :: acc + in + match t with + | EClass d -> build HPrivate d + | EEnum d -> build EPrivate d + | ETypedef d -> build EPrivate d + | EAbstract d -> build APrivAbstract d + | EImport _ | EUsing _ -> acc + ) [(EImport (List.map (fun s -> s,null_pos) (!remap @ [snd m]),INormal),null_pos)] decls) + else + decls + +let load_module ctx m p = + let m2 = (try + Hashtbl.find ctx.g.modules m + with + Not_found -> + match !type_module_hook ctx m p with + | Some m -> m + | None -> + let is_extern = ref false in + let file, decls = (try + parse_module ctx m p + with Not_found -> + let rec loop = function + | [] -> + raise (Error (Module_not_found m,p)) + | load :: l -> + match load m p with + | None -> loop l + | Some (file,(_,a)) -> file, a + in + is_extern := true; + loop ctx.com.load_extern_type + ) in + let is_extern = !is_extern in + try + type_module ctx m file ~is_extern decls p + with Forbid_package (inf,pl,pf) when p <> null_pos -> + raise (Forbid_package (inf,p::pl,pf)) + ) in + add_dependency ctx.m.curmod m2; + if ctx.pass = PTypeField then flush_pass ctx PBuildClass "load_module"; + m2 + +;; +type_function_params_rec := type_function_params + +(* former codegen.ml stuff starting here *) + +(* -------------------------------------------------------------------------- *) +(* REMOTING PROXYS *) + +let extend_remoting ctx c t p async prot = + if c.cl_super <> None then error "Cannot extend several classes" p; + (* remove forbidden packages *) + let rules = ctx.com.package_rules in + ctx.com.package_rules <- PMap.foldi (fun key r acc -> match r with Forbidden -> acc | _ -> PMap.add key r acc) rules PMap.empty; + (* parse module *) + let path = (t.tpackage,t.tname) in + let new_name = (if async then "Async_" else "Remoting_") ^ t.tname in + (* check if the proxy already exists *) + let t = (try + load_type_def ctx p { tpackage = fst path; tname = new_name; tparams = []; tsub = None } + with + Error (Module_not_found _,p2) when p == p2 -> + (* build it *) + Common.log ctx.com ("Building proxy for " ^ s_type_path path); + let file, decls = (try + parse_module ctx path p + with + | Not_found -> ctx.com.package_rules <- rules; error ("Could not load proxy module " ^ s_type_path path ^ (if fst path = [] then " (try using absolute path)" else "")) p + | e -> ctx.com.package_rules <- rules; raise e) in + ctx.com.package_rules <- rules; + let base_fields = [ + { cff_name = "__cnx",null_pos; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = []; cff_kind = FVar (Some (CTPath { tpackage = ["haxe";"remoting"]; tname = if async then "AsyncConnection" else "Connection"; tparams = []; tsub = None },null_pos),None) }; + { cff_name = "new",null_pos; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun { f_args = [("c",null_pos),false,[],None,None]; f_type = None; f_expr = Some (EBinop (OpAssign,(EConst (Ident "__cnx"),p),(EConst (Ident "c"),p)),p); f_params = [] } }; + ] in + let tvoid = CTPath { tpackage = []; tname = "Void"; tparams = []; tsub = None } in + let build_field is_public acc f = + if fst f.cff_name = "new" then + acc + else match f.cff_kind with + | FFun fd when (is_public || List.mem APublic f.cff_access) && not (List.mem AStatic f.cff_access) -> + if List.exists (fun (_,_,_,t,_) -> t = None) fd.f_args then error ("Field " ^ fst f.cff_name ^ " type is not complete and cannot be used by RemotingProxy") p; + let eargs = [EArrayDecl (List.map (fun ((a,_),_,_,_,_) -> (EConst (Ident a),p)) fd.f_args),p] in + let ftype = (match fd.f_type with Some (CTPath { tpackage = []; tname = "Void" },_) -> None | _ -> fd.f_type) in + let fargs, eargs = if async then match ftype with + | Some (tret,_) -> fd.f_args @ [("__callb",null_pos),true,[],Some (CTFunction ([tret,null_pos],(tvoid,null_pos)),null_pos),None], eargs @ [EConst (Ident "__callb"),p] + | _ -> fd.f_args, eargs @ [EConst (Ident "null"),p] + else + fd.f_args, eargs + in + let id = (EConst (String (fst f.cff_name)), p) in + let id = if prot then id else ECall ((EConst (Ident "__unprotect__"),p),[id]),p in + let expr = ECall ( + (EField ( + (ECall ((EField ((EConst (Ident "__cnx"),p),"resolve"),p),[id]),p), + "call") + ,p),eargs),p + in + let expr = if async || ftype = None then expr else (EReturn (Some expr),p) in + let fd = { + f_params = fd.f_params; + f_args = fargs; + f_type = if async then None else ftype; + f_expr = Some (EBlock [expr],p); + } in + { cff_name = f.cff_name; cff_pos = f.cff_pos; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun fd } :: acc + | _ -> acc + in + let decls = List.map (fun d -> + match d with + | EClass c, p when fst c.d_name = t.tname -> + let is_public = List.mem HExtern c.d_flags || List.mem HInterface c.d_flags in + let fields = List.rev (List.fold_left (build_field is_public) base_fields c.d_data) in + (EClass { c with d_flags = []; d_name = new_name,pos c.d_name; d_data = fields },p) + | _ -> d + ) decls in + let m = type_module ctx (t.tpackage,new_name) file decls p in + add_dependency ctx.m.curmod m; + try + List.find (fun tdecl -> snd (t_path tdecl) = new_name) m.m_types + with Not_found -> + error ("Module " ^ s_type_path path ^ " does not define type " ^ t.tname) p + ) in + match t with + | TClassDecl c2 when c2.cl_params = [] -> ignore(c2.cl_build()); c.cl_super <- Some (c2,[]); + | _ -> error "Remoting proxy must be a class without parameters" p + +(* -------------------------------------------------------------------------- *) +(* HAXE.RTTI.GENERIC *) + +exception Generic_Exception of string * pos + +type generic_context = { + ctx : typer; + subst : (t * t) list; + name : string; + p : pos; + mutable mg : module_def option; +} + +let make_generic ctx ps pt p = + let rec loop l1 l2 = + match l1, l2 with + | [] , [] -> [] + | (x,TLazy f) :: l1, _ -> loop ((x,(!f)()) :: l1) l2 + | (_,t1) :: l1 , t2 :: l2 -> (t1,t2) :: loop l1 l2 + | _ -> assert false + in + let name = + String.concat "_" (List.map2 (fun (s,_) t -> + let s_type_path_underscore (p,s) = match p with [] -> s | _ -> String.concat "_" p ^ "_" ^ s in + let rec loop top t = match follow t with + | TInst(c,tl) -> (s_type_path_underscore c.cl_path) ^ (loop_tl tl) + | TEnum(en,tl) -> (s_type_path_underscore en.e_path) ^ (loop_tl tl) + | TAbstract(a,tl) -> (s_type_path_underscore a.a_path) ^ (loop_tl tl) + | _ when not top -> "_" (* allow unknown/incompatible types as type parameters to retain old behavior *) + | TMono _ -> raise (Generic_Exception (("Could not determine type for parameter " ^ s), p)) + | TDynamic _ -> "Dynamic" + | t -> raise (Generic_Exception (("Type parameter must be a class or enum instance (found " ^ (s_type (print_context()) t) ^ ")"), p)) + and loop_tl tl = match tl with + | [] -> "" + | tl -> "_" ^ String.concat "_" (List.map (loop false) tl) + in + loop true t + ) ps pt) + in + { + ctx = ctx; + subst = loop ps pt; + name = name; + p = p; + mg = None; + } + +let rec generic_substitute_type gctx t = + match t with + | TInst ({ cl_kind = KGeneric } as c2,tl2) -> + (* maybe loop, or generate cascading generics *) + let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c2) gctx.p in + let t = f (List.map (generic_substitute_type gctx) tl2) in + (match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ()); + t + | _ -> + try + generic_substitute_type gctx (List.assq t gctx.subst) + with Not_found -> + Type.map (generic_substitute_type gctx) t + +let generic_substitute_expr gctx e = + let vars = Hashtbl.create 0 in + let build_var v = + try + Hashtbl.find vars v.v_id + with Not_found -> + let v2 = alloc_var v.v_name (generic_substitute_type gctx v.v_type) v.v_pos in + v2.v_meta <- v.v_meta; + Hashtbl.add vars v.v_id v2; + v2 + in + let rec build_expr e = + match e.eexpr with + | TField(e1, FInstance({cl_kind = KGeneric} as c,tl,cf)) -> + let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c) gctx.p in + let t = f (List.map (generic_substitute_type gctx) tl) in + let fa = try + quick_field t cf.cf_name + with Not_found -> + error (Printf.sprintf "Type %s has no field %s (possible typing order issue)" (s_type (print_context()) t) cf.cf_name) e.epos + in + build_expr {e with eexpr = TField(e1,fa)} + | TTypeExpr (TClassDecl ({cl_kind = KTypeParameter _;} as c)) when Meta.has Meta.Const c.cl_meta -> + let rec loop subst = match subst with + | (t1,t2) :: subst -> + begin match follow t1 with + | TInst(c2,_) when c == c2 -> t2 + | _ -> loop subst + end + | [] -> raise Not_found + in + begin try + let t = loop gctx.subst in + begin match follow t with + | TInst({cl_kind = KExpr e},_) -> type_expr gctx.ctx e Value + | _ -> error "Only Const type parameters can be used as value" e.epos + end + with Not_found -> + e + end + | _ -> + map_expr_type build_expr (generic_substitute_type gctx) build_var e + in + build_expr e + +let get_short_name = + let i = ref (-1) in + (fun () -> + incr i; + Printf.sprintf "Hx___short___hx_type_%i" !i + ) + +let rec build_generic ctx c p tl = + let pack = fst c.cl_path in + let recurse = ref false in + let rec check_recursive t = + match follow t with + | TInst (c2,tl) -> + (match c2.cl_kind with + | KTypeParameter tl -> + if not (is_generic_parameter ctx c2) && has_ctor_constraint c2 then + error "Type parameters with a constructor cannot be used non-generically" p; + recurse := true + | _ -> ()); + List.iter check_recursive tl; + | _ -> + () + in + List.iter check_recursive tl; + if !recurse || not (ctx.com.display.dms_full_typing) then begin + TInst (c,tl) (* build a normal instance *) + end else begin + let gctx = make_generic ctx c.cl_params tl p in + let name = (snd c.cl_path) ^ "_" ^ gctx.name in + try + load_instance ctx ({ tpackage = pack; tname = name; tparams = []; tsub = None },p) false p + with Error(Module_not_found path,_) when path = (pack,name) -> + let m = (try Hashtbl.find ctx.g.modules (Hashtbl.find ctx.g.types_module c.cl_path) with Not_found -> assert false) in + (* let ctx = { ctx with m = { ctx.m with module_types = m.m_types @ ctx.m.module_types } } in *) + ignore(c.cl_build()); (* make sure the super class is already setup *) + let mg = { + m_id = alloc_mid(); + m_path = (pack,name); + m_types = []; + m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake m.m_extra.m_check_policy; + } in + gctx.mg <- Some mg; + let cg = mk_class mg (pack,name) c.cl_pos null_pos in + mg.m_types <- [TClassDecl cg]; + Hashtbl.add ctx.g.modules mg.m_path mg; + add_dependency mg m; + add_dependency ctx.m.curmod mg; + (* ensure that type parameters are set in dependencies *) + let dep_stack = ref [] in + let rec loop t = + if not (List.memq t !dep_stack) then begin + dep_stack := t :: !dep_stack; + match t with + | TInst (c,tl) -> add_dep c.cl_module tl + | TEnum (e,tl) -> add_dep e.e_module tl + | TType (t,tl) -> add_dep t.t_module tl + | TAbstract (a,tl) -> add_dep a.a_module tl + | TMono r -> + (match !r with + | None -> () + | Some t -> loop t) + | TLazy f -> + loop ((!f)()); + | TDynamic t2 -> + if t == t2 then () else loop t2 + | TAnon a -> + PMap.iter (fun _ f -> loop f.cf_type) a.a_fields + | TFun (args,ret) -> + List.iter (fun (_,_,t) -> loop t) args; + loop ret + end + and add_dep m tl = + add_dependency mg m; + List.iter loop tl + in + List.iter loop tl; + let build_field cf_old = + (* We have to clone the type parameters (issue #4672). We cannot substitute the constraints immediately because + we need the full substitution list first. *) + let param_subst,params = List.fold_left (fun (subst,params) (s,t) -> match follow t with + | TInst(c,tl) as t -> + let t2 = TInst({c with cl_pos = c.cl_pos;},tl) in + (t,t2) :: subst,(s,t2) :: params + | _ -> assert false + ) ([],[]) cf_old.cf_params in + let gctx = {gctx with subst = param_subst @ gctx.subst} in + let cf_new = {cf_old with cf_pos = cf_old.cf_pos} in (* copy *) + (* Type parameter constraints are substituted here. *) + cf_new.cf_params <- List.rev_map (fun (s,t) -> match follow t with + | TInst({cl_kind = KTypeParameter tl1} as c,_) -> + let tl1 = List.map (generic_substitute_type gctx) tl1 in + c.cl_kind <- KTypeParameter tl1; + s,t + | _ -> assert false + ) params; + let f () = + let t = generic_substitute_type gctx cf_old.cf_type in + ignore (follow t); + begin try (match cf_old.cf_expr with + | None -> + begin match cf_old.cf_kind with + | Method _ when not c.cl_interface && not c.cl_extern -> + display_error ctx (Printf.sprintf "Field %s has no expression (possible typing order issue)" cf_new.cf_name) cf_new.cf_pos; + display_error ctx (Printf.sprintf "While building %s" (s_type_path cg.cl_path)) p; + | _ -> + () + end + | Some e -> + cf_new.cf_expr <- Some (generic_substitute_expr gctx e) + ) with Unify_error l -> + error (error_msg (Unify l)) cf_new.cf_pos + end; + t + in + let r = exc_protect ctx (fun r -> + let t = mk_mono() in + r := (fun() -> t); + unify_raise ctx (f()) t p; + t + ) "build_generic" in + delay ctx PForce (fun() -> ignore ((!r)())); + cf_new.cf_type <- TLazy r; + cf_new + in + if c.cl_init <> None || c.cl_dynamic <> None then error "This class can't be generic" p; + List.iter (fun cf -> match cf.cf_kind with + | Method MethMacro when not ctx.in_macro -> () + | _ -> error "A generic class can't have static fields" cf.cf_pos + ) c.cl_ordered_statics; + cg.cl_super <- (match c.cl_super with + | None -> None + | Some (cs,pl) -> + let find_class subst = + let rec loop subst = match subst with + | (TInst(c,[]),t) :: subst when c == cs -> t + | _ :: subst -> loop subst + | [] -> raise Not_found + in + try + if pl <> [] then raise Not_found; + let t = loop subst in + (* extended type parameter: concrete type must have a constructor, but generic base class must not have one *) + begin match follow t,c.cl_constructor with + | TInst(cs,_),None -> + ignore(cs.cl_build()); + begin match cs.cl_constructor with + | None -> error ("Cannot use " ^ (s_type_path cs.cl_path) ^ " as type parameter because it is extended and has no constructor") p + | _ -> () + end; + | _,Some cf -> error "Generics extending type parameters cannot have constructors" cf.cf_pos + | _ -> () + end; + t + with Not_found -> + apply_params c.cl_params tl (TInst(cs,pl)) + in + let ts = follow (find_class gctx.subst) in + let cs,pl = Inheritance.check_extends ctx c ts p in + match cs.cl_kind with + | KGeneric -> + (match build_generic ctx cs p pl with + | TInst (cs,pl) -> Some (cs,pl) + | _ -> assert false) + | _ -> Some(cs,pl) + ); + add_constructor ctx cg false p; + cg.cl_kind <- KGenericInstance (c,tl); + cg.cl_meta <- (Meta.NoDoc,[],null_pos) :: cg.cl_meta; + if has_meta Meta.Keep c.cl_meta then cg.cl_meta <- (Meta.Keep,[],null_pos) :: cg.cl_meta; + cg.cl_interface <- c.cl_interface; + cg.cl_constructor <- (match cg.cl_constructor, c.cl_constructor, c.cl_super with + | _, Some cf, _ -> Some (build_field cf) + | Some ctor, _, _ -> Some ctor + | None, None, None -> None + | _ -> error "Please define a constructor for this class in order to use it as generic" c.cl_pos + ); + cg.cl_implements <- List.map (fun (i,tl) -> + (match follow (generic_substitute_type gctx (TInst (i, List.map (generic_substitute_type gctx) tl))) with + | TInst (i,tl) -> i, tl + | _ -> assert false) + ) c.cl_implements; + cg.cl_ordered_fields <- List.map (fun f -> + let f = build_field f in + cg.cl_fields <- PMap.add f.cf_name f cg.cl_fields; + f + ) c.cl_ordered_fields; + cg.cl_overrides <- List.map (fun f -> + try PMap.find f.cf_name cg.cl_fields with Not_found -> assert false + ) c.cl_overrides; + (* In rare cases the class name can become too long, so let's shorten it (issue #3090). *) + if String.length (snd cg.cl_path) > 254 then begin + let n = get_short_name () in + cg.cl_meta <- (Meta.Native,[EConst(String (n)),p],null_pos) :: cg.cl_meta; + end; + TInst (cg,[]) + end + +(* -------------------------------------------------------------------------- *) +(* HAXE.XML.PROXY *) + +let extend_xml_proxy ctx c t file p = + let t = load_complex_type ctx false p (t,p) in + let file = (try Common.find_file ctx.com file with Not_found -> file) in + add_dependency c.cl_module (create_fake_module ctx file); + let used = ref PMap.empty in + let print_results() = + PMap.iter (fun id used -> + if not used then ctx.com.warning (id ^ " is not used") p; + ) (!used) + in + let check_used = Common.defined ctx.com Define.CheckXmlProxy in + if check_used then ctx.g.hook_generate <- print_results :: ctx.g.hook_generate; + try + let rec loop = function + | Xml.Element (_,attrs,childs) -> + (try + let id = List.assoc "id" attrs in + if PMap.mem id c.cl_fields then error ("Duplicate id " ^ id) p; + let t = if not check_used then t else begin + used := PMap.add id false (!used); + let ft() = used := PMap.add id true (!used); t in + TLazy (ref ft) + end in + let f = { + cf_name = id; + cf_type = t; + cf_public = true; + cf_pos = p; + cf_name_pos = null_pos; + cf_doc = None; + cf_meta = no_meta; + cf_kind = Var { v_read = AccResolve; v_write = AccNo }; + cf_params = []; + cf_expr = None; + cf_expr_unoptimized = None; + cf_overloads = []; + } in + c.cl_fields <- PMap.add id f c.cl_fields; + with + Not_found -> ()); + List.iter loop childs; + | Xml.PCData _ -> () + in + loop (Xml.parse_file file) + with + | Xml.Error e -> error ("XML error " ^ Xml.error e) p + | Xml.File_not_found f -> error ("XML File not found : " ^ f) p + +(* -------------------------------------------------------------------------- *) +(* MACRO TYPE *) + +let get_macro_path ctx e args p = + let rec loop e = + match fst e with + | EField (e,f) -> f :: loop e + | EConst (Ident i) -> [i] + | _ -> error "Invalid macro call" p + in + let path = match e with + | (EConst(Ident i)),_ -> + let path = try + if not (PMap.mem i ctx.curclass.cl_statics) then raise Not_found; + ctx.curclass.cl_path + with Not_found -> try + (t_infos (let path,_,_ = PMap.find i ctx.m.module_globals in path)).mt_path + with Not_found -> + error "Invalid macro call" p + in + i :: (snd path) :: (fst path) + | _ -> + loop e + in + (match path with + | meth :: cl :: path -> (List.rev path,cl), meth, args + | _ -> error "Invalid macro call" p) + +let build_macro_type ctx pl p = + let path, field, args = (match pl with + | [TInst ({ cl_kind = KExpr (ECall (e,args),_) },_)] + | [TInst ({ cl_kind = KExpr (EArrayDecl [ECall (e,args),_],_) },_)] -> + get_macro_path ctx e args p + | _ -> + error "MacroType requires a single expression call parameter" p + ) in + let old = ctx.ret in + let t = (match ctx.g.do_macro ctx MMacroType path field args p with + | None -> mk_mono() + | Some _ -> ctx.ret + ) in + ctx.ret <- old; + t + +let build_macro_build ctx c pl cfl p = + let path, field, args = match Meta.get Meta.GenericBuild c.cl_meta with + | _,[ECall(e,args),_],_ -> get_macro_path ctx e args p + | _ -> error "genericBuild requires a single expression call parameter" p + in + let old = ctx.ret,ctx.g.get_build_infos in + ctx.g.get_build_infos <- (fun() -> Some (TClassDecl c, pl, cfl)); + let t = (match ctx.g.do_macro ctx MMacroType path field args p with + | None -> mk_mono() + | Some _ -> ctx.ret + ) in + ctx.ret <- fst old; + ctx.g.get_build_infos <- snd old; + t + +(* -------------------------------------------------------------------------- *) +(* API EVENTS *) + +let build_instance ctx mtype p = + match mtype with + | TClassDecl c -> + if ctx.pass > PBuildClass then ignore(c.cl_build()); + let build f s = + let r = exc_protect ctx (fun r -> + let t = mk_mono() in + r := (fun() -> t); + let tf = (f()) in + unify_raise ctx tf t p; + link_dynamic t tf; + t + ) s in + delay ctx PForce (fun() -> ignore ((!r)())); + TLazy r + in + let ft = (fun pl -> + match c.cl_kind with + | KGeneric -> + build (fun () -> build_generic ctx c p pl) "build_generic" + | KMacroType -> + build (fun () -> build_macro_type ctx pl p) "macro_type" + | KGenericBuild cfl -> + build (fun () -> build_macro_build ctx c pl cfl p) "generic_build" + | _ -> + TInst (c,pl) + ) in + c.cl_params , c.cl_path , ft + | TEnumDecl e -> + e.e_params , e.e_path , (fun t -> TEnum (e,t)) + | TTypeDecl t -> + t.t_params , t.t_path , (fun tl -> TType(t,tl)) + | TAbstractDecl a -> + a.a_params, a.a_path, (fun tl -> TAbstract(a,tl)) + +let on_inherit ctx c p (is_extends,tp) = + if not is_extends then + true + else match fst tp with + | { tpackage = ["haxe";"remoting"]; tname = "Proxy"; tparams = [TPType(CTPath t,null_pos)] } -> + extend_remoting ctx c t p false true; + false + | { tpackage = ["haxe";"remoting"]; tname = "AsyncProxy"; tparams = [TPType(CTPath t,null_pos)] } -> + extend_remoting ctx c t p true true; + false + | { tpackage = ["haxe";"xml"]; tname = "Proxy"; tparams = [TPExpr(EConst (String file),p);TPType (t,_)] } -> + extend_xml_proxy ctx c t file p; + true + | _ -> + true diff --git a/typer.ml b/src/typing/typer.ml similarity index 58% rename from typer.ml rename to src/typing/typer.ml index 2ddf7ed6..919758a1 100644 --- a/typer.ml +++ b/src/typing/typer.ml @@ -1,29 +1,29 @@ (* - * Copyright (C)2005-2013 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. + The Haxe Compiler + Copyright (C) 2005-2017 Haxe Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) open Ast -open Type +open Common.DisplayMode open Common +open Type open Typecore +open Error +open Globals (* ---------------------------------------------------------------------- *) (* TOOLS *) @@ -37,27 +37,6 @@ type access_mode = | MSet | MCall -type identifier_type = - | ITLocal of tvar - | ITMember of tclass * tclass_field - | ITStatic of tclass * tclass_field - | ITEnum of tenum * tenum_field - | ITGlobal of module_type * string * t - | ITType of module_type - | ITPackage of string - -(* order of these variants affects output sorting *) -type display_field_kind = - | FKVar - | FKMethod - | FKType - | FKPackage - -exception DisplayFields of (string * t * display_field_kind option * documentation) list -exception DisplayToplevel of identifier_type list - -exception WithTypeError of unify_error list * pos - type access_kind = | AKNo of string | AKExpr of texpr @@ -67,18 +46,23 @@ type access_kind = | AKUsing of texpr * tclass * tclass_field * texpr | AKAccess of tabstract * tparams * tclass * texpr * texpr +type object_decl_kind = + | ODKWithStructure of tanon + | ODKWithClass of tclass * tparams + | ODKPlain + let build_call_ref : (typer -> access_kind -> expr list -> with_type -> pos -> texpr) ref = ref (fun _ _ _ _ _ -> assert false) let mk_infos ctx p params = - let file = if ctx.in_macro then p.pfile else if Common.defined ctx.com Define.AbsolutePath then Common.get_full_path p.pfile else Filename.basename p.pfile in + let file = if ctx.in_macro then p.pfile else if Common.defined ctx.com Define.AbsolutePath then Path.get_full_path p.pfile else Filename.basename p.pfile in (EObjectDecl ( - ("fileName" , (EConst (String file) , p)) :: - ("lineNumber" , (EConst (Int (string_of_int (Lexer.get_error_line p))),p)) :: - ("className" , (EConst (String (s_type_path ctx.curclass.cl_path)),p)) :: + (("fileName",null_pos) , (EConst (String file) , p)) :: + (("lineNumber",null_pos) , (EConst (Int (string_of_int (Lexer.get_error_line p))),p)) :: + (("className",null_pos) , (EConst (String (s_type_path ctx.curclass.cl_path)),p)) :: if ctx.curfield.cf_name = "" then params else - ("methodName", (EConst (String ctx.curfield.cf_name),p)) :: params + (("methodName",null_pos), (EConst (String ctx.curfield.cf_name),p)) :: params ) ,p) let check_assign ctx e = @@ -138,6 +122,20 @@ let get_iterable_param t = raise Not_found) | _ -> raise Not_found +let get_abstract_froms a pl = + let l = List.map (apply_params a.a_params pl) a.a_from in + List.fold_left (fun acc (t,f) -> + match follow (field_type f) with + | TFun ([_,_,v],t) -> + (try + ignore(type_eq EqStrict t (TAbstract(a,List.map dup pl))); (* unify fields monomorphs *) + v :: acc + with Unify_error _ -> + acc) + | _ -> + acc + ) l a.a_from_field + (* temporally remove the constant flag from structures to allow larger unification *) @@ -320,7 +318,7 @@ let rec can_access ctx ?(in_overload=false) c cf stat = b (* removes the first argument of the class field's function type and all its overloads *) -let prepare_using_field cf = match cf.cf_type with +let prepare_using_field cf = match follow cf.cf_type with | TFun((_,_,tf) :: args,ret) -> let rec loop acc overloads = match overloads with | ({cf_type = TFun((_,_,tfo) :: args,ret)} as cfo) :: l -> @@ -335,49 +333,21 @@ let prepare_using_field cf = match cf.cf_type with {cf with cf_overloads = loop [] cf.cf_overloads; cf_type = TFun(args,ret)} | _ -> cf -let parse_string com s p inlined = - let old = Lexer.save() in - let old_file = (try Some (Hashtbl.find Lexer.all_files p.pfile) with Not_found -> None) in - let old_display = !Parser.resume_display in - let old_de = !Parser.display_error in - let restore() = - (match old_file with - | None -> () - | Some f -> Hashtbl.replace Lexer.all_files p.pfile f); - if not inlined then Parser.resume_display := old_display; - Lexer.restore old; - Parser.display_error := old_de - in - Lexer.init p.pfile true; - Parser.display_error := (fun e p -> raise (Parser.Error (e,p))); - if not inlined then Parser.resume_display := null_pos; - let pack, decls = try - Parser.parse com (Lexing.from_string s) - with Parser.Error (e,pe) -> - restore(); - error (Parser.error_msg e) (if inlined then pe else p) - | Lexer.Error (e,pe) -> - restore(); - error (Lexer.error_msg e) (if inlined then pe else p) - in - restore(); - pack,decls - let eval ctx s = let p = { pfile = "--eval"; pmin = 0; pmax = String.length s; } in - let pack,decls = parse_string ctx.com s p false in + let pack,decls = Parser.parse_string ctx.com s p error false in let rec find_main current decls = match decls with | (EClass c,_) :: decls -> - let path = pack,c.d_name in + let path = pack,fst c.d_name in begin try - let cff = List.find (fun cff -> cff.cff_name = "main") c.d_data in + let cff = List.find (fun cff -> fst cff.cff_name = "main") c.d_data in if ctx.com.main_class <> None then error "Multiple main" cff.cff_pos; ctx.com.main_class <- Some path; Some path with Not_found -> find_main (if current = None then Some path else current) decls end - | ((EEnum {d_name = s} | ETypedef {d_name = s} | EAbstract {d_name = s}),_) :: decls when current = None -> + | ((EEnum {d_name = (s,_)} | ETypedef {d_name = (s,_)} | EAbstract {d_name = (s,_)}),_) :: decls when current = None -> find_main (Some (pack,s)) decls | _ :: decls -> find_main current decls @@ -391,185 +361,57 @@ let eval ctx s = ignore(Typeload.type_module ctx path_module "eval" decls p); flush_pass ctx PBuildClass "eval" -let parse_expr_string ctx s p inl = - let head = "class X{static function main() " in - let head = (if p.pmin > String.length head then head ^ String.make (p.pmin - String.length head) ' ' else head) in - let rec loop e = let e = Ast.map_expr loop e in (fst e,p) in - match parse_string ctx.com (head ^ s ^ ";}") p inl with - | _,[EClass { d_data = [{ cff_name = "main"; cff_kind = FFun { f_expr = Some e } }]},_] -> if inl then e else loop e - | _ -> raise Interp.Invalid_expr - -let collect_toplevel_identifiers ctx = - let acc = DynArray.create () in - - (* locals *) - PMap.iter (fun _ v -> - if not (is_gen_local v) then - DynArray.add acc (ITLocal v) - ) ctx.locals; - - (* member vars *) - if ctx.curfun <> FunStatic then begin - let rec loop c = - List.iter (fun cf -> - DynArray.add acc (ITMember(ctx.curclass,cf)) - ) c.cl_ordered_fields; - match c.cl_super with - | None -> - () - | Some (csup,tl) -> - loop csup; (* TODO: type parameters *) - in - loop ctx.curclass; - (* TODO: local using? *) - end; - - (* statics *) - List.iter (fun cf -> - DynArray.add acc (ITStatic(ctx.curclass,cf)) - ) ctx.curclass.cl_ordered_statics; - - (* enum constructors *) - let rec enum_ctors t = - match t with - | TClassDecl _ | TAbstractDecl _ -> - () - | TTypeDecl t -> - begin match follow t.t_type with - | TEnum (e,_) -> enum_ctors (TEnumDecl e) - | _ -> () - end - | TEnumDecl e -> - PMap.iter (fun _ ef -> - DynArray.add acc (ITEnum(e,ef)) - ) e.e_constrs; - in - List.iter enum_ctors ctx.m.curmod.m_types; - List.iter enum_ctors ctx.m.module_types; - - (* imported globals *) - PMap.iter (fun _ (mt,s) -> - try - let t = match Typeload.resolve_typedef mt with - | TClassDecl c -> (PMap.find s c.cl_statics).cf_type - | TEnumDecl en -> (PMap.find s en.e_constrs).ef_type - | TAbstractDecl {a_impl = Some c} -> (PMap.find s c.cl_statics).cf_type - | _ -> raise Not_found - in - DynArray.add acc (ITGlobal(mt,s,t)) - with Not_found -> - () - ) ctx.m.module_globals; - - let module_types = ref [] in - - let add_type mt = - match mt with - | TClassDecl {cl_kind = KAbstractImpl _} -> () - | _ -> - let path = (t_infos mt).mt_path in - if not (List.exists (fun mt2 -> (t_infos mt2).mt_path = path) !module_types) then module_types := mt :: !module_types - in - - (* module types *) - List.iter add_type ctx.m.curmod.m_types; - - (* module imports *) - List.iter add_type ctx.m.module_types; - - (* module using *) - List.iter (fun c -> - add_type (TClassDecl c) - ) ctx.m.module_using; - - (* TODO: wildcard packages. How? *) - - (* packages and toplevel types *) - let class_paths = ctx.com.class_path in - let class_paths = List.filter (fun s -> s <> "") class_paths in - - let packages = ref [] in - let add_package pack = - try - begin match PMap.find pack ctx.com.package_rules with - | Forbidden -> - () - | _ -> - raise Not_found - end - with Not_found -> - if not (List.mem pack !packages) then packages := pack :: !packages +let merge_core_doc ctx c = + let c_core = Typeload.load_core_class ctx c in + if c.cl_doc = None then c.cl_doc <- c_core.cl_doc; + let maybe_merge cf_map cf = + if cf.cf_doc = None then try cf.cf_doc <- (PMap.find cf.cf_name cf_map).cf_doc with Not_found -> () in + List.iter (maybe_merge c_core.cl_fields) c.cl_ordered_fields; + List.iter (maybe_merge c_core.cl_statics) c.cl_ordered_statics; + match c.cl_constructor,c_core.cl_constructor with + | Some ({cf_doc = None} as cf),Some cf2 -> cf.cf_doc <- cf2.cf_doc + | _ -> () - List.iter (fun dir -> - try - let entries = Sys.readdir dir in - Array.iter (fun file -> - match file with - | "." | ".." -> - () - | _ when Sys.is_directory (dir ^ file) -> - add_package file - | _ -> - let l = String.length file in - if l > 3 && String.sub file (l - 3) 3 = ".hx" then begin - try - let name = String.sub file 0 (l - 3) in - let md = Typeload.load_module ctx ([],name) Ast.null_pos in - List.iter (fun mt -> - if (t_infos mt).mt_path = md.m_path then add_type mt - ) md.m_types - with _ -> - () - end - ) entries; - with Sys_error _ -> - () - ) class_paths; - - List.iter (fun pack -> - DynArray.add acc (ITPackage pack) - ) !packages; - - List.iter (fun mt -> - DynArray.add acc (ITType mt) - ) !module_types; - - raise (DisplayToplevel (DynArray.to_list acc)) +let check_error ctx err p = match err with + | Module_not_found ([],name) when Display.Diagnostics.is_diagnostics_run ctx -> + Display.ToplevelCollector.handle_unresolved_identifier ctx name p true + | _ -> + display_error ctx (error_msg err) p (* ---------------------------------------------------------------------- *) (* PASS 3 : type expression & check structure *) -let rec base_params t = - let tl = ref [] in - let rec loop t = (match t with - | TInst(cl, params) -> - (match cl.cl_kind with - | KTypeParameter tl -> List.iter loop tl - | _ -> ()); - List.iter (fun (ic, ip) -> - let t = apply_params cl.cl_params params (TInst (ic,ip)) in - loop t - ) cl.cl_implements; - (match cl.cl_super with None -> () | Some (csup, pl) -> - let t = apply_params cl.cl_params params (TInst (csup,pl)) in - loop t); - tl := t :: !tl; - | TEnum(en,(_ :: _ as tl2)) -> - tl := (TEnum(en,List.map (fun _ -> t_dynamic) tl2)) :: !tl; - tl := t :: !tl; - | TType (td,pl) -> - loop (apply_params td.t_params pl td.t_type); - (* prioritize the most generic definition *) - tl := t :: !tl; - | TLazy f -> loop (!f()) - | TMono r -> (match !r with None -> () | Some t -> loop t) - | _ -> tl := t :: !tl) - in - loop t; - !tl - let rec unify_min_raise ctx (el:texpr list) : t = + let rec base_types t = + let tl = ref [] in + let rec loop t = (match t with + | TInst(cl, params) -> + (match cl.cl_kind with + | KTypeParameter tl -> List.iter loop tl + | _ -> ()); + List.iter (fun (ic, ip) -> + let t = apply_params cl.cl_params params (TInst (ic,ip)) in + loop t + ) cl.cl_implements; + (match cl.cl_super with None -> () | Some (csup, pl) -> + let t = apply_params cl.cl_params params (TInst (csup,pl)) in + loop t); + tl := t :: !tl; + | TEnum(en,(_ :: _ as tl2)) -> + tl := (TEnum(en,List.map (fun _ -> t_dynamic) tl2)) :: !tl; + tl := t :: !tl; + | TType (td,pl) -> + loop (apply_params td.t_params pl td.t_type); + (* prioritize the most generic definition *) + tl := t :: !tl; + | TLazy f -> loop (!f()) + | TMono r -> (match !r with None -> () | Some t -> loop t) + | _ -> tl := t :: !tl) + in + loop t; + !tl + in match el with | [] -> mk_mono() | [e] -> e.etype @@ -625,13 +467,13 @@ let rec unify_min_raise ctx (el:texpr list) : t = ) PMap.empty el in let fields = PMap.foldi (fun n el acc -> let t = try unify_min_raise ctx el with Error (Unify _, _) -> raise Not_found in - PMap.add n (mk_field n t (List.hd el).epos) acc + PMap.add n (mk_field n t (List.hd el).epos null_pos) acc ) fields PMap.empty in TAnon { a_fields = fields; a_status = ref Closed } with Not_found -> (* Second pass: Get all base types (interfaces, super classes and their interfaces) of most general type. Then for each additional type filter all types that do not unify. *) - let common_types = base_params t in + let common_types = base_types t in let dyn_types = List.fold_left (fun acc t -> let rec loop c = Meta.has Meta.UnifyMinDynamic c.cl_meta || (match c.cl_super with None -> false | Some (c,_) -> loop c) @@ -673,11 +515,13 @@ let is_forced_inline c cf = | _ -> false let rec unify_call_args' ctx el args r callp inline force_inline = + let in_call_args = ctx.in_call_args in + ctx.in_call_args <- true; let call_error err p = raise (Error (Call_error err,p)) in let arg_error ul name opt p = - let err = Stack (Unify ul,Custom ("For " ^ (if opt then "optional " else "") ^ "function argument '" ^ name ^ "'")) in + let err = Stack (ul,Custom ("For " ^ (if opt then "optional " else "") ^ "function argument '" ^ name ^ "'")) in call_error (Could_not_unify err) p in let mk_pos_infos t = @@ -691,19 +535,27 @@ let rec unify_call_args' ctx el args r callp inline force_inline = null (ctx.t.tnull t) callp in let skipped = ref [] in - let skip name ul t = + let invalid_skips = ref [] in + let skip name ul t p = if not ctx.com.config.pf_can_skip_non_nullable_argument && not (is_nullable t) then - call_error (Cannot_skip_non_nullable name) callp; - skipped := (name,ul) :: !skipped; + invalid_skips := name :: !invalid_skips; + skipped := (name,ul,p) :: !skipped; default_value name t in (* let force_inline, is_extern = match cf with Some(TInst(c,_),f) -> is_forced_inline (Some c) f, c.cl_extern | _ -> false, false in *) let type_against t e = - let e = type_expr ctx e (WithTypeResume t) in - (try Codegen.AbstractCast.cast_or_unify_raise ctx t e e.epos with Error (Unify l,p) -> raise (WithTypeError (l,p))); + try + let e = type_expr ctx e (WithType t) in + AbstractCast.cast_or_unify_raise ctx t e e.epos + with Error(l,p) when (match l with Call_error _ | Module_not_found _ -> false | _ -> true) -> + raise (WithTypeError (l,p)) in let rec loop el args = match el,args with | [],[] -> + begin match List.rev !invalid_skips with + | [] -> () + | name :: _ -> call_error (Cannot_skip_non_nullable name) callp; + end; [] | _,[name,false,t] when (match follow t with TAbstract({a_path = ["haxe";"extern"],"Rest"},_) -> true | _ -> false) -> begin match follow t with @@ -713,7 +565,7 @@ let rec unify_call_args' ctx el args r callp inline force_inline = assert false end | [],(_,false,_) :: _ -> - call_error Not_enough_arguments callp + call_error (Not_enough_arguments args) callp | [],(name,true,t) :: args -> begin match loop [] args with | [] when not (inline && (ctx.g.doinline || force_inline)) && not ctx.com.config.pf_pad_nulls -> @@ -726,22 +578,23 @@ let rec unify_call_args' ctx el args r callp inline force_inline = | (_,p) :: _, [] -> begin match List.rev !skipped with | [] -> call_error Too_many_arguments p - | (s,ul) :: _ -> arg_error ul s true p + | (s,ul,p) :: _ -> arg_error ul s true p end | e :: el,(name,opt,t) :: args -> begin try let e = type_against t e in (e,opt) :: loop el args with - WithTypeError (ul,p) -> + WithTypeError (ul,p)-> if opt then - let e_def = skip name ul t in + let e_def = skip name ul t p in (e_def,true) :: loop (e :: el) args else arg_error ul name false p end in - let el = loop el args in + let el = try loop el args with exc -> ctx.in_call_args <- in_call_args; raise exc; in + ctx.in_call_args <- in_call_args; el,TFun(args,r) let unify_call_args ctx el args r p inline force_inline = @@ -778,7 +631,7 @@ let unify_field_call ctx fa el args ret p inline = let cfl = if cf.cf_name = "new" || not (Meta.has Meta.Overload cf.cf_meta && ctx.com.config.pf_overload) then List.map (map_cf cf map) cf.cf_overloads else - List.map (fun (t,cf) -> map (monomorphs cf.cf_params t),cf) (Typeload.get_overloads c cf.cf_name) + List.map (fun (t,cf) -> map (monomorphs cf.cf_params t),cf) (Overloads.get_overloads c cf.cf_name) in (TFun(args,ret),cf) :: cfl,Some c,cf,(fun cf -> FInstance(c,tl,cf)) | FClosure(co,cf) -> @@ -789,57 +642,110 @@ let unify_field_call ctx fa el args ret p inline = in let is_forced_inline = is_forced_inline co cf in let is_overload = Meta.has Meta.Overload cf.cf_meta in + let attempt_call t cf = match follow t with + | TFun(args,ret) -> + let el,tf = unify_call_args' ctx el args ret p inline is_forced_inline in + let mk_call ethis p_field = + let ef = mk (TField(ethis,mk_fa cf)) tf p_field in + make_call ctx ef (List.map fst el) ret p + in + el,tf,mk_call + | _ -> + assert false + in let rec loop candidates = match candidates with | [] -> [],[] | (t,cf) :: candidates -> begin try - begin match follow t with - | TFun(args,ret) -> - let el,tf = unify_call_args' ctx el args ret p inline is_forced_inline in - let mk_call ethis p_field = - let ef = mk (TField(ethis,mk_fa cf)) tf p_field in - make_call ctx ef (List.map fst el) ret p - in - let candidate = (el,tf,mk_call) in - if ctx.com.config.pf_overload && is_overload then begin - let candidates,failures = loop candidates in - candidate :: candidates,failures - end else - [candidate],[] - | _ -> - assert false - end - with Error (Call_error _,_) as err -> + let candidate = attempt_call t cf in + if ctx.com.config.pf_overload && is_overload then begin + let candidates,failures = loop candidates in + candidate :: candidates,failures + end else + [candidate],[] + with Error ((Call_error _ as err),p) -> let candidates,failures = loop candidates in - candidates,err :: failures + candidates,(cf,err,p) :: failures end in - let candidates,failures = loop candidates in - let fail () = match List.rev failures with - | err :: _ -> raise err - | _ -> assert false + let fail_fun () = + let tf = TFun(args,ret) in + [],tf,(fun ethis p_field -> + let e1 = mk (TField(ethis,mk_fa cf)) tf p_field in + mk (TCall(e1,[])) ret p) in - if is_overload && ctx.com.config.pf_overload then begin match Codegen.Overloads.reduce_compatible candidates with - | [] -> fail() - | [el,tf,mk_call] -> List.map fst el,tf,mk_call - | _ -> error "Ambiguous overload" p - end else begin match List.rev candidates with - | [] -> fail() - | (el,tf,mk_call) :: _ -> List.map fst el,tf,mk_call - end + match candidates with + | [t,cf] -> + begin try + let el,tf,mk_call = attempt_call t cf in + List.map fst el,tf,mk_call + with Error _ when ctx.com.display.dms_error_policy = EPIgnore -> + fail_fun(); + end + | _ -> + let candidates,failures = loop candidates in + let fail () = + let failures = List.map (fun (cf,err,p) -> cf,error_msg err,p) failures in + let failures = remove_duplicates (fun (_,msg1,_) (_,msg2,_) -> msg1 <> msg2) failures in + begin match failures with + | [_,msg,p] -> + error msg p + | _ -> + display_error ctx "Could not find a suitable overload, reasons follow" p; + List.iter (fun (cf,msg,p2) -> + display_error ctx ("Overload resolution failed for " ^ (s_type (print_context()) cf.cf_type)) p; + display_error ctx msg p2; + ) failures; + error "End of overload failure reasons" p + end + in + if is_overload && ctx.com.config.pf_overload then begin match Overloads.Resolution.reduce_compatible candidates with + | [] -> fail() + | [el,tf,mk_call] -> List.map fst el,tf,mk_call + | _ -> error "Ambiguous overload" p + end else begin match List.rev candidates with + | [] -> fail() + | (el,tf,mk_call) :: _ -> List.map fst el,tf,mk_call + end let fast_enum_field e ef p = let et = mk (TTypeExpr (TEnumDecl e)) (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }) p in TField (et,FEnum (e,ef)) +let abstract_module_type a tl = { + t_path = [],Printf.sprintf "Abstract<%s%s>" (s_type_path a.a_path) (s_type_params (ref []) tl); + t_module = a.a_module; + t_doc = None; + t_pos = a.a_pos; + t_name_pos = null_pos; + t_type = TAnon { + a_fields = PMap.empty; + a_status = ref (AbstractStatics a); + }; + t_private = true; + t_params = []; + t_meta = no_meta; +} + let rec type_module_type ctx t tparams p = match t with + | TClassDecl {cl_kind = KGenericBuild _} -> + let _,_,f = Typeload.build_instance ctx t p in + let t = f (match tparams with None -> [] | Some tl -> tl) in + let mt = try + module_type_of_type t + with Exit -> + if follow t == t_dynamic then Typeload.load_type_def ctx p { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None } + else error "Invalid module type" p + in + type_module_type ctx mt None p | TClassDecl c -> let t_tmp = { t_path = [],"Class<" ^ (s_type_path c.cl_path) ^ ">" ; t_module = c.cl_module; t_doc = None; t_pos = c.cl_pos; + t_name_pos = null_pos; t_type = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c); @@ -854,7 +760,8 @@ let rec type_module_type ctx t tparams p = mk (TTypeExpr (TEnumDecl e)) (TType (e.e_type,types)) p | TTypeDecl s -> let t = apply_params s.t_params (List.map (fun _ -> mk_mono()) s.t_params) s.t_type in - Codegen.DeprecationCheck.check_typedef ctx.com s p; + if not (Common.defined ctx.com Define.NoDeprecationWarnings) then + Display.DeprecationCheck.check_typedef ctx.com s p; (match follow t with | TEnum (e,params) -> type_module_type ctx (TEnumDecl e) (Some params) p @@ -868,19 +775,7 @@ let rec type_module_type ctx t tparams p = type_module_type ctx (TClassDecl c) tparams p | TAbstractDecl a -> if not (Meta.has Meta.RuntimeValue a.a_meta) then error (s_type_path a.a_path ^ " is not a value") p; - let t_tmp = { - t_path = [],"Abstract<" ^ (s_type_path a.a_path) ^ ">"; - t_module = a.a_module; - t_doc = None; - t_pos = a.a_pos; - t_type = TAnon { - a_fields = PMap.empty; - a_status = ref (AbstractStatics a); - }; - t_private = true; - t_params = []; - t_meta = no_meta; - } in + let t_tmp = abstract_module_type a [] in mk (TTypeExpr (TAbstractDecl a)) (TType (t_tmp,[])) p let type_type ctx tpath p = @@ -889,11 +784,11 @@ let type_type ctx tpath p = let get_constructor ctx c params p = match c.cl_kind with | KAbstractImpl a -> - let f = (try PMap.find "_new" c.cl_statics with Not_found -> error (s_type_path a.a_path ^ " does not have a constructor") p) in + let f = (try PMap.find "_new" c.cl_statics with Not_found -> raise_error (No_constructor (TAbstractDecl a)) p) in let ct = field_type ctx c params f p in apply_params a.a_params params ct, f | _ -> - let ct, f = (try Type.get_constructor (fun f -> field_type ctx c params f p) c with Not_found -> error (s_type_path c.cl_path ^ " does not have a constructor") p) in + let ct, f = (try Type.get_constructor (fun f -> field_type ctx c params f p) c with Not_found -> raise_error (No_constructor (TClassDecl c)) p) in apply_params c.cl_params params ct, f let make_call ctx e params t p = @@ -934,8 +829,9 @@ let make_call ctx e params t p = ignore(follow f.cf_type); (* force evaluation *) let params = List.map (ctx.g.do_optimize ctx) params in let force_inline = is_forced_inline cl f in - (match f.cf_expr with - | Some { eexpr = TFunction fd } -> + (match f.cf_expr_unoptimized,f.cf_expr with + | Some fd,_ + | None,Some { eexpr = TFunction fd } -> (match Optimizer.type_inline ctx f fd ethis params t config p force_inline with | None -> if force_inline then error "Inline could not be done" p; @@ -953,7 +849,7 @@ let make_call ctx e params t p = let mk_array_get_call ctx (cf,tf,r,e1,e2o) c ebase p = match cf.cf_expr with | None -> - if not (Meta.has Meta.NoExpr cf.cf_meta) && ctx.com.display = DMNone then display_error ctx "Recursive array get method" p; + if not (Meta.has Meta.NoExpr cf.cf_meta) then display_error ctx "Recursive array get method" p; mk (TArray(ebase,e1)) r p | Some _ -> let et = type_module_type ctx (TClassDecl c) None p in @@ -964,7 +860,7 @@ let mk_array_set_call ctx (cf,tf,r,e1,e2o) c ebase p = let evalue = match e2o with None -> assert false | Some e -> e in match cf.cf_expr with | None -> - if not (Meta.has Meta.NoExpr cf.cf_meta) && ctx.com.display = DMNone then display_error ctx "Recursive array set method" p; + if not (Meta.has Meta.NoExpr cf.cf_meta) then display_error ctx "Recursive array set method" p; let ea = mk (TArray(ebase,e1)) r p in mk (TBinop(OpAssign,ea,evalue)) r p | Some _ -> @@ -989,23 +885,19 @@ let rec acc_get ctx g p = (* build a closure with first parameter applied *) (match follow et.etype with | TFun (_ :: args,ret) -> - begin match follow e.etype,cf.cf_kind with - | TAbstract _,Method MethInline -> error "Cannot create closure on abstract inline method" e.epos - | _ -> () - end; let tcallb = TFun (args,ret) in let twrap = TFun ([("_e",false,e.etype)],tcallb) in (* arguments might not have names in case of variable fields of function types, so we generate one (issue #2495) *) let args = List.map (fun (n,o,t) -> let t = if o then ctx.t.tnull t else t in - o,if n = "" then gen_local ctx t else alloc_var n t + o,if n = "" then gen_local ctx t e.epos else alloc_var n t e.epos (* TODO: var pos *) ) args in - let ve = alloc_var "_e" e.etype in + let ve = alloc_var "_e" e.etype e.epos in let ecall = make_call ctx et (List.map (fun v -> mk (TLocal v) v.v_type p) (ve :: List.map snd args)) ret p in let ecallb = mk (TFunction { tf_args = List.map (fun (o,v) -> v,if o then Some TNull else None) args; tf_type = ret; - tf_expr = mk (TReturn (Some ecall)) t_dynamic p; + tf_expr = (match follow ret with | TAbstract ({a_path = [],"Void"},_) -> ecall | _ -> mk (TReturn (Some ecall)) t_dynamic p); }) tcallb p in let ewrap = mk (TFunction { tf_args = [ve,None]; @@ -1019,11 +911,10 @@ let rec acc_get ctx g p = let cmode = (match fmode with FStatic _ -> fmode | FInstance (c,tl,f) -> FClosure (Some (c,tl),f) | _ -> assert false) in ignore(follow f.cf_type); (* force computing *) (match f.cf_expr with + | None when ctx.com.display.dms_display -> + mk (TField (e,cmode)) t p | None -> - if ctx.com.display <> DMNone then - mk (TField (e,cmode)) t p - else - error "Recursive inline is not supported" p + error "Recursive inline is not supported" p | Some { eexpr = TFunction _ } -> let chk_class c = (c.cl_extern || Meta.has Meta.Extern f.cf_meta) && not (Meta.has Meta.Runtime f.cf_meta) in let wrap_extern c = @@ -1038,7 +929,7 @@ let rec acc_get ctx g p = in loop c.cl_module.m_types with Not_found -> - let c2 = mk_class c.cl_module mpath c.cl_pos in + let c2 = mk_class c.cl_module mpath c.cl_pos null_pos in c.cl_module.m_types <- (TClassDecl c2) :: c.cl_module.m_types; c2 in @@ -1060,6 +951,9 @@ let rec acc_get ctx g p = e_def | TAnon a -> begin match !(a.a_status) with + | Statics {cl_extern = false} when Meta.has Meta.Extern f.cf_meta -> + display_error ctx "Cannot create closure on @:extern inline method" p; + e_def | Statics c when chk_class c -> wrap_extern c | _ -> e_def end @@ -1076,7 +970,7 @@ let error_require r p = error "This field is not available with the current compilation flags" p else let r = if r = "sys" then - "a system platform (php,neko,cpp,etc.)" + "a system platform (php,php7,neko,cpp,etc.)" else try if String.sub r 0 5 <> "flash" then raise Exit; let _, v = ExtString.String.replace (String.sub r 5 (String.length r - 5)) "_" "." in @@ -1096,7 +990,7 @@ let get_this ctx p = let v = if ctx.curfun = FunMemberAbstractLocal then PMap.find "this" ctx.locals else - gen_local ctx ctx.tthis + add_local ctx "`this" ctx.tthis p in ctx.vthis <- Some v; v @@ -1151,7 +1045,7 @@ let field_access ctx mode f fmode t e p = end | Var v -> match (match mode with MGet | MCall -> v.v_read | MSet -> v.v_write) with - | AccNo -> + | AccNo when not (Meta.has Meta.PrivateAccess ctx.meta) -> (match follow e.etype with | TInst (c,_) when is_parent c ctx.curclass || can_access ctx c { f with cf_public = false } false -> normal() | TAnon a -> @@ -1163,7 +1057,7 @@ let field_access ctx mode f fmode t e p = | _ -> if ctx.untyped then normal() else AKNo f.cf_name) | _ -> if ctx.untyped then normal() else AKNo f.cf_name) - | AccNormal -> + | AccNormal | AccNo -> (* if we are reading from a read-only variable on an anonymous object, it might actually be a method, so make sure to create a closure *) @@ -1234,17 +1128,17 @@ let rec using_field ctx mode e i p = let rec loop = function | [] -> raise Not_found - | c :: l -> + | (c,pc) :: l -> try let cf = PMap.find i c.cl_statics in - if Meta.has Meta.NoUsing cf.cf_meta || not (can_access ctx c cf true) then raise Not_found; + if Meta.has Meta.NoUsing cf.cf_meta || not (can_access ctx c cf true) || (Meta.has Meta.Impl cf.cf_meta) then raise Not_found; let monos = List.map (fun _ -> mk_mono()) cf.cf_params in let map = apply_params cf.cf_params monos in let t = map cf.cf_type in begin match follow t with | TFun((_,_,(TType({t_path = ["haxe";"macro"],"ExprOf"},[t0]) | t0)) :: args,r) -> if is_dynamic && follow t0 != t_dynamic then raise Not_found; - let e = Codegen.AbstractCast.cast_or_unify_raise ctx t0 e p in + let e = AbstractCast.cast_or_unify_raise ctx t0 e p in (* early constraints check is possible because e.etype has no monomorphs *) List.iter2 (fun m (name,t) -> match follow t with | TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] && not (has_mono m) -> @@ -1252,6 +1146,7 @@ let rec using_field ctx mode e i p = | _ -> () ) monos cf.cf_params; let et = type_module_type ctx (TClassDecl c) None p in + Display.ImportHandling.maybe_mark_import_position ctx pc; AKUsing (mk (TField (et,FStatic (c,cf))) t p,c,cf,e) | _ -> raise Not_found @@ -1273,7 +1168,7 @@ let rec using_field ctx mode e i p = if not !check_constant_struct then raise Not_found; remove_constant_flag e.etype (fun ok -> if ok then using_field ctx mode e i p else raise Not_found) -let rec type_ident_raise ?(imported_enums=true) ctx i p mode = +let rec type_ident_raise ctx i p mode = match i with | "true" -> if mode = MGet then @@ -1305,7 +1200,6 @@ let rec type_ident_raise ?(imported_enums=true) ctx i p mode = | FunMemberAbstract -> error "Cannot access super inside an abstract function" p | FunStatic -> error "Cannot access super inside a static function" p; | FunMemberClassLocal | FunMemberAbstractLocal -> error "Cannot access super inside a local function" p); - if mode <> MSet && ctx.in_super_call then ctx.in_super_call <- false; AKExpr (mk (TConst TSuper) t p) | "null" -> if mode = MGet then @@ -1319,14 +1213,14 @@ let rec type_ident_raise ?(imported_enums=true) ctx i p mode = | Some (params,e) -> let t = monomorphs params v.v_type in (match e with - | Some ({ eexpr = TFunction f } as e) -> + | Some ({ eexpr = TFunction f } as e) when ctx.com.display.dms_full_typing -> begin match mode with | MSet -> error "Cannot set inline closure" p | MGet -> error "Cannot create closure on inline closure" p | MCall -> (* create a fake class with a fake field to emulate inlining *) - let c = mk_class ctx.m.curmod (["local"],v.v_name) e.epos in - let cf = { (mk_field v.v_name v.v_type e.epos) with cf_params = params; cf_expr = Some e; cf_kind = Method MethInline } in + let c = mk_class ctx.m.curmod (["local"],v.v_name) e.epos null_pos in + let cf = { (mk_field v.v_name v.v_type e.epos null_pos) with cf_params = params; cf_expr = Some e; cf_kind = Method MethInline } in c.cl_extern <- true; c.cl_fields <- PMap.add cf.cf_name cf PMap.empty; AKInline (mk (TConst TNull) (TInst (c,[])) p, cf, FInstance(c,[],cf), t) @@ -1349,11 +1243,12 @@ let rec type_ident_raise ?(imported_enums=true) ctx i p mode = with Not_found -> try (* static variable lookup *) let f = PMap.find i ctx.curclass.cl_statics in + if Meta.has Meta.Impl f.cf_meta && not (Meta.has Meta.Impl ctx.curfield.cf_meta) && not (Meta.has Meta.Enum f.cf_meta) then + error (Printf.sprintf "Cannot access non-static field %s from static method" f.cf_name) p; let e = type_type ctx ctx.curclass.cl_path p in (* check_locals_masking already done in type_type *) field_access ctx mode f (FStatic (ctx.curclass,f)) (field_type ctx ctx.curclass [] f p) e p with Not_found -> try - if not imported_enums then raise Not_found; let wrap e = if mode = MSet then AKNo i else @@ -1363,7 +1258,7 @@ let rec type_ident_raise ?(imported_enums=true) ctx i p mode = let rec loop l = match l with | [] -> raise Not_found - | t :: l -> + | (t,pt) :: l -> match t with | TAbstractDecl ({a_impl = Some c} as a) when Meta.has Meta.Enum a.a_meta -> begin try @@ -1372,7 +1267,13 @@ let rec type_ident_raise ?(imported_enums=true) ctx i p mode = loop l else begin let et = type_module_type ctx (TClassDecl c) None p in - AKInline(et,cf,FStatic(c,cf),monomorphs cf.cf_params cf.cf_type) + let fa = FStatic(c,cf) in + let t = monomorphs cf.cf_params cf.cf_type in + Display.ImportHandling.maybe_mark_import_position ctx pt; + begin match cf.cf_kind with + | Var {v_read = AccInline} -> AKInline(et,cf,fa,t) + | _ -> AKExpr (mk (TField(et,fa)) t p) + end end with Not_found -> loop l @@ -1381,7 +1282,7 @@ let rec type_ident_raise ?(imported_enums=true) ctx i p mode = loop l | TTypeDecl t -> (match follow t.t_type with - | TEnum (e,_) -> loop ((TEnumDecl e) :: l) + | TEnum (e,_) -> loop ((TEnumDecl e,pt) :: l) | _ -> loop l) | TEnumDecl e -> try @@ -1389,14 +1290,16 @@ let rec type_ident_raise ?(imported_enums=true) ctx i p mode = let et = type_module_type ctx t None p in let monos = List.map (fun _ -> mk_mono()) e.e_params in let monos2 = List.map (fun _ -> mk_mono()) ef.ef_params in + Display.ImportHandling.maybe_mark_import_position ctx pt; wrap (mk (TField (et,FEnum (e,ef))) (enum_field_type ctx e ef monos monos2 p) p) with Not_found -> loop l in - (try loop (List.rev ctx.m.curmod.m_types) with Not_found -> loop ctx.m.module_types) + (try loop (List.rev_map (fun t -> t,null_pos) ctx.m.curmod.m_types) with Not_found -> loop ctx.m.module_types) with Not_found -> (* lookup imported globals *) - let t, name = PMap.find i ctx.m.module_globals in + let t, name, pi = PMap.find i ctx.m.module_globals in + Display.ImportHandling.maybe_mark_import_position ctx pi; let e = type_module_type ctx t None p in type_field ctx e name p mode @@ -1421,10 +1324,24 @@ and type_field ?(resume=false) ctx e i p mode = (* the abstract field is not part of the field list, which is only true when it has no expression (issue #2344) *) display_error ctx ("Field " ^ i ^ " cannot be called directly because it has no expression") p; | _ -> - display_error ctx (string_error i (string_source t) (s_type (print_context()) t ^ " has no field " ^ i)) p; + display_error ctx (StringError.string_error i (string_source t) (s_type (print_context()) t ^ " has no field " ^ i)) p; end; AKExpr (mk (TField (e,FDynamic i)) (mk_mono()) p) in + let does_forward a stat = + try + let _,el,_ = Meta.get (if stat then Meta.ForwardStatics else Meta.Forward) a.a_meta in + match el with + | [] -> + true + | _ -> + List.exists (fun e -> match fst e with + | EConst(Ident s | String s) -> s = i + | _ -> error "Identifier or string expected as argument to @:forward" (pos e) + ) el + with Not_found -> + false + in match follow e.etype with | TInst (c,params) -> let rec loop_dyn c params = @@ -1527,26 +1444,36 @@ and type_field ?(resume=false) ctx e i p mode = FAnon f, t ) in field_access ctx mode f fmode ft e p - with Not_found -> - if is_closed a then try - using_field ctx mode e i p + with Not_found -> try + match !(a.a_status) with + | Statics {cl_kind = KAbstractImpl a} when does_forward a true -> + let mt = try module_type_of_type a.a_this with Exit -> raise Not_found in + let et = type_module_type ctx mt None p in + type_field ctx et i p mode; + | _ -> + raise Not_found with Not_found -> - no_field() - else - let f = { - cf_name = i; - cf_type = mk_mono(); - cf_doc = None; - cf_meta = no_meta; - cf_public = true; - cf_pos = p; - cf_kind = Var { v_read = AccNormal; v_write = (match mode with MSet -> AccNormal | MGet | MCall -> AccNo) }; - cf_expr = None; - cf_params = []; - cf_overloads = []; - } in - a.a_fields <- PMap.add i f a.a_fields; - field_access ctx mode f (FAnon f) (Type.field_type f) e p + if is_closed a then try + using_field ctx mode e i p + with Not_found -> + no_field() + else + let f = { + cf_name = i; + cf_type = mk_mono(); + cf_doc = None; + cf_meta = no_meta; + cf_public = true; + cf_pos = p; + cf_name_pos = null_pos; + cf_kind = Var { v_read = AccNormal; v_write = (match mode with MSet -> AccNormal | MGet | MCall -> AccNo) }; + cf_expr = None; + cf_expr_unoptimized = None; + cf_params = []; + cf_overloads = []; + } in + a.a_fields <- PMap.add i f a.a_fields; + field_access ctx mode f (FAnon f) (Type.field_type f) e p ) | TMono r -> let f = { @@ -1556,8 +1483,10 @@ and type_field ?(resume=false) ctx e i p mode = cf_meta = no_meta; cf_public = true; cf_pos = p; + cf_name_pos = null_pos; cf_kind = Var { v_read = AccNormal; v_write = (match mode with MSet -> AccNormal | MGet | MCall -> AccNo) }; cf_expr = None; + cf_expr_unoptimized = None; cf_params = []; cf_overloads = []; } in @@ -1621,26 +1550,25 @@ and type_field ?(resume=false) ctx e i p mode = | MSet, _ -> error "This operation is unsupported" p) with Not_found -> try - let _,el,_ = Meta.get Meta.Forward a.a_meta in - if not (List.exists (fun e -> match fst e with - | EConst(Ident s | String s) -> s = i - | _ -> error "Identifier or string expected as argument to @:forward" (pos e) - ) el) && el <> [] then raise Not_found; - type_field ctx {e with etype = apply_params a.a_params pl a.a_this} i p mode; + if does_forward a false then + type_field ~resume:true ctx {e with etype = apply_params a.a_params pl a.a_this} i p mode + else + raise Not_found with Not_found -> try using_field ctx mode e i p with Not_found -> try (match ctx.curfun, e.eexpr with | FunMemberAbstract, TConst (TThis) -> type_field ctx {e with etype = apply_params a.a_params pl a.a_this} i p mode; | _ -> raise Not_found) -(* with Not_found -> try - let c = (match a.a_impl with None -> raise Not_found | Some c -> c) in - let cf = PMap.find "resolve" c.cl_statics in - if not (Meta.has Meta.Resolve cf.cf_meta) then raise Not_found; + with Not_found -> try + let c,cf = match a.a_impl,a.a_resolve with + | Some c,Some cf -> c,cf + | _ -> raise Not_found + in let et = type_module_type ctx (TClassDecl c) None p in let t = apply_params a.a_params pl (field_type ctx c [] cf p) in let ef = mk (TField (et,FStatic (c,cf))) t p in - AKExpr ((!build_call_ref) ctx (AKUsing(ef,c,cf,e)) [EConst (String i),p] NoValue p) *) + AKExpr ((!build_call_ref) ctx (AKUsing(ef,c,cf,e)) [EConst (String i),p] NoValue p) with Not_found -> if !static_abstract_access_through_instance then error ("Invalid call to static function " ^ i ^ " through abstract instance") p else no_field()) @@ -1652,7 +1580,7 @@ let type_bind ctx (e : texpr) params p = let vexpr v = mk (TLocal v) v.v_type p in let acount = ref 0 in let alloc_name n = - if n = "" || String.length n > 2 then begin + if n = "" || String.length n > 2 && not ctx.is_display_file then begin incr acount; "a" ^ string_of_int !acount; end else @@ -1675,12 +1603,12 @@ let type_bind ctx (e : texpr) params p = error "Usage of _ is not supported for optional non-nullable arguments" p | (n,o,t) :: args , ([] as params) | (n,o,t) :: args , (EConst(Ident "_"),_) :: params -> - let v = alloc_var (alloc_name n) (if o then ctx.t.tnull t else t) in + let v = alloc_var (alloc_name n) (if o then ctx.t.tnull t else t) p in loop args params given_args (missing_args @ [v,o]) (ordered_args @ [vexpr v]) | (n,o,t) :: args , param :: params -> let e = type_expr ctx param (WithType t) in - unify ctx e.etype t p; - let v = alloc_var (alloc_name n) t in + let e = AbstractCast.cast_or_unify ctx t e p in + let v = alloc_var (alloc_name n) t (pos param) in loop args params (given_args @ [v,o,Some e]) missing_args (ordered_args @ [vexpr v]) in let given_args,missing_args,ordered_args = loop args params [] [] [] in @@ -1688,7 +1616,7 @@ let type_bind ctx (e : texpr) params p = let name = if n = 0 then "f" else "f" ^ (string_of_int n) in if List.exists (fun (n,_,_) -> name = n) args then gen_loc_name (n + 1) else name in - let loc = alloc_var (gen_loc_name 0) e.etype in + let loc = alloc_var (gen_loc_name 0) e.etype e.epos in let given_args = (loc,false,Some e) :: given_args in let inner_fun_args l = List.map (fun (v,o) -> v.v_name, o, v.v_type) l in let t_inner = TFun(inner_fun_args missing_args, ret) in @@ -1780,8 +1708,8 @@ let unify_int ctx e k = in if cf.cf_params = [] then error "Function has no type parameters and cannot be generic" p; let monos = List.map (fun _ -> mk_mono()) cf.cf_params in - let map t = apply_params cf.cf_params monos t in - let map t = if stat then map t else apply_params c.cl_params tl (map t) in + let map_monos t = apply_params cf.cf_params monos t in + let map t = if stat then map_monos t else apply_params c.cl_params tl (map_monos t) in let t = map cf.cf_type in let args,ret = match t,using_param with | TFun((_,_,ta) :: args,ret),Some e -> @@ -1796,7 +1724,6 @@ let unify_int ctx e k = in begin match with_type with | WithType t -> unify ctx ret t p - | WithTypeResume t -> (try unify_raise ctx ret t p with Error (Unify l,_) -> raise (WithTypeError(l,p))) | _ -> () end; let el,_ = unify_call_args ctx el args ret p false false in @@ -1807,8 +1734,8 @@ let unify_int ctx e k = end; let el = match using_param with None -> el | Some e -> e :: el in (try - let gctx = Codegen.make_generic ctx cf.cf_params monos p in - let name = cf.cf_name ^ "_" ^ gctx.Codegen.name in + let gctx = Typeload.make_generic ctx cf.cf_params monos p in + let name = cf.cf_name ^ "_" ^ gctx.Typeload.name in let unify_existing_field tcf pcf = try unify_raise ctx tcf t p with Error(Unify _,_) as err -> @@ -1828,7 +1755,7 @@ let unify_int ctx e k = in cf2 with Not_found -> - let cf2 = mk_field name t cf.cf_pos in + let cf2 = mk_field name (map_monos cf.cf_type) cf.cf_pos cf.cf_name_pos in if stat then begin c.cl_statics <- PMap.add name cf2 c.cl_statics; c.cl_ordered_statics <- cf2 :: c.cl_ordered_statics @@ -1838,9 +1765,21 @@ let unify_int ctx e k = c.cl_ordered_fields <- cf2 :: c.cl_ordered_fields end; ignore(follow cf.cf_type); + let rec check e = match e.eexpr with + | TNew({cl_kind = KTypeParameter _} as c,_,_) when not (Typeload.is_generic_parameter ctx c) -> + display_error ctx "Only generic type parameters can be constructed" e.epos; + display_error ctx "While specializing this call" p; + | _ -> + Type.iter check e + in cf2.cf_expr <- (match cf.cf_expr with - | None -> error "Recursive @:generic function" p - | Some e -> Some (Codegen.generic_substitute_expr gctx e)); + | None -> + display_error ctx "Recursive @:generic function" p; None; + | Some e -> + let e = Typeload.generic_substitute_expr gctx e in + check e; + Some e + ); cf2.cf_kind <- cf.cf_kind; cf2.cf_public <- cf.cf_public; let metadata = List.filter (fun (m,_,_) -> match m with @@ -1850,17 +1789,24 @@ let unify_int ctx e k = cf2.cf_meta <- (Meta.NoCompletion,[],p) :: (Meta.NoUsing,[],p) :: (Meta.GenericInstance,[],p) :: metadata; cf2 in - let e = if stat then type_type ctx c.cl_path p else e in + let path = match c.cl_kind with + | KAbstractImpl(a) -> + a.a_path + | _ -> c.cl_path + in + let e = if stat then type_type ctx path p else e in let fa = if stat then FStatic (c,cf2) else FInstance (c,tl,cf2) in let e = mk (TField(e,fa)) cf2.cf_type p in make_call ctx e el ret p - with Codegen.Generic_Exception (msg,p) -> + with Typeload.Generic_Exception (msg,p) -> error msg p) -let call_to_string ctx c e = - let et = type_module_type ctx (TClassDecl c) None e.epos in - let cf = PMap.find "toString" c.cl_statics in - make_call ctx (mk (TField(et,FStatic(c,cf))) cf.cf_type e.epos) [e] ctx.t.tstring e.epos +let call_to_string ctx ?(resume=false) e = + (* Ignore visibility of the toString field. *) + ctx.meta <- (Meta.PrivateAccess,[],e.epos) :: ctx.meta; + let acc = type_field ~resume ctx e "toString" e.epos MCall in + ctx.meta <- List.tl ctx.meta; + !build_call_ref ctx acc [] (WithType ctx.t.tstring) e.epos let rec type_binop ctx op e1 e2 is_assign_op with_type p = match op with @@ -1871,7 +1817,7 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p = (match e1 with | AKNo s -> error ("Cannot access field or identifier " ^ s ^ " for writing") p | AKExpr e1 -> - let e2 = Codegen.AbstractCast.cast_or_unify ctx e1.etype e2 p in + let e2 = AbstractCast.cast_or_unify ctx e1.etype e2 p in check_assign ctx e1; (match e1.eexpr , e2.eexpr with | TLocal i1 , TLocal i2 when i1 == i2 -> error "Assigning a value to itself" p @@ -1880,26 +1826,32 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p = | _ , _ -> ()); mk (TBinop (op,e1,e2)) e1.etype p | AKSet (e,t,cf) -> - let e2 = Codegen.AbstractCast.cast_or_unify ctx t e2 p in + let e2 = AbstractCast.cast_or_unify ctx t e2 p in make_call ctx (mk (TField (e,quick_field_dynamic e.etype ("set_" ^ cf.cf_name))) (tfun [t] t) p) [e2] t p | AKAccess(a,tl,c,ebase,ekey) -> - mk_array_set_call ctx (Codegen.AbstractCast.find_array_access ctx a tl ekey (Some e2) p) c ebase p + mk_array_set_call ctx (AbstractCast.find_array_access ctx a tl ekey (Some e2) p) c ebase p | AKUsing(ef,_,_,et) -> (* this must be an abstract setter *) - let ret = match follow ef.etype with + let e2,ret = match follow ef.etype with | TFun([_;(_,_,t)],ret) -> - unify ctx e2.etype t p; - ret + AbstractCast.cast_or_unify ctx t e2 p,ret | _ -> error "Invalid field type for abstract setter" p in make_call ctx ef [et;e2] ret p | AKInline _ | AKMacro _ -> assert false) + | OpAssignOp (OpBoolAnd | OpBoolOr) -> + error "The operators ||= and &&= are not supported" p | OpAssignOp op -> (match type_access ctx (fst e1) (snd e1) MSet with | AKNo s -> error ("Cannot access field or identifier " ^ s ^ " for writing") p | AKExpr e -> + let save = save_locals ctx in + let v = gen_local ctx e.etype e.epos in + let has_side_effect = OptimizerTexpr.has_side_effect e in + let e1 = if has_side_effect then (EConst(Ident v.v_name),e.epos) else e1 in let eop = type_binop ctx op e1 e2 true with_type p in + save(); (match eop.eexpr with | TBinop (_,_,e2) -> unify ctx eop.etype e.etype p; @@ -1908,18 +1860,48 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p = | TMeta((Meta.RequiresAssign,_,_),e2) -> unify ctx e2.etype e.etype p; check_assign ctx e; - mk (TBinop (OpAssign,e,e2)) e.etype p; + begin match e.eexpr with + | TArray(ea1,ea2) when has_side_effect -> + let v1 = gen_local ctx ea1.etype ea1.epos in + let ev1 = mk (TLocal v1) v1.v_type p in + let v2 = gen_local ctx ea2.etype ea2.epos in + let ev2 = mk (TLocal v2) v2.v_type p in + let e = {e with eexpr = TArray(ev1,ev2)} in + mk (TBlock [ + mk (TVar(v1,Some ea1)) ctx.t.tvoid p; + mk (TVar(v2,Some ea2)) ctx.t.tvoid p; + mk (TVar(v,Some e)) ctx.t.tvoid p; + mk (TBinop (OpAssign,e,e2)) e.etype p; + ]) e.etype p + | TField(ea1,fa) when has_side_effect -> + let v1 = gen_local ctx ea1.etype ea1.epos in + let ev1 = mk (TLocal v1) v1.v_type p in + let e = {e with eexpr = TField(ev1,fa)} in + mk (TBlock [ + mk (TVar(v1,Some ea1)) ctx.t.tvoid p; + mk (TVar(v,Some e)) ctx.t.tvoid p; + mk (TBinop (OpAssign,e,e2)) e.etype p; + ]) e.etype p + | _ -> + mk (TBinop (OpAssign,e,e2)) e.etype p; + end | _ -> (* this must be an abstract cast *) check_assign ctx e; - eop) + if has_side_effect then + mk (TBlock [ + mk (TVar(v,Some e)) ctx.t.tvoid eop.epos; + eop + ]) eop.etype eop.epos + else + eop) | AKSet (e,t,cf) -> let l = save_locals ctx in - let v = gen_local ctx e.etype in + let v = gen_local ctx e.etype e.epos in let ev = mk (TLocal v) e.etype p in let get = type_binop ctx op (EField ((EConst (Ident v.v_name),p),cf.cf_name),p) e2 true with_type p in let e' = match get.eexpr with - | TBinop _ -> + | TBinop _ | TMeta((Meta.RequiresAssign,_,_),_) -> unify ctx get.etype t p; make_call ctx (mk (TField (ev,quick_field_dynamic ev.etype ("set_" ^ cf.cf_name))) (tfun [t] t) p) [get] t p | _ -> @@ -1941,7 +1923,7 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p = let l = save_locals ctx in let v,is_temp = match et.eexpr with | TLocal v when not (v.v_name = "this") -> v,false - | _ -> gen_local ctx ta,true + | _ -> gen_local ctx ta ef.epos,true in let ev = mk (TLocal v) ta p in (* this relies on the fact that cf_name is set_name *) @@ -1958,45 +1940,49 @@ let rec type_binop ctx op e1 e2 is_assign_op with_type p = else e_call | AKAccess(a,tl,c,ebase,ekey) -> - let cf_get,tf_get,r_get,ekey,_ = Codegen.AbstractCast.find_array_access ctx a tl ekey None p in + let cf_get,tf_get,r_get,ekey,_ = AbstractCast.find_array_access ctx a tl ekey None p in (* bind complex keys to a variable so they do not make it into the output twice *) - let ekey,l = match Optimizer.make_constant_expression ctx ekey with - | Some e -> e, fun () -> None + let save = save_locals ctx in + let maybe_bind_to_temp e = match Optimizer.make_constant_expression ctx e with + | Some e -> e,None | None -> - let save = save_locals ctx in - let v = gen_local ctx ekey.etype in - let e = mk (TLocal v) ekey.etype p in - e, fun () -> (save(); Some (mk (TVar (v,Some ekey)) ctx.t.tvoid p)) + let v = gen_local ctx e.etype p in + let e' = mk (TLocal v) e.etype p in + e', Some (mk (TVar (v,Some e)) ctx.t.tvoid p) in + let ekey,ekey' = maybe_bind_to_temp ekey in + let ebase,ebase' = maybe_bind_to_temp ebase in let eget = mk_array_get_call ctx (cf_get,tf_get,r_get,ekey,None) c ebase p in let eget = type_binop2 ctx op eget e2 true (WithType eget.etype) p in unify ctx eget.etype r_get p; - let cf_set,tf_set,r_set,ekey,eget = Codegen.AbstractCast.find_array_access ctx a tl ekey (Some eget) p in + let cf_set,tf_set,r_set,ekey,eget = AbstractCast.find_array_access ctx a tl ekey (Some eget) p in let eget = match eget with None -> assert false | Some e -> e in let et = type_module_type ctx (TClassDecl c) None p in - begin match cf_set.cf_expr,cf_get.cf_expr with + let e = match cf_set.cf_expr,cf_get.cf_expr with | None,None -> let ea = mk (TArray(ebase,ekey)) r_get p in mk (TBinop(OpAssignOp op,ea,type_expr ctx e2 (WithType r_get))) r_set p | Some _,Some _ -> let ef_set = mk (TField(et,(FStatic(c,cf_set)))) tf_set p in - (match l() with - | None -> make_call ctx ef_set [ebase;ekey;eget] r_set p - | Some e -> - mk (TBlock [ - e; - make_call ctx ef_set [ebase;ekey;eget] r_set p - ]) r_set p) + let el = [make_call ctx ef_set [ebase;ekey;eget] r_set p] in + let el = match ebase' with None -> el | Some ebase -> ebase :: el in + let el = match ekey' with None -> el | Some ekey -> ekey :: el in + begin match el with + | [e] -> e + | el -> mk (TBlock el) r_set p + end | _ -> error "Invalid array access getter/setter combination" p - end; + in + save(); + e | AKInline _ | AKMacro _ -> assert false) | _ -> (* If the with_type is an abstract which has exactly one applicable @:op method, we can promote it to the individual arguments (issue #2786). *) let wt = match with_type with - | WithType t | WithTypeResume t -> + | WithType t -> begin match follow t with | TAbstract(a,_) -> begin match List.filter (fun (o,_) -> o = OpAssignOp(op) || o == op) a.a_ops with @@ -2020,7 +2006,7 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = let to_string e = let rec loop t = match classify t with | KAbstract ({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> - call_to_string ctx c e + call_to_string ctx e | KInt | KFloat | KString -> e | KUnk | KDyn | KParam _ | KOther -> let std = type_type ctx ([],"Std") e.epos in @@ -2029,7 +2015,10 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = let acc = (match acc.eexpr with TField (e,FClosure (Some (c,tl),f)) -> { acc with eexpr = TField (e,FInstance (c,tl,f)) } | _ -> acc) in make_call ctx acc [e] ctx.t.tstring e.epos | KAbstract (a,tl) -> - loop (Abstract.get_underlying_type a tl) + try + AbstractCast.cast_or_unify_raise ctx tstring e p + with Error (Unify _,_) -> + loop (Abstract.get_underlying_type a tl) in loop e.etype in @@ -2085,6 +2074,18 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = | KUnk, KParam t -> unify ctx e1.etype tfloat e1.epos; tfloat + | KAbstract _,KFloat -> + unify ctx e1.etype tfloat e1.epos; + tfloat + | KFloat, KAbstract _ -> + unify ctx e2.etype tfloat e2.epos; + tfloat + | KAbstract _,KInt -> + unify ctx e1.etype ctx.t.tint e1.epos; + ctx.t.tint + | KInt, KAbstract _ -> + unify ctx e2.etype ctx.t.tint e2.epos; + ctx.t.tint | KAbstract _,_ | _,KAbstract _ | KParam _, _ @@ -2137,9 +2138,9 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = let e1,e2 = try (* we only have to check one type here, because unification fails if one is Void and the other is not *) (match follow e2.etype with TAbstract({a_path=[],"Void"},_) -> error "Cannot compare Void" p | _ -> ()); - Codegen.AbstractCast.cast_or_unify_raise ctx e2.etype e1 p,e2 + AbstractCast.cast_or_unify_raise ctx e2.etype e1 p,e2 with Error (Unify _,_) -> - e1,Codegen.AbstractCast.cast_or_unify ctx e1.etype e2 p + e1,AbstractCast.cast_or_unify ctx e1.etype e2 p in mk_op e1 e2 ctx.t.tbool | OpGt @@ -2222,14 +2223,14 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = in (* special case for == and !=: if the second type is a monomorph, assume that we want to unify it with the first type to preserve comparison semantics. *) - let is_eq_op = match op with OpEq | OpNotEq -> true | _ -> false in + let is_eq_op = match op with OpEq | OpNotEq -> true | _ -> false in if is_eq_op then begin match follow e1.etype,follow e2.etype with | TMono _,_ | _,TMono _ -> Type.unify e1.etype e2.etype | _ -> () end; - let rec loop ol = match ol with + let rec loop ol = match ol with | (op_cf,cf) :: ol when op_cf <> op && (not is_assign_op || op_cf <> OpAssignOp(op)) -> loop ol | (op_cf,cf) :: ol -> @@ -2250,10 +2251,10 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = let t1 = if is_impl then Abstract.follow_with_abstracts t1 else t1 in let e1,e2 = if left || not left && swapped then begin Type.type_eq EqStrict (if is_impl then Abstract.follow_with_abstracts e1.etype else e1.etype) t1; - e1,Codegen.AbstractCast.cast_or_unify_raise ctx t2 e2 p + e1,AbstractCast.cast_or_unify_raise ctx t2 e2 p end else begin Type.type_eq EqStrict e2.etype t2; - Codegen.AbstractCast.cast_or_unify_raise ctx t1 e1 p,e2 + AbstractCast.cast_or_unify_raise ctx t1 e1 p,e2 end in check_constraints ctx "" cf.cf_params monos (apply_params a.a_params tl) false cf.cf_pos; let check_null e t = if is_eq_op then match e.eexpr with @@ -2268,10 +2269,10 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p = end; let e = if not swapped then make e1 e2 - else if not (Optimizer.has_side_effect e1) && not (Optimizer.has_side_effect e2) then + else if not (OptimizerTexpr.has_side_effect e1) && not (OptimizerTexpr.has_side_effect e2) then make e1 e2 else - let v1,v2 = gen_local ctx t1, gen_local ctx t2 in + let v1,v2 = gen_local ctx t1 e1.epos, gen_local ctx t2 e2.epos in let ev1,ev2 = mk (TVar(v1,Some e1)) ctx.t.tvoid p,mk (TVar(v2,Some e2)) ctx.t.tvoid p in let eloc1,eloc2 = mk (TLocal v1) v1.v_type p,mk (TLocal v2) v2.v_type p in let e = make eloc1 eloc2 in @@ -2321,12 +2322,15 @@ and type_unop ctx op flag e p = let make e = let t = (match op with | Not -> + if flag = Postfix then error "Postfix ! is not supported" p; unify ctx e.etype ctx.t.tbool e.epos; ctx.t.tbool + | NegBits -> + unify ctx e.etype ctx.t.tint e.epos; + ctx.t.tint | Increment | Decrement - | Neg - | NegBits -> + | Neg -> if set then check_assign ctx e; (match classify e.etype with | KFloat -> ctx.t.tfloat @@ -2344,7 +2348,7 @@ and type_unop ctx op flag e p = | [] -> raise Not_found | (op2,flag2,cf) :: opl when op == op2 && flag == flag2 -> let m = mk_mono() in - let tcf = apply_params c.cl_params pl (monomorphs cf.cf_params cf.cf_type) in + let tcf = apply_params a.a_params pl (monomorphs cf.cf_params cf.cf_type) in if Meta.has Meta.Impl cf.cf_meta then begin if type_iseq (tfun [apply_params a.a_params pl a.a_this] m) tcf then cf,tcf,m else loop opl end else @@ -2373,13 +2377,32 @@ and type_unop ctx op flag e p = | AKNo s -> error ("The field or identifier " ^ s ^ " is not accessible for " ^ (if set then "writing" else "reading")) p | AKAccess(a,tl,c,ebase,ekey) -> - let e = mk_array_get_call ctx (Codegen.AbstractCast.find_array_access ctx a tl ekey None p) c ebase p in - loop (AKExpr e) + begin try + (match op with Increment | Decrement -> () | _ -> raise Not_found); + let v_key = alloc_var "tmp" ekey.etype ekey.epos in + let evar_key = mk (TVar(v_key,Some ekey)) ctx.com.basic.tvoid ekey.epos in + let ekey = mk (TLocal v_key) ekey.etype ekey.epos in + (* get *) + let e_get = mk_array_get_call ctx (AbstractCast.find_array_access_raise ctx a tl ekey None p) c ebase p in + let v_get = alloc_var "tmp" e_get.etype e_get.epos in + let ev_get = mk (TLocal v_get) v_get.v_type p in + let evar_get = mk (TVar(v_get,Some e_get)) ctx.com.basic.tvoid p in + (* op *) + let e_one = mk (TConst (TInt (Int32.of_int 1))) ctx.com.basic.tint p in + let e_op = mk (TBinop((if op = Increment then OpAdd else OpSub),ev_get,e_one)) ev_get.etype p in + (* set *) + let e_set = mk_array_set_call ctx (AbstractCast.find_array_access_raise ctx a tl ekey (Some e_op) p) c ebase p in + let el = evar_key :: evar_get :: e_set :: (if flag = Postfix then [ev_get] else []) in + mk (TBlock el) e_set.etype p + with Not_found -> + let e = mk_array_get_call ctx (AbstractCast.find_array_access ctx a tl ekey None p) c ebase p in + loop (AKExpr e) + end | AKInline _ | AKUsing _ | AKMacro _ -> error "This kind of operation is not supported" p | AKSet (e,t,cf) -> let l = save_locals ctx in - let v = gen_local ctx e.etype in + let v = gen_local ctx e.etype p in let ev = mk (TLocal v) e.etype p in let op = (match op with Increment -> OpAdd | Decrement -> OpSub | _ -> assert false) in let one = (EConst (Int "1"),p) in @@ -2394,7 +2417,7 @@ and type_unop ctx op flag e p = make_call ctx (mk (TField (ev,quick_field_dynamic ev.etype ("set_" ^ cf.cf_name))) (tfun [t] t) p) [get] t p ]) t p | Postfix -> - let v2 = gen_local ctx t in + let v2 = gen_local ctx t p in let ev2 = mk (TLocal v2) t p in let get = type_expr ctx eget Value in let plusone = type_binop ctx op (EConst (Ident v2.v_name),p) one false Value p in @@ -2409,46 +2432,6 @@ and type_unop ctx op flag e p = in loop acc -and type_switch_old ctx e cases def with_type p = - let eval = type_expr ctx e Value in - let el = ref [] in - let type_case_code e = - let e = (match e with - | Some e -> type_expr ctx e with_type - | None -> mk (TBlock []) ctx.com.basic.tvoid Ast.null_pos - ) in - el := e :: !el; - e - in - let consts = Hashtbl.create 0 in - let exprs (el,_,e) = - let el = List.map (fun e -> - match type_expr ctx e (WithType eval.etype) with - | { eexpr = TConst c } as e -> - if Hashtbl.mem consts c then error "Duplicate constant in switch" e.epos; - Hashtbl.add consts c true; - e - | e -> - e - ) el in - let locals = save_locals ctx in - let e = type_case_code e in - locals(); - el, e - in - let cases = List.map exprs cases in - let def() = (match def with - | None -> None - | Some e -> - let locals = save_locals ctx in - let e = type_case_code e in - locals(); - Some e - ) in - let def = def() in - let t = if with_type = NoValue then (mk_mono()) else unify_min ctx (List.rev !el) in - mk (TSwitch (eval,cases,def)) t p - and type_ident ctx i p mode = try type_ident_raise ctx i p mode @@ -2463,25 +2446,162 @@ and type_ident ctx i p mode = AKExpr (mk (TConst TThis) ctx.tthis p) else let t = mk_mono() in - let v = alloc_unbound_var i t in + let v = alloc_unbound_var i t p in AKExpr (mk (TLocal v) t p) end else begin if ctx.curfun = FunStatic && PMap.mem i ctx.curclass.cl_fields then error ("Cannot access " ^ i ^ " in static function") p; - let err = Unknown_ident i in - if ctx.in_display then raise (Error (err,p)); - if ctx.com.display <> DMNone then begin - display_error ctx (error_msg err) p; - let t = mk_mono() in - AKExpr (mk (TLocal (add_local ctx i t)) t p) - end else begin - if List.exists (fun (i2,_) -> i2 = i) ctx.type_params then - display_error ctx ("Type parameter " ^ i ^ " is only available at compilation and is not a runtime value") p - else - display_error ctx (error_msg err) p; - AKExpr (mk (TConst TNull) t_dynamic p) + begin try + let t = List.find (fun (i2,_) -> i2 = i) ctx.type_params in + let c = match follow (snd t) with TInst(c,_) -> c | _ -> assert false in + if Typeload.is_generic_parameter ctx c && Meta.has Meta.Const c.cl_meta then + AKExpr (type_module_type ctx (TClassDecl c) None p) + else begin + display_error ctx ("Type parameter " ^ i ^ " is only available at compilation and is not a runtime value") p; + AKExpr (mk (TConst TNull) t_dynamic p) + end + with Not_found -> + let err = Unknown_ident i in + if ctx.in_display then begin + raise (Error (err,p)) + end; + match ctx.com.display.dms_kind with + | DMNone -> + raise (Error(err,p)) + | DMDiagnostics b when b || ctx.is_display_file -> + Display.ToplevelCollector.handle_unresolved_identifier ctx i p false; + let t = mk_mono() in + AKExpr (mk (TLocal (add_unbound_local ctx i t p)) t p) + | _ -> + display_error ctx (error_msg err) p; + let t = mk_mono() in + AKExpr (mk (TLocal (add_unbound_local ctx i t p)) t p) end end +(* MORDOR *) +and handle_efield ctx e p mode = + let fields ?(resume=false) path e = + let resume = ref resume in + let force = ref false in + let e = List.fold_left (fun e (f,_,p) -> + let e = acc_get ctx (e MGet) p in + let f = type_field ~resume:(!resume) ctx e f p in + force := !resume; + resume := false; + f + ) e path in + if !force then ignore(e MCall); (* not necessarily a call, but prevent #2602 among others *) + e + in + let type_path path = + let rec loop acc path = + match path with + | [] -> + (match List.rev acc with + | [] -> assert false + | (name,flag,p) :: path -> + try + fields path (type_ident ctx name p) + with + Error (Unknown_ident _,p2) as e when p = p2 -> + try + let path = ref [] in + let name , _ , _ = List.find (fun (name,flag,p) -> + if flag then + true + else begin + path := name :: !path; + false + end + ) (List.rev acc) in + raise (Error (Module_not_found (List.rev !path,name),p)) + with + Not_found -> + if ctx.in_display then raise (Parser.TypePath (List.map (fun (n,_,_) -> n) (List.rev acc),None,false)); + raise e) + | (_,false,_) as x :: path -> + loop (x :: acc) path + | (name,true,p) as x :: path -> + let pack = List.rev_map (fun (x,_,_) -> x) acc in + let def() = + try + let e = type_type ctx (pack,name) p in + fields path (fun _ -> AKExpr e) + with + Error (Module_not_found m,_) when m = (pack,name) -> + loop ((List.rev path) @ x :: acc) [] + in + match path with + | (sname,true,p) :: path -> + let get_static resume t = + fields ~resume ((sname,true,p) :: path) (fun _ -> AKExpr (type_module_type ctx t None p)) + in + let check_module m v = + try + let md = Typeload.load_module ctx m p in + (* first look for existing subtype *) + (try + let t = List.find (fun t -> not (t_infos t).mt_private && t_path t = (fst m,sname)) md.m_types in + Some (fields path (fun _ -> AKExpr (type_module_type ctx t None p))) + with Not_found -> try + (* then look for main type statics *) + if fst m = [] then raise Not_found; (* ensure that we use def() to resolve local types first *) + let t = List.find (fun t -> not (t_infos t).mt_private && t_path t = m) md.m_types in + Some (get_static false t) + with Not_found -> + None) + with Error (Module_not_found m2,_) when m = m2 -> + None + in + let rec loop pack = + match check_module (pack,name) sname with + | Some r -> r + | None -> + match List.rev pack with + | [] -> def() + | _ :: l -> loop (List.rev l) + in + (match pack with + | [] -> + (try + let path_match t = snd (t_infos t).mt_path = name in + let t = try + List.find path_match ctx.m.curmod.m_types + with Not_found -> + let t,p = List.find (fun (t,_) -> path_match t) ctx.m.module_types in + Display.ImportHandling.maybe_mark_import_position ctx p; + t + in + (* if the static is not found, look for a subtype instead - #1916 *) + get_static true t + with Not_found -> + loop (fst ctx.m.curmod.m_path)) + | _ -> + match check_module (pack,name) sname with + | Some r -> r + | None -> def()); + | _ -> def() + in + match path with + | [] -> assert false + | (name,_,p) :: pnext -> + try + fields pnext (fun _ -> type_ident_raise ctx name p MGet) + with + Not_found -> loop [] path + in + let rec loop acc e = + let p = pos e in + match fst e with + | EField (e,s) -> + loop ((s,not (is_lower_ident s),p) :: acc) e + | EConst (Ident i) -> + type_path ((i,not (is_lower_ident i),p) :: acc) + | _ -> + fields acc (type_access ctx (fst e) (snd e)) + in + loop [] (e,p) mode + and type_access ctx e p mode = match e with | EConst (Ident s) -> @@ -2495,7 +2615,7 @@ and type_access ctx e p mode = let monos = List.map (fun _ -> mk_mono()) c.cl_params in let ct, cf = get_constructor ctx c monos p in let args = match follow ct with TFun(args,ret) -> args | _ -> assert false in - let vl = List.map (fun (n,_,t) -> alloc_var n t) args in + let vl = List.map (fun (n,_,t) -> alloc_var n t c.cl_pos) args in let vexpr v = mk (TLocal v) v.v_type p in let el = List.map vexpr vl in let ec,t = match c.cl_kind with @@ -2512,124 +2632,11 @@ and type_access ctx e p mode = tf_args = List.map (fun v -> v,None) vl; tf_type = t; tf_expr = mk (TReturn (Some ec)) t p; - }) (tfun (List.map (fun v -> v.v_type) vl) t) p) + }) (TFun ((List.map (fun v -> v.v_name,false,v.v_type) vl),t)) p) | _ -> error "Binding new is only allowed on class types" p end; | EField _ -> - let fields ?(resume=false) path e = - let resume = ref resume in - let force = ref false in - let e = List.fold_left (fun e (f,_,p) -> - let e = acc_get ctx (e MGet) p in - let f = type_field ~resume:(!resume) ctx e f p in - force := !resume; - resume := false; - f - ) e path in - if !force then ignore(e MCall); (* not necessarily a call, but prevent #2602 among others *) - e - in - let type_path path = - let rec loop acc path = - match path with - | [] -> - (match List.rev acc with - | [] -> assert false - | (name,flag,p) :: path -> - try - fields path (type_access ctx (EConst (Ident name)) p) - with - Error (Unknown_ident _,p2) as e when p = p2 -> - try - let path = ref [] in - let name , _ , _ = List.find (fun (name,flag,p) -> - if flag then - true - else begin - path := name :: !path; - false - end - ) (List.rev acc) in - raise (Error (Module_not_found (List.rev !path,name),p)) - with - Not_found -> - if ctx.in_display then raise (Parser.TypePath (List.map (fun (n,_,_) -> n) (List.rev acc),None,false)); - raise e) - | (_,false,_) as x :: path -> - loop (x :: acc) path - | (name,true,p) as x :: path -> - let pack = List.rev_map (fun (x,_,_) -> x) acc in - let def() = - try - let e = type_type ctx (pack,name) p in - fields path (fun _ -> AKExpr e) - with - Error (Module_not_found m,_) when m = (pack,name) -> - loop ((List.rev path) @ x :: acc) [] - in - match path with - | (sname,true,p) :: path -> - let get_static resume t = - fields ~resume ((sname,true,p) :: path) (fun _ -> AKExpr (type_module_type ctx t None p)) - in - let check_module m v = - try - let md = Typeload.load_module ctx m p in - (* first look for existing subtype *) - (try - let t = List.find (fun t -> not (t_infos t).mt_private && t_path t = (fst m,sname)) md.m_types in - Some (fields path (fun _ -> AKExpr (type_module_type ctx t None p))) - with Not_found -> try - (* then look for main type statics *) - if fst m = [] then raise Not_found; (* ensure that we use def() to resolve local types first *) - let t = List.find (fun t -> not (t_infos t).mt_private && t_path t = m) md.m_types in - Some (get_static false t) - with Not_found -> - None) - with Error (Module_not_found m2,_) when m = m2 -> - None - in - let rec loop pack = - match check_module (pack,name) sname with - | Some r -> r - | None -> - match List.rev pack with - | [] -> def() - | _ :: l -> loop (List.rev l) - in - (match pack with - | [] -> - (try - let t = List.find (fun t -> snd (t_infos t).mt_path = name) (ctx.m.curmod.m_types @ ctx.m.module_types) in - (* if the static is not found, look for a subtype instead - #1916 *) - get_static true t - with Not_found -> - loop (fst ctx.m.curmod.m_path)) - | _ -> - match check_module (pack,name) sname with - | Some r -> r - | None -> def()); - | _ -> def() - in - match path with - | [] -> assert false - | (name,_,p) :: pnext -> - try - fields pnext (fun _ -> type_ident_raise ctx name p MGet) - with - Not_found -> loop [] path - in - let rec loop acc e = - let p = pos e in - match fst e with - | EField (e,s) -> - loop ((s,not (is_lower_ident s),p) :: acc) e - | EConst (Ident i) -> - type_path ((i,not (is_lower_ident i),p) :: acc) - | _ -> - fields acc (type_access ctx (fst e) (snd e)) - in - loop [] (e,p) mode + handle_efield ctx e p mode | EArray (e1,e2) -> let e1 = type_expr ctx e1 Value in let e2 = type_expr ctx e2 Value in @@ -2642,7 +2649,7 @@ and type_access ctx e p mode = AKAccess (a,pl,c,e1,e2) | _ -> has_abstract_array_access := true; - let e = mk_array_get_call ctx (Codegen.AbstractCast.find_array_access ctx a pl e2 None p) c e1 p in + let e = mk_array_get_call ctx (AbstractCast.find_array_access ctx a pl e2 None p) c e1 p in AKExpr e end | _ -> raise Not_found) @@ -2675,27 +2682,28 @@ and type_access ctx e p mode = | _ -> AKExpr (type_expr ctx (e,p) Value) -and type_vars ctx vl p in_block = - let save = if in_block then (fun() -> ()) else save_locals ctx in - let vl = List.map (fun (v,t,e) -> +and type_vars ctx vl p = + let vl = List.map (fun ((v,pv),t,e) -> try - let t = Typeload.load_type_opt ctx p t in + let t = Typeload.load_type_hint ctx p t in let e = (match e with | None -> None | Some e -> let e = type_expr ctx e (WithType t) in - let e = Codegen.AbstractCast.cast_or_unify ctx t e p in + let e = AbstractCast.cast_or_unify ctx t e p in Some e ) in - if v.[0] = '$' && ctx.com.display = DMNone then error "Variables names starting with a dollar are not allowed" p; - add_local ctx v t, e + if v.[0] = '$' then display_error ctx "Variables names starting with a dollar are not allowed" p; + let v = add_local ctx v t pv in + v.v_meta <- (Meta.UserVariable,[],pv) :: v.v_meta; + if ctx.in_display && Display.is_display_position pv then + Display.DisplayEmitter.display_variable ctx.com.display v pv; + v,e with Error (e,p) -> - display_error ctx (error_msg e) p; - add_local ctx v t_dynamic, None + check_error ctx e p; + add_unbound_local ctx v t_dynamic pv, None ) vl in - save(); - match vl with | [v,eo] -> mk (TVar (v,eo)) ctx.t.tvoid p @@ -2703,22 +2711,25 @@ and type_vars ctx vl p in_block = let e = mk (TBlock (List.map (fun (v,e) -> (mk (TVar (v,e)) ctx.t.tvoid p)) vl)) ctx.t.tvoid p in mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos -and with_type_error ctx with_type msg p = - match with_type with - | WithTypeResume _ -> raise (WithTypeError ([Unify_custom msg],p)) - | _ -> display_error ctx msg p - and format_string ctx s p = let e = ref None in let pmin = ref p.pmin in let min = ref (p.pmin + 1) in - let add enext len = - let p = { p with pmin = !min; pmax = !min + len } in + let add_expr (enext,p) len = min := !min + len; + let enext = if ctx.in_display && Display.is_display_position p then + Display.ExprPreprocessing.process_expr ctx.com (enext,p) + else + enext,p + in match !e with - | None -> e := Some (enext,p) + | None -> e := Some enext | Some prev -> - e := Some (EBinop (OpAdd,prev,(enext,p)),punion (pos prev) p) + e := Some (EBinop (OpAdd,prev,enext),punion (pos prev) p) + in + let add enext len = + let p = { p with pmin = !min; pmax = !min + len } in + add_expr (enext,p) len in let add_sub start pos = let len = pos - start in @@ -2787,7 +2798,7 @@ and format_string ctx s p = if warn_escape then warn (pos + 1) slen; min := !min + 2; if slen > 0 then - add (fst (parse_expr_string ctx scode { p with pmin = !pmin + pos + 2; pmax = !pmin + send + 1 } true)) slen; + add_expr (Parser.parse_expr_string ctx.com scode { p with pmin = !pmin + pos + 2; pmax = !pmin + send + 1 } error true) slen; min := !min + 1; parse (send + 1) (send + 1) in @@ -2804,20 +2815,16 @@ and type_block ctx el with_type p = in let rec loop = function | [] -> [] - | (EVars vl,p) :: l -> - let e = type_vars ctx vl p true in - merge e @ loop l | [e] -> (try merge (type_expr ctx e with_type) - with - Error (e,p) -> display_error ctx (error_msg e) p; []) + with Error (e,p) -> check_error ctx e p; []) | e :: l -> try let e = type_expr ctx e NoValue in merge e @ loop l with - Error (e,p) -> display_error ctx (error_msg e) p; loop l + Error (e,p) -> check_error ctx e p; loop l in let l = loop el in let rec loop = function @@ -2827,44 +2834,511 @@ and type_block ctx el with_type p = in mk (TBlock l) (loop l) p -and type_expr ctx (e,p) (with_type:with_type) = - match e with - | EField ((EConst (String s),p),"code") -> - if UTF8.length s <> 1 then error "String must be a single UTF8 char" p; - mk (TConst (TInt (Int32.of_int (UChar.code (UTF8.get s 0))))) ctx.t.tint p - | EField(_,n) when n.[0] = '$' -> - error "Field names starting with $ are not allowed" p - | EConst (Ident s) -> - if s = "super" && with_type <> NoValue then error "Cannot use super as value" p; - (try - acc_get ctx (type_ident_raise ~imported_enums:false ctx s p MGet) p - with Not_found -> try - (match with_type with - | WithType t | WithTypeResume t -> - (match follow t with - | TEnum (e,pl) -> - (try - let ef = PMap.find s e.e_constrs in - let monos = List.map (fun _ -> mk_mono()) ef.ef_params in - mk (fast_enum_field e ef p) (enum_field_type ctx e ef pl monos p) p - with Not_found -> - if ctx.untyped then raise Not_found; - with_type_error ctx with_type (string_error s e.e_names ("Identifier '" ^ s ^ "' is not part of enum " ^ s_type_path e.e_path)) p; - mk (TConst TNull) t p) - | TAbstract (a,pl) when has_meta Meta.Enum a.a_meta -> - let cimpl = (match a.a_impl with None -> assert false | Some c -> c) in - (try - let cf = PMap.find s cimpl.cl_statics in - acc_get ctx (type_field ctx (mk (TTypeExpr (TClassDecl cimpl)) (TAnon { a_fields = PMap.add cf.cf_name cf PMap.empty; a_status = ref (Statics cimpl) }) p) s p MGet) p - with Not_found -> - if ctx.untyped then raise Not_found; - with_type_error ctx with_type (string_error s (List.map (fun f -> f.cf_name) cimpl.cl_ordered_statics) ("Identifier '" ^ s ^ "' is not part of enum " ^ s_type_path a.a_path)) p; - mk (TConst TNull) t p) - | _ -> raise Not_found) +and type_object_decl ctx fl with_type p = + let dynamic_parameter = ref None in + let a = (match with_type with + | WithType t -> + let rec loop in_abstract_from t = + match follow t with + | TAnon a when not (PMap.is_empty a.a_fields) && not in_abstract_from -> ODKWithStructure a + | TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) -> + (match List.fold_left (fun acc t -> match loop true t with ODKPlain -> acc | t -> t :: acc) [] (get_abstract_froms a pl) with + | [t] -> t + | _ -> ODKPlain) + | TDynamic t when (follow t != t_dynamic) -> + dynamic_parameter := Some t; + ODKWithStructure { + a_status = ref Closed; + a_fields = PMap.empty; + } + | TInst(c,tl) when Meta.has Meta.StructInit c.cl_meta -> + ODKWithClass(c,tl) + | _ -> + ODKPlain + in + loop false t + | _ -> + ODKPlain + ) in + let wrap_quoted_meta e = + mk (TMeta((Meta.QuotedField,[],e.epos),e)) e.etype e.epos + in + let type_fields field_map = + let fields = ref PMap.empty in + let extra_fields = ref [] in + let fl = List.map (fun ((n,pn),e) -> + let n,is_quoted,is_valid = Parser.unquote_ident n in + if PMap.mem n !fields then error ("Duplicate field in object declaration : " ^ n) p; + let e = try + let t = match !dynamic_parameter with + | Some t -> t + | None -> + let cf = PMap.find n field_map in + if ctx.in_display && Display.is_display_position pn then Display.DisplayEmitter.display_field ctx.com.display cf pn; + cf.cf_type + in + let e = type_expr ctx e (WithType t) in + let e = AbstractCast.cast_or_unify ctx t e p in + (try type_eq EqStrict e.etype t; e with Unify_error _ -> mk (TCast (e,None)) t e.epos) + with Not_found -> + if is_valid then + extra_fields := n :: !extra_fields; + type_expr ctx e Value + in + if is_valid then begin + if String.length n > 0 && n.[0] = '$' then error "Field names starting with a dollar are not allowed" p; + let cf = mk_field n e.etype (punion pn e.epos) pn in + fields := PMap.add n cf !fields; + end; + let e = if is_quoted then wrap_quoted_meta e else e in + (n,e) + ) fl in + let t = (TAnon { a_fields = !fields; a_status = ref Const }) in + if not ctx.untyped then begin + (match PMap.foldi (fun n cf acc -> if not (Meta.has Meta.Optional cf.cf_meta) && not (PMap.mem n !fields) then n :: acc else acc) field_map [] with + | [] -> () + | [n] -> raise_or_display ctx [Unify_custom ("Object requires field " ^ n)] p + | nl -> raise_or_display ctx [Unify_custom ("Object requires fields: " ^ (String.concat ", " nl))] p); + (match !extra_fields with + | [] -> () + | _ -> raise_or_display ctx (List.map (fun n -> has_extra_field t n) !extra_fields) p); + end; + t, fl + in + (match a with + | ODKPlain -> + let rec loop (l,acc) ((f,pf),e) = + let f,is_quoted,is_valid = Parser.unquote_ident f in + if PMap.mem f acc then error ("Duplicate field in object declaration : " ^ f) p; + let e = type_expr ctx e Value in + (match follow e.etype with TAbstract({a_path=[],"Void"},_) -> error "Fields of type Void are not allowed in structures" e.epos | _ -> ()); + let cf = mk_field f e.etype (punion pf e.epos) pf in + if ctx.in_display && Display.is_display_position pf then Display.DisplayEmitter.display_field ctx.com.display cf pf; + let e = if is_quoted then wrap_quoted_meta e else e in + ((f,e) :: l, if is_valid then begin + if String.length f > 0 && f.[0] = '$' then error "Field names starting with a dollar are not allowed" p; + PMap.add f cf acc + end else acc) + in + let fields , types = List.fold_left loop ([],PMap.empty) fl in + let x = ref Const in + ctx.opened <- x :: ctx.opened; + mk (TObjectDecl (List.rev fields)) (TAnon { a_fields = types; a_status = x }) p + | ODKWithStructure a -> + let t, fl = type_fields a.a_fields in + if !(a.a_status) <> Const then a.a_status := Closed; + mk (TObjectDecl fl) t p + | ODKWithClass (c,tl) -> + let t,ctor = get_constructor ctx c tl p in + let args = match follow t with + | TFun(args,_) -> args + | _ -> assert false + in + let fields = List.fold_left (fun acc (n,opt,t) -> + let f = mk_field n t ctor.cf_pos ctor.cf_name_pos in + if opt then f.cf_meta <- [(Meta.Optional,[],ctor.cf_pos)]; + PMap.add n f acc + ) PMap.empty args in + let t,fl = type_fields fields in + let evars,fl,_ = List.fold_left (fun (evars,elocs,had_side_effect) (s,e) -> + begin match e.eexpr with + | TConst _ | TTypeExpr _ | TFunction _ -> + evars,(s,e) :: elocs,had_side_effect | _ -> - raise Not_found) + if had_side_effect then begin + let v = gen_local ctx e.etype e.epos in + let ev = mk (TVar(v,Some e)) e.etype e.epos in + let eloc = mk (TLocal v) v.v_type e.epos in + (ev :: evars),((s,eloc) :: elocs),had_side_effect + end else + evars,(s,e) :: elocs,OptimizerTexpr.has_side_effect e + end + ) ([],[],false) (List.rev fl) in + let el = List.map (fun (n,_,t) -> + try List.assoc n fl + with Not_found -> mk (TConst TNull) t p + ) args in + let e = mk (TNew(c,tl,el)) (TInst(c,tl)) p in + mk (TBlock (List.rev (e :: (List.rev evars)))) e.etype e.epos + ) + +and type_new ctx path el with_type p = + let unify_constructor_call c params f ct = match follow ct with + | TFun (args,r) -> + (try + let el,_,_ = unify_field_call ctx (FInstance(c,params,f)) el args r p false in + el + with Error (e,p) -> + display_error ctx (error_msg e) p; + []) + | _ -> + error "Constructor is not a function" p + in + let t = if (fst path).tparams <> [] then + follow (Typeload.load_instance ctx path false p) + else try + ctx.call_argument_stack <- el :: ctx.call_argument_stack; + let t = follow (Typeload.load_instance ctx path true p) in + ctx.call_argument_stack <- List.tl ctx.call_argument_stack; + (* Try to properly build @:generic classes here (issue #2016) *) + begin match t with + | TInst({cl_kind = KGeneric } as c,tl) -> follow (Typeload.build_generic ctx c p tl) + | _ -> t + end + with Typeload.Generic_Exception _ -> + (* Try to infer generic parameters from the argument list (issue #2044) *) + match resolve_typedef (Typeload.load_type_def ctx p (fst path)) with + | TClassDecl ({cl_constructor = Some cf} as c) -> + let monos = List.map (fun _ -> mk_mono()) c.cl_params in + let ct, f = get_constructor ctx c monos p in + ignore (unify_constructor_call c monos f ct); + begin try + let t = Typeload.build_generic ctx c p monos in + let map = apply_params c.cl_params monos in + check_constraints ctx (s_type_path c.cl_path) c.cl_params monos map true p; + t + with Typeload.Generic_Exception _ as exc -> + (* If we have an expected type, just use that (issue #3804) *) + begin match with_type with + | WithType t -> + begin match follow t with + | TMono _ -> raise exc + | t -> t + end + | _ -> + raise exc + end + end + | mt -> + error ((s_type_path (t_infos mt).mt_path) ^ " cannot be constructed") p + in + Display.DisplayEmitter.check_display_type ctx t (pos path); + let build_constructor_call c tl = + let ct, f = get_constructor ctx c tl p in + if (Meta.has Meta.CompilerGenerated f.cf_meta) then display_error ctx (error_msg (No_constructor (TClassDecl c))) p; + if not (can_access ctx c f true || is_parent c ctx.curclass) && not ctx.untyped then display_error ctx "Cannot access private constructor" p; + (match f.cf_kind with + | Var { v_read = AccRequire (r,msg) } -> (match msg with Some msg -> error msg p | None -> error_require r p) + | _ -> ()); + let el = unify_constructor_call c tl f ct in + el,f,ct + in + try begin match t with + | TInst ({cl_kind = KTypeParameter tl} as c,params) -> + if not (Typeload.is_generic_parameter ctx c) then error "Only generic type parameters can be constructed" p; + let el = List.map (fun e -> type_expr ctx e Value) el in + let ct = (tfun (List.map (fun e -> e.etype) el) ctx.t.tvoid) in + let rec loop t = match follow t with + | TAnon a -> + (try + unify ctx (PMap.find "new" a.a_fields).cf_type ct p; + true + with Not_found -> + false) + | TAbstract({a_path = ["haxe"],"Constructible"},_) -> true + | TInst({cl_kind = KTypeParameter tl},_) -> List.exists loop tl + | _ -> false + in + if not (List.exists loop tl) then raise_error (No_constructor (TClassDecl c)) p; + mk (TNew (c,params,el)) t p + | TAbstract({a_impl = Some c} as a,tl) when not (Meta.has Meta.MultiType a.a_meta) -> + let el,cf,ct = build_constructor_call c tl in + let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in + let e = mk (TTypeExpr (TClassDecl c)) ta p in + let e = mk (TField (e,(FStatic (c,cf)))) ct p in + make_call ctx e el t p + | TInst (c,params) | TAbstract({a_impl = Some c},params) -> + let el,_,_ = build_constructor_call c params in + mk (TNew (c,params,el)) t p + | _ -> + error (s_type (print_context()) t ^ " cannot be constructed") p + end with Error(No_constructor _ as err,p) when ctx.com.display.dms_display -> + display_error ctx (error_msg err) p; + Display.Diagnostics.secure_generated_code ctx (mk (TConst TNull) t p) + +and type_try ctx e1 catches with_type p = + let e1 = type_expr ctx (Expr.ensure_block e1) with_type in + let rec check_unreachable cases t p = match cases with + | (v,e) :: cases -> + let unreachable () = + display_error ctx "This block is unreachable" p; + let st = s_type (print_context()) in + display_error ctx (Printf.sprintf "%s can be assigned to %s, which is handled here" (st t) (st v.v_type)) e.epos + in + begin try + begin match follow t,follow v.v_type with + | TDynamic _, TDynamic _ -> + unreachable() + | TDynamic _,_ -> + () + | _ -> + Type.unify t v.v_type; + unreachable() + end + with Unify_error _ -> + check_unreachable cases t p + end + | [] -> + () + in + let check_catch_type path params = + List.iter (fun pt -> + if pt != t_dynamic then error "Catch class parameter must be Dynamic" p; + ) params; + (match path with + | x :: _ , _ -> x + | [] , name -> name) + in + let catches = List.fold_left (fun acc ((v,pv),t,e_ast,pc) -> + let t = Typeload.load_complex_type ctx true p t in + let rec loop t = match follow t with + | TInst ({ cl_kind = KTypeParameter _} as c,_) when not (Typeload.is_generic_parameter ctx c) -> + error "Cannot catch non-generic type parameter" p + | TInst ({ cl_path = path },params) + | TEnum ({ e_path = path },params) -> + check_catch_type path params,t + | TAbstract(a,params) when Meta.has Meta.RuntimeValue a.a_meta -> + check_catch_type a.a_path params,t + | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> + loop (Abstract.get_underlying_type a tl) + | TDynamic _ -> "",t + | _ -> error "Catch type must be a class, an enum or Dynamic" (pos e_ast) + in + let name,t2 = loop t in + if v.[0] = '$' then display_error ctx "Catch variable names starting with a dollar are not allowed" p; + check_unreachable acc t2 (pos e_ast); + let locals = save_locals ctx in + let v = add_local ctx v t pv in + if ctx.is_display_file && Display.is_display_position pv then + Display.DisplayEmitter.display_variable ctx.com.display v pv; + let e = type_expr ctx e_ast with_type in + (* If the catch position is the display position it means we get completion on the catch keyword or some + punctuation. Otherwise we wouldn't reach this point. *) + if ctx.is_display_file && Display.is_display_position pc then ignore(display_expr ctx e_ast e with_type pc); + v.v_type <- t2; + locals(); + if with_type <> NoValue then unify ctx e.etype e1.etype e.epos; + if PMap.mem name ctx.locals then error ("Local variable " ^ name ^ " is preventing usage of this type here") e.epos; + (v , e) :: acc + ) [] catches in + mk (TTry (e1,List.rev catches)) (if with_type = NoValue then ctx.t.tvoid else e1.etype) p + +and type_map_declaration ctx e1 el with_type p = + let (tkey,tval,has_type) = + let get_map_params t = match follow t with + | TAbstract({a_path=[],"Map"},[tk;tv]) -> tk,tv,true + | TInst({cl_path=["haxe";"ds"],"IntMap"},[tv]) -> ctx.t.tint,tv,true + | TInst({cl_path=["haxe";"ds"],"StringMap"},[tv]) -> ctx.t.tstring,tv,true + | TInst({cl_path=["haxe";"ds"],("ObjectMap" | "EnumValueMap")},[tk;tv]) -> tk,tv,true + | _ -> mk_mono(),mk_mono(),false + in + match with_type with + | WithType t -> get_map_params t + | _ -> (mk_mono(),mk_mono(),false) + in + let keys = Hashtbl.create 0 in + let check_key e_key = + try + let p = Hashtbl.find keys e_key.eexpr in + display_error ctx "Duplicate key" e_key.epos; + error "Previously defined here" p with Not_found -> - acc_get ctx (type_access ctx e p MGet) p) + Hashtbl.add keys e_key.eexpr e_key.epos; + in + let el = e1 :: el in + let el_kv = List.map (fun e -> match fst e with + | EBinop(OpArrow,e1,e2) -> e1,e2 + | _ -> error "Expected a => b" (pos e) + ) el in + let el_k,el_v,tkey,tval = if has_type then begin + let el_k,el_v = List.fold_left (fun (el_k,el_v) (e1,e2) -> + let e1 = type_expr ctx e1 (WithType tkey) in + check_key e1; + let e1 = AbstractCast.cast_or_unify ctx tkey e1 e1.epos in + let e2 = type_expr ctx e2 (WithType tval) in + let e2 = AbstractCast.cast_or_unify ctx tval e2 e2.epos in + (e1 :: el_k,e2 :: el_v) + ) ([],[]) el_kv in + el_k,el_v,tkey,tval + end else begin + let el_k,el_v = List.fold_left (fun (el_k,el_v) (e1,e2) -> + let e1 = type_expr ctx e1 Value in + check_key e1; + let e2 = type_expr ctx e2 Value in + (e1 :: el_k,e2 :: el_v) + ) ([],[]) el_kv in + let unify_min_resume el = try + unify_min_raise ctx el + with Error (Unify l,p) when ctx.in_call_args -> + raise (WithTypeError(Unify l,p)) + in + let tkey = unify_min_resume el_k in + let tval = unify_min_resume el_v in + el_k,el_v,tkey,tval + end in + let m = Typeload.load_module ctx ([],"Map") null_pos in + let a,c = match m.m_types with + | (TAbstractDecl ({a_impl = Some c} as a)) :: _ -> a,c + | _ -> assert false + in + let tmap = TAbstract(a,[tkey;tval]) in + let cf = PMap.find "set" c.cl_statics in + let v = gen_local ctx tmap p in + let ev = mk (TLocal v) tmap p in + let ec = type_module_type ctx (TClassDecl c) None p in + let ef = mk (TField(ec,FStatic(c,cf))) (tfun [tkey;tval] ctx.t.tvoid) p in + let el = ev :: List.map2 (fun e1 e2 -> (make_call ctx ef [ev;e1;e2] ctx.com.basic.tvoid p)) el_k el_v in + let enew = mk (TNew(c,[tkey;tval],[])) tmap p in + let el = (mk (TVar (v,Some enew)) t_dynamic p) :: (List.rev el) in + mk (TBlock el) tmap p + +and type_local_function ctx name f with_type p = + let params = Typeload.type_function_params ctx f (match name with None -> "localfun" | Some n -> n) p in + if params <> [] then begin + if name = None then display_error ctx "Type parameters not supported in unnamed local functions" p; + if with_type <> NoValue then error "Type parameters are not supported for rvalue functions" p + end; + List.iter (fun tp -> if tp.tp_constraints <> [] then display_error ctx "Type parameter constraints are not supported for local functions" p) f.f_params; + let inline, v = (match name with + | None -> false, None + | Some v when ExtString.String.starts_with v "inline_" -> true, Some (String.sub v 7 (String.length v - 7)) + | Some v -> false, Some v + ) in + let old_tp,old_in_loop = ctx.type_params,ctx.in_loop in + ctx.type_params <- params @ ctx.type_params; + if not inline then ctx.in_loop <- false; + let rt = Typeload.load_type_hint ctx p f.f_type in + let args = List.map (fun ((s,_),opt,_,t,c) -> + let t = Typeload.load_type_hint ctx p t in + let t, c = Typeload.type_function_arg ctx t c opt p in + s, c, t + ) f.f_args in + (match with_type with + | WithType t -> + let rec loop t = + (match follow t with + | TFun (args2,tr) when List.length args2 = List.length args -> + List.iter2 (fun (_,_,t1) (_,_,t2) -> + match follow t1 with + | TMono _ -> unify ctx t2 t1 p + | _ -> () + ) args args2; + (* unify for top-down inference unless we are expecting Void *) + begin match follow tr,follow rt with + | TAbstract({a_path = [],"Void"},_),_ -> () + | _,TMono _ -> unify ctx rt tr p + | _ -> () + end + | TAbstract(a,tl) -> + loop (Abstract.get_underlying_type a tl) + | _ -> ()) + in + loop t + | NoValue -> + if name = None then display_error ctx "Unnamed lvalue functions are not supported" p + | _ -> + ()); + let ft = TFun (fun_args args,rt) in + let v = (match v with + | None -> None + | Some v -> + if v.[0] = '$' then display_error ctx "Variable names starting with a dollar are not allowed" p; + Some (add_local ctx v ft p) (* TODO: var pos *) + ) in + let curfun = match ctx.curfun with + | FunStatic -> FunStatic + | FunMemberAbstract -> FunMemberAbstractLocal + | _ -> FunMemberClassLocal + in + let e , fargs = Typeload.type_function ctx args rt curfun f ctx.in_display p in + ctx.type_params <- old_tp; + ctx.in_loop <- old_in_loop; + let f = { + tf_args = fargs; + tf_type = rt; + tf_expr = e; + } in + let e = mk (TFunction f) ft p in + (match v with + | None -> e + | Some v -> + if params <> [] || inline then v.v_extra <- Some (params,if inline then Some e else None); + let rec loop = function + | Filters.Block f | Filters.Loop f | Filters.Function f -> f loop + | Filters.Use v2 | Filters.Assign v2 when v == v2 -> raise Exit + | Filters.Use _ | Filters.Assign _ | Filters.Declare _ -> () + in + let is_rec = (try Filters.local_usage loop e; false with Exit -> true) in + let decl = (if is_rec then begin + if inline then display_error ctx "Inline function cannot be recursive" e.epos; + let vnew = add_local ctx v.v_name ft v.v_pos in + mk (TVar (vnew,Some (mk (TBlock [ + mk (TVar (v,Some (mk (TConst TNull) ft p))) ctx.t.tvoid p; + mk (TBinop (OpAssign,mk (TLocal v) ft p,e)) ft p; + mk (TLocal v) ft p + ]) ft p))) ctx.t.tvoid p + end else if inline then + mk (TBlock []) ctx.t.tvoid p (* do not add variable since it will be inlined *) + else + mk (TVar (v,Some e)) ctx.t.tvoid p + ) in + if with_type <> NoValue && not inline then mk (TBlock [decl;mk (TLocal v) v.v_type p]) v.v_type p else decl) + +and type_array_decl ctx el with_type p = + let tp = (match with_type with + | WithType t -> + let rec loop t = + (match follow t with + | TInst ({ cl_path = [],"Array" },[tp]) -> + (match follow tp with + | TMono _ -> None + | _ -> Some tp) + | TAnon _ -> + (try + Some (get_iterable_param t) + with Not_found -> + None) + | TAbstract (a,pl) -> + (match List.fold_left (fun acc t -> match loop t with None -> acc | Some t -> t :: acc) [] (get_abstract_froms a pl) with + | [t] -> Some t + | _ -> None) + | t -> + if t == t_dynamic then Some t else None) + in + loop t + | _ -> + None + ) in + (match tp with + | None -> + let el = List.map (fun e -> type_expr ctx e Value) el in + let t = try + unify_min_raise ctx el + with Error (Unify l,p) -> + if ctx.untyped || ctx.com.display.dms_error_policy = EPIgnore then t_dynamic else begin + display_error ctx "Arrays of mixed types are only allowed if the type is forced to Array" p; + raise (Error (Unify l, p)) + end + in + mk (TArrayDecl el) (ctx.t.tarray t) p + | Some t -> + let el = List.map (fun e -> + let e = type_expr ctx e (WithType t) in + AbstractCast.cast_or_unify ctx t e p; + ) el in + mk (TArrayDecl el) (ctx.t.tarray t) p) + +and type_expr ctx (e,p) (with_type:with_type) = + match e with + | EField ((EConst (String s),ps),"code") -> + if UTF8.length s <> 1 then error "String must be a single UTF8 char" ps; + mk (TConst (TInt (Int32.of_int (UChar.code (UTF8.get s 0))))) ctx.t.tint p + | EField(_,n) when n.[0] = '$' -> + error "Field names starting with $ are not allowed" p + | EConst (Ident s) -> + if s = "super" && with_type <> NoValue && not ctx.in_display then error "Cannot use super as value" p; + let e = maybe_type_against_enum ctx (fun () -> type_ident ctx s p MGet) with_type p in + acc_get ctx e p | EField _ | EArray _ -> acc_get ctx (type_access ctx e p MGet) p @@ -2873,7 +3347,7 @@ and type_expr ctx (e,p) (with_type:with_type) = let opt = mk (TConst (TString opt)) ctx.t.tstring p in let t = Typeload.load_core_type ctx "EReg" in mk (TNew ((match t with TInst (c,[]) -> c | _ -> assert false),[],[str;opt])) t p - | EConst (String s) when Lexer.is_fmt_string p -> + | EConst (String s) when s <> "" && Lexer.is_fmt_string p -> type_expr ctx (format_string ctx s p) with_type | EConst c -> Codegen.type_constant ctx.com c p @@ -2890,90 +3364,9 @@ and type_expr ctx (e,p) (with_type:with_type) = let e = type_expr ctx e with_type in mk (TParenthesis e) e.etype p | EObjectDecl fl -> - let dynamic_parameter = ref None in - let a = (match with_type with - | WithType t | WithTypeResume t -> - (match follow t with - | TAnon a when not (PMap.is_empty a.a_fields) -> Some a - (* issues with https://github.com/HaxeFoundation/haxe/issues/3437 *) -(* | TAbstract (a,tl) when not (Meta.has Meta.CoreType a.a_meta) && a.a_from <> [] -> - begin match follow (Abstract.get_underlying_type a tl) with - | TAnon a when not (PMap.is_empty a.a_fields) -> Some a - | _ -> None - end *) - | TDynamic t when (follow t != t_dynamic) -> - dynamic_parameter := Some t; - Some { - a_status = ref Closed; - a_fields = PMap.empty; - } - | _ -> None) - | _ -> None - ) in - let wrap_quoted_meta e = - mk (TMeta((Meta.QuotedField,[],e.epos),e)) e.etype e.epos - in - (match a with - | None -> - let rec loop (l,acc) (f,e) = - let f,is_quoted,is_valid = Parser.unquote_ident f in - if PMap.mem f acc then error ("Duplicate field in object declaration : " ^ f) p; - let e = type_expr ctx e Value in - (match follow e.etype with TAbstract({a_path=[],"Void"},_) -> error "Fields of type Void are not allowed in structures" e.epos | _ -> ()); - let cf = mk_field f e.etype e.epos in - let e = if is_quoted then wrap_quoted_meta e else e in - ((f,e) :: l, if is_valid then begin - if String.length f > 0 && f.[0] = '$' then error "Field names starting with a dollar are not allowed" p; - PMap.add f cf acc - end else acc) - in - let fields , types = List.fold_left loop ([],PMap.empty) fl in - let x = ref Const in - ctx.opened <- x :: ctx.opened; - mk (TObjectDecl (List.rev fields)) (TAnon { a_fields = types; a_status = x }) p - | Some a -> - let fields = ref PMap.empty in - let extra_fields = ref [] in - let fl = List.map (fun (n, e) -> - let n,is_quoted,is_valid = Parser.unquote_ident n in - if PMap.mem n !fields then error ("Duplicate field in object declaration : " ^ n) p; - let e = try - let t = (match !dynamic_parameter with Some t -> t | None -> (PMap.find n a.a_fields).cf_type) in - let e = type_expr ctx e (match with_type with WithTypeResume _ -> WithTypeResume t | _ -> WithType t) in - let e = Codegen.AbstractCast.cast_or_unify ctx t e p in - (try type_eq EqStrict e.etype t; e with Unify_error _ -> mk (TCast (e,None)) t e.epos) - with Not_found -> - if is_valid then - extra_fields := n :: !extra_fields; - type_expr ctx e Value - in - if is_valid then begin - if String.length n > 0 && n.[0] = '$' then error "Field names starting with a dollar are not allowed" p; - let cf = mk_field n e.etype e.epos in - fields := PMap.add n cf !fields; - end; - let e = if is_quoted then wrap_quoted_meta e else e in - (n,e) - ) fl in - let t = (TAnon { a_fields = !fields; a_status = ref Const }) in - if not ctx.untyped then begin - let unify_error l p = - match with_type with - | WithTypeResume _ -> raise (WithTypeError (l,p)) - | _ -> raise (Error (Unify l,p)) - in - (match PMap.foldi (fun n cf acc -> if not (Meta.has Meta.Optional cf.cf_meta) && not (PMap.mem n !fields) then n :: acc else acc) a.a_fields [] with - | [] -> () - | [n] -> unify_error [Unify_custom ("Object requires field " ^ n)] p - | nl -> unify_error [Unify_custom ("Object requires fields: " ^ (String.concat ", " nl))] p); - (match !extra_fields with - | [] -> () - | _ -> unify_error (List.map (fun n -> has_extra_field t n) !extra_fields) p); - end; - if !(a.a_status) <> Const then a.a_status := Closed; - mk (TObjectDecl fl) t p) + type_object_decl ctx fl with_type p | EArrayDecl [(EFor _,_) | (EWhile _,_) as e] -> - let v = gen_local ctx (mk_mono()) in + let v = gen_local ctx (mk_mono()) p in let et = ref (EConst(Ident "null"),p) in let rec map_compr (e,p) = match e with @@ -2983,7 +3376,7 @@ and type_expr ctx (e,p) (with_type:with_type) = | EBlock [e] -> (EBlock [map_compr e],p) | EParenthesis e2 -> (EParenthesis (map_compr e2),p) | EBinop(OpArrow,a,b) -> - et := (ENew({tpackage=[];tname="Map";tparams=[];tsub=None},[]),p); + et := (ENew(({tpackage=[];tname="Map";tparams=[];tsub=None},null_pos),[]),p); (ECall ((EField ((EConst (Ident v.v_name),p),"set"),p),[a;b]),p) | _ -> et := (EArrayDecl [],p); @@ -2999,134 +3392,62 @@ and type_expr ctx (e,p) (with_type:with_type) = mk (TLocal v) v.v_type p; ]) v.v_type p | EArrayDecl ((EBinop(OpArrow,_,_),_) as e1 :: el) -> - let keys = Hashtbl.create 0 in - let (tkey,tval),resume = - let get_map_params t = match follow t with - | TAbstract({a_path=[],"Map"},[tk;tv]) -> tk,tv - | _ -> mk_mono(),mk_mono() - in - match with_type with - | WithType t -> get_map_params t,false - | WithTypeResume t -> get_map_params t,true - | _ -> (mk_mono(),mk_mono()),false - in - let unify_with_resume ctx e t p = - if resume then try Codegen.AbstractCast.cast_or_unify_raise ctx t e p with Error (Unify l,p) -> raise (WithTypeError(l,p)) - else Codegen.AbstractCast.cast_or_unify ctx t e p - in - let type_arrow e1 e2 = - let e1 = type_expr ctx e1 (WithType tkey) in - try - let p = Hashtbl.find keys e1.eexpr in - display_error ctx "Duplicate key" e1.epos; - error "Previously defined here" p - with Not_found -> - Hashtbl.add keys e1.eexpr e1.epos; - let e1 = unify_with_resume ctx e1 tkey e1.epos in - let e2 = type_expr ctx e2 (WithType tval) in - let e2 = unify_with_resume ctx e2 tval e2.epos in - e1,e2 - in - let m = Typeload.load_module ctx ([],"Map") null_pos in - let a,c = match m.m_types with - | (TAbstractDecl ({a_impl = Some c} as a)) :: _ -> a,c - | _ -> assert false - in - let tmap = TAbstract(a,[tkey;tval]) in - let cf = PMap.find "set" c.cl_statics in - let el = e1 :: el in - let v = gen_local ctx tmap in - let ev = mk (TLocal v) tmap p in - let ec = type_module_type ctx (TClassDecl c) None p in - let ef = mk (TField(ec,FStatic(c,cf))) (tfun [tkey;tval] ctx.t.tvoid) p in - let el = ev :: List.fold_left (fun acc e -> match fst e with - | EBinop(OpArrow,e1,e2) -> - let e1,e2 = type_arrow e1 e2 in - (make_call ctx ef [ev;e1;e2] ctx.com.basic.tvoid p) :: acc - | _ -> - error "Expected a => b" (snd e) - ) [] el in - let enew = mk (TNew(c,[tkey;tval],[])) tmap p in - let el = (mk (TVar (v,Some enew)) t_dynamic p) :: (List.rev el) in - mk (TBlock el) tmap p + type_map_declaration ctx e1 el with_type p | EArrayDecl el -> - let tp = (match with_type with - | WithType t | WithTypeResume t -> - (match follow t with - | TInst ({ cl_path = [],"Array" },[tp]) -> - (match follow tp with - | TMono _ -> None - | _ -> Some tp) - | TAnon _ -> - (try - Some (get_iterable_param t) - with Not_found -> - None) - | t -> - if t == t_dynamic then Some t else None) - | _ -> - None - ) in - (match tp with - | None -> - let el = List.map (fun e -> type_expr ctx e Value) el in - let t = try - unify_min_raise ctx el - with Error (Unify l,p) -> - if ctx.untyped then t_dynamic else begin - display_error ctx "Arrays of mixed types are only allowed if the type is forced to Array" p; - raise (Error (Unify l, p)) - end - in - mk (TArrayDecl el) (ctx.t.tarray t) p - | Some t -> - let el = List.map (fun e -> - let e = type_expr ctx e (match with_type with WithTypeResume _ -> WithTypeResume t | _ -> WithType t) in - (match with_type with - | WithTypeResume _ -> (try Codegen.AbstractCast.cast_or_unify_raise ctx t e p with Error (Unify l,p) -> raise (WithTypeError (l,p))) - | _ -> Codegen.AbstractCast.cast_or_unify ctx t e p); - ) el in - mk (TArrayDecl el) (ctx.t.tarray t) p) + type_array_decl ctx el with_type p | EVars vl -> - type_vars ctx vl p false + type_vars ctx vl p | EFor (it,e2) -> - let i, pi, e1 = (match it with - | (EIn ((EConst (Ident i),pi),e),_) -> i, pi, e + let rec loop_ident display e1 = match e1 with + | EConst(Ident i),p -> i,p,display + | EDisplay(e1,_),_ -> loop_ident true e1 + | _ -> error "Identifier expected" (pos e1) + in + let rec loop display e1 = match fst e1 with + | EIn(e1,e2) -> loop_ident display e1,e2 + | EDisplay(e1,_) -> loop true e1 | _ -> error "For expression should be 'v in expr'" (snd it) - ) in + in + let (i, pi, display), e1 = loop false it in let e1 = type_expr ctx e1 Value in let old_loop = ctx.in_loop in let old_locals = save_locals ctx in ctx.in_loop <- true; - let e = (match Optimizer.optimize_for_loop ctx (i,pi) e1 e2 p with - | Some e -> e - | None -> - let t, pt = Typeload.t_iterator ctx in - let i = add_local ctx i pt in - let e1 = (match follow e1.etype with - | TMono _ - | TDynamic _ -> - display_error ctx "You can't iterate on a Dynamic value, please specify Iterator or Iterable" e1.epos; - e1 - | TLazy _ -> - assert false - | _ -> - (try - Codegen.AbstractCast.cast_or_unify_raise ctx t e1 p - with Error (Unify _,_) -> - let acc = build_call ctx (type_field ctx e1 "iterator" e1.epos MCall) [] Value e1.epos in - try - unify_raise ctx acc.etype t acc.epos; - acc - with Error (Unify(l),p) -> - display_error ctx "Field iterator has an invalid type" acc.epos; - display_error ctx (error_msg (Unify l)) p; - mk (TConst TNull) t_dynamic p - ) - ) in - let e2 = type_expr ctx e2 NoValue in - (try Optimizer.optimize_for_loop_iterator ctx i e1 e2 p with Exit -> mk (TFor (i,e1,e2)) ctx.t.tvoid p) - ) in + let e2 = Expr.ensure_block e2 in + let default() = + let t, pt = Typeload.t_iterator ctx in + let i = add_local ctx i pt pi in + let e1 = (match follow e1.etype with + | TMono _ + | TDynamic _ -> + display_error ctx "You can't iterate on a Dynamic value, please specify Iterator or Iterable" e1.epos; + e1 + | TLazy _ -> + assert false + | _ -> + (try + AbstractCast.cast_or_unify_raise ctx t e1 p + with Error (Unify _,_) -> + let acc = build_call ctx (type_field ctx e1 "iterator" e1.epos MCall) [] Value e1.epos in + try + unify_raise ctx acc.etype t acc.epos; + acc + with Error (Unify(l),p) -> + display_error ctx "Field iterator has an invalid type" acc.epos; + display_error ctx (error_msg (Unify l)) p; + mk (TConst TNull) t_dynamic p + ) + ) in + if display then ignore(handle_display ctx (EConst(Ident i.v_name),i.v_pos) (WithType i.v_type)); + let e2 = type_expr ctx e2 NoValue in + (try Optimizer.optimize_for_loop_iterator ctx i e1 e2 p with Exit -> mk (TFor (i,e1,e2)) ctx.t.tvoid p) + in + let e = match Optimizer.optimize_for_loop ctx (i,pi) e1 e2 p with + | Some e -> + if display then ignore(handle_display ctx (EConst(Ident i),pi) Value); + e + | None -> default() + in ctx.in_loop <- old_loop; old_locals(); e @@ -3136,66 +3457,63 @@ and type_expr ctx (e,p) (with_type:with_type) = type_expr ctx (EIf (e1,e2,Some e3),p) with_type | EIf (e,e1,e2) -> let e = type_expr ctx e Value in - let e = Codegen.AbstractCast.cast_or_unify ctx ctx.t.tbool e p in - let e1 = type_expr ctx e1 with_type in + let e = AbstractCast.cast_or_unify ctx ctx.t.tbool e p in + let e1 = type_expr ctx (Expr.ensure_block e1) with_type in (match e2 with | None -> mk (TIf (e,e1,None)) ctx.t.tvoid p | Some e2 -> - let e2 = type_expr ctx e2 with_type in + let e2 = type_expr ctx (Expr.ensure_block e2) with_type in let e1,e2,t = match with_type with | NoValue -> e1,e2,ctx.t.tvoid | Value -> e1,e2,unify_min ctx [e1; e2] - | WithType t | WithTypeResume t when (match follow t with TMono _ -> true | _ -> false) -> e1,e2,unify_min ctx [e1; e2] - | WithType t | WithTypeResume t -> - begin try - let e1 = Codegen.AbstractCast.cast_or_unify_raise ctx t e1 e1.epos in - let e2 = Codegen.AbstractCast.cast_or_unify_raise ctx t e2 e2.epos in + | WithType t when (match follow t with TMono _ -> true | _ -> false) -> e1,e2,unify_min ctx [e1; e2] + | WithType t -> + let e1 = AbstractCast.cast_or_unify ctx t e1 e1.epos in + let e2 = AbstractCast.cast_or_unify ctx t e2 e2.epos in e1,e2,t - with Error (Unify l,p) -> match with_type with - | WithTypeResume _ -> raise (WithTypeError (l,p)) - | _ -> - display_error ctx (error_msg (Unify l)) p; - e1,e2,t - end; in mk (TIf (e,e1,Some e2)) t p) | EWhile (cond,e,NormalWhile) -> let old_loop = ctx.in_loop in let cond = type_expr ctx cond Value in - let cond = Codegen.AbstractCast.cast_or_unify ctx ctx.t.tbool cond p in + let cond = AbstractCast.cast_or_unify ctx ctx.t.tbool cond p in ctx.in_loop <- true; - let e = type_expr ctx e NoValue in + let e = type_expr ctx (Expr.ensure_block e) NoValue in ctx.in_loop <- old_loop; mk (TWhile (cond,e,NormalWhile)) ctx.t.tvoid p | EWhile (cond,e,DoWhile) -> let old_loop = ctx.in_loop in ctx.in_loop <- true; - let e = type_expr ctx e NoValue in + let e = type_expr ctx (Expr.ensure_block e) NoValue in ctx.in_loop <- old_loop; let cond = type_expr ctx cond Value in - let cond = Codegen.AbstractCast.cast_or_unify ctx ctx.t.tbool cond p in + let cond = AbstractCast.cast_or_unify ctx ctx.t.tbool cond cond.epos in mk (TWhile (cond,e,DoWhile)) ctx.t.tvoid p | ESwitch (e1,cases,def) -> - begin try - let dt = match_expr ctx e1 cases def with_type p in - let wrap e1 = if not dt.dt_is_complex then e1 else mk (TMeta((Meta.Ast,[e,p],p),e1)) e1.etype e1.epos in - wrap (Codegen.PatternMatchConversion.to_typed_ast ctx dt p) - with Exit -> - type_switch_old ctx e1 cases def with_type p - end + let wrap e1 = mk (TMeta((Meta.Ast,[e,p],p),e1)) e1.etype e1.epos in + let e = match_expr ctx e1 cases def with_type p in + wrap e | EReturn e -> - let e , t = (match e with + begin match e with | None -> let v = ctx.t.tvoid in unify ctx v ctx.ret p; - None , v + mk (TReturn None) t_dynamic p | Some e -> let e = type_expr ctx e (WithType ctx.ret) in - let e = Codegen.AbstractCast.cast_or_unify ctx ctx.ret e p in - Some e , e.etype - ) in - mk (TReturn e) t_dynamic p + let e = AbstractCast.cast_or_unify ctx ctx.ret e p in + begin match follow e.etype with + | TAbstract({a_path=[],"Void"},_) -> + (* if we get a Void expression (e.g. from inlining) we don't want to return it (issue #4323) *) + mk (TBlock [ + e; + mk (TReturn None) t_dynamic p + ]) t_dynamic e.epos; + | _ -> + mk (TReturn (Some e)) t_dynamic p + end + end | EBreak -> if not ctx.in_loop then display_error ctx "Break outside loop" p; mk TBreak t_dynamic p @@ -3205,272 +3523,18 @@ and type_expr ctx (e,p) (with_type:with_type) = | ETry (e1,[]) -> type_expr ctx e1 with_type | ETry (e1,catches) -> - let e1 = type_expr ctx e1 with_type in - let rec check_unreachable cases t p = match cases with - | (v,e) :: cases -> - let unreachable () = - display_error ctx "This block is unreachable" p; - let st = s_type (print_context()) in - display_error ctx (Printf.sprintf "%s can be assigned to %s, which is handled here" (st t) (st v.v_type)) e.epos - in - begin try - begin match follow t,follow v.v_type with - | TDynamic _, TDynamic _ -> - unreachable() - | TDynamic _,_ -> - () - | _ -> - Type.unify t v.v_type; - unreachable() - end - with Unify_error _ -> - check_unreachable cases t p - end - | [] -> - () - in - let check_catch_type path params = - List.iter (fun pt -> - if pt != t_dynamic then error "Catch class parameter must be Dynamic" p; - ) params; - (match path with - | x :: _ , _ -> x - | [] , name -> name) - in - let catches = List.fold_left (fun acc (v,t,e) -> - let t = Typeload.load_complex_type ctx (pos e) t in - let rec loop t = match follow t with - | TInst ({ cl_kind = KTypeParameter _} as c,_) when not (Typeload.is_generic_parameter ctx c) -> - error "Cannot catch non-generic type parameter" p - | TInst ({ cl_path = path },params) - | TEnum ({ e_path = path },params) -> - check_catch_type path params,t - | TAbstract(a,params) when Meta.has Meta.RuntimeValue a.a_meta -> - check_catch_type a.a_path params,t - | TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> - loop (Abstract.get_underlying_type a tl) - | TDynamic _ -> "",t - | _ -> error "Catch type must be a class, an enum or Dynamic" (pos e) - in - let name,t2 = loop t in - if v.[0] = '$' then display_error ctx "Catch variable names starting with a dollar are not allowed" p; - check_unreachable acc t2 (pos e); - let locals = save_locals ctx in - let v = add_local ctx v t in - let e = type_expr ctx e with_type in - v.v_type <- t2; - locals(); - if with_type <> NoValue then unify ctx e.etype e1.etype e.epos; - if PMap.mem name ctx.locals then error ("Local variable " ^ name ^ " is preventing usage of this type here") e.epos; - (v , e) :: acc - ) [] catches in - mk (TTry (e1,List.rev catches)) (if with_type = NoValue then ctx.t.tvoid else e1.etype) p + type_try ctx e1 catches with_type p | EThrow e -> let e = type_expr ctx e Value in mk (TThrow e) (mk_mono()) p - | ECall (((EConst (Ident s),pc) as e),el) -> - (try - let en,t = (match with_type with - | WithType t | WithTypeResume t -> - (match follow t with - | TEnum (e,pl) -> e,t - | _ -> raise Exit) - | _ -> raise Exit - ) in - let old = ctx.on_error,ctx.m.curmod.m_types in - ctx.m.curmod.m_types <- ctx.m.curmod.m_types @ [(TEnumDecl en)]; - let restore = fun () -> - ctx.m.curmod.m_types <- snd old; - ctx.on_error <- fst old; - in - ctx.on_error <- (fun ctx msg ep -> - (* raise Not_found only if the error is actually about the outside identifier (issue #2148) *) - if ep = pc then - raise Not_found - else begin - restore(); - ctx.on_error ctx msg ep; - end - ); - begin try - let e = type_call ctx e el with_type p in - restore(); - e - with Not_found -> - restore(); - if ctx.untyped then raise Exit; (* __js__, etc. *) - with_type_error ctx with_type (string_error s en.e_names ("Identifier '" ^ s ^ "' is not part of enum " ^ s_type_path en.e_path)) p; - mk (TConst TNull) t p - | err -> - restore(); - raise err - end - with Exit -> - type_call ctx e el with_type p) | ECall (e,el) -> type_call ctx e el with_type p | ENew (t,el) -> - let unify_constructor_call c params f ct = match follow ct with - | TFun (args,r) -> - (try - let el,_,_ = unify_field_call ctx (FInstance(c,params,f)) el args r p false in - el - with Error (e,p) -> - display_error ctx (error_msg e) p; - []) - | _ -> - error "Constructor is not a function" p - in - let t = try - ctx.call_argument_stack <- el :: ctx.call_argument_stack; - let t = follow (Typeload.load_instance ctx t p true) in - ctx.call_argument_stack <- List.tl ctx.call_argument_stack; - (* Try to properly build @:generic classes here (issue #2016) *) - begin match t with - | TInst({cl_kind = KGeneric } as c,tl) -> follow (Codegen.build_generic ctx c p tl) - | _ -> t - end - with Codegen.Generic_Exception _ -> - (* Try to infer generic parameters from the argument list (issue #2044) *) - match Typeload.resolve_typedef (Typeload.load_type_def ctx p t) with - | TClassDecl ({cl_constructor = Some cf} as c) -> - let monos = List.map (fun _ -> mk_mono()) c.cl_params in - let ct, f = get_constructor ctx c monos p in - ignore (unify_constructor_call c monos f ct); - Codegen.build_generic ctx c p monos - | mt -> - error ((s_type_path (t_infos mt).mt_path) ^ " cannot be constructed") p - in - let build_constructor_call c tl = - let ct, f = get_constructor ctx c tl p in - if (Meta.has Meta.CompilerGenerated f.cf_meta) then display_error ctx (s_type_path c.cl_path ^ " does not have a constructor") p; - if not (can_access ctx c f true || is_parent c ctx.curclass) && not ctx.untyped then display_error ctx "Cannot access private constructor" p; - (match f.cf_kind with - | Var { v_read = AccRequire (r,msg) } -> (match msg with Some msg -> error msg p | None -> error_require r p) - | _ -> ()); - let el = unify_constructor_call c tl f ct in - el,f,ct - in - (match t with - | TInst ({cl_kind = KTypeParameter tl} as c,params) -> - if not (Typeload.is_generic_parameter ctx c) then error "Only generic type parameters can be constructed" p; - let el = List.map (fun e -> type_expr ctx e Value) el in - let ct = (tfun (List.map (fun e -> e.etype) el) ctx.t.tvoid) in - if not (List.exists (fun t -> match follow t with - | TAnon a -> - (try - unify ctx (PMap.find "new" a.a_fields).cf_type ct p; - true - with Not_found -> - false) - | _ -> false - ) tl) then error (s_type_path c.cl_path ^ " does not have a constructor") p; - mk (TNew (c,params,el)) t p - | TAbstract({a_impl = Some c} as a,tl) when not (Meta.has Meta.MultiType a.a_meta) -> - let el,cf,ct = build_constructor_call c tl in - let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in - let e = mk (TTypeExpr (TClassDecl c)) ta p in - let e = mk (TField (e,(FStatic (c,cf)))) ct p in - make_call ctx e el t p - | TInst (c,params) | TAbstract({a_impl = Some c},params) -> - let el,_,_ = build_constructor_call c params in - mk (TNew (c,params,el)) t p - | _ -> - error (s_type (print_context()) t ^ " cannot be constructed") p) + type_new ctx t el with_type p | EUnop (op,flag,e) -> type_unop ctx op flag e p | EFunction (name,f) -> - let params = Typeload.type_function_params ctx f (match name with None -> "localfun" | Some n -> n) p in - if params <> [] then begin - if name = None then display_error ctx "Type parameters not supported in unnamed local functions" p; - if with_type <> NoValue then error "Type parameters are not supported for rvalue functions" p - end; - List.iter (fun tp -> if tp.tp_constraints <> [] then display_error ctx "Type parameter constraints are not supported for local functions" p) f.f_params; - let inline, v = (match name with - | None -> false, None - | Some v when ExtString.String.starts_with v "inline_" -> true, Some (String.sub v 7 (String.length v - 7)) - | Some v -> false, Some v - ) in - let old_tp,old_in_loop = ctx.type_params,ctx.in_loop in - ctx.type_params <- params @ ctx.type_params; - if not inline then ctx.in_loop <- false; - let rt = Typeload.load_type_opt ctx p f.f_type in - let args = List.map (fun (s,opt,t,c) -> - let t = Typeload.load_type_opt ctx p t in - let t, c = Typeload.type_function_arg ctx t c opt p in - s , c, t - ) f.f_args in - (match with_type with - | WithType t | WithTypeResume t -> - let rec loop t = - (match follow t with - | TFun (args2,tr) when List.length args2 = List.length args -> - List.iter2 (fun (_,_,t1) (_,_,t2) -> - match follow t1 with - | TMono _ -> unify ctx t2 t1 p - | _ -> () - ) args args2; - (* unify for top-down inference unless we are expecting Void *) - begin match follow tr,follow rt with - | TAbstract({a_path = [],"Void"},_),_ -> () - | _,TMono _ -> unify ctx rt tr p - | _ -> () - end - | TAbstract(a,tl) -> - loop (Abstract.get_underlying_type a tl) - | _ -> ()) - in - loop t - | NoValue -> - if name = None then display_error ctx "Unnamed lvalue functions are not supported" p - | _ -> - ()); - let ft = TFun (fun_args args,rt) in - - let v = (match v with - | None -> None - | Some v -> - if v.[0] = '$' then display_error ctx "Variable names starting with a dollar are not allowed" p; - Some (add_local ctx v ft) - ) in - let curfun = match ctx.curfun with - | FunStatic -> FunStatic - | FunMemberAbstract -> FunMemberAbstractLocal - | _ -> FunMemberClassLocal - in - let e , fargs = Typeload.type_function ctx args rt curfun f false p in - ctx.type_params <- old_tp; - ctx.in_loop <- old_in_loop; - let f = { - tf_args = fargs; - tf_type = rt; - tf_expr = e; - } in - let e = mk (TFunction f) ft p in - (match v with - | None -> e - | Some v -> - if params <> [] || inline then v.v_extra <- Some (params,if inline then Some e else None); - let rec loop = function - | Filters.Block f | Filters.Loop f | Filters.Function f -> f loop - | Filters.Use v2 | Filters.Assign v2 when v == v2 -> raise Exit - | Filters.Use _ | Filters.Assign _ | Filters.Declare _ -> () - in - let is_rec = (try Filters.local_usage loop e; false with Exit -> true) in - let decl = (if is_rec then begin - if inline then display_error ctx "Inline function cannot be recursive" e.epos; - let vnew = add_local ctx v.v_name ft in - mk (TVar (vnew,Some (mk (TBlock [ - mk (TVar (v,Some (mk (TConst TNull) ft p))) ctx.t.tvoid p; - mk (TBinop (OpAssign,mk (TLocal v) ft p,e)) ft p; - mk (TLocal v) ft p - ]) ft p))) ctx.t.tvoid p - end else if inline then - mk (TBlock []) ctx.t.tvoid p (* do not add variable since it will be inlined *) - else - mk (TVar (v,Some e)) ctx.t.tvoid p - ) in - if with_type <> NoValue && not inline then mk (TBlock [decl;mk (TLocal v) v.v_type p]) v.v_type p else decl) + type_local_function ctx name f with_type p | EUntyped e -> let old = ctx.untyped in ctx.untyped <- true; @@ -3486,12 +3550,15 @@ and type_expr ctx (e,p) (with_type:with_type) = let e = type_expr ctx e Value in mk (TCast (e,None)) (mk_mono()) p | ECast (e, Some t) -> - let t = Typeload.load_complex_type ctx (pos e) t in + let t = Typeload.load_complex_type ctx true p t in + let check_param pt = match follow pt with + | TMono _ -> () (* This probably means that Dynamic wasn't bound (issue #4675). *) + | t when t == t_dynamic -> () + | _ ->error "Cast type parameters must be Dynamic" p + in let rec loop t = match follow t with | TInst (_,params) | TEnum (_,params) -> - List.iter (fun pt -> - if follow pt != t_dynamic then error "Cast type parameters must be Dynamic" p; - ) params; + List.iter check_param params; (match follow t with | TInst (c,_) -> (match c.cl_kind with KTypeParameter _ -> error "Can't cast to a type parameter" p | _ -> ()); @@ -3499,9 +3566,7 @@ and type_expr ctx (e,p) (with_type:with_type) = | TEnum (e,_) -> TEnumDecl e | _ -> assert false); | TAbstract (a,params) when Meta.has Meta.RuntimeValue a.a_meta -> - List.iter (fun pt -> - if follow pt != t_dynamic then error "Cast type parameters must be Dynamic" p; - ) params; + List.iter check_param params; TAbstractDecl a | TAbstract (a,params) -> loop (Abstract.get_underlying_type a params) @@ -3511,21 +3576,26 @@ and type_expr ctx (e,p) (with_type:with_type) = let texpr = loop t in mk (TCast (type_expr ctx e Value,Some texpr)) t p | EDisplay (e,iscall) -> - handle_display ctx e iscall p + begin match ctx.com.display.dms_kind with + | DMField | DMSignature when iscall -> handle_signature_display ctx e with_type + | _ -> handle_display ctx e with_type + end | EDisplayNew t -> - let t = Typeload.load_instance ctx t p true in + assert false + (*let t = Typeload.load_instance ctx t true p in (match follow t with | TInst (c,params) | TAbstract({a_impl = Some c},params) -> let ct, f = get_constructor ctx c params p in - raise (DisplayTypes (ct :: List.map (fun f -> f.cf_type) f.cf_overloads)) + raise (Display.DisplaySignatures ((ct,f.cf_doc) :: List.map (fun f -> (f.cf_type,f.cf_doc)) f.cf_overloads)) | _ -> - error "Not a class" p) + error "Not a class" p)*) | ECheckType (e,t) -> - let t = Typeload.load_complex_type ctx p t in + let t = Typeload.load_complex_type ctx true p t in let e = type_expr ctx e (WithType t) in - let e = Codegen.AbstractCast.cast_or_unify ctx t e p in + let e = AbstractCast.cast_or_unify ctx t e p in if e.etype == t then e else mk (TCast (e,None)) t p | EMeta (m,e1) -> + if ctx.is_display_file then Display.DisplayEmitter.check_display_metadata ctx [m]; let old = ctx.meta in ctx.meta <- m :: ctx.meta; let e () = type_expr ctx e1 with_type in @@ -3533,10 +3603,13 @@ and type_expr ctx (e,p) (with_type:with_type) = | (Meta.ToString,_,_) -> let e = e() in (match follow e.etype with - | TAbstract({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> call_to_string ctx c e + | TAbstract({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> call_to_string ctx e | _ -> e) | (Meta.This,_,_) -> - let e = List.hd ctx.this_stack in + let e = match ctx.this_stack with + | [] -> error "Cannot type @:this this here" p + | e :: _ -> e + in let rec loop e = match e.eexpr with | TConst TThis -> get_this ctx e.epos | _ -> Type.map_expr loop e @@ -3547,132 +3620,236 @@ and type_expr ctx (e,p) (with_type:with_type) = {e with eexpr = TMeta(m,e)} | (Meta.MergeBlock,_,_) -> begin match fst e1 with - | EBlock el -> type_block ctx el with_type p + | EBlock el -> + let e = type_block ctx el with_type p in + {e with eexpr = TMeta(m,e)} | _ -> e() end | (Meta.StoredTypedExpr,_,_) -> let id = match e1 with (EConst (Int s),_) -> int_of_string s | _ -> assert false in - get_stored_typed_expr ctx.com id + MacroContext.get_stored_typed_expr ctx.com id | (Meta.NoPrivateAccess,_,_) -> ctx.meta <- List.filter (fun(m,_,_) -> m <> Meta.PrivateAccess) ctx.meta; e() + | (Meta.Fixed,_,_) when ctx.com.platform=Cpp -> + let e = e() in + {e with eexpr = TMeta(m,e)} | _ -> e() in ctx.meta <- old; e -and get_next_stored_typed_expr_id = - let uid = ref 0 in - (fun() -> incr uid; !uid) - -and get_stored_typed_expr com id = - let vars = Hashtbl.create 0 in - let copy_var v = - let v2 = alloc_var v.v_name v.v_type in - v2.v_meta <- v.v_meta; - Hashtbl.add vars v.v_id v2; - v2; - in - let rec build_expr e = - match e.eexpr with - | TVar (v,eo) -> - let v2 = copy_var v in - {e with eexpr = TVar(v2, Option.map build_expr eo)} - | TFor (v,e1,e2) -> - let v2 = copy_var v in - {e with eexpr = TFor(v2, build_expr e1, build_expr e2)} - | TTry (e1,cl) -> - let cl = List.map (fun (v,e) -> - let v2 = copy_var v in - v2, build_expr e - ) cl in - {e with eexpr = TTry(build_expr e1, cl)} - | TFunction f -> - let args = List.map (fun (v,c) -> copy_var v, c) f.tf_args in - let f = { - tf_args = args; - tf_type = f.tf_type; - tf_expr = build_expr f.tf_expr; - } in - {e with eexpr = TFunction f} - | TLocal v -> - (try - let v2 = Hashtbl.find vars v.v_id in - {e with eexpr = TLocal v2} - with _ -> - e) - | _ -> - map_expr build_expr e - in - let e = PMap.find id com.stored_typed_exprs in - build_expr e - +and get_submodule_fields ctx path = + let m = Hashtbl.find ctx.g.modules path in + let tl = List.filter (fun t -> path <> (t_infos t).mt_path && not (t_infos t).mt_private) m.m_types in + let tl = List.map (fun mt -> + let infos = t_infos mt in + (snd infos.mt_path),Display.FKType (type_of_module_type mt),infos.mt_doc + ) tl in + tl -and handle_display ctx e_ast iscall p = - let old = ctx.in_display in +and handle_display ctx e_ast with_type = + let old = ctx.in_display,ctx.in_call_args in ctx.in_display <- true; - let get_submodule_fields path = - let m = Hashtbl.find ctx.g.modules path in - let tl = List.filter (fun t -> path <> (t_infos t).mt_path && not (t_infos t).mt_private) m.m_types in - let tl = List.map (fun mt -> - let infos = t_infos mt in - (snd infos.mt_path),type_of_module_type mt,Some FKType,infos.mt_doc - ) tl in - tl - in - let e = try - type_expr ctx e_ast Value - with Error (Unknown_ident n,_) when not iscall -> + ctx.in_call_args <- false; + let e = match e_ast,with_type with + | (EConst (Ident "$type"),_),_ -> + let mono = mk_mono() in + raise (Display.DisplaySignatures ([(TFun(["expression",false,mono],mono),Some "Outputs type of argument as a warning and uses argument as value")],0)) + | (EConst (Ident "trace"),_),_ -> + raise (Display.DisplaySignatures ([(tfun [t_dynamic] ctx.com.basic.tvoid,Some "Print given arguments")],0)) + | (EConst (Ident "_"),p),WithType t -> + mk (TConst TNull) t p (* This is "probably" a bind skip, let's just use the expected type *) + | _ -> try + type_expr ctx e_ast with_type + with Error (Unknown_ident n,_) -> raise (Parser.TypePath ([n],None,false)) - | Error (Unknown_ident "trace",_) -> - raise (DisplayTypes [tfun [t_dynamic] ctx.com.basic.tvoid]) | Error (Type_not_found (path,_),_) as err -> begin try - raise (DisplayFields (get_submodule_fields path)) + raise (Display.DisplayFields (get_submodule_fields ctx path)) with Not_found -> raise err end in - ctx.in_display <- old; - let handle_field cf = - if ctx.com.display = DMPosition then - raise (DisplayPosition [cf.cf_pos]); - cf.cf_meta <- (Meta.Usage,[],p) :: cf.cf_meta; + let p = e.epos in + let e = match with_type with + | WithType t -> (try AbstractCast.cast_or_unify_raise ctx t e e.epos with Error (Unify l,p) -> e) + | _ -> e + in + ctx.in_display <- fst old; + ctx.in_call_args <- snd old; + display_expr ctx e_ast e with_type p + +and handle_signature_display ctx e_ast with_type = + ctx.in_display <- true; + let p = pos e_ast in + let find_constructor_types t = match follow t with + | TInst (c,tl) | TAbstract({a_impl = Some c},tl) -> + let ct,cf = get_constructor ctx c tl p in + let tl = (ct,cf.cf_doc) :: List.rev_map (fun cf' -> cf'.cf_type,cf.cf_doc) cf.cf_overloads in + tl + | _ -> + [] + in + let tl,el,p0 = match fst e_ast with + | ECall(e1,el) -> + let e1 = try + type_expr ctx e1 Value + with Error (Unknown_ident "trace",_) -> + let e = expr_of_type_path (["haxe";"Log"],"trace") p in + type_expr ctx e Value + in + let tl = match e1.eexpr with + | TField(_,fa) -> + begin match extract_field fa with + | Some cf -> (e1.etype,cf.cf_doc) :: List.rev_map (fun cf' -> cf'.cf_type,cf.cf_doc) cf.cf_overloads + | None -> [e1.etype,None] + end + | TConst TSuper -> + find_constructor_types e1.etype + | _ -> [e1.etype,None] + in + tl,el,e1.epos + | ENew(tpath,el) -> + let t = Typeload.load_instance ctx tpath true p in + find_constructor_types t,el,pos tpath + | _ -> error "Call expected" p + in + let rec follow_with_callable (t,doc) = match follow t with + | TAbstract(a,tl) when Meta.has Meta.Callable a.a_meta -> follow_with_callable (Abstract.get_underlying_type a tl,doc) + | t -> (t,doc) + in + let tl = List.map follow_with_callable tl in + let rec loop i p1 el = match el with + | (e,p2) :: el -> + if Display.is_display_position (punion p1 p2) then i else loop (i + 1) p2 el + | [] -> + i in - match ctx.com.display with - | DMResolve _ -> + let display_arg = loop 0 p0 el in + (* If our display position exceeds the argument number we add a null expression in order to make + unify_call_args error out. *) + let el = if display_arg >= List.length el then el @ [EConst (Ident "null"),null_pos] else el in + let rec loop acc tl = match tl with + | (t,doc) :: tl -> + let keep t = match t with + | TFun (args,r) -> + begin try + let _ = unify_call_args' ctx el args r p false false in + true + with + | Error(Call_error (Not_enough_arguments _),_) -> true + | _ -> false + end + | _ -> false + in + loop (if keep t then (t,doc) :: acc else acc) tl + | [] -> + acc + in + let overloads = match loop [] tl with [] -> tl | tl -> tl in + raise (Display.DisplaySignatures(overloads,display_arg)) + +and display_expr ctx e_ast e with_type p = + let get_super_constructor () = match ctx.curclass.cl_super with + | None -> error "Current class does not have a super" p + | Some (c,params) -> + let _, f = get_constructor ctx c params p in + f + in + match ctx.com.display.dms_kind with + | DMResolve _ | DMPackage | DMSignature -> assert false | DMType -> - raise (DisplayTypes [e.etype]) - | DMUsage | DMPosition -> - begin match e.eexpr with + let rec loop e = match e.eexpr with + | TVar(v,_) -> v.v_type,None + | TCall({eexpr = TConst TSuper; etype = t},_) -> t,None + | TNew({cl_kind = KAbstractImpl a},tl,_) -> TType(abstract_module_type a tl,[]),None + | TNew(c,tl,_) -> TInst(c,tl),None + | TTypeExpr (TClassDecl {cl_kind = KAbstractImpl a}) -> TType(abstract_module_type a (List.map snd a.a_params),[]),None + | TField(e1,FDynamic "bind") when (match follow e1.etype with TFun _ -> true | _ -> false) -> e1.etype,None + | TReturn (Some e1) -> loop e1 (* No point in letting the internal Dynamic surface (issue #5655) *) + | TField(_,(FStatic(c,cf) | FInstance(c,_,cf) | FClosure(Some(c,_),cf))) -> + if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc ctx c; + e.etype,cf.cf_doc + | TField(_,FEnum(_,ef)) -> + e.etype,ef.ef_doc + | _ -> e.etype,None + in + let t,doc = loop e in + raise (Display.DisplayType (t,p,doc)) + | DMUsage _ -> + let rec loop e = match e.eexpr with | TField(_,FEnum(_,ef)) -> - if ctx.com.display = DMPosition then - raise (DisplayPosition [ef.ef_pos]); ef.ef_meta <- (Meta.Usage,[],p) :: ef.ef_meta; | TField(_,(FAnon cf | FInstance (_,_,cf) | FStatic (_,cf) | FClosure (_,cf))) -> - handle_field cf; - | TLocal v -> + cf.cf_meta <- (Meta.Usage,[],p) :: cf.cf_meta; + | TLocal v | TVar(v,_) -> v.v_meta <- (Meta.Usage,[],p) :: v.v_meta; | TTypeExpr mt -> let ti = t_infos mt in - if ctx.com.display = DMPosition then - raise (DisplayPosition [ti.mt_pos]); ti.mt_meta <- (Meta.Usage,[],p) :: ti.mt_meta; | TNew(c,tl,_) -> begin try let _,cf = get_constructor ctx c tl p in - handle_field cf; + cf.cf_meta <- (Meta.Usage,[],p) :: cf.cf_meta; with Not_found -> () end + | TCall({eexpr = TConst TSuper},_) -> + begin try + let cf = get_super_constructor() in + cf.cf_meta <- (Meta.Usage,[],p) :: cf.cf_meta; + with Not_found -> + () + end + | TConst TSuper -> + begin match ctx.curclass.cl_super with + | None -> () + | Some (c,_) -> c.cl_meta <- (Meta.Usage,[],p) :: c.cl_meta; + end + | TCall(e1,_) -> + loop e1 | _ -> () - end; + in + loop e; e + | DMPosition -> + let rec loop e = match e.eexpr with + | TField(_,FEnum(_,ef)) -> [ef.ef_pos] + | TField(_,(FAnon cf | FInstance (_,_,cf) | FStatic (_,cf) | FClosure (_,cf))) -> [cf.cf_pos] + | TLocal v | TVar(v,_) -> [v.v_pos] + | TTypeExpr mt -> [(t_infos mt).mt_pos] + | TNew(c,tl,_) -> + begin try + let _,cf = get_constructor ctx c tl p in + [cf.cf_pos] + with Not_found -> + [] + end + | TCall({eexpr = TConst TSuper},_) -> + begin try + let cf = get_super_constructor() in + [cf.cf_pos] + with Not_found -> + [] + end + | TConst TSuper -> + begin match ctx.curclass.cl_super with + | None -> [] + | Some (c,_) -> [c.cl_pos] + end + | TCall(e1,_) -> + loop e1 + | _ -> + [] + in + let pl = loop e in + raise (Display.DisplayPosition pl); | DMToplevel -> - collect_toplevel_identifiers ctx; - | DMDefault | DMNone -> + raise (Display.DisplayToplevel (Display.ToplevelCollector.run ctx false)) + | DMField | DMNone | DMModuleSymbols _ | DMDiagnostics _ | DMStatistics -> let opt_args args ret = TFun(List.map(fun (n,o,t) -> n,true,t) args,ret) in let e = match e.eexpr with | TField (e1,fa) -> @@ -3694,23 +3871,17 @@ and handle_display ctx e_ast iscall p = | _ -> t in - let merge_core_doc c = - let c_core = Typeload.load_core_class ctx c in - if c.cl_doc = None then c.cl_doc <- c_core.cl_doc; - let maybe_merge cf_map cf = - if cf.cf_doc = None then try cf.cf_doc <- (PMap.find cf.cf_name cf_map).cf_doc with Not_found -> () - in - List.iter (maybe_merge c_core.cl_fields) c.cl_ordered_fields; - List.iter (maybe_merge c_core.cl_statics) c.cl_ordered_statics; - match c.cl_constructor,c_core.cl_constructor with - | Some ({cf_doc = None} as cf),Some cf2 -> cf.cf_doc <- cf2.cf_doc - | _ -> () + let should_access c cf stat = + if c != ctx.curclass && not cf.cf_public && String.length cf.cf_name > 4 then begin match String.sub cf.cf_name 0 4 with + | "get_" | "set_" -> false + | _ -> can_access ctx c cf stat + end else + can_access ctx c cf stat in let rec get_fields t = match follow t with | TInst (c,params) -> - if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc c; - let priv = is_parent c ctx.curclass in + if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc ctx c; let merge ?(cond=(fun _ -> true)) a b = PMap.foldi (fun k f m -> if cond f then PMap.add k f m else m) a b in @@ -3722,7 +3893,7 @@ and handle_display ctx e_ast iscall p = | None -> m | Some (csup,cparams) -> merge m (loop csup cparams) ) in - let m = merge ~cond:(fun f -> priv || can_access ctx c f false) c.cl_fields m in + let m = merge ~cond:(fun f -> should_access c f false) c.cl_fields m in let m = (match c.cl_kind with | KTypeParameter pl -> List.fold_left (fun acc t -> merge acc (get_fields t)) m pl | _ -> m @@ -3731,8 +3902,7 @@ and handle_display ctx e_ast iscall p = in loop c params | TAbstract({a_impl = Some c} as a,pl) -> - if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc c; - ctx.m.module_using <- c :: ctx.m.module_using; + if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc ctx c; let fields = try let _,el,_ = Meta.get Meta.Forward a.a_meta in let sl = ExtList.List.filter_map (fun e -> match fst e with @@ -3750,28 +3920,33 @@ and handle_display ctx e_ast iscall p = PMap.empty in PMap.fold (fun f acc -> - if f.cf_name <> "_new" && can_access ctx c f true && Meta.has Meta.Impl f.cf_meta && not (Meta.has Meta.Enum f.cf_meta) then begin + if f.cf_name <> "_new" && should_access c f true && Meta.has Meta.Impl f.cf_meta && not (Meta.has Meta.Enum f.cf_meta) then begin let f = prepare_using_field f in let t = apply_params a.a_params pl (follow f.cf_type) in PMap.add f.cf_name { f with cf_public = true; cf_type = opt_type t } acc end else acc ) c.cl_statics fields + | TAnon a when PMap.is_empty a.a_fields -> + begin match with_type with + | WithType t -> get_fields t + | _ -> a.a_fields + end | TAnon a -> (match !(a.a_status) with | Statics c -> - if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc c; + if Meta.has Meta.CoreApi c.cl_meta then merge_core_doc ctx c; let is_abstract_impl = match c.cl_kind with KAbstractImpl _ -> true | _ -> false in let pm = match c.cl_constructor with None -> PMap.empty | Some cf -> PMap.add "new" cf PMap.empty in PMap.fold (fun f acc -> - if can_access ctx c f true && (not is_abstract_impl || not (Meta.has Meta.Impl f.cf_meta) || Meta.has Meta.Enum f.cf_meta) then + if should_access c f true && (not is_abstract_impl || not (Meta.has Meta.Impl f.cf_meta) || Meta.has Meta.Enum f.cf_meta) then PMap.add f.cf_name { f with cf_public = true; cf_type = opt_type f.cf_type } acc else acc ) a.a_fields pm | _ -> a.a_fields) | TFun (args,ret) -> let t = opt_args args ret in - let cf = mk_field "bind" (tfun [t] t) p in + let cf = mk_field "bind" (tfun [t] t) p null_pos in PMap.add "bind" cf PMap.empty | _ -> PMap.empty @@ -3782,7 +3957,7 @@ and handle_display ctx e_ast iscall p = *) let rec loop acc = function | [] -> acc - | c :: l -> + | (c,_) :: l -> let acc = ref (loop acc l) in let rec dup t = Type.map dup t in List.iter (fun f -> @@ -3814,65 +3989,106 @@ and handle_display ctx e_ast iscall p = in let use_methods = match follow e.etype with TMono _ -> PMap.empty | _ -> loop (loop PMap.empty ctx.g.global_using) ctx.m.module_using in let fields = PMap.fold (fun f acc -> PMap.add f.cf_name f acc) fields use_methods in - let fields = PMap.fold (fun f acc -> if Meta.has Meta.NoCompletion f.cf_meta then acc else f :: acc) fields [] in - let t = if iscall then - let rec loop t = match follow t with - | TFun _ -> t - | TAbstract(a,tl) when Meta.has Meta.Callable a.a_meta -> loop (Abstract.get_underlying_type a tl) - | _ -> t_dynamic - in - loop e.etype - else - let get_field acc f = - List.fold_left (fun acc f -> - let kind = match f.cf_kind with Method _ -> FKMethod | Var _ -> FKVar in - if f.cf_public then (f.cf_name,f.cf_type,Some kind,f.cf_doc) :: acc else acc - ) acc (f :: f.cf_overloads) - in - let fields = List.fold_left get_field [] fields in - let fields = try - let sl = string_list_of_expr_path_raise e_ast in - fields @ get_submodule_fields (List.tl sl,List.hd sl) - with Exit | Not_found -> + let fields = match fst e_ast with + | EConst(String s) when String.length s = 1 -> + let cf = mk_field "code" ctx.t.tint e.epos null_pos in + cf.cf_doc <- Some "The character code of this character (inlined at compile-time)."; + cf.cf_kind <- Var { v_read = AccNormal; v_write = AccNever }; + PMap.add cf.cf_name cf fields + | _ -> fields - in - if fields = [] then - e.etype - else - raise (DisplayFields fields) in - (match follow t with - | TMono _ | TDynamic _ when ctx.in_macro -> mk (TConst TNull) t p - | _ -> raise (DisplayTypes [t])) + let fields = PMap.fold (fun f acc -> if Meta.has Meta.NoCompletion f.cf_meta then acc else f :: acc) fields [] in + let get_field acc f = + List.fold_left (fun acc f -> + let kind = match f.cf_kind with Method _ -> Display.FKMethod f.cf_type | Var _ -> Display.FKVar f.cf_type in + if f.cf_public then (f.cf_name,kind,f.cf_doc) :: acc else acc + ) acc (f :: f.cf_overloads) + in + let fields = List.fold_left get_field [] fields in + let fields = try + let sl = string_list_of_expr_path_raise e_ast in + fields @ get_submodule_fields ctx (List.tl sl,List.hd sl) + with Exit | Not_found -> + fields + in + raise (Display.DisplayFields fields) +and maybe_type_against_enum ctx f with_type p = + try + begin match with_type with + | WithType t -> + let rec loop stack t = match follow t with + | TEnum (en,_) -> + en.e_path,en.e_names,TEnumDecl en + | TAbstract ({a_impl = Some c} as a,_) when has_meta Meta.Enum a.a_meta -> + let fields = ExtList.List.filter_map (fun cf -> + if Meta.has Meta.Enum cf.cf_meta then Some cf.cf_name else None + ) c.cl_ordered_statics in + a.a_path,fields,TAbstractDecl a + | TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) -> + begin match get_abstract_froms a pl with + | [t2] -> + if (List.exists (fast_eq t) stack) then raise Exit; + loop (t :: stack) t2 + | _ -> raise Exit + end + (* We might type against an enum constructor. *) + | TFun(_,tr) -> + loop stack tr + | _ -> + raise Exit + in + let path,fields,mt = loop [] t in + let old = ctx.m.curmod.m_types in + let restore () = ctx.m.curmod.m_types <- old in + ctx.m.curmod.m_types <- ctx.m.curmod.m_types @ [mt]; + let e = try + f() + with + | Error (Unknown_ident n,_) -> + restore(); + raise_or_display_message ctx (StringError.string_error n fields ("Identifier '" ^ n ^ "' is not part of " ^ s_type_path path)) p; + AKExpr (mk (TConst TNull) (mk_mono()) p) + | exc -> + restore(); + raise exc; + in + restore(); + e + | _ -> + raise Exit + end + with Exit -> + f() and type_call ctx e el (with_type:with_type) p = - let def () = (match e with - | EField ((EConst (Ident "super"),_),_) , _ -> ctx.in_super_call <- true - | _ -> ()); - build_call ctx (type_access ctx (fst e) (snd e) MCall) el with_type p + let def () = + let e = maybe_type_against_enum ctx (fun () -> type_access ctx (fst e) (snd e) MCall) with_type p in + let e = build_call ctx e el with_type p in + e in match e, el with | (EConst (Ident "trace"),p) , e :: el -> if Common.defined ctx.com Define.NoTraces then null ctx.t.tvoid p else - let params = (match el with [] -> [] | _ -> ["customParams",(EArrayDecl el , p)]) in + let mk_to_string_meta e = EMeta((Meta.ToString,[],null_pos),e),pos e in + let params = (match el with [] -> [] | _ -> [("customParams",null_pos),(EArrayDecl (List.map mk_to_string_meta el) , p)]) in let infos = mk_infos ctx p params in if (platform ctx.com Js || platform ctx.com Python) && el = [] && has_dce ctx.com then let e = type_expr ctx e Value in let infos = type_expr ctx infos Value in let e = match follow e.etype with | TAbstract({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> - call_to_string ctx c e + call_to_string ctx e | _ -> e in - let v_trace = alloc_unbound_var "`trace" t_dynamic in + let v_trace = alloc_unbound_var "`trace" t_dynamic p in mk (TCall (mk (TLocal v_trace) t_dynamic p,[e;infos])) ctx.t.tvoid p else - let me = Meta.ToString,[],pos e in - type_expr ctx (ECall ((EField ((EField ((EConst (Ident "haxe"),p),"Log"),p),"trace"),p),[(EMeta (me,e),pos e);infos]),p) NoValue + type_expr ctx (ECall ((EField ((EField ((EConst (Ident "haxe"),p),"Log"),p),"trace"),p),[mk_to_string_meta e;infos]),p) NoValue | (EConst(Ident "callback"),p1),args -> let ecb = try Some (type_ident_raise ctx "callback" p1 MCall) with Not_found -> None in (match ecb with @@ -3892,31 +4108,35 @@ and type_call ctx e el (with_type:with_type) p = | (EConst (Ident "$type"),_) , [e] -> let e = type_expr ctx e Value in ctx.com.warning (s_type (print_context()) e.etype) e.epos; + let e = Display.Diagnostics.secure_generated_code ctx e in e | (EField(e,"match"),p), [epat] -> let et = type_expr ctx e Value in (match follow et.etype with - | TEnum _ as t -> - let e = match_expr ctx e [[epat],None,Some (EConst(Ident "true"),p)] (Some (Some (EConst(Ident "false"),p))) (WithType ctx.t.tbool) p in - let locals = !get_pattern_locals_ref ctx epat t in - PMap.iter (fun _ (_,p) -> display_error ctx "Capture variables are not allowed" p) locals; - Codegen.PatternMatchConversion.to_typed_ast ctx e p + | TEnum _ -> + let e = match_expr ctx e [[epat],None,Some (EConst(Ident "true"),p),p] (Some (Some (EConst(Ident "false"),p),p)) (WithType ctx.t.tbool) p in + (* TODO: add that back *) +(* let locals = !get_pattern_locals_ref ctx epat t in + PMap.iter (fun _ (_,p) -> display_error ctx "Capture variables are not allowed" p) locals; *) + e | _ -> def ()) | (EConst (Ident "__unprotect__"),_) , [(EConst (String _),_) as e] -> let e = type_expr ctx e Value in if Common.platform ctx.com Flash then let t = tfun [e.etype] e.etype in - let v_unprotect = alloc_unbound_var "__unprotect__" t in + let v_unprotect = alloc_unbound_var "__unprotect__" t p in mk (TCall (mk (TLocal v_unprotect) t p,[e])) e.etype e.epos else e + | (EDisplay((EConst (Ident "super"),_ as e1),false),_),_ -> + handle_display ctx (ECall(e1,el),p) with_type | (EConst (Ident "super"),sp) , el -> if ctx.curfun <> FunConstructor then error "Cannot call super constructor outside class constructor" p; let el, t = (match ctx.curclass.cl_super with | None -> error "Current class does not have a super" p | Some (c,params) -> let ct, f = get_constructor ctx c params p in - if (Meta.has Meta.CompilerGenerated f.cf_meta) then display_error ctx (s_type_path c.cl_path ^ " does not have a constructor") p; + if (Meta.has Meta.CompilerGenerated f.cf_meta) then display_error ctx (error_msg (No_constructor (TClassDecl c))) p; let el = (match follow ct with | TFun (args,r) -> let el,_,_ = unify_field_call ctx (FInstance(c,params,f)) el args r p false in @@ -3931,17 +4151,8 @@ and type_call ctx e el (with_type:with_type) p = def () and build_call ctx acc el (with_type:with_type) p = - let push_this e = - match e.eexpr with - | TConst (TInt _ | TFloat _ | TString _ | TBool _) -> - (Interp.make_ast e),fun () -> () - | _ -> - ctx.this_stack <- e :: ctx.this_stack; - let er = EMeta((Meta.This,[],e.epos), (EConst(Ident "this"),e.epos)),e.epos in - er,fun () -> ctx.this_stack <- List.tl ctx.this_stack - in match acc with - | AKInline (ethis,f,fmode,t) when Meta.has Meta.Generic f.cf_meta -> + | AKInline (ethis,f,fmode,t) when Meta.has Meta.Generic f.cf_meta -> type_generic_function ctx (ethis,fmode) el with_type p | AKInline (ethis,f,fmode,t) -> (match follow t with @@ -3960,7 +4171,7 @@ and build_call ctx acc el (with_type:with_type) p = begin match ef.cf_kind with | Method MethMacro -> let ethis = type_module_type ctx (TClassDecl cl) None p in - let eparam,f = push_this eparam in + let eparam,f = push_this ctx eparam in let e = build_call ctx (AKMacro (ethis,ef)) (eparam :: el) with_type p in f(); e @@ -3993,7 +4204,6 @@ and build_call ctx acc el (with_type:with_type) p = (match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name el p with | None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) Value) | Some (EMeta((Meta.MergeBlock,_,_),(EBlock el,_)),_) -> (fun () -> let e = type_block ctx el with_type p in mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos) - | Some (EVars vl,p) -> (fun() -> type_vars ctx vl p true) | Some e -> (fun() -> type_expr ctx e with_type)) | _ -> (* member-macro call : since we will make a static call, let's found the actual class and not its subclass *) @@ -4001,7 +4211,7 @@ and build_call ctx acc el (with_type:with_type) p = | TInst (c,_) -> let rec loop c = if PMap.mem cf.cf_name c.cl_fields then - let eparam,f = push_this ethis in + let eparam,f = push_this ctx ethis in ethis_f := f; let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name (eparam :: el) p with | None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) Value) @@ -4036,6 +4246,7 @@ and build_call ctx acc el (with_type:with_type) p = !ethis_f(); raise (Fatal_error ((error_msg m),p)) in + let e = Display.Diagnostics.secure_generated_code ctx e in ctx.on_error <- old; !ethis_f(); e @@ -4082,7 +4293,7 @@ and build_call ctx acc el (with_type:with_type) p = (* ---------------------------------------------------------------------- *) (* FINALIZATION *) -let get_main ctx = +let get_main ctx types = match ctx.com.main_class with | None -> None | Some cl -> @@ -4101,10 +4312,38 @@ let get_main ctx = Not_found -> error ("Invalid -main : " ^ s_type_path cl ^ " does not have static function main") c.cl_pos ) in let emain = type_type ctx cl null_pos in - Some (mk (TCall (mk (TField (emain,fmode)) ft null_pos,[])) r null_pos) + let main = mk (TCall (mk (TField (emain,fmode)) ft null_pos,[])) r null_pos in + (* add haxe.EntryPoint.run() call *) + let main = (try + let et = List.find (fun t -> t_path t = (["haxe"],"EntryPoint")) types in + let ec = (match et with TClassDecl c -> c | _ -> assert false) in + let ef = PMap.find "run" ec.cl_statics in + let p = null_pos in + let et = mk (TTypeExpr et) (TAnon { a_fields = PMap.empty; a_status = ref (Statics ec) }) p in + let call = mk (TCall (mk (TField (et,FStatic (ec,ef))) ef.cf_type p,[])) ctx.t.tvoid p in + mk (TBlock [main;call]) ctx.t.tvoid p + with Not_found -> + main + ) in + Some main let finalize ctx = - flush_pass ctx PFinal "final" + flush_pass ctx PFinal "final"; + match ctx.com.callbacks.after_typing with + | [] -> + () + | fl -> + let rec loop handled_types = + let all_types = Hashtbl.fold (fun _ m acc -> m.m_types @ acc) ctx.g.modules [] in + match (List.filter (fun mt -> not (List.memq mt handled_types)) all_types) with + | [] -> + () + | new_types -> + List.iter (fun f -> f new_types) fl; + flush_pass ctx PFinal "final"; + loop all_types + in + loop [] type state = | Generating @@ -4204,697 +4443,7 @@ let generate ctx = in let sorted_modules = List.sort (fun m1 m2 -> compare m1.m_path m2.m_path) (Hashtbl.fold (fun _ m acc -> m :: acc) ctx.g.modules []) in List.iter (fun m -> List.iter loop m.m_types) sorted_modules; - get_main ctx, List.rev !types, sorted_modules - -(* ---------------------------------------------------------------------- *) -(* MACROS *) - -let macro_enable_cache = ref false -let macro_interp_cache = ref None -let delayed_macro_result = ref ((fun() -> assert false) : unit -> unit -> Interp.value) - -let get_type_patch ctx t sub = - let new_patch() = - { tp_type = None; tp_remove = false; tp_meta = [] } - in - let path = Ast.parse_path t in - let h, tp = (try - Hashtbl.find ctx.g.type_patches path - with Not_found -> - let h = Hashtbl.create 0 in - let tp = new_patch() in - Hashtbl.add ctx.g.type_patches path (h,tp); - h, tp - ) in - match sub with - | None -> tp - | Some k -> - try - Hashtbl.find h k - with Not_found -> - let tp = new_patch() in - Hashtbl.add h k tp; - tp - -let macro_timer ctx path = - Common.timer (if Common.defined ctx.com Define.MacroTimes then "macro " ^ path else "macro execution") - -let typing_timer ctx f = - let t = Common.timer "typing" in - let old = ctx.com.error and oldp = ctx.pass in - (* - disable resumable errors... unless we are in display mode (we want to reach point of completion) - *) - if ctx.com.display = DMNone then ctx.com.error <- (fun e p -> raise (Error(Custom e,p))); - if ctx.pass < PTypeField then ctx.pass <- PTypeField; - let exit() = - t(); - ctx.com.error <- old; - ctx.pass <- oldp; - in - try - let r = f() in - exit(); - r - with Error (ekind,p) -> - exit(); - Interp.compiler_error (Typecore.error_msg ekind) p - | WithTypeError (l,p) -> - exit(); - Interp.compiler_error (Typecore.error_msg (Unify l)) p - | e -> - exit(); - raise e - -let make_macro_api ctx p = - let parse_expr_string s p inl = - typing_timer ctx (fun() -> parse_expr_string ctx s p inl) - in - { - Interp.pos = p; - Interp.get_com = (fun() -> ctx.com); - Interp.get_type = (fun s -> - typing_timer ctx (fun() -> - let path = parse_path s in - let tp = match List.rev (fst path) with - | s :: sl when String.length s > 0 && (match s.[0] with 'A'..'Z' -> true | _ -> false) -> - { tpackage = List.rev sl; tname = s; tparams = []; tsub = Some (snd path) } - | _ -> - { tpackage = fst path; tname = snd path; tparams = []; tsub = None } - in - try - let m = Some (Typeload.load_instance ctx tp p true) in - m - with Error (Module_not_found _,p2) when p == p2 -> - None - ) - ); - Interp.get_module = (fun s -> - typing_timer ctx (fun() -> - let path = parse_path s in - let m = List.map type_of_module_type (Typeload.load_module ctx path p).m_types in - m - ) - ); - Interp.on_generate = (fun f -> - Common.add_filter ctx.com (fun() -> - let t = macro_timer ctx "onGenerate" in - f (List.map type_of_module_type ctx.com.types); - t() - ) - ); - Interp.after_generate = (fun f -> - Common.add_final_filter ctx.com (fun() -> - let t = macro_timer ctx "afterGenerate" in - f(); - t() - ) - ); - Interp.on_type_not_found = (fun f -> - ctx.com.load_extern_type <- ctx.com.load_extern_type @ [fun path p -> - match f (s_type_path path) with - | Interp.VNull -> None - | td -> - let (pack,name),tdef,p = Interp.decode_type_def td in - Some (name,(pack,[tdef,p])) - ]; - ); - Interp.parse_string = parse_expr_string; - Interp.type_expr = (fun e -> - typing_timer ctx (fun() -> (type_expr ctx e Value)) - ); - Interp.store_typed_expr = (fun te -> - let p = te.epos in - let id = get_next_stored_typed_expr_id() in - ctx.com.stored_typed_exprs <- PMap.add id te ctx.com.stored_typed_exprs; - let eid = (EConst (Int (string_of_int id))), p in - (EMeta ((Meta.StoredTypedExpr,[],p), eid)), p - ); - Interp.get_display = (fun s -> - let is_displaying = ctx.com.display <> DMNone in - let old_resume = !Parser.resume_display in - let old_error = ctx.on_error in - let restore () = - if not is_displaying then begin - ctx.com.defines <- PMap.remove (fst (Define.infos Define.Display)) ctx.com.defines; - ctx.com.display <- DMNone - end; - Parser.resume_display := old_resume; - ctx.on_error <- old_error; - in - (* temporarily enter display mode with a fake position *) - if not is_displaying then begin - Common.define ctx.com Define.Display; - ctx.com.display <- DMDefault; - end; - Parser.resume_display := { - Ast.pfile = "macro"; - Ast.pmin = 0; - Ast.pmax = 0; - }; - ctx.on_error <- (fun ctx msg p -> raise (Error(Custom msg,p))); - let str = try - let e = parse_expr_string s Ast.null_pos true in - let e = Optimizer.optimize_completion_expr e in - ignore (type_expr ctx e Value); - "NO COMPLETION" - with DisplayFields fields -> - let pctx = print_context() in - String.concat "," (List.map (fun (f,t,_,_) -> f ^ ":" ^ s_type pctx t) fields) - | DisplayTypes tl -> - let pctx = print_context() in - String.concat "," (List.map (s_type pctx) tl) - | Parser.TypePath (p,sub,_) -> - (match sub with - | None -> - "path(" ^ String.concat "." p ^ ")" - | Some (c,_) -> - "path(" ^ String.concat "." p ^ ":" ^ c ^ ")") - | Typecore.Error (msg,p) -> - "error(" ^ error_msg msg ^ ")" - in - restore(); - str - ); - Interp.allow_package = (fun v -> Common.allow_package ctx.com v); - Interp.type_patch = (fun t f s v -> - typing_timer ctx (fun() -> - let v = (match v with None -> None | Some s -> - match parse_string ctx.com ("typedef T = " ^ s) null_pos false with - | _,[ETypedef { d_data = ct },_] -> Some ct - | _ -> assert false - ) in - let tp = get_type_patch ctx t (Some (f,s)) in - match v with - | None -> tp.tp_remove <- true - | Some _ -> tp.tp_type <- v - ); - ); - Interp.meta_patch = (fun m t f s -> - let m = (match parse_string ctx.com (m ^ " typedef T = T") null_pos false with - | _,[ETypedef t,_] -> t.d_meta - | _ -> assert false - ) in - let tp = get_type_patch ctx t (match f with None -> None | Some f -> Some (f,s)) in - tp.tp_meta <- tp.tp_meta @ m; - ); - Interp.set_js_generator = (fun gen -> - let js_ctx = Genjs.alloc_ctx ctx.com in - ctx.com.js_gen <- Some (fun() -> - let jsctx = Interp.enc_obj [ - "outputFile", Interp.enc_string ctx.com.file; - "types", Interp.enc_array (List.map (fun t -> Interp.encode_type (type_of_module_type t)) ctx.com.types); - "main", (match ctx.com.main with None -> Interp.VNull | Some e -> Interp.encode_texpr e); - "generateValue", Interp.VFunction (Interp.Fun1 (fun v -> - let e = Interp.decode_texpr v in - let str = Genjs.gen_single_expr js_ctx e false in - Interp.enc_string str - )); - "isKeyword", Interp.VFunction (Interp.Fun1 (fun v -> - Interp.VBool (Hashtbl.mem Genjs.kwds (Interp.dec_string v)) - )); - "hasFeature", Interp.VFunction (Interp.Fun1 (fun v -> - Interp.VBool (Common.has_feature ctx.com (Interp.dec_string v)) - )); - "addFeature", Interp.VFunction (Interp.Fun1 (fun v -> - Common.add_feature ctx.com (Interp.dec_string v); - Interp.VNull - )); - "quoteString", Interp.VFunction (Interp.Fun1 (fun v -> - Interp.enc_string ("\"" ^ Ast.s_escape (Interp.dec_string v) ^ "\"") - )); - "buildMetaData", Interp.VFunction (Interp.Fun1 (fun t -> - match Codegen.build_metadata ctx.com (Interp.decode_tdecl t) with - | None -> Interp.VNull - | Some e -> Interp.encode_texpr e - )); - "generateStatement", Interp.VFunction (Interp.Fun1 (fun v -> - let e = Interp.decode_texpr v in - let str = Genjs.gen_single_expr js_ctx e true in - Interp.enc_string str - )); - "setTypeAccessor", Interp.VFunction (Interp.Fun1 (fun callb -> - js_ctx.Genjs.type_accessor <- (fun t -> - let v = Interp.encode_type (type_of_module_type t) in - let ret = Interp.call (Interp.get_ctx()) Interp.VNull callb [v] Nast.null_pos in - Interp.dec_string ret - ); - Interp.VNull - )); - "setCurrentClass", Interp.VFunction (Interp.Fun1 (fun c -> - Genjs.set_current_class js_ctx (match Interp.decode_tdecl c with TClassDecl c -> c | _ -> assert false); - Interp.VNull - )); - ] in - let t = macro_timer ctx "jsGenerator" in - gen jsctx; - t() - ); - ); - Interp.get_local_type = (fun() -> - match ctx.g.get_build_infos() with - | Some (mt,tl,_) -> - Some (match mt with - | TClassDecl c -> TInst (c,tl) - | TEnumDecl e -> TEnum (e,tl) - | TTypeDecl t -> TType (t,tl) - | TAbstractDecl a -> TAbstract(a,tl)) - | None -> - if ctx.curclass == null_class then - None - else - Some (TInst (ctx.curclass,[])) - ); - Interp.get_expected_type = (fun() -> - match ctx.with_type_stack with - | (WithType t | WithTypeResume t) :: _ -> Some t - | _ -> None - ); - Interp.get_call_arguments = (fun() -> - match ctx.call_argument_stack with - | [] -> None - | el :: _ -> Some el - ); - Interp.get_local_method = (fun() -> - ctx.curfield.cf_name; - ); - Interp.get_local_using = (fun() -> - ctx.m.module_using; - ); - Interp.get_local_vars = (fun () -> - ctx.locals; - ); - Interp.get_build_fields = (fun() -> - match ctx.g.get_build_infos() with - | None -> Interp.VNull - | Some (_,_,fields) -> Interp.enc_array (List.map Interp.encode_field fields) - ); - Interp.get_pattern_locals = (fun e t -> - !get_pattern_locals_ref ctx e t - ); - Interp.define_type = (fun v -> - let m, tdef, pos = (try Interp.decode_type_def v with Interp.Invalid_expr -> Interp.exc (Interp.VString "Invalid type definition")) in - let add ctx = - let prev = (try Some (Hashtbl.find ctx.g.modules m) with Not_found -> None) in - let mnew = Typeload.type_module ctx m ctx.m.curmod.m_extra.m_file [tdef,pos] pos in - add_dependency mnew ctx.m.curmod; - (* if we defined a type in an existing module, let's move the types here *) - (match prev with - | None -> - mnew.m_extra.m_kind <- MFake; - | Some mold -> - Hashtbl.replace ctx.g.modules mnew.m_path mold; - mold.m_types <- mold.m_types @ mnew.m_types; - mnew.m_extra.m_kind <- MSub; - add_dependency mold mnew; - ); - in - add ctx; - (* if we are adding a class which has a macro field, we also have to add it to the macro context (issue #1497) *) - if not ctx.in_macro then match tdef,ctx.g.macros with - | EClass c,Some (_,mctx) when List.exists (fun cff -> (Meta.has Meta.Macro cff.cff_meta || List.mem AMacro cff.cff_access)) c.d_data -> - add mctx - | _ -> - () - ); - Interp.define_module = (fun m types imports usings -> - let types = List.map (fun v -> - let _, tdef, pos = (try Interp.decode_type_def v with Interp.Invalid_expr -> Interp.exc (Interp.VString "Invalid type definition")) in - tdef, pos - ) types in - let pos = (match types with [] -> Ast.null_pos | (_,p) :: _ -> p) in - let imports = List.map (fun (il,ik) -> EImport(il,ik),pos) imports in - let usings = List.map (fun tp -> EUsing tp,pos) usings in - let types = imports @ usings @ types in - let m = Ast.parse_path m in - let prev = (try Some (Hashtbl.find ctx.g.modules m) with Not_found -> None) in - let mnew = Typeload.type_module ctx m ctx.m.curmod.m_extra.m_file types pos in - add_dependency mnew ctx.m.curmod; - (* if we defined a type in an existing module, let's move the types here *) - (match prev with - | None -> - mnew.m_extra.m_kind <- MFake; - | Some mold -> - Hashtbl.replace ctx.g.modules mnew.m_path mold; - mold.m_types <- mold.m_types @ mnew.m_types; - mnew.m_extra.m_kind <- MSub; - add_dependency mold mnew; - ); - ); - Interp.module_dependency = (fun mpath file ismacro -> - let m = typing_timer ctx (fun() -> Typeload.load_module ctx (parse_path mpath) p) in - if ismacro then - m.m_extra.m_macro_calls <- file :: List.filter ((<>) file) m.m_extra.m_macro_calls - else - add_dependency m (create_fake_module ctx file); - ); - Interp.current_module = (fun() -> - ctx.m.curmod - ); - Interp.delayed_macro = (fun i -> - let mctx = (match ctx.g.macros with None -> assert false | Some (_,mctx) -> mctx) in - let f = (try DynArray.get mctx.g.delayed_macros i with _ -> failwith "Delayed macro retrieve failure") in - f(); - let ret = !delayed_macro_result in - delayed_macro_result := (fun() -> assert false); - ret - ); - Interp.use_cache = (fun() -> - !macro_enable_cache - ); - Interp.format_string = (fun s p -> - format_string ctx s p - ); - Interp.cast_or_unify = (fun t e p -> - Codegen.AbstractCast.cast_or_unify_raise ctx t e p - ); - Interp.add_global_metadata = (fun s1 s2 config -> - let meta = (match parse_string ctx.com (s2 ^ " typedef T = T") null_pos false with - | _,[ETypedef t,_] -> t.d_meta - | _ -> assert false - ) in - List.iter (fun m -> - ctx.g.global_metadata <- (ExtString.String.nsplit s1 ".",m,config) :: ctx.g.global_metadata; - ) meta; - ); - } - -let rec init_macro_interp ctx mctx mint = - let p = Ast.null_pos in - ignore(Typeload.load_module mctx (["haxe";"macro"],"Expr") p); - ignore(Typeload.load_module mctx (["haxe";"macro"],"Type") p); - flush_macro_context mint ctx; - Interp.init mint; - if !macro_enable_cache && not (Common.defined mctx.com Define.NoMacroCache) then macro_interp_cache := Some mint - -and flush_macro_context mint ctx = - let mctx = (match ctx.g.macros with None -> assert false | Some (_,mctx) -> mctx) in - finalize mctx; - let _, types, modules = generate mctx in - mctx.com.types <- types; - mctx.com.Common.modules <- modules; - (* if one of the type we are using has been modified, we need to create a new macro context from scratch *) - let mint = if not (Interp.can_reuse mint types) then begin - let com2 = mctx.com in - let mint = Interp.create com2 (make_macro_api ctx Ast.null_pos) in - let macro = ((fun() -> Interp.select mint), mctx) in - ctx.g.macros <- Some macro; - mctx.g.macros <- Some macro; - init_macro_interp ctx mctx mint; - mint - end else mint in - (* we should maybe ensure that all filters in Main are applied. Not urgent atm *) - let expr_filters = [Codegen.AbstractCast.handle_abstract_casts mctx; Filters.captured_vars mctx.com; Filters.rename_local_vars mctx] in - let type_filters = [Filters.add_field_inits mctx] in - let ready = fun t -> - Filters.apply_filters_once mctx expr_filters t; - List.iter (fun f -> f t) type_filters - in - (try Interp.add_types mint types ready - with Error (e,p) -> raise (Fatal_error(error_msg e,p))); - Filters.next_compilation() - -let create_macro_interp ctx mctx = - let com2 = mctx.com in - let mint, init = (match !macro_interp_cache with - | None -> - let mint = Interp.create com2 (make_macro_api ctx Ast.null_pos) in - mint, (fun() -> init_macro_interp ctx mctx mint) - | Some mint -> - Interp.do_reuse mint (make_macro_api ctx Ast.null_pos); - mint, (fun() -> ()) - ) in - let on_error = com2.error in - com2.error <- (fun e p -> - Interp.set_error (Interp.get_ctx()) true; - macro_interp_cache := None; - on_error e p - ); - let macro = ((fun() -> Interp.select mint), mctx) in - ctx.g.macros <- Some macro; - mctx.g.macros <- Some macro; - (* mctx.g.core_api <- ctx.g.core_api; // causes some issues because of optional args and Null type in Flash9 *) - init() - -let get_macro_context ctx p = - let api = make_macro_api ctx p in - match ctx.g.macros with - | Some (select,ctx) -> - select(); - api, ctx - | None -> - let com2 = Common.clone ctx.com in - ctx.com.get_macros <- (fun() -> Some com2); - com2.package_rules <- PMap.empty; - com2.main_class <- None; - com2.display <- DMNone; - List.iter (fun p -> com2.defines <- PMap.remove (platform_name p) com2.defines) platforms; - com2.defines_signature <- None; - com2.class_path <- List.filter (fun s -> not (ExtString.String.exists s "/_std/")) com2.class_path; - com2.class_path <- List.map (fun p -> p ^ "neko" ^ "/_std/") com2.std_path @ com2.class_path; - let to_remove = List.map (fun d -> fst (Define.infos d)) [Define.NoTraces] in - let to_remove = to_remove @ List.map (fun (_,d) -> "flash" ^ d) Common.flash_versions in - com2.defines <- PMap.foldi (fun k v acc -> if List.mem k to_remove then acc else PMap.add k v acc) com2.defines PMap.empty; - Common.define com2 Define.Macro; - Common.init_platform com2 Neko; - let mctx = ctx.g.do_create com2 in - create_macro_interp ctx mctx; - api, mctx - -let load_macro ctx cpath f p = - (* - The time measured here takes into account both macro typing an init, but benchmarks - shows that - unless you re doing heavy statics vars init - the time is mostly spent in - typing the classes needed for macro execution. - *) - let t = macro_timer ctx "typing (+init)" in - let api, mctx = get_macro_context ctx p in - let mint = Interp.get_ctx() in - let cpath, sub = (match List.rev (fst cpath) with - | name :: pack when name.[0] >= 'A' && name.[0] <= 'Z' -> (List.rev pack,name), Some (snd cpath) - | _ -> cpath, None - ) in - let m = (try Hashtbl.find ctx.g.types_module cpath with Not_found -> cpath) in - let mloaded = Typeload.load_module mctx m p in - mctx.m <- { - curmod = mloaded; - module_types = []; - module_using = []; - module_globals = PMap.empty; - wildcard_packages = []; - }; - add_dependency ctx.m.curmod mloaded; - let mt = Typeload.load_type_def mctx p { tpackage = fst cpath; tname = snd cpath; tparams = []; tsub = sub } in - let cl, meth = (match mt with - | TClassDecl c -> - finalize mctx; - c, (try PMap.find f c.cl_statics with Not_found -> error ("Method " ^ f ^ " not found on class " ^ s_type_path cpath) p) - | _ -> error "Macro should be called on a class" p - ) in - let meth = (match follow meth.cf_type with TFun (args,ret) -> args,ret,cl,meth | _ -> error "Macro call should be a method" p) in - if not ctx.in_macro then flush_macro_context mint ctx; - t(); - let call args = - let t = macro_timer ctx (s_type_path cpath ^ "." ^ f) in - incr stats.s_macros_called; - let r = Interp.call_path (Interp.get_ctx()) ((fst cpath) @ [(match sub with None -> snd cpath | Some s -> s)]) f args api in - t(); - r - in - mctx, meth, call - -let type_macro ctx mode cpath f (el:Ast.expr list) p = - let mctx, (margs,mret,mclass,mfield), call_macro = load_macro ctx cpath f p in - let mpos = mfield.cf_pos in - let ctexpr = { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = None } in - let expr = Typeload.load_instance mctx ctexpr p false in - (match mode with - | MExpr -> - unify mctx mret expr mpos; - | MBuild -> - let ctfields = { tpackage = []; tname = "Array"; tparams = [TPType (CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = Some "Field" })]; tsub = None } in - let tfields = Typeload.load_instance mctx ctfields p false in - unify mctx mret tfields mpos - | MMacroType -> - let cttype = { tpackage = ["haxe";"macro"]; tname = "Type"; tparams = []; tsub = None } in - let ttype = Typeload.load_instance mctx cttype p false in - try - unify_raise mctx mret ttype mpos; - (* TODO: enable this again in the future *) - (* ctx.com.warning "Returning Type from @:genericBuild macros is deprecated, consider returning ComplexType instead" p; *) - with Error (Unify _,_) -> - let cttype = { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = Some ("ComplexType") } in - let ttype = Typeload.load_instance mctx cttype p false in - unify_raise mctx mret ttype mpos; - ); - (* - if the function's last argument is of Array, split the argument list and use [] for unify_call_args - *) - let el,el2 = match List.rev margs with - | (_,_,TInst({cl_path=([], "Array")},[e])) :: rest when (try Type.type_eq EqStrict e expr; true with Unify_error _ -> false) -> - let rec loop (acc1,acc2) el1 el2 = match el1,el2 with - | [],[] -> - List.rev acc1, List.rev acc2 - | [], e2 :: [] -> - (List.rev ((EArrayDecl [],p) :: acc1), []) - | [], _ -> - (* not enough arguments, will be handled by unify_call_args *) - List.rev acc1, List.rev acc2 - | e1 :: l1, e2 :: [] -> - loop (((EArrayDecl [],p) :: acc1), [e1]) l1 [] - | e1 :: l1, [] -> - loop (acc1, e1 :: acc2) l1 [] - | e1 :: l1, e2 :: l2 -> - loop (e1 :: acc1, acc2) l1 l2 - in - loop ([],[]) el margs - | _ -> - el,[] - in - let todo = ref [] in - let args = - (* - force default parameter types to haxe.macro.Expr, and if success allow to pass any value type since it will be encoded - *) - let eargs = List.map (fun (n,o,t) -> try unify_raise mctx t expr p; (n, o, t_dynamic), true with Error (Unify _,_) -> (n,o,t), false) margs in - (* - this is quite tricky here : we want to use unify_call_args which will type our AST expr - but we want to be able to get it back after it's been padded with nulls - *) - let index = ref (-1) in - let constants = List.map (fun e -> - let p = snd e in - let e = (try - (match Codegen.type_constant_value ctx.com e with - | { eexpr = TConst (TString _); epos = p } when Lexer.is_fmt_string p -> - Lexer.remove_fmt_string p; - todo := (fun() -> Lexer.add_fmt_string p) :: !todo; - | _ -> ()); - e - with Error (Custom _,_) -> - (* if it's not a constant, let's make something that is typed as haxe.macro.Expr - for nice error reporting *) - (EBlock [ - (EVars ["__tmp",Some (CTPath ctexpr),Some (EConst (Ident "null"),p)],p); - (EConst (Ident "__tmp"),p); - ],p) - ) in - (* let's track the index by doing [e][index] (we will keep the expression type this way) *) - incr index; - (EArray ((EArrayDecl [e],p),(EConst (Int (string_of_int (!index))),p)),p) - ) el in - let elt, _ = unify_call_args mctx constants (List.map fst eargs) t_dynamic p false false in - List.iter (fun f -> f()) (!todo); - List.map2 (fun (_,ise) e -> - let e, et = (match e.eexpr with - (* get back our index and real expression *) - | TArray ({ eexpr = TArrayDecl [e] }, { eexpr = TConst (TInt index) }) -> List.nth el (Int32.to_int index), e - (* added by unify_call_args *) - | TConst TNull -> (EConst (Ident "null"),e.epos), e - | _ -> assert false - ) in - if ise then - Interp.encode_expr e - else match Interp.eval_expr (Interp.get_ctx()) et with - | None -> assert false - | Some v -> v - ) eargs elt - in - let args = match el2 with - | [] -> args - | _ -> (match List.rev args with _::args -> List.rev args | [] -> []) @ [Interp.enc_array (List.map Interp.encode_expr el2)] - in - let call() = - match call_macro args with - | None -> None - | Some v -> - try - Some (match mode with - | MExpr -> Interp.decode_expr v - | MBuild -> - let fields = (match v with - | Interp.VNull -> - (match ctx.g.get_build_infos() with - | None -> assert false - | Some (_,_,fields) -> fields) - | _ -> - List.map Interp.decode_field (Interp.dec_array v) - ) in - (EVars ["fields",Some (CTAnonymous fields),None],p) - | MMacroType -> - let t = if v = Interp.VNull then - mk_mono() - else try - let ct = Interp.decode_ctype v in - Typeload.load_complex_type ctx p ct; - with Interp.Invalid_expr -> - Interp.decode_type v - in - ctx.ret <- t; - (EBlock [],p) - ) - with Interp.Invalid_expr -> - if v = Interp.VNull then - error "Unexpected null value returned from macro" p - else - error "The macro didn't return a valid result" p - in - let e = (if ctx.in_macro then begin - (* - this is super-tricky : we can't evaluate a macro inside a macro because we might trigger some cycles. - So instead, we generate a haxe.macro.Context.delayedCalled(i) expression that will only evaluate the - macro if/when it is called. - - The tricky part is that the whole delayed-evaluation process has to use the same contextual informations - as if it was evaluated now. - *) - let ctx = { - ctx with locals = ctx.locals; - } in - let pos = DynArray.length mctx.g.delayed_macros in - DynArray.add mctx.g.delayed_macros (fun() -> - delayed_macro_result := (fun() -> - let mint = Interp.get_ctx() in - match call() with - | None -> (fun() -> raise Interp.Abort) - | Some e -> Interp.eval mint (Genneko.gen_expr mint.Interp.gen (type_expr ctx e Value)) - ); - ); - ctx.m.curmod.m_extra.m_time <- -1.; (* disable caching for modules having macro-in-macro *) - let e = (EConst (Ident "__dollar__delay_call"),p) in - Some (EUntyped (ECall (e,[EConst (Int (string_of_int pos)),p]),p),p) - end else - call() - ) in - e - -let call_macro ctx path meth args p = - let mctx, (margs,_,mclass,mfield), call = load_macro ctx path meth p in - let el, _ = unify_call_args mctx args margs t_dynamic p false false in - call (List.map (fun e -> try Interp.make_const e with Exit -> error "Parameter should be a constant" e.epos) el) - -let call_init_macro ctx e = - let p = { pfile = "--macro"; pmin = 0; pmax = 0 } in - let e = try - parse_expr_string ctx e p false - with err -> - display_error ctx ("Could not parse `" ^ e ^ "`") p; - raise err - in - match fst e with - | ECall (e,args) -> - let rec loop e = - match fst e with - | EField (e,f) -> f :: loop e - | EConst (Ident i) -> [i] - | _ -> error "Invalid macro call" p - in - let path, meth = (match loop e with - | [meth] -> (["haxe";"macro"],"Compiler"), meth - | meth :: cl :: path -> (List.rev path,cl), meth - | _ -> error "Invalid macro call" p) in - ignore(call_macro ctx path meth args p); - | _ -> - error "Invalid macro call" p + get_main ctx !types, List.rev !types, sorted_modules (* ---------------------------------------------------------------------- *) (* TYPER INITIALIZATION *) @@ -4910,20 +4459,24 @@ let rec create com = types_module = Hashtbl.create 0; type_patches = Hashtbl.create 0; global_metadata = []; + module_check_policies = []; delayed = []; debug_delayed = []; delayed_macros = DynArray.create(); - doinline = not (Common.defined com Define.NoInline || com.display <> DMNone); + doinline = com.display.dms_inline && not (Common.defined com Define.NoInline); hook_generate = []; get_build_infos = (fun() -> None); std = null_module; global_using = []; - do_inherit = Codegen.on_inherit; + do_inherit = Typeload.on_inherit; do_create = create; - do_macro = type_macro; + do_macro = MacroContext.type_macro; do_load_module = Typeload.load_module; do_optimize = Optimizer.reduce_expression; - do_build_instance = Codegen.build_instance; + do_build_instance = Typeload.build_instance; + do_format_string = format_string; + do_finalize = finalize; + do_generate = generate; }; m = { curmod = null_module; @@ -4931,7 +4484,9 @@ let rec create com = module_using = []; module_globals = PMap.empty; wildcard_packages = []; + module_imports = []; }; + is_display_file = false; meta = []; this_stack = []; with_type_stack = []; @@ -4941,7 +4496,6 @@ let rec create com = untyped = false; curfun = FunStatic; in_loop = false; - in_super_call = false; in_display = false; in_macro = Common.defined com Define.Macro; ret = mk_mono(); @@ -4952,6 +4506,7 @@ let rec create com = tthis = mk_mono(); opened = []; vthis = None; + in_call_args = false; on_error = (fun ctx msg p -> ctx.com.error msg p); } in ctx.g.std <- (try @@ -4960,7 +4515,7 @@ let rec create com = Error (Module_not_found ([],"StdTypes"),_) -> error "Standard library not found" null_pos ); (* We always want core types to be available so we add them as default imports (issue #1904 and #3131). *) - ctx.m.module_types <- ctx.g.std.m_types; + ctx.m.module_types <- List.map (fun t -> t,null_pos) ctx.g.std.m_types; List.iter (fun t -> match t with | TAbstractDecl a -> @@ -4969,6 +4524,7 @@ let rec create com = | "Float" -> ctx.t.tfloat <- TAbstract (a,[]); | "Int" -> ctx.t.tint <- TAbstract (a,[]) | "Bool" -> ctx.t.tbool <- TAbstract (a,[]) + | "Dynamic" -> t_dynamic_def := TAbstract(a,List.map snd a.a_params); | _ -> ()); | TEnumDecl e -> () @@ -5010,11 +4566,11 @@ let rec create com = with Exit -> ()); let m = Typeload.load_module ctx (["haxe"],"EnumTools") null_pos in (match m.m_types with - | [TClassDecl c1;TClassDecl c2] -> ctx.g.global_using <- c1 :: c2 :: ctx.g.global_using + | [TClassDecl c1;TClassDecl c2] -> ctx.g.global_using <- (c1,c1.cl_pos) :: (c2,c2.cl_pos) :: ctx.g.global_using | [TClassDecl c1] -> let m = Typeload.load_module ctx (["haxe"],"EnumValueTools") null_pos in (match m.m_types with - | [TClassDecl c2 ] -> ctx.g.global_using <- c1 :: c2 :: ctx.g.global_using + | [TClassDecl c2 ] -> ctx.g.global_using <- (c1,c1.cl_pos) :: (c2,c2.cl_pos) :: ctx.g.global_using | _ -> assert false); | _ -> assert false); ctx @@ -5023,7 +4579,9 @@ let rec create com = unify_min_ref := unify_min; make_call_ref := make_call; get_constructor_ref := get_constructor; -cast_or_unify_ref := Codegen.AbstractCast.cast_or_unify_raise; +cast_or_unify_ref := AbstractCast.cast_or_unify_raise; type_module_type_ref := type_module_type; -find_array_access_raise_ref := Codegen.AbstractCast.find_array_access_raise; -build_call_ref := build_call +find_array_access_raise_ref := AbstractCast.find_array_access_raise; +build_call_ref := build_call; +merge_core_doc_ref := merge_core_doc; +MacroContext.unify_call_args_ref := unify_call_args \ No newline at end of file diff --git a/std/Any.hx b/std/Any.hx new file mode 100644 index 00000000..015fd735 --- /dev/null +++ b/std/Any.hx @@ -0,0 +1,37 @@ +/* + * Copyright (C)2005-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. + */ + +/** + `Any` is a type that is compatible with any other in both ways. + + This means that a value of any type can be assigned to `Any`, and + vice-versa, a value of `Any` type can be assigned to any other type. + + It's a more type-safe alternative to `Dynamic`, because it doesn't + support field access or operators and it's bound to monomorphs. So, + to work with the actual value, it needs to be explicitly promoted + to another type. +**/ +abstract Any(Dynamic) { + @:noCompletion @:extern @:to inline function __promote():T return this; + @:noCompletion @:extern @:from inline static function __cast(value:T):Any return cast value; +} diff --git a/std/Array.hx b/std/Array.hx index 2645f922..76784692 100644 --- a/std/Array.hx +++ b/std/Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,6 +22,9 @@ /** An Array is a storage for values. You can access it using indexes or with its API. + + @see https://haxe.org/manual/std-Array.html + @see https://haxe.org/manual/lf-array-comprehension.html **/ extern class Array { @@ -121,11 +124,11 @@ extern class Array { `this` Array. If `pos` or `end` are negative, their offsets are calculated from the - end of `this` Array by `this.length + pos` and `this.length + end` + end of `this` Array by `this.length + pos` and `this.length + end` respectively. If this yields a negative value, 0 is used instead. - If `pos` exceeds `this.length` or if `end` exceeds or equals `pos`, - the result is `[]`. + If `pos` exceeds `this.length` or if `end` is less than or equals + `pos`, the result is `[]`. **/ function slice( pos : Int, ?end : Int ) : Array; @@ -173,7 +176,7 @@ extern class Array { The result will include the individual elements' String representations separated by comma. The enclosing [ ] may be missing on some platforms, - use Std.string() to get a String representation that is consistent + use `Std.string()` to get a String representation that is consistent across platforms. **/ function toString() : String; diff --git a/std/Class.hx b/std/Class.hx index 6d28bb2f..5eb31102 100644 --- a/std/Class.hx +++ b/std/Class.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -23,6 +23,8 @@ An abstract type that represents a Class. See `Type` for the Haxe Reflection API. + + @see https://haxe.org/manual/types-class-instance.html **/ @:coreType @:runtimeValue abstract Class { } diff --git a/std/Date.hx b/std/Date.hx index 6fb58a14..fa833baf 100644 --- a/std/Date.hx +++ b/std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -29,9 +29,9 @@ - `Date.fromTime()` with a given timestamp or - `Date.fromString()` by parsing from a String. - There is some extra functions available in the `DateTools` class. + There are some extra functions available in the `DateTools` class. - In the context of haxe dates, a timestamp is defined as the number of + In the context of Haxe dates, a timestamp is defined as the number of milliseconds elapsed since 1st January 1970. **/ extern class Date @@ -51,8 +51,8 @@ extern class Date function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void; /** - Returns the timestamp of the date. It might only have a per-second - precision depending on the platforms. + Returns the timestamp (in milliseconds) of the date. It might + only have a per-second precision depending on the platforms. **/ function getTime() : Float; @@ -87,7 +87,7 @@ extern class Date function getDate() : Int; /** - Returns the day of the week of `this` Date (0-6 range). + Returns the day of the week of `this` Date (0-6 range) where `0` is Sunday. **/ function getDay() : Int; diff --git a/std/DateTools.hx b/std/DateTools.hx index a4a0e1c9..f7578bd9 100644 --- a/std/DateTools.hx +++ b/std/DateTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,7 +24,7 @@ The DateTools class contains some extra functionalities for handling `Date` instances and timestamps. - In the context of haxe dates, a timestamp is defined as the number of + In the context of Haxe dates, a timestamp is defined as the number of milliseconds elapsed since 1st January 1970. **/ class DateTools { @@ -33,10 +33,23 @@ class DateTools { #elseif (neko && !(macro || interp)) static var date_format = neko.Lib.load("std","date_format",2); #else + static var DAY_SHORT_NAMES = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + static var DAY_NAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; + static var MONTH_SHORT_NAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + static var MONTH_NAMES = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; + private static function __format_get( d : Date, e : String ) : String { return switch( e ){ case "%": "%"; + case "a": + DAY_SHORT_NAMES[d.getDay()]; + case "A": + DAY_NAMES[d.getDay()]; + case "b","h": + MONTH_SHORT_NAMES[d.getMonth()]; + case "B": + MONTH_NAMES[d.getMonth()]; case "C": untyped StringTools.lpad(Std.string(Std.int(d.getFullYear()/100)),"0",2); case "d": @@ -112,6 +125,20 @@ class DateTools { support in Flash and JS for day and months names (due to lack of proper internationalization API). On Haxe/Neko/Windows, some formats are not supported. + + ```haxe + var t = DateTools.format(Date.now(), "%Y-%m-%d_%H:%M:%S"); + // 2016-07-08_14:44:05 + + var t = DateTools.format(Date.now(), "%r"); + // 02:44:05 PM + + var t = DateTools.format(Date.now(), "%T"); + // 14:44:05 + + var t = DateTools.format(Date.now(), "%F"); + // 2016-07-08 + ``` **/ public static function format( d : Date, f : String ) : String { #if (neko && !(macro || interp)) @@ -161,7 +188,7 @@ class DateTools { /** Converts a number of minutes to a timestamp. **/ - public static inline function minutes( n : Float ) : Float { + #if as3 @:extern #end public static inline function minutes( n : Float ) : Float { return n * 60.0 * 1000.0; } diff --git a/std/EReg.hx b/std/EReg.hx index 509c6c81..62f2397b 100644 --- a/std/EReg.hx +++ b/std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -28,13 +28,13 @@ off to retain a certain level of performance. EReg instances can be created by calling the constructor, or with the - special syntax ~/pattern/modifier + special syntax `~/pattern/modifier` EReg instances maintain an internal state, which is affected by several of its methods. A detailed explanation of the supported operations is available at - http://haxe.org/manual/std-regex.html + **/ class EReg { @@ -145,7 +145,7 @@ class EReg { empty String "" entry. If two matching substrings appear next to each other, the result - contains the empty String "" between them. + contains the empty String `""` between them. By default, this method splits `s` into two parts at the first matched substring. If the global g modifier is in place, `s` is split at each diff --git a/std/Enum.hx b/std/Enum.hx index ce1bc76b..8748bf94 100644 --- a/std/Enum.hx +++ b/std/Enum.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,6 +26,8 @@ The corresponding enum instance type is `EnumValue`. See `Type` for the Haxe Reflection API. + + @see https://haxe.org/manual/types-enum-instance.html **/ @:coreType @:runtimeValue abstract Enum { } diff --git a/std/EnumValue.hx b/std/EnumValue.hx index db0b5bfe..eca6d58d 100644 --- a/std/EnumValue.hx +++ b/std/EnumValue.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -23,6 +23,8 @@ /** An abstract type that represents any enum value. See `Type` for the Haxe Reflection API. + + @see https://haxe.org/manual/types-enum-instance.html **/ @:coreType abstract EnumValue { } diff --git a/std/IntIterator.hx b/std/IntIterator.hx index a97c4297..64705e2b 100644 --- a/std/IntIterator.hx +++ b/std/IntIterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -30,6 +30,8 @@ field, it is worth noting that IntIterator does not reset after being used in a for-loop. Subsequent uses of the same instance will then have no effect. + + @see https://haxe.org/manual/lf-iterators.html **/ class IntIterator { diff --git a/std/Lambda.hx b/std/Lambda.hx index 9313d9b2..5d6efecb 100644 --- a/std/Lambda.hx +++ b/std/Lambda.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,7 +22,7 @@ /** The `Lambda` class is a collection of methods to support functional - programming. It is ideally used with 'using Lambda' and then acts as an + programming. It is ideally used with `using Lambda` and then acts as an extension to Iterable types. On static platforms, working with the Iterable structure might be slower @@ -31,6 +31,8 @@ If the first argument to any of the methods is null, the result is unspecified. + + @see https://haxe.org/manual/std-Lambda.html **/ class Lambda { @@ -87,6 +89,30 @@ class Lambda { return l; } + /** + Concatenate a list of lists. + + The order of elements is preserved. + **/ + public static function flatten
( it : Iterable> ) : List { + var l = new List(); + for (e in it) + for (x in e) + l.add(x); + return l; + } + + /** + A composition of map and flatten. + + The order of elements is preserved. + + If `f` is null, the result is unspecified. + **/ + public static function flatMap( it : Iterable, f: A -> Iterable ) : List { + return Lambda.flatten(Lambda.map(it, f)); + } + /** Tells if `it` contains `elt`. diff --git a/std/List.hx b/std/List.hx index dcb58bd5..4cfed401 100644 --- a/std/List.hx +++ b/std/List.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,15 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + /** - A linked-list of elements. The list is composed of two-elements arrays + A linked-list of elements. The list is composed of element container objects that are chained together. It is optimized so that adding or removing an - element does not imply copying the whole array content every time. + element does not imply copying the whole list content every time. + + @see https://haxe.org/manual/std-List.html **/ class List { - private var h : Array; - private var q : Array; + private var h : ListNode; + private var q : ListNode; /** The length of `this` List. @@ -47,11 +50,11 @@ class List { `this.length` increases by 1. **/ public function add( item : T ) { - var x:Array = #if neko untyped __dollar__array(item,null) #else [item] #end; + var x = ListNode.create(item, null); if( h == null ) h = x; else - q[1] = x; + q.next = x; q = x; length++; } @@ -62,11 +65,7 @@ class List { `this.length` increases by 1. **/ public function push( item : T ) { - var x : Array = #if neko - untyped __dollar__array(item,h) - #else - [item,h] - #end; + var x = ListNode.create(item, h); h = x; if( q == null ) q = x; @@ -79,7 +78,7 @@ class List { This function does not modify `this` List. **/ public function first() : Null { - return if( h == null ) null else h[0]; + return if( h == null ) null else h.item; } /** @@ -88,7 +87,7 @@ class List { This function does not modify `this` List. **/ public function last() : Null { - return if( q == null ) null else q[0]; + return if( q == null ) null else q.item; } @@ -100,8 +99,8 @@ class List { public function pop() : Null { if( h == null ) return null; - var x = h[0]; - h = h[1]; + var x = h.item; + h = h.next; if( h == null ) q = null; length--; @@ -136,21 +135,21 @@ class List { Otherwise, false is returned. **/ public function remove( v : T ) : Bool { - var prev = null; + var prev:ListNode = null; var l = h; while( l != null ) { - if( l[0] == v ) { + if( l.item == v ) { if( prev == null ) - h = l[1]; + h = l.next; else - prev[1] = l[1]; + prev.next = l.next; if( q == l ) q = prev; length--; return true; } prev = l; - l = l[1]; + l = l.next; } return false; } @@ -178,8 +177,8 @@ class List { first = false; else s.add(", "); - s.add(Std.string(l[0])); - l = l[1]; + s.add(Std.string(l.item)); + l = l.next; } s.add("}"); return s.toString(); @@ -198,8 +197,8 @@ class List { first = false; else s.add(sep); - s.add(l[0]); - l = l[1]; + s.add(l.item); + l = l.next; } return s.toString(); } @@ -212,8 +211,8 @@ class List { var l2 = new List(); var l = h; while( l != null ) { - var v = l[0]; - l = l[1]; + var v = l.item; + l = l.next; if( f(v) ) l2.add(v); } @@ -228,8 +227,8 @@ class List { var b = new List(); var l = h; while( l != null ) { - var v = l[0]; - l = l[1]; + var v = l.item; + l = l.next; b.add(f(v)); } return b; @@ -237,13 +236,37 @@ class List { } +#if neko +private extern class ListNode extends neko.NativeArray { + var item(get,set):T; + var next(get,set):ListNode; + private inline function get_item():T return this[0]; + private inline function set_item(v:T):T return this[0] = v; + private inline function get_next():ListNode return this[1]; + private inline function set_next(v:ListNode):ListNode return this[1] = v; + inline static function create(item:T, next:ListNode):ListNode { + return untyped __dollar__array(item, next); + } +} +#else +private class ListNode { + public var item:T; + public var next:ListNode; + public function new(item:T, next:ListNode) { + this.item = item; + this.next = next; + } + @:extern public inline static function create(item:T, next:ListNode):ListNode { + return new ListNode(item, next); + } +} +#end + private class ListIterator { - var head:Array; - var val:Dynamic; + var head:ListNode; - public inline function new(head:Array) { + public inline function new(head:ListNode) { this.head = head; - this.val = null; } public inline function hasNext():Bool { @@ -251,8 +274,8 @@ private class ListIterator { } public inline function next():T { - val = head[0]; - head = head[1]; + var val = head.item; + head = head.next; return val; } } diff --git a/std/Map.hx b/std/Map.hx index 1d0227ac..e9eece55 100644 --- a/std/Map.hx +++ b/std/Map.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -41,8 +41,10 @@ import haxe.Constraints.IMap; Maps can also be created with `key1 => value1, key2 => value2` syntax. Map is an abstract type, it is not available at runtime. + + @see https://haxe.org/manual/std-Map.html **/ -@:multiType(K) +@:multiType(@:followWithAbstracts K) abstract Map(IMap ) { /** @@ -163,5 +165,6 @@ abstract Map(IMap ) { } } +@:dox(hide) @:deprecated typedef IMap = haxe.Constraints.IMap; \ No newline at end of file diff --git a/std/Math.hx b/std/Math.hx index 4d246f8a..8837f100 100644 --- a/std/Math.hx +++ b/std/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,8 +21,11 @@ */ /** This class defines mathematical functions and constants. + + @see https://haxe.org/manual/std-math.html **/ #if cpp @:include("hxMath.h") #end +@:pure extern class Math { /** @@ -45,7 +48,7 @@ extern class Math static var NEGATIVE_INFINITY(default, null) : Float; /** - A special `Float` constant which denotes negative infinity. + A special `Float` constant which denotes positive infinity. For example, this is the result of 1.0 / 0.0. @@ -73,7 +76,7 @@ extern class Math @php In PHP versions prior to 5.3.1 VC 9 there may be unexpected results when performing arithmetic operations with `NaN` on Windows, - see [https://bugs.php.net/bug.php?id=42143] + see **/ static var NaN(default, null) : Float; @@ -203,6 +206,8 @@ extern class Math /** Rounds `v` to the nearest integer value. + Ties are rounded up, so that `0.5` becomes `1` and `-0.5` becomes `0`. + If `v` is outside of the signed `Int32` range, or is `NaN`, `NEGATIVE_INFINITY` or `POSITIVE_INFINITY`, the result is unspecified. **/ @@ -250,6 +255,8 @@ extern class Math /** Rounds `v` to the nearest integer value, as a Float. + Ties are rounded up, so that `0.5` becomes `1` and `-0.5` becomes `0`. + If `v` is is `NaN`, `NEGATIVE_INFINITY` or `POSITIVE_INFINITY`, the result is unspecified. **/ diff --git a/std/Reflect.hx b/std/Reflect.hx index e94ac321..03807936 100644 --- a/std/Reflect.hx +++ b/std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,6 +22,8 @@ /** The Reflect API is a way to manipulate values dynamically through an abstract interface in an untyped manner. Use with care. + + @see https://haxe.org/manual/std-reflection.html **/ extern class Reflect { @@ -148,8 +150,8 @@ extern class Reflect { - class instance - structure - - Class - - Enum + - `Class` + - `Enum` Otherwise, including if `v` is null, the result is false. **/ diff --git a/std/Std.hx b/std/Std.hx index 70e64b96..10cffb3a 100644 --- a/std/Std.hx +++ b/std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/StdTypes.hx b/std/StdTypes.hx index 76222f7f..8a2a62c6 100644 --- a/std/StdTypes.hx +++ b/std/StdTypes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,98 +22,134 @@ // standard Haxe types /** - The standard Void type. Only `null` values can be of the type `Void`. + The standard `Void` type. Only `null` values can be of the type `Void`. + + @see https://haxe.org/manual/types-void.html **/ @:coreType abstract Void { } /** - The standard Float type, this is a double-precision IEEE 64bit float. + The standard `Float` type, this is a double-precision IEEE 64bit float. - On static targets, null cannot be assigned to Float. If this is necessary, + On static targets, `null` cannot be assigned to Float. If this is necessary, `Null` can be used instead. + + `Std.int` converts a `Float` to an `Int`, rounded towards 0. + `Std.parseFloat` converts a `String` to a `Float`. + + @see https://haxe.org/manual/types-basic-types.html + @see https://haxe.org/manual/types-nullability.html **/ @:coreType @:notNull @:runtimeValue abstract Float { } /** - The standard Int type. Its precision depends on the platform. + The standard `Int` type. Its precision depends on the platform. - On static targets, null cannot be assigned to Int. If this is necessary, + On static targets, `null` cannot be assigned to `Int`. If this is necessary, `Null` can be used instead. + + `Std.int` converts a `Float` to an `Int`, rounded towards 0. + `Std.parseInt` converts a `String` to an `Int`. + + @see https://haxe.org/manual/types-basic-types.html + @see https://haxe.org/manual/std-math-integer-math.html + @see https://haxe.org/manual/types-nullability.html **/ @:coreType @:notNull @:runtimeValue abstract Int to Float { } -#if (java || cs) +#if (java || cs || hl) +/** + Single-precision IEEE 32bit float (4-byte). +**/ @:coreType @:notNull @:runtimeValue abstract Single to Float from Float {} #end /** `Null` can be useful in two cases. In order to document some methods - that accepts or can return a `null` value, or for the Flash compiler and AS3 - generator to distinguish between base values that can be null and others that + that accept or can return a `null` value, or for the Flash compiler and AS3 + generator to distinguish between base values that can be `null` and others that can't. + + @see https://haxe.org/manual/types-nullability.html **/ typedef Null = T /** - The standard Boolean type, which can either be true or false. + The standard Boolean type, which can either be `true` or `false`. - On static targets, null cannot be assigned to Bool. If this is necessary, + On static targets, `null` cannot be assigned to `Bool`. If this is necessary, `Null` can be used instead. + + @see https://haxe.org/manual/types-bool.html + @see https://haxe.org/manual/types-nullability.html **/ @:coreType @:notNull @:runtimeValue abstract Bool { } /** - Dynamic is a special type which is compatible with all other types. + `Dynamic` is a special type which is compatible with all other types. - Use of Dynamic should be minimized as it prevents several compiler - checks and optimizations. + Use of `Dynamic` should be minimized as it prevents several compiler + checks and optimizations. See `Any` type for a safer alternative for + representing values of any type. + + @see https://haxe.org/manual/types-dynamic.html **/ @:coreType @:runtimeValue abstract Dynamic { } /** - An Iterator is a structure that permits iteration over elements of type T. + An `Iterator` is a structure that permits iteration over elements of type `T`. - Any class with matching hasNext and next fields is considered an Iterator - and can then be used e.g. in for-loops. This makes it easy to implement + Any class with matching `hasNext()` and `next()` fields is considered an `Iterator` + and can then be used e.g. in `for`-loops. This makes it easy to implement custom iterators. + + @see https://haxe.org/manual/lf-iterators.html **/ typedef Iterator = { /** - Returns false if the iteration is complete, true otherwise. + Returns `false` if the iteration is complete, `true` otherwise. Usually iteration is considered to be complete if all elements of the - underlying data structure were handled through calls to next(). However, + underlying data structure were handled through calls to `next()`. However, in custom iterators any logic may be used to determine the completion state. **/ function hasNext() : Bool; /** - Returns the current item of the Iterator and advances to the next one. + Returns the current item of the `Iterator` and advances to the next one. - This method is not required to check `hasNext` first. A call to this - method while `hasNext` is false yields unspecified behavior. + This method is not required to check `hasNext()` first. A call to this + method while `hasNext()` is `false` yields unspecified behavior. - On the other hand iterators should not require a call to `hasNext` - before the first call to `next` if an element is available. + On the other hand, iterators should not require a call to `hasNext()` + before the first call to `next()` if an element is available. **/ function next() : T; } /** - An Iterable is a data structure which has an iterator() method. + An `Iterable` is a data structure which has an `iterator()` method. See `Lambda` for generic functions on iterable structures. + + @see https://haxe.org/manual/lf-iterators.html **/ typedef Iterable = { function iterator() : Iterator; } /** - ArrayAccess is used to indicate a class that can be accessed using brackets. + `ArrayAccess` is used to indicate a class that can be accessed using brackets. The type parameter represents the type of the elements stored. + + This interface should be used for externs only. Haxe does not support custom + array access on classes. However, array access can be implemented for + abstract types. + + @see https://haxe.org/manual/types-abstract-array-access.html **/ extern interface ArrayAccess { } diff --git a/std/String.hx b/std/String.hx index e523500c..37b38e20 100644 --- a/std/String.hx +++ b/std/String.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,13 +22,15 @@ /** The basic String class. - A haxe String is immutable, it is not possible to modify individual + A Haxe String is immutable, it is not possible to modify individual characters. No method of this class changes the state of `this` String. - Strings can be constructed using the string literal syntax "string value". + Strings can be constructed using the String literal syntax `"string value"`. - String can be concatenated by using the + operator. If an operand is not a - String, it is passed through Std.string() first. + String can be concatenated by using the `+` operator. If an operand is not a + String, it is passed through `Std.string()` first. + + @see https://haxe.org/manual/std-String.html **/ extern class String { @@ -59,7 +61,7 @@ extern class String { /** Returns the character at position `index` of `this` String. - If `index` is negative or exceeds `this.length`, the empty String "" + If `index` is negative or exceeds `this.length`, the empty String `""` is returned. **/ function charAt(index : Int) : String; @@ -67,11 +69,11 @@ extern class String { /** Returns the character code at position `index` of `this` String. - If `index` is negative or exceeds `this.length`, null is returned. + If `index` is negative or exceeds `this.length`, `null` is returned. - To obtain the character code of a single character, "x".code can be used - instead to inline the character code at compile time. Note that this - only works on String literals of length 1. + To obtain the character code of a single character, `"x".code` can be + used instead to inline the character code at compile time. Note that + this only works on String literals of length 1. **/ function charCodeAt( index : Int) : Null; @@ -104,10 +106,10 @@ extern class String { /** Splits `this` String at each occurence of `delimiter`. - If `this` String is the empty String "", the result is not consistent + If `this` String is the empty String `""`, the result is not consistent across targets and may either be `[]` (on Js, Cpp) or `[""]`. - If `delimiter` is the empty String "", `this` String is split into an + If `delimiter` is the empty String `""`, `this` String is split into an Array of `this.length` elements, where the elements correspond to the characters of `this` String. @@ -117,9 +119,9 @@ extern class String { If `delimiter` is null, the result is unspecified. Otherwise, `this` String is split into parts at each occurence of - `delimiter`. If `this` String starts (or ends) with [delimiter}, the - result Array contains a leading (or trailing) empty String "" element. - Two subsequent delimiters also result in an empty String "" element. + `delimiter`. If `this` String starts (or ends) with `delimiter`, the + result `Array` contains a leading (or trailing) empty String `""` element. + Two subsequent delimiters also result in an empty String `""` element. **/ function split( delimiter : String ) : Array; @@ -151,7 +153,7 @@ extern class String { `this.length`, `this.length` is used instead. If the (possibly swapped) `startIndex` exceeds `this.length`, the empty - String "" is returned. + String `""` is returned. **/ function substring( startIndex : Int, ?endIndex : Int ) : String; @@ -166,5 +168,5 @@ extern class String { If `code` is negative or has another invalid value, the result is unspecified. **/ - static function fromCharCode( code : Int ) : String; -} \ No newline at end of file + @:pure static function fromCharCode( code : Int ) : String; +} diff --git a/std/StringBuf.hx b/std/StringBuf.hx index 2684e2a0..6b80b117 100644 --- a/std/StringBuf.hx +++ b/std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/StringTools.hx b/std/StringTools.hx index 23fb84d7..3d502516 100644 --- a/std/StringTools.hx +++ b/std/StringTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,7 +21,8 @@ */ /** This class provides advanced methods on Strings. It is ideally used with - 'using StringTools' and then acts as an extension to the String class. + `using StringTools` and then acts as an [extension](https://haxe.org/manual/lf-static-extension.html) + to the `String` class. If the first argument to any of the methods is null, the result is unspecified. @@ -33,7 +34,7 @@ class StringTools { /** Encode an URL by using the standard format. **/ - #if (!java && !cpp) inline #end public static function urlEncode( s : String ) : String { + #if (!java && !cpp && !lua) inline #end public static function urlEncode( s : String ) : String { #if flash return untyped __global__["encodeURIComponent"](s); #elseif neko @@ -43,22 +44,67 @@ class StringTools { #elseif cpp return untyped s.__URLEncode(); #elseif java - try - return untyped __java__("java.net.URLEncoder.encode(s, \"UTF-8\")") - catch (e:Dynamic) throw e; + return postProcessUrlEncode(java.net.URLEncoder.encode(s, "UTF-8")); #elseif cs return untyped cs.system.Uri.EscapeDataString(s); #elseif python return python.lib.urllib.Parse.quote(s, ""); + #elseif hl + var len = 0; + var b = @:privateAccess s.bytes.urlEncode(len); + return @:privateAccess String.__alloc__(b,len); + #elseif lua + s = lua.NativeStringTools.gsub(s, "\n", "\r\n"); + s = lua.NativeStringTools.gsub(s, "([^%w %-%_%.%~])", function (c) { + return lua.NativeStringTools.format("%%%02X", lua.NativeStringTools.byte(c) + ''); + }); + s = lua.NativeStringTools.gsub(s, " ", "+"); + return s; #else return null; #end } +#if java + private static function postProcessUrlEncode( s : String ) : String { + var ret = new StringBuf(); + var i = 0, + len = s.length; + while (i < len) { + switch(_charAt(s, i++)) { + case '+'.code: + ret.add('%20'); + case '%'.code if (i <= len - 2): + var c1 = _charAt(s, i++), + c2 = _charAt(s, i++); + switch[c1, c2] { + case ['2'.code, '1'.code]: + ret.addChar('!'.code); + case ['2'.code, '7'.code]: + ret.addChar('\''.code); + case ['2'.code, '8'.code]: + ret.addChar('('.code); + case ['2'.code, '9'.code]: + ret.addChar(')'.code); + case ['7'.code, 'E'.code] | ['7'.code, 'e'.code]: + ret.addChar('~'.code); + case _: + ret.addChar('%'.code); + ret.addChar(cast c1); + ret.addChar(cast c2); + } + case chr: + ret.addChar(cast chr); + } + } + return ret.toString(); + } +#end + /** Decode an URL using the standard format. **/ - #if (!java && !cpp) inline #end public static function urlDecode( s : String ) : String { + #if (!java && !cpp && !lua) inline #end public static function urlDecode( s : String ) : String { #if flash return untyped __global__["decodeURIComponent"](s.split("+").join(" ")); #elseif neko @@ -75,6 +121,16 @@ class StringTools { return untyped cs.system.Uri.UnescapeDataString(s); #elseif python return python.lib.urllib.Parse.unquote(s); + #elseif hl + var len = 0; + var b = @:privateAccess s.bytes.urlDecode(len); + return @:privateAccess String.__alloc__(b,len); + #elseif lua + s = lua.NativeStringTools.gsub (s, "+", " "); + s = lua.NativeStringTools.gsub (s, "%%(%x%x)", + function(h) {return lua.NativeStringTools.char(lua.Lua.tonumber(h,16));}); + s = lua.NativeStringTools.gsub (s, "\r\n", "\n"); + return s; #else return null; #end @@ -103,7 +159,7 @@ class StringTools { Unescapes HTML special characters of the string `s`. This is the inverse operation to htmlEscape, i.e. the following always - holds: htmlUnescape(htmlEscape(s)) == s + holds: `htmlUnescape(htmlEscape(s)) == s` The replacements follow: @@ -120,9 +176,9 @@ class StringTools { /** Tells if the string `s` starts with the string `start`. - If `start` is null, the result is unspecified. + If `start` is `null`, the result is unspecified. - If `start` is the empty String "", the result is true. + If `start` is the empty String `""`, the result is true. **/ public static #if (cs || java) inline #end function startsWith( s : String, start : String ) : Bool { #if java @@ -138,6 +194,8 @@ class StringTools { if ( p0.at(i) != p1.at(i) ) return false; return true; + #elseif hl + return @:privateAccess (s.length >= start.length && s.bytes.compare(0,start.bytes,0,start.length<<1) == 0); #else return( s.length >= start.length && s.substr(0, start.length) == start ); #end @@ -146,9 +204,9 @@ class StringTools { /** Tells if the string `s` ends with the string `end`. - If `end` is null, the result is unspecified. + If `end` is `null`, the result is unspecified. - If `end` is the empty String "", the result is true. + If `end` is the empty String `""`, the result is true. **/ public static #if (cs || java) inline #end function endsWith( s : String, end : String ) : Bool { #if java @@ -164,6 +222,10 @@ class StringTools { if ( p0.at(i) != p1.at(i) ) return false; return true; + #elseif hl + var elen = end.length; + var slen = s.length; + return @:privateAccess (slen >= elen && s.bytes.compare((slen - elen) << 1, end.bytes, 0, elen << 1) == 0); #else var elen = end.length; var slen = s.length; @@ -177,11 +239,11 @@ class StringTools { A character is considered to be a space character if its character code is 9,10,11,12,13 or 32. - If `s` is the empty String "", or if pos is not a valid position within + If `s` is the empty String `""`, or if pos is not a valid position within `s`, the result is false. **/ public static function isSpace( s : String, pos : Int ) : Bool { - #if python + #if (python || lua) if (s.length == 0 || pos < 0 || pos >= s.length) return false; #end var c = s.charCodeAt( pos ); @@ -191,11 +253,11 @@ class StringTools { /** Removes leading space characters of `s`. - This function internally calls isSpace() to decide which characters to + This function internally calls `isSpace()` to decide which characters to remove. - If `s` is the empty String "" or consists only of space characters, the - result is the empty String "". + If `s` is the empty String `""` or consists only of space characters, the + result is the empty String `""`. **/ public #if cs inline #end static function ltrim( s : String ) : String { #if cs @@ -216,11 +278,11 @@ class StringTools { /** Removes trailing space characters of `s`. - This function internally calls isSpace() to decide which characters to + This function internally calls `isSpace()` to decide which characters to remove. - If `s` is the empty String "" or consists only of space characters, the - result is the empty String "". + If `s` is the empty String `""` or consists only of space characters, the + result is the empty String `""`. **/ public #if cs inline #end static function rtrim( s : String ) : String { #if cs @@ -242,7 +304,7 @@ class StringTools { /** Removes leading and trailing space characters of `s`. - This is a convenience function for ltrim(rtrim(s)). + This is a convenience function for `ltrim(rtrim(s))`. **/ public #if (cs || java) inline #end static function trim( s : String ) : String { #if cs @@ -257,7 +319,7 @@ class StringTools { /** Concatenates `c` to `s` until `s.length` is at least `l`. - If `c` is the empty String "" or if `l` does not exceed `s.length`, + If `c` is the empty String `""` or if `l` does not exceed `s.length`, `s` is returned unchanged. If `c.length` is 1, the resulting String length is exactly `l`. @@ -279,7 +341,7 @@ class StringTools { /** Appends `c` to `s` until `s.length` is at least `l`. - If `c` is the empty String "" or if `l` does not exceed `s.length`, + If `c` is the empty String `""` or if `l` does not exceed `s.length`, `s` is returned unchanged. If `c.length` is 1, the resulting String length is exactly `l`. @@ -302,8 +364,8 @@ class StringTools { Replace all occurences of the String `sub` in the String `s` by the String `by`. - If `sub` is the empty String "", `by` is inserted after each character - of `s`. If `by` is also the empty String "", `s` remains unchanged. + If `sub` is the empty String `""`, `by` is inserted after each character + of `s`. If `by` is also the empty String `""`, `s` remains unchanged. This is a convenience function for `s.split(sub).join(by)`. @@ -329,7 +391,7 @@ class StringTools { Encodes `n` into a hexadecimal representation. If `digits` is specified, the resulting String is padded with "0" until - its length equals `digits`. + its `length` equals `digits`. **/ public static function hex( n : Int, ?digits : Int ) { #if flash @@ -363,14 +425,14 @@ class StringTools { Returns the character code at position `index` of String `s`, or an end-of-file indicator at if `position` equals `s.length`. - This method is faster than String.charCodeAt() on some platforms, but + This method is faster than `String.charCodeAt()` on some platforms, but the result is unspecified if `index` is negative or greater than `s.length`. - End of file status can be checked by calling `StringTools.isEof` with + End of file status can be checked by calling `StringTools.isEof()` with the returned value as argument. - This operation is not guaranteed to work if `s` contains the \0 + This operation is not guaranteed to work if `s` contains the `\0` character. **/ public static inline function fastCodeAt( s : String, index : Int ) : Int { @@ -388,6 +450,10 @@ class StringTools { return (untyped s).charCodeAt(index); #elseif python return if (index >= s.length) -1 else python.internal.UBuiltins.ord(python.Syntax.arrayAccess(s, index)); + #elseif hl + return @:privateAccess s.bytes.getUI16(index << 1); + #elseif lua + return lua.NativeStringTools.byte(s,index+1); #else return untyped s.cca(index); #end @@ -397,11 +463,11 @@ class StringTools { Tells if `c` represents the end-of-file (EOF) character. */ @:noUsing public static inline function isEof( c : Int ) : Bool { - #if (flash || cpp) + #if (flash || cpp || hl) return c == 0; #elseif js return c != c; // fast NaN - #elseif neko + #elseif (neko || lua) return c == null; #elseif cs return c == -1; @@ -414,6 +480,106 @@ class StringTools { #end } + /** + Returns a String that can be used as a single command line argument + on Unix. + The input will be quoted, or escaped if necessary. + */ + public static function quoteUnixArg(argument:String):String { + // Based on cpython's shlex.quote(). + // https://hg.python.org/cpython/file/a3f076d4f54f/Lib/shlex.py#l278 + + if (argument == "") + return "''"; + + if (!~/[^a-zA-Z0-9_@%+=:,.\/-]/.match(argument)) + return argument; + + // use single quotes, and put single quotes into double quotes + // the string $'b is then quoted as '$'"'"'b' + return "'" + replace(argument, "'", "'\"'\"'") + "'"; + } + + /** + Character codes of the characters that will be escaped by `quoteWinArg(_, true)`. + */ + public static var winMetaCharacters = [" ".code, "(".code, ")".code, "%".code, "!".code, "^".code, "\"".code, "<".code, ">".code, "&".code, "|".code, "\n".code, "\r".code, ",".code, ";".code]; + + /** + Returns a String that can be used as a single command line argument + on Windows. + The input will be quoted, or escaped if necessary, such that the output + will be parsed as a single argument using the rule specified in + http://msdn.microsoft.com/en-us/library/ms880421 + + Examples: + ``` + quoteWinArg("abc") == "abc"; + quoteWinArg("ab c") == '"ab c"'; + ``` + */ + public static function quoteWinArg(argument:String, escapeMetaCharacters:Bool):String { + // If there is no space, tab, back-slash, or double-quotes, and it is not an empty string. + if (!~/^[^ \t\\"]+$/.match(argument)) { + + // Based on cpython's subprocess.list2cmdline(). + // https://hg.python.org/cpython/file/50741316dd3a/Lib/subprocess.py#l620 + + var result = new StringBuf(); + var needquote = argument.indexOf(" ") != -1 || argument.indexOf("\t") != -1 || argument == ""; + + if (needquote) + result.add('"'); + + var bs_buf = new StringBuf(); + for (i in 0...argument.length) { + switch (argument.charCodeAt(i)) { + case "\\".code: + // Don't know if we need to double yet. + bs_buf.add("\\"); + case '"'.code: + // Double backslashes. + var bs = bs_buf.toString(); + result.add(bs); + result.add(bs); + bs_buf = new StringBuf(); + result.add('\\"'); + case c: + // Normal char + if (bs_buf.length > 0) { + result.add(bs_buf.toString()); + bs_buf = new StringBuf(); + } + result.addChar(c); + } + } + + // Add remaining backslashes, if any. + result.add(bs_buf.toString()); + + if (needquote) { + result.add(bs_buf.toString()); + result.add('"'); + } + + argument = result.toString(); + } + + if (escapeMetaCharacters) { + var result = new StringBuf(); + for (i in 0...argument.length) { + var c = argument.charCodeAt(i); + if (winMetaCharacters.indexOf(c) >= 0) { + result.addChar("^".code); + } + result.addChar(c); + } + return result.toString(); + } else { + return argument; + } + } + #if java private static inline function _charAt(str:String, idx:Int):java.StdTypes.Char16 return untyped str._charAt(idx); #end diff --git a/std/Sys.hx b/std/Sys.hx index 687a1248..de52eaf8 100644 --- a/std/Sys.hx +++ b/std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ /** - This class gives you access to many base functionalities of system platforms. Looks in [sys] sub packages for more system APIs. + This class gives you access to many base functionalities of system platforms. Looks in `sys` sub packages for more system APIs. **/ @:require(sys) extern class Sys { @@ -31,7 +31,7 @@ extern class Sys { static function print( v : Dynamic ) : Void; /** - Print any value on the standard output, followed by a newline + Print any value on the standard output, followed by a newline. **/ static function println( v : Dynamic ) : Void; @@ -61,7 +61,7 @@ extern class Sys { static function sleep( seconds : Float ) : Void; /** - Change the current time locale, which will affect [DateTools.format] date formating. + Change the current time locale, which will affect `DateTools.format` date formating. Returns true if the locale was successfully changed **/ static function setTimeLocale( loc : String ) : Bool; @@ -83,9 +83,18 @@ extern class Sys { static function systemName() : String; /** - Run the given command with the list of arguments. The command output will be printed on the same output as the current process. + Run the given command. The command output will be printed on the same output as the current process. The current process will block until the command terminates and it will return the command result (0 if there was no error). - Read the [sys.io.Process] api for a more complete way to start background processes. + + Command arguments can be passed in two ways: 1. using `args`, 2. appending to `cmd` and leaving `args` as `null`. + + 1. When using `args` to pass command arguments, each argument will be automatically quoted, and shell meta-characters will be escaped if needed. + `cmd` should be an executable name that can be located in the `PATH` environment variable, or a path to an executable. + + 2. When `args` is not given or is `null`, command arguments can be appended to `cmd`. No automatic quoting/escaping will be performed. `cmd` should be formatted exactly as it would be when typed at the command line. + It can run executables, as well as shell commands that are not executables (e.g. on Windows: `dir`, `cd`, `echo` etc). + + Read the `sys.io.Process` api for a more complete way to start background processes. **/ static function command( cmd : String, ?args : Array ) : Int; @@ -107,15 +116,22 @@ extern class Sys { /** Returns the path to the current executable that we are running. **/ - static function executablePath() : String; + @:deprecated("Use programPath instead") static function executablePath() : String; + + /** + Returns the absolute path to the current program file that we are running. + Concretely, for an executable binary, it returns the path to the binary. + For a script (e.g. a PHP file), it returns the path to the script. + **/ + static function programPath() : String; /** - Read a single input character from the standard input (without blocking) and returns it. Setting [echo] to true will also display it on the output. + Read a single input character from the standard input (without blocking) and returns it. Setting `echo` to true will also display it on the output. **/ static function getChar( echo : Bool ) : Int; /** - Returns the process standard input, from which you can read what user enters. Usually it will block until the user send a full input line. See [getChar] for an alternative. + Returns the process standard input, from which you can read what user enters. Usually it will block until the user send a full input line. See `getChar` for an alternative. **/ static function stdin() : haxe.io.Input; diff --git a/std/Type.hx b/std/Type.hx index fe1c8315..ad81c280 100644 --- a/std/Type.hx +++ b/std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,26 +19,15 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -/** - The diffent possible runtime types of a value. -**/ -enum ValueType { - TNull; - TInt; - TFloat; - TBool; - TObject; - TFunction; - TClass( c : Class ); - TEnum( e : Enum ); - TUnknown; -} /** - The haxe Reflection API allows retrieval of type information at runtime. + The Haxe Reflection API allows retrieval of type information at runtime. This class complements the more lightweight Reflect class, with a focus on class and enum instances. + + @see https://haxe.org/manual/types.html + @see https://haxe.org/manual/std-reflection.html **/ extern class Type { @@ -82,7 +71,7 @@ extern class Type { If `c` is inside a package, the package structure is returned dot- separated, with another dot separating the class name: `pack1.pack2.(...).packN.ClassName` - If `c` is a sub-type of a haxe module, that module is not part of the + If `c` is a sub-type of a Haxe module, that module is not part of the package structure. If `c` has no package, the class name is returned. @@ -99,7 +88,7 @@ extern class Type { If `e` is inside a package, the package structure is returned dot- separated, with another dot separating the enum name: `pack1.pack2.(...).packN.EnumName` - If `e` is a sub-type of a haxe module, that module is not part of the + If `e` is a sub-type of a Haxe module, that module is not part of the package structure. If `e` has no package, the enum name is returned. @@ -182,7 +171,7 @@ extern class Type { Creates an instance of enum `e` by calling its constructor number `index` with arguments `params`. - The constructor indices are preserved from haxe syntax, so the first + The constructor indices are preserved from Haxe syntax, so the first declared is index 0, the next index 1 etc. If `e` or `constr` is null, or if enum `e` has no constructor named @@ -284,7 +273,7 @@ extern class Type { Returns a list of all constructors of enum `e` that require no arguments. - This may return the empty Array [] if all constructors of `e` require + This may return the empty Array `[]` if all constructors of `e` require arguments. Otherwise an instance of `e` constructed through each of its non- @@ -297,3 +286,18 @@ extern class Type { } + +/** + The different possible runtime types of a value. +**/ +enum ValueType { + TNull; + TInt; + TFloat; + TBool; + TObject; + TFunction; + TClass( c : Class ); + TEnum( e : Enum ); + TUnknown; +} diff --git a/std/UInt.hx b/std/UInt.hx index 458ce7f4..bdef243d 100644 --- a/std/UInt.hx +++ b/std/UInt.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,12 @@ * DEALINGS IN THE SOFTWARE. */ -#if ((flash || flash9doc || cs) && !doc_gen) +#if ((flash || flash9doc || cs || hl) && !doc_gen) /** - The unsigned Int type is only defined for Flash and C#. It's currently + The unsigned `Int` type is only defined for Flash and C#. It's currently handled the same as a normal Int. + + @see https://haxe.org/manual/types-basic-types.html **/ @:coreType @:notNull @@ -61,7 +63,7 @@ abstract UInt to Int from Int @:op(A&B) private static function and(lhs:UInt, rhs:UInt):UInt; @:op(A<>B) private static function shr(lhs:UInt, rhs:Int):UInt; + @:op(A>>B) private static inline function shr(lhs:UInt, rhs:Int):UInt return lhs >>> rhs; @:op(A>>>B) private static function ushr(lhs:UInt, rhs:Int):UInt; @:op(A>B) private static function gt(lhs:UInt, rhs:UInt):Bool; @@ -70,13 +72,13 @@ abstract UInt to Int from Int @:op(A<=B) private static function lte(lhs:UInt, rhs:UInt):Bool; @:op(A>B) private static function gtf(lhs:UInt, rhs:Float):Bool; - @:op(A>B) private static function gtf(lhs:Float, rhs:UInt):Bool; + @:op(A>B) private static function gtf2(lhs:Float, rhs:UInt):Bool; @:op(A>=B) private static function gtef(lhs:UInt, rhs:Float):Bool; - @:op(A>=B) private static function gtef(lhs:Float, rhs:UInt):Bool; + @:op(A>=B) private static function gtef2(lhs:Float, rhs:UInt):Bool; @:op(A> B) private static inline function shr(a:UInt, b:Int):UInt { - return a.toInt() >> b; + return a.toInt() >>> b; } @:op(A >>> B) private static inline function ushr(a:UInt, b:Int):UInt { @@ -202,12 +206,12 @@ abstract UInt(Int) from Int to Int { } @:commutative @:op(A == B) private static inline function equalsFloat(a:UInt, b:T):Bool { - return a.toFloat() == b; - } + return a.toFloat() == b; + } - @:commutative @:op(A != B) private static inline function notEqualsFloat(a:UInt, b:T):Bool { - return a.toFloat() != b; - } + @:commutative @:op(A != B) private static inline function notEqualsFloat(a:UInt, b:T):Bool { + return a.toFloat() != b; + } @:op(A >= B) private static inline function gteFloat(a:UInt, b:Float):Bool { return a.toFloat() >= b; diff --git a/std/Xml.hx b/std/Xml.hx index 0cd40d40..0a0f922e 100644 --- a/std/Xml.hx +++ b/std/Xml.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,26 +20,80 @@ * DEALINGS IN THE SOFTWARE. */ +/** + Xml node types. + + @see https://haxe.org/manual/std-Xml.html +**/ @:enum abstract XmlType(Int) { + /** + Represents an XML element type. + **/ var Element = 0; + /** + Represents XML parsed character data type. + **/ var PCData = 1; + /** + Represents XML character data type. + **/ var CData = 2; + /** + Represents an XML comment type. + **/ var Comment = 3; + /** + Represents an XML doctype element type. + **/ var DocType = 4; + /** + Represents an XML processing instruction type. + **/ var ProcessingInstruction = 5; + /** + Represents an XML document type. + **/ var Document = 6; } -class Xml { +/** + Crossplatform Xml API. - static public var Element(default,null) = XmlType.Element; - static public var PCData(default,null) = XmlType.PCData; - static public var CData(default,null) = XmlType.CData; - static public var Comment(default,null) = XmlType.Comment; - static public var DocType(default,null) = XmlType.DocType; - static public var ProcessingInstruction(default,null) = XmlType.ProcessingInstruction; - static public var Document(default,null) = XmlType.Document; + @see https://haxe.org/manual/std-Xml.html +**/ +class Xml { + /** + XML element type. + **/ + static public var Element(default,never) = XmlType.Element; + /** + XML parsed character data type. + **/ + static public var PCData(default,never) = XmlType.PCData; + /** + XML character data type. + **/ + static public var CData(default,never) = XmlType.CData; + /** + XML comment type. + **/ + static public var Comment(default,never) = XmlType.Comment; + /** + XML doctype element type. + **/ + static public var DocType(default,never) = XmlType.DocType; + /** + XML processing instruction type. + **/ + static public var ProcessingInstruction(default,never) = XmlType.ProcessingInstruction; + /** + XML document type. + **/ + static public var Document(default,never) = XmlType.Document; + /** + Parses the String into an Xml document. + **/ static public function parse( str : String ) : Xml { return haxe.xml.Parser.parse(str); } @@ -63,35 +117,35 @@ class Xml { /** Returns the parent object in the Xml hierarchy. - The parent can be [null], an Element or a Document. + The parent can be `null`, an Element or a Document. **/ public var parent(default, null) : Xml; var children:Array; var attributeMap:Map; - inline function get_nodeName() { + #if !cppia inline #end function get_nodeName() { if (nodeType != Element) { throw 'Bad node type, expected Element but found $nodeType'; } return nodeName; } - inline function set_nodeName(v) { + #if !cppia inline #end function set_nodeName(v) { if (nodeType != Element) { throw 'Bad node type, expected Element but found $nodeType'; } return this.nodeName = v; } - inline function get_nodeValue() { + #if !cppia inline #end function get_nodeValue() { if (nodeType == Document || nodeType == Element) { throw 'Bad node type, unexpected $nodeType'; } return nodeValue; } - inline function set_nodeValue(v) { + #if !cppia inline #end function set_nodeValue(v) { if (nodeType == Document || nodeType == Element) { throw 'Bad node type, unexpected $nodeType'; } @@ -160,7 +214,7 @@ class Xml { } /** - Get the given attribute of an Element node. Returns [null] if not found. + Get the given attribute of an Element node. Returns `null` if not found. Attributes are case-sensitive. **/ public function get( att : String ) : String { @@ -204,7 +258,7 @@ class Xml { } /** - Returns an [Iterator] on all the attribute names. + Returns an `Iterator` on all the attribute names. **/ public function attributes() : Iterator { if (nodeType != Element) { @@ -217,7 +271,7 @@ class Xml { Returns an iterator of all child nodes. Only works if the current node is an Element or a Document. **/ - public inline function iterator() : Iterator { + public #if !cppia inline #end function iterator() : Iterator { ensureElementType(); return children.iterator(); } @@ -245,7 +299,7 @@ class Xml { /** Returns the first child node. **/ - public inline function firstChild() : Xml { + public #if !cppia inline #end function firstChild() : Xml { ensureElementType(); return children[0]; } @@ -265,7 +319,7 @@ class Xml { /** Adds a child node to the Document or Element. - A child node can only be inside one given parent node, which is indicated by the [parent] property. + A child node can only be inside one given parent node, which is indicated by the `parent` property. If the child is already inside this Document or Element, it will be moved to the last position among the Document or Element's children. If the child node was previously inside a different node, it will be moved to this Document or Element. **/ @@ -309,7 +363,7 @@ class Xml { /** Returns a String representation of the Xml node. **/ - public inline function toString() : String { + public #if !cppia inline #end function toString() : String { return haxe.xml.Printer.print(this); } diff --git a/std/cpp/ArrayBase.hx b/std/cpp/ArrayBase.hx index 06e26eab..518db9a4 100644 --- a/std/cpp/ArrayBase.hx +++ b/std/cpp/ArrayBase.hx @@ -1,4 +1,25 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; extern class ArrayBase { diff --git a/std/cpp/AtomicInt.hx b/std/cpp/AtomicInt.hx new file mode 100644 index 00000000..cc88d8c0 --- /dev/null +++ b/std/cpp/AtomicInt.hx @@ -0,0 +1,18 @@ +package cpp; + +@:scalar @:coreType +extern abstract AtomicInt from(Int) to(Int) +{ + // returns true if exchange took place + @:native("_hx_atomic_exchange_if") + public static function exchangeIf(ioValue:Pointer, test:Int, newVal:Int) : Bool; + + // returns value before increment + @:native("_hx_atomic_inc") + public static function atomicInc(ioValue:Pointer) : Int; + + // returns value before decrement + @:native("_hx_atomic_dec") + public static function atomicDec(ioValue:Pointer) : Int; +} + diff --git a/std/cpp/AutoCast.hx b/std/cpp/AutoCast.hx new file mode 100644 index 00000000..f7fe302a --- /dev/null +++ b/std/cpp/AutoCast.hx @@ -0,0 +1,24 @@ +/* + * Copyright (C)2005-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 cpp; + +extern class AutoCast { } diff --git a/std/cpp/Callable.hx b/std/cpp/Callable.hx index 6488a1dc..a3c55b2a 100644 --- a/std/cpp/Callable.hx +++ b/std/cpp/Callable.hx @@ -1,22 +1,58 @@ +/* + * Copyright (C)2005-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 cpp; -#if cpp -typedef Callable = Function +@:noPackageRestrict @:callable +typedef CallableData = T; -#else - -@:noPackageRestrict -abstract Callable(T) +// The generator intercepts this type and converts it to a cpp.Function on cpp +@:noPackageRestrict @:callable +#if cpp extern #end +abstract Callable( CallableData ) { + inline public function new(inValue:T) this = inValue; public var call(get,never):T; + inline function get_call():T return this; - inline public function new(inValue:T) this = inValue; + #if cpp + @:from + inline static public function fromFunction( func:Function ) : Callable + return new Callable(cast func); + @:to + inline public function toFunction() : Function return cast this; - inline function get_call():T return this; -} + inline public static function getProcAddress(inModule:String, inFunction:String) : Function + return Function.getProcAddress(inModule, inFunction); -#end + inline public static function fromStaticFunction(inStaticFunction:T) : Callable + return Function.fromStaticFunction(inStaticFunction); + + inline public function lt(inOther:Callable):Bool return toFunction().lt(inOther.toFunction()); + inline public function leq(inOther:Callable):Bool return toFunction().leq(inOther.toFunction()); + inline public function gt(inOther:Callable):Bool return toFunction().gt(inOther.toFunction()); + inline public function geq(inOther:Callable):Bool return toFunction().geq(inOther.toFunction()); + #end +} diff --git a/std/cpp/CastCharStar.hx b/std/cpp/CastCharStar.hx index 0d6d2957..fb91fb98 100644 --- a/std/cpp/CastCharStar.hx +++ b/std/cpp/CastCharStar.hx @@ -1,4 +1,25 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; abstract CastCharStar( RawPointer ) to(RawPointer) { diff --git a/std/cpp/Char.hx b/std/cpp/Char.hx index bff39e9e..5524efa6 100644 --- a/std/cpp/Char.hx +++ b/std/cpp/Char.hx @@ -1,3 +1,24 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:coreType @:notNull @:runtimeValue abstract Char from Int to Int {} diff --git a/std/cpp/ConstCharStar.hx b/std/cpp/ConstCharStar.hx index 10818f95..5c7cd822 100644 --- a/std/cpp/ConstCharStar.hx +++ b/std/cpp/ConstCharStar.hx @@ -1,6 +1,27 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; -abstract ConstCharStar( RawConstPointer ) to(RawConstPointer) +@:extern abstract ConstCharStar( RawConstPointer ) to(RawConstPointer) { inline function new(s:String) this = untyped s.__s; diff --git a/std/cpp/ConstPointer.hx b/std/cpp/ConstPointer.hx index 27dd222c..3d1225c3 100644 --- a/std/cpp/ConstPointer.hx +++ b/std/cpp/ConstPointer.hx @@ -1,41 +1,70 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; -@:coreType @:include("cpp/Pointer.h") @:native("cpp.Pointer") -@:analyzer(no_simplification) +@:coreType @:include("cpp/Pointer.h") @:native("cpp.Pointer") @:analyzer(as_var) extern class ConstPointer { // ptr actually returns the pointer - not strictly a 'T' - for pointers to smart pointers // Use value or ref to get dereferenced value - public var ptr:T; + public var ptr:Star; - @:analyzer(no_simplification) - public var value(get,never):T; - public var raw(get,never):RawConstPointer; + public var value(get,never):T; - @:analyzer(no_simplification) - public function get_value() : T; + // Typecast to non-const + public var raw(get,never):RawPointer; - public function lt(inOther:Pointer):Bool; - public function leq(inOther:Pointer):Bool; - public function gt(inOther:Pointer):Bool; - public function geq(inOther:Pointer):Bool; + // const version + public var constRaw(get,never):RawConstPointer; + + public function get_value() : Reference; + + public function get_constRaw() : RawConstPointer; + public function get_raw() : RawPointer; + + + public function lt(inOther:ConstPointer):Bool; + public function leq(inOther:ConstPointer):Bool; + public function gt(inOther:ConstPointer):Bool; + public function geq(inOther:ConstPointer):Bool; + + public function setRaw(ptr:RawPointer) : Void; public static function fromRaw(ptr:RawConstPointer) : ConstPointer; + public static function fromPointer(inNativePointer:Dynamic) : ConstPointer; - public function reinterpret():Pointer; - public function rawCast():RawPointer; + public function reinterpret():Pointer; + + public function rawCast():RawPointer; - @:analyzer(no_simplification) - public function at(inIndex:Int):T; + public function at(inIndex:Int):Reference; - public function inc():ConstPointer; - public function dec():ConstPointer; - @:analyzer(no_simplification) - public function postIncVal():T; - public function incBy(inT:Int):ConstPointer; - public function add(inT:Int):ConstPointer; + public function inc():ConstPointer; + public function dec():ConstPointer; + public function postIncVal():Reference; + public function incBy(inT:Int):ConstPointer; + public function add(inT:Int):ConstPointer; } diff --git a/std/cpp/EnumBase.hx b/std/cpp/EnumBase.hx new file mode 100644 index 00000000..9cb66493 --- /dev/null +++ b/std/cpp/EnumBase.hx @@ -0,0 +1,31 @@ +package cpp; + +@:native("hx.EnumBase") +extern class EnumBase +{ + #if (hxcpp_api_level >= 330) + public function _hx_getIndex():Int; + public function _hx_getTag():String; + public function _hx_getParamCount():Int; + public function _hx_getParamI(inIndex:Int):Dynamic; + public function _hx_getParameters():Array; + + inline public function getIndex():Int return _hx_getIndex(); + inline public function getTag():String return _hx_getTag(); + inline public function getParamCount():Int return _hx_getParamCount(); + inline public function getParamI(inIndex:Int):Dynamic return _hx_getParamI(inIndex); + inline public function getParameters():Array return _hx_getParameters(); + #else + public function __EnumParams():Array; + public function __Tag():String; + public function __Index():Int; + + inline public function _hx_getIndex():Int return untyped __Index(); + inline public function _hx_getTag():String return untyped __Tag(); + inline public function _hx_getParamCount():Int return untyped __EnumParams()==null ? 0 : __EnumParams().length; + inline public function _hx_getParamI(inIndex:Int):Dynamic return untyped __EnumParams()[inIndex]; + inline public function _hx_getParameters():Array return __EnumParams()==null ? [] : __EnumParams(); + + #end +} + diff --git a/std/js/html/Point.hx b/std/cpp/FILE.hx similarity index 85% rename from std/js/html/Point.hx rename to std/cpp/FILE.hx index d7b11a49..f80371d9 100644 --- a/std/js/html/Point.hx +++ b/std/cpp/FILE.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,8 +20,9 @@ * DEALINGS IN THE SOFTWARE. */ -package js.html; +package cpp; + +@:include("stdio.h") +@:native(" ::cpp::Pointer") +extern class FILE { } -/** @deprecated Use DOMPoint instead. */ -@:deprecated("Point is deprecated, use DOMPoint instead") -typedef Point = DOMPoint; diff --git a/std/cpp/FastIterator.hx b/std/cpp/FastIterator.hx index bf31025e..b64f4179 100644 --- a/std/cpp/FastIterator.hx +++ b/std/cpp/FastIterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cpp/Finalizable.hx b/std/cpp/Finalizable.hx new file mode 100644 index 00000000..31a086ac --- /dev/null +++ b/std/cpp/Finalizable.hx @@ -0,0 +1,14 @@ +package cpp; + +// This is just a helper class. You do not actually need to inherit from this to use +// NativeGc.addFinalizable(this,inPin), you just need a function called "finalize" +class Finalizable +{ + public function new(inPin = false) + { + NativeGc.addFinalizable(this,inPin); + } + + public function finalize():Void { } +} + diff --git a/std/cpp/Float32.hx b/std/cpp/Float32.hx index 16fee0e1..7b852f03 100644 --- a/std/cpp/Float32.hx +++ b/std/cpp/Float32.hx @@ -1,3 +1,24 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:coreType @:notNull @:runtimeValue abstract Float32 from Float to Float {} diff --git a/std/cpp/Float64.hx b/std/cpp/Float64.hx index 122a7382..1bf957fd 100644 --- a/std/cpp/Float64.hx +++ b/std/cpp/Float64.hx @@ -1,3 +1,24 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:coreType @:notNull @:runtimeValue abstract Float64 from Float to Float {} diff --git a/std/cpp/Function.hx b/std/cpp/Function.hx index 0f266a51..dc1ad36e 100644 --- a/std/cpp/Function.hx +++ b/std/cpp/Function.hx @@ -1,21 +1,57 @@ +/* + * Copyright (C)2005-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 cpp; -@:coreType @:structAccess @:include("cpp/Pointer.h") -@:analyzer(no_simplification) -extern class Function +typedef FunctionData = T; + + +@:include("cpp/Pointer.h") @:callable +extern abstract Function( FunctionData ) { - public function new(d:Dynamic); + inline public function new(inValue:T) this = inValue; + + // Legacy Api + public var call(get,never):T; + inline function get_call():T return this; + - // Actually a function pointer, but can be called using haxe notation - public var call(default,null):T; + @:native("::cpp::Function_obj::getProcAddress") + @:extern static function nativeGetProcAddress(inModule:String, inFunction:String) : AutoCast return null; + inline public static function getProcAddress(inModule:String, inFunction:String) : Function + { + return cast nativeGetProcAddress(inModule, inFunction); + } - public static function getProcAddress(inModule:String, inFunction:String) : Function; - public static function fromStaticFunction(inStaticFunction:T) : Callable; + @:native("::cpp::Function_obj::fromStaticFunction") + @:extern static function nativeFromStaticFunction(inStaticFunction:T) : AutoCast return null; + inline public static function fromStaticFunction(inStaticFunction:T) : Callable + { + return cast nativeFromStaticFunction(inStaticFunction); + } - public function lt(inOther:Function):Bool; - public function leq(inOther:Function):Bool; - public function gt(inOther:Function):Bool; - public function geq(inOther:Function):Bool; + @:extern public function lt(inOther:Function):Bool return false; + @:extern public function leq(inOther:Function):Bool return false; + @:extern public function gt(inOther:Function):Bool return false; + @:extern public function geq(inOther:Function):Bool return false; } diff --git a/std/cpp/Int16.hx b/std/cpp/Int16.hx index 3a4e5d5a..0b67d0d3 100644 --- a/std/cpp/Int16.hx +++ b/std/cpp/Int16.hx @@ -1,3 +1,24 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:coreType @:notNull @:runtimeValue abstract Int16 from Int to Int {} diff --git a/std/cpp/Int32.hx b/std/cpp/Int32.hx index 200d91df..62549901 100644 --- a/std/cpp/Int32.hx +++ b/std/cpp/Int32.hx @@ -1,3 +1,24 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:coreType @:notNull @:runtimeValue abstract Int32 from Int to Int {} diff --git a/std/cpp/Int64.hx b/std/cpp/Int64.hx index 0ceed936..b10e041f 100644 --- a/std/cpp/Int64.hx +++ b/std/cpp/Int64.hx @@ -1,3 +1,24 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:coreType @:notNull @:runtimeValue abstract Int64 from Int to Int {} diff --git a/std/cpp/Int8.hx b/std/cpp/Int8.hx index bd195bc1..844cdd3e 100644 --- a/std/cpp/Int8.hx +++ b/std/cpp/Int8.hx @@ -1,3 +1,24 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:coreType @:notNull @:runtimeValue abstract Int8 from Int to Int {} diff --git a/std/cpp/Lib.hx b/std/cpp/Lib.hx index af6bcd0a..49978fa9 100644 --- a/std/cpp/Lib.hx +++ b/std/cpp/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,7 +21,11 @@ */ package cpp; - +/** + Platform-specific Cpp Library. Provides some platform-specific functions + for the C++ target, such as conversion from Haxe types to native types + and vice-versa. +**/ class Lib { /** @@ -43,18 +47,17 @@ class Lib { return untyped __global__.__hxcpp_unload_all_libraries(); } - @:analyzer(no_simplification) public static function _loadPrime( lib : String, prim : String, signature : String, quietFail = false ) : Dynamic { var factory:Callable< ConstCharStar -> Object > = - untyped __global__.__hxcpp_cast_get_proc_address(lib, prim + "__prime", quietFail); - if (factory!=null) - { - var func:Dynamic = factory.call(signature); - if (func==null && !quietFail) - throw '$prim does not have signature $signature'; - return func; - } - return null; + untyped __global__.__hxcpp_cast_get_proc_address(lib, prim + "__prime", quietFail); + if (factory!=null) + { + var func:Dynamic = factory.call(signature); + if (func==null && !quietFail) + throw '$prim does not have signature $signature'; + return func; + } + return null; } @@ -78,33 +81,37 @@ class Lib { return null; } - public static function rethrow(inExp:Dynamic) { throw inExp; } + @:extern @:noDebug @:native("HX_STACK_DO_RETHROW") + static function do_rethrow(inExp:Dynamic) { throw inExp; } + + @:noDebug #if(!cppia) inline #end + public static function rethrow(inExp:Dynamic) { do_rethrow(inExp); } public static function stringReference(inBytes:haxe.io.Bytes) : String - { - var result:String = ""; - untyped __global__.__hxcpp_string_of_bytes(inBytes.b, result, 0, 0, true); - return result; - } + { + var result:String = ""; + untyped __global__.__hxcpp_string_of_bytes(inBytes.b, result, 0, 0, true); + return result; + } public static function pushDllSearchPath(inPath:String) : Void - untyped __global__.__hxcpp_push_dll_path(inPath); + untyped __global__.__hxcpp_push_dll_path(inPath); public static function getDllExtension() : String - return untyped __global__.__hxcpp_get_dll_extension(); + return untyped __global__.__hxcpp_get_dll_extension(); public static function getBinDirectory() : String - return untyped __global__.__hxcpp_get_bin_dir(); + return untyped __global__.__hxcpp_get_bin_dir(); /** Returns bytes referencing the content of a string. - Use with extreme caution - changing constant strings will crash. - Changing one string can cause others to change unexpectedly. - Only really safe if you are using it read-only or if it comes from stringReference above + Use with extreme caution - changing constant strings will crash. + Changing one string can cause others to change unexpectedly. + Only really safe if you are using it read-only or if it comes from stringReference above **/ public inline static function bytesReference( s : String ) : haxe.io.Bytes { - var bytes = new haxe.io.BytesData(); - untyped bytes.__unsafeStringReference(s); + var bytes = new haxe.io.BytesData(); + untyped bytes.__unsafeStringReference(s); return haxe.io.Bytes.ofData(bytes); } @@ -137,9 +144,9 @@ class Lib { untyped __global__.__hxcpp_println(v); } - public static function setFloatFormat(inFormat:String):Void - { - untyped __global__.__hxcpp_set_float_format(inFormat); - } + public static function setFloatFormat(inFormat:String):Void + { + untyped __global__.__hxcpp_set_float_format(inFormat); + } } diff --git a/std/cpp/NativeArc.hx b/std/cpp/NativeArc.hx new file mode 100644 index 00000000..286b7147 --- /dev/null +++ b/std/cpp/NativeArc.hx @@ -0,0 +1,12 @@ +package cpp; + +extern class NativeArc +{ + @:native("(__bridge_transfer id)") + public static function _bridgeTransfer(ptr:cpp.RawPointer ):cpp.RawPointer; + + public static inline function bridgeTransfer(ptr:cpp.RawPointer ):T return cast _bridgeTransfer(ptr); +} + + + diff --git a/std/cpp/NativeArray.hx b/std/cpp/NativeArray.hx index 901d9e36..05bec622 100644 --- a/std/cpp/NativeArray.hx +++ b/std/cpp/NativeArray.hx @@ -1,8 +1,43 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; extern class NativeArray { - public static inline function blit( ioDestArray:Array, + #if cppia + public static inline function create(length:Int):Array + { + var result = new Array(); + NativeArray.setSize(result,length); + return result; + } + + #else + + @:native("_hx_create_array_length") + public static function create(length:Int):Array; + #end + + public static inline function blit( ioDestArray:Array, inDestElement:Int, inSourceArray:Array, inSourceElement:Int, inElementCount:Int ): Void { untyped ioDestArray.blit(inDestElement, inSourceArray, inSourceElement, inElementCount); @@ -12,22 +47,36 @@ extern class NativeArray { return untyped inArray; } + @:nativeStaticExtension + public static function reserve( inArray:Array,inElements:Int ) : Void { } + + @:nativeStaticExtension + public static function capacity( inArray:Array ) : Int { } + + @:nativeStaticExtension + public static function getElementSize( inArray:Array ) : Int { } + public static inline function address( inArray:Array,inIndex:Int ) : Pointer { return Pointer.arrayElem(inArray,inIndex); } - public static inline function setData( inArray:Array,inData:Pointer,inElementCount:Int ) : Void { - untyped inArray.setData(inData.raw,inElementCount); - } - public static inline function setUnmanagedData( inArray:Array,inData:Pointer,inElementCount:Int ) : Void { - untyped inArray.setUnmanagedData(inData.raw,inElementCount); - } + @:nativeStaticExtension + public static function setData( inArray:Array,inData:Pointer,inElementCount:Int ) : Void { } + @:nativeStaticExtension + public static function setUnmanagedData( inArray:Array,inData:ConstPointer,inElementCount:Int ) : Void { } - public static inline function zero( ioDestArray:Array, ?inFirst:Int, ?inElements:Int ) : Void { - untyped ioDestArray.zero(inFirst, inElements); - }; + @:nativeStaticExtension + public static function zero( ioDestArray:Array, ?inFirst:Int, ?inElements:Int ) : Void { }; + + @:nativeStaticExtension + public static function memcmp( inArrayA:Array, inArrayB:Array) : Int { } + @:native("_hx_reslove_virtual_array") + public static function resolveVirtualArray( inArray:Array) : Dynamic { } + + + #if cppia public static inline function unsafeGet( inDestArray:Array, inIndex:Int) : T { return untyped inDestArray.__unsafe_get(inIndex); } @@ -36,11 +85,21 @@ extern class NativeArray { return untyped ioDestArray.__unsafe_set(inIndex,inValue); } - public static inline function memcmp( inArrayA:Array, inArrayB:Array) : Int { - return untyped inArrayA.memcmp(inArrayB); - } - public static inline function setSize( ioArray:Array, inSize:Int) : Array { return untyped ioArray.__SetSizeExact(inSize); } + + #else + @:native("_hx_array_unsafe_get") + public static function unsafeGet( inDestArray:Array, inIndex:Int) : T { return untyped null; } + + @:native("_hx_array_unsafe_set") + public static inline function unsafeSet( ioDestArray:Array, inIndex:Int, inValue:T) : T { + return untyped ioDestArray.__unsafe_set(inIndex,inValue); + } + + @:native("_hx_array_set_size_exact") + public static function setSize( ioArray:Array, inSize:Int) : Array return null; + #end + } diff --git a/std/cpp/NativeFile.hx b/std/cpp/NativeFile.hx new file mode 100644 index 00000000..1caaf9b2 --- /dev/null +++ b/std/cpp/NativeFile.hx @@ -0,0 +1,64 @@ +package cpp; + +@:buildXml('') +extern class NativeFile +{ + @:extern @:native("_hx_std_file_open") + public static function file_open(fname:String,r:String) : Dynamic return null; + + @:extern @:native("_hx_std_file_close") + public static function file_close(handle:Dynamic) : Void { } + + + @:extern @:native("_hx_std_file_write") + public static function file_write(handle:Dynamic,s:haxe.io.BytesData,p:Int,n:Int) : Int return 0; + + + @:extern @:native("_hx_std_file_write_char") + public static function file_write_char(handle:Dynamic,c:Int) : Void { } + + + @:extern @:native("_hx_std_file_read") + public static function file_read(handle:Dynamic,s:haxe.io.BytesData,p:Int,n:Int) : Int return 0; + + + @:extern @:native("_hx_std_file_read_char") + public static function file_read_char(handle:Dynamic) : Int return 0; + + + @:extern @:native("_hx_std_file_seek") + public static function file_seek(handle:Dynamic,pos:Int,kind:Int) : Void { } + + + @:extern @:native("_hx_std_file_tell") + public static function file_tell(handle:Dynamic) : Int return 0; + + + @:extern @:native("_hx_std_file_eof") + public static function file_eof(handle:Dynamic) : Bool return false; + + + @:extern @:native("_hx_std_file_flush") + public static function file_flush(handle:Dynamic) : Void return null; + + + @:extern @:native("_hx_std_file_contents_string") + public static function file_contents_string(name:String) : String return null; + + + @:extern @:native("_hx_std_file_contents_bytes") + public static function file_contents_bytes(name:String) : haxe.io.BytesData return null; + + + @:extern @:native("_hx_std_file_stdin") + public static function file_stdin() : Dynamic return null; + + + @:extern @:native("_hx_std_file_stdout") + public static function file_stdout() : Dynamic return null; + + + @:extern @:native("_hx_std_file_stderr") + public static function file_stderr() : Dynamic return null; + +} diff --git a/std/cpp/NativeGc.hx b/std/cpp/NativeGc.hx new file mode 100644 index 00000000..efe65a94 --- /dev/null +++ b/std/cpp/NativeGc.hx @@ -0,0 +1,22 @@ +package cpp; + +extern class NativeGc +{ + @:native("__hxcpp_gc_mem_info") + static public function memInfo(inWhatInfo:Int) : Float return 0.0; + + @:native("_hx_allocate_extended") @:templatedCall + static public function allocateExtended(cls:Class, size:Int) : T return null; + + @:native("_hx_add_finalizable") + public static function addFinalizable( instance:{ function finalize():Void; }, inPin:Bool ): Void {} + + @:native("hx::InternalNew") + public static function allocGcBytesRaw( inBytes : Int, isContainer:Bool ): RawPointer return null; + + inline public static function allocGcBytes( inBytes : Int ): Pointer + { + return Pointer.fromRaw( allocGcBytesRaw(inBytes, false) ); + } +} + diff --git a/std/cpp/NativeMath.hx b/std/cpp/NativeMath.hx new file mode 100644 index 00000000..d6bfaa6a --- /dev/null +++ b/std/cpp/NativeMath.hx @@ -0,0 +1,31 @@ +package cpp; + +@:noPackageRestrict +extern class NativeMath +{ +#if (cpp && !cppia) + @:native("_hx_idiv") + public static function idiv(num:Int,denom:Int):Int return 0; + @:native("_hx_imod") + public static function imod(num:Int,denom:Int):Int return 0; + @:native("_hx_cast_int") + public static function castInt(f:Float):Int return 0; + @:native("_hx_fast_floor") + public static function fastInt(f:Float):Int return 0; + +#else + + public static inline function imod(num:Int,denom:Int):Int + return num%denom; + + public static inline function idiv(num:Int,denom:Int):Int + return Std.int(num/denom); + + public static inline function castInt(f:Float):Int + return Std.int(f); + + public static inline function fastInt(f:Float):Int + return Std.int(f); + +#end +} diff --git a/std/cpp/NativeProcess.hx b/std/cpp/NativeProcess.hx new file mode 100644 index 00000000..fcce680f --- /dev/null +++ b/std/cpp/NativeProcess.hx @@ -0,0 +1,40 @@ +package cpp; + +@:buildXml('') +extern class NativeProcess +{ + + @:extern @:native("_hx_std_process_run") + public static function process_run(cmd:String,vargs:Array) : Dynamic return null; + + @:extern @:native("_hx_std_process_run") + public static function process_run_with_show(cmd:String,vargs:Array,inShow:Int) : Dynamic return null; + + @:extern @:native("_hx_std_process_stdout_read") + public static function process_stdout_read(handle:Dynamic,buf:haxe.io.BytesData,pos:Int,len:Int) : Int return 0; + + + @:extern @:native("_hx_std_process_stderr_read") + public static function process_stderr_read(handle:Dynamic,buf:haxe.io.BytesData,pos:Int,len:Int) : Int return 0; + + + @:extern @:native("_hx_std_process_stdin_write") + public static function process_stdin_write(handle:Dynamic,buf:haxe.io.BytesData,pos:Int,len:Int) : Int return 0; + + + @:extern @:native("_hx_std_process_stdin_close") + public static function process_stdin_close(handle:Dynamic) : Void { } + + + @:extern @:native("_hx_std_process_exit") + public static function process_exit(handle:Dynamic) : Int return 0; + + + @:extern @:native("_hx_std_process_pid") + public static function process_pid(handle:Dynamic) : Int return 0; + + + @:extern @:native("_hx_std_process_close") + public static function process_close(handle:Dynamic) : Void { }; + +} diff --git a/std/cpp/NativeRandom.hx b/std/cpp/NativeRandom.hx new file mode 100644 index 00000000..3b6a41be --- /dev/null +++ b/std/cpp/NativeRandom.hx @@ -0,0 +1,23 @@ +package cpp; + +@:buildXml('') +extern class NativeRandom +{ + + @:extern @:native("_hx_std_random_new") + public static function random_new() : Dynamic return null; + + + @:extern @:native("_hx_std_random_set_seed") + public static function random_set_seed(handle:Dynamic,v:Int) : Void { } + + + @:extern @:native("_hx_std_random_int") + public static function random_int(handle:Dynamic,max:Int) : Int return 0; + + @:extern @:native("_hx_std_random_float") + public static function random_float(handle:Dynamic) : Float return 0.0; + + +} + diff --git a/std/cpp/NativeSocket.hx b/std/cpp/NativeSocket.hx new file mode 100644 index 00000000..01255564 --- /dev/null +++ b/std/cpp/NativeSocket.hx @@ -0,0 +1,155 @@ +package cpp; + +import sys.net.Socket; + +@:buildXml('') +extern class NativeSocket +{ + @:extern @:native("_hx_std_socket_init") + public static function socket_init() : Void { } + + + @:extern @:native("_hx_std_socket_new") + public static function socket_new(udp:Bool) : Dynamic return null; + + @:extern @:native("_hx_std_socket_new") + public static function socket_new_ip(udp:Bool,ipv6:Bool) : Dynamic return null; + + + @:extern @:native("_hx_std_socket_close") + public static function socket_close(handle:Dynamic) : Void { } + + + @:extern @:native("_hx_std_socket_bind") + public static function socket_bind(o:Dynamic,host:Int,port:Int) : Void { } + + @:extern @:native("_hx_std_socket_bind_ipv6") + public static function socket_bind_ipv6(o:Dynamic,host:haxe.io.BytesData,port:Int) : Void { } + + + @:extern @:native("_hx_std_socket_send_char") + public static function socket_send_char(o:Dynamic,c:Int) : Void { } + + + @:extern @:native("_hx_std_socket_send") + public static function socket_send(o:Dynamic,buf:haxe.io.BytesData,p:Int,l:Int) : Int return 0; + + + @:extern @:native("_hx_std_socket_recv") + public static function socket_recv(o:Dynamic,buf:haxe.io.BytesData,p:Int,l:Int) : Int return 0; + + + @:extern @:native("_hx_std_socket_recv_char") + public static function socket_recv_char(o:Dynamic) : Int return 0; + + + @:extern @:native("_hx_std_socket_write") + public static function socket_write(o:Dynamic,buf:haxe.io.BytesData) : Void { } + + + @:extern @:native("_hx_std_socket_read") + public static function socket_read(o:Dynamic) : haxe.io.BytesData return null; + + @:extern @:native("_hx_std_host_resolve_ipv6") + public static function host_resolve_ipv6(host:String) : haxe.io.BytesData return null; + + + @:extern @:native("_hx_std_host_resolve") + public static function host_resolve(host:String) : Int return 0; + + + @:extern @:native("_hx_std_host_to_string") + public static function host_to_string(ip:Int) : String return null; + + @:extern @:native("_hx_std_host_to_string_ipv6") + public static function host_to_string_ipv6(ipv6:haxe.io.BytesData) : String return null; + + + @:extern @:native("_hx_std_host_reverse") + public static function host_reverse(host:Int) : String return null; + + @:extern @:native("_hx_std_host_reverse_ipv6") + public static function host_reverse_ipv6(ipv6:haxe.io.BytesData) : String return null; + + + @:extern @:native("_hx_std_host_local") + public static function host_local() : String return null; + + inline public static function host_local_ipv6() : String return "::1"; + + + @:extern @:native("_hx_std_socket_connect") + public static function socket_connect(o:Dynamic,host:Int,port:Int) : Void { } + + @:extern @:native("_hx_std_socket_connect_ipv6") + public static function socket_connect_ipv6(o:Dynamic,host:haxe.io.BytesData,port:Int) : Void { } + + + @:extern @:native("_hx_std_socket_listen") + public static function socket_listen(o:Dynamic,n:Int) : Void { } + + + @:extern @:native("_hx_std_socket_select") + public static function socket_select(rs:Array,ws:Array,es:Array,timeout:Dynamic) : Array return null; + + + @:extern @:native("_hx_std_socket_fast_select") + public static function socket_fast_select(rs:Array,ws:Array,es:Array,timeout:Dynamic) : Void { } + + + @:extern @:native("_hx_std_socket_accept") + public static function socket_accept(o:Dynamic) : Dynamic return null; + + + @:extern @:native("_hx_std_socket_peer") + public static function socket_peer(o:Dynamic) : Array return null; + + + @:extern @:native("_hx_std_socket_host") + public static function socket_host(o:Dynamic) : Array return null; + + + @:extern @:native("_hx_std_socket_set_timeout") + public static function socket_set_timeout(o:Dynamic,t:Dynamic) : Void { } + + + @:extern @:native("_hx_std_socket_shutdown") + public static function socket_shutdown(o:Dynamic,r:Bool,w:Bool) : Void { } + + + @:extern @:native("_hx_std_socket_set_blocking") + public static function socket_set_blocking(o:Dynamic,b:Bool) : Void { } + + + @:extern @:native("_hx_std_socket_set_fast_send") + public static function socket_set_fast_send(o:Dynamic,b:Bool) : Void { } + + + @:extern @:native("_hx_std_socket_poll_alloc") + public static function socket_poll_alloc(nsocks:Int) : Dynamic return null; + + + @:extern @:native("_hx_std_socket_poll_prepare") + public static function socket_poll_prepare(pdata:Dynamic,rsocks:Array,wsocks:Array) : Array< Array > return null; + + + @:extern @:native("_hx_std_socket_poll_events") + public static function socket_poll_events(pdata:Dynamic,timeout:Float) : Void { } + + + @:extern @:native("_hx_std_socket_poll") + public static function socket_poll(socks:Array,pdata:Dynamic,timeout:Float) : Array return null; + + + @:extern @:native("_hx_std_socket_send_to") + public static function socket_send_to(o:Dynamic,buf:haxe.io.BytesData,p:Int,l:Int,inAddr:Dynamic) : Int return 0; + + + @:extern @:native("_hx_std_socket_recv_from") + public static function socket_recv_from(o:Dynamic,buf:haxe.io.BytesData,p:Int,l:Int,outAddr:Dynamic) : Int return 0; + + + +} + + diff --git a/std/cpp/NativeSsl.hx b/std/cpp/NativeSsl.hx new file mode 100644 index 00000000..24766599 --- /dev/null +++ b/std/cpp/NativeSsl.hx @@ -0,0 +1,114 @@ +package cpp; + +@:buildXml('') +extern class NativeSsl +{ + @:extern @:native("_hx_ssl_new") + public static function ssl_new( conf : Dynamic ) : Dynamic { } + + @:extern @:native("_hx_ssl_close") + public static function ssl_close( ctx : Dynamic ) : Void { } + + @:extern @:native("_hx_ssl_handshake") + public static function ssl_handshake( ctx : Dynamic ) : Void { } + + @:extern @:native("_hx_ssl_set_socket") + public static function ssl_set_socket( ctx : Dynamic, socket : Dynamic ) : Void { } + + @:extern @:native("_hx_ssl_set_hostname") + public static function ssl_set_hostname( ctx : Dynamic, hostname : String ) : Void { } + + @:extern @:native("_hx_ssl_get_peer_certificate") + public static function ssl_get_peer_certificate( ctx : Dynamic ) : Dynamic { } + + @:extern @:native("_hx_ssl_get_verify_result") + public static function ssl_get_verify_result( ctx : Dynamic ) : Bool { } + + @:extern @:native("_hx_ssl_send_char") + public static function ssl_send_char( ctx : Dynamic, char : Int ) : Void { } + + @:extern @:native("_hx_ssl_send") + public static function ssl_send( ctx : Dynamic, buf : haxe.io.BytesData, p : Int, l : Int ) : Int { } + + @:extern @:native("_hx_ssl_write") + public static function ssl_write( ctx : Dynamic, data : haxe.io.BytesData ) : Void { } + + @:extern @:native("_hx_ssl_recv_char") + public static function ssl_recv_char( ctx : Dynamic ) : Int { } + + @:extern @:native("_hx_ssl_recv") + public static function ssl_recv( ctx : Dynamic, buf : haxe.io.BytesData, p : Int, l : Int ) : Int { } + + @:extern @:native("_hx_ssl_read") + public static function ssl_read( ctx : Dynamic ) : haxe.io.BytesData { } + + @:extern @:native("_hx_ssl_conf_new") + public static function conf_new( server : Bool ) : Dynamic { } + + @:extern @:native("_hx_ssl_conf_close") + public static function conf_close( conf : Dynamic ) : Void { } + + @:extern @:native("_hx_ssl_conf_set_ca") + public static function conf_set_ca( conf : Dynamic, cert : Dynamic ) : Void { } + + @:extern @:native("_hx_ssl_conf_set_verify") + public static function conf_set_verify( conf : Dynamic, mode : Int ) : Void { } + + @:extern @:native("_hx_ssl_conf_set_cert") + public static function conf_set_cert( conf : Dynamic, cert : Dynamic, pkey : Dynamic ) : Void { } + + @:extern @:native("_hx_ssl_conf_set_servername_callback") + public static function conf_set_servername_callback( conf : Dynamic, cb : Dynamic ) : Void { } + + @:extern @:native("_hx_ssl_cert_load_defaults") + public static function cert_load_defaults() : Dynamic { } + + @:extern @:native("_hx_ssl_cert_load_file") + public static function cert_load_file( file : String ) : Dynamic { } + + @:extern @:native("_hx_ssl_cert_load_path") + public static function cert_load_path( path : String ) : Dynamic { } + + @:extern @:native("_hx_ssl_cert_get_subject") + public static function cert_get_subject( cert : Dynamic, field : String ) : String { } + + @:extern @:native("_hx_ssl_cert_get_issuer") + public static function cert_get_issuer( cert : Dynamic, field : String ) : String { } + + @:extern @:native("_hx_ssl_cert_get_altnames") + public static function cert_get_altnames( cert : Dynamic ) : Array { } + + @:extern @:native("_hx_ssl_cert_get_notbefore") + public static function cert_get_notbefore( cert : Dynamic ) : Array { } + + @:extern @:native("_hx_ssl_cert_get_notafter") + public static function cert_get_notafter( cert : Dynamic ) : Array { } + + @:extern @:native("_hx_ssl_cert_get_next") + public static function cert_get_next( cert : Dynamic ) : Dynamic { } + + @:extern @:native("_hx_ssl_cert_add_pem") + public static function cert_add_pem( cert : Dynamic, data : String ) : Dynamic { } + + @:extern @:native("_hx_ssl_cert_add_der") + public static function cert_add_der( cert : Dynamic, data : haxe.io.BytesData ) : Dynamic { } + + @:extern @:native("_hx_ssl_key_from_der") + public static function key_from_der( data : haxe.io.BytesData, pub : Bool ) : Dynamic { } + + @:extern @:native("_hx_ssl_key_from_pem") + public static function key_from_pem( data : String, pub : Bool, pass : String ) : Dynamic { } + + @:extern @:native("_hx_ssl_dgst_make") + public static function dgst_make( data : haxe.io.BytesData, alg : String ) : haxe.io.BytesData { } + + @:extern @:native("_hx_ssl_dgst_sign") + public static function dgst_sign( data : haxe.io.BytesData, key : Dynamic, alg : String ) : haxe.io.BytesData { } + + @:extern @:native("_hx_ssl_dgst_verify") + public static function dgst_verify( data : haxe.io.BytesData, sign : haxe.io.BytesData, key : Dynamic, alg : String ) : Bool { } + + @:extern @:native("_hx_ssl_init") + public static function init() : Void { } + +} diff --git a/std/cpp/NativeString.hx b/std/cpp/NativeString.hx index c0f9d5c9..b9e3ce53 100644 --- a/std/cpp/NativeString.hx +++ b/std/cpp/NativeString.hx @@ -1,4 +1,25 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; extern class NativeString { @@ -11,5 +32,31 @@ extern class NativeString { public static inline function fromPointer(inPtr:ConstPointer ) : String { return untyped __global__.String(inPtr.ptr); } + public static inline function fromGcPointer(inPtr:ConstPointer, inLen:Int ) : String { + return untyped __global__.String(inPtr.ptr,inLen); + } + + + @:native("_hx_string_compare") + public static function compare(inString0:String, inString1:String) : Int return 0; + + @:native("_hx_utf8_char_code_at") + public static function utf8CharCodeAt(inString:String, inIndex:Int) : Int return 0; + + @:native("_hx_utf8_length") + public static function utf8Length(inString:String) : Int return 1; + + @:native("_hx_utf8_is_valid") + public static function utf8IsValid(inString:String) : Bool return false; + + @:native("_hx_utf8_sub") + public static function utf8Sub(inString:String,charStart:Int, inLen:Int) : String return null; + + @:native("_hx_string_create") + public static function fromPointerLen(inPtr:ConstPointer, len:Int ) : String; + + @:native("_hx_utf8_decode_advance") + public static function utf8DecodeAdvance(reference:Char) : Int return 0; + } diff --git a/std/cpp/NativeSys.hx b/std/cpp/NativeSys.hx new file mode 100644 index 00000000..17e0383d --- /dev/null +++ b/std/cpp/NativeSys.hx @@ -0,0 +1,113 @@ +package cpp; + +@:buildXml('') +extern class NativeSys +{ + @:native("__hxcpp_print") + public static function print( v : Dynamic ) : Void { } + + @:native("__hxcpp_println") + public static function println( v : Dynamic ) : Void { } + + @:extern @:native("_hx_std_get_env") + public static function get_env(v:String) : String return null; + + + @:extern @:native("_hx_std_put_env") + public static function put_env(e:String,v:String) : Void { } + + + @:extern @:native("_hx_std_sys_sleep") + public static function sys_sleep(f:Float) : Void { } + + + @:extern @:native("_hx_std_set_time_locale") + public static function set_time_locale(l:String) : Bool return false; + + + @:extern @:native("_hx_std_get_cwd") + public static function get_cwd() : String return null; + + + @:extern @:native("_hx_std_set_cwd") + public static function set_cwd(d:String) : Void { } + + + @:extern @:native("_hx_std_sys_string") + public static function sys_string() : String return null; + + + @:extern @:native("_hx_std_sys_is64") + public static function sys_is64() : Bool return false; + + + @:extern @:native("_hx_std_sys_command") + public static function sys_command(cmd:String) : Int return 0; + + + @:extern @:native("_hx_std_sys_exit") + public static function sys_exit(code:Int) : Void { } + + + @:extern @:native("_hx_std_sys_exists") + public static function sys_exists(path:String) : Bool return false; + + + @:extern @:native("_hx_std_file_delete") + public static function file_delete(path:String) : Void { } + + + @:extern @:native("_hx_std_sys_rename") + public static function sys_rename(path:String,newname:String) : Bool return false; + + + @:extern @:native("_hx_std_sys_stat") + public static function sys_stat(path:String) : Dynamic return null; + + + @:extern @:native("_hx_std_sys_file_type") + public static function sys_file_type(path:String) : String return null; + + + @:extern @:native("_hx_std_sys_create_dir") + public static function sys_create_dir(path:String,mode:Int) : Bool return false; + + + @:extern @:native("_hx_std_sys_remove_dir") + public static function sys_remove_dir(path:String) : Void { } + + + @:extern @:native("_hx_std_sys_time") + public static function sys_time() : Float return 0; + + + @:extern @:native("_hx_std_sys_cpu_time") + public static function sys_cpu_time() : Float return 0; + + + @:extern @:native("_hx_std_sys_read_dir") + public static function sys_read_dir(p:String) : Array return null; + + + @:extern @:native("_hx_std_file_full_path") + public static function file_full_path(path:String) : String return null; + + + @:extern @:native("_hx_std_sys_exe_path") + public static function sys_exe_path() : String return null; + + + @:extern @:native("_hx_std_sys_env") + public static function sys_env() : Array return null; + + + @:extern @:native("_hx_std_sys_getch") + public static function sys_getch(b:Bool) : Int return 0; + + + @:extern @:native("_hx_std_sys_get_pid") + public static function sys_get_pid() : Int return 0; + +} + + diff --git a/std/cpp/NativeXml.hx b/std/cpp/NativeXml.hx index 9e2a6f22..0670d686 100644 --- a/std/cpp/NativeXml.hx +++ b/std/cpp/NativeXml.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,404 +21,480 @@ */ package cpp; -enum XmlType { +@:enum abstract XmlType(Int) { + /** + Represents an XML element type. + **/ + var Element = 0; + /** + Represents XML parsed character data type. + **/ + var PCData = 1; + /** + Represents XML character data type. + **/ + var CData = 2; + /** + Represents an XML comment type. + **/ + var Comment = 3; + /** + Represents an XML doctype element type. + **/ + var DocType = 4; + /** + Represents an XML processing instruction type. + **/ + var ProcessingInstruction = 5; + /** + Represents an XML document type. + **/ + var Document = 6; } -typedef NativeXml = Xml; +class NativeXmlState +{ + var cur : Xml; + + public function new(x:Xml) + { + x._children = new Array(); + cur = x; + } + + + @:keep + public function xml(name:String, att:Dynamic) + { + var x = new Xml(); + x._parent = cur; + x.nodeType = Xml.Element; + x._nodeName = name; + x._attributes = att; + x._children = new Array(); + cur.addChild(x); + cur = x; + } + + @:keep + public function cdata(text:String) + { + var x = new Xml(); + x._parent = cur; + x.nodeType = Xml.CData; + x._nodeValue = text; + cur.addChild(x); + } + + @:keep + public function pcdata(text:String) + { + var x = new Xml(); + x._parent = cur; + x.nodeType = Xml.PCData; + x._nodeValue = text; + cur.addChild(x); + } + + @:keep + public function comment(text:String) + { + var x = new Xml(); + x._parent = cur; + if( text.length>1 && StringTools.fastCodeAt(text,0) == 63 ) + { + x.nodeType = Xml.ProcessingInstruction; + text = text.substr(1, text.length - 2); + } + else + { + x.nodeType = Xml.Comment; + } + x._nodeValue = text; + cur.addChild(x); + } + + @:keep + public function doctype(text:String) + { + var x = new Xml(); + x._parent = cur; + x.nodeType = Xml.DocType; + x._nodeValue = text.substr(1); + cur.addChild(x); + } + + @:keep + public function done() + { + cur = cur._parent; + } +} + +private class NativeXmlIterator +{ + var cur = 0; + var children:Array; + + public function new(inChildren:Array) + { + children = inChildren; + cur = 0; + } + + public function hasNext() : Bool + { + var k = cur; + var l = children.length; + while( k < l ) + { + if (children[k].nodeType == Xml.Element) + break; + k += 1; + } + cur = k; + return k < l; + } + + public function next():Xml + { + var k = cur; + var l = children.length; + while( k < l ) + { + var n = children[k]; + k += 1; + if( n.nodeType == Xml.Element ) + { + cur = k; + return n; + } + } + return null; + } +} + +private class NativeXmlNamedIterator +{ + var cur = 0; + var children:Array; + var name:String; + + public function new(inChildren:Array, inName:String) + { + children = inChildren; + name = inName; + cur = 0; + } + + + public function hasNext() : Bool + { + var k = cur; + var l = children.length; + while( k < l ) + { + var n = children[k]; + if( n.nodeType == Xml.Element && n._nodeName == name ) + break; + k++; + } + cur = k; + return k < l; + } + + public function next():Xml + { + var k = cur; + var l = children.length; + while( k < l ) + { + var n = children[k]; + k++; + if( n.nodeType == Xml.Element && n._nodeName == name ) { + cur = k; + return n; + } + } + return null; + } +} + + + +@:cppInclude("./NativeXmlImport.cpp") +@:allow(cpp.NativeXmlState) @:allow(cpp.NativeXmlIterator) @:allow(cpp.NativeXmlNamedIterator) class Xml { - public static var Element(default,null) : XmlType; - public static var PCData(default,null) : XmlType; - public static var CData(default,null) : XmlType; - public static var Comment(default,null) : XmlType; - public static var DocType(default,null) : XmlType; - public static var ProcessingInstruction(default,null) : XmlType; - public static var Document(default,null) : XmlType; - - - private var _nodeName : String; - private var _nodeValue : String; - private var _attributes : Dynamic; - private var _children : Array; - private var _parent : Xml; - - function new() : Void { - } - - private static var _parse = cpp.Lib.load("std","parse_xml",2); - - @:analyzer(ignore) public static function parse( str : String ) : Xml { - var x = new Xml(); - x._children = new Array(); - var parser = { - cur : x, - xml : function(name,att) { - var x = new Xml(); - x._parent = untyped __this__.cur; - x.nodeType = Xml.Element; - x._nodeName = new String(name); - x._attributes = att; - x._children = new Array(); - untyped { - var i = 0; - __this__.cur.addChild(x); - __this__.cur = x; - } - }, - cdata : function(text) { - var x = new Xml(); - x._parent = untyped __this__.cur; - x.nodeType = Xml.CData; - x._nodeValue = new String(text); - untyped __this__.cur.addChild(x); - }, - pcdata : function(text) { - var x = new Xml(); - x._parent = untyped __this__.cur; - x.nodeType = Xml.PCData; - x._nodeValue = new String(text); - untyped __this__.cur.addChild(x); - }, - comment : function(text:String) { - var x = new Xml(); - x._parent = untyped __this__.cur; - if( untyped text.cca(0) == 63 ) { - x.nodeType = Xml.ProcessingInstruction; - text = new String(text); - text = text.substr(1, text.length - 2); - } else { - x.nodeType = Xml.Comment; - text = new String(text); - } - x._nodeValue = text; - untyped __this__.cur.addChild(x); - }, - doctype : function(text) { - var x = new Xml(); - x._parent = untyped __this__.cur; - x.nodeType = Xml.DocType; - x._nodeValue = (new String(text)).substr(1); - var p : Xml = untyped __this__.cur; - p.addChild(x); - }, - done : function() { - untyped __this__.cur = __this__.cur._parent; - } - }; - untyped _parse(str,parser); - x.nodeType = Xml.Document; - return x; - } - - - public static function createElement( name : String ) : Xml { - var r = new Xml(); - r.nodeType = Xml.Element; - r._nodeName = name; - r._attributes = null; - r._children = new Array(); - return r; - } - - public static function createPCData( data : String ) : Xml { - var r = new Xml(); - r.nodeType = Xml.PCData; - r._nodeValue = data; - return r; - } - - public static function createCData( data : String ) : Xml { - var r = new Xml(); - r.nodeType = Xml.CData; - r._nodeValue = data; - return r; - } - - public static function createComment( data : String ) : Xml { - var r = new Xml(); - r.nodeType = Xml.Comment; - r._nodeValue = data; - return r; - } - - public static function createDocType( data : String ) : Xml { - var r = new Xml(); - r.nodeType = Xml.DocType; - r._nodeValue = data; - return r; - } - - public static function createProcessingInstruction( data : String ) : Xml { - var r = new Xml(); - r.nodeType = Xml.ProcessingInstruction; - r._nodeValue = data; - return r; - } - - public static function createDocument() : Xml { - var r = new Xml(); - r.nodeType = Xml.Document; - r._children = new Array(); - return r; - } - - public var nodeType(default,null) : XmlType; - - public var nodeName(get,set) : String; - - public var nodeValue(get,set) : String; - - - private function get_nodeName() : String { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - return _nodeName; - } - - private function set_nodeName( n : String ) : String { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - return _nodeName = n; - } - - private function get_nodeValue() : String { - if( nodeType == Xml.Element || nodeType == Xml.Document ) - throw "bad nodeType"; - return _nodeValue; - } - - private function set_nodeValue( v : String ) : String { - if( nodeType == Xml.Element || nodeType == Xml.Document ) - throw "bad nodeType"; - return _nodeValue = v; - } - - public var parent(get,null) : Xml; - private function get_parent() : Xml { - return _parent; - } - - public function get( att : String ) : String { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - return Reflect.field( _attributes, att ); - } - - public function set( att : String, value : String ) : Void { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - if (_attributes==null) - _attributes = {}; - Reflect.setField (_attributes, att, value ); - return null; - } - - public function remove( att : String ) : Void{ - if( nodeType != Xml.Element ) - throw "bad nodeType"; - Reflect.deleteField( _attributes, att ); - return null; - } - - public function exists( att : String ) : Bool { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - return Reflect.hasField( _attributes, att ); - } - - public function attributes() : Iterator { - if( nodeType != Xml.Element ) - throw "bad nodeType"; - return Reflect.fields( _attributes ).iterator(); - } - - public function iterator() : Iterator { - if( _children == null ) - throw "bad nodetype"; + static inline var Element = XmlType.Element; + static inline var PCData = XmlType.PCData; + static inline var CData = XmlType.CData; + static inline var Comment = XmlType.Comment; + static inline var DocType = XmlType.DocType; + static inline var ProcessingInstruction = XmlType.ProcessingInstruction; + static inline var Document = XmlType.Document; + + + private var _nodeName : String; + private var _nodeValue : String; + private var _attributes : Dynamic; + private var _children : Array; + private var _parent : Xml; + + function new() : Void { + } + + @:extern @:native("parse_xml") + static function parse_xml(str:String, state:NativeXmlState) { } + + public static function parse( str : String ) : Xml + { + var x = new Xml(); + var state = new NativeXmlState(x); + parse_xml(str,state); + x.nodeType = Xml.Document; + return x; + } + + + public static function createElement( name : String ) : Xml { + var r = new Xml(); + r.nodeType = Xml.Element; + r._nodeName = name; + r._attributes = null; + r._children = new Array(); + return r; + } + + public static function createPCData( data : String ) : Xml { + var r = new Xml(); + r.nodeType = Xml.PCData; + r._nodeValue = data; + return r; + } + + public static function createCData( data : String ) : Xml { + var r = new Xml(); + r.nodeType = Xml.CData; + r._nodeValue = data; + return r; + } + + public static function createComment( data : String ) : Xml { + var r = new Xml(); + r.nodeType = Xml.Comment; + r._nodeValue = data; + return r; + } + + public static function createDocType( data : String ) : Xml { + var r = new Xml(); + r.nodeType = Xml.DocType; + r._nodeValue = data; + return r; + } + + public static function createProcessingInstruction( data : String ) : Xml { + var r = new Xml(); + r.nodeType = Xml.ProcessingInstruction; + r._nodeValue = data; + return r; + } + + public static function createDocument() : Xml { + var r = new Xml(); + r.nodeType = Xml.Document; + r._children = new Array(); + return r; + } + + public var nodeType(default,null) : XmlType; + + public var nodeName(get,set) : String; + + public var nodeValue(get,set) : String; + + + private function get_nodeName() : String { + if( nodeType != Xml.Element ) + throw "bad nodeType"; + return _nodeName; + } + + private function set_nodeName( n : String ) : String { + if( nodeType != Xml.Element ) + throw "bad nodeType"; + return _nodeName = n; + } + + private function get_nodeValue() : String { + if( nodeType == Xml.Element || nodeType == Xml.Document ) + throw "bad nodeType"; + return _nodeValue; + } + + private function set_nodeValue( v : String ) : String { + if( nodeType == Xml.Element || nodeType == Xml.Document ) + throw "bad nodeType"; + return _nodeValue = v; + } + + public var parent(get,null) : Xml; + private function get_parent() : Xml { + return _parent; + } + + public function get( att : String ) : String { + if( nodeType != Xml.Element ) + throw "bad nodeType"; + return Reflect.field( _attributes, att ); + } + + public function set( att : String, value : String ) : Void { + if( nodeType != Xml.Element ) + throw "bad nodeType"; + if (_attributes==null) + _attributes = {}; + Reflect.setField (_attributes, att, value ); + return null; + } + + public function remove( att : String ) : Void{ + if( nodeType != Xml.Element ) + throw "bad nodeType"; + Reflect.deleteField( _attributes, att ); + return null; + } + + public function exists( att : String ) : Bool { + if( nodeType != Xml.Element ) + throw "bad nodeType"; + return Reflect.hasField( _attributes, att ); + } + + public function attributes() : Iterator { + if( nodeType != Xml.Element ) + throw "bad nodeType"; + return Reflect.fields( _attributes ).iterator(); + } + + public function iterator() : Iterator { + if( _children == null ) + throw "bad nodetype"; return untyped _children.iterator(); - } - - - @:analyzer(ignore) public function elements(): Iterator { - if( _children == null ) - throw "bad nodetype"; - var children = _children; - return untyped { - cur: 0, - hasNext : function() { - var k:Int = __this__.cur; - var l = children.length; - while( k < l ) { - if( children[k].nodeType == Xml.Element ) - break; - k += 1; - } - __this__.cur = k; - return k < l; - }, - next : function() { - var k = __this__.cur; - var l = children.length; - while( k < l ) { - var n = children[k]; - k += 1; - if( n.nodeType == Xml.Element ) { - __this__.cur = k; - return n; - } - } - return null; - } - } - } - - @:analyzer(ignore) public function elementsNamed( name : String ) : Iterator { - if( _children == null ) - throw "bad nodetype"; - var children = _children; - return untyped { - cur: 0, - hasNext : function() { - var k = __this__.cur; - var l = children.length; - while( k < l ) { - var n = children[k]; - if( n.nodeType == Xml.Element && n._nodeName == name ) - break; - k++; - } - __this__.cur = k; - return k < l; - }, - next : function() { - var k = __this__.cur; - var l = children.length; - while( k < l ) { - var n = children[k]; - k++; - if( n.nodeType == Xml.Element && n._nodeName == name ) { - __this__.cur = k; - return n; - } - } - return null; - } - } - } - - public function firstChild() : Xml { - if( _children == null ) - throw "bad nodetype"; - return _children[0]; - } - - public function firstElement() : Xml { - if( _children == null ) - throw "bad nodetype"; - for( cur in 0..._children.length ) { - var n:Xml = _children[cur]; - if( n.nodeType == Xml.Element ) - return n; - } - return null; - } + } + + + public function elements(): Iterator + { + if( _children == null ) + throw "bad nodetype"; + return new NativeXmlIterator(_children); + } + + public function elementsNamed( name : String ) : Iterator + { + if( _children == null ) + throw "bad nodetype"; + return new NativeXmlNamedIterator(_children,name); + } + + public function firstChild() : Xml { + if( _children == null ) + throw "bad nodetype"; + return _children[0]; + } + + public function firstElement() : Xml { + if( _children == null ) + throw "bad nodetype"; + for( cur in 0..._children.length ) { + var n:Xml = _children[cur]; + if( n.nodeType == Xml.Element ) + return n; + } + return null; + } public function addChild( x : Xml ) : Void { - if( _children == null ) - throw "bad nodetype"; - if( x._parent != null ) x._parent._children.remove(x); - x._parent = this; - _children.push( x ); - return null; - } + if( _children == null ) + throw "bad nodetype"; + if( x._parent != null ) x._parent._children.remove(x); + x._parent = this; + _children.push( x ); + return null; + } public function removeChild( x : Xml ) : Bool { - if( _children == null ) - throw "bad nodetype"; - var b = _children.remove( x ); - if( b ) x._parent = null; - return b; - } - - public function insertChild( x : Xml, pos : Int ) : Void { - if( _children == null ) - throw "bad nodetype"; - if( x._parent != null ) x._parent._children.remove(x); - x._parent = this; - _children.insert( pos, x ); - return null; - } - - public function toString() : String { - var s = new StringBuf(); - toStringRec(s); - return s.toString(); - } - - private function toStringRec(s: StringBuf) : Void { - switch( nodeType ) { - case Xml.Document: - for( x in _children ) - x.toStringRec(s); - case Xml.Element: - s.addChar("<".code); - s.add(_nodeName); - for( k in Reflect.fields(_attributes) ) { - s.addChar(" ".code); - s.add(k); - s.addChar("=".code); - s.addChar("\"".code); - s.add(Reflect.field(_attributes,k)); - s.addChar("\"".code); - } - if( _children.length == 0 ) { - s.addChar("/".code); - s.addChar(">".code); - return; - } - s.addChar(">".code); - for( x in _children ) - x.toStringRec(s); - s.addChar("<".code); - s.addChar("/".code); - s.add(_nodeName); - s.addChar(">".code); - case Xml.PCData: - s.add(StringTools.htmlEscape(_nodeValue)); - case Xml.CData: - s.add(""); - case Xml.Comment: - s.add(""); - case Xml.DocType: - s.add(""); - case Xml.ProcessingInstruction: - s.add(""); - } - } - - static function __init__() : Void untyped { - PCData = Type.createEnum(XmlType,"__"); - Element = Type.createEnum(XmlType,"__"); - CData = Type.createEnum(XmlType,"__"); - Comment = Type.createEnum(XmlType,"__"); - DocType = Type.createEnum(XmlType,"__"); - ProcessingInstruction = Type.createEnum(XmlType,"__"); - Document = Type.createEnum(XmlType,"__"); - __global__.__hxcpp_enum_force(PCData , "pcdata", 0); - __global__.__hxcpp_enum_force(Element , "element", 1); - __global__.__hxcpp_enum_force(CData , "cdata", 2); - __global__.__hxcpp_enum_force(Comment , "comment", 3); - __global__.__hxcpp_enum_force(DocType , "doctype", 4); - __global__.__hxcpp_enum_force(ProcessingInstruction , "processingInstruction", 5); - __global__.__hxcpp_enum_force(Document , "document", 6); - } - -} \ No newline at end of file + if( _children == null ) + throw "bad nodetype"; + var b = _children.remove( x ); + if( b ) x._parent = null; + return b; + } + + public function insertChild( x : Xml, pos : Int ) : Void { + if( _children == null ) + throw "bad nodetype"; + if( x._parent != null ) x._parent._children.remove(x); + x._parent = this; + _children.insert( pos, x ); + return null; + } + + public function toString() : String { + var s = new StringBuf(); + toStringRec(s); + return s.toString(); + } + + private function toStringRec(s: StringBuf) : Void { + switch( nodeType ) { + case Xml.Document: + for( x in _children ) + x.toStringRec(s); + case Xml.Element: + s.addChar("<".code); + s.add(_nodeName); + for( k in Reflect.fields(_attributes) ) { + s.addChar(" ".code); + s.add(k); + s.addChar("=".code); + s.addChar("\"".code); + s.add(Reflect.field(_attributes,k)); + s.addChar("\"".code); + } + if( _children.length == 0 ) { + s.addChar("/".code); + s.addChar(">".code); + return; + } + s.addChar(">".code); + for( x in _children ) + x.toStringRec(s); + s.addChar("<".code); + s.addChar("/".code); + s.add(_nodeName); + s.addChar(">".code); + case Xml.PCData: + s.add(StringTools.htmlEscape(_nodeValue)); + case Xml.CData: + s.add(""); + case Xml.Comment: + s.add(""); + case Xml.DocType: + s.add(""); + case Xml.ProcessingInstruction: + s.add(""); + } + } + +} diff --git a/std/cpp/NativeXmlImport.cpp b/std/cpp/NativeXmlImport.cpp new file mode 100644 index 00000000..140f3988 --- /dev/null +++ b/std/cpp/NativeXmlImport.cpp @@ -0,0 +1,365 @@ + +#ifdef EPPC +#include +#else +#include +#endif + + +#ifndef HX_WINDOWS +# include +# undef strcmpi +# define strcmpi(a,b) strcasecmp(a,b) +#else +# include +#endif + + +// -------------- parsing -------------------------- + + +enum STATE { + IGNORE_SPACES, + BEGIN, + BEGIN_NODE, + TAG_NAME, + BODY, + ATTRIB_NAME, + EQUALS, + ATTVAL_BEGIN, + ATTRIB_VAL, + CHILDS, + CLOSE, + WAIT_END, + WAIT_END_RET, + PCDATA, + HEADER, + COMMENT, + DOCTYPE, + CDATA, +}; + +static void xml_error( const char *xml, const char *inWhere, int *line, String msg ) { + String b = HX_CSTRING("Xml parse error : ") + msg + HX_CSTRING(" at line ") + String(*line) + HX_CSTRING(" : "); + String where(inWhere); + + int l = where.length; + int nchars = 30; + if( inWhere != xml ) + b += HX_CSTRING("..."); + + if (where.length==0) + b+= HX_CSTRING(""); + else if (where.length= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || ( c >= '0' && c <= '9' ) || c == ':' || c == '.' || c == '_' || c == '-'; +} + +static void do_parse_xml( const char *xml, const char **lp, int *line, cpp::NativeXmlState callb, String parentname ) +{ + STATE state = BEGIN; + STATE next = BEGIN; + String aname; + hx::Anon attribs; + String nodename; + + const char *start = NULL; + const char *p = *lp; + char c = *p; + int nsubs = 0, nbrackets = 0; + while( c ) { + switch( state ) { + case IGNORE_SPACES: + switch( c ) { + case '\n': + case '\r': + case '\t': + case ' ': + break; + default: + state = next; + continue; + } + break; + case BEGIN: + switch( c ) { + case '<': + state = IGNORE_SPACES; + next = BEGIN_NODE; + break; + default: + start = p; + state = PCDATA; + continue; + } + break; + case PCDATA: + if( c == '<' ) { + callb->pcdata(String(start,p-start).dup()); + nsubs++; + state = IGNORE_SPACES; + next = BEGIN_NODE; + } + break; + case CDATA: + if( c == ']' && p[1] == ']' && p[2] == '>' ) { + callb->cdata(String(start,p-start).dup()); + nsubs++; + p += 2; + state = BEGIN; + } + break; + case BEGIN_NODE: + switch( c ) { + case '!': + if( p[1] == '[' ) { + p += 2; + if( (p[0] != 'C' && p[0] != 'c') || + (p[1] != 'D' && p[1] != 'd') || + (p[2] != 'A' && p[2] != 'a') || + (p[3] != 'T' && p[3] != 't') || + (p[4] != 'A' && p[4] != 'a') || + (p[5] != '[') ) + ERROR("Expected xml(nodename,attribs); + break; + case '>': + state = CHILDS; + nsubs++; + callb->xml(nodename,attribs); + break; + default: + state = ATTRIB_NAME; + start = p; + continue; + } + break; + case ATTRIB_NAME: + if( !is_valid_char(c) ) { + if( start == p ) + ERROR("Expected attribute name"); + aname = String(start,p-start).dup(); + if( attribs->__Field(aname,hx::paccDynamic) != null() ) + ERROR("Duplicate attribute"); + state = IGNORE_SPACES; + next = EQUALS; + continue; + } + break; + case EQUALS: + switch( c ) { + case '=': + state = IGNORE_SPACES; + next = ATTVAL_BEGIN; + break; + default: + ERROR("Expected ="); + } + break; + case ATTVAL_BEGIN: + switch( c ) { + case '"': + case '\'': + state = ATTRIB_VAL; + start = p; + break; + default: + ERROR("Expected \""); + } + break; + case ATTRIB_VAL: + if( c == *start ) { + attribs->Add( aname, String(start+1,p-start-1).dup() ); + state = IGNORE_SPACES; + next = BODY; + } + break; + case CHILDS: + *lp = p; + do_parse_xml(xml,lp,line,callb,nodename); + p = *lp; + start = p; + state = BEGIN; + break; + case WAIT_END: + switch( c ) { + case '>': + callb->done(); + state = BEGIN; + break; + default : + ERROR("Expected >"); + } + break; + case WAIT_END_RET: + switch( c ) { + case '>': + if( nsubs == 0 ) + callb->pcdata(HX_CSTRING("")); + *lp = p; + return; + default : + ERROR("Expected >"); + } + break; + case CLOSE: + if( !is_valid_char(c) ) { + if( start == p ) + ERROR("Expected node name"); + { + String v = String(start,p - start).dup(); + if( strcmpi(parentname.__s,v.__s) != 0 ) { + ERRORSTR(HX_CSTRING("Expected ")); + } + } + state = IGNORE_SPACES; + next = WAIT_END_RET; + continue; + } + break; + case COMMENT: + if( c == '-' && p[1] == '-' && p[2] == '>' ) { + callb->comment(String(start,p-start).dup()); + p += 2; + state = BEGIN; + } + break; + case DOCTYPE: + if( c == '[' ) + nbrackets++; + else if( c == ']' ) + nbrackets--; + else if( c == '>' && nbrackets == 0 ) { + callb->doctype(String(start,p-start).dup()); + state = BEGIN; + } + break; + case HEADER: + if( c == '?' && p[1] == '>' ) { + p++; + callb->comment(String(start,p-start).dup()); + state = BEGIN; + } + break; + } + c = *++p; + if( c == '\n' ) + (*line)++; + } + if( state == BEGIN ) { + start = p; + state = PCDATA; + } + if( parentname.__s == 0 && state == PCDATA ) { + if( p != start || nsubs == 0 ) + callb->pcdata(String(start,p-start).dup()); + return; + } + ERROR("Unexpected end"); +} + +// ---------------------------------------------- + +/** + +

Xml

+

+ The standard event-driven XML parser. +

+
+**/ + +/** + parse_xml : xml:string -> events:object -> void + + The [parse_xml] parse a string and for each parsed element call the + corresponding object method in [events] : +
    +
  • [void xml( name : string, attribs : object)] when an XML node is found
  • +
  • [void done()] when an XML node is closed
  • +
  • [void pcdata(string)] when PCData chars found
  • +
  • [void cdata(string)] when a CData session is found
  • +
  • [void comment(string)] when some comment or special header is found
  • +
+ You can then implement the events so they build the appropriate XML data + structure needed by your language. +
+**/ +static void parse_xml( String str, cpp::NativeXmlState state ) +{ + int line = 0; + const char *p = str.__s; + // skip BOM + if( p[0] == (char)0xEF && p[1] == (char)0xBB && p[2] == (char)0xBF ) + p += 3; + do_parse_xml(p,&p,&line,state,String()); +} + + diff --git a/std/cpp/Object.hx b/std/cpp/Object.hx index 26697092..0a038696 100644 --- a/std/cpp/Object.hx +++ b/std/cpp/Object.hx @@ -1,16 +1,26 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; -@:native("::hx::Object *") -extern class HxObjectPtr -{ - @:native("hx::DynamicPtr") - static function fromDynamic(x:Dynamic):Object; - @:native("Dynamic") - static function toDynamic(x:Object):Dynamic; -} +@:noPackageRestrict +typedef Object = Dynamic; -@:extern -abstract Object(HxObjectPtr) { - @:from public inline static function from(x:Dynamic):Object return HxObjectPtr.fromDynamic(x); - @:to public inline static function to(inVal:HxObjectPtr):Dynamic return HxObjectPtr.toDynamic(inVal); -} diff --git a/std/cpp/ObjectType.hx b/std/cpp/ObjectType.hx new file mode 100644 index 00000000..b527fc2a --- /dev/null +++ b/std/cpp/ObjectType.hx @@ -0,0 +1,19 @@ +package cpp; + +extern class ObjectType +{ + public inline static var vtUnknown = -1; + public inline static var vtInt = 0xff; + public inline static var vtNull = 0; + public inline static var vtFloat = 1; + public inline static var vtBool = 2; + public inline static var vtString = 3; + public inline static var vtObject = 4; + public inline static var vtArray = 5; + public inline static var vtFunction = 6; + public inline static var vtEnum = 7; + public inline static var vtClass = 8; + public inline static var vtInt64 = 9; + public inline static var vtAbstractBase = 0x100; +} + diff --git a/std/cpp/Pointer.hx b/std/cpp/Pointer.hx index de4aa7f4..98cc1323 100644 --- a/std/cpp/Pointer.hx +++ b/std/cpp/Pointer.hx @@ -1,39 +1,87 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; + +import haxe.extern.AsVar; @:coreType -@:analyzer(no_simplification) +@:analyzer(as_var) extern class Pointer extends ConstPointer implements ArrayAccess { - @:analyzer(no_simplification) - public var ref(get,set):T; + public var ref(get,set):Reference; - @:analyzer(no_simplification) - public function get_ref() : T; - @:analyzer(no_simplification) - public function set_ref(t:T) : T; + public function get_ref() : Reference; + public function set_ref(t:T) : Reference; + public function setAt(inIndex:Int, value:T):Void; public static function fromRaw(ptr:RawPointer) : Pointer; - public static function fromHandle(inHandle:Dynamic,?inKind:String) : Pointer; + @:native("::cpp::Pointer_obj::fromHandle") + static function nativeFromHandle(inHandle:Dynamic,?inKind:String):AutoCast; + inline public static function fromHandle(inHandle:Dynamic,?inKind:String) : Pointer + { + return cast nativeFromHandle(inHandle,inKind); + } public static function fromPointer(inNativePointer:Dynamic) : Pointer; - public static function addressOf(inVariable:T) : Pointer; + public static function addressOf(inVariable:cpp.Reference) : Pointer; + + public static function endOf(inVariable:T) : Pointer; + + @:native("::cpp::Pointer_obj::arrayElem") + static function nativeArrayElem(array:Array, inElem:Int):AutoCast; + inline static function arrayElem(array:Array, inElem:Int):Pointer + { + return cast nativeArrayElem(array,inElem); + } + + @:native("::cpp::Pointer_obj::ofArray") + static function nativeOfArray(array:Array):AutoCast; + inline public static function ofArray(array:Array):Pointer + { + return cast nativeOfArray(array); + } + + inline public function toUnmanagedArray(elementCount:Int) : Array + { + var result = new Array(); + NativeArray.setUnmanagedData(result,this,elementCount); + return result; + } - public static function arrayElem(array:Array, inElem:Int):Pointer; + inline public function toUnmanagedVector(elementCount:Int) : haxe.ds.Vector + return cast toUnmanagedArray(elementCount); - public function get_raw() : RawPointer; - override public function inc():Pointer; - override public function dec():Pointer; - override public function incBy(inT:Int):Pointer; - override public function add(inT:Int):Pointer; + override public function inc():Pointer; + override public function dec():Pointer; + override public function incBy(inT:Int):Pointer; + override public function add(inT:Int):Pointer; - @:analyzer(no_simplification) - public function postIncRef():T; + public function postIncRef():Reference; - public function destroy():Void; - public function destroyArray():Void; + public function destroy():Void; + public function destroyArray():Void; } diff --git a/std/cpp/Prime.hx b/std/cpp/Prime.hx index 5f601907..b0ce509f 100644 --- a/std/cpp/Prime.hx +++ b/std/cpp/Prime.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -32,7 +32,6 @@ class Prime { #if (!macro && cpp) - @:analyzer(no_simplification) public static function _loadPrime( lib : String, prim : String, signature : String, quietFail = false ) : Dynamic { var factory:Callable< ConstCharStar -> Object > = untyped __global__.__hxcpp_cast_get_proc_address(lib, prim + "__prime", quietFail); @@ -76,7 +75,7 @@ class Prime { #if neko var init = neko.Lib.load(inModuleName, "neko_init", 5); - if (init != null) + if (init != null) { init( function(s) return new String(s), function(len:Int) { var r = []; if (len > 0) r[len - 1] = null; return r; }, @@ -96,10 +95,11 @@ class Prime { var parts = inSig.split(""); if (parts.length<1) throw "Invalid function signature " + inSig; + var argCount = parts.length-1; var cppMode = Context.defined("cpp"); - var typeString = parts.length==1 ? codeToType("v",cppMode) : codeToType(parts.shift(),cppMode); + var typeString = parts.length==1 ? "Void" : codeToType(parts.shift(),cppMode); for(p in parts) typeString += "->" + codeToType(p,cppMode); @@ -111,11 +111,10 @@ class Prime { } else { - var len = parts.length; - if (len>5) - len = -1; + if (argCount>5) + argCount = -1; var lazy = inAllowFail ? "loadLazy" : "load"; - var expr = 'new cpp.Callable<$typeString>(neko.Lib.$lazy("$inModule","$inName",$len))'; + var expr = 'new cpp.Callable<$typeString>(neko.Lib.$lazy("$inModule","$inName",$argCount))'; return Context.parse( expr, Context.currentPos() ); } } diff --git a/std/cpp/Random.hx b/std/cpp/Random.hx index 5821def7..3b47b887 100644 --- a/std/cpp/Random.hx +++ b/std/cpp/Random.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,24 +26,19 @@ class Random { var r : Dynamic; public function new() { - r = random_new(); + r = cpp.NativeRandom.random_new(); } public function setSeed( s : Int ) { - random_set_seed(r,s); + cpp.NativeRandom.random_set_seed(r,s); } public function int( max : Int ) : Int { - return random_int(r,max); + return cpp.NativeRandom.random_int(r,max); } public function float() : Float { - return random_float(r); + return cpp.NativeRandom.random_float(r); } - static var random_new = Lib.load("std","random_new",0); - static var random_set_seed = Lib.load("std","random_set_seed",2); - static var random_int = Lib.load("std","random_int",2); - static var random_float = Lib.load("std","random_float",1); - } diff --git a/std/cpp/RawConstPointer.hx b/std/cpp/RawConstPointer.hx index 80a51ade..426b0307 100644 --- a/std/cpp/RawConstPointer.hx +++ b/std/cpp/RawConstPointer.hx @@ -1,6 +1,29 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:unreflective -extern class RawConstPointer +extern class RawConstPointer implements ArrayAccess { + @:native("hx::AddressOf") + public static function addressOf(t:T) : RawConstPointer; } diff --git a/std/cpp/RawPointer.hx b/std/cpp/RawPointer.hx index 17bdc048..2a9381bb 100644 --- a/std/cpp/RawPointer.hx +++ b/std/cpp/RawPointer.hx @@ -1,6 +1,29 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:unreflective extern class RawPointer extends RawConstPointer { + @:native("hx::AddressOf") + public static function addressOf(t:T) : RawPointer; } diff --git a/std/js/html/BarInfo.hx b/std/cpp/Reference.hx similarity index 85% rename from std/js/html/BarInfo.hx rename to std/cpp/Reference.hx index 7dbef5e2..884608cd 100644 --- a/std/js/html/BarInfo.hx +++ b/std/cpp/Reference.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,9 +19,10 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +package cpp; + +// Allows haxe to type result correctly, and hxcpp can recognise this and prevent +// unwanted casting +typedef Reference = T; -package js.html; -/** @deprecated Use BarProp instead. */ -@:deprecated("BarInfo is deprecated, use BarProp instead") -typedef BarInfo = BarProp; diff --git a/std/cpp/SizeT.hx b/std/cpp/SizeT.hx new file mode 100644 index 00000000..c476e72c --- /dev/null +++ b/std/cpp/SizeT.hx @@ -0,0 +1,27 @@ +/* + * Copyright (C)2005-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 cpp; + +@:native("size_t") +@:scalar @:coreType @:notNull +extern abstract SizeT from(Int) to(Int) { +} diff --git a/std/js/html/DOMWindow.hx b/std/cpp/Star.hx similarity index 85% rename from std/js/html/DOMWindow.hx rename to std/cpp/Star.hx index b87ce198..7adb8404 100644 --- a/std/js/html/DOMWindow.hx +++ b/std/cpp/Star.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,9 +19,9 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +package cpp; + +// Allows haxe to type result correctly, and hxcpp can recognise this use the correct type +typedef Star = T; -package js.html; -/** @deprecated Use Window instead. */ -@:deprecated("DOMWindow is deprecated, use Window instead") -typedef DOMWindow = Window; diff --git a/std/cpp/StdString.hx b/std/cpp/StdString.hx new file mode 100644 index 00000000..f640dc30 --- /dev/null +++ b/std/cpp/StdString.hx @@ -0,0 +1,22 @@ +package cpp; + +using cpp.NativeString; + +@:native("hx::StdString") +@:include("hx/StdString.h") +@:stackOnly +@:structAccess +extern class StdString extends StdStringRef +{ + @:extern @:native("std::string::npos") + public static var npos(default,null):Int; + + //public function new(inData:StdStringData); + + @:native("hx::StdString") + static public function ofString(s:String) : StdString; + //public function toString():String; + //public function find(s:String):Int; + //public function substr(pos:Int, len:Int):StdString; +} + diff --git a/std/cpp/StdStringRef.hx b/std/cpp/StdStringRef.hx new file mode 100644 index 00000000..63dd8f27 --- /dev/null +++ b/std/cpp/StdStringRef.hx @@ -0,0 +1,17 @@ +package cpp; + +using cpp.NativeString; + +@:native("hx::StdString const &") +@:include("hx/StdString.h") +@:structAccess +extern class StdStringRef +{ + public function c_str() : ConstPointer; + public function size() : Int; + public function find(s:String):Int; + public function substr(pos:Int, len:Int):StdString; + public function toString():String; + public function toStdString():StdString; +} + diff --git a/std/cpp/Stdio.hx b/std/cpp/Stdio.hx new file mode 100644 index 00000000..6e09a660 --- /dev/null +++ b/std/cpp/Stdio.hx @@ -0,0 +1,45 @@ +/* + * Copyright (C)2005-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 cpp; + +import haxe.extern.Rest; + +@:include("stdio.h") +extern class Stdio +{ + @:native("printf") + public static function printf(format:ConstCharStar, rest:Rest):Void; + + @:native("fopen") + public static function fopen(filename:ConstCharStar, mode:ConstCharStar) : FILE; + + @:native("fwrite") + public static function fwrite(data:RawPointer, elemSize:SizeT, elemCount:SizeT, file:FILE ) : SizeT; + + @:native("fclose") + public static function fclose(file:FILE) : Int; + + + @:native("fprintf") + public static function fprintf(file:FILE,format:ConstCharStar, rest:Rest):Void; +} + diff --git a/std/cpp/Stdlib.hx b/std/cpp/Stdlib.hx new file mode 100644 index 00000000..12a46143 --- /dev/null +++ b/std/cpp/Stdlib.hx @@ -0,0 +1,62 @@ +/* + * Copyright (C)2005-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 cpp; + +@:include("stdlib.h") +extern class Stdlib +{ + @:native("malloc") + public static function nativeMalloc(bytes:Int) : cpp.RawPointer return null; + @:native("calloc") + public static function nativeCalloc(bytes:Int) : cpp.RawPointer return null; + @:native("realloc") + public static function nativeRealloc(inPtr:cpp.RawPointer,bytes:Int) : cpp.RawPointer return null; + @:native("free") + public static function nativeFree(ptr:cpp.RawPointer) : Void { } + @:native("memcpy") + public static function nativeMemcpy(dest:cpp.RawPointer, src:cpp.RawConstPointer, bytes:Int) : Void { } + + @:native("hx::ClassSizeOf") @:templatedCall + public static function sizeof(t:T) : Int { } + + inline public static function memcpy(dest:cpp.Pointer, src:cpp.ConstPointer, bytes:Int) : Void + nativeMemcpy(cast dest.ptr, cast src.ptr, bytes); + + inline public static function malloc(bytes:Int) : cpp.Pointer + return cast nativeMalloc(bytes); + + inline public static function calloc(bytes:Int) : cpp.Pointer + return cast nativeCalloc(bytes); + + inline public static function realloc(ioPtr:cpp.Pointer, bytes:Int) : Void + ioPtr.setRaw( nativeRealloc(cast ioPtr.ptr, bytes) ); + + inline public static function free(ptr:cpp.Pointer) : Void + { + if (ptr!=null) + { + nativeFree(cast ptr.ptr); + ptr.ptr = null; + } + } +} diff --git a/std/cpp/UInt16.hx b/std/cpp/UInt16.hx index 5cc859b5..9a82bbb4 100644 --- a/std/cpp/UInt16.hx +++ b/std/cpp/UInt16.hx @@ -1,3 +1,24 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:coreType @:notNull @:runtimeValue abstract UInt16 from Int to Int {} diff --git a/std/cpp/UInt32.hx b/std/cpp/UInt32.hx index 825497bc..0188d5b9 100644 --- a/std/cpp/UInt32.hx +++ b/std/cpp/UInt32.hx @@ -1,3 +1,24 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:coreType @:notNull @:runtimeValue abstract UInt32 from Int to Int {} diff --git a/std/cpp/UInt64.hx b/std/cpp/UInt64.hx index ee729164..6662d6a6 100644 --- a/std/cpp/UInt64.hx +++ b/std/cpp/UInt64.hx @@ -1,3 +1,24 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:coreType @:notNull @:runtimeValue abstract UInt64 from Int to Int {} diff --git a/std/cpp/UInt8.hx b/std/cpp/UInt8.hx index 5514225e..f32df37c 100644 --- a/std/cpp/UInt8.hx +++ b/std/cpp/UInt8.hx @@ -1,3 +1,24 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:coreType @:notNull @:runtimeValue abstract UInt8 from Int to Int {} diff --git a/std/cpp/VarArg.hx b/std/cpp/VarArg.hx new file mode 100644 index 00000000..655587fe --- /dev/null +++ b/std/cpp/VarArg.hx @@ -0,0 +1,28 @@ +/* + * Copyright (C)2005-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 cpp; + +// Allows haxe to type params correctly, and hxcpp can recognise this use the correct type +typedef VarArg = Dynamic; + + + diff --git a/std/cpp/VirtualArray.hx b/std/cpp/VirtualArray.hx new file mode 100644 index 00000000..263ab752 --- /dev/null +++ b/std/cpp/VirtualArray.hx @@ -0,0 +1,76 @@ +package cpp; + +@:native("cpp::VirtualArray") +@:coreType extern class NativeVirtualArray implements ArrayAccess +{ + public function new() : Void; + public var length(get,null) : Int; + // concat( a:Array ) : Array ? + public function concat( a : VirtualArray ) : VirtualArray; + public function join( sep : String ) : String; + public function pop() : Dynamic; + public function push(x : Dynamic) : Int; + public function reverse() : Void; + public function shift() : Dynamic; + public function slice( pos : Int, ?end : Int ) : VirtualArray; + public function sort( f : Dynamic -> Dynamic -> Int ) : Void; + public function splice( pos : Int, len : Int ) : VirtualArray; + public function toString() : String; + public function unshift( x : Dynamic ) : Void; + public function insert( pos : Int, x : Dynamic ) : Void; + public function remove( x : Dynamic ) : Bool; + public function indexOf( x : Dynamic, ?fromIndex:Int ) : Int; + public function lastIndexOf( x : Dynamic, ?fromIndex:Int ) : Int; + public function copy() : VirtualArray; + public function iterator() : Iterator; + public function map( f : Dynamic -> S ) : VirtualArray; + public function filter( f : Dynamic -> Bool ) : VirtualArray; +} + + +abstract VirtualArray(NativeVirtualArray) +{ + // Add these two functions... + @:from @:extern inline static public function fromArray(a:Array) : VirtualArray + return untyped a; + @:to @:extern inline public function toArray() : Array + return untyped this; + + + + + // The rest is just boiler-plate + inline public function new() this=new NativeVirtualArray(); + + @:extern @:arrayAccess inline function get(idx:Int) : Dynamic + return untyped this[idx]; + + @:extern @:arrayAccess inline function set(pos:Int, value:T ) : T + return untyped this[idx] = value; + + public var length(get,never) : Int; + @:extern inline public function get_length() : Int return this.length; + + + + // concat( a:Array ) : Array ? + @:extern inline public function concat( a : VirtualArray ) : VirtualArray return this.concat(a); + @:extern inline public function join( sep : String ) : String return this.join(sep); + @:extern inline public function pop() : Dynamic return this.pop(); + @:extern inline public function push(x : Dynamic) : Int return this.push(x); + @:extern inline public function reverse() : Void this.reverse(); + @:extern inline public function shift() : Dynamic return this.shift(); + @:extern inline public function slice( pos : Int, ?end : Int ) : VirtualArray return this.slice(pos,end); + @:extern inline public function sort( f : Dynamic -> Dynamic -> Int ) : Void this.sort(f); + @:extern inline public function splice( pos : Int, len : Int ) : VirtualArray return this.slice(pos,len); + @:extern inline public function unshift( x : Dynamic ) : Void this.unshift(x); + @:extern inline public function insert( pos : Int, x : Dynamic ) : Void this.insert(pos,x); + @:extern inline public function remove( x : Dynamic ) : Bool return this.remove(x); + @:extern inline public function indexOf( x : Dynamic, ?fromIndex:Int ) : Int return this.indexOf(x,fromIndex); + @:extern inline public function lastIndexOf( x : Dynamic, ?fromIndex:Int ) : Int return this.lastIndexOf(x,fromIndex); + @:extern inline public function copy() : VirtualArray return this.copy(); + @:extern inline public function iterator() : Iterator return this.iterator(); + @:extern inline public function map( f : Dynamic -> S ) : VirtualArray return this.map(f); + @:extern inline public function filter( f : Dynamic -> Bool ) : VirtualArray return this.filter(f); +} + diff --git a/std/cpp/Void.hx b/std/cpp/Void.hx index 4f5bea48..af33561e 100644 --- a/std/cpp/Void.hx +++ b/std/cpp/Void.hx @@ -1,4 +1,25 @@ -package cpp; +/* + * Copyright (C)2005-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 cpp; @:native("void") extern class Void { } diff --git a/std/cpp/_std/Date.hx b/std/cpp/_std/Date.hx index f448b1f8..f960aa14 100644 --- a/std/cpp/_std/Date.hx +++ b/std/cpp/_std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cpp/_std/EReg.hx b/std/cpp/_std/EReg.hx index c806668d..67683755 100644 --- a/std/cpp/_std/EReg.hx +++ b/std/cpp/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,6 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + +@:buildXml('') @:coreApi class EReg { var r : Dynamic; @@ -30,11 +32,11 @@ global = a.length > 1; if( global ) opt = a.join(""); - this.r = regexp_new_options(r, opt); + this.r = _hx_regexp_new_options(r, opt); } public function match( s : String ) : Bool { - var p = regexp_match(r,s,0,s.length); + var p = _hx_regexp_match(r,s,0,s.length); if( p ) last = s; else @@ -43,27 +45,27 @@ } public function matched( n : Int ) : String { - var m = regexp_matched(r,n); + var m = _hx_regexp_matched(r,n); return m; } public function matchedLeft() : String { - var p = regexp_matched_pos(r,0); + var p = _hx_regexp_matched_pos(r,0); return last.substr(0,p.pos); } public function matchedRight() : String { - var p = regexp_matched_pos(r,0); + var p = _hx_regexp_matched_pos(r,0); var sz = p.pos+p.len; return last.substr(sz,last.length-sz); } public function matchedPos() : { pos : Int, len : Int } { - return regexp_matched_pos(r,0); + return _hx_regexp_matched_pos(r,0); } public function matchSub( s : String, pos : Int, len : Int = -1):Bool { - var p = regexp_match(r, s, pos, len < 0 ? s.length - pos : len); + var p = _hx_regexp_match(r, s, pos, len < 0 ? s.length - pos : len); if (p) last = s; else @@ -77,9 +79,9 @@ var a = new Array(); var first = true; do { - if( !regexp_match(r,s,pos,len) ) + if( !_hx_regexp_match(r,s,pos,len) ) break; - var p = regexp_matched_pos(r,0); + var p = _hx_regexp_matched_pos(r,0); if( p.len == 0 && !first ) { if( p.pos == s.length ) break; @@ -102,9 +104,9 @@ var a = by.split("$"); var first = true; do { - if( !regexp_match(r,s,pos,len) ) + if( !_hx_regexp_match(r,s,pos,len) ) break; - var p = regexp_matched_pos(r,0); + var p = _hx_regexp_matched_pos(r,0); if( p.len == 0 && !first ) { if( p.pos == s.length ) break; @@ -119,7 +121,7 @@ var c = k.charCodeAt(0); // 1...9 if( c >= 49 && c <= 57 ) { - var p = try regexp_matched_pos(r,Std.int(c)-48) catch( e : String ) null; + var p = try _hx_regexp_matched_pos(r,Std.int(c)-48) catch( e : String ) null; if( p == null ){ b.add("$"); b.add(k); @@ -156,7 +158,7 @@ buf.add(s.substr(offset)); break; } - var p = regexp_matched_pos(r,0); + var p = _hx_regexp_matched_pos(r,0); buf.add(s.substr(offset, p.pos - offset)); buf.add(f(this)); if (p.len == 0) { @@ -171,8 +173,16 @@ return buf.toString(); } - static var regexp_new_options : String -> String -> Dynamic = cpp.Lib.load("regexp","regexp_new_options",2); - static var regexp_match : Dynamic -> String -> Int -> Int -> Dynamic = cpp.Lib.load("regexp","regexp_match",4); - static var regexp_matched : Dynamic -> Int -> Dynamic = cpp.Lib.load("regexp","regexp_matched",2); - static var regexp_matched_pos : Dynamic -> Int -> { pos : Int, len : Int } = cpp.Lib.load("regexp","regexp_matched_pos",2); + + @:extern @:native("_hx_regexp_new_options") + static function _hx_regexp_new_options(s:String, options:String) : Dynamic return null; + + @:extern @:native("_hx_regexp_match") + static function _hx_regexp_match(handler: Dynamic, string:String, pos:Int, len:Int) : Bool return false; + + @:extern @:native("_hx_regexp_matched") + static function _hx_regexp_matched(handle:Dynamic, pos:Int) : String return null; + + @:extern @:native("_hx_regexp_matched_pos") + static function _hx_regexp_matched_pos(handle:Dynamic, match:Int) : {pos:Int, len:Int} return null; } diff --git a/std/cpp/_std/Reflect.hx b/std/cpp/_std/Reflect.hx index c6d53f6c..a80e4d21 100644 --- a/std/cpp/_std/Reflect.hx +++ b/std/cpp/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,7 +19,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -@:coreApi class Reflect { + +import cpp.ObjectType; + +@:coreApi +@:analyzer(ignore) +class Reflect { public static function hasField( o : Dynamic, field : String ) : Bool untyped { return o!=null && o.__HasField(field); @@ -44,7 +49,7 @@ } public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array ) : Dynamic untyped { - if (func!=null && func.__GetType()==__global__.vtString) + if (func!=null && func.__GetType()==ObjectType.vtString) func = o.__Field(func,untyped __cpp__("hx::paccDynamic")); untyped func.__SetThis(o); return untyped func.__Run(args); @@ -58,7 +63,7 @@ } public static function isFunction( f : Dynamic ) : Bool untyped { - return f!=null && f.__GetType() == __global__.vtFunction; + return f!=null && f.__GetType() == ObjectType.vtFunction; } public static function compare( a : T, b : T ) : Int { @@ -76,12 +81,12 @@ public static function isObject( v : Dynamic ) : Bool untyped { if (v==null) return false; var t:Int = v.__GetType(); - return t == __global__.vtObject || t==__global__.vtClass || t==__global__.vtString || - t==__global__.vtArray; + return t == ObjectType.vtObject || t==ObjectType.vtClass || t==ObjectType.vtString || + t==ObjectType.vtArray; } public static function isEnumValue( v : Dynamic ) : Bool untyped { - return v!=null && v.__GetType() == __global__.vtEnum; + return v!=null && v.__GetType() == ObjectType.vtEnum; } public static function deleteField( o : Dynamic, field : String ) : Bool untyped { @@ -91,8 +96,8 @@ public static function copy( o : T ) : T { if (o==null) return null; - if(untyped o.__GetType()==__global__.vtString ) return o; - if(untyped o.__GetType()==__global__.vtArray ) + if(untyped o.__GetType()==ObjectType.vtString ) return o; + if(untyped o.__GetType()==ObjectType.vtArray ) return untyped o.__Field("copy", untyped __cpp__("hx::paccDynamic"))(); var o2 : Dynamic = {}; for( f in Reflect.fields(o) ) diff --git a/std/cpp/_std/Std.hx b/std/cpp/_std/Std.hx index 1ea51dc3..fe7a7104 100644 --- a/std/cpp/_std/Std.hx +++ b/std/cpp/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cpp/_std/StringBuf.hx b/std/cpp/_std/StringBuf.hx index 5f4dd1a0..30d4e4b8 100644 --- a/std/cpp/_std/StringBuf.hx +++ b/std/cpp/_std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,38 +19,73 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +import cpp.NativeString; +using cpp.NativeArray; + @:coreApi class StringBuf { + private var b : Array; + public var length(get,never) : Int; + var charBuf:Array; - private var b : Array; - - public var length(get,never) : Int; + public function new() : Void { + } - public function new() : Void { - b = new Array(); - } + private function charBufAsString() : String + { + var len = charBuf.length; + charBuf.push(0); + return NativeString.fromGcPointer( charBuf.address(0), len ); + } - function get_length() : Int { - var len = 0; - for(s in b) - len += s==null ? 4 : s.length; - return len; - } + private function flush() : Void{ + if (b==null) + b = [charBufAsString()]; + else + b.push( charBufAsString() ); + charBuf = null; + } + function get_length() : Int { + var len = 0; + if (charBuf!=null) + len = charBuf.length; + if (b!=null) + for(s in b) + len += s==null ? 4 : s.length; + return len; + } - public function add( x : T ) : Void { - b.push(Std.string(x)); - } + public inline function add( x : T ) : Void { + if (charBuf!=null) flush(); + if (b==null) + b = [Std.string(x)]; + else + b.push(Std.string(x)); + } - public inline function addSub( s : String, pos : Int, ?len : Int ) : Void { - b.push(s.substr(pos,len)); - } + public #if !cppia inline #end function addSub( s : String, pos : Int, ?len : Int ) : Void { + if (charBuf!=null) flush(); + if (b==null) + b = [s.substr(pos,len)]; + else + b.push(s.substr(pos,len)); + } - public inline function addChar( c : Int ) : Void untyped { - b.push(String.fromCharCode(c)); - } + public #if !cppia inline #end function addChar( c : Int ) : Void { + if (charBuf==null) charBuf = new Array(); + charBuf.push(c); + } - public inline function toString() : String { - return b.join(""); - } + public function toString() : String { + if (charBuf!=null) + { + if (b==null) + return( charBufAsString() ); + flush(); + } + if (b==null) + return ""; + return b.join(""); + } } diff --git a/std/cpp/_std/Sys.hx b/std/cpp/_std/Sys.hx index e5bd3f98..88a0c90f 100644 --- a/std/cpp/_std/Sys.hx +++ b/std/cpp/_std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,6 +19,8 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +import cpp.NativeSys; + @:coreApi class Sys { public static function print( v : Dynamic ) : Void { @@ -26,24 +28,26 @@ } public static function println( v : Dynamic ) : Void { - print(v); - print("\n"); + untyped __global__.__hxcpp_println(v); } + @:access(sys.io.FileInput) public static function stdin() : haxe.io.Input { - return untyped new sys.io.FileInput(file_stdin()); + return new sys.io.FileInput(cpp.NativeFile.file_stdin()); } + @:access(sys.io.FileOutput) public static function stdout() : haxe.io.Output { - return untyped new sys.io.FileOutput(file_stdout()); + return new sys.io.FileOutput(cpp.NativeFile.file_stdout()); } + @:access(sys.io.FileOutput) public static function stderr() : haxe.io.Output { - return untyped new sys.io.FileOutput(file_stderr()); + return new sys.io.FileOutput(cpp.NativeFile.file_stderr()); } public static function getChar( echo : Bool ) : Int { - return getch(echo); + return NativeSys.sys_getch(echo); } public static function args() : Array untyped { @@ -51,58 +55,52 @@ } public static function getEnv( s : String ):String { - var v = get_env(s); + var v = NativeSys.get_env(s); if( v == null ) return null; return v; } public static function putEnv( s : String, v : String ) : Void { - put_env(s,v); + NativeSys.put_env(s,v); } public static function sleep( seconds : Float ) : Void { - _sleep(seconds); + NativeSys.sys_sleep(seconds); } public static function setTimeLocale( loc : String ) : Bool { - return set_time_locale(loc); + return NativeSys.set_time_locale(loc); } public static function getCwd() : String { - return new String(get_cwd()); + return NativeSys.get_cwd(); } public static function setCwd( s : String ) : Void { - set_cwd(s); + NativeSys.set_cwd(s); } public static function systemName() : String { - return sys_string(); - } - - static function escapeArgument( arg : String ) : String { - var ok = true; - for( i in 0...arg.length ) - switch( arg.charCodeAt(i) ) { - case ' '.code, '\t'.code, '"'.code, '&'.code, '|'.code, '<'.code, '>'.code, '#'.code , ';'.code, '*'.code, '?'.code, '('.code, ')'.code, '{'.code, '}'.code, '$'.code: - ok = false; - case 0, 13, 10: // [eof] [cr] [lf] - arg = arg.substr(0,i); - } - if( ok ) - return arg; - return '"'+arg.split('\\').join("\\\\").split('"').join('\\"')+'"'; + return NativeSys.sys_string(); } public static function command( cmd : String, ?args : Array ) : Int { - if( args != null ) { - cmd = escapeArgument(cmd); - for( a in args ) - cmd += " "+escapeArgument(a); + if (args == null) { + return NativeSys.sys_command(cmd); + } else { + switch (systemName()) { + case "Windows": + cmd = [ + for (a in [StringTools.replace(cmd, "/", "\\")].concat(args)) + StringTools.quoteWinArg(a, true) + ].join(" "); + return NativeSys.sys_command(cmd); + case _: + cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" "); + return NativeSys.sys_command(cmd); + } } - if (systemName() == "Windows") cmd = '"$cmd"'; - return sys_command(cmd); } public static function exit( code : Int ) : Void { @@ -110,19 +108,23 @@ } public static function time() : Float { - return sys_time(); + return NativeSys.sys_time(); } public static function cpuTime() : Float { - return sys_cpu_time(); + return NativeSys.sys_cpu_time(); + } + + @:deprecated("Use programPath instead") public static function executablePath() : String { + return NativeSys.sys_exe_path(); } - public static function executablePath() : String { - return new String(sys_exe_path()); + public static function programPath() : String { + return NativeSys.sys_exe_path(); } public static function environment() : Map { - var vars:Array = sys_env(); + var vars:Array = NativeSys.sys_env(); var result = new haxe.ds.StringMap(); var i = 0; while(i { - var result : Array = untyped e.__EnumParams(); - return result==null ? [] : result; + var value:cpp.EnumBase = cast e; + return value._hx_getParameters(); } - public inline static function enumIndex( e : EnumValue ) : Int { - return untyped e.__Index(); + @:extern @:native("_hx_getEnumValueIndex") + private static function getEnumValueIndex( e : EnumValue ) : Int return 0; + + #if !cppia inline #end public static function enumIndex( e : EnumValue ) : Int { + return getEnumValueIndex(e); } public static function allEnums( e : Enum ) : Array { diff --git a/std/cpp/_std/haxe/Int64.hx b/std/cpp/_std/haxe/Int64.hx index 9ec0bf51..0e75eea5 100644 --- a/std/cpp/_std/haxe/Int64.hx +++ b/std/cpp/_std/haxe/Int64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,12 +21,119 @@ */ package haxe; - +import haxe.Int64Helper; @:notNull + +@:include("cpp/Int64.h") @:native("cpp::Int64Struct") -private extern class ___Int64 { public function get():cpp.Int64; } +private extern class ___Int64 { + public function get():cpp.Int64; + + @:native("_hx_int64_make") + public static function make(high:Int32, low:Int32): __Int64 return null; + + @:native(" ::cpp::Int64Struct") + public static function ofInt(value:Int): __Int64 return null; + + @:native(" ::cpp::Int64Struct::is") + public static function is(d:Dynamic):Bool return false; + + @:native("_hx_int64_is_neg") + public static function isNeg(a:__Int64):Bool return false; + + @:native("_hx_int64_is_zero") + public static function isZero(a:__Int64):Bool return false; + + @:native("_hx_int64_compare") + public static function compare(a:__Int64, b:__Int64):Int return 0; + + @:native("_hx_int64_ucompare") + public static function ucompare(a:__Int64, b:__Int64):Int return 0; + + @:native("_hx_int64_to_string") + public static function toString(a:__Int64):String return null; + + @:native("_hx_int64_neg") + public static function neg(a:__Int64): __Int64 return null; + + @:native("_hx_int64_pre_increment") + public static function preIncrement(a:__Int64): __Int64 return null; + + @:native("_hx_int64_post_increment") + public static function postIncrement(a:__Int64): __Int64 return null; + + @:native("_hx_int64_pre_decrement") + public static function preDecrement(a:__Int64): __Int64 return null; + + @:native("_hx_int64_post_decrement") + public static function postDecrement(a:__Int64): __Int64 return null; + + @:native("_hx_int64_add") + public static function add(a:__Int64, b:__Int64): __Int64 return null; + + @:native("_hx_int64_add") + public static function addInt(a:__Int64, b:Int): __Int64 return null; + + @:native("_hx_int64_sub") + public static function sub(a:__Int64, b:__Int64): __Int64 return null; + + @:native("_hx_int64_sub") + public static function subInt(a:__Int64, b:Int): __Int64 return null; + + @:native("_hx_int64_sub") + public static function intSub(a:Int, b:__Int64): __Int64 return null; + + @:native("_hx_int64_mul") + public static function mul(a:__Int64, b:__Int64): __Int64 return null; + + @:native("_hx_int64_div") + public static function div(a:__Int64, b:__Int64): __Int64 return null; + + @:native("_hx_int64_mod") + public static function mod(a:__Int64, b:__Int64): __Int64 return null; + + @:native("_hx_int64_eq") + public static function eq(a:__Int64, b:__Int64): Bool return null; + + @:native("_hx_int64_eq") + public static function eqInt(a:__Int64, b:Int): Bool return null; + + @:native("_hx_int64_neq") + public static function neq(a:__Int64, b:__Int64): Bool return null; + + @:native("_hx_int64_neq") + public static function neqInt(a:__Int64, b:Int): Bool return null; + + @:native("_hx_int64_complement") + public static function complement(a:__Int64): __Int64 return null; + + @:native("_hx_int64_and") + public static function bitAnd(a:__Int64, b:__Int64): __Int64 return null; + + @:native("_hx_int64_or") + public static function bitOr(a:__Int64, b:__Int64): __Int64 return null; + + @:native("_hx_int64_xor") + public static function bitXor(a:__Int64, b:__Int64): __Int64 return null; + + @:native("_hx_int64_shl") + public static function shl(a:__Int64, b:Int): __Int64 return null; + + @:native("_hx_int64_shr") + public static function shr(a:__Int64, b:Int): __Int64 return null; + + @:native("_hx_int64_ushr") + public static function ushr(a:__Int64, b:Int): __Int64 return null; + + @:native("_hx_int64_high") + public static function high(a:__Int64):Int32 return 0; + + @:native("_hx_int64_low") + public static function low(a:__Int64):Int32 return 0; + +} private typedef __Int64 = ___Int64; @@ -36,15 +143,15 @@ abstract Int64( __Int64 ) from __Int64 to __Int64 /** Makes a copy of `this` Int64. **/ - public #if !cppua inline #end function copy():Int64 return this; + public #if !cppia inline #end function copy():Int64 return this; public static #if !cppia inline #end function make( high : Int32, low : Int32 ) : Int64 { - return untyped __cpp__("cpp::Int64Struct(( ( (cpp::Int64)((unsigned int){0}) ) << 32 ) | ((unsigned int){1}))",high, low); + return __Int64.make(high,low); } - @:from public static function ofInt( x : Int ) : Int64 { - return untyped __cpp__("((cpp::Int64)({0}))", x); + @:from public static #if !cppia inline #end function ofInt( x : Int ) : Int64 { + return __Int64.ofInt(x); } @@ -63,7 +170,7 @@ abstract Int64( __Int64 ) from __Int64 to __Int64 Returns whether the value `val` is of type `haxe.Int64` **/ public static #if !cppia inline #end function is( val : Dynamic ) : Bool - return untyped __cpp__("(cpp::Int64Struct::is({0}))",val); + return __Int64.is(val); /** Returns the high 32-bit word of `x`. @@ -83,31 +190,29 @@ abstract Int64( __Int64 ) from __Int64 to __Int64 Returns `true` if `x` is less than zero. **/ public static #if !cppia inline #end function isNeg( x : Int64) : Bool - return untyped __cpp__("(({0}.get()) < 0)", x); + return __Int64.isNeg(x); /** Returns `true` if `x` is exactly zero. **/ public static #if !cppia inline #end function isZero( x : Int64 ) : Bool - return untyped __cpp__("(({0}.get()) == 0)", x); + return __Int64.isZero(x); /** Compares `a` and `b` in signed mode. Returns a negative value if `a < b`, positive if `a > b`, or 0 if `a == b`. **/ - public static #if !cppia inline #end function compare( a : Int64, b : Int64 ) : Int { - return untyped __cpp__("( ({0}.get()) < ({1}.get()) ? -1 : ({0})==({1}) ? 0 : 1)", a, b, a, b); - } + public static #if !cppia inline #end function compare( a : Int64, b : Int64 ) : Int + return __Int64.compare(a,b); /** Compares `a` and `b` in unsigned mode. Returns a negative value if `a < b`, positive if `a > b`, or 0 if `a == b`. **/ - public static #if !cppia inline #end function ucompare( a : Int64, b : Int64 ) : Int { - return untyped __cpp__("( (cpp::UInt64)({0}.get()) < (cpp::UInt64)({1}.get()) ? -1 : ({0}.get())==({1}.get()) ? 0 : 1)", a, b, a, b); - } + public static #if !cppia inline #end function ucompare( a : Int64, b : Int64 ) : Int + return __Int64.ucompare(a,b); /** Returns a signed decimal `String` representation of `x`. @@ -115,9 +220,15 @@ abstract Int64( __Int64 ) from __Int64 to __Int64 public static #if !cppia inline #end function toStr(x:Int64) : String return x.toString(); - private function toString() : String - { - return untyped __cpp__("String( ({0}).get() )", this); + private #if !cppia inline #end function toString() : String + return __Int64.toString(this); + + public static function parseString( sParam : String ) : Int64 { + return Int64Helper.parseString( sParam ); + } + + public static function fromFloat( f : Float ) : Int64 { + return Int64Helper.fromFloat( f ); } /** @@ -139,16 +250,15 @@ abstract Int64( __Int64 ) from __Int64 to __Int64 /** Returns the negative of `x`. **/ - @:op(-A) public static #if !cppia inline #end function neg( x : Int64 ) : Int64 { - return untyped __cpp__("(-({0}.get()))",x); - } + @:op(-A) public static #if !cppia inline #end function neg( x : Int64 ) : Int64 + return __Int64.neg(x); @:op(++A) private inline function preIncrement() : Int64 { #if cppia this = this + make(0,1); return this; #else - return untyped __cpp__("(++({0}.get()))",this); + return __Int64.preIncrement(this); #end } @@ -158,7 +268,7 @@ abstract Int64( __Int64 ) from __Int64 to __Int64 this = this + make(0,1); return result; #else - return untyped __cpp__("(({0}.get())++)",this); + return __Int64.postIncrement(this); #end } @@ -167,7 +277,7 @@ abstract Int64( __Int64 ) from __Int64 to __Int64 untyped this = this - make(0,1); return this; #else - return untyped __cpp__("(--({0}.get()))",this); + return __Int64.preDecrement(this); #end } @@ -177,39 +287,37 @@ abstract Int64( __Int64 ) from __Int64 to __Int64 this = this - make(0,1); return result; #else - return untyped __cpp__("(({0}.get())--)",this); + return __Int64.postDecrement(this); #end } /** Returns the sum of `a` and `b`. **/ - @:op(A + B) public static #if !cppia inline #end function add( a : Int64, b : Int64 ) : Int64 { - return untyped __cpp__("(({0}.get()) + ({1}.get()))", a, b); - } + @:op(A + B) public static #if !cppia inline #end function add( a : Int64, b : Int64 ) : Int64 + return __Int64.add(a,b); @:op(A + B) @:commutative private static #if !cppia inline #end function addInt( a : Int64, b : Int ) : Int64 - return add( a, b ); + return __Int64.addInt(a,b); /** Returns `a` minus `b`. **/ @:op(A - B) public static #if !cppia inline #end function sub( a : Int64, b : Int64 ) : Int64 { - return untyped __cpp__("(({0}.get()) - ({1}.get()))", a, b); + return __Int64.sub(a,b); } @:op(A - B) private static #if !cppia inline #end function subInt( a : Int64, b : Int ) : Int64 - return sub( a, b ); + return __Int64.subInt( a, b ); @:op(A - B) private static #if !cppia inline #end function intSub( a : Int, b : Int64 ) : Int64 - return sub( a, b ); + return __Int64.intSub( a, b ); /** Returns the product of `a` and `b`. **/ - @:op(A * B) public static #if !cppia inline #end function mul( a : Int64, b : Int64 ) : Int64 { - return untyped __cpp__("(({0}.get()) * ({1}.get()))", a, b); - } + @:op(A * B) public static #if !cppia inline #end function mul( a : Int64, b : Int64 ) : Int64 + return __Int64.mul( a, b ); @:op(A * B) @:commutative private static #if !cppia inline #end function mulInt( a : Int64, b : Int ) : Int64 return mul( a, b ); @@ -217,10 +325,10 @@ abstract Int64( __Int64 ) from __Int64 to __Int64 /** Returns the quotient of `a` divided by `b`. **/ - @:op(A / B) public static function div( a : Int64, b : Int64 ) : Int64 { - if (untyped __cpp__("(({0}.get()) == 0)",b) ) + @:op(A / B) public static #if !cppia inline #end function div( a : Int64, b : Int64 ) : Int64 { + if (__Int64.isZero(b)) throw "divide by zero"; - return untyped __cpp__("(({0}.get()) / ({1}.get()))", a, b); + return __Int64.div(a,b); } @@ -235,9 +343,9 @@ abstract Int64( __Int64 ) from __Int64 to __Int64 **/ @:op(A % B) public static #if !cppia inline #end function mod( a : Int64, b : Int64 ) : Int64 { - if (untyped __cpp__("(({0}.get()) == 0)",b) ) + if (__Int64.isZero(b)) throw "divide by zero"; - return untyped __cpp__("(({0}.get()) % ({1}.get()))", a, b); + return __Int64.mod(a, b); } @:op(A % B) private static #if !cppia inline #end function modInt( a : Int64, b : Int ) : Int64 @@ -250,19 +358,19 @@ abstract Int64( __Int64 ) from __Int64 to __Int64 Returns `true` if `a` is equal to `b`. **/ @:op(A == B) public static #if !cppia inline #end function eq( a : Int64, b : Int64 ) : Bool - return untyped __cpp__("(({0}.get()) == ({1}.get()))", a, b); + return __Int64.eq(a,b); @:op(A == B) @:commutative private static #if !cppia inline #end function eqInt( a : Int64, b : Int ) : Bool - return eq( a, b ); + return __Int64.eqInt( a, b ); /** Returns `true` if `a` is not equal to `b`. **/ @:op(A != B) public static #if !cppia inline #end function neq( a : Int64, b : Int64 ) : Bool - return untyped __cpp__("(({0}.get()) != ({1}.get()))", a, b); + return __Int64.neq( a, b ); @:op(A != B) @:commutative private static #if !cppia inline #end function neqInt( a : Int64, b : Int ) : Bool - return neq(a, b); + return neq( a, b ); @:op(A < B) private static #if !cppia inline #end function lt( a : Int64, b : Int64 ) : Bool return compare(a, b) < 0; @@ -304,53 +412,53 @@ abstract Int64( __Int64 ) from __Int64 to __Int64 Returns the bitwise NOT of `a`. **/ @:op(~A) private static #if !cppia inline #end function complement( a : Int64 ) : Int64 - return untyped __cpp__("(~({0}.get()))", a); + return __Int64.complement(a); /** Returns the bitwise AND of `a` and `b`. **/ @:op(A & B) public static #if !cppia inline #end function and( a : Int64, b : Int64 ) : Int64 - return untyped __cpp__("(({0}) & ({1}))", a, b); + return __Int64.bitAnd(a,b); /** Returns the bitwise OR of `a` and `b`. **/ @:op(A | B) public static #if !cppia inline #end function or( a : Int64, b : Int64 ) : Int64 - return untyped __cpp__("(({0}) | ({1}))", a, b); + return __Int64.bitOr(a,b); /** Returns the bitwise XOR of `a` and `b`. **/ @:op(A ^ B) public static #if !cppia inline #end function xor( a : Int64, b : Int64 ) : Int64 - return untyped __cpp__("(({0}) ^ ({1}))", a, b); + return __Int64.bitXor(a,b); /** Returns `a` left-shifted by `b` bits. **/ @:op(A << B) public static #if !cppia inline #end function shl( a : Int64, b : Int ) : Int64 - return untyped __cpp__("(({0}) << ({1}))", a, (b&63)); + return __Int64.shl(a,b); /** Returns `a` right-shifted by `b` bits in signed mode. `a` is sign-extended. **/ @:op(A >> B) public static #if !cppia inline #end function shr( a : Int64, b : Int) : Int64 - return untyped __cpp__("(({0}) >> ({1}))", a, (b&63)); + return __Int64.shr(a,b); /** Returns `a` right-shifted by `b` bits in unsigned mode. `a` is padded with zeroes. **/ @:op(A >>> B) public static #if !cppia inline #end function ushr( a : Int64, b : Int ) : Int64 - return untyped __cpp__("(((cpp::UInt64)({0})) >> ({1}))", a, (b&63)); + return __Int64.ushr(a,b); public var high(get, never) : Int32; private #if !cppia inline #end function get_high() : Int32 - return untyped __cpp__("(int)(((cpp::Int64)({0}))>>32)",this); + return __Int64.high(this); public var low(get, never) : Int32; private #if !cppia inline #end function get_low() : Int32 - return untyped __cpp__("(int)(({0})&0xffffffff)", this); + return __Int64.low(this); } diff --git a/std/cpp/_std/haxe/Resource.hx b/std/cpp/_std/haxe/Resource.hx index 96a040e4..e59d97a7 100644 --- a/std/cpp/_std/haxe/Resource.hx +++ b/std/cpp/_std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cpp/_std/haxe/Utf8.hx b/std/cpp/_std/haxe/Utf8.hx index a5a13dd9..ff6e0501 100644 --- a/std/cpp/_std/haxe/Utf8.hx +++ b/std/cpp/_std/haxe/Utf8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,8 @@ */ package haxe; +using cpp.NativeString; + @:coreApi class Utf8 { @@ -29,7 +31,7 @@ class Utf8 public function new( ?size : Null ) : Void { __s = new Array(); if (size!=null && size>0) - __s[size-1] = 0; + cpp.NativeArray.reserve(__s,size); } public function addChar( c : Int ) : Void { @@ -52,61 +54,34 @@ class Utf8 return untyped __global__.__hxcpp_utf8_string_to_char_bytes(s); } - public static function iter( s : String, chars : Int -> Void ) : Void { - var array:Array = untyped __global__.__hxcpp_utf8_string_to_char_array(s); - for(a in array) - chars(a); + public #if !cppia inline #end static function iter( s : String, chars : Int -> Void ) : Void { + var src = s.c_str(); + var end = src.add( s.length ); + + while(src.lt(end)) + chars(src.ptr.utf8DecodeAdvance()); } public static function charCodeAt( s : String, index : Int ) : Int { - var array:Array = untyped __global__.__hxcpp_utf8_string_to_char_array(s); - return array[index]; + return s.utf8CharCodeAt(index); } public static function validate( s : String ) : Bool { - try { - untyped __global__.__hxcpp_utf8_string_to_char_array(s); - return true; - } catch(e:Dynamic) { } - return false; + return s.utf8IsValid(); } public static function length( s : String ) : Int { - var array:Array = untyped __global__.__hxcpp_utf8_string_to_char_array(s); - return array.length; + return s.utf8Length(); } public static function compare( a : String, b : String ) : Int { - var a_:Array = untyped __global__.__hxcpp_utf8_string_to_char_array(a); - var b_:Array = untyped __global__.__hxcpp_utf8_string_to_char_array(b); - var min = a_.length < b_.length ? a_.length : b_.length; - for(i in 0...min) - { - if (a_[i] < b_[i]) return -1; - if (a_[i] > b_[i]) return 1; - } - return a_.length==b_.length ? 0 : a_.length = untyped __global__.__hxcpp_utf8_string_to_char_array(s); - var last = len < 0 ? array.length : pos+len; - if (last>array.length) last = array.length; - var sub = array.slice(pos,last); - return untyped __global__.__hxcpp_char_array_to_utf8_string(sub); + return s.utf8Sub(pos,len); } - - - - - - - - - - - } diff --git a/std/cpp/_std/haxe/ds/IntMap.hx b/std/cpp/_std/haxe/ds/IntMap.hx index b2b2a989..24645e12 100644 --- a/std/cpp/_std/haxe/ds/IntMap.hx +++ b/std/cpp/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -43,11 +43,12 @@ package haxe.ds; inline void set(int key, const ::cpp::Pointer &value) {__int_hash_set(h,key,(Dynamic)value ); } template - inline Void set(Dynamic &key, const VALUE &value) { set( (int)key, value ); return null(); } + inline void set(Dynamic &key, const VALUE &value) { set( (int)key, value ); } ") @:coreApi class IntMap implements haxe.Constraints.IMap { - @:ifFeature("haxe.ds.IntMap.*") private var h : Dynamic; + @:ifFeature("haxe.ds.IntMap.*") + private var h : Dynamic; public function new() : Void { } diff --git a/std/cpp/_std/haxe/ds/ObjectMap.hx b/std/cpp/_std/haxe/ds/ObjectMap.hx index 6a454ce6..4dd8ba34 100644 --- a/std/cpp/_std/haxe/ds/ObjectMap.hx +++ b/std/cpp/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -46,6 +46,7 @@ package haxe.ds; ") @:coreApi class ObjectMap implements haxe.Constraints.IMap { + @:ifFeature("haxe.ds.ObjectMap.*") private var h : Dynamic; public function new() : Void { } diff --git a/std/cpp/_std/haxe/ds/StringMap.hx b/std/cpp/_std/haxe/ds/StringMap.hx index 44c1ddcb..5fdf58ee 100644 --- a/std/cpp/_std/haxe/ds/StringMap.hx +++ b/std/cpp/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -43,7 +43,7 @@ package haxe.ds; inline void set(String key, const ::cpp::Pointer &value) {__string_hash_set(h,key,(Dynamic)value ); } template - inline Void set(Dynamic &key, const VALUE &value) { set( (String)key, value ); return null(); } + inline void set(Dynamic &key, const VALUE &value) { set( (String)key, value ); } ") @:coreApi class StringMap implements haxe.Constraints.IMap { @:ifFeature("haxe.ds.StringMap.*") diff --git a/std/cpp/_std/haxe/ds/WeakMap.hx b/std/cpp/_std/haxe/ds/WeakMap.hx index ac0df37e..0b7b34e0 100644 --- a/std/cpp/_std/haxe/ds/WeakMap.hx +++ b/std/cpp/_std/haxe/ds/WeakMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -44,6 +44,7 @@ package haxe.ds; ") @:coreApi class WeakMap implements haxe.Constraints.IMap { + @:ifFeature("haxe.ds.WeakMap.*") private var h : Dynamic; public function new() : Void { } diff --git a/std/cpp/_std/haxe/zip/Compress.hx b/std/cpp/_std/haxe/zip/Compress.hx index eba27795..afa69eb3 100644 --- a/std/cpp/_std/haxe/zip/Compress.hx +++ b/std/cpp/_std/haxe/zip/Compress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,7 +21,7 @@ */ package haxe.zip; -@:coreApi +@:coreApi @:buildXml('') class Compress { var s : Dynamic; @@ -53,10 +53,19 @@ class Compress { return out.sub(0,r.write); } - static var _deflate_init = cpp.Lib.load("zlib","deflate_init",1); - static var _deflate_bound = cpp.Lib.load("zlib","deflate_bound",2); - static var _deflate_buffer = cpp.Lib.load("zlib","deflate_buffer",5); - static var _deflate_end = cpp.Lib.load("zlib","deflate_end",1); - static var _set_flush_mode = cpp.Lib.load("zlib","set_flush_mode",2); + @:extern @:native("_hx_deflate_init") + static function _deflate_init(level:Int) : Dynamic return null; + + @:extern @:native("_hx_deflate_bound") + static function _deflate_bound(handle:Dynamic,length:Int):Int return 0; + + @:extern @:native("_hx_deflate_buffer") + static function _deflate_buffer(handle:Dynamic, src:haxe.io.BytesData, srcPos:Int, dest:haxe.io.BytesData, destPos:Int) : { done : Bool, read : Int, write : Int } return null; + + @:extern @:native("_hx_deflate_end") + static function _deflate_end(handle:Dynamic) : Void { } + + @:extern @:native("_hx_zip_set_flush_mode") + static function _set_flush_mode(handle:Dynamic, flushMode:String):Void { } } diff --git a/std/cpp/_std/haxe/zip/Uncompress.hx b/std/cpp/_std/haxe/zip/Uncompress.hx index 92e23644..8a6244f3 100644 --- a/std/cpp/_std/haxe/zip/Uncompress.hx +++ b/std/cpp/_std/haxe/zip/Uncompress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,7 +21,7 @@ */ package haxe.zip; -@:coreApi +@:coreApi @:buildXml('') class Uncompress { var s : Dynamic; @@ -59,9 +59,16 @@ class Uncompress { return b.getBytes(); } - static var _inflate_init = cpp.Lib.load("zlib","inflate_init",1); - static var _inflate_buffer = cpp.Lib.load("zlib","inflate_buffer",5); - static var _inflate_end = cpp.Lib.load("zlib","inflate_end",1); - static var _set_flush_mode = cpp.Lib.load("zlib","set_flush_mode",2); + @:extern @:native("_hx_inflate_init") + static function _inflate_init(windowBits:Dynamic) : Dynamic return null; + + @:extern @:native("_hx_inflate_buffer") + static function _inflate_buffer(handle:Dynamic, src:haxe.io.BytesData, srcPos:Int, dest:haxe.io.BytesData, destPos:Int) : { done : Bool, read : Int, write : Int } return null; + + @:extern @:native("_hx_inflate_end") + static function _inflate_end(handle:Dynamic):Void { } + + @:extern @:native("_hx_zip_set_flush_mode") + static function _set_flush_mode(handle:Dynamic, flushMode:String):Void { } } diff --git a/std/cpp/_std/sys/FileSystem.hx b/std/cpp/_std/sys/FileSystem.hx index 39725055..959b42e8 100644 --- a/std/cpp/_std/sys/FileSystem.hx +++ b/std/cpp/_std/sys/FileSystem.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,26 +21,22 @@ */ package sys; -private enum FileKind { - kdir; - kfile; - kother( k : String ); -} +import cpp.NativeSys; +@:buildXml('') @:coreApi class FileSystem { public static function exists( path : String ) : Bool { - return sys_exists(haxe.io.Path.removeTrailingSlashes(path)); + return NativeSys.sys_exists(makeCompatiblePath(path)); } public static function rename( path : String, newPath : String ) : Void { - if (sys_rename(path,newPath)==null) - throw "Could not rename:" + path + " to " + newPath; + NativeSys.sys_rename(path,newPath); } public static function stat( path : String ) : FileStat { - var s : FileStat = sys_stat(path); + var s : FileStat = NativeSys.sys_stat(makeCompatiblePath(path)); if (s==null) return { gid:0, uid:0, atime:Date.fromTime(0), mtime:Date.fromTime(0), ctime:Date.fromTime(0), dev:0, ino:0, nlink:0, rdev:0, size:0, mode:0 }; s.atime = Date.fromTime(1000.0*(untyped s.atime)); @@ -50,7 +46,7 @@ class FileSystem { } public static function fullPath( relPath : String ) : String { - return new String(file_full_path(relPath)); + return NativeSys.file_full_path(relPath); } public static function absolutePath ( relPath : String ) : String { @@ -58,17 +54,12 @@ class FileSystem { return haxe.io.Path.join([Sys.getCwd(), relPath]); } - static function kind( path : String ) : FileKind { - var k:String = sys_file_type(haxe.io.Path.removeTrailingSlashes(path)); - return switch(k) { - case "file": kfile; - case "dir": kdir; - default: kother(k); - } + inline static function kind( path : String ) : String { + return NativeSys.sys_file_type(makeCompatiblePath(path)); } public static function isDirectory( path : String ) : Bool { - return kind(path) == kdir; + return kind(path) == "dir"; } public static function createDirectory( path : String ) : Void { @@ -80,33 +71,28 @@ class FileSystem { path = _p; } for (part in parts) { - if (part.charCodeAt(part.length - 1) != ":".code && !exists(part) && sys_create_dir( part, 493 )==null) + if (part.charCodeAt(part.length - 1) != ":".code && !exists(part) && !NativeSys.sys_create_dir( part, 493 )) throw "Could not create directory:" + part; } } public static function deleteFile( path : String ) : Void { - if (file_delete(path)==null) - throw "Could not delete file:" + path; + NativeSys.file_delete(path); } public static function deleteDirectory( path : String ) : Void { - if (sys_remove_dir(path)==null) - throw "Could not delete directory:" + path; + NativeSys.sys_remove_dir(path); } public static function readDirectory( path : String ) : Array { - return sys_read_dir(path); + return NativeSys.sys_read_dir(path); } - private static var sys_exists = cpp.Lib.load("std","sys_exists",1); - private static var file_delete = cpp.Lib.load("std","file_delete",1); - private static var sys_rename = cpp.Lib.load("std","sys_rename",2); - private static var sys_stat = cpp.Lib.load("std","sys_stat",1); - private static var sys_file_type = cpp.Lib.load("std","sys_file_type",1); - private static var sys_create_dir = cpp.Lib.load("std","sys_create_dir",2); - private static var sys_remove_dir = cpp.Lib.load("std","sys_remove_dir",1); - private static var sys_read_dir = cpp.Lib.load("std","sys_read_dir",1); - private static var file_full_path = cpp.Lib.load("std","file_full_path",1); - + private static inline function makeCompatiblePath(path:String):String { + return if (path.charCodeAt(1) == ":".code && path.length <= 3) { + haxe.io.Path.addTrailingSlash(path); + } else { + haxe.io.Path.removeTrailingSlashes(path); + } + } } diff --git a/std/cpp/_std/sys/db/Mysql.hx b/std/cpp/_std/sys/db/Mysql.hx index c6783360..449b97f6 100644 --- a/std/cpp/_std/sys/db/Mysql.hx +++ b/std/cpp/_std/sys/db/Mysql.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,26 +21,44 @@ */ package sys.db; +@:keep private class D { - static function load(fun,args) : Dynamic { - return cpp.Lib.load(lib,fun,args); - } - - static var lib = "mysql5"; - public static var connect = load("mysql_connect",1); - public static var select_db = load("select_db",2); - public static var request = load("request",2); - public static var close = load("close",1); - public static var escape = load("escape", 2); - public static var set_conv_funs = load("set_conv_funs", 4); - public static var result_get_length = load("result_get_length",1); - public static var result_get_nfields = load("result_get_nfields",1); - public static var result_next = load("result_next",1); - public static var result_get = load("result_get",2); - public static var result_get_int = load("result_get_int",2); - public static var result_get_float = load("result_get_float",2); - public static var result_fields_names = cpp.Lib.loadLazy(lib,"result_get_fields_names",1); + @:extern @:native("_hx_mysql_connect") + public static function connect(params:Dynamic):Dynamic return null; + @:extern @:native("_hx_mysql_select_db") + public static function select_db(handle:Dynamic, db:String):Void { } + @:extern @:native("_hx_mysql_request") + public static function request(handle:Dynamic,req:String):Dynamic return null; + @:extern @:native("_hx_mysql_close") + public static function close(handle:Dynamic):Dynamic return null; + @:extern @:native("_hx_mysql_escape") + public static function escape(handle:Dynamic,str:String):String return null; + @:extern @:native("_hx_mysql_result_get_length") + public static function result_get_length(handle:Dynamic):Int return 0; + @:extern @:native("_hx_mysql_result_get_nfields") + public static function result_get_nfields(handle:Dynamic):Int return 0; + @:extern @:native("_hx_mysql_result_next") + public static function result_next(handle:Dynamic):Dynamic return null; + @:extern @:native("_hx_mysql_result_get") + public static function result_get(handle:Dynamic,i:Int) : String return null; + @:extern @:native("_hx_mysql_result_get_int") + public static function result_get_int(handle:Dynamic,i:Int) : Int return 0; + @:extern @:native("_hx_mysql_result_get_float") + public static function result_get_float(handle:Dynamic,i:Int):Float return 0.0; + @:extern @:native("_hx_mysql_result_get_fields_names") + public static function result_fields_names(handle:Dynamic):Array return null; + + @:extern @:native("_hx_mysql_set_conversion") + public static function set_conv_funs( + charsToBytes: cpp.Callable< Dynamic -> Dynamic >, + intToDate: cpp.Callable< Float -> Dynamic > ) : Void {} + + public static function charsToBytes(data:Dynamic) : Dynamic + return haxe.io.Bytes.ofData(data); + + public static function secondsToDate(seconds:Float) : Dynamic + return Date.fromTime(seconds); } @@ -87,7 +105,7 @@ private class MysqlResultSet implements sys.db.ResultSet { } public function getResult( n : Int ) { - return new String(D.result_get(__r,n)); + return D.result_get(__r,n); } public function getIntResult( n : Int ) : Int { @@ -111,7 +129,9 @@ private class MysqlConnection implements sys.db.Connection { public function new(c) { __c = c; - D.set_conv_funs(c, function(s) return new String(s), function(d) return untyped Date.new1(d), function(b) return haxe.io.Bytes.ofData(b)); + D.set_conv_funs( cpp.Function.fromStaticFunction(D.charsToBytes), + cpp.Function.fromStaticFunction(D.secondsToDate) ); + } public function request( s : String ) : sys.db.ResultSet { @@ -124,7 +144,7 @@ private class MysqlConnection implements sys.db.Connection { } public function escape( s : String ) { - return new String(D.escape(__c,s)); + return D.escape(__c,s); } public function quote( s : String ) { @@ -174,6 +194,7 @@ private class MysqlConnection implements sys.db.Connection { private static var __use_date = Date; } +@:buildXml('') @:coreApi class Mysql { public static function connect( params : { diff --git a/std/cpp/_std/sys/db/Sqlite.hx b/std/cpp/_std/sys/db/Sqlite.hx index 4fe60d37..153207bb 100644 --- a/std/cpp/_std/sys/db/Sqlite.hx +++ b/std/cpp/_std/sys/db/Sqlite.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -47,7 +47,12 @@ private class SqliteConnection implements Connection { public function quote( s : String ) { if( s.indexOf("\000") >= 0 ) - return "x'"+new String(_encode(s,"0123456789ABCDEF"))+"'"; + { + var hexChars = new Array(); + for(i in 0...s.length) + hexChars.push( StringTools.hex( StringTools.fastCodeAt(s,i),2 ) ); + return "x'"+ hexChars.join("") +"'"; + } return "'"+s.split("'").join("''")+"'"; } @@ -68,7 +73,7 @@ private class SqliteConnection implements Connection { } } - public function lastInsertId() { + public function lastInsertId() : Int{ return _last_id(c); } @@ -90,11 +95,16 @@ private class SqliteConnection implements Connection { startTransaction(); // match mysql usage } - static var _encode = cpp.Lib.load("std","base_encode",2); - static var _connect = cpp.Lib.load("sqlite","sqlite_connect",1); - static var _close = cpp.Lib.load("sqlite","close",1); - static var _request = cpp.Lib.load("sqlite","request",2); - static var _last_id = cpp.Lib.load("sqlite","last_insert_id",1); + + @:extern @:native("_hx_sqlite_connect") + public static function _connect(filename:String):Dynamic return null; + @:extern @:native("_hx_sqlite_request") + public static function _request(handle:Dynamic,req:String):Dynamic return null; + @:extern @:native("_hx_sqlite_close") + public static function _close(handle:Dynamic):Void { }; + @:extern @:native("_hx_sqlite_last_insert_id") + public static function _last_id(handle:Dynamic):Int return 0; + } @@ -170,15 +180,24 @@ private class SqliteResultSet implements ResultSet { return null; } - static var result_next = cpp.Lib.load("sqlite","result_next",1); - static var result_get_length = cpp.Lib.load("sqlite","result_get_length",1); - static var result_get_nfields = cpp.Lib.load("sqlite","result_get_nfields",1); - static var result_get = cpp.Lib.load("sqlite","result_get",2); - static var result_get_int = cpp.Lib.load("sqlite","result_get_int",2); - static var result_get_float = cpp.Lib.load("sqlite","result_get_float",2); + + + @:extern @:native("_hx_sqlite_result_next") + public static function result_next(handle:Dynamic):Dynamic return null; + @:extern @:native("_hx_sqlite_result_get_length") + public static function result_get_length(handle:Dynamic):Int return 0; + @:extern @:native("_hx_sqlite_result_get_nfields") + public static function result_get_nfields(handle:Dynamic):Int return 0; + @:extern @:native("_hx_sqlite_result_get") + public static function result_get(handle:Dynamic,i:Int) : String return null; + @:extern @:native("_hx_sqlite_result_get_int") + public static function result_get_int(handle:Dynamic,i:Int) : Int return 0; + @:extern @:native("_hx_sqlite_result_get_float") + public static function result_get_float(handle:Dynamic,i:Int):Float return 0.0; } +@:buildXml('') @:coreApi class Sqlite { public static function open( file : String ) : Connection { diff --git a/std/cpp/_std/sys/io/File.hx b/std/cpp/_std/sys/io/File.hx index babadf95..d193f9ee 100644 --- a/std/cpp/_std/sys/io/File.hx +++ b/std/cpp/_std/sys/io/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,16 +21,17 @@ */ package sys.io; +import cpp.NativeFile; + @:coreApi class File { public static function getContent( path : String ) : String { - var b = getBytes(path); - return b.toString(); + return NativeFile.file_contents_string(path); } public static function getBytes( path : String ) : haxe.io.Bytes { - var data:haxe.io.BytesData = file_contents(path); + var data = NativeFile.file_contents_bytes(path); return haxe.io.Bytes.ofData(data); } @@ -47,15 +48,15 @@ class File { } public static function read( path : String, binary : Bool = true ) : FileInput { - return untyped new FileInput(file_open(path,(if( binary ) "rb" else "r"))); + return untyped new FileInput(NativeFile.file_open(path,(if( binary ) "rb" else "r"))); } public static function write( path : String, binary : Bool = true ) : FileOutput { - return untyped new FileOutput(file_open(path,(if( binary ) "wb" else "w"))); + return untyped new FileOutput(NativeFile.file_open(path,(if( binary ) "wb" else "w"))); } public static function append( path : String, binary : Bool = true ) : FileOutput { - return untyped new FileOutput(file_open(path,(if( binary ) "ab" else "a"))); + return untyped new FileOutput(NativeFile.file_open(path,(if( binary ) "ab" else "a"))); } public static function copy( srcPath : String, dstPath : String ) : Void { @@ -66,8 +67,4 @@ class File { d.close(); } - private static var file_contents = cpp.Lib.load("std","file_contents",1); - private static var file_open = cpp.Lib.load("std","file_open",2); - - } diff --git a/std/cpp/_std/sys/io/FileInput.hx b/std/cpp/_std/sys/io/FileInput.hx index 1f97f6b1..08664158 100644 --- a/std/cpp/_std/sys/io/FileInput.hx +++ b/std/cpp/_std/sys/io/FileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,7 @@ */ package sys.io; import sys.io.FileSeek; +import cpp.NativeFile; @:coreApi class FileInput extends haxe.io.Input { @@ -33,7 +34,7 @@ class FileInput extends haxe.io.Input { public override function readByte() : Int { return try { - file_read_char(__f); + NativeFile.file_read_char(__f); } catch( e : Dynamic ) { if( untyped e.__IsArray() ) throw new haxe.io.Eof(); @@ -44,7 +45,7 @@ class FileInput extends haxe.io.Input { public override function readBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int { return try { - file_read(__f,s.getData(),p,l); + NativeFile.file_read(__f,s.getData(),p,l); } catch( e : Dynamic ) { if( untyped e.__IsArray() ) throw new haxe.io.Eof(); @@ -55,29 +56,20 @@ class FileInput extends haxe.io.Input { public override function close() : Void { super.close(); - file_close(__f); + NativeFile.file_close(__f); } public function seek( p : Int, pos : FileSeek ) : Void { - file_seek(__f,p,pos==SeekBegin ? 0 : pos==SeekCur ? 1 : 2 ); + NativeFile.file_seek(__f,p,pos==SeekBegin ? 0 : pos==SeekCur ? 1 : 2 ); } public function tell() : Int { - return file_tell(__f); + return NativeFile.file_tell(__f); } public function eof() : Bool { - return file_eof(__f); + return NativeFile.file_eof(__f); } - private static var file_eof = cpp.Lib.load("std","file_eof",1); - - private static var file_read = cpp.Lib.load("std","file_read",4); - private static var file_read_char = cpp.Lib.load("std","file_read_char",1); - - private static var file_close = cpp.Lib.load("std","file_close",1); - private static var file_seek = cpp.Lib.load("std","file_seek",3); - private static var file_tell = cpp.Lib.load("std","file_tell",1); - } diff --git a/std/cpp/_std/sys/io/FileOutput.hx b/std/cpp/_std/sys/io/FileOutput.hx index 1cc9d44c..e7ba92bc 100644 --- a/std/cpp/_std/sys/io/FileOutput.hx +++ b/std/cpp/_std/sys/io/FileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,7 @@ */ package sys.io; import sys.io.FileSeek; +import cpp.NativeFile; @:coreApi class FileOutput extends haxe.io.Output { @@ -32,36 +33,28 @@ class FileOutput extends haxe.io.Output { } public override function writeByte( c : Int ) : Void { - try file_write_char(__f,c) catch( e : Dynamic ) throw haxe.io.Error.Custom(e); + try NativeFile.file_write_char(__f,c) catch( e : Dynamic ) throw haxe.io.Error.Custom(e); } public override function writeBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int { - return try file_write(__f,s.getData(),p,l) catch( e : Dynamic ) throw haxe.io.Error.Custom(e); + return try NativeFile.file_write(__f,s.getData(),p,l) catch( e : Dynamic ) throw haxe.io.Error.Custom(e); } public override function flush() : Void { - file_flush(__f); + NativeFile.file_flush(__f); } public override function close() : Void { super.close(); - file_close(__f); + NativeFile.file_close(__f); } public function seek( p : Int, pos : FileSeek ) : Void { - file_seek(__f,p, pos == SeekBegin ? 0 : pos == SeekCur ? 1 : 2); + NativeFile.file_seek(__f,p, pos == SeekBegin ? 0 : pos == SeekCur ? 1 : 2); } public function tell() : Int { - return file_tell(__f); + return NativeFile.file_tell(__f); } - private static var file_close = cpp.Lib.load("std","file_close",1); - private static var file_seek = cpp.Lib.load("std","file_seek",3); - private static var file_tell = cpp.Lib.load("std","file_tell",1); - - private static var file_flush = cpp.Lib.load("std","file_flush",1); - private static var file_write = cpp.Lib.load("std","file_write",4); - private static var file_write_char = cpp.Lib.load("std","file_write_char",2); - } diff --git a/std/cpp/_std/sys/io/Process.hx b/std/cpp/_std/sys/io/Process.hx index 59d8e249..a719e501 100644 --- a/std/cpp/_std/sys/io/Process.hx +++ b/std/cpp/_std/sys/io/Process.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,8 @@ */ package sys.io; +import cpp.NativeProcess; + private class Stdin extends haxe.io.Output { var p : Dynamic; @@ -33,7 +35,7 @@ private class Stdin extends haxe.io.Output { public override function close() { super.close(); - _stdin_close(p); + NativeProcess.process_stdin_close(p); } public override function writeByte(c) { @@ -43,16 +45,13 @@ private class Stdin extends haxe.io.Output { public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { try { - return _stdin_write(p,buf.getData(),pos,len); + return NativeProcess.process_stdin_write(p,buf.getData(),pos,len); } catch( e : Dynamic ) { throw new haxe.io.Eof(); } return 0; } - static var _stdin_write = cpp.Lib.load("std","process_stdin_write",4); - static var _stdin_close = cpp.Lib.load("std","process_stdin_close",1); - } private class Stdout extends haxe.io.Input { @@ -76,17 +75,14 @@ private class Stdout extends haxe.io.Input { public override function readBytes( str : haxe.io.Bytes, pos : Int, len : Int ) : Int { var result:Int; try { - result = (out?_stdout_read:_stderr_read)(p,str.getData(),pos,len); + result = out? NativeProcess.process_stdout_read(p,str.getData(),pos,len) : + NativeProcess.process_stderr_read(p,str.getData(),pos,len); } catch( e : Dynamic ) { throw new haxe.io.Eof(); } if (result==0)throw new haxe.io.Eof(); return result; } - - static var _stdout_read = cpp.Lib.load("std","process_stdout_read",4); - static var _stderr_read = cpp.Lib.load("std","process_stderr_read",4); - } @:coreApi @@ -97,32 +93,28 @@ class Process { public var stderr(default,null) : haxe.io.Input; public var stdin(default,null) : haxe.io.Output; - public function new( cmd : String, args : Array ) : Void { - p = try _run(cmd,args) catch( e : Dynamic ) throw "Process creation failure : "+cmd; + public function new( cmd : String, ?args : Array ) : Void { + p = try NativeProcess.process_run(cmd,args) catch( e : Dynamic ) throw "Process creation failure : "+cmd; stdin = new Stdin(p); stdout = new Stdout(p,true); stderr = new Stdout(p,false); } public function getPid() : Int { - return _pid(p); + return NativeProcess.process_pid(p); } - public function exitCode() : Int { - return _exit(p); + public function exitCode( block : Bool = true ) : Null { + if( block == false ) throw "Non blocking exitCode() not supported on this platform"; + return NativeProcess.process_exit(p); } public function close() : Void { - _close(p); + NativeProcess.process_close(p); } public function kill() : Void { throw "Not implemented"; } - static var _run = cpp.Lib.load("std","process_run",2); - static var _exit = cpp.Lib.load("std","process_exit",1); - static var _pid = cpp.Lib.load("std","process_pid",1); - static var _close = cpp.Lib.loadLazy("std","process_close",1); - } diff --git a/std/cpp/_std/sys/net/Host.hx b/std/cpp/_std/sys/net/Host.hx index 3035104b..1d1177f6 100644 --- a/std/cpp/_std/sys/net/Host.hx +++ b/std/cpp/_std/sys/net/Host.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,34 +21,42 @@ */ package sys.net; +import cpp.NativeSocket; + @:coreApi class Host { + public var host(default,null) : String; + public var ip(default,null) : Int; + private var ipv6(default,null) : haxe.io.BytesData; + public function new( name : String ) : Void { - ip = host_resolve(name); + host = name; + try { + ip = NativeSocket.host_resolve(name); + } + catch(e:Dynamic) + { + ipv6 = NativeSocket.host_resolve_ipv6(name); + } } public function toString() : String { - return new String(host_to_string(ip)); + return ipv6==null ? NativeSocket.host_to_string(ip) : NativeSocket.host_to_string_ipv6(ipv6); } public function reverse() : String { - return new String(host_reverse(ip)); + return ipv6==null ? NativeSocket.host_reverse(ip) : NativeSocket.host_reverse_ipv6(ipv6); } public static function localhost() : String { - return new String(host_local()); + return NativeSocket.host_local(); } static function __init__() : Void { - cpp.Lib.load("std","socket_init",0)(); + NativeSocket.socket_init(); } - private static var host_resolve = cpp.Lib.load("std","host_resolve",1); - private static var host_reverse = cpp.Lib.load("std","host_reverse",1); - private static var host_to_string = cpp.Lib.load("std","host_to_string",1); - private static var host_local = cpp.Lib.load("std","host_local",0); - } diff --git a/std/cpp/_std/sys/net/Socket.hx b/std/cpp/_std/sys/net/Socket.hx index e6612ef4..e8710b31 100644 --- a/std/cpp/_std/sys/net/Socket.hx +++ b/std/cpp/_std/sys/net/Socket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,96 +22,91 @@ package sys.net; import haxe.io.Error; +import cpp.NativeSocket; private class SocketInput extends haxe.io.Input { - var __s : Dynamic; - - public function new(s) { - __s = s; - } - - public override function readByte() { - return try { - socket_recv_char(__s); - } catch( e : Dynamic ) { - if( e == "Blocking" ) - throw Blocked; - else if( __s == null ) - throw Custom(e); - else - throw new haxe.io.Eof(); - } - } - - public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { - var r; - if (__s==null) - throw "Invalid handle"; - try { - r = socket_recv(__s,buf.getData(),pos,len); - } catch( e : Dynamic ) { - if( e == "Blocking" ) - throw Blocked; - else - throw Custom(e); - } - if( r == 0 ) - throw new haxe.io.Eof(); - return r; - } - - public override function close() { - super.close(); - if( __s != null ) socket_close(__s); - } - - private static var socket_recv = cpp.Lib.load("std","socket_recv",4); - private static var socket_recv_char = cpp.Lib.load("std","socket_recv_char",1); - private static var socket_close = cpp.Lib.load("std","socket_close",1); + var __s : Dynamic; + + public function new(s) { + __s = s; + } + + public override function readByte() { + return try { + NativeSocket.socket_recv_char(__s); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw Blocked; + else if( __s == null ) + throw Custom(e); + else + throw new haxe.io.Eof(); + } + } + + public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { + var r; + if (__s==null) + throw "Invalid handle"; + try { + r = NativeSocket.socket_recv(__s,buf.getData(),pos,len); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw Blocked; + else + throw Custom(e); + } + if( r == 0 ) + throw new haxe.io.Eof(); + return r; + } + + public override function close() { + super.close(); + if( __s != null ) NativeSocket.socket_close(__s); + } } private class SocketOutput extends haxe.io.Output { - var __s : Dynamic; - - public function new(s) { - __s = s; - } - - public override function writeByte( c : Int ) { - if (__s==null) - throw "Invalid handle"; - try { - socket_send_char(__s, c); - } catch( e : Dynamic ) { - if( e == "Blocking" ) - throw Blocked; - else - throw Custom(e); - } - } - - public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int { - return try { - socket_send(__s, buf.getData(), pos, len); - } catch( e : Dynamic ) { - if( e == "Blocking" ) - throw Blocked; - else - throw Custom(e); - } - } - - public override function close() { - super.close(); - if( __s != null ) socket_close(__s); - } - - private static var socket_close = cpp.Lib.load("std","socket_close",1); - private static var socket_send_char = cpp.Lib.load("std","socket_send_char",2); - private static var socket_send = cpp.Lib.load("std","socket_send",4); + var __s : Dynamic; + + public function new(s) { + __s = s; + } + + public override function writeByte( c : Int ) { + if (__s==null) + throw "Invalid handle"; + try { + NativeSocket.socket_send_char(__s, c); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw Blocked; + else + throw Custom(e); + } + } + + public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int { + return try { + NativeSocket.socket_send(__s, buf.getData(), pos, len); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw Blocked; + else if (e == "EOF") + throw new haxe.io.Eof(); + else + throw Custom(e); + } + } + + public override function close() { + super.close(); + if( __s != null ) NativeSocket.socket_close(__s); + } } @@ -119,126 +114,152 @@ private class SocketOutput extends haxe.io.Output { @:coreApi class Socket { - private var __s : Dynamic; - public var input(default,null) : haxe.io.Input; - public var output(default,null) : haxe.io.Output; - public var custom : Dynamic; - - public function new() : Void { - __s = socket_new(false); - input = new SocketInput(__s); - output = new SocketOutput(__s); - } - - public function close() : Void { - socket_close(__s); - untyped { - var input : SocketInput = cast input; - var output : SocketOutput = cast output; - input.__s = null; - output.__s = null; - } - input.close(); - output.close(); - } - - public function read() : String { - var bytes:haxe.io.BytesData = socket_read(__s); - if (bytes==null) return ""; - return bytes.toString(); - } - - public function write( content : String ) : Void { - socket_write(__s, haxe.io.Bytes.ofString(content).getData() ); - } - - public function connect(host : Host, port : Int) : Void { - try { - socket_connect(__s, host.ip, port); - } catch( s : String ) { - if( s == "std@socket_connect" ) - throw "Failed to connect on "+host.toString()+":"+port; - else - cpp.Lib.rethrow(s); - } - } - - public function listen(connections : Int) : Void { - socket_listen(__s, connections); - } - - public function shutdown( read : Bool, write : Bool ) : Void { - socket_shutdown(__s,read,write); - } - - public function bind(host : Host, port : Int) : Void { - socket_bind(__s, host.ip, port); - } - - public function accept() : Socket { - var c = socket_accept(__s); - var s = Type.createEmptyInstance(Socket); - s.__s = c; - s.input = new SocketInput(c); - s.output = new SocketOutput(c); - return s; - } - - public function peer() : { host : Host, port : Int } { - var a : Dynamic = socket_peer(__s); - var h = new Host("127.0.0.1"); - untyped h.ip = a[0]; - return { host : h, port : a[1] }; - } - - public function host() : { host : Host, port : Int } { - var a : Dynamic = socket_host(__s); - var h = new Host("127.0.0.1"); - untyped h.ip = a[0]; - return { host : h, port : a[1] }; - } - - public function setTimeout( timeout : Float ) : Void { - socket_set_timeout(__s, timeout); - } - - public function waitForRead() : Void { - select([this],null,null,null); - } - - public function setBlocking( b : Bool ) : Void { - socket_set_blocking(__s,b); - } - - public function setFastSend( b : Bool ) : Void { - socket_set_fast_send(__s,b); - } - - public static function select(read : Array, write : Array, others : Array, ?timeout : Float ) : {read: Array,write: Array,others: Array} { - var neko_array = socket_select(read,write,others, timeout); - if (neko_array==null) - throw "Select error"; - return { - read: neko_array[0], - write: neko_array[1], - others: neko_array[2] - }; - } - - private static var socket_new = cpp.Lib.load("std","socket_new",1); - private static var socket_close = cpp.Lib.load("std","socket_close",1); - private static var socket_write = cpp.Lib.load("std","socket_write",2); - private static var socket_read = cpp.Lib.load("std","socket_read",1); - private static var socket_connect = cpp.Lib.load("std","socket_connect",3); - private static var socket_listen = cpp.Lib.load("std","socket_listen",2); - private static var socket_select = cpp.Lib.load("std","socket_select",4); - private static var socket_bind = cpp.Lib.load("std","socket_bind",3); - private static var socket_accept = cpp.Lib.load("std","socket_accept",1); - private static var socket_peer = cpp.Lib.load("std","socket_peer",1); - private static var socket_host = cpp.Lib.load("std","socket_host",1); - private static var socket_set_timeout = cpp.Lib.load("std","socket_set_timeout",2); - private static var socket_shutdown = cpp.Lib.load("std","socket_shutdown",3); - private static var socket_set_blocking = cpp.Lib.load("std","socket_set_blocking",2); - private static var socket_set_fast_send = cpp.Lib.loadLazy("std","socket_set_fast_send",2); + private var __s : Dynamic; + public var input(default,null) : haxe.io.Input; + public var output(default,null) : haxe.io.Output; + public var custom : Dynamic; + + public function new() : Void { + init(); + } + + private function init() : Void { + if( __s == null )__s = NativeSocket.socket_new(false); + input = new SocketInput(__s); + output = new SocketOutput(__s); + } + + public function close() : Void { + NativeSocket.socket_close(__s); + untyped { + var input : SocketInput = cast input; + var output : SocketOutput = cast output; + input.__s = null; + output.__s = null; + } + input.close(); + output.close(); + } + + public function read() : String { + var bytes:haxe.io.BytesData = NativeSocket.socket_read(__s); + if (bytes==null) return ""; + return bytes.toString(); + } + + public function write( content : String ) : Void { + NativeSocket.socket_write(__s, haxe.io.Bytes.ofString(content).getData() ); + } + + public function connect(host : Host, port : Int) : Void { + try { + if (host.ip==0) { + // hack, hack, hack + var ipv6:haxe.io.BytesData = Reflect.field(host,"ipv6"); + if (ipv6!=null) + { + close(); + __s = NativeSocket.socket_new_ip(false,true); + init(); + NativeSocket.socket_connect_ipv6(__s, ipv6, port); + } + else + throw "Unresolved host"; + } + else + NativeSocket.socket_connect(__s, host.ip, port); + } catch( s : String ) { + if( s == "Invalid socket handle" ) + throw "Failed to connect on "+host.toString()+":"+port; + else if (s == "Blocking") { + // Do nothing, this is not a real error, it simply indicates + // that a non-blocking connect is in progress + } + else + cpp.Lib.rethrow(s); + } + } + + public function listen(connections : Int) : Void { + NativeSocket.socket_listen(__s, connections); + } + + public function shutdown( read : Bool, write : Bool ) : Void { + NativeSocket.socket_shutdown(__s,read,write); + } + + public function bind(host : Host, port : Int) : Void { + if (host.ip==0) + { + var ipv6:haxe.io.BytesData = Reflect.field(host,"ipv6"); + if (ipv6!=null) + { + close(); + __s = NativeSocket.socket_new_ip(false,true); + init(); + NativeSocket.socket_bind_ipv6(__s, ipv6, port); + } + else + throw "Unresolved host"; + } + else + NativeSocket.socket_bind(__s, host.ip, port); + } + + public function accept() : Socket { + var c = NativeSocket.socket_accept(__s); + var s = Type.createEmptyInstance(Socket); + s.__s = c; + s.input = new SocketInput(c); + s.output = new SocketOutput(c); + return s; + } + + public function peer() : { host : Host, port : Int } { + var a : Dynamic = NativeSocket.socket_peer(__s); + if (a == null) { + return null; + } + var h = new Host("127.0.0.1"); + untyped h.ip = a[0]; + return { host : h, port : a[1] }; + } + + public function host() : { host : Host, port : Int } { + var a : Dynamic = NativeSocket.socket_host(__s); + if (a == null) { + return null; + } + var h = new Host("127.0.0.1"); + untyped h.ip = a[0]; + return { host : h, port : a[1] }; + } + + public function setTimeout( timeout : Float ) : Void { + NativeSocket.socket_set_timeout(__s, timeout); + } + + public function waitForRead() : Void { + select([this],null,null,null); + } + + public function setBlocking( b : Bool ) : Void { + NativeSocket.socket_set_blocking(__s,b); + } + + public function setFastSend( b : Bool ) : Void { + NativeSocket.socket_set_fast_send(__s,b); + } + + public static function select(read : Array, write : Array, others : Array, ?timeout : Float ) : {read: Array,write: Array,others: Array} { + var neko_array = NativeSocket.socket_select(read,write,others, timeout); + if (neko_array==null) + throw "Select error"; + return @:fixed { + read: neko_array[0], + write: neko_array[1], + others: neko_array[2] + }; + } } diff --git a/std/cpp/_std/sys/net/UdpSocket.hx b/std/cpp/_std/sys/net/UdpSocket.hx new file mode 100644 index 00000000..f3deae9f --- /dev/null +++ b/std/cpp/_std/sys/net/UdpSocket.hx @@ -0,0 +1,60 @@ +/* + * Copyright (C)2005-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 sys.net; +import haxe.io.Error; +import cpp.NativeSocket; + +@:coreApi +class UdpSocket extends Socket { + + private override function init() : Void { + __s = NativeSocket.socket_new(true); + super.init(); + } + + public function sendTo( buf : haxe.io.Bytes, pos : Int, len : Int, addr : Address ) : Int { + return try { + NativeSocket.socket_send_to(__s, buf.getData(), pos, len, addr); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw Blocked; + else + throw Custom(e); + } + } + + public function readFrom( buf : haxe.io.Bytes, pos : Int, len : Int, addr : Address ) : Int { + var r; + try { + r = NativeSocket.socket_recv_from(__s,buf.getData(),pos,len,addr); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw Blocked; + else + throw Custom(e); + } + if( r == 0 ) + throw new haxe.io.Eof(); + return r; + } + +} diff --git a/std/cpp/_std/sys/ssl/Certificate.hx b/std/cpp/_std/sys/ssl/Certificate.hx new file mode 100644 index 00000000..de676f4a --- /dev/null +++ b/std/cpp/_std/sys/ssl/Certificate.hx @@ -0,0 +1,115 @@ +package sys.ssl; +import cpp.NativeSsl; + +@:coreApi +class Certificate { + + var __h : Null; + var __x : Dynamic; + + @:allow(sys.ssl.Socket) + function new( x : Dynamic, ?h: Null ){ + __x = x; + __h = h; + } + + public static function loadFile( file : String ) : Certificate { + return new Certificate( NativeSsl.cert_load_file( file ) ); + } + + public static function loadPath( path : String ) : Certificate { + return new Certificate( NativeSsl.cert_load_path( path ) ); + } + + public static function fromString( str : String ) : Certificate { + return new Certificate( NativeSsl.cert_add_pem(null, str) ); + } + + public static function loadDefaults() : Certificate { + var x = NativeSsl.cert_load_defaults(); + if ( x != null ) + return new Certificate( x ); + + var defPaths = null; + switch( Sys.systemName() ){ + case "Linux": + defPaths = [ + "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. + "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL + "/etc/ssl/ca-bundle.pem", // OpenSUSE + "/etc/pki/tls/cacert.pem", // OpenELEC + "/etc/ssl/certs", // SLES10/SLES11 + "/system/etc/security/cacerts" // Android + ]; + case "BSD": + defPaths = [ + "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly + "/etc/ssl/cert.pem", // OpenBSD + "/etc/openssl/certs/ca-certificates.crt", // NetBSD + ]; + case "Android": + defPaths = ["/system/etc/security/cacerts"]; + default: + } + if( defPaths != null ){ + for ( path in defPaths ){ + if ( sys.FileSystem.exists(path) ){ + if( sys.FileSystem.isDirectory(path) ) + return loadPath(path); + else + return loadFile(path); + } + } + } + return null; + } + + public var commonName(get,null) : Null; + public var altNames(get, null) : Array; + public var notBefore(get,null) : Date; + public var notAfter(get,null) : Date; + + function get_commonName() : Null { + return subject("CN"); + } + + function get_altNames() : Array { + return NativeSsl.cert_get_altnames(__x); + } + + public function subject( field : String ) : Null { + return NativeSsl.cert_get_subject(__x, field); + } + + public function issuer( field : String ) : Null { + return NativeSsl.cert_get_issuer(__x, field); + } + + function get_notBefore() : Date { + var a = NativeSsl.cert_get_notbefore( __x ); + return new Date( a[0], a[1] - 1, a[2], a[3], a[4], a[5] ); + } + + function get_notAfter() : Date { + var a = NativeSsl.cert_get_notafter( __x ); + return new Date( a[0], a[1] - 1, a[2], a[3], a[4], a[5] ); + } + + public function next() : Null { + var n = NativeSsl.cert_get_next(__x); + return n == null ? null : new Certificate( n, __h==null ? this : __h ); + } + + public function add( pem : String ) : Void { + NativeSsl.cert_add_pem(__x,pem); + } + + public function addDER( der : haxe.io.Bytes ) : Void { + NativeSsl.cert_add_der(__x,der.getData()); + } + + static function __init__() : Void { + NativeSsl.init(); + } + +} diff --git a/std/cpp/_std/sys/ssl/Digest.hx b/std/cpp/_std/sys/ssl/Digest.hx new file mode 100644 index 00000000..ca6300b4 --- /dev/null +++ b/std/cpp/_std/sys/ssl/Digest.hx @@ -0,0 +1,19 @@ +package sys.ssl; +import cpp.NativeSsl; + +@:coreApi +class Digest { + + public static function make( data : haxe.io.Bytes, alg : DigestAlgorithm ) : haxe.io.Bytes { + return haxe.io.Bytes.ofData( NativeSsl.dgst_make( data.getData(), alg ) ); + } + + public static function sign( data : haxe.io.Bytes, privKey : Key, alg : DigestAlgorithm ) : haxe.io.Bytes { + return haxe.io.Bytes.ofData( NativeSsl.dgst_sign( data.getData(), @:privateAccess privKey.__k, alg ) ); + } + + public static function verify( data : haxe.io.Bytes, signature : haxe.io.Bytes, pubKey : Key, alg : DigestAlgorithm ) : Bool{ + return NativeSsl.dgst_verify( data.getData(), signature.getData(), @:privateAccess pubKey.__k, alg ); + } + +} diff --git a/std/cpp/_std/sys/ssl/Key.hx b/std/cpp/_std/sys/ssl/Key.hx new file mode 100644 index 00000000..b078855d --- /dev/null +++ b/std/cpp/_std/sys/ssl/Key.hx @@ -0,0 +1,36 @@ +package sys.ssl; +import cpp.NativeSsl; + +private typedef PKEY = Dynamic; + +@:coreApi +class Key { + + private var __k : PKEY; + + private function new( k : PKEY ){ + __k = k; + } + + public static function loadFile( file : String, ?isPublic : Bool, ?pass : String ) : Key { + var data = sys.io.File.getBytes( file ); + var str = cpp.Lib.stringReference(data); + if( str.indexOf("-----BEGIN ") >= 0 ) + return readPEM( str, isPublic==true, pass ); + else + return readDER( data, isPublic==true ); + } + + public static function readPEM( data : String, isPublic : Bool, ?pass : String ) : Key { + return new Key( NativeSsl.key_from_pem( data, isPublic, pass ) ); + } + + public static function readDER( data : haxe.io.Bytes, isPublic : Bool ) : Key { + return new Key( NativeSsl.key_from_der( data.getData(), isPublic ) ); + } + + static function __init__() : Void { + NativeSsl.init(); + } + +} diff --git a/std/cpp/_std/sys/ssl/Socket.hx b/std/cpp/_std/sys/ssl/Socket.hx new file mode 100644 index 00000000..204ffc41 --- /dev/null +++ b/std/cpp/_std/sys/ssl/Socket.hx @@ -0,0 +1,268 @@ +package sys.ssl; +import cpp.NativeSocket; +import cpp.NativeSsl; + +private typedef SocketHandle = Dynamic; +private typedef CONF = Dynamic; +private typedef SSL = Dynamic; + +private class SocketInput extends haxe.io.Input { + @:allow(sys.ssl.Socket) private var __s : Socket; + + public function new( s : Socket ) { + this.__s = s; + } + + public override function readByte() { + return try { + __s.handshake(); + NativeSsl.ssl_recv_char( @:privateAccess __s.ssl ); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw haxe.io.Error.Blocked; + else if( __s == null ) + throw haxe.io.Error.Custom(e); + else + throw new haxe.io.Eof(); + } + } + + public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { + var r : Int; + if( __s == null ) + throw "Invalid handle"; + try { + __s.handshake(); + r = NativeSsl.ssl_recv( @:privateAccess __s.ssl, buf.getData(), pos, len ); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw haxe.io.Error.Blocked; + else + throw haxe.io.Error.Custom(e); + } + if( r == 0 ) + throw new haxe.io.Eof(); + return r; + } + + public override function close() { + super.close(); + if( __s != null ) __s.close(); + } + +} + +private class SocketOutput extends haxe.io.Output { + @:allow(sys.ssl.Socket) private var __s : Socket; + + public function new( s : Socket ) { + this.__s = s; + } + + public override function writeByte( c : Int ) { + if( __s == null ) + throw "Invalid handle"; + try { + __s.handshake(); + NativeSsl.ssl_send_char( @:privateAccess __s.ssl, c ); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw haxe.io.Error.Blocked; + else + throw haxe.io.Error.Custom(e); + } + } + + public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int { + return try { + __s.handshake(); + NativeSsl.ssl_send( @:privateAccess __s.ssl, buf.getData(), pos, len ); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw haxe.io.Error.Blocked; + else + throw haxe.io.Error.Custom(e); + } + } + + public override function close() { + super.close(); + if( __s != null ) __s.close(); + } + +} + +@:coreApi +class Socket extends sys.net.Socket { + + public static var DEFAULT_VERIFY_CERT : Null = true; + + public static var DEFAULT_CA : Null; + + private var conf : CONF; + private var ssl : SSL; + + public var verifyCert : Null; + private var caCert : Null; + private var hostname : String; + + private var ownCert : Null; + private var ownKey : Null; + private var altSNIContexts : NullBool, key: Key, cert: Certificate}>>; + private var sniCallback : Dynamic; + private var handshakeDone : Bool; + + private override function init() : Void { + __s = NativeSocket.socket_new( false ); + input = new SocketInput( this ); + output = new SocketOutput( this ); + if( DEFAULT_VERIFY_CERT && DEFAULT_CA == null ){ + try { + DEFAULT_CA = Certificate.loadDefaults(); + }catch( e : Dynamic ){} + } + caCert = DEFAULT_CA; + verifyCert = DEFAULT_VERIFY_CERT; + } + + public override function connect(host : sys.net.Host, port : Int) : Void { + try { + conf = buildSSLConfig( false ); + ssl = NativeSsl.ssl_new( conf ); + handshakeDone = false; + NativeSsl.ssl_set_socket( ssl, __s ); + if( hostname == null ) + hostname = host.host; + if( hostname != null ) + NativeSsl.ssl_set_hostname( ssl, hostname ); + NativeSocket.socket_connect( __s, host.ip, port ); + handshake(); + } catch( s : String ) { + if( s == "Invalid socket handle" ) + throw "Failed to connect on "+host.host+":"+port; + else + cpp.Lib.rethrow(s); + } catch( e : Dynamic ) { + cpp.Lib.rethrow(e); + } + } + + public function handshake() : Void { + if( !handshakeDone ){ + try { + NativeSsl.ssl_handshake( ssl ); + handshakeDone = true; + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw haxe.io.Error.Blocked; + else + cpp.Lib.rethrow( e ); + } + } + } + + public function setCA( cert : Certificate ) : Void { + caCert = cert; + } + + public function setHostname( name : String ) : Void { + hostname = name; + } + + public function setCertificate( cert : Certificate, key : Key ) : Void { + ownCert = cert; + ownKey = key; + } + + public override function read() : String { + handshake(); + var b = NativeSsl.ssl_read( ssl ); + if( b == null ) + return ""; + return haxe.io.Bytes.ofData(b).toString(); + } + + public override function write( content : String ) : Void { + handshake(); + NativeSsl.ssl_write( ssl, haxe.io.Bytes.ofString(content).getData() ); + } + + public override function close() : Void { + if( ssl != null ) NativeSsl.ssl_close( ssl ); + if( conf != null ) NativeSsl.conf_close( conf ); + if( altSNIContexts != null ) + sniCallback = null; + NativeSocket.socket_close( __s ); + var input : SocketInput = cast input; + var output : SocketOutput = cast output; + @:privateAccess input.__s = output.__s = null; + input.close(); + output.close(); + } + + public function addSNICertificate( cbServernameMatch : String->Bool, cert : Certificate, key : Key ) : Void { + if( altSNIContexts == null ) + altSNIContexts = []; + altSNIContexts.push( {match: cbServernameMatch, cert: cert, key: key} ); + } + + public override function bind( host : sys.net.Host, port : Int ) : Void { + conf = buildSSLConfig( true ); + + NativeSocket.socket_bind( __s, host.ip, port ); + } + + public override function accept() : Socket { + var c = NativeSocket.socket_accept( __s ); + var ssl = NativeSsl.ssl_new( conf ); + NativeSsl.ssl_set_socket( ssl, c ); + + var s = Type.createEmptyInstance( sys.ssl.Socket ); + s.__s = c; + s.ssl = ssl; + s.input = new SocketInput(s); + s.output = new SocketOutput(s); + s.handshakeDone = false; + + return s; + } + + public function peerCertificate() : sys.ssl.Certificate { + var x = NativeSsl.ssl_get_peer_certificate( ssl ); + return x==null ? null : new sys.ssl.Certificate( x ); + } + + private function buildSSLConfig( server : Bool ) : CONF { + var conf : CONF = NativeSsl.conf_new( server ); + + if( ownCert != null && ownKey != null ) + NativeSsl.conf_set_cert( conf, @:privateAccess ownCert.__x, @:privateAccess ownKey.__k ); + + if ( altSNIContexts != null ) { + sniCallback = function(servername) { + var servername = new String(cast servername); + for( c in altSNIContexts ){ + if( c.match(servername) ) + return @:privateAccess {key: c.key.__k, cert: c.cert.__x}; + } + if( ownKey != null && ownCert != null ) + return @:privateAccess { key: ownKey.__k, cert: ownCert.__x }; + return null; + } + NativeSsl.conf_set_servername_callback( conf, sniCallback ); + } + + if ( caCert != null ) + NativeSsl.conf_set_ca( conf, caCert == null ? null : @:privateAccess caCert.__x ); + if( verifyCert == null ) + NativeSsl.conf_set_verify( conf, 2 ); + else + NativeSsl.conf_set_verify( conf, verifyCert ? 1 : 0 ); + + return conf; + } + + static function __init__() : Void { + NativeSsl.init(); + } +} diff --git a/std/cpp/abi/Abi.hx b/std/cpp/abi/Abi.hx index 4e65c89e..c3130809 100644 --- a/std/cpp/abi/Abi.hx +++ b/std/cpp/abi/Abi.hx @@ -1,4 +1,25 @@ -package cpp.abi; +/* + * Copyright (C)2005-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 cpp.abi; // Base case, for calling conventions - means "use default" extern class Abi { } diff --git a/std/cpp/abi/CDecl.hx b/std/cpp/abi/CDecl.hx index dd754e40..8b8cf6f5 100644 --- a/std/cpp/abi/CDecl.hx +++ b/std/cpp/abi/CDecl.hx @@ -1,4 +1,25 @@ -package cpp.abi; +/* + * Copyright (C)2005-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 cpp.abi; @:abi("__cdecl") extern class CDecl extends Abi { } diff --git a/std/cpp/abi/FastCall.hx b/std/cpp/abi/FastCall.hx index a8802b71..921bfa2f 100644 --- a/std/cpp/abi/FastCall.hx +++ b/std/cpp/abi/FastCall.hx @@ -1,4 +1,25 @@ -package cpp.abi; +/* + * Copyright (C)2005-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 cpp.abi; @:abi("__fastcall") extern class FastCall extends Abi { } diff --git a/std/cpp/abi/StdCall.hx b/std/cpp/abi/StdCall.hx index 3e0fd817..271f3d79 100644 --- a/std/cpp/abi/StdCall.hx +++ b/std/cpp/abi/StdCall.hx @@ -1,4 +1,25 @@ -package cpp.abi; +/* + * Copyright (C)2005-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 cpp.abi; @:abi("__stdcall") extern class StdCall extends Abi { } diff --git a/std/cpp/abi/ThisCall.hx b/std/cpp/abi/ThisCall.hx index 1e98f0e7..077f8294 100644 --- a/std/cpp/abi/ThisCall.hx +++ b/std/cpp/abi/ThisCall.hx @@ -1,4 +1,25 @@ -package cpp.abi; +/* + * Copyright (C)2005-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 cpp.abi; @:abi("__thiscall") extern class ThisCall extends Abi { } diff --git a/std/cpp/abi/Winapi.hx b/std/cpp/abi/Winapi.hx index 4a57e31d..1ad8dd7b 100644 --- a/std/cpp/abi/Winapi.hx +++ b/std/cpp/abi/Winapi.hx @@ -1,4 +1,25 @@ -package cpp.abi; +/* + * Copyright (C)2005-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 cpp.abi; @:abi("__stdcall") extern class Winapi extends Abi { } diff --git a/std/cpp/cppia/Host.hx b/std/cpp/cppia/Host.hx index dac1e758..5efd1e9e 100644 --- a/std/cpp/cppia/Host.hx +++ b/std/cpp/cppia/Host.hx @@ -1,14 +1,42 @@ -package cpp.cppia; +/* + * Copyright (C)2005-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 cpp.cppia; -@:build(cpp.cppia.HostClasses.include()) class Host { public static function run(source:String) { - untyped __global__.__scriptable_load_cppia(source); + var module = Module.fromString(source); + module.boot(); + module.run(); } + public static function runFile(filename:String) + { + run( sys.io.File.getContent(filename) ); + } + + public static function main() { var script = Sys.args()[0]; @@ -22,7 +50,9 @@ class Host else { var source = sys.io.File.getContent(script); - run(source); + var module = Module.fromString(source); + module.boot(); + module.run(); } } } diff --git a/std/cpp/cppia/HostClasses.hx b/std/cpp/cppia/HostClasses.hx index d2b9c664..5f371114 100644 --- a/std/cpp/cppia/HostClasses.hx +++ b/std/cpp/cppia/HostClasses.hx @@ -1,4 +1,25 @@ -package cpp.cppia; +/* + * Copyright (C)2005-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 cpp.cppia; import haxe.macro.Compiler; import haxe.macro.Context; @@ -38,19 +59,22 @@ class HostClasses "StringBuf", "sys.db.Mysql", "sys.db.Sqlite", - "sys.db.Object", - "sys.db.Manager", - "sys.db.Connection", "sys.FileSystem", "sys.io.File", "sys.io.FileInput", + "sys.net.UdpSocket", "sys.net.Socket", + "sys.ssl.Certificate", + "sys.ssl.Digest", + "sys.ssl.Key", + "sys.ssl.Socket", "Enum", "EnumValue", //"Sys", "Type", "Xml", "Date", + "Lambda", "DateTools", "List", "Math", @@ -61,6 +85,7 @@ class HostClasses "haxe.ds.IntMap", "haxe.ds.ObjectMap", "haxe.ds.StringMap", + "haxe.ds.BalancedTree", "haxe.CallStack", "haxe.Serializer", "haxe.Unserializer", @@ -68,6 +93,7 @@ class HostClasses "haxe.Template", "haxe.Utf8", "haxe.Log", + "haxe.zip.Compress", "haxe.zip.Uncompress", "haxe.crypto.BaseCode", @@ -78,7 +104,7 @@ class HostClasses "haxe.crypto.Adler32", "haxe.crypto.Md5", "haxe.crypto.Sha1", - + "haxe.io.BufferInput", "haxe.io.Bytes", "haxe.io.BytesBuffer", @@ -123,7 +149,7 @@ class HostClasses "EReg", "Enum", "EnumValue", - "IntIterator", + // "IntIterator", "List", "Map", "String", @@ -163,6 +189,18 @@ class HostClasses externs.set("haxe._Int64.___Int64",true); externs.set("haxe._Int32.Int32_Impl_",true); externs.set("haxe._Int32.___Int32",true); + // Hidded in implementation classes + //externs.set("sys.db.RecordType",true); + externs.set("sys.db._Sqlite.SqliteConnection",true); + externs.set("sys.db._Sqlite.SqliteResultSet",true); + externs.set("sys.db._Mysql.MysqlConnection",true); + externs.set("sys.db._Mysql.MysqlResultSet",true); + externs.set("sys.net._Socket.SocketInput",true); + externs.set("sys.net._Socket.SocketOutput",true); + externs.set("sys.ssl._Socket.SocketInput",true); + externs.set("sys.ssl._Socket.SocketOutput",true); + externs.set("haxe.ds.TreeNode",true); + externs.set("haxe.xml.XmlParserException",true); for(e in classes) externs.set(e,true); diff --git a/std/cpp/cppia/Module.hx b/std/cpp/cppia/Module.hx new file mode 100644 index 00000000..8bcbee36 --- /dev/null +++ b/std/cpp/cppia/Module.hx @@ -0,0 +1,35 @@ +/* + * Copyright (C)2005-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 cpp.cppia; + + +@:native("hx::CppiaLoadedModule") +@:build(cpp.cppia.HostClasses.include()) +extern class Module +{ + @:native("__scriptable_cppia_from_string") + public static function fromString(sourceCode:String) : Module; + public function boot():Void; + public function run():Void; + public function resolveClass(inName:String):Class; +} + diff --git a/std/cpp/link/StaticMysql.hx b/std/cpp/link/StaticMysql.hx index 75d5e448..bf6a487f 100644 --- a/std/cpp/link/StaticMysql.hx +++ b/std/cpp/link/StaticMysql.hx @@ -1,5 +1,30 @@ +/* + * Copyright (C)2005-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 cpp.link; +#if (hxcpp_api_level>=330) +class StaticMysql { } +#else + @:cppFileCode( 'extern "C" int mysql_register_prims();') @:buildXml(" @@ -15,3 +40,4 @@ package cpp.link; } } +#end diff --git a/std/cpp/link/StaticRegexp.hx b/std/cpp/link/StaticRegexp.hx index 74a8cdfb..9e470c18 100644 --- a/std/cpp/link/StaticRegexp.hx +++ b/std/cpp/link/StaticRegexp.hx @@ -1,5 +1,30 @@ +/* + * Copyright (C)2005-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 cpp.link; +#if (hxcpp_api_level>=330) +class StaticRegexp { } +#else + @:cppFileCode( 'extern "C" int regexp_register_prims();') @:buildXml(" @@ -14,3 +39,4 @@ package cpp.link; } } +#end diff --git a/std/cpp/link/StaticSqlite.hx b/std/cpp/link/StaticSqlite.hx index 1e382f13..dcc34722 100644 --- a/std/cpp/link/StaticSqlite.hx +++ b/std/cpp/link/StaticSqlite.hx @@ -1,5 +1,30 @@ +/* + * Copyright (C)2005-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 cpp.link; +#if (hxcpp_api_level>=330) +class StaticSqlite { } +#else + @:cppFileCode( 'extern "C" int sqlite_register_prims();') @:buildXml(" @@ -15,3 +40,4 @@ package cpp.link; } } +#end diff --git a/std/cpp/link/StaticStd.hx b/std/cpp/link/StaticStd.hx index a58166d8..d65097c3 100644 --- a/std/cpp/link/StaticStd.hx +++ b/std/cpp/link/StaticStd.hx @@ -1,5 +1,30 @@ +/* + * Copyright (C)2005-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 cpp.link; +#if (hxcpp_api_level>=330) +class StaticStd { } +#else + @:cppFileCode( 'extern "C" int std_register_prims();') @:buildXml(" @@ -15,3 +40,4 @@ package cpp.link; } } +#end diff --git a/std/cpp/link/StaticZlib.hx b/std/cpp/link/StaticZlib.hx index 471000a0..ef71a568 100644 --- a/std/cpp/link/StaticZlib.hx +++ b/std/cpp/link/StaticZlib.hx @@ -1,5 +1,30 @@ +/* + * Copyright (C)2005-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 cpp.link; +#if (hxcpp_api_level>=330) +class StaticZlib { } +#else + @:cppFileCode( 'extern "C" int zlib_register_prims();') @:buildXml(" @@ -14,3 +39,5 @@ package cpp.link; } } +#end + diff --git a/std/cpp/net/Poll.hx b/std/cpp/net/Poll.hx index 08bd05b2..58a502d4 100644 --- a/std/cpp/net/Poll.hx +++ b/std/cpp/net/Poll.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,46 +21,34 @@ */ package cpp.net; import sys.net.Socket; +import cpp.NativeSocket; class Poll { var mPollHandle : Dynamic; - public var readIndexes : Array; - public var writeIndexes : Array; + public var readIndexes : Array; + public var writeIndexes : Array; public function new( n : Int ) { - mPollHandle = socket_poll_alloc(n); + mPollHandle = NativeSocket.socket_poll_alloc(n); readIndexes = []; writeIndexes = []; } public function prepare( read : Array, write : Array ) { - var k = socket_poll_prepare(mPollHandle,read,write); + var k = NativeSocket.socket_poll_prepare(mPollHandle,read,write); readIndexes = k[0]; writeIndexes = k[1]; } public function events( ?t : Float ) { if (t==null) t=-1.0; - socket_poll_events(mPollHandle,t); + NativeSocket.socket_poll_events(mPollHandle,t); } public function poll( a : Array, ?t : Float ) : Array { if (t==null) t=-1.0; - var read:Array = socket_poll(a,mPollHandle,t); - // Convert to array of sockets... - var result = new Array(); - if (read!=null && read.length>0) { - result[read.length-1]=null; - for(i in 0...read.length) - result[i] = read[i]; - } - return result; + return NativeSocket.socket_poll(a,mPollHandle,t); } - static var socket_poll_alloc = cpp.Lib.load("std","socket_poll_alloc",1); - static var socket_poll = cpp.Lib.load("std","socket_poll",3); - static var socket_poll_prepare = cpp.Lib.loadLazy("std","socket_poll_prepare",3); - static var socket_poll_events = cpp.Lib.loadLazy("std","socket_poll_events",2); - } diff --git a/std/cpp/net/ThreadServer.hx b/std/cpp/net/ThreadServer.hx index ebc996ae..54d85fae 100644 --- a/std/cpp/net/ThreadServer.hx +++ b/std/cpp/net/ThreadServer.hx @@ -1,5 +1,5 @@ /* -* Copyright (C)2005-2013 Haxe Foundation +* Copyright (C)2005-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"), @@ -40,22 +40,65 @@ private typedef ClientInfos = { var bufpos : Int; } +/** + The ThreadServer can be used to easily create a multithreaded server where each thread polls multiple connections. + To use it, at a minimum you must override or rebind clientConnected, readClientMessage, and clientMessage and you must define your Client and Message. +**/ class ThreadServer { var threads : Array; var sock : sys.net.Socket; var worker : Thread; var timer : Thread; + + /** + Number of total connections the server will accept. + **/ public var listen : Int; + + /** + Number of server threads. + **/ public var nthreads : Int; + + /** + Polling timeout. + **/ public var connectLag : Float; + + /** + Stream to send error messages. + **/ public var errorOutput : haxe.io.Output; + + /** + Space allocated to buffers when they are created. + **/ public var initialBufferSize : Int; + + /** + Maximum size of buffered data read from a socket. An exception is thrown if the buffer exceeds this value. + **/ public var maxBufferSize : Int; + + /** + Minimum message size. + **/ public var messageHeaderSize : Int; + + /** + Time between calls to update. + **/ public var updateTime : Float; + + /** + The most sockets a thread will handle. + **/ public var maxSockPerThread : Int; + /** + Creates a ThreadServer. + **/ public function new() { threads = new Array(); nthreads = if( Sys.systemName() == "Windows" ) 150 else 10; @@ -156,6 +199,9 @@ class ThreadServer { } } + /** + Internally used to delegate something to the worker thread. + **/ public function work( f : Void -> Void ) { worker.sendMessage(f); } @@ -216,11 +262,17 @@ class ThreadServer { } } + /** + Called when the server gets a new connection. + **/ public function addSocket( s : sys.net.Socket ) { s.setBlocking(false); work(addClient.bind(s)); } + /** + Start the server at the specified host and port. + **/ public function run( host, port ) { sock = new sys.net.Socket(); sock.bind(new sys.net.Host(host),port); @@ -235,6 +287,9 @@ class ThreadServer { } } + /** + Send data to a client. + **/ public function sendData( s : sys.net.Socket, data : String ) { try { s.write(data); @@ -243,6 +298,9 @@ class ThreadServer { } } + /** + Shutdown a client's connection and remove them from the server. + **/ public function stopClient( s : sys.net.Socket ) { var infos : ClientInfos = s.custom; try s.shutdown(true,true) catch( e : Dynamic ) { }; @@ -251,19 +309,33 @@ class ThreadServer { // --- CUSTOMIZABLE API --- + /** + Called when an error has ocurred. + **/ public dynamic function onError( e : Dynamic, stack ) { var estr = try Std.string(e) catch( e2 : Dynamic ) "???" + try "["+Std.string(e2)+"]" catch( e : Dynamic ) ""; errorOutput.writeString( estr + "\n" + haxe.CallStack.toString(stack) ); errorOutput.flush(); } + /** + Called when a client connects. Returns a client object. + **/ public dynamic function clientConnected( s : sys.net.Socket ) : Client { return null; } + /** + Called when a client disconnects or an error forces the connection to close. + **/ public dynamic function clientDisconnected( c : Client ) { } + /** + Called when data has been read from a socket. This method should try to extract a message from the buffer. + The available data resides in buf, starts at pos, and is len bytes wide. Return the new message and the number of bytes read from the buffer. + If no message could be read, return null. + **/ public dynamic function readClientMessage( c : Client, buf : haxe.io.Bytes, pos : Int, len : Int ) : { msg : Message, bytes : Int } { return { msg : null, @@ -271,12 +343,21 @@ class ThreadServer { }; } + /** + Called when a message has been recieved. Message handling code should go here. + **/ public dynamic function clientMessage( c : Client, msg : Message ) { } + /** + This method is called periodically. It can be used to do server maintenance. + **/ public dynamic function update() { } + /** + Called after a client connects, disconnects, a message is received, or an update is performed. + **/ public dynamic function afterEvent() { } diff --git a/std/cpp/objc/NSData.hx b/std/cpp/objc/NSData.hx new file mode 100644 index 00000000..9980c8bd --- /dev/null +++ b/std/cpp/objc/NSData.hx @@ -0,0 +1,51 @@ +/* + * Copyright (C)2005-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 cpp.objc; + +@:native("NSData") @:objc extern class NSDataData { } + +@:objc +extern abstract NSData( NSDataData ) +{ + @:native("_hx_value_to_objc") @:extern static function to_data(b:haxe.io.BytesData) : NSData return null; + @:native("_hx_value_to_objc") @:extern static function to_data_data(b:haxe.io.BytesData) : NSDataData return null; + @:native("_hx_objc_to_bytes") @:extern static function NSDataDataToBytes(d:NSDataData) : haxe.io.BytesData return null; + + + inline function new(d:NSDataData) this = d; + + @:from @:extern + static public inline function fromBytesData(d:haxe.io.BytesData):NSData return new NSData( to_data_data(d) ); + + @:from @:extern + static public inline function fromBytes(d:haxe.io.Bytes):NSData return new NSData( to_data_data(d.getData()) ); + + @:to @:extern + public inline function toBytesData():haxe.io.BytesData return NSDataDataToBytes(this); + + @:to @:extern + public inline function toBytes():haxe.io.Bytes return haxe.io.Bytes.ofData(NSDataDataToBytes(this)); + + @:to @:extern public inline function toNSObject():NSObject return cast this; + +} + diff --git a/std/cpp/objc/NSDictionary.hx b/std/cpp/objc/NSDictionary.hx new file mode 100644 index 00000000..a8dd97d6 --- /dev/null +++ b/std/cpp/objc/NSDictionary.hx @@ -0,0 +1,44 @@ +/* + * Copyright (C)2005-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 cpp.objc; + +@:native("NSDictionary") @:objc extern class DictionaryData { } + +@:objc +extern abstract NSDictionary( DictionaryData ) +{ + @:native("_hx_obj_to_nsdictionary") @:extern static function _hx_obj_to_nsdictionary(obj:Dynamic) : DictionaryData return null; + @:native("_hx_nsdictionary_to_obj") @:extern static function _hx_nsdictionary_to_obj(d:DictionaryData) : Dynamic return null; + + + inline function new(dict:DictionaryData) this = dict; + + @:from @:extern + static public inline function fromDynamic(o:Dynamic):NSDictionary return new NSDictionary( _hx_obj_to_nsdictionary(o) ); + + @:to @:extern + public inline function toDynamic():Dynamic return _hx_nsdictionary_to_obj(this); + + @:to @:extern public inline function toNSObject():NSObject return cast this; + +} + diff --git a/std/js/html/DOMPlugin.hx b/std/cpp/objc/NSError.hx similarity index 85% rename from std/js/html/DOMPlugin.hx rename to std/cpp/objc/NSError.hx index ccd57269..2510d66d 100644 --- a/std/js/html/DOMPlugin.hx +++ b/std/cpp/objc/NSError.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,9 +19,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +package cpp.objc; -package js.html; +@:objc +@:native("NSError") +extern class NSError +{ + public var localizedDescription(default,null):NSString; +} -/** @deprecated Use Plugin instead. */ -@:deprecated("DOMPlugin is deprecated, use Plugin instead") -typedef DOMPlugin = Plugin; diff --git a/std/cpp/objc/NSLog.hx b/std/cpp/objc/NSLog.hx new file mode 100644 index 00000000..9bba4c32 --- /dev/null +++ b/std/cpp/objc/NSLog.hx @@ -0,0 +1,33 @@ +/* + * Copyright (C)2005-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 cpp.objc; + +extern class NSLog +{ + @:native("NSLog") + @:overload(function(format:NSString,a0:NSObject):Void { }) + @:overload(function(format:NSString,a0:NSObject,a1:NSObject):Void { }) + public static function log(format:NSString):Void; + +} + + diff --git a/std/cpp/objc/NSObject.hx b/std/cpp/objc/NSObject.hx new file mode 100644 index 00000000..9c8398d8 --- /dev/null +++ b/std/cpp/objc/NSObject.hx @@ -0,0 +1,44 @@ +/* + * Copyright (C)2005-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 cpp.objc; + +@:native("id") @:objc extern class NSObjectData { } + +@:objc +extern abstract NSObject( NSObjectData ) +{ + @:native("_hx_value_to_objc") @:extern static function _hx_value_to_objc(obj:Dynamic) : NSObject return null; + @:native("_hx_objc_to_dynamic") @:extern static function _hx_objc_to_dynamic(d:NSObjectData) : Dynamic return null; + + + inline function new(d:NSObjectData) this = d; + + + @:from @:extern + static public inline function fromHaxe(d:Dynamic):NSObject return _hx_value_to_objc(d); + + + @:to @:extern + public inline function toHaxe():Dynamic return _hx_objc_to_dynamic(this); +} + + diff --git a/std/cpp/objc/NSString.hx b/std/cpp/objc/NSString.hx new file mode 100644 index 00000000..c82e228b --- /dev/null +++ b/std/cpp/objc/NSString.hx @@ -0,0 +1,45 @@ +/* + * Copyright (C)2005-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 cpp.objc; + +@:native("NSString") @:objc extern class NSStringData { } + +@:objc +extern abstract NSString( NSStringData ) +{ + inline function new(s:NSStringData) this = s; + @:native("(id)") @:extern static function toObject(d:NSStringData) : NSObject return null; + + @:native("(NSString *)") @:extern static function castFromString(s:String) : NSString return null; + @:native("String") @:extern static function castToString(s:NSStringData) : String return null; + + + @:from @:extern + static public inline function fromString(s:String):NSString return castFromString(s); + + + @:to @:extern + public inline function toString():String return castToString(this); + + @:to @:extern public inline function toNSObject():NSObject return toObject(this); +} + diff --git a/std/cpp/objc/ObjcBlock.hx b/std/cpp/objc/ObjcBlock.hx new file mode 100644 index 00000000..4075faaa --- /dev/null +++ b/std/cpp/objc/ObjcBlock.hx @@ -0,0 +1,27 @@ +/* + * Copyright (C)2005-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 cpp.objc; + +@:objc +typedef ObjcBlock = T; + + diff --git a/std/cpp/objc/Protocol.hx b/std/cpp/objc/Protocol.hx new file mode 100644 index 00000000..1c5c4d92 --- /dev/null +++ b/std/cpp/objc/Protocol.hx @@ -0,0 +1,27 @@ +/* + * Copyright (C)2005-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 cpp.objc; + +@:objc +typedef Protocol = T; + + diff --git a/std/cpp/rtti/FieldIntegerLookup.hx b/std/cpp/rtti/FieldIntegerLookup.hx index 9b9ad7c3..86908b8c 100644 --- a/std/cpp/rtti/FieldIntegerLookup.hx +++ b/std/cpp/rtti/FieldIntegerLookup.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cpp/rtti/FieldNumericIntegerLookup.hx b/std/cpp/rtti/FieldNumericIntegerLookup.hx index baf3d9d3..bc04b1d3 100644 --- a/std/cpp/rtti/FieldNumericIntegerLookup.hx +++ b/std/cpp/rtti/FieldNumericIntegerLookup.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cpp/vm/Debugger.hx b/std/cpp/vm/Debugger.hx index 1dc517bb..acfac5bf 100644 --- a/std/cpp/vm/Debugger.hx +++ b/std/cpp/vm/Debugger.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -279,7 +279,7 @@ class Debugger * Breaks all threads except the debugger thread (which should be the same * as the calling thread!). * - * If [wait] is true, waits up to 2 seconds for all threads to be broken. + * If `wait` is true, waits up to 2 seconds for all threads to be broken. * Threads which are in blocking system calls and cannot break after 2 * seconds remain running when this function returns. **/ @@ -291,7 +291,7 @@ class Debugger /** * Continue execution of all stopped threads. If specialThreadNumber * is a valid thread number, then it will be continued past - * [continueCount] breakpoints instead of just 1 like all of the other + * `continueCount` breakpoints instead of just 1 like all of the other * threads. **/ public static function continueThreads(specialThreadNumber : Int, diff --git a/std/cpp/vm/Deque.hx b/std/cpp/vm/Deque.hx index 999afe52..df6859f8 100644 --- a/std/cpp/vm/Deque.hx +++ b/std/cpp/vm/Deque.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cpp/vm/ExecutionTrace.hx b/std/cpp/vm/ExecutionTrace.hx index 773bcf16..a9a9e579 100644 --- a/std/cpp/vm/ExecutionTrace.hx +++ b/std/cpp/vm/ExecutionTrace.hx @@ -1,4 +1,25 @@ -package cpp.vm; +/* + * Copyright (C)2005-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 cpp.vm; class ExecutionTrace { diff --git a/std/cpp/vm/Gc.hx b/std/cpp/vm/Gc.hx index be6b593e..7aa0f861 100644 --- a/std/cpp/vm/Gc.hx +++ b/std/cpp/vm/Gc.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -52,12 +52,19 @@ class Gc // MEM_INFO_LARGE - Size of separate pool used for large allocs. Included in all the above. static public function memInfo(inWhatInfo:Int) : Int { - return untyped __global__.__hxcpp_gc_mem_info(inWhatInfo); + return Std.int(NativeGc.memInfo(inWhatInfo)); } + // Returns Float + static public function memInfo64(inWhatInfo:Int) : Float + { + return NativeGc.memInfo(inWhatInfo); + } + + static public function memUsage() : Int { - return untyped __global__.__hxcpp_gc_mem_info(MEM_INFO_USAGE); + return Std.int(NativeGc.memInfo(MEM_INFO_USAGE)); } static public function trace(sought:Class,printInstances:Bool=true) : Int @@ -92,6 +99,21 @@ class Gc untyped __global__.__hxcpp_exit_gc_free_zone(); } + static public function setMinimumFreeSpace(inBytes:Int) : Void + { + untyped __global__.__hxcpp_set_minimum_free_space(inBytes); + } + + static public function setTargetFreeSpacePercentage(inPercentage:Int) : Void + { + untyped __global__.__hxcpp_set_target_free_space_percentage(inPercentage); + } + + static public function setMinimumWorkingMemory(inBytes:Int) : Void + { + untyped __global__.__hxcpp_set_minimum_working_memory(inBytes); + } + @:unreflective inline static public function setFinalizer(inObject:T, inFinalizer:cpp.CallableVoid> ) : Void { diff --git a/std/cpp/vm/Lock.hx b/std/cpp/vm/Lock.hx index 5b65939c..bcde565e 100644 --- a/std/cpp/vm/Lock.hx +++ b/std/cpp/vm/Lock.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cpp/vm/Mutex.hx b/std/cpp/vm/Mutex.hx index 6c0759e2..926e0992 100644 --- a/std/cpp/vm/Mutex.hx +++ b/std/cpp/vm/Mutex.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cpp/vm/Profiler.hx b/std/cpp/vm/Profiler.hx index 8d2f9eb7..256ff70d 100644 --- a/std/cpp/vm/Profiler.hx +++ b/std/cpp/vm/Profiler.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cpp/vm/Thread.hx b/std/cpp/vm/Thread.hx index db7fec68..1c23f1d1 100644 --- a/std/cpp/vm/Thread.hx +++ b/std/cpp/vm/Thread.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -32,7 +32,7 @@ class Thread { } /** - Send a message to the thread queue. This message can be readed by using [readMessage]. + Send a message to the thread queue. This message can be read by using `readMessage`. **/ public function sendMessage( msg : Dynamic ) { untyped __global__.__hxcpp_thread_send(handle,msg); @@ -47,16 +47,16 @@ class Thread { } /** - Creates a new thread that will execute the [callb] function, then exit. + Creates a new thread that will execute the `callb` function, then exit. **/ public static function create( callb : Void -> Void ) { return new Thread(untyped __global__.__hxcpp_thread_create(callb)); } /** - Reads a message from the thread queue. If [block] is true, the function - blocks until a message is available. If [block] is false, the function - returns [null] if no message is available. + Reads a message from the thread queue. If `block` is true, the function + blocks until a message is available. If `block` is false, the function + returns `null` if no message is available. **/ public static function readMessage( block : Bool ) : Dynamic { return untyped __global__.__hxcpp_thread_read_message(block); diff --git a/std/cpp/vm/Tls.hx b/std/cpp/vm/Tls.hx index e5585aed..7b04453e 100644 --- a/std/cpp/vm/Tls.hx +++ b/std/cpp/vm/Tls.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cpp/vm/Unsafe.hx b/std/cpp/vm/Unsafe.hx index f7291145..c6a96975 100644 --- a/std/cpp/vm/Unsafe.hx +++ b/std/cpp/vm/Unsafe.hx @@ -1,4 +1,25 @@ -package cpp.vm; +/* + * Copyright (C)2005-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 cpp.vm; class Unsafe { diff --git a/std/cpp/vm/WeakRef.hx b/std/cpp/vm/WeakRef.hx index 5e52bf68..5f94877a 100644 --- a/std/cpp/vm/WeakRef.hx +++ b/std/cpp/vm/WeakRef.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cpp/zip/Compress.hx b/std/cpp/zip/Compress.hx index aebaf300..adfc2827 100644 --- a/std/cpp/zip/Compress.hx +++ b/std/cpp/zip/Compress.hx @@ -1,5 +1,26 @@ -package cpp.zip; +/* + * Copyright (C)2005-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 cpp.zip; -#if (haxe_ver < 3.4) +#if (haxe_ver < 4.0) typedef Compress = haxe.zip.Compress; #end \ No newline at end of file diff --git a/std/cpp/zip/Flush.hx b/std/cpp/zip/Flush.hx index 1af75362..5f256fb1 100644 --- a/std/cpp/zip/Flush.hx +++ b/std/cpp/zip/Flush.hx @@ -1,5 +1,26 @@ -package cpp.zip; +/* + * Copyright (C)2005-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 cpp.zip; -#if (haxe_ver < 3.4) +#if (haxe_ver < 4.0) typedef Flush = haxe.zip.FlushMode; #end \ No newline at end of file diff --git a/std/cpp/zip/Uncompress.hx b/std/cpp/zip/Uncompress.hx index 6313aca6..8446b444 100644 --- a/std/cpp/zip/Uncompress.hx +++ b/std/cpp/zip/Uncompress.hx @@ -1,5 +1,26 @@ -package cpp.zip; +/* + * Copyright (C)2005-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 cpp.zip; -#if (haxe_ver < 3.4) +#if (haxe_ver < 4.0) typedef Uncompress = haxe.zip.Uncompress; #end \ No newline at end of file diff --git a/std/cs/Boot.hx b/std/cs/Boot.hx index 9a3d6bf4..be60e5ca 100644 --- a/std/cs/Boot.hx +++ b/std/cs/Boot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,7 +25,8 @@ import cs.internal.FieldLookup; import cs.internal.Function; import cs.internal.HxObject; import cs.internal.Runtime; -import cs.internal.Iterator; +// TODO (see Gencommon.IteratorsInterfaceModf) +//import cs.internal.Iterator; #if !erase_generics import cs.internal.Null; #end @@ -37,6 +38,7 @@ import cs.StdTypes; import haxe.ds.StringMap; import Reflect; +@:dox(hide) class Boot { diff --git a/std/cs/Flags.hx b/std/cs/Flags.hx index f9204ba3..2dcbddac 100644 --- a/std/cs/Flags.hx +++ b/std/cs/Flags.hx @@ -1,12 +1,33 @@ -package cs; +/* + * Copyright (C)2005-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 cs; /** Use this type to have access to the bitwise operators of C# enums that have a `cs.system.FlagsAttribute` attribute. Usage example: + ```haxe import cs.system.reflection.BindingFlags; - var binding = new Flags(BindingFlags.Public) | BindingFlags.Static | BindingFlags.NonPublic; ``` **/ diff --git a/std/cs/Lib.hx b/std/cs/Lib.hx index b884dfe2..b8cd8cea 100644 --- a/std/cs/Lib.hx +++ b/std/cs/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -28,13 +28,13 @@ import cs.system.Type; **/ class Lib { - @:keep private static var decimalSeparator:String; + private static var decimalSeparator:String; /** Changes the current culture settings to allow a consistent cross-target behavior. Currently the only change made is in regard to the decimal separator, which is always set to "." **/ - @:keep public static function applyCultureChanges():Void + public static function applyCultureChanges():Void { var ci = new cs.system.globalization.CultureInfo(cs.system.threading.Thread.CurrentThread.CurrentCulture.Name, true); decimalSeparator = ci.NumberFormat.NumberDecimalSeparator; @@ -84,6 +84,7 @@ class Lib This function will not work with Value Types (such as Int, Float, Bool...) **/ + @:pure @:extern public static inline function as(obj:Dynamic, cl:Class):T { return untyped __as__(obj); @@ -124,7 +125,7 @@ class Lib [deprecated] - use `getNativeType` instead **/ @:deprecated('The function `nativeType` is deprecated and will be removed in later versions. Please use `getNativeType` instead') - public static function nativeType(obj:Dynamic):Type + public static inline function nativeType(obj:Dynamic):Type { return untyped obj.GetType(); } @@ -132,7 +133,7 @@ class Lib /** Gets the native System.Type from the supplied object. Will throw an exception in case of null being passed. **/ - public static function getNativeType(obj:Dynamic):Type + public static inline function getNativeType(obj:Dynamic):Type { return untyped obj.GetType(); } diff --git a/std/cs/NativeArray.hx b/std/cs/NativeArray.hx index 2435dd3c..478cbe3b 100644 --- a/std/cs/NativeArray.hx +++ b/std/cs/NativeArray.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/Out.hx b/std/cs/Out.hx index df8c0d85..58709766 100644 --- a/std/cs/Out.hx +++ b/std/cs/Out.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/Pointer.hx b/std/cs/Pointer.hx index 16dc0474..b71af6b4 100644 --- a/std/cs/Pointer.hx +++ b/std/cs/Pointer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/Ref.hx b/std/cs/Ref.hx index aeec15ad..024d5da8 100644 --- a/std/cs/Ref.hx +++ b/std/cs/Ref.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/StdTypes.hx b/std/cs/StdTypes.hx index bcf746db..05cef4bc 100644 --- a/std/cs/StdTypes.hx +++ b/std/cs/StdTypes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,12 +21,12 @@ */ package cs; -@:notNull @:runtimeValue @:coreType abstract Int8 to Int {} -@:notNull @:runtimeValue @:coreType abstract Int16 to Int {} -@:notNull @:runtimeValue @:coreType abstract Char16 from Int {} -@:notNull @:runtimeValue @:coreType abstract UInt8 to Int from Int {} -@:notNull @:runtimeValue @:coreType abstract UInt16 to Int {} -@:notNull @:runtimeValue @:coreType abstract Int64 from Int from Float +@:notNull @:runtimeValue @:coreType extern abstract Int8 to Int {} +@:notNull @:runtimeValue @:coreType extern abstract Int16 to Int {} +@:notNull @:runtimeValue @:coreType extern abstract Char16 from Int {} +@:notNull @:runtimeValue @:coreType extern abstract UInt8 to Int from Int {} +@:notNull @:runtimeValue @:coreType extern abstract UInt16 to Int {} +@:notNull @:runtimeValue @:coreType extern abstract Int64 from Int from Float { @:op(A+B) public static function addI(lhs:Int64, rhs:Int):Int64; @:op(A+B) public static function add(lhs:Int64, rhs:Int64):Int64; @@ -62,7 +62,7 @@ package cs; @:op(--A) public static function preDecrement(t:Int64):Int64; @:op(A--) public static function postDecrement(t:Int64):Int64; } -@:notNull @:runtimeValue @:coreType abstract UInt64 from Int from Int64 from Float from haxe.Int64 +@:notNull @:runtimeValue @:coreType extern abstract UInt64 from Int from Int64 from Float from haxe.Int64 { @:op(A+B) public static function addI(lhs:UInt64, rhs:Int):UInt64; @:op(A+B) public static function add(lhs:UInt64, rhs:UInt64):UInt64; diff --git a/std/cs/_std/Array.hx b/std/cs/_std/Array.hx index d8e1f6f1..5ed8d0f0 100644 --- a/std/cs/_std/Array.hx +++ b/std/cs/_std/Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/_std/Date.hx b/std/cs/_std/Date.hx index afe45e87..1f94ac2a 100644 --- a/std/cs/_std/Date.hx +++ b/std/cs/_std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -29,18 +29,24 @@ import haxe.Int64; #end @:coreApi class Date { + @:readOnly private static var epochTicks:Int64 = new DateTime(1970, 1, 1).Ticks; private var date:DateTime; - public function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void + @:overload public function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void { if (day <= 0) day = 1; if (year <= 0) year = 1; date = new DateTime(year, month + 1, day, hour, min, sec); } + @:overload private function new(native:DateTime) + { + date = native; + } + public inline function getTime() : Float { - return (cast(date.Ticks, Float) / cast(TimeSpan.TicksPerMillisecond, Float)); + return cast(cs.system.TimeZone.CurrentTimeZone.ToUniversalTime(date).Ticks - epochTicks, Float) / cast(TimeSpan.TicksPerMillisecond, Float); } public inline function getHours() : Int @@ -93,18 +99,14 @@ import haxe.Int64; +":"+(if( s < 10 ) "0"+s else ""+s); } - static public function now() : Date + static public inline function now() : Date { - var d = new Date(0, 0, 0, 0, 0, 0); - d.date = DateTime.Now; - return d; + return new Date(DateTime.Now); } - static public function fromTime( t : Float ) : Date + static public inline function fromTime( t : Float ) : Date { - var d = new Date(0, 0, 0, 0, 0, 0); - d.date = new DateTime(cast(t * cast(TimeSpan.TicksPerMillisecond, Float), Int64)); - return d; + return new Date(cs.system.TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(cast(t * cast(TimeSpan.TicksPerMillisecond, Float), Int64) + epochTicks))); } static public function fromString( s : String ) : Date @@ -128,10 +130,8 @@ import haxe.Int64; } } - private static function fromNative( d : cs.system.DateTime ) : Date + private static inline function fromNative( d : cs.system.DateTime ) : Date { - var date = new Date(0, 0, 0, 0, 0, 0); - date.date = d; - return date; + return new Date(d); } } diff --git a/std/cs/_std/EReg.hx b/std/cs/_std/EReg.hx index 262407a4..b430359a 100644 --- a/std/cs/_std/EReg.hx +++ b/std/cs/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/_std/Math.hx b/std/cs/_std/Math.hx index b06b4d11..3b867070 100644 --- a/std/cs/_std/Math.hx +++ b/std/cs/_std/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/_std/Reflect.hx b/std/cs/_std/Reflect.hx index b4b2164a..1462caab 100644 --- a/std/cs/_std/Reflect.hx +++ b/std/cs/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -30,7 +30,7 @@ import cs.Lib; import cs.system.Object; import cs.system.reflection.*; -@:keep @:coreApi class Reflect { +@:coreApi class Reflect { public static function hasField( o : Dynamic, field : String ) : Bool { @@ -40,6 +40,7 @@ import cs.system.reflection.*; return Runtime.slowHasField(o,field); } + @:keep public static function field( o : Dynamic, field : String ) : Dynamic { var ihx:IHxObject = Lib.as(o,IHxObject); @@ -48,6 +49,7 @@ import cs.system.reflection.*; return Runtime.slowGetField(o,field,false); } + @:keep public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void { var ihx:IHxObject = Lib.as(o,IHxObject); @@ -84,10 +86,11 @@ import cs.system.reflection.*; return untyped cast(func, Function).__hx_invokeDynamic(args); } + @:keep public static function fields( o : Dynamic ) : Array { var ihx = Lib.as(o,IHxObject); - if (o != null) + if (ihx != null) { var ret = []; untyped ihx.__hx_getFields(ret); diff --git a/std/cs/_std/Std.hx b/std/cs/_std/Std.hx index d67b0f80..9a1349d4 100644 --- a/std/cs/_std/Std.hx +++ b/std/cs/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -30,24 +30,37 @@ import cs.internal.Exceptions; return t == Dynamic; if (t == null) return false; - var clt:cs.system.Type = cast t; + var clt = cs.Lib.as(t, cs.system.Type); if (clt == null) return false; - var name:String = cast clt; - switch(name) + switch(clt.ToString()) { case "System.Double": - return untyped __cs__('v is double || v is int'); + return untyped __cs__('{0} is double || {0} is int', v); case "System.Int32": - return untyped __cs__('haxe.lang.Runtime.isInt(v)'); + return cs.internal.Runtime.isInt(v); case "System.Boolean": - return untyped __cs__('v is bool'); + return untyped __cs__('{0} is bool', v); case "System.Object": return true; } - return clt.IsAssignableFrom(cs.Lib.getNativeType(v)); + var vt = cs.Lib.getNativeType(v); + + if (clt.IsAssignableFrom(vt)) + return true; + + #if !erase_generics + for (iface in clt.GetInterfaces()) { + var g = cs.internal.Runtime.getGenericAttr(iface); + if (g != null && g.generic == clt) { + return iface.IsAssignableFrom(vt); + } + } + #end + + return false; } public static function string( s : Dynamic ) : String { @@ -59,7 +72,7 @@ import cs.internal.Exceptions; return s.ToString(); } - public static inline function int( x : Float ) : Int { + public static function int( x : Float ) : Int { return cast x; } @@ -173,7 +186,7 @@ import cs.internal.Exceptions; x = x.substr(0,i); } return try - cs.system.Double.Parse(x, (null : cs.system.IFormatProvider)) + cs.system.Double.Parse(x, cs.system.globalization.CultureInfo.InvariantCulture) catch(e:Dynamic) Math.NaN; } diff --git a/std/cs/_std/String.hx b/std/cs/_std/String.hx index 7c7d984f..f4af89a2 100644 --- a/std/cs/_std/String.hx +++ b/std/cs/_std/String.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/_std/StringBuf.hx b/std/cs/_std/StringBuf.hx index 2dfe944c..2fadac9b 100644 --- a/std/cs/_std/StringBuf.hx +++ b/std/cs/_std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/_std/Sys.hx b/std/cs/_std/Sys.hx index 3acc1c1d..edb583bd 100644 --- a/std/cs/_std/Sys.hx +++ b/std/cs/_std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -28,12 +28,12 @@ class Sys { private static var _env:haxe.ds.StringMap; private static var _args:Array; - public static function print( v : Dynamic ) : Void + public static inline function print( v : Dynamic ) : Void { cs.system.Console.Write(v); } - public static function println( v : Dynamic ) : Void + public static inline function println( v : Dynamic ) : Void { cs.system.Console.WriteLine(v); } @@ -49,7 +49,7 @@ class Sys { return _args.copy(); } - public static function getEnv( s : String ) : String + public static inline function getEnv( s : String ) : String { return Environment.GetEnvironmentVariable(s); } @@ -76,7 +76,7 @@ class Sys { return _env; } - public static function sleep( seconds : Float ) : Void + public static inline function sleep( seconds : Float ) : Void { Thread.Sleep( Std.int(seconds * 1000) ); } @@ -87,12 +87,12 @@ class Sys { return false; } - public static function getCwd() : String + public static inline function getCwd() : String { return cs.system.io.Directory.GetCurrentDirectory(); } - public static function setCwd( s : String ) : Void + public static inline function setCwd( s : String ) : Void { cs.system.io.Directory.SetCurrentDirectory(s); } @@ -115,33 +115,56 @@ class Sys { public static function command( cmd : String, ?args : Array ) : Int { - var proc:Process = new Process(cmd, args == null ? [] : args); - var ret = proc.exitCode(); - proc.close(); - - return ret; + var proc = Process.createNativeProcess(cmd, args); + proc.add_OutputDataReceived(new cs.system.diagnostics.DataReceivedEventHandler( + function(p, evtArgs) { + var data = evtArgs.Data; + if (data != null && data != "") + println(data); + } + )); + var stderr = stderr(); + proc.add_ErrorDataReceived(new cs.system.diagnostics.DataReceivedEventHandler( + function(p, evtArgs) { + var data = evtArgs.Data; + if (data != null && data != "") + stderr.writeString(data + "\n"); + } + )); + proc.Start(); + proc.BeginOutputReadLine(); + proc.BeginErrorReadLine(); + proc.WaitForExit(); + var exitCode = proc.ExitCode; + proc.Dispose(); + return exitCode; } - public static function exit( code : Int ) : Void + public static inline function exit( code : Int ) : Void { Environment.Exit(code); } + @:readOnly static var epochTicks = new cs.system.DateTime(1970, 1, 1).Ticks; public static function time() : Float { - return Date.now().getTime() / 1000; + return cast((cs.system.DateTime.UtcNow.Ticks - epochTicks), Float) / cast(cs.system.TimeSpan.TicksPerSecond, Float); } - public static function cpuTime() : Float + public static inline function cpuTime() : Float { return Environment.TickCount / 1000; } - public static inline function executablePath() : String + @:deprecated("Use programPath instead") public static inline function executablePath() : String { return cs.system.reflection.Assembly.GetExecutingAssembly().GetName().CodeBase; } + public static function programPath() : String { + return cs.system.reflection.Assembly.GetExecutingAssembly().Location; + } + public static function getChar( echo : Bool ) : Int { #if !(Xbox || CF || MF) //Xbox, Compact Framework, Micro Framework @@ -151,7 +174,7 @@ class Sys { #end } - public static function stdin() : haxe.io.Input + public static inline function stdin() : haxe.io.Input { #if !(Xbox || CF || MF) return new cs.io.NativeInput(cs.system.Console.OpenStandardInput()); @@ -160,7 +183,7 @@ class Sys { #end } - public static function stdout() : haxe.io.Output + public static inline function stdout() : haxe.io.Output { #if !(Xbox || CF || MF) return new cs.io.NativeOutput(cs.system.Console.OpenStandardOutput()); @@ -169,7 +192,7 @@ class Sys { #end } - public static function stderr() : haxe.io.Output + public static inline function stderr() : haxe.io.Output { #if !(Xbox || CF || MF) return new cs.io.NativeOutput(cs.system.Console.OpenStandardError()); diff --git a/std/cs/_std/Type.hx b/std/cs/_std/Type.hx index 06468d77..a45c1735 100644 --- a/std/cs/_std/Type.hx +++ b/std/cs/_std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -28,7 +28,7 @@ import cs.system.Object; import cs.system.reflection.*; using StringTools; -@:keep enum ValueType { +enum ValueType { TNull; TInt; TFloat; @@ -40,7 +40,7 @@ using StringTools; TUnknown; } -@:keep @:coreApi class Type { +@:coreApi class Type { public static function getClass( o : T ) : Class untyped { @@ -166,32 +166,29 @@ using StringTools; return Runtime.callMethod(null, cast ctors, ctors.Length, args); } - public static function createEmptyInstance( cl : Class ) : T - { - var t:cs.system.Type = Lib.toNativeType(cl); - if (t.IsInterface) - { - //may be generic - t = Lib.toNativeType(resolveClass(getClassName(cl))); - } - - if (Reflect.hasField(cl, "__hx_createEmpty")) - return untyped cl.__hx_createEmpty(); - if (untyped cl == String) - return cast ""; - var t:cs.system.Type = Lib.toNativeType(cl); - - var ctors = t.GetConstructors(); - for (c in 0...ctors.Length) - { - if (ctors[c].GetParameters().Length == 0) - { - var arr = new cs.NativeArray(1); - arr[0] = ctors[c]; - return Runtime.callMethod(null, cast arr, arr.Length, []); - } - } - return cs.system.Activator.CreateInstance(t); + // cache empty constructor arguments so we don't allocate it on each createEmptyInstance call + @:protected @:readOnly static var __createEmptyInstance_EMPTY_ARGS = cs.NativeArray.make((cs.internal.Runtime.EmptyObject.EMPTY : Any)); + + public static function createEmptyInstance( cl : Class ) : T { + var t = Lib.toNativeType(cl); + + if (cs.system.Object.ReferenceEquals(t, String)) + #if erase_generics + return untyped ""; + #else + return untyped __cs__("(T)(object){0}", ""); + #end + + var res = try + cs.system.Activator.CreateInstance(t, __createEmptyInstance_EMPTY_ARGS) + catch (_:cs.system.MissingMemberException) + cs.system.Activator.CreateInstance(t); + + #if erase_generics + return res; + #else + return untyped __cs__("(T){0}", res); + #end } public static function createEnum( e : Enum, constr : String, ?params : Array ) : T @@ -332,6 +329,7 @@ using StringTools; return Std.is(e, cs.system.Enum) ? [] : cast(e,HxEnum).getParams(); } + @:pure public static function enumIndex( e : EnumValue ) : Int untyped { if (Std.is(e, cs.system.Enum)) diff --git a/std/cs/_std/haxe/Int64.hx b/std/cs/_std/haxe/Int64.hx index 79e51e7c..7f441fbb 100644 --- a/std/cs/_std/haxe/Int64.hx +++ b/std/cs/_std/haxe/Int64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,6 +22,8 @@ package haxe; using haxe.Int64; +import haxe.Int64Helper; + private typedef __Int64 = cs.StdTypes.Int64; @:coreApi @@ -29,7 +31,7 @@ abstract Int64(__Int64) from __Int64 to __Int64 { public static inline function make( high : Int32, low : Int32 ) : Int64 - return new Int64( (cast(high, __Int64) << 32) | (cast(low, __Int64)& untyped __cs__('0xffffffffL')) ); + return new Int64( (cast(high, __Int64) << 32) | (cast(low, __Int64)& (untyped __cs__('0xffffffffL') : Int64)) ); private inline function new(x : __Int64) this = x; @@ -93,6 +95,14 @@ abstract Int64(__Int64) from __Int64 to __Int64 private inline function toString() : String return '$this'; + public static function parseString( sParam : String ) : Int64 { + return Int64Helper.parseString( sParam ); + } + + public static function fromFloat( f : Float ) : Int64 { + return Int64Helper.fromFloat( f ); + } + @:op(-A) public static function neg( x : Int64 ) : Int64 return -x.val; diff --git a/std/cs/_std/haxe/Resource.hx b/std/cs/_std/haxe/Resource.hx index 5c326e4c..958040cc 100644 --- a/std/cs/_std/haxe/Resource.hx +++ b/std/cs/_std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -48,6 +48,8 @@ package haxe; public static function getString( name : String ) : String { name = haxe.io.Path.escape(name, true); var path = getPaths().get(name); + if (path == null) + return null; var str = cs.Lib.toNativeType(haxe.Resource).Assembly.GetManifestResourceStream(path); if (str != null) return new cs.io.NativeInput(str).readAll().toString(); @@ -58,6 +60,8 @@ package haxe; public static function getBytes( name : String ) : haxe.io.Bytes { name = haxe.io.Path.escape(name, true); var path = getPaths().get(name); + if (path == null) + return null; var str = cs.Lib.toNativeType(haxe.Resource).Assembly.GetManifestResourceStream(path); if (str != null) return new cs.io.NativeInput(str).readAll(); diff --git a/std/cs/_std/haxe/ds/IntMap.hx b/std/cs/_std/haxe/ds/IntMap.hx index eea2791c..864edfa8 100644 --- a/std/cs/_std/haxe/ds/IntMap.hx +++ b/std/cs/_std/haxe/ds/IntMap.hx @@ -1,26 +1,23 @@ /* - * Copyright (c) 2005, The Haxe Project Contributors - * 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)2005-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 haxe.ds; diff --git a/std/cs/_std/haxe/ds/ObjectMap.hx b/std/cs/_std/haxe/ds/ObjectMap.hx index 4f1315fe..d7137e6c 100644 --- a/std/cs/_std/haxe/ds/ObjectMap.hx +++ b/std/cs/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -476,7 +476,7 @@ import cs.NativeArray; } @:access(haxe.ds.ObjectMap) -@:final @:keep +@:final private class ObjectMapKeyIterator { var m:ObjectMap; var i:Int; @@ -514,7 +514,7 @@ private class ObjectMapKeyIterator { } @:access(haxe.ds.ObjectMap) -@:final @:keep +@:final private class ObjectMapValueIterator { var m:ObjectMap; var i:Int; diff --git a/std/cs/_std/haxe/ds/StringMap.hx b/std/cs/_std/haxe/ds/StringMap.hx index 9a53bff6..72faafcc 100644 --- a/std/cs/_std/haxe/ds/StringMap.hx +++ b/std/cs/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/_std/sys/FileSystem.hx b/std/cs/_std/sys/FileSystem.hx index f2793885..52ef590e 100644 --- a/std/cs/_std/sys/FileSystem.hx +++ b/std/cs/_std/sys/FileSystem.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -38,6 +38,7 @@ class FileSystem { Directory.Move(path, newPath); } + @:access(Date.fromNative) public static function stat( path : String ) : FileStat { if (File.Exists(path)) @@ -46,9 +47,9 @@ class FileSystem { return { gid: 0, //C# doesn't let you get this info uid: 0, //same - atime: untyped Date.fromNative(fi.LastAccessTime), - mtime: untyped Date.fromNative(fi.LastWriteTime), - ctime: untyped Date.fromNative(fi.CreationTime), + atime: Date.fromNative(fi.LastAccessTime), + mtime: Date.fromNative(fi.LastWriteTime), + ctime: Date.fromNative(fi.CreationTime), size: cast(fi.Length, Int), //TODO: maybe change to Int64 for Haxe 3? dev: 0, //FIXME: not sure what that is ino: 0, //FIXME: not sure what that is @@ -61,9 +62,9 @@ class FileSystem { return { gid: 0, //C# doesn't let you get this info uid: 0, //same - atime: untyped Date.fromNative(fi.LastAccessTime), - mtime: untyped Date.fromNative(fi.LastWriteTime), - ctime: untyped Date.fromNative(fi.CreationTime), + atime: Date.fromNative(fi.LastAccessTime), + mtime: Date.fromNative(fi.LastWriteTime), + ctime: Date.fromNative(fi.CreationTime), size: 0, //TODO: maybe change to Int64 for Haxe 3? dev: 0, //FIXME: not sure what that is ino: 0, //FIXME: not sure what that is @@ -102,11 +103,13 @@ class FileSystem { public static function deleteFile( path : String ) : Void { + if (!File.Exists(path)) throw "Path '" + path + "' doesn't exist"; File.Delete(path); } public static function deleteDirectory( path : String ) : Void { + if (!Directory.Exists(path)) throw "Path '" + path + "' doesn't exist"; Directory.Delete(path); } diff --git a/std/cs/_std/sys/db/Sqlite.hx b/std/cs/_std/sys/db/Sqlite.hx index efa64ab4..ae41d4f7 100644 --- a/std/cs/_std/sys/db/Sqlite.hx +++ b/std/cs/_std/sys/db/Sqlite.hx @@ -1,4 +1,25 @@ -package sys.db; +/* + * Copyright (C)2005-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 sys.db; class Sqlite { diff --git a/std/cs/_std/sys/io/File.hx b/std/cs/_std/sys/io/File.hx index 05f08ef6..10e84f4a 100644 --- a/std/cs/_std/sys/io/File.hx +++ b/std/cs/_std/sys/io/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/_std/sys/io/FileInput.hx b/std/cs/_std/sys/io/FileInput.hx index 305f615f..51c1d1a5 100644 --- a/std/cs/_std/sys/io/FileInput.hx +++ b/std/cs/_std/sys/io/FileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/_std/sys/io/FileOutput.hx b/std/cs/_std/sys/io/FileOutput.hx index 640fe8e0..b58bdb21 100644 --- a/std/cs/_std/sys/io/FileOutput.hx +++ b/std/cs/_std/sys/io/FileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/_std/sys/io/Process.hx b/std/cs/_std/sys/io/Process.hx index af578c52..71f49b48 100644 --- a/std/cs/_std/sys/io/Process.hx +++ b/std/cs/_std/sys/io/Process.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -35,23 +35,9 @@ class Process { private var native:NativeProcess; - - public function new( cmd : String, args : Array ) : Void + public function new( cmd : String, ?args : Array ) : Void { - this.native = new NativeProcess(); - native.StartInfo.FileName = cmd; - native.StartInfo.CreateNoWindow = true; - var buf = new StringBuf(); - for (arg in args) - { - buf.add("\""); - buf.add(StringTools.replace(arg, "\"", "\\\"")); - buf.add("\" "); - } - native.StartInfo.Arguments = buf.toString(); - native.StartInfo.RedirectStandardError = native.StartInfo.RedirectStandardInput = native.StartInfo.RedirectStandardOutput = true; - native.StartInfo.UseShellExecute = false; - + this.native = createNativeProcess(cmd, args); native.Start(); this.stdout = new cs.io.NativeInput(native.StandardOutput.BaseStream); @@ -59,13 +45,74 @@ class Process { this.stdin = new cs.io.NativeOutput(native.StandardInput.BaseStream); } + @:allow(Sys) + private static function createNativeProcess( cmd : String, ?args : Array ) : NativeProcess { + var native = new NativeProcess(); + native.StartInfo.CreateNoWindow = true; + native.StartInfo.RedirectStandardError = native.StartInfo.RedirectStandardInput = native.StartInfo.RedirectStandardOutput = true; + if (args != null) { + // mono 4.2.1 on Windows doesn't support relative path correctly + if (cmd.indexOf("/") != -1 || cmd.indexOf("\\") != -1) + cmd = sys.FileSystem.fullPath(cmd); + native.StartInfo.FileName = cmd; + native.StartInfo.UseShellExecute = false; + native.StartInfo.Arguments = buildArgumentsString(args); + } else { + switch (Sys.systemName()) { + case "Windows": + native.StartInfo.FileName = switch (Sys.getEnv("COMSPEC")) { + case null: "cmd.exe"; + case comspec: comspec; + } + native.StartInfo.Arguments = '/C "$cmd"'; + case _: + native.StartInfo.FileName = "/bin/sh"; + native.StartInfo.Arguments = buildArgumentsString(["-c", cmd]); + } + native.StartInfo.UseShellExecute = false; + } + return native; + } + + private static function buildArgumentsString(args:Array):String { + return switch (Sys.systemName()) { + case "Windows": + [ + for (a in args) + StringTools.quoteWinArg(a, false) + ].join(" "); + case _: + // mono uses a slightly different quoting/escaping rule... + // https://bugzilla.xamarin.com/show_bug.cgi?id=19296 + [ + for (arg in args) { + var b = new StringBuf(); + b.add('"'); + for (i in 0...arg.length) { + var c = arg.charCodeAt(i); + switch (c) { + case '"'.code | '\\'.code: + b.addChar('\\'.code); + case _: //pass + } + b.addChar(c); + } + b.add('"'); + b.toString(); + } + ].join(" "); + } + } + public function getPid() : Int { return native.Id; } - public function exitCode() : Int + public function exitCode( block : Bool = true ) : Null { + if( block == false && !native.HasExited ) + return null; native.WaitForExit(); return native.ExitCode; } diff --git a/std/cs/_std/sys/net/Host.hx b/std/cs/_std/sys/net/Host.hx index b9d0b496..6e02ef9f 100644 --- a/std/cs/_std/sys/net/Host.hx +++ b/std/cs/_std/sys/net/Host.hx @@ -1,4 +1,25 @@ - +/* + * Copyright (C)2005-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 sys.net; import cs.system.Array; @@ -17,6 +38,11 @@ class Host { public var hostEntry(default, null) : IPHostEntry; public var ipAddress(default, null) : IPAddress; + /** + The provided host string. + **/ + var host(default,null) : String; + /** The actual IP corresponding to the host. **/ @@ -30,6 +56,7 @@ class Host { the corresponding IP address is resolved using DNS. An exception occur if the host name could not be found. **/ public function new( name : String ) : Void { + host = name; hostEntry = Dns.GetHostEntry(name); for (i in 0...hostEntry.AddressList.Length) { if (hostEntry.AddressList[i].AddressFamily == InterNetwork) { diff --git a/std/cs/_std/sys/net/Socket.hx b/std/cs/_std/sys/net/Socket.hx index 31c9f777..735e1171 100644 --- a/std/cs/_std/sys/net/Socket.hx +++ b/std/cs/_std/sys/net/Socket.hx @@ -1,4 +1,25 @@ - +/* + * Copyright (C)2005-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 sys.net; import cs.system.net.IPEndPoint; @@ -23,17 +44,17 @@ class Socket { /** The stream on which you can read available data. By default the stream is blocking until the requested data is available, - use [setBlocking(false)] or [setTimeout] to prevent infinite waiting. + use `setBlocking(false)` or `setTimeout` to prevent infinite waiting. **/ public var input(default,null) : haxe.io.Input; /** - The stream on which you can send data. Please note that in case the output buffer you will block while writing the data, use [setBlocking(false)] or [setTimeout] to prevent that. + The stream on which you can send data. Please note that in case the output buffer you will block while writing the data, use `setBlocking(false)` or `setTimeout` to prevent that. **/ public var output(default,null) : haxe.io.Output; /** - A custom value that can be associated with the socket. Can be used to retreive your custom infos after a [select]. + A custom value that can be associated with the socket. Can be used to retreive your custom infos after a `select`. ***/ public var custom : Dynamic; @@ -82,7 +103,7 @@ class Socket { } /** - Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use [accept()] to accept incoming connections. + Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use `accept()` to accept incoming connections. **/ public function listen( connections : Int ) : Void { sock.Listen( connections ); @@ -173,11 +194,11 @@ class Socket { /** Wait until one of the sockets groups is ready for the given operation : - [read] contains sockets on which we want to wait for available data to be read, - [write] contains sockets on which we want to wait until we are allowed to write some data to their output buffers, - [others] contains sockets on which we want to wait for exceptional conditions. - [select] will block until one of the condition is met, in which case it will return the sockets for which the condition was true. - In case a [timeout] (in seconds) is specified, select might wait at worse until the timeout expires. + * `read` contains sockets on which we want to wait for available data to be read, + * `write` contains sockets on which we want to wait until we are allowed to write some data to their output buffers, + * `others` contains sockets on which we want to wait for exceptional conditions. + * `select` will block until one of the condition is met, in which case it will return the sockets for which the condition was true. + In case a `timeout` (in seconds) is specified, select might wait at worse until the timeout expires. **/ static public function select(read : Array, write : Array, others : Array, ?timeout : Float) : { read: Array,write: Array,others: Array } { throw "Not implemented yet."; diff --git a/std/cs/db/AdoNet.hx b/std/cs/db/AdoNet.hx index 58cea1ea..0d32b25b 100644 --- a/std/cs/db/AdoNet.hx +++ b/std/cs/db/AdoNet.hx @@ -1,4 +1,25 @@ -package cs.db; +/* + * Copyright (C)2005-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 cs.db; import sys.db.*; import cs.system.data.*; @@ -266,13 +287,14 @@ private class AdoResultSet implements ResultSet for (i in 0...names.length) { var name = names[i], t = types[i], val:Dynamic = null; - if (t == cs.system.Single) - { + if (reader.IsDBNull(i)) { + val = null; + } else if (t == cs.system.Single) { val = reader.GetDouble(i); } else if (t == cs.system.DateTime || t == cs.system.TimeSpan) { var d = reader.GetDateTime(i); if (d != null) - val = Date.fromTime(cast(d.Ticks,Float) / cast(cs.system.TimeSpan.TicksPerMillisecond,Float)); + val = @:privateAccess Date.fromNative(d); } else if (t == cs.system.DBNull) { val = null; } else if (t == cs.system.Byte) { diff --git a/std/cs/internal/BoxedPointer.hx b/std/cs/internal/BoxedPointer.hx index e76d5677..3c9d7c3b 100644 --- a/std/cs/internal/BoxedPointer.hx +++ b/std/cs/internal/BoxedPointer.hx @@ -1,4 +1,25 @@ -package cs.internal; +/* + * Copyright (C)2005-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 cs.internal; @:unsafe @:keep @:native('haxe.lang.BoxedPointer') @:nativeGen class BoxedPointer { diff --git a/std/cs/internal/Exceptions.hx b/std/cs/internal/Exceptions.hx index 2a75ac8c..5ac0df5b 100644 --- a/std/cs/internal/Exceptions.hx +++ b/std/cs/internal/Exceptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -29,7 +29,7 @@ import cs.system.Exception; static var exception:cs.system.Exception; } -//should NOT be usable inside haxe code +//should NOT be usable inside Haxe code @:classCode('override public string Message { get { return this.toString(); } }\n\n') @:nativeGen @:keep @:native("haxe.lang.HaxeException") private class HaxeException extends Exception { diff --git a/std/cs/internal/FieldLookup.hx b/std/cs/internal/FieldLookup.hx index 9ca1580d..aa532dc3 100644 --- a/std/cs/internal/FieldLookup.hx +++ b/std/cs/internal/FieldLookup.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,21 @@ */ package cs.internal; +@:native('haxe.lang.FieldHashConflict') +@:final @:nativeGen +@:keep class FieldHashConflict { + @:readOnly public var hash(default,never):Int; + @:readOnly public var name(default,never):String; + public var value:Dynamic; + public var next:FieldHashConflict; + public function new(hash, name, value, next) { + untyped this.hash = hash; + untyped this.name = name; + this.value = value; + this.next = next; + } +} + @:native('haxe.lang.FieldLookup') @:final @:nativeGen @:classCode("#pragma warning disable 628\n") @@ -325,4 +340,59 @@ package cs.internal; static function insertDynamic(a:cs.NativeArray, length:Int, pos:Int, x:Dynamic):cs.NativeArray return __insert(a, length, pos, x); static function insertString(a:cs.NativeArray, length:Int, pos:Int, x:Dynamic):cs.NativeArray return __insert(a, length, pos, x); #end + + static function getHashConflict(head:FieldHashConflict, hash:Int, name:String):FieldHashConflict { + while (head != null) { + if (head.hash == hash && head.name == name) { + return head; + } + head = head.next; + } + return null; + } + + static function setHashConflict(head:cs.Ref, hash:Int, name:String, value:Dynamic):Void { + var node = head; + while (node != null) { + if (node.hash == hash && node.name == name) { + node.value = value; + return; + } + node = node.next; + } + head = new FieldHashConflict(hash, name, value, head); + } + + static function deleteHashConflict(head:cs.Ref, hash:Int, name:String):Bool { + // no conflicting fields at all + if (head == null) { + return false; + } + + // list head is conflicting - just point it to the next one + if (head.hash == hash && head.name == name) { + head = head.next; + return true; + } + + // loop through the list, removing node if there's one + var prev = head, node = head.next; + while (node != null) { + if (node.hash == hash && node.name == name) { + prev.next = node.next; + return true; + } + node = node.next; + } + + // not found + return false; + } + + static function addHashConflictNames(head:FieldHashConflict, arr:Array):Void { + while (head != null) { + arr.push(head.name); + head = head.next; + } + } } diff --git a/std/cs/internal/Function.hx b/std/cs/internal/Function.hx index abfadac6..d0c674ce 100644 --- a/std/cs/internal/Function.hx +++ b/std/cs/internal/Function.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -80,10 +80,9 @@ package cs.internal; public function Equals(obj:Dynamic):Bool { - if (obj == null) + var c = cs.Lib.as(obj, Closure); + if (c == null) return false; - - var c:Closure = cast obj; return (c.obj == this.obj && c.field == this.field); } diff --git a/std/cs/internal/HxObject.hx b/std/cs/internal/HxObject.hx index 2a91688a..12446a76 100644 --- a/std/cs/internal/HxObject.hx +++ b/std/cs/internal/HxObject.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/internal/Iterator.hx b/std/cs/internal/Iterator.hx index 9b63d327..d43153ce 100644 --- a/std/cs/internal/Iterator.hx +++ b/std/cs/internal/Iterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ package cs.internal; - +/* TODO (see Gencommon.IteratorsInterfaceModf) @:keep @:native('haxe.lang.Iterator') interface Iterator { @@ -35,4 +35,5 @@ package cs.internal; public function iterator():Iterator; -} \ No newline at end of file +} +*/ diff --git a/std/cs/internal/Null.hx b/std/cs/internal/Null.hx index 3fa19e2e..92fd1eb1 100644 --- a/std/cs/internal/Null.hx +++ b/std/cs/internal/Null.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,29 +21,31 @@ */ package cs.internal; -@:classCode(' - static public readonly System.Type Type = typeof(T); - static public readonly bool IsValueType = haxe.lang.NullMetadata.Type.IsValueType; -') -@:keep @:nativeGen @:native("haxe.lang.NullMetadata") private class NullMetadata -{ -} +@:classCode('//This function is here to be used with Reflection, when the haxe.lang.Null type is known + public static haxe.lang.Null _ofDynamic(object obj) { + if (obj == null) { + return new haxe.lang.Null(default(T), false); + } else if (typeof(T).Equals(typeof(double))) { + return new haxe.lang.Null((T) (object) haxe.lang.Runtime.toDouble(obj), true); + } else if (typeof(T).Equals(typeof(int))) { + return new haxe.lang.Null((T) (object) haxe.lang.Runtime.toInt(obj), true); + } else { + return new haxe.lang.Null((T) obj, true); + } + } -@:classCode(' - //This function is here to be used with Reflection, when the haxe.lang.Null type is known - public static haxe.lang.Null _ofDynamic(object obj) - { - if (obj == null) - { + public static implicit operator haxe.lang.Null(T val) { + return new haxe.lang.Null(val, true); + } + + public static implicit operator Null(__NoValue__ noValue) { return new haxe.lang.Null(default(T), false); - } else if (typeof(T).Equals(typeof(double))) { - return new haxe.lang.Null((T) (object) haxe.lang.Runtime.toDouble(obj), true); - } else if (typeof(T).Equals(typeof(int))) { - return new haxe.lang.Null((T) (object) haxe.lang.Runtime.toInt(obj), true); - } else { - return new haxe.lang.Null((T) obj, true); } - } + + public sealed class __NoValue__ { + private __NoValue__() {} + } + ') #if core_api_serialize @:meta(System.Serializable) @@ -54,45 +56,34 @@ package cs.internal; @:readOnly public var value(default,never):T; @:readOnly public var hasValue(default,never):Bool; - @:functionCode(' - if (!haxe.lang.NullMetadata.IsValueType && System.Object.ReferenceEquals(v, default(T))) - { - hasValue = false; - } - - this.@value = v; - this.hasValue = hasValue; - ') public function new(v:T, hasValue:Bool) { + if (hasValue && cs.system.Object.ReferenceEquals(v, null)) + { + hasValue = false; + } untyped this.value = v; untyped this.hasValue = hasValue; } - @:functionCode(' - if (obj == null) - { - return new haxe.lang.Null(default(D), false); - } else if (typeof(D).Equals(typeof(double))) { - return new haxe.lang.Null((D) (object) haxe.lang.Runtime.toDouble(obj), true); - } else if (typeof(D).Equals(typeof(int))) { - return new haxe.lang.Null((D) (object) haxe.lang.Runtime.toInt(obj), true); - } else { - return new haxe.lang.Null((D) obj, true); - } - ') + @:functionCode('if (obj == null) { + return new haxe.lang.Null(default(D), false); + } else if (typeof(D).Equals(typeof(double))) { + return new haxe.lang.Null((D) (object) haxe.lang.Runtime.toDouble(obj), true); + } else if (typeof(D).Equals(typeof(int))) { + return new haxe.lang.Null((D) (object) haxe.lang.Runtime.toInt(obj), true); + } else { + return new haxe.lang.Null((D) obj, true); + }') public static function ofDynamic(obj:Dynamic):Nullable { return null; } - @:functionCode(' - if (this.hasValue) - return value; - return null; - ') public function toDynamic():Dynamic { + if (this.hasValue) + return value; return null; } } diff --git a/std/cs/internal/Runtime.hx b/std/cs/internal/Runtime.hx index b4be8bcb..32d2b816 100644 --- a/std/cs/internal/Runtime.hx +++ b/std/cs/internal/Runtime.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -23,7 +23,7 @@ package cs.internal; import cs.Lib; import cs.Lib.*; import cs.NativeArray; -import cs.NativeArray; +import cs.StdTypes; import cs.system.Activator; import cs.system.IConvertible; import cs.system.IComparable; @@ -106,7 +106,9 @@ import cs.system.Object; { case [Decimal, _] | [_, Decimal]: return v1c.ToDecimal(null) == v2c.ToDecimal(null); - case [UInt64 | Int64 | DateTime, _] | [_, UInt64 | Int64 | DateTime]: + case [Int64, _] | [_, Int64]: + return v1c.ToInt64(null) == v2c.ToInt64(null); + case [UInt64 | DateTime, _] | [_, UInt64 | DateTime]: return v1c.ToUInt64(null) == v2c.ToUInt64(null); case [Double | Single, _] | [_, Double | Single]: return v1c.ToDouble(null) == v2c.ToDouble(null); @@ -154,6 +156,13 @@ import cs.system.Object; return (obj == null) ? 0 : Std.is(obj,Int) ? cast obj : Lib.as(obj,IConvertible).ToInt32(null); } +#if erase_generics + public static function toLong(obj:Dynamic):Int64 + { + return (obj == null) ? 0 : Std.is(obj,Int64) ? cast obj : Lib.as(obj,IConvertible).ToInt64(null); + } +#end + public static function isInt(obj:Dynamic):Bool { var cv1 = Lib.as(obj, IConvertible); @@ -376,7 +385,7 @@ import cs.system.Object; { value = mkNullable(value, f.FieldType); } - if (Object.ReferenceEquals(Lib.toNativeType(cs.system.Double), Lib.getNativeType(value)) && !Object.ReferenceEquals(t, f.FieldType)) + if (value != null && Object.ReferenceEquals(Lib.toNativeType(cs.system.Double), Lib.getNativeType(value)) && !Object.ReferenceEquals(t, f.FieldType)) { var ic = Lib.as(value, IConvertible); value = ic.ToType(f.FieldType, null); @@ -788,7 +797,7 @@ import cs.system.Object; #if !erase_generics - private static function getGenericAttr(t:cs.system.Type):cs.internal.HxObject.GenericInterface + public static function getGenericAttr(t:cs.system.Type):cs.internal.HxObject.GenericInterface { for (attr in t.GetCustomAttributes(true)) if (Std.is(attr,cs.internal.HxObject.GenericInterface)) @@ -850,7 +859,7 @@ import cs.system.Object; } @:nativeGen -@:keep @:native("haxe.lang.EmptyObject") private enum EmptyObject +@:keep @:native("haxe.lang.EmptyObject") enum EmptyObject { EMPTY; } diff --git a/std/cs/internal/StringExt.hx b/std/cs/internal/StringExt.hx index 3d0b5b57..ca60c984 100644 --- a/std/cs/internal/StringExt.hx +++ b/std/cs/internal/StringExt.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/cs/io/NativeInput.hx b/std/cs/io/NativeInput.hx index 08907e4a..782e58d6 100644 --- a/std/cs/io/NativeInput.hx +++ b/std/cs/io/NativeInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -28,7 +28,7 @@ import haxe.io.Input; class NativeInput extends Input { - public var canSeek(get_canSeek, null):Bool; + public var canSeek(get,never):Bool; var stream:cs.system.io.Stream; var _eof:Bool; @@ -67,7 +67,7 @@ class NativeInput extends Input stream.Close(); } - private function get_canSeek():Bool + private inline function get_canSeek():Bool { return stream.CanSeek; } diff --git a/std/cs/io/NativeOutput.hx b/std/cs/io/NativeOutput.hx index 3fa5f822..a78dd707 100644 --- a/std/cs/io/NativeOutput.hx +++ b/std/cs/io/NativeOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,7 +26,8 @@ import haxe.io.Output; class NativeOutput extends Output { - var canSeek(get_canSeek, null):Bool; + var canSeek(get,never):Bool; + var stream:cs.system.io.Stream; public function new(stream) { @@ -55,7 +56,7 @@ class NativeOutput extends Output stream.SetLength(haxe.Int64.add(stream.Length, cast(nbytes, Int64))); } - private function get_canSeek():Bool + private inline function get_canSeek():Bool { return stream.CanSeek; } diff --git a/std/cs/types/Char16.hx b/std/cs/types/Char16.hx index 084eb711..0943e224 100644 --- a/std/cs/types/Char16.hx +++ b/std/cs/types/Char16.hx @@ -1,3 +1,24 @@ -package cs.types; +/* + * Copyright (C)2005-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 cs.types; typedef Char16 = cs.StdTypes.Char16; diff --git a/std/cs/types/Int16.hx b/std/cs/types/Int16.hx index 682d19fd..8513cda5 100644 --- a/std/cs/types/Int16.hx +++ b/std/cs/types/Int16.hx @@ -1,3 +1,24 @@ -package cs.types; +/* + * Copyright (C)2005-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 cs.types; typedef Int16 = cs.StdTypes.Int16; diff --git a/std/cs/types/Int64.hx b/std/cs/types/Int64.hx index a39604a3..1bed6783 100644 --- a/std/cs/types/Int64.hx +++ b/std/cs/types/Int64.hx @@ -1,4 +1,25 @@ -package cs.types; +/* + * Copyright (C)2005-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 cs.types; typedef Int64 = cs.StdTypes.Int64; diff --git a/std/cs/types/Int8.hx b/std/cs/types/Int8.hx index ac4d92fd..2a112a2d 100644 --- a/std/cs/types/Int8.hx +++ b/std/cs/types/Int8.hx @@ -1,3 +1,24 @@ -package cs.types; +/* + * Copyright (C)2005-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 cs.types; typedef Int8 = cs.StdTypes.Int8; diff --git a/std/cs/types/UInt16.hx b/std/cs/types/UInt16.hx index 28e8876e..59d12456 100644 --- a/std/cs/types/UInt16.hx +++ b/std/cs/types/UInt16.hx @@ -1,3 +1,24 @@ -package cs.types; +/* + * Copyright (C)2005-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 cs.types; typedef UInt16 = cs.StdTypes.UInt16; diff --git a/std/cs/types/UInt64.hx b/std/cs/types/UInt64.hx index a556a53f..22cfd083 100644 --- a/std/cs/types/UInt64.hx +++ b/std/cs/types/UInt64.hx @@ -1,3 +1,24 @@ -package cs.types; +/* + * Copyright (C)2005-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 cs.types; typedef UInt64 = cs.StdTypes.UInt64; diff --git a/std/cs/types/UInt8.hx b/std/cs/types/UInt8.hx index 2635604c..9fbc97ce 100644 --- a/std/cs/types/UInt8.hx +++ b/std/cs/types/UInt8.hx @@ -1,3 +1,24 @@ -package cs.types; +/* + * Copyright (C)2005-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 cs.types; typedef UInt8 = cs.StdTypes.UInt8; diff --git a/std/flash/Boot.hx b/std/flash/Boot.hx index a49d6afd..c19a7d00 100644 --- a/std/flash/Boot.hx +++ b/std/flash/Boot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -41,6 +41,7 @@ package flash; } #end +@:dox(hide) @:keep class Boot extends flash.display.MovieClip { @@ -79,12 +80,19 @@ class Boot extends flash.display.MovieClip { throw "assert"; } + static var IN_E = 0; public static function enum_to_string( e : { tag : String, params : Array } ) { if( e.params == null ) return e.tag; var pstr = []; - for( p in e.params ) - pstr.push(__string_rec(p,"")); + if( IN_E > 15 ) { + pstr.push("..."); + } else { + IN_E++; + for( p in e.params ) + pstr.push(__string_rec(p, "")); + IN_E--; + } return e.tag+"("+pstr.join(",")+")"; } @@ -235,7 +243,11 @@ class Boot extends flash.display.MovieClip { aproto.remove = function(obj) { var idx = __this__.indexOf(obj); if( idx == -1 ) return false; + #if flash19 + __this__.removeAt(idx); + #else __this__.splice(idx,1); + #end return true; } aproto.iterator = function() { diff --git a/std/flash/Lib.hx b/std/flash/Lib.hx index 19768d6d..5dd355a3 100644 --- a/std/flash/Lib.hx +++ b/std/flash/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,10 @@ */ package flash; +/** + Platform-specific Flash Library. Provides some platform-specific + functions for the Flash target. +**/ class Lib { public static var current : flash.display.MovieClip; diff --git a/std/flash/Memory.hx b/std/flash/Memory.hx index c80e1497..4d20d19d 100644 --- a/std/flash/Memory.hx +++ b/std/flash/Memory.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/flash/NativeXml.hx b/std/flash/NativeXml.hx index b9610a95..dfb090f3 100644 --- a/std/flash/NativeXml.hx +++ b/std/flash/NativeXml.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/flash/Vector.hx b/std/flash/Vector.hx index 5273fc28..b841ae7e 100644 --- a/std/flash/Vector.hx +++ b/std/flash/Vector.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/flash/_std/EReg.hx b/std/flash/_std/EReg.hx index 7ba12b0c..7c49a78f 100644 --- a/std/flash/_std/EReg.hx +++ b/std/flash/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/flash/_std/Reflect.hx b/std/flash/_std/Reflect.hx index a950f85e..e5b1dd82 100644 --- a/std/flash/_std/Reflect.hx +++ b/std/flash/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/flash/_std/Std.hx b/std/flash/_std/Std.hx index 0f4a78a7..361f24f8 100644 --- a/std/flash/_std/Std.hx +++ b/std/flash/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/flash/_std/Type.hx b/std/flash/_std/Type.hx index 4aaeefae..f5c83694 100644 --- a/std/flash/_std/Type.hx +++ b/std/flash/_std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + enum ValueType { TNull; TInt; @@ -269,6 +270,7 @@ enum ValueType { return untyped if( e.params == null ) [] else e.params; } + @:extern public inline static function enumIndex( e : EnumValue ) : Int { return untyped e.index; } diff --git a/std/flash/_std/haxe/Json.hx b/std/flash/_std/haxe/Json.hx index a7865eef..39a32f42 100644 --- a/std/flash/_std/haxe/Json.hx +++ b/std/flash/_std/haxe/Json.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/flash/_std/haxe/Resource.hx b/std/flash/_std/haxe/Resource.hx index 437a4de2..dd4ebd42 100644 --- a/std/flash/_std/haxe/Resource.hx +++ b/std/flash/_std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/flash/_std/haxe/ds/IntMap.hx b/std/flash/_std/haxe/ds/IntMap.hx index 681de03b..ba0d0467 100644 --- a/std/flash/_std/haxe/ds/IntMap.hx +++ b/std/flash/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -47,6 +47,10 @@ package haxe.ds; return true; } + #if as3 + + // unoptimized version + public function keys() : Iterator { return untyped (__keys__(h)).iterator(); } @@ -60,6 +64,18 @@ package haxe.ds; }; } + #else + + public inline function keys() : Iterator { + return new IntMapKeysIterator(h); + } + + public inline function iterator() : Iterator { + return new IntMapValuesIterator(h); + } + + #end + public function toString() : String { var s = new StringBuf(); s.add("{"); @@ -74,5 +90,63 @@ package haxe.ds; s.add("}"); return s.toString(); } +} + +#if !as3 + +// this version uses __has_next__/__forin__ special SWF opcodes for iteration with no allocation + +@:allow(haxe.ds.IntMap) +private class IntMapKeysIterator { + var h:flash.utils.Dictionary; + var index : Int; + var nextIndex : Int; + + inline function new(h:flash.utils.Dictionary):Void { + this.h = h; + this.index = 0; + hasNext(); + } + + public inline function hasNext():Bool { + var h = h, index = index; // tmp vars required for __has_next + var n = untyped __has_next__(h, index); + this.nextIndex = index; // store next index + return n; + } + + public inline function next():Int { + var r : Int = untyped __forin__(h, nextIndex); + index = nextIndex; + return r; + } + +} + +@:allow(haxe.ds.IntMap) +private class IntMapValuesIterator { + var h:flash.utils.Dictionary; + var index : Int; + var nextIndex : Int; + + inline function new(h:flash.utils.Dictionary):Void { + this.h = h; + this.index = 0; + hasNext(); + } + + public inline function hasNext():Bool { + var h = h, index = index; // tmp vars required for __has_next + var n = untyped __has_next__(h, index); + this.nextIndex = index; // store next index + return n; + } + + public inline function next():T { + var r = untyped __foreach__(h, nextIndex); + index = nextIndex; + return r; + } } +#end diff --git a/std/flash/_std/haxe/ds/ObjectMap.hx b/std/flash/_std/haxe/ds/ObjectMap.hx index 9c264761..e62b794c 100644 --- a/std/flash/_std/haxe/ds/ObjectMap.hx +++ b/std/flash/_std/haxe/ds/ObjectMap.hx @@ -1,4 +1,25 @@ -package haxe.ds; +/* + * Copyright (C)2005-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 haxe.ds; @:coreApi class ObjectMap extends flash.utils.Dictionary implements haxe.Constraints.IMap { diff --git a/std/flash/_std/haxe/ds/StringMap.hx b/std/flash/_std/haxe/ds/StringMap.hx index edf394f3..d037d673 100644 --- a/std/flash/_std/haxe/ds/StringMap.hx +++ b/std/flash/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/flash/_std/haxe/ds/UnsafeStringMap.hx b/std/flash/_std/haxe/ds/UnsafeStringMap.hx index 7c817f7f..da4f5ace 100644 --- a/std/flash/_std/haxe/ds/UnsafeStringMap.hx +++ b/std/flash/_std/haxe/ds/UnsafeStringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -52,6 +52,10 @@ class UnsafeStringMap implements haxe.Constraints.IMap { return true; } + #if as3 + + // unoptimized version + public function keys() : Iterator { return untyped (__keys__(h)).iterator(); } @@ -65,6 +69,18 @@ class UnsafeStringMap implements haxe.Constraints.IMap { }; } + #else + + public inline function keys() : Iterator { + return new UnsafeStringMapKeysIterator(h); + } + + public inline function iterator() : Iterator { + return new UnsafeStringMapValuesIterator(h); + } + + #end + public function toString() : String { var s = new StringBuf(); s.add("{"); @@ -81,3 +97,62 @@ class UnsafeStringMap implements haxe.Constraints.IMap { } } + +#if !as3 + +// this version uses __has_next__/__forin__ special SWF opcodes for iteration with no allocation + +@:allow(haxe.ds.UnsafeStringMap) +private class UnsafeStringMapKeysIterator { + var h:flash.utils.Dictionary; + var index : Int; + var nextIndex : Int; + + inline function new(h:flash.utils.Dictionary):Void { + this.h = h; + this.index = 0; + hasNext(); + } + + public inline function hasNext():Bool { + var h = h, index = index; // tmp vars required for __has_next + var n = untyped __has_next__(h, index); + this.nextIndex = index; // store next index + return n; + } + + public inline function next():String { + var r : String = untyped __forin__(h, nextIndex); + index = nextIndex; + return r; + } + +} + +@:allow(haxe.ds.UnsafeStringMap) +private class UnsafeStringMapValuesIterator { + var h:flash.utils.Dictionary; + var index : Int; + var nextIndex : Int; + + inline function new(h:flash.utils.Dictionary):Void { + this.h = h; + this.index = 0; + hasNext(); + } + + public inline function hasNext():Bool { + var h = h, index = index; // tmp vars required for __has_next + var n = untyped __has_next__(h, index); + this.nextIndex = index; // store next index + return n; + } + + public inline function next():T { + var r = untyped __foreach__(h, nextIndex); + index = nextIndex; + return r; + } + +} +#end diff --git a/std/flash/_std/haxe/ds/WeakMap.hx b/std/flash/_std/haxe/ds/WeakMap.hx index 4f2c5a2e..9b125e5f 100644 --- a/std/flash/_std/haxe/ds/WeakMap.hx +++ b/std/flash/_std/haxe/ds/WeakMap.hx @@ -1,4 +1,25 @@ -package haxe.ds; +/* + * Copyright (C)2005-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 haxe.ds; @:coreApi class WeakMap extends flash.utils.Dictionary implements haxe.Constraints.IMap { diff --git a/std/flash/_std/haxe/zip/Compress.hx b/std/flash/_std/haxe/zip/Compress.hx index e833c6d2..0efc61f6 100644 --- a/std/flash/_std/haxe/zip/Compress.hx +++ b/std/flash/_std/haxe/zip/Compress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/flash/_std/haxe/zip/Uncompress.hx b/std/flash/_std/haxe/zip/Uncompress.hx index 8dbf8402..2332fe9f 100644 --- a/std/flash/_std/haxe/zip/Uncompress.hx +++ b/std/flash/_std/haxe/zip/Uncompress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/flash/accessibility/Accessibility.hx b/std/flash/accessibility/Accessibility.hx index dcfd80f4..6df721c3 100644 --- a/std/flash/accessibility/Accessibility.hx +++ b/std/flash/accessibility/Accessibility.hx @@ -1,7 +1,7 @@ package flash.accessibility; extern class Accessibility { - static var active(default,null) : Bool; + static var active(default,never) : Bool; static function sendEvent(source : flash.display.DisplayObject, childID : UInt, eventType : UInt, nonHTML : Bool = false) : Void; static function updateProperties() : Void; } diff --git a/std/flash/accessibility/ISearchableText.hx b/std/flash/accessibility/ISearchableText.hx index 19544846..474dee64 100644 --- a/std/flash/accessibility/ISearchableText.hx +++ b/std/flash/accessibility/ISearchableText.hx @@ -1,5 +1,5 @@ package flash.accessibility; @:require(flash10_1) extern interface ISearchableText { - var searchText(default,null) : String; + var searchText(default,never) : String; } diff --git a/std/flash/accessibility/ISimpleTextSelection.hx b/std/flash/accessibility/ISimpleTextSelection.hx index 9f437821..01b8c890 100644 --- a/std/flash/accessibility/ISimpleTextSelection.hx +++ b/std/flash/accessibility/ISimpleTextSelection.hx @@ -1,6 +1,6 @@ package flash.accessibility; @:require(flash10_1) extern interface ISimpleTextSelection { - var selectionActiveIndex(default,null) : Int; - var selectionAnchorIndex(default,null) : Int; + var selectionActiveIndex(default,never) : Int; + var selectionAnchorIndex(default,never) : Int; } diff --git a/std/flash/automation/Configuration.hx b/std/flash/automation/Configuration.hx index 35eb783a..3bd1b84b 100644 --- a/std/flash/automation/Configuration.hx +++ b/std/flash/automation/Configuration.hx @@ -2,5 +2,5 @@ package flash.automation; @:require(flash10_1) extern class Configuration { static var deviceConfiguration : String; - static var testAutomationConfiguration(default,null) : String; + static var testAutomationConfiguration(default,never) : String; } diff --git a/std/flash/automation/KeyboardAutomationAction.hx b/std/flash/automation/KeyboardAutomationAction.hx index 08aa180f..ed5ca7b9 100644 --- a/std/flash/automation/KeyboardAutomationAction.hx +++ b/std/flash/automation/KeyboardAutomationAction.hx @@ -3,6 +3,6 @@ package flash.automation; @:require(flash10_1) extern class KeyboardAutomationAction extends AutomationAction { var keyCode : UInt; function new(type : String, keyCode : UInt = 0) : Void; - static var KEY_DOWN : String; - static var KEY_UP : String; + static var KEY_DOWN(default,never) : String; + static var KEY_UP(default,never) : String; } diff --git a/std/flash/automation/MouseAutomationAction.hx b/std/flash/automation/MouseAutomationAction.hx index d9574f83..518b3520 100644 --- a/std/flash/automation/MouseAutomationAction.hx +++ b/std/flash/automation/MouseAutomationAction.hx @@ -5,12 +5,12 @@ package flash.automation; var stageX : Float; var stageY : Float; function new(type : String, stageX : Float = 0, stageY : Float = 0, delta : Int = 0) : Void; - static var MIDDLE_MOUSE_DOWN : String; - static var MIDDLE_MOUSE_UP : String; - static var MOUSE_DOWN : String; - static var MOUSE_MOVE : String; - static var MOUSE_UP : String; - static var MOUSE_WHEEL : String; - static var RIGHT_MOUSE_DOWN : String; - static var RIGHT_MOUSE_UP : String; + static var MIDDLE_MOUSE_DOWN(default,never) : String; + static var MIDDLE_MOUSE_UP(default,never) : String; + static var MOUSE_DOWN(default,never) : String; + static var MOUSE_MOVE(default,never) : String; + static var MOUSE_UP(default,never) : String; + static var MOUSE_WHEEL(default,never) : String; + static var RIGHT_MOUSE_DOWN(default,never) : String; + static var RIGHT_MOUSE_UP(default,never) : String; } diff --git a/std/flash/automation/StageCapture.hx b/std/flash/automation/StageCapture.hx index 43f5c3cc..dfd58f2a 100644 --- a/std/flash/automation/StageCapture.hx +++ b/std/flash/automation/StageCapture.hx @@ -1,6 +1,7 @@ package flash.automation; @:require(flash10_1) extern class StageCapture extends flash.events.EventDispatcher { + var capturePTS : Float; var captureSource : String; var clipRect : flash.geom.Rectangle; var fileNameBase : String; @@ -8,10 +9,10 @@ package flash.automation; function cancel() : Void; function capture(type : String) : Void; function captureBitmapData() : flash.display.BitmapData; - static var CURRENT : String; - static var MULTIPLE : String; - static var NEXT : String; - static var RASTER : String; - static var SCREEN : String; - static var STAGE : String; + static var CURRENT(default,never) : String; + static var MULTIPLE(default,never) : String; + static var NEXT(default,never) : String; + static var RASTER(default,never) : String; + static var SCREEN(default,never) : String; + static var STAGE(default,never) : String; } diff --git a/std/flash/automation/StageCaptureEvent.hx b/std/flash/automation/StageCaptureEvent.hx index 8b89542d..c0222266 100644 --- a/std/flash/automation/StageCaptureEvent.hx +++ b/std/flash/automation/StageCaptureEvent.hx @@ -1,8 +1,9 @@ package flash.automation; @:require(flash10_1) extern class StageCaptureEvent extends flash.events.Event { - var checksum(default,null) : UInt; - var url(default,null) : String; - function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?url : String, checksum : UInt = 0) : Void; - static var CAPTURE : String; + var checksum(default,never) : UInt; + var pts(default,never) : Float; + var url(default,never) : String; + function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?url : String, checksum : UInt = 0, pts : Float = 0) : Void; + static var CAPTURE(default,never) : String; } diff --git a/std/flash/concurrent/Condition.hx b/std/flash/concurrent/Condition.hx index fb7b9b9c..66316fcb 100644 --- a/std/flash/concurrent/Condition.hx +++ b/std/flash/concurrent/Condition.hx @@ -1,10 +1,10 @@ package flash.concurrent; @:final @:require(flash11_4) extern class Condition { - var mutex(default,null) : Mutex; + var mutex(default,never) : Mutex; function new(mutex : Mutex) : Void; function notify() : Void; function notifyAll() : Void; function wait(timeout : Float = -1) : Bool; - static var isSupported(default,null) : Bool; + static var isSupported(default,never) : Bool; } diff --git a/std/flash/concurrent/Mutex.hx b/std/flash/concurrent/Mutex.hx index a8cd7c06..45fed1f6 100644 --- a/std/flash/concurrent/Mutex.hx +++ b/std/flash/concurrent/Mutex.hx @@ -5,5 +5,5 @@ package flash.concurrent; function lock() : Void; function tryLock() : Bool; function unlock() : Void; - static var isSupported(default,null) : Bool; + static var isSupported(default,never) : Bool; } diff --git a/std/flash/desktop/Clipboard.hx b/std/flash/desktop/Clipboard.hx index cc0df798..1b5dad0d 100644 --- a/std/flash/desktop/Clipboard.hx +++ b/std/flash/desktop/Clipboard.hx @@ -1,12 +1,12 @@ package flash.desktop; @:require(flash10) extern class Clipboard { - var formats(default,null) : Array; + var formats(default,never) : Array; function clear() : Void; function clearData(format : ClipboardFormats) : Void; function getData(format : ClipboardFormats, ?transferMode : ClipboardTransferMode) : flash.utils.Object; function hasFormat(format : ClipboardFormats) : Bool; function setData(format : ClipboardFormats, data : flash.utils.Object, serializable : Bool = true) : Bool; function setDataHandler(format : ClipboardFormats, handler : flash.utils.Function, serializable : Bool = true) : Bool; - static var generalClipboard(default,null) : Clipboard; + static var generalClipboard(default,never) : Clipboard; } diff --git a/std/flash/display/AVLoader.hx b/std/flash/display/AVLoader.hx new file mode 100644 index 00000000..4d476377 --- /dev/null +++ b/std/flash/display/AVLoader.hx @@ -0,0 +1,5 @@ +package flash.display; + +extern class AVLoader extends Loader { + function new() : Void; +} diff --git a/std/flash/display/BitmapData.hx b/std/flash/display/BitmapData.hx index 54fd145c..2f100402 100644 --- a/std/flash/display/BitmapData.hx +++ b/std/flash/display/BitmapData.hx @@ -1,10 +1,10 @@ package flash.display; extern class BitmapData implements IBitmapDrawable { - var height(default,null) : Int; - var rect(default,null) : flash.geom.Rectangle; - var transparent(default,null) : Bool; - var width(default,null) : Int; + var height(default,never) : Int; + var rect(default,never) : flash.geom.Rectangle; + var transparent(default,never) : Bool; + var width(default,never) : Int; function new(width : Int, height : Int, transparent : Bool = true, fillColor : UInt = 0xFFFFFFFF) : Void; function applyFilter(sourceBitmapData : BitmapData, sourceRect : flash.geom.Rectangle, destPoint : flash.geom.Point, filter : flash.filters.BitmapFilter) : Void; function clone() : BitmapData; diff --git a/std/flash/display/DisplayObject.hx b/std/flash/display/DisplayObject.hx index 183f412d..639e08a6 100644 --- a/std/flash/display/DisplayObject.hx +++ b/std/flash/display/DisplayObject.hx @@ -4,18 +4,18 @@ extern class DisplayObject extends flash.events.EventDispatcher implements IBitm var accessibilityProperties : flash.accessibility.AccessibilityProperties; var alpha : Float; var blendMode : BlendMode; - @:require(flash10) var blendShader(null,default) : Shader; + @:require(flash10) var blendShader(never,default) : Shader; var cacheAsBitmap : Bool; var filters : Array; var height : Float; - var loaderInfo(default,null) : LoaderInfo; + var loaderInfo(default,never) : LoaderInfo; var mask : DisplayObject; - var mouseX(default,null) : Float; - var mouseY(default,null) : Float; + var mouseX(default,never) : Float; + var mouseY(default,never) : Float; var name : String; var opaqueBackground : Null; - var parent(default,null) : DisplayObjectContainer; - var root(default,null) : DisplayObject; + var parent(default,never) : DisplayObjectContainer; + var root(default,never) : DisplayObject; var rotation : Float; @:require(flash10) var rotationX : Float; @:require(flash10) var rotationY : Float; @@ -25,7 +25,7 @@ extern class DisplayObject extends flash.events.EventDispatcher implements IBitm var scaleY : Float; @:require(flash10) var scaleZ : Float; var scrollRect : flash.geom.Rectangle; - var stage(default,null) : Stage; + var stage(default,never) : Stage; var transform : flash.geom.Transform; var visible : Bool; var width : Float; diff --git a/std/flash/display/DisplayObjectContainer.hx b/std/flash/display/DisplayObjectContainer.hx index 417c7a2d..deb49ed2 100644 --- a/std/flash/display/DisplayObjectContainer.hx +++ b/std/flash/display/DisplayObjectContainer.hx @@ -2,9 +2,9 @@ package flash.display; extern class DisplayObjectContainer extends InteractiveObject { var mouseChildren : Bool; - var numChildren(default,null) : Int; + var numChildren(default,never) : Int; var tabChildren : Bool; - var textSnapshot(default,null) : flash.text.TextSnapshot; + var textSnapshot(default,never) : flash.text.TextSnapshot; function new() : Void; function addChild(child : DisplayObject) : DisplayObject; function addChildAt(child : DisplayObject, index : Int) : DisplayObject; diff --git a/std/flash/display/FrameLabel.hx b/std/flash/display/FrameLabel.hx index 2295b715..60563365 100644 --- a/std/flash/display/FrameLabel.hx +++ b/std/flash/display/FrameLabel.hx @@ -1,7 +1,7 @@ package flash.display; @:final extern class FrameLabel extends flash.events.EventDispatcher { - var frame(default,null) : Int; - var name(default,null) : String; + var frame(default,never) : Int; + var name(default,never) : String; function new(name : String, frame : Int) : Void; } diff --git a/std/flash/display/Graphics.hx b/std/flash/display/Graphics.hx index a520bc02..eaa237b3 100644 --- a/std/flash/display/Graphics.hx +++ b/std/flash/display/Graphics.hx @@ -15,14 +15,14 @@ package flash.display; @:require(flash10) function drawGraphicsData(graphicsData : flash.Vector) : Void; @:require(flash10) function drawPath(commands : flash.Vector, data : flash.Vector, ?winding : GraphicsPathWinding) : Void; function drawRect(x : Float, y : Float, width : Float, height : Float) : Void; - function drawRoundRect(x : Float, y : Float, width : Float, height : Float, ellipseWidth : Float, ?ellipseHeight : Float) : Void; + function drawRoundRect(x : Float, y : Float, width : Float, height : Float, ellipseWidth : Float, ellipseHeight : Null = 0) : Void; function drawRoundRectComplex(x : Float, y : Float, width : Float, height : Float, topLeftRadius : Float, topRightRadius : Float, bottomLeftRadius : Float, bottomRightRadius : Float) : Void; @:require(flash10) function drawTriangles(vertices : flash.Vector, ?indices : flash.Vector, ?uvtData : flash.Vector, ?culling : TriangleCulling) : Void; function endFill() : Void; @:require(flash10) function lineBitmapStyle(bitmap : BitmapData, ?matrix : flash.geom.Matrix, repeat : Bool = true, smooth : Bool = false) : Void; function lineGradientStyle(type : GradientType, colors : Array, alphas : Array, ratios : Array, ?matrix : flash.geom.Matrix, ?spreadMethod : SpreadMethod, ?interpolationMethod : InterpolationMethod, focalPointRatio : Float = 0) : Void; @:require(flash10) function lineShaderStyle(shader : Shader, ?matrix : flash.geom.Matrix) : Void; - function lineStyle(?thickness : Float, color : UInt = 0, alpha : Float = 1, pixelHinting : Bool = false, ?scaleMode : LineScaleMode, ?caps : CapsStyle, ?joints : JointStyle, miterLimit : Float = 3) : Void; + function lineStyle(thickness : Null = 0, color : UInt = 0, alpha : Float = 1, pixelHinting : Bool = false, ?scaleMode : LineScaleMode, ?caps : CapsStyle, ?joints : JointStyle, miterLimit : Float = 3) : Void; function lineTo(x : Float, y : Float) : Void; function moveTo(x : Float, y : Float) : Void; @:require(flash11_6) function readGraphicsData(recurse : Bool = true) : flash.Vector; diff --git a/std/flash/display/Loader.hx b/std/flash/display/Loader.hx index 7133a365..3264fd6a 100644 --- a/std/flash/display/Loader.hx +++ b/std/flash/display/Loader.hx @@ -1,9 +1,9 @@ package flash.display; extern class Loader extends DisplayObjectContainer { - var content(default,null) : DisplayObject; - var contentLoaderInfo(default,null) : LoaderInfo; - @:require(flash10_1) var uncaughtErrorEvents(default,null) : flash.events.UncaughtErrorEvents; + var content(default,never) : DisplayObject; + var contentLoaderInfo(default,never) : LoaderInfo; + @:require(flash10_1) var uncaughtErrorEvents(default,never) : flash.events.UncaughtErrorEvents; function new() : Void; function close() : Void; function load(request : flash.net.URLRequest, ?context : flash.system.LoaderContext) : Void; diff --git a/std/flash/display/LoaderInfo.hx b/std/flash/display/LoaderInfo.hx index ebfd9f77..eeaacb89 100644 --- a/std/flash/display/LoaderInfo.hx +++ b/std/flash/display/LoaderInfo.hx @@ -1,28 +1,28 @@ package flash.display; extern class LoaderInfo extends flash.events.EventDispatcher { - var actionScriptVersion(default,null) : ActionScriptVersion; - var applicationDomain(default,null) : flash.system.ApplicationDomain; - var bytes(default,null) : flash.utils.ByteArray; - var bytesLoaded(default,null) : UInt; - var bytesTotal(default,null) : UInt; - var childAllowsParent(default,null) : Bool; + var actionScriptVersion(default,never) : ActionScriptVersion; + var applicationDomain(default,never) : flash.system.ApplicationDomain; + var bytes(default,never) : flash.utils.ByteArray; + var bytesLoaded(default,never) : UInt; + var bytesTotal(default,never) : UInt; + var childAllowsParent(default,never) : Bool; @:require(flash11_4) var childSandboxBridge : Dynamic; - var content(default,null) : DisplayObject; - var contentType(default,null) : String; - var frameRate(default,null) : Float; - var height(default,null) : Int; - @:require(flash10_1) var isURLInaccessible(default,null) : Bool; - var loader(default,null) : Loader; - var loaderURL(default,null) : String; - var parameters(default,null) : Dynamic; - var parentAllowsChild(default,null) : Bool; + var content(default,never) : DisplayObject; + var contentType(default,never) : String; + var frameRate(default,never) : Float; + var height(default,never) : Int; + @:require(flash10_1) var isURLInaccessible(default,never) : Bool; + var loader(default,never) : Loader; + var loaderURL(default,never) : String; + var parameters(default,never) : Dynamic; + var parentAllowsChild(default,never) : Bool; @:require(flash11_4) var parentSandboxBridge : Dynamic; - var sameDomain(default,null) : Bool; - var sharedEvents(default,null) : flash.events.EventDispatcher; - var swfVersion(default,null) : UInt; - @:require(flash10_1) var uncaughtErrorEvents(default,null) : flash.events.UncaughtErrorEvents; - var url(default,null) : String; - var width(default,null) : Int; + var sameDomain(default,never) : Bool; + var sharedEvents(default,never) : flash.events.EventDispatcher; + var swfVersion(default,never) : UInt; + @:require(flash10_1) var uncaughtErrorEvents(default,never) : flash.events.UncaughtErrorEvents; + var url(default,never) : String; + var width(default,never) : Int; static function getLoaderInfoByDefinition(object : Dynamic) : LoaderInfo; } diff --git a/std/flash/display/MovieClip.hx b/std/flash/display/MovieClip.hx index ca5727e6..10ba642a 100644 --- a/std/flash/display/MovieClip.hx +++ b/std/flash/display/MovieClip.hx @@ -1,16 +1,16 @@ package flash.display; extern class MovieClip extends Sprite #if !flash_strict implements Dynamic #end { - var currentFrame(default,null) : Int; - @:require(flash10) var currentFrameLabel(default,null) : String; - var currentLabel(default,null) : String; - var currentLabels(default,null) : Array; - var currentScene(default,null) : Scene; + var currentFrame(default,never) : Int; + @:require(flash10) var currentFrameLabel(default,never) : String; + var currentLabel(default,never) : String; + var currentLabels(default,never) : Array; + var currentScene(default,never) : Scene; var enabled : Bool; - var framesLoaded(default,null) : Int; - @:require(flash11) var isPlaying(default,null) : Bool; - var scenes(default,null) : Array; - var totalFrames(default,null) : Int; + var framesLoaded(default,never) : Int; + @:require(flash11) var isPlaying(default,never) : Bool; + var scenes(default,never) : Array; + var totalFrames(default,never) : Int; var trackAsMenu : Bool; function new() : Void; function addFrameScript(?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; diff --git a/std/flash/display/SWFVersion.hx b/std/flash/display/SWFVersion.hx index 297ae67b..9912de01 100644 --- a/std/flash/display/SWFVersion.hx +++ b/std/flash/display/SWFVersion.hx @@ -1,16 +1,16 @@ package flash.display; extern class SWFVersion { - static var FLASH1 : UInt; - static var FLASH10 : UInt; - static var FLASH11 : UInt; - static var FLASH12 : UInt; - static var FLASH2 : UInt; - static var FLASH3 : UInt; - static var FLASH4 : UInt; - static var FLASH5 : UInt; - static var FLASH6 : UInt; - static var FLASH7 : UInt; - static var FLASH8 : UInt; - static var FLASH9 : UInt; + static var FLASH1(default,never) : UInt; + static var FLASH10(default,never) : UInt; + static var FLASH11(default,never) : UInt; + static var FLASH12(default,never) : UInt; + static var FLASH2(default,never) : UInt; + static var FLASH3(default,never) : UInt; + static var FLASH4(default,never) : UInt; + static var FLASH5(default,never) : UInt; + static var FLASH6(default,never) : UInt; + static var FLASH7(default,never) : UInt; + static var FLASH8(default,never) : UInt; + static var FLASH9(default,never) : UInt; } diff --git a/std/flash/display/Scene.hx b/std/flash/display/Scene.hx index 3141fe10..4fa35213 100644 --- a/std/flash/display/Scene.hx +++ b/std/flash/display/Scene.hx @@ -1,8 +1,8 @@ package flash.display; @:final extern class Scene { - var labels(default,null) : Array; - var name(default,null) : String; - var numFrames(default,null) : Int; + var labels(default,never) : Array; + var name(default,never) : String; + var numFrames(default,never) : Int; function new(name : String, labels : Array, numFrames : Int) : Void; } diff --git a/std/flash/display/Shader.hx b/std/flash/display/Shader.hx index e97974c9..59a70c4d 100644 --- a/std/flash/display/Shader.hx +++ b/std/flash/display/Shader.hx @@ -1,7 +1,7 @@ package flash.display; @:require(flash10) extern class Shader { - var byteCode(null,default) : flash.utils.ByteArray; + var byteCode(never,default) : flash.utils.ByteArray; var data : ShaderData; var precisionHint : ShaderPrecision; function new(?code : flash.utils.ByteArray) : Void; diff --git a/std/flash/display/ShaderInput.hx b/std/flash/display/ShaderInput.hx index 45aeb0a7..5ce1686d 100644 --- a/std/flash/display/ShaderInput.hx +++ b/std/flash/display/ShaderInput.hx @@ -1,9 +1,9 @@ package flash.display; @:final extern class ShaderInput implements Dynamic { - var channels(default,null) : Int; + var channels(default,never) : Int; var height : Int; - var index(default,null) : Int; + var index(default,never) : Int; var input : Dynamic; var width : Int; function new() : Void; diff --git a/std/flash/display/ShaderJob.hx b/std/flash/display/ShaderJob.hx index bd14b500..f5108222 100644 --- a/std/flash/display/ShaderJob.hx +++ b/std/flash/display/ShaderJob.hx @@ -2,7 +2,7 @@ package flash.display; extern class ShaderJob extends flash.events.EventDispatcher { var height : Int; - var progress(default,null) : Float; + var progress(default,never) : Float; var shader : Shader; var target : Dynamic; var width : Int; diff --git a/std/flash/display/ShaderParameter.hx b/std/flash/display/ShaderParameter.hx index a0687f61..4b02ccb8 100644 --- a/std/flash/display/ShaderParameter.hx +++ b/std/flash/display/ShaderParameter.hx @@ -1,7 +1,7 @@ package flash.display; @:final extern class ShaderParameter implements Dynamic { - var index(default,null) : Int; - var type(default,null) : ShaderParameterType; + var index(default,never) : Int; + var type(default,never) : ShaderParameterType; var value : Array; } diff --git a/std/flash/display/Shape.hx b/std/flash/display/Shape.hx index dd4cbbe3..fb13285c 100644 --- a/std/flash/display/Shape.hx +++ b/std/flash/display/Shape.hx @@ -1,6 +1,6 @@ package flash.display; extern class Shape extends DisplayObject { - var graphics(default,null) : Graphics; + var graphics(default,never) : Graphics; function new() : Void; } diff --git a/std/flash/display/Sprite.hx b/std/flash/display/Sprite.hx index d559f2a9..aad8eeb9 100644 --- a/std/flash/display/Sprite.hx +++ b/std/flash/display/Sprite.hx @@ -2,8 +2,8 @@ package flash.display; extern class Sprite extends DisplayObjectContainer { var buttonMode : Bool; - var dropTarget(default,null) : DisplayObject; - var graphics(default,null) : Graphics; + var dropTarget(default,never) : DisplayObject; + var graphics(default,never) : Graphics; var hitArea : Sprite; var soundTransform : flash.media.SoundTransform; var useHandCursor : Bool; diff --git a/std/flash/display/Stage.hx b/std/flash/display/Stage.hx index 3bebca40..6bdc2aaa 100644 --- a/std/flash/display/Stage.hx +++ b/std/flash/display/Stage.hx @@ -2,31 +2,31 @@ package flash.display; extern class Stage extends DisplayObjectContainer { var align : StageAlign; - @:require(flash10_2) var allowsFullScreen(default,null) : Bool; - @:require(flash11_3) var allowsFullScreenInteractive(default,null) : Bool; - @:require(flash15) var browserZoomFactor(default,null) : Float; + var allowsFullScreen(default,never) : Bool; + @:require(flash11_3) var allowsFullScreenInteractive(default,never) : Bool; + var browserZoomFactor(default,never) : Float; @:require(flash10_2) var color : UInt; @:require(flash10) var colorCorrection : ColorCorrection; - @:require(flash10) var colorCorrectionSupport(default,null) : ColorCorrectionSupport; - @:require(flash11_4) var contentsScaleFactor(default,null) : Float; - @:require(flash11) var displayContextInfo(default,null) : String; + @:require(flash10) var colorCorrectionSupport(default,never) : ColorCorrectionSupport; + @:require(flash11_4) var contentsScaleFactor(default,never) : Float; + @:require(flash11) var displayContextInfo(default,never) : String; var displayState : StageDisplayState; var focus : InteractiveObject; var frameRate : Float; - var fullScreenHeight(default,null) : UInt; + var fullScreenHeight(default,never) : UInt; var fullScreenSourceRect : flash.geom.Rectangle; - var fullScreenWidth(default,null) : UInt; + var fullScreenWidth(default,never) : UInt; @:require(flash11_2) var mouseLock : Bool; var quality : StageQuality; var scaleMode : StageScaleMode; var showDefaultContextMenu : Bool; - @:require(flash11) var softKeyboardRect(default,null) : flash.geom.Rectangle; - @:require(flash11) var stage3Ds(default,null) : flash.Vector; + @:require(flash11) var softKeyboardRect(default,never) : flash.geom.Rectangle; + @:require(flash11) var stage3Ds(default,never) : flash.Vector; var stageFocusRect : Bool; var stageHeight : Int; - @:require(flash10_2) var stageVideos(default,null) : flash.Vector; + @:require(flash10_2) var stageVideos(default,never) : flash.Vector; var stageWidth : Int; - @:require(flash10_1) var wmodeGPU(default,null) : Bool; + @:require(flash10_1) var wmodeGPU(default,never) : Bool; function invalidate() : Void; function isFocusInaccessible() : Bool; } diff --git a/std/flash/display/Stage3D.hx b/std/flash/display/Stage3D.hx index e76f9b67..09784dc1 100644 --- a/std/flash/display/Stage3D.hx +++ b/std/flash/display/Stage3D.hx @@ -1,10 +1,10 @@ package flash.display; @:require(flash11) extern class Stage3D extends flash.events.EventDispatcher { - var context3D(default,null) : flash.display3D.Context3D; + var context3D(default,never) : flash.display3D.Context3D; var visible : Bool; var x : Float; var y : Float; - function requestContext3D(?context3DRenderMode : flash.display3D.Context3DRenderMode, ?profile : flash.display3D.Context3DProfile) : Void; + function requestContext3D(?context3DRenderMode : String, ?profile : flash.display3D.Context3DProfile) : Void; @:require(flash12) function requestContext3DMatchingProfiles(profiles : flash.Vector) : Void; } diff --git a/std/flash/display3D/Context3D.hx b/std/flash/display3D/Context3D.hx index e9154f7e..7d355ad7 100644 --- a/std/flash/display3D/Context3D.hx +++ b/std/flash/display3D/Context3D.hx @@ -1,13 +1,14 @@ package flash.display3D; @:final extern class Context3D extends flash.events.EventDispatcher { - @:require(flash15) var backBufferHeight(default,null) : Int; - @:require(flash15) var backBufferWidth(default,null) : Int; - var driverInfo(default,null) : String; + var backBufferHeight(default,never) : Int; + var backBufferWidth(default,never) : Int; + var driverInfo(default,never) : String; var enableErrorChecking : Bool; - @:require(flash15) var maxBackBufferHeight : Int; - @:require(flash15) var maxBackBufferWidth : Int; - @:require(flash12) var profile(default,null) : String; + var maxBackBufferHeight : Int; + var maxBackBufferWidth : Int; + @:require(flash12) var profile(default,never) : String; + var totalGPUMemory(default,never) : Float; function clear(red : Float = 0, green : Float = 0, blue : Float = 0, alpha : Float = 1, depth : Float = 1, stencil : UInt = 0, mask : UInt = 0xFFFFFFFF) : Void; function configureBackBuffer(width : Int, height : Int, antiAlias : Int, enableDepthAndStencil : Bool = true, wantsBestResolution : Bool = false, wantsBestResolutionOnBrowserZoom : Bool = false) : Void; function createCubeTexture(size : Int, format : Context3DTextureFormat, optimizeForRenderToTexture : Bool, streamingLevels : Int = 0) : flash.display3D.textures.CubeTexture; @@ -16,7 +17,7 @@ package flash.display3D; @:require(flash11_8) function createRectangleTexture(width : Int, height : Int, format : Context3DTextureFormat, optimizeForRenderToTexture : Bool) : flash.display3D.textures.RectangleTexture; function createTexture(width : Int, height : Int, format : Context3DTextureFormat, optimizeForRenderToTexture : Bool, streamingLevels : Int = 0) : flash.display3D.textures.Texture; function createVertexBuffer(numVertices : Int, data32PerVertex : Int, ?bufferUsage : Context3DBufferUsage) : VertexBuffer3D; - @:require(flash15) function createVideoTexture() : flash.display3D.textures.VideoTexture; + function createVideoTexture() : flash.display3D.textures.VideoTexture; function dispose(recreate : Bool = true) : Void; function drawToBitmapData(destination : flash.display.BitmapData) : Void; function drawTriangles(indexBuffer : IndexBuffer3D, firstIndex : Int = 0, numTriangles : Int = -1) : Void; @@ -25,7 +26,6 @@ package flash.display3D; function setColorMask(red : Bool, green : Bool, blue : Bool, alpha : Bool) : Void; function setCulling(triangleFaceToCull : Context3DTriangleFace) : Void; function setDepthTest(depthMask : Bool, passCompareMode : Context3DCompareMode) : Void; - @:require(flash16) function setFillMode( fillMode : Context3DFillMode ) : Void; function setProgram(program : Program3D) : Void; @:require(flash11_2) function setProgramConstantsFromByteArray(programType : Context3DProgramType, firstRegister : Int, numRegisters : Int, data : flash.utils.ByteArray, byteArrayOffset : UInt) : Void; function setProgramConstantsFromMatrix(programType : Context3DProgramType, firstRegister : Int, matrix : flash.geom.Matrix3D, transposedMatrix : Bool = false) : Void; @@ -38,5 +38,5 @@ package flash.display3D; function setStencilReferenceValue(referenceValue : UInt, readMask : UInt = 255, writeMask : UInt = 255) : Void; function setTextureAt(sampler : Int, texture : flash.display3D.textures.TextureBase) : Void; function setVertexBufferAt(index : Int, buffer : VertexBuffer3D, bufferOffset : Int = 0, ?format : Context3DVertexBufferFormat) : Void; - @:require(flash15) static var supportsVideoTexture(default,null) : Bool; + static var supportsVideoTexture(default,never) : Bool; } diff --git a/std/flash/display3D/Context3DClearMask.hx b/std/flash/display3D/Context3DClearMask.hx index f2aaf21a..c66f3122 100644 --- a/std/flash/display3D/Context3DClearMask.hx +++ b/std/flash/display3D/Context3DClearMask.hx @@ -1,8 +1,8 @@ package flash.display3D; extern class Context3DClearMask { - static var ALL : Int; - static var COLOR : Int; - static var DEPTH : Int; - static var STENCIL : Int; + static var ALL(default,never) : Int; + static var COLOR(default,never) : Int; + static var DEPTH(default,never) : Int; + static var STENCIL(default,never) : Int; } diff --git a/std/flash/display3D/Context3DProfile.hx b/std/flash/display3D/Context3DProfile.hx index cd5184c7..a90ea9c6 100644 --- a/std/flash/display3D/Context3DProfile.hx +++ b/std/flash/display3D/Context3DProfile.hx @@ -6,4 +6,5 @@ package flash.display3D; BASELINE_EXTENDED; STANDARD; STANDARD_CONSTRAINED; + STANDARD_EXTENDED; } diff --git a/std/flash/display3D/textures/VideoTexture.hx b/std/flash/display3D/textures/VideoTexture.hx index 0c04f1d2..ae3175e9 100644 --- a/std/flash/display3D/textures/VideoTexture.hx +++ b/std/flash/display3D/textures/VideoTexture.hx @@ -1,8 +1,8 @@ package flash.display3D.textures; @:final extern class VideoTexture extends TextureBase { - var videoHeight(default,null) : Int; - var videoWidth(default,null) : Int; + var videoHeight(default,never) : Int; + var videoWidth(default,never) : Int; function new() : Void; function attachCamera(theCamera : flash.media.Camera) : Void; function attachNetStream(netStream : flash.net.NetStream) : Void; diff --git a/std/flash/errors/DRMManagerError.hx b/std/flash/errors/DRMManagerError.hx index cb53e4a0..573d73c1 100644 --- a/std/flash/errors/DRMManagerError.hx +++ b/std/flash/errors/DRMManagerError.hx @@ -1,7 +1,7 @@ package flash.errors; @:require(flash10_1) extern class DRMManagerError extends Error { - var subErrorID(default,null) : Int; + var subErrorID(default,never) : Int; function new(message : String, id : Int, subErrorID : Int) : Void; function toString() : String; } diff --git a/std/flash/errors/Error.hx b/std/flash/errors/Error.hx index 3f7f2b13..b5bd7281 100644 --- a/std/flash/errors/Error.hx +++ b/std/flash/errors/Error.hx @@ -1,12 +1,12 @@ package flash.errors; extern class Error #if !flash_strict implements Dynamic #end { - var errorID(default,null) : Int; + var errorID(default,never) : Int; var message : Dynamic; var name : Dynamic; function new(?message : Dynamic, id : Dynamic = 0) : Void; function getStackTrace() : String; - static var length : Int; + static var length(default,never) : Int; static function getErrorMessage(index : Int) : String; static function throwError(type : Class, index : UInt, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Dynamic; } diff --git a/std/flash/events/AVDictionaryDataEvent.hx b/std/flash/events/AVDictionaryDataEvent.hx index 396ad8c2..98e41dbe 100644 --- a/std/flash/events/AVDictionaryDataEvent.hx +++ b/std/flash/events/AVDictionaryDataEvent.hx @@ -1,8 +1,8 @@ package flash.events; extern class AVDictionaryDataEvent extends Event { - var dictionary(default,null) : flash.utils.Dictionary; - var time(default,null) : Float; + var dictionary(default,never) : flash.utils.Dictionary; + var time(default,never) : Float; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?init_dictionary : flash.utils.Dictionary, init_dataTime : Float = 0) : Void; - static var AV_DICTIONARY_DATA : String; + static var AV_DICTIONARY_DATA(default,never) : String; } diff --git a/std/flash/events/AVHTTPStatusEvent.hx b/std/flash/events/AVHTTPStatusEvent.hx index bed4c2e2..a0f02831 100644 --- a/std/flash/events/AVHTTPStatusEvent.hx +++ b/std/flash/events/AVHTTPStatusEvent.hx @@ -3,7 +3,7 @@ package flash.events; extern class AVHTTPStatusEvent extends Event { var responseHeaders : Array; var responseURL : String; - var status(default,null) : Int; + var status(default,never) : Int; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, status : Int = 0, ?responseUrl : String, ?responseHeaders : Array) : Void; - static var AV_HTTP_RESPONSE_STATUS : String; + static var AV_HTTP_RESPONSE_STATUS(default,never) : String; } diff --git a/std/flash/events/AVLoadInfoEvent.hx b/std/flash/events/AVLoadInfoEvent.hx index 9923eb35..2415b32f 100644 --- a/std/flash/events/AVLoadInfoEvent.hx +++ b/std/flash/events/AVLoadInfoEvent.hx @@ -1,7 +1,7 @@ package flash.events; extern class AVLoadInfoEvent extends Event { - var loadInfo(default,null) : flash.utils.Dictionary; + var loadInfo(default,never) : flash.utils.Dictionary; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?inLoadInfo : flash.utils.Dictionary) : Void; - static var AV_LOAD_INFO : Dynamic; + static var AV_LOAD_INFO(default,never) : Dynamic; } diff --git a/std/flash/events/AVManifestLoadEvent.hx b/std/flash/events/AVManifestLoadEvent.hx index ac596852..5a168b6e 100644 --- a/std/flash/events/AVManifestLoadEvent.hx +++ b/std/flash/events/AVManifestLoadEvent.hx @@ -1,10 +1,10 @@ package flash.events; extern class AVManifestLoadEvent extends Event { - var duration(default,null) : Float; - var handle(default,null) : Int; - var result(default,null) : flash.media.AVResult; - var userData(default,null) : Int; + var duration(default,never) : Float; + var handle(default,never) : Int; + var result(default,never) : flash.media.AVResult; + var userData(default,never) : Int; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, inResult : Int = 0, inUserData : Int = 0, inHandle : Int = 0, inDuration : Float = 0) : Void; - static var AV_MANIFEST_LOAD : String; + static var AV_MANIFEST_LOAD(default,never) : String; } diff --git a/std/flash/events/AVPauseAtPeriodEndEvent.hx b/std/flash/events/AVPauseAtPeriodEndEvent.hx index d211ebb9..2a577c88 100644 --- a/std/flash/events/AVPauseAtPeriodEndEvent.hx +++ b/std/flash/events/AVPauseAtPeriodEndEvent.hx @@ -1,7 +1,7 @@ package flash.events; extern class AVPauseAtPeriodEndEvent extends Event { - var userData(default,null) : Int; + var userData(default,never) : Int; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, userData : Int = 0) : Void; - static var AV_PAUSE_AT_PERIOD_END : String; + static var AV_PAUSE_AT_PERIOD_END(default,never) : String; } diff --git a/std/flash/events/AVPlayStateEvent.hx b/std/flash/events/AVPlayStateEvent.hx index 8a9dd654..f5c6d217 100644 --- a/std/flash/events/AVPlayStateEvent.hx +++ b/std/flash/events/AVPlayStateEvent.hx @@ -1,7 +1,7 @@ package flash.events; extern class AVPlayStateEvent extends Event { - var playState(default,null) : flash.media.AVPlayState; + var playState(default,never) : flash.media.AVPlayState; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, inState : Int = 0) : Void; - static var AV_PLAY_STATE : String; + static var AV_PLAY_STATE(default,never) : String; } diff --git a/std/flash/events/AVStatusEvent.hx b/std/flash/events/AVStatusEvent.hx index 24f618b4..99a2a806 100644 --- a/std/flash/events/AVStatusEvent.hx +++ b/std/flash/events/AVStatusEvent.hx @@ -1,25 +1,25 @@ package flash.events; extern class AVStatusEvent extends Event { - var description(default,null) : String; - var notificationType(default,null) : String; - var result(default,null) : flash.media.AVResult; + var description(default,never) : String; + var notificationType(default,never) : String; + var result(default,never) : flash.media.AVResult; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?inNotificationType : String, inResult : Int = 0, ?inDescription : String) : Void; - static var AV_STATUS : String; - static var BACKGROUND_MANIFEST_ERROR : String; - static var BACKGROUND_MANIFEST_WARNING : String; - static var BUFFER_STATE : String; - static var DECODER_TYPE : String; - static var DIMENSION_CHANGE : String; - static var ERROR : String; - static var INSERTION_COMPLETE : String; - static var LOAD_COMPLETE : String; - static var MANIFEST_UPDATE : String; - static var PLAY_STATE : String; - static var RENDER_TYPE : String; - static var SEEK_COMPLETE : String; - static var STEP_COMPLETE : String; - static var STREAM_SWITCH : String; - static var TRICKPLAY_ENDED : String; - static var WARNING : String; + static var AV_STATUS(default,never) : String; + static var BACKGROUND_MANIFEST_ERROR(default,never) : String; + static var BACKGROUND_MANIFEST_WARNING(default,never) : String; + static var BUFFER_STATE(default,never) : String; + static var DECODER_TYPE(default,never) : String; + static var DIMENSION_CHANGE(default,never) : String; + static var ERROR(default,never) : String; + static var INSERTION_COMPLETE(default,never) : String; + static var LOAD_COMPLETE(default,never) : String; + static var MANIFEST_UPDATE(default,never) : String; + static var PLAY_STATE(default,never) : String; + static var RENDER_TYPE(default,never) : String; + static var SEEK_COMPLETE(default,never) : String; + static var STEP_COMPLETE(default,never) : String; + static var STREAM_SWITCH(default,never) : String; + static var TRICKPLAY_ENDED(default,never) : String; + static var WARNING(default,never) : String; } diff --git a/std/flash/events/AVStreamSwitchEvent.hx b/std/flash/events/AVStreamSwitchEvent.hx index da837bb9..e216a7af 100644 --- a/std/flash/events/AVStreamSwitchEvent.hx +++ b/std/flash/events/AVStreamSwitchEvent.hx @@ -1,13 +1,13 @@ package flash.events; extern class AVStreamSwitchEvent extends Event { - var bitrate(default,null) : Int; - var description(default,null) : String; - var switchType(default,null) : Int; - var time(default,null) : Float; - var userData(default,null) : Int; + var bitrate(default,never) : Int; + var description(default,never) : String; + var switchType(default,never) : Int; + var time(default,never) : Float; + var userData(default,never) : Int; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, time : Float = 0, switchType : Int = 0, bitrate : Int = 0, ?description : String, userData : Int = 0) : Void; - static var ABR_SWITCH : Int; - static var AV_STREAM_SWITCH : String; - static var PERIOD_SWITCH : Int; + static var ABR_SWITCH(default,never) : Int; + static var AV_STREAM_SWITCH(default,never) : String; + static var PERIOD_SWITCH(default,never) : Int; } diff --git a/std/flash/events/AccelerometerEvent.hx b/std/flash/events/AccelerometerEvent.hx index 427a5af8..08997c6d 100644 --- a/std/flash/events/AccelerometerEvent.hx +++ b/std/flash/events/AccelerometerEvent.hx @@ -6,5 +6,5 @@ package flash.events; var accelerationZ : Float; var timestamp : Float; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, timestamp : Float = 0, accelerationX : Float = 0, accelerationY : Float = 0, accelerationZ : Float = 0) : Void; - static var UPDATE : String; + static var UPDATE(default,never) : String; } diff --git a/std/flash/events/ActivityEvent.hx b/std/flash/events/ActivityEvent.hx index 6298c475..c569a3da 100644 --- a/std/flash/events/ActivityEvent.hx +++ b/std/flash/events/ActivityEvent.hx @@ -3,5 +3,5 @@ package flash.events; extern class ActivityEvent extends Event { var activating : Bool; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, activating : Bool = false) : Void; - static var ACTIVITY : String; + static var ACTIVITY(default,never) : String; } diff --git a/std/flash/events/AsyncErrorEvent.hx b/std/flash/events/AsyncErrorEvent.hx index 26a397fa..00e8def8 100644 --- a/std/flash/events/AsyncErrorEvent.hx +++ b/std/flash/events/AsyncErrorEvent.hx @@ -3,5 +3,5 @@ package flash.events; extern class AsyncErrorEvent extends ErrorEvent { var error : flash.errors.Error; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?text : String, ?error : flash.errors.Error) : Void; - static var ASYNC_ERROR : String; + static var ASYNC_ERROR(default,never) : String; } diff --git a/std/flash/events/ContextMenuEvent.hx b/std/flash/events/ContextMenuEvent.hx index 4e23891e..35cc0959 100644 --- a/std/flash/events/ContextMenuEvent.hx +++ b/std/flash/events/ContextMenuEvent.hx @@ -5,6 +5,6 @@ extern class ContextMenuEvent extends Event { @:require(flash10) var isMouseTargetInaccessible : Bool; var mouseTarget : flash.display.InteractiveObject; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?mouseTarget : flash.display.InteractiveObject, ?contextMenuOwner : flash.display.InteractiveObject) : Void; - static var MENU_ITEM_SELECT : String; - static var MENU_SELECT : String; + static var MENU_ITEM_SELECT(default,never) : String; + static var MENU_SELECT(default,never) : String; } diff --git a/std/flash/events/DRMAuthenticateEvent.hx b/std/flash/events/DRMAuthenticateEvent.hx index 4146a1fe..02181ee5 100644 --- a/std/flash/events/DRMAuthenticateEvent.hx +++ b/std/flash/events/DRMAuthenticateEvent.hx @@ -1,14 +1,14 @@ package flash.events; @:require(flash10_1) extern class DRMAuthenticateEvent extends Event { - var authenticationType(default,null) : String; - var header(default,null) : String; - var netstream(default,null) : flash.net.NetStream; - var passwordPrompt(default,null) : String; - var urlPrompt(default,null) : String; - var usernamePrompt(default,null) : String; + var authenticationType(default,never) : String; + var header(default,never) : String; + var netstream(default,never) : flash.net.NetStream; + var passwordPrompt(default,never) : String; + var urlPrompt(default,never) : String; + var usernamePrompt(default,never) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?header : String, ?userPrompt : String, ?passPrompt : String, ?urlPrompt : String, ?authenticationType : String, ?netstream : flash.net.NetStream) : Void; - static var AUTHENTICATION_TYPE_DRM : String; - static var AUTHENTICATION_TYPE_PROXY : String; - static var DRM_AUTHENTICATE : String; + static var AUTHENTICATION_TYPE_DRM(default,never) : String; + static var AUTHENTICATION_TYPE_PROXY(default,never) : String; + static var DRM_AUTHENTICATE(default,never) : String; } diff --git a/std/flash/events/DRMAuthenticationCompleteEvent.hx b/std/flash/events/DRMAuthenticationCompleteEvent.hx index 020953a1..018b08a6 100644 --- a/std/flash/events/DRMAuthenticationCompleteEvent.hx +++ b/std/flash/events/DRMAuthenticationCompleteEvent.hx @@ -5,5 +5,5 @@ package flash.events; var serverURL : String; var token : flash.utils.ByteArray; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?inServerURL : String, ?inDomain : String, ?inToken : flash.utils.ByteArray) : Void; - static var AUTHENTICATION_COMPLETE : String; + static var AUTHENTICATION_COMPLETE(default,never) : String; } diff --git a/std/flash/events/DRMAuthenticationErrorEvent.hx b/std/flash/events/DRMAuthenticationErrorEvent.hx index 1ebd39ae..cfd134f6 100644 --- a/std/flash/events/DRMAuthenticationErrorEvent.hx +++ b/std/flash/events/DRMAuthenticationErrorEvent.hx @@ -5,5 +5,5 @@ package flash.events; var serverURL : String; var subErrorID : Int; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?inDetail : String, inErrorID : Int = 0, inSubErrorID : Int = 0, ?inServerURL : String, ?inDomain : String) : Void; - static var AUTHENTICATION_ERROR : String; + static var AUTHENTICATION_ERROR(default,never) : String; } diff --git a/std/flash/events/DRMDeviceGroupErrorEvent.hx b/std/flash/events/DRMDeviceGroupErrorEvent.hx index 3a3c0e38..982bf386 100644 --- a/std/flash/events/DRMDeviceGroupErrorEvent.hx +++ b/std/flash/events/DRMDeviceGroupErrorEvent.hx @@ -2,10 +2,10 @@ package flash.events; extern class DRMDeviceGroupErrorEvent extends ErrorEvent { var deviceGroup : flash.net.drm.DRMDeviceGroup; - var drmUpdateNeeded(default,null) : Bool; + var drmUpdateNeeded(default,never) : Bool; var subErrorID : Int; - var systemUpdateNeeded(default,null) : Bool; + var systemUpdateNeeded(default,never) : Bool; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?errorDetail : String, errorCode : Int = 0, subErrorID : Int = 0, ?deviceGroup : flash.net.drm.DRMDeviceGroup, systemUpdateNeeded : Bool = false, drmUpdateNeeded : Bool = false) : Void; - static var ADD_TO_DEVICE_GROUP_ERROR : String; - static var REMOVE_FROM_DEVICE_GROUP_ERROR : String; + static var ADD_TO_DEVICE_GROUP_ERROR(default,never) : String; + static var REMOVE_FROM_DEVICE_GROUP_ERROR(default,never) : String; } diff --git a/std/flash/events/DRMDeviceGroupEvent.hx b/std/flash/events/DRMDeviceGroupEvent.hx index 9149c102..57af6bd0 100644 --- a/std/flash/events/DRMDeviceGroupEvent.hx +++ b/std/flash/events/DRMDeviceGroupEvent.hx @@ -3,6 +3,6 @@ package flash.events; extern class DRMDeviceGroupEvent extends Event { var deviceGroup : flash.net.drm.DRMDeviceGroup; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?deviceGroup : flash.net.drm.DRMDeviceGroup) : Void; - static var ADD_TO_DEVICE_GROUP_COMPLETE : String; - static var REMOVE_FROM_DEVICE_GROUP_COMPLETE : String; + static var ADD_TO_DEVICE_GROUP_COMPLETE(default,never) : String; + static var REMOVE_FROM_DEVICE_GROUP_COMPLETE(default,never) : String; } diff --git a/std/flash/events/DRMErrorEvent.hx b/std/flash/events/DRMErrorEvent.hx index 75d4f28c..9e035fab 100644 --- a/std/flash/events/DRMErrorEvent.hx +++ b/std/flash/events/DRMErrorEvent.hx @@ -2,10 +2,10 @@ package flash.events; @:require(flash10_1) extern class DRMErrorEvent extends ErrorEvent { var contentData : flash.net.drm.DRMContentData; - var drmUpdateNeeded(default,null) : Bool; - var subErrorID(default,null) : Int; - var systemUpdateNeeded(default,null) : Bool; + var drmUpdateNeeded(default,never) : Bool; + var subErrorID(default,never) : Int; + var systemUpdateNeeded(default,never) : Bool; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?inErrorDetail : String, inErrorCode : Int = 0, insubErrorID : Int = 0, ?inMetadata : flash.net.drm.DRMContentData, inSystemUpdateNeeded : Bool = false, inDrmUpdateNeeded : Bool = false) : Void; - static var DRM_ERROR : String; - static var DRM_LOAD_DEVICEID_ERROR : String; + static var DRM_ERROR(default,never) : String; + static var DRM_LOAD_DEVICEID_ERROR(default,never) : String; } diff --git a/std/flash/events/DRMLicenseRequestEvent.hx b/std/flash/events/DRMLicenseRequestEvent.hx index db39bd6b..873f4b82 100644 --- a/std/flash/events/DRMLicenseRequestEvent.hx +++ b/std/flash/events/DRMLicenseRequestEvent.hx @@ -3,5 +3,5 @@ package flash.events; extern class DRMLicenseRequestEvent extends Event { var serverURL : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?inServerURL : String) : Void; - static var LICENSE_REQUEST : String; + static var LICENSE_REQUEST(default,never) : String; } diff --git a/std/flash/events/DRMMetadataEvent.hx b/std/flash/events/DRMMetadataEvent.hx index b585b964..4a4aebd0 100644 --- a/std/flash/events/DRMMetadataEvent.hx +++ b/std/flash/events/DRMMetadataEvent.hx @@ -1,8 +1,8 @@ package flash.events; extern class DRMMetadataEvent extends Event { - var drmMetadata(default,null) : flash.net.drm.DRMContentData; - var timestamp(default,null) : Float; + var drmMetadata(default,never) : flash.net.drm.DRMContentData; + var timestamp(default,never) : Float; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?inMetadata : flash.utils.ByteArray, inTimestamp : Float = 0) : Void; - static var DRM_METADATA : String; + static var DRM_METADATA(default,never) : String; } diff --git a/std/flash/events/DRMReturnVoucherCompleteEvent.hx b/std/flash/events/DRMReturnVoucherCompleteEvent.hx index 076f21c4..dbec165c 100644 --- a/std/flash/events/DRMReturnVoucherCompleteEvent.hx +++ b/std/flash/events/DRMReturnVoucherCompleteEvent.hx @@ -6,5 +6,5 @@ extern class DRMReturnVoucherCompleteEvent extends Event { var policyID : String; var serverURL : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?inServerURL : String, ?inLicenseID : String, ?inPolicyID : String, inNumberOfVouchersReturned : Int = 0) : Void; - static var RETURN_VOUCHER_COMPLETE : String; + static var RETURN_VOUCHER_COMPLETE(default,never) : String; } diff --git a/std/flash/events/DRMReturnVoucherErrorEvent.hx b/std/flash/events/DRMReturnVoucherErrorEvent.hx index 83b89115..568a31ad 100644 --- a/std/flash/events/DRMReturnVoucherErrorEvent.hx +++ b/std/flash/events/DRMReturnVoucherErrorEvent.hx @@ -6,5 +6,5 @@ extern class DRMReturnVoucherErrorEvent extends ErrorEvent { var serverURL : String; var subErrorID : Int; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?inDetail : String, inErrorID : Int = 0, inSubErrorID : Int = 0, ?inServerURL : String, ?inLicenseID : String, ?inPolicyID : String) : Void; - static var RETURN_VOUCHER_ERROR : String; + static var RETURN_VOUCHER_ERROR(default,never) : String; } diff --git a/std/flash/events/DRMStatusEvent.hx b/std/flash/events/DRMStatusEvent.hx index 78224797..ac71f0b5 100644 --- a/std/flash/events/DRMStatusEvent.hx +++ b/std/flash/events/DRMStatusEvent.hx @@ -5,5 +5,5 @@ package flash.events; var isLocal : Bool; var voucher : flash.net.drm.DRMVoucher; function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?inMetadata : flash.net.drm.DRMContentData, ?inVoucher : flash.net.drm.DRMVoucher, inLocal : Bool = false) : Void; - static var DRM_STATUS : String; + static var DRM_STATUS(default,never) : String; } diff --git a/std/flash/events/DataEvent.hx b/std/flash/events/DataEvent.hx index 1e478b6c..359146c4 100644 --- a/std/flash/events/DataEvent.hx +++ b/std/flash/events/DataEvent.hx @@ -3,6 +3,6 @@ package flash.events; extern class DataEvent extends TextEvent { var data : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?data : String) : Void; - static var DATA : String; - static var UPLOAD_COMPLETE_DATA : String; + static var DATA(default,never) : String; + static var UPLOAD_COMPLETE_DATA(default,never) : String; } diff --git a/std/flash/events/ErrorEvent.hx b/std/flash/events/ErrorEvent.hx index 97335b2e..1541236f 100644 --- a/std/flash/events/ErrorEvent.hx +++ b/std/flash/events/ErrorEvent.hx @@ -1,7 +1,7 @@ package flash.events; extern class ErrorEvent extends TextEvent { - @:require(flash10_1) var errorID(default,null) : Int; + @:require(flash10_1) var errorID(default,never) : Int; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?text : String, id : Int = 0) : Void; - static var ERROR : String; + static var ERROR(default,never) : String; } diff --git a/std/flash/events/Event.hx b/std/flash/events/Event.hx index af8180de..1406fbde 100644 --- a/std/flash/events/Event.hx +++ b/std/flash/events/Event.hx @@ -1,12 +1,12 @@ package flash.events; extern class Event { - var bubbles(default,null) : Bool; - var cancelable(default,null) : Bool; - var currentTarget(default,null) : Dynamic; - var eventPhase(default,null) : EventPhase; - var target(default,null) : Dynamic; - var type(default,null) : String; + var bubbles(default,never) : Bool; + var cancelable(default,never) : Bool; + var currentTarget(default,never) : Dynamic; + var eventPhase(default,never) : EventPhase; + var target(default,never) : Dynamic; + var type(default,never) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false) : Void; function clone() : Event; function formatToString(className : String, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : String; @@ -15,47 +15,47 @@ extern class Event { function stopImmediatePropagation() : Void; function stopPropagation() : Void; function toString() : String; - static var ACTIVATE : String; - static var ADDED : String; - static var ADDED_TO_STAGE : String; - @:require(flash15) static var BROWSER_ZOOM_CHANGE : String; - static var CANCEL : String; - static var CHANGE : String; - static var CHANNEL_MESSAGE : String; - static var CHANNEL_STATE : String; - @:require(flash10) static var CLEAR : String; - static var CLOSE : String; - static var COMPLETE : String; - static var CONNECT : String; - @:require(flash11) static var CONTEXT3D_CREATE : String; - @:require(flash10) static var COPY : String; - @:require(flash10) static var CUT : String; - static var DEACTIVATE : String; - static var ENTER_FRAME : String; - @:require(flash10) static var EXIT_FRAME : String; - @:require(flash10) static var FRAME_CONSTRUCTED : String; - @:require(flash11_3) static var FRAME_LABEL : String; - static var FULLSCREEN : String; - static var ID3 : String; - static var INIT : String; - static var MOUSE_LEAVE : String; - static var OPEN : String; - @:require(flash10) static var PASTE : String; - static var REMOVED : String; - static var REMOVED_FROM_STAGE : String; - static var RENDER : String; - static var RESIZE : String; - static var SCROLL : String; - static var SELECT : String; - @:require(flash10) static var SELECT_ALL : String; - static var SOUND_COMPLETE : String; - @:require(flash11_3) static var SUSPEND : String; - static var TAB_CHILDREN_CHANGE : String; - static var TAB_ENABLED_CHANGE : String; - static var TAB_INDEX_CHANGE : String; - @:require(flash11_3) static var TEXTURE_READY : String; - @:require(flash11) static var TEXT_INTERACTION_MODE_CHANGE : String; - static var UNLOAD : String; - static var VIDEO_FRAME : String; - static var WORKER_STATE : String; + static var ACTIVATE(default,never) : String; + static var ADDED(default,never) : String; + static var ADDED_TO_STAGE(default,never) : String; + static var BROWSER_ZOOM_CHANGE(default,never) : String; + static var CANCEL(default,never) : String; + static var CHANGE(default,never) : String; + static var CHANNEL_MESSAGE(default,never) : String; + static var CHANNEL_STATE(default,never) : String; + @:require(flash10) static var CLEAR(default,never) : String; + static var CLOSE(default,never) : String; + static var COMPLETE(default,never) : String; + static var CONNECT(default,never) : String; + @:require(flash11) static var CONTEXT3D_CREATE(default,never) : String; + @:require(flash10) static var COPY(default,never) : String; + @:require(flash10) static var CUT(default,never) : String; + static var DEACTIVATE(default,never) : String; + static var ENTER_FRAME(default,never) : String; + @:require(flash10) static var EXIT_FRAME(default,never) : String; + @:require(flash10) static var FRAME_CONSTRUCTED(default,never) : String; + @:require(flash11_3) static var FRAME_LABEL(default,never) : String; + static var FULLSCREEN(default,never) : String; + static var ID3(default,never) : String; + static var INIT(default,never) : String; + static var MOUSE_LEAVE(default,never) : String; + static var OPEN(default,never) : String; + @:require(flash10) static var PASTE(default,never) : String; + static var REMOVED(default,never) : String; + static var REMOVED_FROM_STAGE(default,never) : String; + static var RENDER(default,never) : String; + static var RESIZE(default,never) : String; + static var SCROLL(default,never) : String; + static var SELECT(default,never) : String; + @:require(flash10) static var SELECT_ALL(default,never) : String; + static var SOUND_COMPLETE(default,never) : String; + @:require(flash11_3) static var SUSPEND(default,never) : String; + static var TAB_CHILDREN_CHANGE(default,never) : String; + static var TAB_ENABLED_CHANGE(default,never) : String; + static var TAB_INDEX_CHANGE(default,never) : String; + @:require(flash11_3) static var TEXTURE_READY(default,never) : String; + @:require(flash11) static var TEXT_INTERACTION_MODE_CHANGE(default,never) : String; + static var UNLOAD(default,never) : String; + static var VIDEO_FRAME(default,never) : String; + static var WORKER_STATE(default,never) : String; } diff --git a/std/flash/events/FocusEvent.hx b/std/flash/events/FocusEvent.hx index 8d7691d9..1142f5ab 100644 --- a/std/flash/events/FocusEvent.hx +++ b/std/flash/events/FocusEvent.hx @@ -6,8 +6,8 @@ extern class FocusEvent extends Event { var relatedObject : flash.display.InteractiveObject; var shiftKey : Bool; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, ?relatedObject : flash.display.InteractiveObject, shiftKey : Bool = false, keyCode : UInt = 0) : Void; - static var FOCUS_IN : String; - static var FOCUS_OUT : String; - static var KEY_FOCUS_CHANGE : String; - static var MOUSE_FOCUS_CHANGE : String; + static var FOCUS_IN(default,never) : String; + static var FOCUS_OUT(default,never) : String; + static var KEY_FOCUS_CHANGE(default,never) : String; + static var MOUSE_FOCUS_CHANGE(default,never) : String; } diff --git a/std/flash/events/FullScreenEvent.hx b/std/flash/events/FullScreenEvent.hx index c4a6646d..bcb6e000 100644 --- a/std/flash/events/FullScreenEvent.hx +++ b/std/flash/events/FullScreenEvent.hx @@ -1,9 +1,9 @@ package flash.events; extern class FullScreenEvent extends ActivityEvent { - var fullScreen(default,null) : Bool; - @:require(flash11_3) var interactive(default,null) : Bool; + var fullScreen(default,never) : Bool; + @:require(flash11_3) var interactive(default,never) : Bool; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, fullScreen : Bool = false, interactive : Bool = false) : Void; - static var FULL_SCREEN : String; - @:require(flash11_3) static var FULL_SCREEN_INTERACTIVE_ACCEPTED : String; + static var FULL_SCREEN(default,never) : String; + @:require(flash11_3) static var FULL_SCREEN_INTERACTIVE_ACCEPTED(default,never) : String; } diff --git a/std/flash/events/GameInputEvent.hx b/std/flash/events/GameInputEvent.hx index ea5b84bc..7bcbb9a9 100644 --- a/std/flash/events/GameInputEvent.hx +++ b/std/flash/events/GameInputEvent.hx @@ -1,9 +1,9 @@ package flash.events; @:final @:require(flash11_8) extern class GameInputEvent extends Event { - var device(default,null) : flash.ui.GameInputDevice; + var device(default,never) : flash.ui.GameInputDevice; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?device : flash.ui.GameInputDevice) : Void; - static var DEVICE_ADDED : String; - static var DEVICE_REMOVED : String; - static var DEVICE_UNUSABLE : String; + static var DEVICE_ADDED(default,never) : String; + static var DEVICE_REMOVED(default,never) : String; + static var DEVICE_UNUSABLE(default,never) : String; } diff --git a/std/flash/events/GeolocationEvent.hx b/std/flash/events/GeolocationEvent.hx index dd4ba592..d6248acc 100644 --- a/std/flash/events/GeolocationEvent.hx +++ b/std/flash/events/GeolocationEvent.hx @@ -10,5 +10,5 @@ package flash.events; var timestamp : Float; var verticalAccuracy : Float; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, latitude : Float = 0, longitude : Float = 0, altitude : Float = 0, hAccuracy : Float = 0, vAccuracy : Float = 0, speed : Float = 0, heading : Float = 0, timestamp : Float = 0) : Void; - static var UPDATE : String; + static var UPDATE(default,never) : String; } diff --git a/std/flash/events/GestureEvent.hx b/std/flash/events/GestureEvent.hx index 845b3bd7..40e00285 100644 --- a/std/flash/events/GestureEvent.hx +++ b/std/flash/events/GestureEvent.hx @@ -7,9 +7,9 @@ package flash.events; var localY : Float; var phase : String; var shiftKey : Bool; - var stageX(default,null) : Float; - var stageY(default,null) : Float; + var stageX(default,never) : Float; + var stageY(default,never) : Float; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, ?phase : String, localX : Float = 0, localY : Float = 0, ctrlKey : Bool = false, altKey : Bool = false, shiftKey : Bool = false) : Void; function updateAfterEvent() : Void; - static var GESTURE_TWO_FINGER_TAP : String; + static var GESTURE_TWO_FINGER_TAP(default,never) : String; } diff --git a/std/flash/events/HTTPStatusEvent.hx b/std/flash/events/HTTPStatusEvent.hx index 25d2e4da..131b65cf 100644 --- a/std/flash/events/HTTPStatusEvent.hx +++ b/std/flash/events/HTTPStatusEvent.hx @@ -4,8 +4,8 @@ extern class HTTPStatusEvent extends Event { var redirected : Bool; @:require(flash10_1) var responseHeaders : Array; @:require(flash10_1) var responseURL : String; - var status(default,null) : Int; + var status(default,never) : Int; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, status : Int = 0, redirected : Bool = false) : Void; - @:require(flash10_1) static var HTTP_RESPONSE_STATUS : String; - static var HTTP_STATUS : String; + @:require(flash10_1) static var HTTP_RESPONSE_STATUS(default,never) : String; + static var HTTP_STATUS(default,never) : String; } diff --git a/std/flash/events/IMEEvent.hx b/std/flash/events/IMEEvent.hx index fe37fb8c..0553d585 100644 --- a/std/flash/events/IMEEvent.hx +++ b/std/flash/events/IMEEvent.hx @@ -3,6 +3,6 @@ package flash.events; extern class IMEEvent extends TextEvent { @:require(flash10_1) var imeClient : flash.text.ime.IIMEClient; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?text : String, ?imeClient : flash.text.ime.IIMEClient) : Void; - static var IME_COMPOSITION : String; - @:require(flash10_1) static var IME_START_COMPOSITION : String; + static var IME_COMPOSITION(default,never) : String; + @:require(flash10_1) static var IME_START_COMPOSITION(default,never) : String; } diff --git a/std/flash/events/IOErrorEvent.hx b/std/flash/events/IOErrorEvent.hx index a4fac09b..4b351378 100644 --- a/std/flash/events/IOErrorEvent.hx +++ b/std/flash/events/IOErrorEvent.hx @@ -2,8 +2,8 @@ package flash.events; extern class IOErrorEvent extends ErrorEvent { function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?text : String, id : Int = 0) : Void; - static var DISK_ERROR : String; - static var IO_ERROR : String; - static var NETWORK_ERROR : String; - static var VERIFY_ERROR : String; + static var DISK_ERROR(default,never) : String; + static var IO_ERROR(default,never) : String; + static var NETWORK_ERROR(default,never) : String; + static var VERIFY_ERROR(default,never) : String; } diff --git a/std/flash/events/KeyboardEvent.hx b/std/flash/events/KeyboardEvent.hx index e14199be..5e913d45 100644 --- a/std/flash/events/KeyboardEvent.hx +++ b/std/flash/events/KeyboardEvent.hx @@ -9,6 +9,6 @@ extern class KeyboardEvent extends Event { var shiftKey : Bool; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, charCodeValue : UInt = 0, keyCodeValue : UInt = 0, keyLocationValue : flash.ui.KeyLocation = 0, ctrlKeyValue : Bool = false, altKeyValue : Bool = false, shiftKeyValue : Bool = false) : Void; function updateAfterEvent() : Void; - static var KEY_DOWN : String; - static var KEY_UP : String; + static var KEY_DOWN(default,never) : String; + static var KEY_UP(default,never) : String; } diff --git a/std/flash/events/MouseEvent.hx b/std/flash/events/MouseEvent.hx index 96a0110d..c5b1d4c1 100644 --- a/std/flash/events/MouseEvent.hx +++ b/std/flash/events/MouseEvent.hx @@ -12,26 +12,26 @@ extern class MouseEvent extends Event { @:require(flash11_2) var movementY : Float; var relatedObject : flash.display.InteractiveObject; var shiftKey : Bool; - var stageX(default,null) : Float; - var stageY(default,null) : Float; - function new(type : String, bubbles : Bool = true, cancelable : Bool = false, ?localX : Float, ?localY : Float, ?relatedObject : flash.display.InteractiveObject, ctrlKey : Bool = false, altKey : Bool = false, shiftKey : Bool = false, buttonDown : Bool = false, delta : Int = 0) : Void; + var stageX(default,never) : Float; + var stageY(default,never) : Float; + function new(type : String, bubbles : Bool = true, cancelable : Bool = false, localX : Null = 0, localY : Null = 0, ?relatedObject : flash.display.InteractiveObject, ctrlKey : Bool = false, altKey : Bool = false, shiftKey : Bool = false, buttonDown : Bool = false, delta : Int = 0) : Void; function updateAfterEvent() : Void; - static var CLICK : String; - @:require(flash11_2) static var CONTEXT_MENU : String; - static var DOUBLE_CLICK : String; - @:require(flash11_2) static var MIDDLE_CLICK : String; - @:require(flash11_2) static var MIDDLE_MOUSE_DOWN : String; - @:require(flash11_2) static var MIDDLE_MOUSE_UP : String; - static var MOUSE_DOWN : String; - static var MOUSE_MOVE : String; - static var MOUSE_OUT : String; - static var MOUSE_OVER : String; - static var MOUSE_UP : String; - static var MOUSE_WHEEL : String; - @:require(flash11_3) static var RELEASE_OUTSIDE : String; - @:require(flash11_2) static var RIGHT_CLICK : String; - @:require(flash11_2) static var RIGHT_MOUSE_DOWN : String; - @:require(flash11_2) static var RIGHT_MOUSE_UP : String; - static var ROLL_OUT : String; - static var ROLL_OVER : String; + static var CLICK(default,never) : String; + @:require(flash11_2) static var CONTEXT_MENU(default,never) : String; + static var DOUBLE_CLICK(default,never) : String; + @:require(flash11_2) static var MIDDLE_CLICK(default,never) : String; + @:require(flash11_2) static var MIDDLE_MOUSE_DOWN(default,never) : String; + @:require(flash11_2) static var MIDDLE_MOUSE_UP(default,never) : String; + static var MOUSE_DOWN(default,never) : String; + static var MOUSE_MOVE(default,never) : String; + static var MOUSE_OUT(default,never) : String; + static var MOUSE_OVER(default,never) : String; + static var MOUSE_UP(default,never) : String; + static var MOUSE_WHEEL(default,never) : String; + @:require(flash11_3) static var RELEASE_OUTSIDE(default,never) : String; + @:require(flash11_2) static var RIGHT_CLICK(default,never) : String; + @:require(flash11_2) static var RIGHT_MOUSE_DOWN(default,never) : String; + @:require(flash11_2) static var RIGHT_MOUSE_UP(default,never) : String; + static var ROLL_OUT(default,never) : String; + static var ROLL_OVER(default,never) : String; } diff --git a/std/flash/events/NetDataEvent.hx b/std/flash/events/NetDataEvent.hx index 6a9201b5..8349d780 100644 --- a/std/flash/events/NetDataEvent.hx +++ b/std/flash/events/NetDataEvent.hx @@ -1,8 +1,8 @@ package flash.events; extern class NetDataEvent extends Event { - var info(default,null) : Dynamic; - var timestamp(default,null) : Float; + var info(default,never) : Dynamic; + var timestamp(default,never) : Float; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, timestamp : Float = 0, ?info : Dynamic) : Void; - static var MEDIA_TYPE_DATA : String; + static var MEDIA_TYPE_DATA(default,never) : String; } diff --git a/std/flash/events/NetMonitorEvent.hx b/std/flash/events/NetMonitorEvent.hx index 63876883..6c3b743d 100644 --- a/std/flash/events/NetMonitorEvent.hx +++ b/std/flash/events/NetMonitorEvent.hx @@ -1,7 +1,7 @@ package flash.events; extern class NetMonitorEvent extends Event { - var netStream(default,null) : flash.net.NetStream; + var netStream(default,never) : flash.net.NetStream; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?netStream : flash.net.NetStream) : Void; - static var NET_STREAM_CREATE : String; + static var NET_STREAM_CREATE(default,never) : String; } diff --git a/std/flash/events/NetStatusEvent.hx b/std/flash/events/NetStatusEvent.hx index c0e43a04..fe23b7bc 100644 --- a/std/flash/events/NetStatusEvent.hx +++ b/std/flash/events/NetStatusEvent.hx @@ -3,5 +3,5 @@ package flash.events; extern class NetStatusEvent extends Event { var info : Dynamic; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?info : Dynamic) : Void; - static var NET_STATUS : String; + static var NET_STATUS(default,never) : String; } diff --git a/std/flash/events/OutputProgressEvent.hx b/std/flash/events/OutputProgressEvent.hx index 79028438..501a67bf 100644 --- a/std/flash/events/OutputProgressEvent.hx +++ b/std/flash/events/OutputProgressEvent.hx @@ -4,5 +4,5 @@ extern class OutputProgressEvent extends Event { var bytesPending : Float; var bytesTotal : Float; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, bytesPending : Float = 0, bytesTotal : Float = 0) : Void; - static var OUTPUT_PROGRESS : String; + static var OUTPUT_PROGRESS(default,never) : String; } diff --git a/std/flash/events/PressAndTapGestureEvent.hx b/std/flash/events/PressAndTapGestureEvent.hx index 339d862d..6a65ab76 100644 --- a/std/flash/events/PressAndTapGestureEvent.hx +++ b/std/flash/events/PressAndTapGestureEvent.hx @@ -3,8 +3,8 @@ package flash.events; @:require(flash10_1) extern class PressAndTapGestureEvent extends GestureEvent { var tapLocalX : Float; var tapLocalY : Float; - var tapStageX(default,null) : Float; - var tapStageY(default,null) : Float; + var tapStageX(default,never) : Float; + var tapStageY(default,never) : Float; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, ?phase : String, localX : Float = 0, localY : Float = 0, tapLocalX : Float = 0, tapLocalY : Float = 0, ctrlKey : Bool = false, altKey : Bool = false, shiftKey : Bool = false) : Void; - static var GESTURE_PRESS_AND_TAP : String; + static var GESTURE_PRESS_AND_TAP(default,never) : String; } diff --git a/std/flash/events/ProgressEvent.hx b/std/flash/events/ProgressEvent.hx index 51f74df0..d49dc348 100644 --- a/std/flash/events/ProgressEvent.hx +++ b/std/flash/events/ProgressEvent.hx @@ -4,6 +4,6 @@ extern class ProgressEvent extends Event { var bytesLoaded : Float; var bytesTotal : Float; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, bytesLoaded : Float = 0, bytesTotal : Float = 0) : Void; - static var PROGRESS : String; - static var SOCKET_DATA : String; + static var PROGRESS(default,never) : String; + static var SOCKET_DATA(default,never) : String; } diff --git a/std/flash/events/SampleDataEvent.hx b/std/flash/events/SampleDataEvent.hx index dd7e7ffb..219332fb 100644 --- a/std/flash/events/SampleDataEvent.hx +++ b/std/flash/events/SampleDataEvent.hx @@ -4,5 +4,5 @@ extern class SampleDataEvent extends Event { var data : flash.utils.ByteArray; var position : Float; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, theposition : Float = 0, ?thedata : flash.utils.ByteArray) : Void; - static var SAMPLE_DATA : String; + static var SAMPLE_DATA(default,never) : String; } diff --git a/std/flash/events/SecurityErrorEvent.hx b/std/flash/events/SecurityErrorEvent.hx index 754af509..9d4e267f 100644 --- a/std/flash/events/SecurityErrorEvent.hx +++ b/std/flash/events/SecurityErrorEvent.hx @@ -2,5 +2,5 @@ package flash.events; extern class SecurityErrorEvent extends ErrorEvent { function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?text : String, id : Int = 0) : Void; - static var SECURITY_ERROR : String; + static var SECURITY_ERROR(default,never) : String; } diff --git a/std/flash/events/ShaderEvent.hx b/std/flash/events/ShaderEvent.hx index 589c990b..b7055cb6 100644 --- a/std/flash/events/ShaderEvent.hx +++ b/std/flash/events/ShaderEvent.hx @@ -5,5 +5,5 @@ extern class ShaderEvent extends Event { var byteArray : flash.utils.ByteArray; var vector : flash.Vector; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?bitmap : flash.display.BitmapData, ?array : flash.utils.ByteArray, ?vector : flash.Vector) : Void; - static var COMPLETE : String; + static var COMPLETE(default,never) : String; } diff --git a/std/flash/events/SoftKeyboardEvent.hx b/std/flash/events/SoftKeyboardEvent.hx index 7f393683..c1100893 100644 --- a/std/flash/events/SoftKeyboardEvent.hx +++ b/std/flash/events/SoftKeyboardEvent.hx @@ -2,9 +2,9 @@ package flash.events; extern class SoftKeyboardEvent extends Event { var relatedObject : flash.display.InteractiveObject; - var triggerType(default,null) : String; + var triggerType(default,never) : String; function new(type : String, bubbles : Bool, cancelable : Bool, relatedObjectVal : flash.display.InteractiveObject, triggerTypeVal : String) : Void; - static var SOFT_KEYBOARD_ACTIVATE : String; - static var SOFT_KEYBOARD_ACTIVATING : String; - static var SOFT_KEYBOARD_DEACTIVATE : String; + static var SOFT_KEYBOARD_ACTIVATE(default,never) : String; + static var SOFT_KEYBOARD_ACTIVATING(default,never) : String; + static var SOFT_KEYBOARD_DEACTIVATE(default,never) : String; } diff --git a/std/flash/events/SoftKeyboardTrigger.hx b/std/flash/events/SoftKeyboardTrigger.hx index ab656d14..1396ac37 100644 --- a/std/flash/events/SoftKeyboardTrigger.hx +++ b/std/flash/events/SoftKeyboardTrigger.hx @@ -2,6 +2,6 @@ package flash.events; extern class SoftKeyboardTrigger { function new() : Void; - static var CONTENT_TRIGGERED : String; - static var USER_TRIGGERED : String; + static var CONTENT_TRIGGERED(default,never) : String; + static var USER_TRIGGERED(default,never) : String; } diff --git a/std/flash/events/StageVideoAvailabilityEvent.hx b/std/flash/events/StageVideoAvailabilityEvent.hx index 03a65121..8a8c1680 100644 --- a/std/flash/events/StageVideoAvailabilityEvent.hx +++ b/std/flash/events/StageVideoAvailabilityEvent.hx @@ -1,9 +1,9 @@ package flash.events; extern class StageVideoAvailabilityEvent extends Event { - var availability(default,null) : String; - var driver : String; - var reason : String; + var availability(default,never) : String; + var driver(default,never) : String; + var reason(default,never) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?availability : String) : Void; - static var STAGE_VIDEO_AVAILABILITY : String; + static var STAGE_VIDEO_AVAILABILITY(default,never) : String; } diff --git a/std/flash/events/StageVideoEvent.hx b/std/flash/events/StageVideoEvent.hx index 4e0e95f0..8df13c91 100644 --- a/std/flash/events/StageVideoEvent.hx +++ b/std/flash/events/StageVideoEvent.hx @@ -1,12 +1,12 @@ package flash.events; @:require(flash10_2) extern class StageVideoEvent extends Event { - var codecInfo : String; - var colorSpace(default,null) : String; - var status(default,null) : String; + var codecInfo(default,never) : String; + var colorSpace(default,never) : String; + var status(default,never) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?status : String, ?colorSpace : String) : Void; - static var RENDER_STATE : String; - static var RENDER_STATUS_ACCELERATED : String; - static var RENDER_STATUS_SOFTWARE : String; - static var RENDER_STATUS_UNAVAILABLE : String; + static var RENDER_STATE(default,never) : String; + static var RENDER_STATUS_ACCELERATED(default,never) : String; + static var RENDER_STATUS_SOFTWARE(default,never) : String; + static var RENDER_STATUS_UNAVAILABLE(default,never) : String; } diff --git a/std/flash/events/StatusEvent.hx b/std/flash/events/StatusEvent.hx index fd98a5b3..fa06b595 100644 --- a/std/flash/events/StatusEvent.hx +++ b/std/flash/events/StatusEvent.hx @@ -4,5 +4,5 @@ extern class StatusEvent extends Event { var code : String; var level : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?code : String, ?level : String) : Void; - static var STATUS : String; + static var STATUS(default,never) : String; } diff --git a/std/flash/events/SyncEvent.hx b/std/flash/events/SyncEvent.hx index 501bfc85..c519ab9f 100644 --- a/std/flash/events/SyncEvent.hx +++ b/std/flash/events/SyncEvent.hx @@ -3,5 +3,5 @@ package flash.events; extern class SyncEvent extends Event { var changeList : Array; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?changeList : Array) : Void; - static var SYNC : String; + static var SYNC(default,never) : String; } diff --git a/std/flash/events/TextEvent.hx b/std/flash/events/TextEvent.hx index d5ca5a28..fbaa1e36 100644 --- a/std/flash/events/TextEvent.hx +++ b/std/flash/events/TextEvent.hx @@ -3,6 +3,6 @@ package flash.events; extern class TextEvent extends Event { var text : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?text : String) : Void; - static var LINK : String; - static var TEXT_INPUT : String; + static var LINK(default,never) : String; + static var TEXT_INPUT(default,never) : String; } diff --git a/std/flash/events/ThrottleEvent.hx b/std/flash/events/ThrottleEvent.hx index a277cb87..8cf89a37 100644 --- a/std/flash/events/ThrottleEvent.hx +++ b/std/flash/events/ThrottleEvent.hx @@ -1,8 +1,8 @@ package flash.events; @:require(flash11_2) extern class ThrottleEvent extends Event { - var state(default,null) : String; - var targetFrameRate(default,null) : Float; + var state(default,never) : String; + var targetFrameRate(default,never) : Float; function new(type : ThrottleType, bubbles : Bool = false, cancelable : Bool = false, ?state : String, targetFrameRate : Float = 0) : Void; - static var THROTTLE : String; + static var THROTTLE(default,never) : String; } diff --git a/std/flash/events/TimerEvent.hx b/std/flash/events/TimerEvent.hx index 83ea065e..3195b0fa 100644 --- a/std/flash/events/TimerEvent.hx +++ b/std/flash/events/TimerEvent.hx @@ -3,6 +3,6 @@ package flash.events; extern class TimerEvent extends Event { function new(type : String, bubbles : Bool = false, cancelable : Bool = false) : Void; function updateAfterEvent() : Void; - static var TIMER : String; - static var TIMER_COMPLETE : String; + static var TIMER(default,never) : String; + static var TIMER_COMPLETE(default,never) : String; } diff --git a/std/flash/events/TouchEvent.hx b/std/flash/events/TouchEvent.hx index 9f562271..3b164614 100644 --- a/std/flash/events/TouchEvent.hx +++ b/std/flash/events/TouchEvent.hx @@ -12,24 +12,24 @@ package flash.events; var shiftKey : Bool; var sizeX : Float; var sizeY : Float; - var stageX(default,null) : Float; - var stageY(default,null) : Float; + var stageX(default,never) : Float; + var stageY(default,never) : Float; var touchPointID : Int; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, touchPointID : Int = 0, isPrimaryTouchPoint : Bool = false, localX : Float = 0./*NaN*/, localY : Float = 0./*NaN*/, sizeX : Float = 0./*NaN*/, sizeY : Float = 0./*NaN*/, pressure : Float = 0./*NaN*/, ?relatedObject : flash.display.InteractiveObject, ctrlKey : Bool = false, altKey : Bool = false, shiftKey : Bool = false) : Void; function updateAfterEvent() : Void; - static var PROXIMITY_BEGIN : String; - static var PROXIMITY_END : String; - static var PROXIMITY_MOVE : String; - static var PROXIMITY_OUT : String; - static var PROXIMITY_OVER : String; - static var PROXIMITY_ROLL_OUT : String; - static var PROXIMITY_ROLL_OVER : String; - static var TOUCH_BEGIN : String; - static var TOUCH_END : String; - static var TOUCH_MOVE : String; - static var TOUCH_OUT : String; - static var TOUCH_OVER : String; - static var TOUCH_ROLL_OUT : String; - static var TOUCH_ROLL_OVER : String; - static var TOUCH_TAP : String; + static var PROXIMITY_BEGIN(default,never) : String; + static var PROXIMITY_END(default,never) : String; + static var PROXIMITY_MOVE(default,never) : String; + static var PROXIMITY_OUT(default,never) : String; + static var PROXIMITY_OVER(default,never) : String; + static var PROXIMITY_ROLL_OUT(default,never) : String; + static var PROXIMITY_ROLL_OVER(default,never) : String; + static var TOUCH_BEGIN(default,never) : String; + static var TOUCH_END(default,never) : String; + static var TOUCH_MOVE(default,never) : String; + static var TOUCH_OUT(default,never) : String; + static var TOUCH_OVER(default,never) : String; + static var TOUCH_ROLL_OUT(default,never) : String; + static var TOUCH_ROLL_OVER(default,never) : String; + static var TOUCH_TAP(default,never) : String; } diff --git a/std/flash/events/TransformGestureEvent.hx b/std/flash/events/TransformGestureEvent.hx index ff783a6e..1aaf5542 100644 --- a/std/flash/events/TransformGestureEvent.hx +++ b/std/flash/events/TransformGestureEvent.hx @@ -7,8 +7,8 @@ package flash.events; var scaleX : Float; var scaleY : Float; function new(type : String, bubbles : Bool = true, cancelable : Bool = false, ?phase : String, localX : Float = 0, localY : Float = 0, scaleX : Float = 1, scaleY : Float = 1, rotation : Float = 0, offsetX : Float = 0, offsetY : Float = 0, ctrlKey : Bool = false, altKey : Bool = false, shiftKey : Bool = false) : Void; - static var GESTURE_PAN : String; - static var GESTURE_ROTATE : String; - static var GESTURE_SWIPE : String; - static var GESTURE_ZOOM : String; + static var GESTURE_PAN(default,never) : String; + static var GESTURE_ROTATE(default,never) : String; + static var GESTURE_SWIPE(default,never) : String; + static var GESTURE_ZOOM(default,never) : String; } diff --git a/std/flash/events/UncaughtErrorEvent.hx b/std/flash/events/UncaughtErrorEvent.hx index f169f9c8..835d0928 100644 --- a/std/flash/events/UncaughtErrorEvent.hx +++ b/std/flash/events/UncaughtErrorEvent.hx @@ -1,7 +1,7 @@ package flash.events; @:require(flash10_1) extern class UncaughtErrorEvent extends ErrorEvent { - var error(default,null) : Dynamic; + var error(default,never) : Dynamic; function new(?type : String, bubbles : Bool = true, cancelable : Bool = true, ?error_in : Dynamic) : Void; - static var UNCAUGHT_ERROR : String; + static var UNCAUGHT_ERROR(default,never) : String; } diff --git a/std/flash/events/VideoEvent.hx b/std/flash/events/VideoEvent.hx index 45052bca..69b1d50a 100644 --- a/std/flash/events/VideoEvent.hx +++ b/std/flash/events/VideoEvent.hx @@ -1,11 +1,11 @@ package flash.events; @:require(flash10_2) extern class VideoEvent extends Event { - var codecInfo : String; - var status(default,null) : String; + var codecInfo(default,never) : String; + var status(default,never) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?status : String) : Void; - static var RENDER_STATE : String; - static var RENDER_STATUS_ACCELERATED : String; - static var RENDER_STATUS_SOFTWARE : String; - static var RENDER_STATUS_UNAVAILABLE : String; + static var RENDER_STATE(default,never) : String; + static var RENDER_STATUS_ACCELERATED(default,never) : String; + static var RENDER_STATUS_SOFTWARE(default,never) : String; + static var RENDER_STATUS_UNAVAILABLE(default,never) : String; } diff --git a/std/flash/events/VideoTextureEvent.hx b/std/flash/events/VideoTextureEvent.hx index 2a10f06d..c17657f8 100644 --- a/std/flash/events/VideoTextureEvent.hx +++ b/std/flash/events/VideoTextureEvent.hx @@ -1,9 +1,9 @@ package flash.events; extern class VideoTextureEvent extends Event { - var codecInfo : String; - var colorSpace(default,null) : String; - var status(default,null) : String; + var codecInfo(default,never) : String; + var colorSpace(default,never) : String; + var status(default,never) : String; function new(type : String, bubbles : Bool = false, cancelable : Bool = false, ?status : String, ?colorSpace : String) : Void; - static var RENDER_STATE : String; + static var RENDER_STATE(default,never) : String; } diff --git a/std/flash/external/ExternalInterface.hx b/std/flash/external/ExternalInterface.hx index cfc5cc72..052a7372 100644 --- a/std/flash/external/ExternalInterface.hx +++ b/std/flash/external/ExternalInterface.hx @@ -1,9 +1,9 @@ package flash.external; extern class ExternalInterface { - static var available(default,null) : Bool; + static var available(default,never) : Bool; static var marshallExceptions : Bool; - static var objectID(default,null) : String; + static var objectID(default,never) : String; static function addCallback(functionName : String, closure : Dynamic) : Void; static function call(functionName : String, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Dynamic; } diff --git a/std/flash/geom/Matrix3D.hx b/std/flash/geom/Matrix3D.hx index 5b974996..3f7bab6e 100644 --- a/std/flash/geom/Matrix3D.hx +++ b/std/flash/geom/Matrix3D.hx @@ -1,7 +1,7 @@ package flash.geom; @:require(flash10) extern class Matrix3D { - var determinant(default,null) : Float; + var determinant(default,never) : Float; var position : Vector3D; var rawData : flash.Vector; function new(?v : flash.Vector) : Void; diff --git a/std/flash/geom/Point.hx b/std/flash/geom/Point.hx index df42a68e..1396b7fe 100644 --- a/std/flash/geom/Point.hx +++ b/std/flash/geom/Point.hx @@ -1,7 +1,7 @@ package flash.geom; extern class Point { - var length(default,null) : Float; + var length(default,never) : Float; var x : Float; var y : Float; function new(x : Float = 0, y : Float = 0) : Void; diff --git a/std/flash/geom/Transform.hx b/std/flash/geom/Transform.hx index fd4d1660..13f3c440 100644 --- a/std/flash/geom/Transform.hx +++ b/std/flash/geom/Transform.hx @@ -2,12 +2,12 @@ package flash.geom; extern class Transform { var colorTransform : ColorTransform; - var concatenatedColorTransform(default,null) : ColorTransform; - var concatenatedMatrix(default,null) : Matrix; + var concatenatedColorTransform(default,never) : ColorTransform; + var concatenatedMatrix(default,never) : Matrix; var matrix : Matrix; @:require(flash10) var matrix3D : Matrix3D; @:require(flash10) var perspectiveProjection : PerspectiveProjection; - var pixelBounds(default,null) : Rectangle; + var pixelBounds(default,never) : Rectangle; function new(displayObject : flash.display.DisplayObject) : Void; @:require(flash10) function getRelativeMatrix3D(relativeTo : flash.display.DisplayObject) : Matrix3D; } diff --git a/std/flash/geom/Vector3D.hx b/std/flash/geom/Vector3D.hx index 89ec85c4..01a91ff5 100644 --- a/std/flash/geom/Vector3D.hx +++ b/std/flash/geom/Vector3D.hx @@ -1,8 +1,8 @@ package flash.geom; @:require(flash10) extern class Vector3D { - var length(default,null) : Float; - var lengthSquared(default,null) : Float; + var length(default,never) : Float; + var lengthSquared(default,never) : Float; var w : Float; var x : Float; var y : Float; @@ -24,9 +24,9 @@ package flash.geom; @:require(flash11) function setTo(xa : Float, ya : Float, za : Float) : Void; function subtract(a : Vector3D) : Vector3D; function toString() : String; - static var X_AXIS : Vector3D; - static var Y_AXIS : Vector3D; - static var Z_AXIS : Vector3D; + static var X_AXIS(default,never) : Vector3D; + static var Y_AXIS(default,never) : Vector3D; + static var Z_AXIS(default,never) : Vector3D; static function angleBetween(a : Vector3D, b : Vector3D) : Float; static function distance(pt1 : Vector3D, pt2 : Vector3D) : Float; } diff --git a/std/flash/globalization/Collator.hx b/std/flash/globalization/Collator.hx index 9d957200..de60b570 100644 --- a/std/flash/globalization/Collator.hx +++ b/std/flash/globalization/Collator.hx @@ -1,15 +1,15 @@ package flash.globalization; @:final @:require(flash10_1) extern class Collator { - var actualLocaleIDName(default,null) : String; + var actualLocaleIDName(default,never) : String; var ignoreCase : Bool; var ignoreCharacterWidth : Bool; var ignoreDiacritics : Bool; var ignoreKanaType : Bool; var ignoreSymbols : Bool; - var lastOperationStatus(default,null) : LastOperationStatus; + var lastOperationStatus(default,never) : LastOperationStatus; var numericComparison : Bool; - var requestedLocaleIDName(default,null) : String; + var requestedLocaleIDName(default,never) : String; function new(requestedLocaleIDName : String, ?initialMode : CollatorMode) : Void; function compare(string1 : String, string2 : String) : Int; function equals(string1 : String, string2 : String) : Bool; diff --git a/std/flash/globalization/CurrencyFormatter.hx b/std/flash/globalization/CurrencyFormatter.hx index c0cf91de..c19793ba 100644 --- a/std/flash/globalization/CurrencyFormatter.hx +++ b/std/flash/globalization/CurrencyFormatter.hx @@ -1,20 +1,20 @@ package flash.globalization; @:final @:require(flash10_1) extern class CurrencyFormatter { - var actualLocaleIDName(default,null) : String; - var currencyISOCode(default,null) : String; - var currencySymbol(default,null) : String; + var actualLocaleIDName(default,never) : String; + var currencyISOCode(default,never) : String; + var currencySymbol(default,never) : String; var decimalSeparator : String; var digitsType : UInt; var fractionalDigits : Int; var groupingPattern : String; var groupingSeparator : String; - var lastOperationStatus(default,null) : LastOperationStatus; + var lastOperationStatus(default,never) : LastOperationStatus; var leadingZero : Bool; var negativeCurrencyFormat : UInt; var negativeSymbol : String; var positiveCurrencyFormat : UInt; - var requestedLocaleIDName(default,null) : String; + var requestedLocaleIDName(default,never) : String; var trailingZeros : Bool; var useGrouping : Bool; function new(requestedLocaleIDName : String) : Void; diff --git a/std/flash/globalization/CurrencyParseResult.hx b/std/flash/globalization/CurrencyParseResult.hx index b376b22a..b26e7c8d 100644 --- a/std/flash/globalization/CurrencyParseResult.hx +++ b/std/flash/globalization/CurrencyParseResult.hx @@ -1,7 +1,7 @@ package flash.globalization; @:final extern class CurrencyParseResult { - var currencyString(default,null) : String; - var value(default,null) : Float; + var currencyString(default,never) : String; + var value(default,never) : Float; function new(value : Float = 0./*NaN*/, ?symbol : String) : Void; } diff --git a/std/flash/globalization/DateTimeFormatter.hx b/std/flash/globalization/DateTimeFormatter.hx index 0caf2d14..03b019cb 100644 --- a/std/flash/globalization/DateTimeFormatter.hx +++ b/std/flash/globalization/DateTimeFormatter.hx @@ -1,9 +1,9 @@ package flash.globalization; @:final @:require(flash10_1) extern class DateTimeFormatter { - var actualLocaleIDName(default,null) : String; - var lastOperationStatus(default,null) : LastOperationStatus; - var requestedLocaleIDName(default,null) : String; + var actualLocaleIDName(default,never) : String; + var lastOperationStatus(default,never) : LastOperationStatus; + var requestedLocaleIDName(default,never) : String; function new(requestedLocaleIDName : String, ?dateStyle : DateTimeStyle, ?timeStyle : DateTimeStyle) : Void; function format(dateTime : Date) : String; function formatUTC(dateTime : Date) : String; diff --git a/std/flash/globalization/LocaleID.hx b/std/flash/globalization/LocaleID.hx index b1a131b7..250840c5 100644 --- a/std/flash/globalization/LocaleID.hx +++ b/std/flash/globalization/LocaleID.hx @@ -1,8 +1,8 @@ package flash.globalization; @:final @:require(flash10_1) extern class LocaleID { - var lastOperationStatus(default,null) : LastOperationStatus; - var name(default,null) : String; + var lastOperationStatus(default,never) : LastOperationStatus; + var name(default,never) : String; function new(name : String) : Void; function getKeysAndValues() : flash.utils.Object; function getLanguage() : String; @@ -10,6 +10,6 @@ package flash.globalization; function getScript() : String; function getVariant() : String; function isRightToLeft() : Bool; - static var DEFAULT : String; + static var DEFAULT(default,never) : String; static function determinePreferredLocales(want : flash.Vector, have : flash.Vector, ?keyword : String) : flash.Vector; } diff --git a/std/flash/globalization/NumberFormatter.hx b/std/flash/globalization/NumberFormatter.hx index 6c01e02d..325edfc7 100644 --- a/std/flash/globalization/NumberFormatter.hx +++ b/std/flash/globalization/NumberFormatter.hx @@ -1,17 +1,17 @@ package flash.globalization; @:final @:require(flash10_1) extern class NumberFormatter { - var actualLocaleIDName(default,null) : String; + var actualLocaleIDName(default,never) : String; var decimalSeparator : String; var digitsType : NationalDigitsType; var fractionalDigits : Int; var groupingPattern : String; var groupingSeparator : String; - var lastOperationStatus(default,null) : LastOperationStatus; + var lastOperationStatus(default,never) : LastOperationStatus; var leadingZero : Bool; var negativeNumberFormat : UInt; var negativeSymbol : String; - var requestedLocaleIDName(default,null) : String; + var requestedLocaleIDName(default,never) : String; var trailingZeros : Bool; var useGrouping : Bool; function new(requestedLocaleIDName : String) : Void; diff --git a/std/flash/globalization/NumberParseResult.hx b/std/flash/globalization/NumberParseResult.hx index 426590e0..ab3484f6 100644 --- a/std/flash/globalization/NumberParseResult.hx +++ b/std/flash/globalization/NumberParseResult.hx @@ -1,8 +1,8 @@ package flash.globalization; @:final @:require(flash10_1) extern class NumberParseResult { - var endIndex(default,null) : Int; - var startIndex(default,null) : Int; - var value(default,null) : Float; + var endIndex(default,never) : Int; + var startIndex(default,never) : Int; + var value(default,never) : Float; function new(value : Float = 0./*NaN*/, startIndex : Int = 2147483647, endIndex : Int = 2147483647) : Void; } diff --git a/std/flash/globalization/StringTools.hx b/std/flash/globalization/StringTools.hx index 55c3f8f1..7dd7fce8 100644 --- a/std/flash/globalization/StringTools.hx +++ b/std/flash/globalization/StringTools.hx @@ -1,9 +1,9 @@ package flash.globalization; @:final @:require(flash10_1) extern class StringTools { - var actualLocaleIDName(default,null) : String; - var lastOperationStatus(default,null) : LastOperationStatus; - var requestedLocaleIDName(default,null) : String; + var actualLocaleIDName(default,never) : String; + var lastOperationStatus(default,never) : LastOperationStatus; + var requestedLocaleIDName(default,never) : String; function new(requestedLocaleIDName : String) : Void; function toLowerCase(s : String) : String; function toUpperCase(s : String) : String; diff --git a/std/flash/media/AVABRParameters.hx b/std/flash/media/AVABRParameters.hx index 5c694a33..fb6f2e72 100644 --- a/std/flash/media/AVABRParameters.hx +++ b/std/flash/media/AVABRParameters.hx @@ -6,7 +6,7 @@ extern class AVABRParameters { var policy : String; var startBitsPerSecond : Int; function new(init_policy : String, init_startBitsPerSecond : UInt, init_minBitsPerSecond : UInt, init_maxBitsPerSecond : UInt) : Void; - static var AGGRESSIVE : String; - static var CONSERVATIVE : String; - static var MODERATE : String; + static var AGGRESSIVE(default,never) : String; + static var CONSERVATIVE(default,never) : String; + static var MODERATE(default,never) : String; } diff --git a/std/flash/media/AVABRProfileInfo.hx b/std/flash/media/AVABRProfileInfo.hx index 90372068..990cc96b 100644 --- a/std/flash/media/AVABRProfileInfo.hx +++ b/std/flash/media/AVABRProfileInfo.hx @@ -1,8 +1,8 @@ package flash.media; extern class AVABRProfileInfo { - var bitsPerSecond(default,null) : Int; - var height(default,null) : Int; - var width(default,null) : Int; + var bitsPerSecond(default,never) : Int; + var height(default,never) : Int; + var width(default,never) : Int; function new(init_bitsPerSecond : Int, init_width : Int, init_height : Int) : Void; } diff --git a/std/flash/media/AVCaptionStyle.hx b/std/flash/media/AVCaptionStyle.hx index dd1603b3..21436f18 100644 --- a/std/flash/media/AVCaptionStyle.hx +++ b/std/flash/media/AVCaptionStyle.hx @@ -13,43 +13,43 @@ extern class AVCaptionStyle { var fontOpacity : String; var size : String; function new() : Void; - static var BLACK : String; - static var BLUE : String; - static var BRIGHT_BLUE : String; - static var BRIGHT_CYAN : String; - static var BRIGHT_GREEN : String; - static var BRIGHT_MAGENTA : String; - static var BRIGHT_RED : String; - static var BRIGHT_WHITE : String; - static var BRIGHT_YELLOW : String; - static var CASUAL : String; - static var CURSIVE : String; - static var CYAN : String; - static var DARK_BLUE : String; - static var DARK_CYAN : String; - static var DARK_GREEN : String; - static var DARK_MAGENTA : String; - static var DARK_RED : String; - static var DARK_YELLOW : String; - static var DEFAULT : String; - static var DEPRESSED : String; - static var GRAY : String; - static var GREEN : String; - static var LARGE : String; - static var LEFT_DROP_SHADOW : String; - static var MAGENTA : String; - static var MEDIUM : String; - static var MONOSPACED_WITHOUT_SERIFS : String; - static var MONOSPACE_WITH_SERIFS : String; - static var NONE : String; - static var PROPORTIONAL_WITHOUT_SERIFS : String; - static var PROPORTIONAL_WITH_SERIFS : String; - static var RAISED : String; - static var RED : String; - static var RIGHT_DROP_SHADOW : String; - static var SMALL : String; - static var SMALL_CAPITALS : String; - static var UNIFORM : String; - static var WHITE : String; - static var YELLOW : String; + static var BLACK(default,never) : String; + static var BLUE(default,never) : String; + static var BRIGHT_BLUE(default,never) : String; + static var BRIGHT_CYAN(default,never) : String; + static var BRIGHT_GREEN(default,never) : String; + static var BRIGHT_MAGENTA(default,never) : String; + static var BRIGHT_RED(default,never) : String; + static var BRIGHT_WHITE(default,never) : String; + static var BRIGHT_YELLOW(default,never) : String; + static var CASUAL(default,never) : String; + static var CURSIVE(default,never) : String; + static var CYAN(default,never) : String; + static var DARK_BLUE(default,never) : String; + static var DARK_CYAN(default,never) : String; + static var DARK_GREEN(default,never) : String; + static var DARK_MAGENTA(default,never) : String; + static var DARK_RED(default,never) : String; + static var DARK_YELLOW(default,never) : String; + static var DEFAULT(default,never) : String; + static var DEPRESSED(default,never) : String; + static var GRAY(default,never) : String; + static var GREEN(default,never) : String; + static var LARGE(default,never) : String; + static var LEFT_DROP_SHADOW(default,never) : String; + static var MAGENTA(default,never) : String; + static var MEDIUM(default,never) : String; + static var MONOSPACED_WITHOUT_SERIFS(default,never) : String; + static var MONOSPACE_WITH_SERIFS(default,never) : String; + static var NONE(default,never) : String; + static var PROPORTIONAL_WITHOUT_SERIFS(default,never) : String; + static var PROPORTIONAL_WITH_SERIFS(default,never) : String; + static var RAISED(default,never) : String; + static var RED(default,never) : String; + static var RIGHT_DROP_SHADOW(default,never) : String; + static var SMALL(default,never) : String; + static var SMALL_CAPITALS(default,never) : String; + static var UNIFORM(default,never) : String; + static var WHITE(default,never) : String; + static var YELLOW(default,never) : String; } diff --git a/std/flash/media/AVCuePoint.hx b/std/flash/media/AVCuePoint.hx index 732ef255..b8d7c852 100644 --- a/std/flash/media/AVCuePoint.hx +++ b/std/flash/media/AVCuePoint.hx @@ -1,7 +1,7 @@ package flash.media; extern class AVCuePoint { - var dictionary(default,null) : flash.utils.Dictionary; - var localTime(default,null) : Float; + var dictionary(default,never) : flash.utils.Dictionary; + var localTime(default,never) : Float; function new(init_dictionary : flash.utils.Dictionary, init_localTime : Float) : Void; } diff --git a/std/flash/media/AVInsertionResult.hx b/std/flash/media/AVInsertionResult.hx index c3790e63..b306a15b 100644 --- a/std/flash/media/AVInsertionResult.hx +++ b/std/flash/media/AVInsertionResult.hx @@ -1,7 +1,7 @@ package flash.media; extern class AVInsertionResult extends AVResult { - var insertedBeforeReadHead(default,null) : Bool; - var periodIndex(default,null) : Int; + var insertedBeforeReadHead(default,never) : Bool; + var periodIndex(default,never) : Int; function new(result : Int, periodIndex : Int, insertedBeforeReadHead : Bool) : Void; } diff --git a/std/flash/media/AVPeriodInfo.hx b/std/flash/media/AVPeriodInfo.hx index a5851039..91cde1a7 100644 --- a/std/flash/media/AVPeriodInfo.hx +++ b/std/flash/media/AVPeriodInfo.hx @@ -1,15 +1,15 @@ package flash.media; extern class AVPeriodInfo { - var duration(default,null) : Float; - var firstCuePointIndex(default,null) : Int; - var firstSubscribedTagIndex(default,null) : Int; - var lastCuePointIndex(default,null) : Int; - var lastSubscribedTagIndex(default,null) : Int; - var localStartTime(default,null) : Float; - var supportsTrickPlay(default,null) : Bool; - var targetDuration(default,null) : Float; - var userData(default,null) : Int; - var virtualStartTime(default,null) : Float; + var duration(default,never) : Float; + var firstCuePointIndex(default,never) : Int; + var firstSubscribedTagIndex(default,never) : Int; + var lastCuePointIndex(default,never) : Int; + var lastSubscribedTagIndex(default,never) : Int; + var localStartTime(default,never) : Float; + var supportsTrickPlay(default,never) : Bool; + var targetDuration(default,never) : Float; + var userData(default,never) : Int; + var virtualStartTime(default,never) : Float; function new(init_localStartTime : Float, init_virtualStartTime : Float, init_duration : Float, init_firstCuePointIndex : Int, init_lastCuePointIndex : Int, init_firstSubscribedTagIndex : Int, init_lastSubscribedTagIndex : Int, init_userData : Int, init_supportsTrickPlay : Bool, init_targetDuration : Float) : Void; } diff --git a/std/flash/media/AVPlayState.hx b/std/flash/media/AVPlayState.hx index 6b49c80f..2b610918 100644 --- a/std/flash/media/AVPlayState.hx +++ b/std/flash/media/AVPlayState.hx @@ -1,15 +1,15 @@ package flash.media; extern class AVPlayState { - var state(default,null) : Int; + var state(default,never) : Int; function new(state : UInt) : Void; - static var BUFFERING : Int; - static var EOF : Int; - static var PAUSED : Int; - static var PLAYING : Int; - static var READY : Int; - static var SUSPENDED : Int; - static var TRICK_PLAY : Int; - static var UNINITIALIZED : Int; - static var UNRECOVERABLE_ERROR : Int; + static var BUFFERING(default,never) : Int; + static var EOF(default,never) : Int; + static var PAUSED(default,never) : Int; + static var PLAYING(default,never) : Int; + static var READY(default,never) : Int; + static var SUSPENDED(default,never) : Int; + static var TRICK_PLAY(default,never) : Int; + static var UNINITIALIZED(default,never) : Int; + static var UNRECOVERABLE_ERROR(default,never) : Int; } diff --git a/std/flash/media/AVResult.hx b/std/flash/media/AVResult.hx index 245e4d3b..0fad410f 100644 --- a/std/flash/media/AVResult.hx +++ b/std/flash/media/AVResult.hx @@ -1,105 +1,107 @@ package flash.media; extern class AVResult { - var result(default,null) : Int; + var result(default,never) : Int; function new(inResult : Int) : Void; - static var ASYNC_OPERATION_IN_PROGRESS : Int; - static var AUDIO_ONLY_STREAM_END : Int; - static var AUDIO_ONLY_STREAM_START : Int; - static var AUDIO_START_ERROR : Int; - static var BAD_MANIFEST_SIGNATURE : Int; - static var BAD_MEDIASAMPLE_FOUND : Int; - static var BAD_MEDIA_INTERLEAVING : Int; - static var CALLED_FROM_WRONG_THREAD : Int; - static var CANNOT_ERASE_TIMELINE : Int; - static var CANNOT_FAIL_OVER : Int; - static var CANNOT_HANDLE_MAIN_MANIFEST_UPDATE : Int; - static var CANNOT_LOAD_PLAY_LIST : Int; - static var CANNOT_SPLIT_TIMELINE : Int; - static var CODEC_NOT_SUPPORTED : Int; - static var COMPONENT_CREATION_FAILURE : Int; - static var CONTAINER_NOT_SUPPORTED : Int; - static var CONTENT_LENGTH_MISMATCH : Int; - static var CRYPTO_ALGORITHM_NOT_SUPPORTED : Int; - static var CRYPTO_ERROR_BAD_CERTIFICATE : Int; - static var CRYPTO_ERROR_BAD_PARAMETER : Int; - static var CRYPTO_ERROR_BUFFER_TOO_SMALL : Int; - static var CRYPTO_ERROR_CORRUPTED_DATA : Int; - static var CRYPTO_ERROR_DIGEST_FINISH : Int; - static var CRYPTO_ERROR_DIGEST_UPDATE : Int; - static var CRYPTO_ERROR_UNKNOWN : Int; - static var CURRENT_PERIOD_EXPIRED : Int; - static var DECODER_FAILED : Int; - static var DEVICE_OPEN_ERROR : Int; - static var DID_NOT_GET_NEXT_FRAGMENT : Int; - static var DRM_INIT_ERROR : Int; - static var DRM_NOT_AVAILABLE : Int; - static var END_OF_PERIOD : Int; - static var EOF : Int; - static var FILE_NOT_FOUND : Int; - static var FILE_OPEN_ERROR : Int; - static var FILE_READ_ERROR : Int; - static var FILE_STRUCTURE_INVALID : Int; - static var FILE_WRITE_ERROR : Int; - static var FRAGMENT_READ_ERROR : Int; - static var GENERIC_ERROR : Int; - static var HTTP_TIME_OUT : Int; - static var ID3_PARSE_ERROR : Int; - static var INCOMPATIBLE_RENDER_MODE : Int; - static var INCOMPATIBLE_VERSION : Int; - static var INTERNAL_ERROR : Int; - static var INVALID_KEY : Int; - static var INVALID_OPERATION : Int; - static var INVALID_PARAMETER : Int; - static var INVALID_REPLACE_DURATION : Int; - static var INVALID_SEEK_TIME : Int; - static var INVALID_WITH_AUDIO_ONLY_FILE : Int; - static var IRRECOVERABLE_ERROR : Int; - static var KEY_NOT_FOUND : Int; - static var KEY_SERVER_NOT_FOUND : Int; - static var LISTENER_NOT_FOUND : Int; - static var LIVE_HOLD : Int; - static var LIVE_WINDOW_MOVED_BACKWARD : Int; - static var LOST_CONNECTION_RECOVERABLE : Int; - static var MANIFEST_FILE_UNEXPECTEDLY_CHANGED : Int; - static var NETWORK_DOWN : Int; - static var NETWORK_ERROR : Int; - static var NETWORK_UNAVAILABLE : Int; - static var NOT_IMPLEMENTED : Int; - static var NO_AUDIO_SINK : Int; - static var NO_FIXED_SIZE : Int; - static var NO_TIMELINE : Int; - static var NO_USEABLE_BITRATE_PROFILE : Int; - static var NULL_OPERATION : Int; - static var ONLY_ALLOWED_IN_PAUSED_STATE : Int; - static var OPERATION_ABORTED : Int; - static var OUT_OF_MEMORY : Int; - static var OVERFLOW : Int; - static var PARSE_ERROR : Int; - static var PARTIAL_REPLACEMENT : Int; - static var PERIOD_HOLD : Int; - static var PERIOD_NOT_LOADED : Int; - static var PLAYBACK_NOT_ENABLED : Int; - static var POSTROLL_WITH_LIVE_NOT_ALLOWED : Int; - static var PREVIOUS_STEP_SEEK_IN_PROGRESS : Int; - static var PROTOCOL_NOT_SUPPORTED : Int; - static var RANGE_ERROR : Int; - static var RANGE_SPANS_READHEAD : Int; - static var RENDITION_M3U8_ERROR : Int; - static var REPLACEMENT_FAILED : Int; - static var RESOURCE_NOT_SPECIFIED : Int; - static var SECURITY_ERROR : Int; - static var SEEK_FAILED : Int; - static var SEGMENT_SKIPPED_ON_FAILURE : Int; - static var SIZE_UNKNOWN : Int; - static var SPS_PPS_FOUND_OUTSIDE_AVCC : Int; - static var SUCCESS : Int; - static var SWITCH_TO_ASYMMETRIC_PROFILE : Int; - static var TIMELINE_TOO_SHORT : Int; - static var UNDERFLOW : Int; - static var UNSUPPORTED_CONFIGURATION : Int; - static var UNSUPPORTED_HLS_VERSION : Int; - static var UNSUPPORTED_OPERATION : Int; - static var VIDEO_PROFILE_NOT_SUPPORTED : Int; - static var WAITING_FOR_INIT : Int; + static var ASYNC_OPERATION_IN_PROGRESS(default,never) : Int; + static var AUDIO_ONLY_STREAM_END(default,never) : Int; + static var AUDIO_ONLY_STREAM_START(default,never) : Int; + static var AUDIO_START_ERROR(default,never) : Int; + static var BAD_MANIFEST_SIGNATURE(default,never) : Int; + static var BAD_MEDIASAMPLE_FOUND(default,never) : Int; + static var BAD_MEDIA_INTERLEAVING(default,never) : Int; + static var CALLED_FROM_WRONG_THREAD(default,never) : Int; + static var CANNOT_ERASE_TIMELINE(default,never) : Int; + static var CANNOT_FAIL_OVER(default,never) : Int; + static var CANNOT_HANDLE_MAIN_MANIFEST_UPDATE(default,never) : Int; + static var CANNOT_LOAD_PLAY_LIST(default,never) : Int; + static var CANNOT_SPLIT_TIMELINE(default,never) : Int; + static var CODEC_NOT_SUPPORTED(default,never) : Int; + static var COMPONENT_CREATION_FAILURE(default,never) : Int; + static var CONTAINER_NOT_SUPPORTED(default,never) : Int; + static var CONTENT_LENGTH_MISMATCH(default,never) : Int; + static var CRYPTO_ALGORITHM_NOT_SUPPORTED(default,never) : Int; + static var CRYPTO_ERROR_BAD_CERTIFICATE(default,never) : Int; + static var CRYPTO_ERROR_BAD_PARAMETER(default,never) : Int; + static var CRYPTO_ERROR_BUFFER_TOO_SMALL(default,never) : Int; + static var CRYPTO_ERROR_CORRUPTED_DATA(default,never) : Int; + static var CRYPTO_ERROR_DIGEST_FINISH(default,never) : Int; + static var CRYPTO_ERROR_DIGEST_UPDATE(default,never) : Int; + static var CRYPTO_ERROR_UNKNOWN(default,never) : Int; + static var CURRENT_PERIOD_EXPIRED(default,never) : Int; + static var DECODER_FAILED(default,never) : Int; + static var DEVICE_OPEN_ERROR(default,never) : Int; + static var DID_NOT_GET_NEXT_FRAGMENT(default,never) : Int; + static var DRM_INIT_ERROR(default,never) : Int; + static var DRM_NOT_AVAILABLE(default,never) : Int; + static var END_OF_PERIOD(default,never) : Int; + static var EOF(default,never) : Int; + static var FILE_NOT_FOUND(default,never) : Int; + static var FILE_OPEN_ERROR(default,never) : Int; + static var FILE_READ_ERROR(default,never) : Int; + static var FILE_STRUCTURE_INVALID(default,never) : Int; + static var FILE_WRITE_ERROR(default,never) : Int; + static var FRAGMENT_READ_ERROR(default,never) : Int; + static var GENERIC_ERROR(default,never) : Int; + static var HTTP_TIME_OUT(default,never) : Int; + static var ID3_PARSE_ERROR(default,never) : Int; + static var INCOMPATIBLE_RENDER_MODE(default,never) : Int; + static var INCOMPATIBLE_VERSION(default,never) : Int; + static var INTERNAL_ERROR(default,never) : Int; + static var INVALID_KEY(default,never) : Int; + static var INVALID_OPERATION(default,never) : Int; + static var INVALID_PARAMETER(default,never) : Int; + static var INVALID_REPLACE_DURATION(default,never) : Int; + static var INVALID_SEEK_TIME(default,never) : Int; + static var INVALID_WITH_AUDIO_ONLY_FILE(default,never) : Int; + static var IRRECOVERABLE_ERROR(default,never) : Int; + static var KEY_NOT_FOUND(default,never) : Int; + static var KEY_SERVER_NOT_FOUND(default,never) : Int; + static var LISTENER_NOT_FOUND(default,never) : Int; + static var LIVE_HOLD(default,never) : Int; + static var LIVE_WINDOW_MOVED_BACKWARD(default,never) : Int; + static var LOST_CONNECTION_RECOVERABLE(default,never) : Int; + static var MAIN_MANIFEST_UPDATE_TO_BE_HANDLED(default,never) : Int; + static var MANIFEST_FILE_UNEXPECTEDLY_CHANGED(default,never) : Int; + static var NETWORK_DOWN(default,never) : Int; + static var NETWORK_ERROR(default,never) : Int; + static var NETWORK_UNAVAILABLE(default,never) : Int; + static var NOT_IMPLEMENTED(default,never) : Int; + static var NO_AUDIO_SINK(default,never) : Int; + static var NO_FIXED_SIZE(default,never) : Int; + static var NO_TIMELINE(default,never) : Int; + static var NO_USEABLE_BITRATE_PROFILE(default,never) : Int; + static var NULL_OPERATION(default,never) : Int; + static var ONLY_ALLOWED_IN_PAUSED_STATE(default,never) : Int; + static var OPERATION_ABORTED(default,never) : Int; + static var OUT_OF_MEMORY(default,never) : Int; + static var OVERFLOW(default,never) : Int; + static var PARSE_ERROR(default,never) : Int; + static var PARTIAL_REPLACEMENT(default,never) : Int; + static var PERIOD_HOLD(default,never) : Int; + static var PERIOD_NOT_LOADED(default,never) : Int; + static var PLAYBACK_NOT_ENABLED(default,never) : Int; + static var POSTROLL_WITH_LIVE_NOT_ALLOWED(default,never) : Int; + static var PREVIOUS_STEP_SEEK_IN_PROGRESS(default,never) : Int; + static var PROTOCOL_NOT_SUPPORTED(default,never) : Int; + static var RANGE_ERROR(default,never) : Int; + static var RANGE_SPANS_READHEAD(default,never) : Int; + static var RENDITION_M3U8_ERROR(default,never) : Int; + static var REPLACEMENT_FAILED(default,never) : Int; + static var RESOURCE_NOT_SPECIFIED(default,never) : Int; + static var SECURITY_ERROR(default,never) : Int; + static var SEEK_FAILED(default,never) : Int; + static var SEGMENT_SKIPPED_ON_FAILURE(default,never) : Int; + static var SIZE_UNKNOWN(default,never) : Int; + static var SPS_PPS_FOUND_OUTSIDE_AVCC(default,never) : Int; + static var SUCCESS(default,never) : Int; + static var SWITCH_TO_ASYMMETRIC_PROFILE(default,never) : Int; + static var TIMELINE_TOO_SHORT(default,never) : Int; + static var UNDERFLOW(default,never) : Int; + static var UNREPORTED_TIME_DISCONTINUITY_FOUND(default,never) : Int; + static var UNSUPPORTED_CONFIGURATION(default,never) : Int; + static var UNSUPPORTED_HLS_VERSION(default,never) : Int; + static var UNSUPPORTED_OPERATION(default,never) : Int; + static var VIDEO_PROFILE_NOT_SUPPORTED(default,never) : Int; + static var WAITING_FOR_INIT(default,never) : Int; } diff --git a/std/flash/media/AVSegmentedSource.hx b/std/flash/media/AVSegmentedSource.hx index ab202aed..537775aa 100644 --- a/std/flash/media/AVSegmentedSource.hx +++ b/std/flash/media/AVSegmentedSource.hx @@ -1,11 +1,12 @@ package flash.media; extern class AVSegmentedSource extends AVSource { - var cookieHeader(null,default) : String; - var masterUpdateInterval(null,default) : Int; + var cookieHeader(never,default) : String; + var masterUpdateInterval(never,default) : Int; var networkingParams : AVNetworkingParams; - var useRedirectedUrl(null,default) : Bool; + var useRedirectedUrl(never,default) : Bool; function new() : Void; + function addCustomHeader(headerName : String, args : flash.Vector) : Void; function clearPauseAtPeriodEnd(periodIndex : Int) : AVResult; function getABRProfileCount(periodIndex : Int) : Int; function getABRProfileInfoAtIndex(periodIndex : Int, abrProfileIndex : Int) : AVABRProfileInfo; @@ -17,6 +18,8 @@ extern class AVSegmentedSource extends AVSource { function getSubscribedTag(periodIndex : Int, tagDataIndex : Int) : AVTagData; function getSubscribedTagForBackgroundManifest(periodIndex : Int, tagDataIndex : Int) : AVTagData; function getTimeline() : AVTimeline; + function getTimelineSubscribedTag(tagDataIndex : Int) : AVTagData; + function getTimelineSubscribedTagForBackgroundManifest(tagDataIndex : Int) : AVTagData; function getTrackCount(periodIndex : Int, payloadType : String) : Int; function getTrackInfo(periodIndex : Int, payloadType : String, trackIndex : Int) : AVTrackInfo; function insertByLocalTime(periodIndex : Int, insertionTime : Float, handle : Int, userData : Int = 0, replaceDuration : Float = 0) : AVInsertionResult; @@ -36,14 +39,14 @@ extern class AVSegmentedSource extends AVSource { function setPauseAtPeriodEnd(periodIndex : Int, userData : Int = 0) : AVResult; function setSubscribedTags(tagArray : Array) : AVResult; function setSubscribedTagsForBackgroundManifest(tagArray : Array) : AVResult; - static var AUDIO : String; - static var AUDIO_DESCRIPTION : String; - static var AUDIO_LANGUAGE : String; - static var AUDIO_PID : String; - static var DASH : String; - static var DATA : String; - static var DATA_DESCRIPTION : String; - static var HLS : String; - static var VIDEO : String; - static var VIDEO_DESCRIPTION : String; + static var AUDIO(default,never) : String; + static var AUDIO_DESCRIPTION(default,never) : String; + static var AUDIO_LANGUAGE(default,never) : String; + static var AUDIO_PID(default,never) : String; + static var DASH(default,never) : String; + static var DATA(default,never) : String; + static var DATA_DESCRIPTION(default,never) : String; + static var HLS(default,never) : String; + static var VIDEO(default,never) : String; + static var VIDEO_DESCRIPTION(default,never) : String; } diff --git a/std/flash/media/AVStream.hx b/std/flash/media/AVStream.hx index 56b4a60d..e98442ce 100644 --- a/std/flash/media/AVStream.hx +++ b/std/flash/media/AVStream.hx @@ -1,21 +1,21 @@ package flash.media; extern class AVStream extends flash.events.EventDispatcher { - var backBufferLength(default,null) : Float; - var backBufferTime(null,default) : Float; - var bufferLength(default,null) : Float; - var bufferTime(null,default) : Float; - var captionStyle(null,default) : AVCaptionStyle; + var backBufferLength(default,never) : Float; + var backBufferTime(never,default) : Float; + var bufferLength(default,never) : Float; + var bufferTime(never,default) : Float; + var captionStyle(never,default) : AVCaptionStyle; var captionsEnabled : Bool; - var clientLivePoint(default,null) : Float; - var currentFPS(default,null) : Float; - var decoderType(default,null) : String; - var droppedFrames(default,null) : Int; - var frameTime(default,null) : Float; - var initialBufferTime(null,default) : Float; - var playState(default,null) : AVPlayState; - var renderType(default,null) : String; - var time(default,null) : Float; + var clientLivePoint(default,never) : Float; + var currentFPS(default,never) : Float; + var decoderType(default,never) : String; + var droppedFrames(default,never) : Int; + var frameTime(default,never) : Float; + var initialBufferTime(never,default) : Float; + var playState(default,never) : AVPlayState; + var renderType(default,never) : String; + var time(default,never) : Float; var useHardwareDecoder : Bool; var volume : Float; function new(source : AVSource) : Void; @@ -31,7 +31,7 @@ extern class AVStream extends flash.events.EventDispatcher { function seekToLocalTime(periodIndex : Int, time : Float) : AVResult; function setPlaySpeed(speed : Float, reserved : Float) : Void; function step(frames : Int) : AVResult; - static var HARDWARE : String; - static var SOFTWARE : String; - static var UNDEFINED : String; + static var HARDWARE(default,never) : String; + static var SOFTWARE(default,never) : String; + static var UNDEFINED(default,never) : String; } diff --git a/std/flash/media/AVTagData.hx b/std/flash/media/AVTagData.hx index 5b469417..6f3d42b6 100644 --- a/std/flash/media/AVTagData.hx +++ b/std/flash/media/AVTagData.hx @@ -1,7 +1,7 @@ package flash.media; extern class AVTagData { - var data(default,null) : String; - var localTime(default,null) : Float; + var data(default,never) : String; + var localTime(default,never) : Float; function new(init_data : String, init_localTime : Float) : Void; } diff --git a/std/flash/media/AVTimeline.hx b/std/flash/media/AVTimeline.hx index 9497bc85..b5ebd161 100644 --- a/std/flash/media/AVTimeline.hx +++ b/std/flash/media/AVTimeline.hx @@ -1,11 +1,13 @@ package flash.media; extern class AVTimeline { - var complete(default,null) : Bool; - var firstPeriodIndex(default,null) : Int; - var lastPeriodIndex(default,null) : Int; - var type(default,null) : String; - var virtualDuration(default,null) : Float; - var virtualStartTime(default,null) : Float; - function new(init_type : String, init_virtualStartTime : Float, init_virtualDuration : Float, init_firstPeriodIndex : Int, init_lastPeriodIndex : Int, init_complete : Bool) : Void; + var complete(default,never) : Bool; + var firstPeriodIndex(default,never) : Int; + var firstSubscribedTagIndex(default,never) : Int; + var lastPeriodIndex(default,never) : Int; + var lastSubscribedTagIndex(default,never) : Int; + var type(default,never) : String; + var virtualDuration(default,never) : Float; + var virtualStartTime(default,never) : Float; + function new(init_type : String, init_virtualStartTime : Float, init_virtualDuration : Float, init_firstPeriodIndex : Int, init_lastPeriodIndex : Int, init_firstSubscribedIndex : Int, init_lastSubscribedIndex : Int, init_complete : Bool) : Void; } diff --git a/std/flash/media/AVTrackInfo.hx b/std/flash/media/AVTrackInfo.hx index b47eafdf..8ca3777a 100644 --- a/std/flash/media/AVTrackInfo.hx +++ b/std/flash/media/AVTrackInfo.hx @@ -1,16 +1,16 @@ package flash.media; extern class AVTrackInfo { - var activity(default,null) : Bool; - var autoSelect(default,null) : Bool; - var dataTrackInfoServiceType(default,null) : String; - var defaultTrack(default,null) : Bool; - var description(default,null) : String; - var forced(default,null) : Bool; - var language(default,null) : String; - var pid(default,null) : Int; + var activity(default,never) : Bool; + var autoSelect(default,never) : Bool; + var dataTrackInfoServiceType(default,never) : String; + var defaultTrack(default,never) : Bool; + var description(default,never) : String; + var forced(default,never) : Bool; + var language(default,never) : String; + var pid(default,never) : Int; function new(init_description : String, init_language : String, init_defaultTrack : Bool, init_autoSelect : Bool, init_forced : Bool, init_activity : Bool, init_dataTrackInfoServiceType : String, init_pid : Int) : Void; - static var DTI_608_CAPTIONS : String; - static var DTI_708_CAPTIONS : String; - static var DTI_WEBVTT_CAPTIONS : String; + static var DTI_608_CAPTIONS(default,never) : String; + static var DTI_708_CAPTIONS(default,never) : String; + static var DTI_WEBVTT_CAPTIONS(default,never) : String; } diff --git a/std/flash/media/AVURLLoader.hx b/std/flash/media/AVURLLoader.hx index f0e2ab75..05c4ca97 100644 --- a/std/flash/media/AVURLLoader.hx +++ b/std/flash/media/AVURLLoader.hx @@ -1,7 +1,7 @@ package flash.media; extern class AVURLLoader extends flash.net.URLLoader { - var cookieHeader(null,default) : String; + var cookieHeader(never,default) : String; var stream : AVURLStream; function new(?request : flash.net.URLRequest) : Void; } diff --git a/std/flash/media/AVURLStream.hx b/std/flash/media/AVURLStream.hx index c416d8c2..6e6ef8ff 100644 --- a/std/flash/media/AVURLStream.hx +++ b/std/flash/media/AVURLStream.hx @@ -1,6 +1,6 @@ package flash.media; extern class AVURLStream extends flash.net.URLStream { - var cookieHeader(null,default) : String; + var cookieHeader(never,default) : String; function new() : Void; } diff --git a/std/flash/media/AudioDecoder.hx b/std/flash/media/AudioDecoder.hx index bfea1a2b..a4fe5e95 100644 --- a/std/flash/media/AudioDecoder.hx +++ b/std/flash/media/AudioDecoder.hx @@ -2,10 +2,10 @@ package flash.media; extern class AudioDecoder { function new() : Void; - static var DOLBY_DIGITAL : String; - static var DOLBY_DIGITAL_PLUS : String; - static var DTS : String; - static var DTS_EXPRESS : String; - static var DTS_HD_HIGH_RESOLUTION_AUDIO : String; - static var DTS_HD_MASTER_AUDIO : String; + static var DOLBY_DIGITAL(default,never) : String; + static var DOLBY_DIGITAL_PLUS(default,never) : String; + static var DTS(default,never) : String; + static var DTS_EXPRESS(default,never) : String; + static var DTS_HD_HIGH_RESOLUTION_AUDIO(default,never) : String; + static var DTS_HD_MASTER_AUDIO(default,never) : String; } diff --git a/std/flash/media/Camera.hx b/std/flash/media/Camera.hx index e016c142..75f0ef79 100644 --- a/std/flash/media/Camera.hx +++ b/std/flash/media/Camera.hx @@ -1,21 +1,21 @@ package flash.media; @:final extern class Camera extends flash.events.EventDispatcher { - var activityLevel(default,null) : Float; - var bandwidth(default,null) : Int; - var currentFPS(default,null) : Float; - var fps(default,null) : Float; - var height(default,null) : Int; - var index(default,null) : Int; - var keyFrameInterval(default,null) : Int; - var loopback(default,null) : Bool; - var motionLevel(default,null) : Int; - var motionTimeout(default,null) : Int; - var muted(default,null) : Bool; - var name(default,null) : String; - @:require(flash11_2) var position(default,null) : String; - var quality(default,null) : Int; - var width(default,null) : Int; + var activityLevel(default,never) : Float; + var bandwidth(default,never) : Int; + var currentFPS(default,never) : Float; + var fps(default,never) : Float; + var height(default,never) : Int; + var index(default,never) : Int; + var keyFrameInterval(default,never) : Int; + var loopback(default,never) : Bool; + var motionLevel(default,never) : Int; + var motionTimeout(default,never) : Int; + var muted(default,never) : Bool; + var name(default,never) : String; + @:require(flash11_2) var position(default,never) : String; + var quality(default,never) : Int; + var width(default,never) : Int; function new() : Void; @:require(flash11_4) function copyToByteArray(rect : flash.geom.Rectangle, destination : flash.utils.ByteArray) : Void; @:require(flash11_4) function copyToVector(rect : flash.geom.Rectangle, destination : flash.Vector) : Void; @@ -26,8 +26,8 @@ package flash.media; function setMode(width : Int, height : Int, fps : Float, favorArea : Bool = true) : Void; function setMotionLevel(motionLevel : Int, timeout : Int = 2000) : Void; function setQuality(bandwidth : Int, quality : Int) : Void; - @:require(flash10_1) static var isSupported(default,null) : Bool; - static var names(default,null) : Array; + @:require(flash10_1) static var isSupported(default,never) : Bool; + static var names(default,never) : Array; @:require(flash10_1) static function _scanHardware() : Void; static function getCamera(?name : String) : Camera; } diff --git a/std/flash/media/H264Level.hx b/std/flash/media/H264Level.hx index 6581b5fd..02f62e1a 100644 --- a/std/flash/media/H264Level.hx +++ b/std/flash/media/H264Level.hx @@ -2,20 +2,20 @@ package flash.media; extern class H264Level { function new() : Void; - static var LEVEL_1 : String; - static var LEVEL_1B : String; - static var LEVEL_1_1 : String; - static var LEVEL_1_2 : String; - static var LEVEL_1_3 : String; - static var LEVEL_2 : String; - static var LEVEL_2_1 : String; - static var LEVEL_2_2 : String; - static var LEVEL_3 : String; - static var LEVEL_3_1 : String; - static var LEVEL_3_2 : String; - static var LEVEL_4 : String; - static var LEVEL_4_1 : String; - static var LEVEL_4_2 : String; - static var LEVEL_5 : String; - static var LEVEL_5_1 : String; + static var LEVEL_1(default,never) : String; + static var LEVEL_1B(default,never) : String; + static var LEVEL_1_1(default,never) : String; + static var LEVEL_1_2(default,never) : String; + static var LEVEL_1_3(default,never) : String; + static var LEVEL_2(default,never) : String; + static var LEVEL_2_1(default,never) : String; + static var LEVEL_2_2(default,never) : String; + static var LEVEL_3(default,never) : String; + static var LEVEL_3_1(default,never) : String; + static var LEVEL_3_2(default,never) : String; + static var LEVEL_4(default,never) : String; + static var LEVEL_4_1(default,never) : String; + static var LEVEL_4_2(default,never) : String; + static var LEVEL_5(default,never) : String; + static var LEVEL_5_1(default,never) : String; } diff --git a/std/flash/media/H264Profile.hx b/std/flash/media/H264Profile.hx index dc15ae4f..92ec2928 100644 --- a/std/flash/media/H264Profile.hx +++ b/std/flash/media/H264Profile.hx @@ -2,6 +2,6 @@ package flash.media; extern class H264Profile { function new() : Void; - static var BASELINE : String; - static var MAIN : String; + static var BASELINE(default,never) : String; + static var MAIN(default,never) : String; } diff --git a/std/flash/media/H264VideoStreamSettings.hx b/std/flash/media/H264VideoStreamSettings.hx index c49823d5..cc2c6e4e 100644 --- a/std/flash/media/H264VideoStreamSettings.hx +++ b/std/flash/media/H264VideoStreamSettings.hx @@ -1,8 +1,8 @@ package flash.media; extern class H264VideoStreamSettings extends VideoStreamSettings { - var level(default,null) : String; - var profile(default,null) : String; + var level(default,never) : String; + var profile(default,never) : String; function new() : Void; function setProfileLevel(profile : String, level : String) : Void; } diff --git a/std/flash/media/Microphone.hx b/std/flash/media/Microphone.hx index 3364b92c..f2daac99 100644 --- a/std/flash/media/Microphone.hx +++ b/std/flash/media/Microphone.hx @@ -1,28 +1,28 @@ package flash.media; @:final extern class Microphone extends flash.events.EventDispatcher { - var activityLevel(default,null) : Float; + var activityLevel(default,never) : Float; @:require(flash10) var codec : SoundCodec; @:require(flash10_1) var enableVAD : Bool; @:require(flash10) var encodeQuality : Int; @:require(flash10_2) var enhancedOptions : MicrophoneEnhancedOptions; @:require(flash10) var framesPerPacket : Int; var gain : Float; - var index(default,null) : Int; - var muted(default,null) : Bool; - var name(default,null) : String; + var index(default,never) : Int; + var muted(default,never) : Bool; + var name(default,never) : String; @:require(flash10_1) var noiseSuppressionLevel : Int; var rate : Int; - var silenceLevel(default,null) : Float; - var silenceTimeout(default,null) : Int; + var silenceLevel(default,never) : Float; + var silenceTimeout(default,never) : Int; var soundTransform : SoundTransform; - var useEchoSuppression(default,null) : Bool; + var useEchoSuppression(default,never) : Bool; function new() : Void; function setLoopBack(state : Bool = true) : Void; function setSilenceLevel(silenceLevel : Float, timeout : Int = -1) : Void; function setUseEchoSuppression(useEchoSuppression : Bool) : Void; - @:require(flash10_1) static var isSupported(default,null) : Bool; - static var names(default,null) : Array; + @:require(flash10_1) static var isSupported(default,never) : Bool; + static var names(default,never) : Array; @:require(flash10_2) static function getEnhancedMicrophone(index : Int = -1) : Microphone; static function getMicrophone(index : Int = -1) : Microphone; } diff --git a/std/flash/media/Sound.hx b/std/flash/media/Sound.hx index 6cfeaf88..6fda1e36 100644 --- a/std/flash/media/Sound.hx +++ b/std/flash/media/Sound.hx @@ -1,13 +1,13 @@ package flash.media; extern class Sound extends flash.events.EventDispatcher { - var bytesLoaded(default,null) : UInt; - var bytesTotal(default,null) : Int; - var id3(default,null) : ID3Info; - var isBuffering(default,null) : Bool; - @:require(flash10_1) var isURLInaccessible(default,null) : Bool; - var length(default,null) : Float; - var url(default,null) : String; + var bytesLoaded(default,never) : UInt; + var bytesTotal(default,never) : Int; + var id3(default,never) : ID3Info; + var isBuffering(default,never) : Bool; + @:require(flash10_1) var isURLInaccessible(default,never) : Bool; + var length(default,never) : Float; + var url(default,never) : String; function new(?stream : flash.net.URLRequest, ?context : SoundLoaderContext) : Void; function close() : Void; @:require(flash10) function extract(target : flash.utils.ByteArray, length : Float, startPosition : Float = -1) : Float; diff --git a/std/flash/media/SoundChannel.hx b/std/flash/media/SoundChannel.hx index 82d2cf42..adee7c79 100644 --- a/std/flash/media/SoundChannel.hx +++ b/std/flash/media/SoundChannel.hx @@ -1,9 +1,9 @@ package flash.media; @:final extern class SoundChannel extends flash.events.EventDispatcher { - var leftPeak(default,null) : Float; - var position(default,null) : Float; - var rightPeak(default,null) : Float; + var leftPeak(default,never) : Float; + var position(default,never) : Float; + var rightPeak(default,never) : Float; var soundTransform : SoundTransform; function new() : Void; function stop() : Void; diff --git a/std/flash/media/StageVideo.hx b/std/flash/media/StageVideo.hx index 3de0c786..39a716e5 100644 --- a/std/flash/media/StageVideo.hx +++ b/std/flash/media/StageVideo.hx @@ -1,11 +1,11 @@ package flash.media; @:require(flash10_2) extern class StageVideo extends flash.events.EventDispatcher { - var colorSpaces(default,null) : flash.Vector; + var colorSpaces(default,never) : flash.Vector; var depth : Int; var pan : flash.geom.Point; - var videoHeight(default,null) : Int; - var videoWidth(default,null) : Int; + var videoHeight(default,never) : Int; + var videoWidth(default,never) : Int; var viewPort : flash.geom.Rectangle; var zoom : flash.geom.Point; function new() : Void; diff --git a/std/flash/media/StageVideoAvailability.hx b/std/flash/media/StageVideoAvailability.hx index 9b0038da..88583b48 100644 --- a/std/flash/media/StageVideoAvailability.hx +++ b/std/flash/media/StageVideoAvailability.hx @@ -2,6 +2,6 @@ package flash.media; extern class StageVideoAvailability { function new() : Void; - static var AVAILABLE : String; - static var UNAVAILABLE : String; + static var AVAILABLE(default,never) : String; + static var UNAVAILABLE(default,never) : String; } diff --git a/std/flash/media/StageVideoAvailabilityReason.hx b/std/flash/media/StageVideoAvailabilityReason.hx index 20ef59e4..a09dfac3 100644 --- a/std/flash/media/StageVideoAvailabilityReason.hx +++ b/std/flash/media/StageVideoAvailabilityReason.hx @@ -2,9 +2,9 @@ package flash.media; extern class StageVideoAvailabilityReason { function new() : Void; - static var DRIVER_TOO_OLD : String; - static var NO_ERROR : String; - static var UNAVAILABLE : String; - static var USER_DISABLED : String; - static var WMODE_INCOMPATIBLE : String; + static var DRIVER_TOO_OLD(default,never) : String; + static var NO_ERROR(default,never) : String; + static var UNAVAILABLE(default,never) : String; + static var USER_DISABLED(default,never) : String; + static var WMODE_INCOMPATIBLE(default,never) : String; } diff --git a/std/flash/media/Video.hx b/std/flash/media/Video.hx index b2a08fe4..f8ac7596 100644 --- a/std/flash/media/Video.hx +++ b/std/flash/media/Video.hx @@ -3,8 +3,8 @@ package flash.media; extern class Video extends flash.display.DisplayObject { var deblocking : Int; var smoothing : Bool; - var videoHeight(default,null) : Int; - var videoWidth(default,null) : Int; + var videoHeight(default,never) : Int; + var videoWidth(default,never) : Int; function new(width : Int = 320, height : Int = 240) : Void; function attachCamera(camera : Camera) : Void; function attachNetStream(netStream : flash.net.NetStream) : Void; diff --git a/std/flash/media/VideoCodec.hx b/std/flash/media/VideoCodec.hx index 09200e1e..e18325f6 100644 --- a/std/flash/media/VideoCodec.hx +++ b/std/flash/media/VideoCodec.hx @@ -2,7 +2,7 @@ package flash.media; extern class VideoCodec { function new() : Void; - static var H264AVC : String; - static var SORENSON : String; - static var VP6 : String; + static var H264AVC(default,never) : String; + static var SORENSON(default,never) : String; + static var VP6(default,never) : String; } diff --git a/std/flash/media/VideoStatus.hx b/std/flash/media/VideoStatus.hx index 86cce3e0..0304da72 100644 --- a/std/flash/media/VideoStatus.hx +++ b/std/flash/media/VideoStatus.hx @@ -2,7 +2,7 @@ package flash.media; extern class VideoStatus { function new() : Void; - static var ACCELERATED : String; - static var SOFTWARE : String; - static var UNAVAILABLE : String; + static var ACCELERATED(default,never) : String; + static var SOFTWARE(default,never) : String; + static var UNAVAILABLE(default,never) : String; } diff --git a/std/flash/media/VideoStreamSettings.hx b/std/flash/media/VideoStreamSettings.hx index 6db4bb9c..305d8cc7 100644 --- a/std/flash/media/VideoStreamSettings.hx +++ b/std/flash/media/VideoStreamSettings.hx @@ -1,13 +1,13 @@ package flash.media; extern class VideoStreamSettings { - var bandwidth(default,null) : Int; - var codec(default,null) : String; - var fps(default,null) : Float; - var height(default,null) : Int; - var keyFrameInterval(default,null) : Int; - var quality(default,null) : Int; - var width(default,null) : Int; + var bandwidth(default,never) : Int; + var codec(default,never) : String; + var fps(default,never) : Float; + var height(default,never) : Int; + var keyFrameInterval(default,never) : Int; + var quality(default,never) : Int; + var width(default,never) : Int; function new() : Void; function setKeyFrameInterval(keyFrameInterval : Int) : Void; function setMode(width : Int, height : Int, fps : Float) : Void; diff --git a/std/flash/net/FileReference.hx b/std/flash/net/FileReference.hx index 698a698d..d86d601f 100644 --- a/std/flash/net/FileReference.hx +++ b/std/flash/net/FileReference.hx @@ -1,13 +1,13 @@ package flash.net; extern class FileReference extends flash.events.EventDispatcher { - var creationDate(default,null) : Date; - var creator(default,null) : String; - @:require(flash10) var data(default,null) : flash.utils.ByteArray; - var modificationDate(default,null) : Date; - var name(default,null) : String; - var size(default,null) : Float; - var type(default,null) : String; + var creationDate(default,never) : Date; + var creator(default,never) : String; + @:require(flash10) var data(default,never) : flash.utils.ByteArray; + var modificationDate(default,never) : Date; + var name(default,never) : String; + var size(default,never) : Float; + var type(default,never) : String; function new() : Void; function browse(?typeFilter : Array) : Bool; function cancel() : Void; diff --git a/std/flash/net/FileReferenceList.hx b/std/flash/net/FileReferenceList.hx index c96c3e9d..decb89dd 100644 --- a/std/flash/net/FileReferenceList.hx +++ b/std/flash/net/FileReferenceList.hx @@ -1,7 +1,7 @@ package flash.net; extern class FileReferenceList extends flash.events.EventDispatcher { - var fileList(default,null) : Array; + var fileList(default,never) : Array; function new() : Void; function browse(?typeFilter : Array) : Bool; } diff --git a/std/flash/net/GroupSpecifier.hx b/std/flash/net/GroupSpecifier.hx index ded161bb..c04e28a6 100644 --- a/std/flash/net/GroupSpecifier.hx +++ b/std/flash/net/GroupSpecifier.hx @@ -19,7 +19,7 @@ package flash.net; function setPostingPassword(?password : String, ?salt : String) : Void; function setPublishPassword(?password : String, ?salt : String) : Void; function toString() : String; - static var maxSupportedGroupspecVersion(default,null) : Int; + static var maxSupportedGroupspecVersion(default,never) : Int; static function encodeBootstrapPeerIDSpec(peerID : String) : String; static function encodeIPMulticastAddressSpec(address : String, ?port : Dynamic, ?source : String) : String; static function encodePostingAuthorization(password : String) : String; diff --git a/std/flash/net/LocalConnection.hx b/std/flash/net/LocalConnection.hx index 90e65f2d..5ba14b21 100644 --- a/std/flash/net/LocalConnection.hx +++ b/std/flash/net/LocalConnection.hx @@ -2,7 +2,7 @@ package flash.net; extern class LocalConnection extends flash.events.EventDispatcher { var client : Dynamic; - var domain(default,null) : String; + var domain(default,never) : String; @:require(flash10_1) var isPerUser : Bool; function new() : Void; function allowDomain(?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; @@ -10,5 +10,5 @@ extern class LocalConnection extends flash.events.EventDispatcher { function close() : Void; function connect(connectionName : String) : Void; function send(connectionName : String, methodName : String, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; - @:require(flash10_1) static var isSupported(default,null) : Bool; + @:require(flash10_1) static var isSupported(default,never) : Bool; } diff --git a/std/flash/net/NetConnection.hx b/std/flash/net/NetConnection.hx index 9a376557..a2acc221 100644 --- a/std/flash/net/NetConnection.hx +++ b/std/flash/net/NetConnection.hx @@ -2,19 +2,19 @@ package flash.net; extern class NetConnection extends flash.events.EventDispatcher { var client : Dynamic; - var connected(default,null) : Bool; - var connectedProxyType(default,null) : String; - @:require(flash10) var farID(default,null) : String; - @:require(flash10) var farNonce(default,null) : String; + var connected(default,never) : Bool; + var connectedProxyType(default,never) : String; + @:require(flash10) var farID(default,never) : String; + @:require(flash10) var farNonce(default,never) : String; @:require(flash10) var maxPeerConnections : UInt; - @:require(flash10) var nearID(default,null) : String; - @:require(flash10) var nearNonce(default,null) : String; + @:require(flash10) var nearID(default,never) : String; + @:require(flash10) var nearNonce(default,never) : String; var objectEncoding : UInt; - @:require(flash10) var protocol(default,null) : String; + @:require(flash10) var protocol(default,never) : String; var proxyType : String; - @:require(flash10) var unconnectedPeerStreams(default,null) : Array; - var uri(default,null) : String; - var usingTLS(default,null) : Bool; + @:require(flash10) var unconnectedPeerStreams(default,never) : Array; + var uri(default,never) : String; + var usingTLS(default,never) : Bool; function new() : Void; function addHeader(operation : String, mustUnderstand : Bool = false, ?param : flash.utils.Object) : Void; function call(command : String, responder : Responder, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; diff --git a/std/flash/net/NetGroup.hx b/std/flash/net/NetGroup.hx index a1a1bb31..542541ae 100644 --- a/std/flash/net/NetGroup.hx +++ b/std/flash/net/NetGroup.hx @@ -1,11 +1,11 @@ package flash.net; @:require(flash10_1) extern class NetGroup extends flash.events.EventDispatcher { - var estimatedMemberCount(default,null) : Float; - var info(default,null) : NetGroupInfo; - var localCoverageFrom(default,null) : String; - var localCoverageTo(default,null) : String; - var neighborCount(default,null) : Float; + var estimatedMemberCount(default,never) : Float; + var info(default,never) : NetGroupInfo; + var localCoverageFrom(default,never) : String; + var localCoverageTo(default,never) : String; + var neighborCount(default,never) : Float; var receiveMode : String; var replicationStrategy : String; function new(connection : NetConnection, groupspec : String) : Void; diff --git a/std/flash/net/NetGroupInfo.hx b/std/flash/net/NetGroupInfo.hx index a0b0dc53..3f569646 100644 --- a/std/flash/net/NetGroupInfo.hx +++ b/std/flash/net/NetGroupInfo.hx @@ -1,14 +1,14 @@ package flash.net; @:final @:require(flash10_1) extern class NetGroupInfo { - var objectReplicationReceiveBytesPerSecond(default,null) : Float; - var objectReplicationSendBytesPerSecond(default,null) : Float; - var postingReceiveControlBytesPerSecond(default,null) : Float; - var postingReceiveDataBytesPerSecond(default,null) : Float; - var postingSendControlBytesPerSecond(default,null) : Float; - var postingSendDataBytesPerSecond(default,null) : Float; - var routingReceiveBytesPerSecond(default,null) : Float; - var routingSendBytesPerSecond(default,null) : Float; + var objectReplicationReceiveBytesPerSecond(default,never) : Float; + var objectReplicationSendBytesPerSecond(default,never) : Float; + var postingReceiveControlBytesPerSecond(default,never) : Float; + var postingReceiveDataBytesPerSecond(default,never) : Float; + var postingSendControlBytesPerSecond(default,never) : Float; + var postingSendDataBytesPerSecond(default,never) : Float; + var routingReceiveBytesPerSecond(default,never) : Float; + var routingSendBytesPerSecond(default,never) : Float; function new(postingSendDataBytesPerSecond : Float, postingSendControlBytesPerSecond : Float, postingReceiveDataBytesPerSecond : Float, postingReceiveControlBytesPerSecond : Float, routingSendBytesPerSecond : Float, routingReceiveBytesPerSecond : Float, objectReplicationSendBytesPerSecond : Float, objectReplicationReceiveBytesPerSecond : Float) : Void; function toString() : String; } diff --git a/std/flash/net/NetGroupReceiveMode.hx b/std/flash/net/NetGroupReceiveMode.hx index 3a8b9bb0..00bdd9e7 100644 --- a/std/flash/net/NetGroupReceiveMode.hx +++ b/std/flash/net/NetGroupReceiveMode.hx @@ -2,6 +2,6 @@ package flash.net; extern class NetGroupReceiveMode { function new() : Void; - static var EXACT : String; - static var NEAREST : String; + static var EXACT(default,never) : String; + static var NEAREST(default,never) : String; } diff --git a/std/flash/net/NetGroupReplicationStrategy.hx b/std/flash/net/NetGroupReplicationStrategy.hx index 012c27c1..5c7e2bd7 100644 --- a/std/flash/net/NetGroupReplicationStrategy.hx +++ b/std/flash/net/NetGroupReplicationStrategy.hx @@ -2,6 +2,6 @@ package flash.net; extern class NetGroupReplicationStrategy { function new() : Void; - static var LOWEST_FIRST : String; - static var RAREST_FIRST : String; + static var LOWEST_FIRST(default,never) : String; + static var RAREST_FIRST(default,never) : String; } diff --git a/std/flash/net/NetGroupSendMode.hx b/std/flash/net/NetGroupSendMode.hx index ef20a556..79de5b70 100644 --- a/std/flash/net/NetGroupSendMode.hx +++ b/std/flash/net/NetGroupSendMode.hx @@ -2,6 +2,6 @@ package flash.net; extern class NetGroupSendMode { function new() : Void; - static var NEXT_DECREASING : String; - static var NEXT_INCREASING : String; + static var NEXT_DECREASING(default,never) : String; + static var NEXT_INCREASING(default,never) : String; } diff --git a/std/flash/net/NetGroupSendResult.hx b/std/flash/net/NetGroupSendResult.hx index 8f0903de..aa0122db 100644 --- a/std/flash/net/NetGroupSendResult.hx +++ b/std/flash/net/NetGroupSendResult.hx @@ -2,7 +2,7 @@ package flash.net; extern class NetGroupSendResult { function new() : Void; - static var ERROR : String; - static var NO_ROUTE : String; - static var SENT : String; + static var ERROR(default,never) : String; + static var NO_ROUTE(default,never) : String; + static var SENT(default,never) : String; } diff --git a/std/flash/net/NetStream.hx b/std/flash/net/NetStream.hx index 1b4e6250..8451653d 100644 --- a/std/flash/net/NetStream.hx +++ b/std/flash/net/NetStream.hx @@ -1,42 +1,42 @@ package flash.net; extern class NetStream extends flash.events.EventDispatcher { - var audioCodec(default,null) : UInt; + var audioCodec(default,never) : UInt; @:require(flash10_1) var audioReliable : Bool; @:require(flash10_1) var audioSampleAccess : Bool; - @:require(flash10_1) var backBufferLength(default,null) : Float; + @:require(flash10_1) var backBufferLength(default,never) : Float; @:require(flash10_1) var backBufferTime : Float; - var bufferLength(default,null) : Float; + var bufferLength(default,never) : Float; var bufferTime : Float; @:require(flash10_1) var bufferTimeMax : Float; - var bytesLoaded(default,null) : UInt; - var bytesTotal(default,null) : UInt; + var bytesLoaded(default,never) : UInt; + var bytesTotal(default,never) : UInt; var checkPolicyFile : Bool; var client : Dynamic; - var currentFPS(default,null) : Float; + var currentFPS(default,never) : Float; @:require(flash10_1) var dataReliable : Bool; - var decodedFrames(default,null) : UInt; - @:require(flash10) var farID(default,null) : String; - @:require(flash10) var farNonce(default,null) : String; + var decodedFrames(default,never) : UInt; + @:require(flash10) var farID(default,never) : String; + @:require(flash10) var farNonce(default,never) : String; @:require(flash10_1) var inBufferSeek : Bool; - @:require(flash10) var info(default,null) : NetStreamInfo; - var liveDelay(default,null) : Float; + @:require(flash10) var info(default,never) : NetStreamInfo; + var liveDelay(default,never) : Float; @:require(flash10) var maxPauseBufferTime : Float; @:require(flash10_1) var multicastAvailabilitySendToAll : Bool; @:require(flash10_1) var multicastAvailabilityUpdatePeriod : Float; @:require(flash10_1) var multicastFetchPeriod : Float; - @:require(flash10_1) var multicastInfo(default,null) : NetStreamMulticastInfo; + @:require(flash10_1) var multicastInfo(default,never) : NetStreamMulticastInfo; @:require(flash10_1) var multicastPushNeighborLimit : Float; @:require(flash10_1) var multicastRelayMarginDuration : Float; @:require(flash10_1) var multicastWindowDuration : Float; - @:require(flash10) var nearNonce(default,null) : String; - var objectEncoding(default,null) : UInt; - @:require(flash10) var peerStreams(default,null) : Array; + @:require(flash10) var nearNonce(default,never) : String; + var objectEncoding(default,never) : UInt; + @:require(flash10) var peerStreams(default,never) : Array; var soundTransform : flash.media.SoundTransform; - var time(default,null) : Float; + var time(default,never) : Float; @:require(flash11) var useHardwareDecoder : Bool; @:require(flash11_3) var useJitterBuffer : Bool; - var videoCodec(default,null) : UInt; + var videoCodec(default,never) : UInt; @:require(flash10_1) var videoReliable : Bool; @:require(flash10_1) var videoSampleAccess : Bool; @:require(flash11) var videoStreamSettings : flash.media.VideoStreamSettings; @@ -61,7 +61,7 @@ extern class NetStream extends flash.events.EventDispatcher { function send(handlerName : String, ?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; @:require(flash10_1) function step(frames : Int) : Void; function togglePause() : Void; - @:require(flash10) static var CONNECT_TO_FMS : String; - @:require(flash10) static var DIRECT_CONNECTIONS : String; + @:require(flash10) static var CONNECT_TO_FMS(default,never) : String; + @:require(flash10) static var DIRECT_CONNECTIONS(default,never) : String; static function resetDRMVouchers() : Void; } diff --git a/std/flash/net/NetStreamAppendBytesAction.hx b/std/flash/net/NetStreamAppendBytesAction.hx index c0292526..b7c7f8c9 100644 --- a/std/flash/net/NetStreamAppendBytesAction.hx +++ b/std/flash/net/NetStreamAppendBytesAction.hx @@ -2,7 +2,7 @@ package flash.net; extern class NetStreamAppendBytesAction { function new() : Void; - static var END_SEQUENCE : String; - static var RESET_BEGIN : String; - static var RESET_SEEK : String; + static var END_SEQUENCE(default,never) : String; + static var RESET_BEGIN(default,never) : String; + static var RESET_SEEK(default,never) : String; } diff --git a/std/flash/net/NetStreamInfo.hx b/std/flash/net/NetStreamInfo.hx index 0d34233c..b65ea776 100644 --- a/std/flash/net/NetStreamInfo.hx +++ b/std/flash/net/NetStreamInfo.hx @@ -1,31 +1,31 @@ package flash.net; @:final extern class NetStreamInfo { - var SRTT(default,null) : Float; - var audioBufferByteLength(default,null) : Float; - var audioBufferLength(default,null) : Float; - var audioByteCount(default,null) : Float; - var audioBytesPerSecond(default,null) : Float; - var audioLossRate(default,null) : Float; - var byteCount(default,null) : Float; - var currentBytesPerSecond(default,null) : Float; - var dataBufferByteLength(default,null) : Float; - var dataBufferLength(default,null) : Float; - var dataByteCount(default,null) : Float; - var dataBytesPerSecond(default,null) : Float; - var droppedFrames(default,null) : Float; - var isLive(default,null) : Bool; - var maxBytesPerSecond(default,null) : Float; - var metaData(default,null) : Dynamic; - var playbackBytesPerSecond(default,null) : Float; - var resourceName(default,null) : String; - var uri(default,null) : String; - var videoBufferByteLength(default,null) : Float; - var videoBufferLength(default,null) : Float; - var videoByteCount(default,null) : Float; - var videoBytesPerSecond(default,null) : Float; - @:require(flash10_1) var videoLossRate(default,null) : Float; - var xmpData(default,null) : Dynamic; + var SRTT(default,never) : Float; + var audioBufferByteLength(default,never) : Float; + var audioBufferLength(default,never) : Float; + var audioByteCount(default,never) : Float; + var audioBytesPerSecond(default,never) : Float; + var audioLossRate(default,never) : Float; + var byteCount(default,never) : Float; + var currentBytesPerSecond(default,never) : Float; + var dataBufferByteLength(default,never) : Float; + var dataBufferLength(default,never) : Float; + var dataByteCount(default,never) : Float; + var dataBytesPerSecond(default,never) : Float; + var droppedFrames(default,never) : Float; + var isLive(default,never) : Bool; + var maxBytesPerSecond(default,never) : Float; + var metaData(default,never) : Dynamic; + var playbackBytesPerSecond(default,never) : Float; + var resourceName(default,never) : String; + var uri(default,never) : String; + var videoBufferByteLength(default,never) : Float; + var videoBufferLength(default,never) : Float; + var videoByteCount(default,never) : Float; + var videoBytesPerSecond(default,never) : Float; + @:require(flash10_1) var videoLossRate(default,never) : Float; + var xmpData(default,never) : Dynamic; function new(curBPS : Float, byteCount : Float, maxBPS : Float, audioBPS : Float, audioByteCount : Float, videoBPS : Float, videoByteCount : Float, dataBPS : Float, dataByteCount : Float, playbackBPS : Float, droppedFrames : Float, audioBufferByteLength : Float, videoBufferByteLength : Float, dataBufferByteLength : Float, audioBufferLength : Float, videoBufferLength : Float, dataBufferLength : Float, srtt : Float, audioLossRate : Float, videoLossRate : Float, ?metaData : Dynamic, ?xmpData : Dynamic, ?uri : String, ?resourceName : String, isLive : Bool = true) : Void; function toString() : String; } diff --git a/std/flash/net/NetStreamMulticastInfo.hx b/std/flash/net/NetStreamMulticastInfo.hx index ebc8cecd..c86a04df 100644 --- a/std/flash/net/NetStreamMulticastInfo.hx +++ b/std/flash/net/NetStreamMulticastInfo.hx @@ -1,25 +1,25 @@ package flash.net; @:final @:require(flash10_1) extern class NetStreamMulticastInfo { - var bytesPushedFromPeers(default,null) : Float; - var bytesPushedToPeers(default,null) : Float; - var bytesReceivedFromIPMulticast(default,null) : Float; - var bytesReceivedFromServer(default,null) : Float; - var bytesRequestedByPeers(default,null) : Float; - var bytesRequestedFromPeers(default,null) : Float; - var fragmentsPushedFromPeers(default,null) : Float; - var fragmentsPushedToPeers(default,null) : Float; - var fragmentsReceivedFromIPMulticast(default,null) : Float; - var fragmentsReceivedFromServer(default,null) : Float; - var fragmentsRequestedByPeers(default,null) : Float; - var fragmentsRequestedFromPeers(default,null) : Float; - var receiveControlBytesPerSecond(default,null) : Float; - var receiveDataBytesPerSecond(default,null) : Float; - var receiveDataBytesPerSecondFromIPMulticast(default,null) : Float; - var receiveDataBytesPerSecondFromServer(default,null) : Float; - var sendControlBytesPerSecond(default,null) : Float; - var sendControlBytesPerSecondToServer(default,null) : Float; - var sendDataBytesPerSecond(default,null) : Float; + var bytesPushedFromPeers(default,never) : Float; + var bytesPushedToPeers(default,never) : Float; + var bytesReceivedFromIPMulticast(default,never) : Float; + var bytesReceivedFromServer(default,never) : Float; + var bytesRequestedByPeers(default,never) : Float; + var bytesRequestedFromPeers(default,never) : Float; + var fragmentsPushedFromPeers(default,never) : Float; + var fragmentsPushedToPeers(default,never) : Float; + var fragmentsReceivedFromIPMulticast(default,never) : Float; + var fragmentsReceivedFromServer(default,never) : Float; + var fragmentsRequestedByPeers(default,never) : Float; + var fragmentsRequestedFromPeers(default,never) : Float; + var receiveControlBytesPerSecond(default,never) : Float; + var receiveDataBytesPerSecond(default,never) : Float; + var receiveDataBytesPerSecondFromIPMulticast(default,never) : Float; + var receiveDataBytesPerSecondFromServer(default,never) : Float; + var sendControlBytesPerSecond(default,never) : Float; + var sendControlBytesPerSecondToServer(default,never) : Float; + var sendDataBytesPerSecond(default,never) : Float; function new(sendDataBytesPerSecond : Float, sendControlBytesPerSecond : Float, receiveDataBytesPerSecond : Float, receiveControlBytesPerSecond : Float, bytesPushedToPeers : Float, fragmentsPushedToPeers : Float, bytesRequestedByPeers : Float, fragmentsRequestedByPeers : Float, bytesPushedFromPeers : Float, fragmentsPushedFromPeers : Float, bytesRequestedFromPeers : Float, fragmentsRequestedFromPeers : Float, sendControlBytesPerSecondToServer : Float, receiveDataBytesPerSecondFromServer : Float, bytesReceivedFromServer : Float, fragmentsReceivedFromServer : Float, receiveDataBytesPerSecondFromIPMulticast : Float, bytesReceivedFromIPMulticast : Float, fragmentsReceivedFromIPMulticast : Float) : Void; function toString() : String; } diff --git a/std/flash/net/ObjectEncoding.hx b/std/flash/net/ObjectEncoding.hx index e01c559c..0b7b9f14 100644 --- a/std/flash/net/ObjectEncoding.hx +++ b/std/flash/net/ObjectEncoding.hx @@ -1,8 +1,8 @@ package flash.net; extern class ObjectEncoding { - static var AMF0 : UInt; - static var AMF3 : UInt; - static var DEFAULT : UInt; + static var AMF0(default,never) : UInt; + static var AMF3(default,never) : UInt; + static var DEFAULT(default,never) : UInt; static var dynamicPropertyWriter : IDynamicPropertyWriter; } diff --git a/std/flash/net/SecureSocket.hx b/std/flash/net/SecureSocket.hx index be064bcc..a895d58e 100644 --- a/std/flash/net/SecureSocket.hx +++ b/std/flash/net/SecureSocket.hx @@ -1,9 +1,9 @@ package flash.net; @:require(flash11) extern class SecureSocket extends Socket { - var serverCertificate(default,null) : flash.security.X509Certificate; - var serverCertificateStatus(default,null) : String; + var serverCertificate(default,never) : flash.security.X509Certificate; + var serverCertificateStatus(default,never) : String; function new() : Void; function addBinaryChainBuildingCertificate(certificate : flash.utils.ByteArray, trusted : Bool) : Void; - static var isSupported(default,null) : Bool; + static var isSupported(default,never) : Bool; } diff --git a/std/flash/net/SharedObject.hx b/std/flash/net/SharedObject.hx index e29bb655..267eb4fb 100644 --- a/std/flash/net/SharedObject.hx +++ b/std/flash/net/SharedObject.hx @@ -2,10 +2,10 @@ package flash.net; extern class SharedObject extends flash.events.EventDispatcher { var client : Dynamic; - var data(default,null) : Dynamic; - var fps(null,default) : Float; + var data(default,never) : Dynamic; + var fps(never,default) : Float; var objectEncoding : UInt; - var size(default,null) : UInt; + var size(default,never) : UInt; function new() : Void; function clear() : Void; function close() : Void; diff --git a/std/flash/net/SharedObjectFlushStatus.hx b/std/flash/net/SharedObjectFlushStatus.hx index 1c64d810..505c2da0 100644 --- a/std/flash/net/SharedObjectFlushStatus.hx +++ b/std/flash/net/SharedObjectFlushStatus.hx @@ -2,6 +2,6 @@ package flash.net; extern class SharedObjectFlushStatus { function new() : Void; - static var FLUSHED : String; - static var PENDING : String; + static var FLUSHED(default,never) : String; + static var PENDING(default,never) : String; } diff --git a/std/flash/net/Socket.hx b/std/flash/net/Socket.hx index 852f563a..d8dfd147 100644 --- a/std/flash/net/Socket.hx +++ b/std/flash/net/Socket.hx @@ -1,9 +1,9 @@ package flash.net; extern class Socket extends flash.events.EventDispatcher implements flash.utils.IDataOutput implements flash.utils.IDataInput { - var bytesAvailable(default,null) : UInt; - @:require(flash11) var bytesPending(default,null) : UInt; - var connected(default,null) : Bool; + var bytesAvailable(default,never) : UInt; + @:require(flash11) var bytesPending(default,never) : UInt; + var connected(default,never) : Bool; var endian : flash.utils.Endian; var objectEncoding : UInt; @:require(flash10) var timeout : UInt; diff --git a/std/flash/net/URLRequestMethod.hx b/std/flash/net/URLRequestMethod.hx index 0032a84d..7e00873f 100644 --- a/std/flash/net/URLRequestMethod.hx +++ b/std/flash/net/URLRequestMethod.hx @@ -1,10 +1,10 @@ package flash.net; extern class URLRequestMethod { - @:require(flash10_1) static var DELETE : String; - static var GET : String; - @:require(flash10_1) static var HEAD : String; - @:require(flash10_1) static var OPTIONS : String; - static var POST : String; - @:require(flash10_1) static var PUT : String; + @:require(flash10_1) static var DELETE(default,never) : String; + static var GET(default,never) : String; + @:require(flash10_1) static var HEAD(default,never) : String; + @:require(flash10_1) static var OPTIONS(default,never) : String; + static var POST(default,never) : String; + @:require(flash10_1) static var PUT(default,never) : String; } diff --git a/std/flash/net/URLStream.hx b/std/flash/net/URLStream.hx index 5f0b02f3..2cb4cf41 100644 --- a/std/flash/net/URLStream.hx +++ b/std/flash/net/URLStream.hx @@ -1,11 +1,11 @@ package flash.net; extern class URLStream extends flash.events.EventDispatcher implements flash.utils.IDataInput { - var bytesAvailable(default,null) : UInt; - var connected(default,null) : Bool; - @:require(flash11_4) var diskCacheEnabled(default,null) : Bool; + var bytesAvailable(default,never) : UInt; + var connected(default,never) : Bool; + @:require(flash11_4) var diskCacheEnabled(default,never) : Bool; var endian : flash.utils.Endian; - @:require(flash11_4) var length(default,null) : Float; + @:require(flash11_4) var length(default,never) : Float; var objectEncoding : UInt; @:require(flash11_4) var position : Float; function new() : Void; diff --git a/std/flash/net/XMLSocket.hx b/std/flash/net/XMLSocket.hx index 39779e12..b8e787ef 100644 --- a/std/flash/net/XMLSocket.hx +++ b/std/flash/net/XMLSocket.hx @@ -1,7 +1,7 @@ package flash.net; extern class XMLSocket extends flash.events.EventDispatcher { - var connected(default,null) : Bool; + var connected(default,never) : Bool; @:require(flash10) var timeout : Int; function new(?host : String, port : Int = 0) : Void; function close() : Void; diff --git a/std/flash/net/drm/AddToDeviceGroupSetting.hx b/std/flash/net/drm/AddToDeviceGroupSetting.hx index 156edf1e..89739329 100644 --- a/std/flash/net/drm/AddToDeviceGroupSetting.hx +++ b/std/flash/net/drm/AddToDeviceGroupSetting.hx @@ -2,7 +2,7 @@ package flash.net.drm; extern class AddToDeviceGroupSetting { function new() : Void; - static var ALLOW_SERVER : String; - static var FORCE_REFRESH : String; - static var LOCAL_ONLY : String; + static var ALLOW_SERVER(default,never) : String; + static var FORCE_REFRESH(default,never) : String; + static var LOCAL_ONLY(default,never) : String; } diff --git a/std/flash/net/drm/AuthenticationMethod.hx b/std/flash/net/drm/AuthenticationMethod.hx index fcc01a11..44b4afe5 100644 --- a/std/flash/net/drm/AuthenticationMethod.hx +++ b/std/flash/net/drm/AuthenticationMethod.hx @@ -2,6 +2,6 @@ package flash.net.drm; extern class AuthenticationMethod { function new() : Void; - static var ANONYMOUS : String; - static var USERNAME_AND_PASSWORD : String; + static var ANONYMOUS(default,never) : String; + static var USERNAME_AND_PASSWORD(default,never) : String; } diff --git a/std/flash/net/drm/DRMAuthenticationContext.hx b/std/flash/net/drm/DRMAuthenticationContext.hx index 3655f7ee..c2206589 100644 --- a/std/flash/net/drm/DRMAuthenticationContext.hx +++ b/std/flash/net/drm/DRMAuthenticationContext.hx @@ -1,7 +1,7 @@ package flash.net.drm; extern class DRMAuthenticationContext extends DRMManagerSession { - var authenticationToken(default,null) : flash.utils.ByteArray; + var authenticationToken(default,never) : flash.utils.ByteArray; function new() : Void; function authenticate(url : String, domain : String, username : String, password : String) : Void; } diff --git a/std/flash/net/drm/DRMContentData.hx b/std/flash/net/drm/DRMContentData.hx index dbe2e761..5b5487ca 100644 --- a/std/flash/net/drm/DRMContentData.hx +++ b/std/flash/net/drm/DRMContentData.hx @@ -1,10 +1,10 @@ package flash.net.drm; extern class DRMContentData { - var authenticationMethod(default,null) : String; - var domain(default,null) : String; - var licenseID(default,null) : String; - var serverURL(default,null) : String; + var authenticationMethod(default,never) : String; + var domain(default,never) : String; + var licenseID(default,never) : String; + var serverURL(default,never) : String; function new(?rawData : flash.utils.ByteArray) : Void; function getVoucherAccessInfo() : flash.Vector; } diff --git a/std/flash/net/drm/DRMDeviceGroup.hx b/std/flash/net/drm/DRMDeviceGroup.hx index fb2784f6..7ede90f9 100644 --- a/std/flash/net/drm/DRMDeviceGroup.hx +++ b/std/flash/net/drm/DRMDeviceGroup.hx @@ -1,9 +1,9 @@ package flash.net.drm; @:final extern class DRMDeviceGroup { - var authenticationMethod(default,null) : String; - var domain(default,null) : String; + var authenticationMethod(default,never) : String; + var domain(default,never) : String; var name : String; - var serverURL(default,null) : String; + var serverURL(default,never) : String; function new() : Void; } diff --git a/std/flash/net/drm/DRMManager.hx b/std/flash/net/drm/DRMManager.hx index e21977b6..6e857657 100644 --- a/std/flash/net/drm/DRMManager.hx +++ b/std/flash/net/drm/DRMManager.hx @@ -12,7 +12,7 @@ extern class DRMManager extends flash.events.EventDispatcher { function returnVoucher(inServerURL : String, immediateCommit : Bool, licenseID : String, policyID : String) : Void; function setAuthenticationToken(serverUrl : String, domain : String, token : flash.utils.ByteArray) : Void; function storeVoucher(voucher : flash.utils.ByteArray) : Void; - static var isSupported(default,null) : Bool; + static var isSupported(default,never) : Bool; static var networkIdleTimeout : Float; static function getDRMManager() : DRMManager; static function getDRMManagerInternal() : DRMManager; diff --git a/std/flash/net/drm/DRMManagerSession.hx b/std/flash/net/drm/DRMManagerSession.hx index e8cb8b29..be1f4222 100644 --- a/std/flash/net/drm/DRMManagerSession.hx +++ b/std/flash/net/drm/DRMManagerSession.hx @@ -14,8 +14,8 @@ extern class DRMManagerSession extends flash.events.EventDispatcher { function onSessionComplete() : Void; function onSessionError() : Void; function setTimerUp() : Void; - static var STATUS_FAILED : UInt; - static var STATUS_NOTREADY : UInt; - static var STATUS_READY : UInt; - static var STATUS_UNKNOWN : UInt; + static var STATUS_FAILED(default,never) : UInt; + static var STATUS_NOTREADY(default,never) : UInt; + static var STATUS_READY(default,never) : UInt; + static var STATUS_UNKNOWN(default,never) : UInt; } diff --git a/std/flash/net/drm/DRMPlaybackTimeWindow.hx b/std/flash/net/drm/DRMPlaybackTimeWindow.hx index f4eb2c57..7014bd2e 100644 --- a/std/flash/net/drm/DRMPlaybackTimeWindow.hx +++ b/std/flash/net/drm/DRMPlaybackTimeWindow.hx @@ -1,8 +1,8 @@ package flash.net.drm; extern class DRMPlaybackTimeWindow { - var endDate(default,null) : Date; - var period(default,null) : UInt; - var startDate(default,null) : Date; + var endDate(default,never) : Date; + var period(default,never) : UInt; + var startDate(default,never) : Date; function new() : Void; } diff --git a/std/flash/net/drm/DRMStoreVoucherContext.hx b/std/flash/net/drm/DRMStoreVoucherContext.hx new file mode 100644 index 00000000..5a182247 --- /dev/null +++ b/std/flash/net/drm/DRMStoreVoucherContext.hx @@ -0,0 +1,6 @@ +package flash.net.drm; + +extern class DRMStoreVoucherContext extends DRMManagerSession { + function new(voucher : flash.utils.ByteArray) : Void; + function doStoreVoucher() : Void; +} diff --git a/std/flash/net/drm/DRMVoucher.hx b/std/flash/net/drm/DRMVoucher.hx index 809f83cb..71051044 100644 --- a/std/flash/net/drm/DRMVoucher.hx +++ b/std/flash/net/drm/DRMVoucher.hx @@ -1,15 +1,15 @@ package flash.net.drm; extern class DRMVoucher { - var licenseID(default,null) : String; - var offlineLeaseEndDate(default,null) : Date; - var offlineLeaseStartDate(default,null) : Date; - var playbackTimeWindow(default,null) : DRMPlaybackTimeWindow; - var policies(default,null) : Dynamic; - var policyID(default,null) : String; - var serverURL(default,null) : String; - var voucherEndDate(default,null) : Date; - var voucherStartDate(default,null) : Date; + var licenseID(default,never) : String; + var offlineLeaseEndDate(default,never) : Date; + var offlineLeaseStartDate(default,never) : Date; + var playbackTimeWindow(default,never) : DRMPlaybackTimeWindow; + var policies(default,never) : Dynamic; + var policyID(default,never) : String; + var serverURL(default,never) : String; + var voucherEndDate(default,never) : Date; + var voucherStartDate(default,never) : Date; function new() : Void; function toByteArray() : flash.utils.ByteArray; } diff --git a/std/flash/net/drm/DRMVoucherDownloadContext.hx b/std/flash/net/drm/DRMVoucherDownloadContext.hx index 74757052..44c6725f 100644 --- a/std/flash/net/drm/DRMVoucherDownloadContext.hx +++ b/std/flash/net/drm/DRMVoucherDownloadContext.hx @@ -1,7 +1,7 @@ package flash.net.drm; extern class DRMVoucherDownloadContext extends DRMManagerSession { - var voucher(default,null) : DRMVoucher; + var voucher(default,never) : DRMVoucher; function new() : Void; function download(inMetadata : DRMContentData, previewVoucher : Bool = false) : Void; } diff --git a/std/flash/net/drm/DRMVoucherStoreContext.hx b/std/flash/net/drm/DRMVoucherStoreContext.hx index f961f15d..dc731f06 100644 --- a/std/flash/net/drm/DRMVoucherStoreContext.hx +++ b/std/flash/net/drm/DRMVoucherStoreContext.hx @@ -1,7 +1,7 @@ package flash.net.drm; extern class DRMVoucherStoreContext extends DRMManagerSession { - var voucher(default,null) : DRMVoucher; + var voucher(default,never) : DRMVoucher; function new() : Void; function getVoucherFromStore(inMetadata : DRMContentData) : Void; } diff --git a/std/flash/net/drm/LoadVoucherSetting.hx b/std/flash/net/drm/LoadVoucherSetting.hx index 678dc7a5..18993c8d 100644 --- a/std/flash/net/drm/LoadVoucherSetting.hx +++ b/std/flash/net/drm/LoadVoucherSetting.hx @@ -2,7 +2,7 @@ package flash.net.drm; extern class LoadVoucherSetting { function new() : Void; - static var ALLOW_SERVER : String; - static var FORCE_REFRESH : String; - static var LOCAL_ONLY : String; + static var ALLOW_SERVER(default,never) : String; + static var FORCE_REFRESH(default,never) : String; + static var LOCAL_ONLY(default,never) : String; } diff --git a/std/flash/net/drm/VoucherAccessInfo.hx b/std/flash/net/drm/VoucherAccessInfo.hx index 41c41dd5..895bd536 100644 --- a/std/flash/net/drm/VoucherAccessInfo.hx +++ b/std/flash/net/drm/VoucherAccessInfo.hx @@ -1,10 +1,10 @@ package flash.net.drm; @:final extern class VoucherAccessInfo { - var authenticationMethod(default,null) : String; - var deviceGroup(default,null) : DRMDeviceGroup; - var displayName(default,null) : String; - var domain(default,null) : String; - var policyID(default,null) : String; + var authenticationMethod(default,never) : String; + var deviceGroup(default,never) : DRMDeviceGroup; + var displayName(default,never) : String; + var domain(default,never) : String; + var policyID(default,never) : String; function new() : Void; } diff --git a/std/flash/printing/PrintJob.hx b/std/flash/printing/PrintJob.hx index e7fe3760..1fc72279 100644 --- a/std/flash/printing/PrintJob.hx +++ b/std/flash/printing/PrintJob.hx @@ -1,14 +1,14 @@ package flash.printing; extern class PrintJob extends flash.events.EventDispatcher { - var orientation(default,null) : PrintJobOrientation; - var pageHeight(default,null) : Int; - var pageWidth(default,null) : Int; - var paperHeight(default,null) : Int; - var paperWidth(default,null) : Int; + var orientation(default,never) : PrintJobOrientation; + var pageHeight(default,never) : Int; + var pageWidth(default,never) : Int; + var paperHeight(default,never) : Int; + var paperWidth(default,never) : Int; function new() : Void; function addPage(sprite : flash.display.Sprite, ?printArea : flash.geom.Rectangle, ?options : PrintJobOptions, frameNum : Int = 0) : Void; function send() : Void; function start() : Bool; - @:require(flash10_1) static var isSupported(default,null) : Bool; + @:require(flash10_1) static var isSupported(default,never) : Bool; } diff --git a/std/flash/profiler/Telemetry.hx b/std/flash/profiler/Telemetry.hx new file mode 100644 index 00000000..2e878d40 --- /dev/null +++ b/std/flash/profiler/Telemetry.hx @@ -0,0 +1,11 @@ +package flash.profiler; + +extern class Telemetry { + function new() : Void; + static var connected(default,never) : Bool; + static var spanMarker(default,never) : Float; + static function registerCommandHandler(commandName : String, handler : Dynamic) : Bool; + static function sendMetric(metric : String, value : Dynamic) : Void; + static function sendSpanMetric(metric : String, startSpanMarker : Float, ?value : Dynamic) : Void; + static function unregisterCommandHandler(commandName : String) : Bool; +} diff --git a/std/flash/sampler/ClassFactory.hx b/std/flash/sampler/ClassFactory.hx index 463a56ed..2969ec56 100644 --- a/std/flash/sampler/ClassFactory.hx +++ b/std/flash/sampler/ClassFactory.hx @@ -2,8 +2,8 @@ package flash.sampler; extern class ClassFactory { function new() : Void; - static var DeleteObjectSampleClass : Class; - static var NewObjectSampleClass : Class; - static var SampleClass : Class; - static var StackFrameClass : Class; + static var DeleteObjectSampleClass(default,never) : Class; + static var NewObjectSampleClass(default,never) : Class; + static var SampleClass(default,never) : Class; + static var StackFrameClass(default,never) : Class; } diff --git a/std/flash/sampler/DeleteObjectSample.hx b/std/flash/sampler/DeleteObjectSample.hx index 18b13c44..333afdd2 100644 --- a/std/flash/sampler/DeleteObjectSample.hx +++ b/std/flash/sampler/DeleteObjectSample.hx @@ -1,6 +1,6 @@ package flash.sampler; @:final extern class DeleteObjectSample extends Sample { - var id : Float; - var size : Float; + var id(default,never) : Float; + var size(default,never) : Float; } diff --git a/std/flash/sampler/NewObjectSample.hx b/std/flash/sampler/NewObjectSample.hx index 4ecf240a..3b78bcc0 100644 --- a/std/flash/sampler/NewObjectSample.hx +++ b/std/flash/sampler/NewObjectSample.hx @@ -1,8 +1,8 @@ package flash.sampler; @:final extern class NewObjectSample extends Sample { - var id : Float; - var object(default,null) : Dynamic; - @:require(flash10_1) var size(default,null) : Float; - var type : Class; + var id(default,never) : Float; + var object(default,never) : Dynamic; + @:require(flash10_1) var size(default,never) : Float; + var type(default,never) : Class; } diff --git a/std/flash/sampler/Sample.hx b/std/flash/sampler/Sample.hx index 80f0ffeb..173137b3 100644 --- a/std/flash/sampler/Sample.hx +++ b/std/flash/sampler/Sample.hx @@ -1,6 +1,6 @@ package flash.sampler; extern class Sample { - var stack : Array; - var time : Float; + var stack(default,never) : Array; + var time(default,never) : Float; } diff --git a/std/flash/sampler/StackFrame.hx b/std/flash/sampler/StackFrame.hx index a201103f..330213de 100644 --- a/std/flash/sampler/StackFrame.hx +++ b/std/flash/sampler/StackFrame.hx @@ -1,9 +1,9 @@ package flash.sampler; @:final extern class StackFrame { - var file : String; - var line : UInt; - var name : String; - @:require(flash10_1) var scriptID : Float; + var file(default,never) : String; + var line(default,never) : UInt; + var name(default,never) : String; + @:require(flash10_1) var scriptID(default,never) : Float; function toString() : String; } diff --git a/std/flash/security/CertificateStatus.hx b/std/flash/security/CertificateStatus.hx index 7c89bb3b..05f873cd 100644 --- a/std/flash/security/CertificateStatus.hx +++ b/std/flash/security/CertificateStatus.hx @@ -2,13 +2,13 @@ package flash.security; extern class CertificateStatus { function new() : Void; - static var EXPIRED : String; - static var INVALID : String; - static var INVALID_CHAIN : String; - static var NOT_YET_VALID : String; - static var PRINCIPAL_MISMATCH : String; - static var REVOKED : String; - static var TRUSTED : String; - static var UNKNOWN : String; - static var UNTRUSTED_SIGNERS : String; + static var EXPIRED(default,never) : String; + static var INVALID(default,never) : String; + static var INVALID_CHAIN(default,never) : String; + static var NOT_YET_VALID(default,never) : String; + static var PRINCIPAL_MISMATCH(default,never) : String; + static var REVOKED(default,never) : String; + static var TRUSTED(default,never) : String; + static var UNKNOWN(default,never) : String; + static var UNTRUSTED_SIGNERS(default,never) : String; } diff --git a/std/flash/security/X500DistinguishedName.hx b/std/flash/security/X500DistinguishedName.hx index 6c0c396b..37defca3 100644 --- a/std/flash/security/X500DistinguishedName.hx +++ b/std/flash/security/X500DistinguishedName.hx @@ -1,12 +1,12 @@ package flash.security; extern class X500DistinguishedName { - var commonName(default,null) : String; - var countryName(default,null) : String; - var localityName(default,null) : String; - var organizationName(default,null) : String; - var organizationalUnitName(default,null) : String; - var stateOrProvinceName(default,null) : String; + var commonName(default,never) : String; + var countryName(default,never) : String; + var localityName(default,never) : String; + var organizationName(default,never) : String; + var organizationalUnitName(default,never) : String; + var stateOrProvinceName(default,never) : String; function new() : Void; function toString() : String; } diff --git a/std/flash/security/X509Certificate.hx b/std/flash/security/X509Certificate.hx index f8be9304..dfdd82c5 100644 --- a/std/flash/security/X509Certificate.hx +++ b/std/flash/security/X509Certificate.hx @@ -1,18 +1,18 @@ package flash.security; extern class X509Certificate { - var encoded(default,null) : flash.utils.ByteArray; - var issuer(default,null) : X500DistinguishedName; - var issuerUniqueID(default,null) : String; - var serialNumber(default,null) : String; - var signatureAlgorithmOID(default,null) : String; - var signatureAlgorithmParams(default,null) : flash.utils.ByteArray; - var subject(default,null) : X500DistinguishedName; - var subjectPublicKey(default,null) : String; - var subjectPublicKeyAlgorithmOID(default,null) : String; - var subjectUniqueID(default,null) : String; - var validNotAfter(default,null) : Date; - var validNotBefore(default,null) : Date; - var version(default,null) : UInt; + var encoded(default,never) : flash.utils.ByteArray; + var issuer(default,never) : X500DistinguishedName; + var issuerUniqueID(default,never) : String; + var serialNumber(default,never) : String; + var signatureAlgorithmOID(default,never) : String; + var signatureAlgorithmParams(default,never) : flash.utils.ByteArray; + var subject(default,never) : X500DistinguishedName; + var subjectPublicKey(default,never) : String; + var subjectPublicKeyAlgorithmOID(default,never) : String; + var subjectUniqueID(default,never) : String; + var validNotAfter(default,never) : Date; + var validNotBefore(default,never) : Date; + var version(default,never) : UInt; function new() : Void; } diff --git a/std/flash/sensors/Accelerometer.hx b/std/flash/sensors/Accelerometer.hx index a1ca5d7b..dbeab47f 100644 --- a/std/flash/sensors/Accelerometer.hx +++ b/std/flash/sensors/Accelerometer.hx @@ -1,8 +1,8 @@ package flash.sensors; @:require(flash10_1) extern class Accelerometer extends flash.events.EventDispatcher { - var muted(default,null) : Bool; + var muted(default,never) : Bool; function new() : Void; function setRequestedUpdateInterval(interval : Float) : Void; - static var isSupported(default,null) : Bool; + static var isSupported(default,never) : Bool; } diff --git a/std/flash/sensors/Geolocation.hx b/std/flash/sensors/Geolocation.hx index 74227bde..7f917e24 100644 --- a/std/flash/sensors/Geolocation.hx +++ b/std/flash/sensors/Geolocation.hx @@ -1,8 +1,8 @@ package flash.sensors; @:require(flash10_1) extern class Geolocation extends flash.events.EventDispatcher { - var muted(default,null) : Bool; + var muted(default,never) : Bool; function new() : Void; function setRequestedUpdateInterval(interval : Float) : Void; - static var isSupported(default,null) : Bool; + static var isSupported(default,never) : Bool; } diff --git a/std/flash/system/ApplicationDomain.hx b/std/flash/system/ApplicationDomain.hx index d422d6b4..557689e7 100644 --- a/std/flash/system/ApplicationDomain.hx +++ b/std/flash/system/ApplicationDomain.hx @@ -2,11 +2,11 @@ package flash.system; @:final extern class ApplicationDomain { @:require(flash10) var domainMemory : flash.utils.ByteArray; - var parentDomain(default,null) : ApplicationDomain; + var parentDomain(default,never) : ApplicationDomain; function new(?parentDomain : ApplicationDomain) : Void; function getDefinition(name : String) : flash.utils.Object; @:require(flash11_3) function getQualifiedDefinitionNames() : flash.Vector; function hasDefinition(name : String) : Bool; - @:require(flash10) static var MIN_DOMAIN_MEMORY_LENGTH(default,null) : UInt; - static var currentDomain(default,null) : ApplicationDomain; + @:require(flash10) static var MIN_DOMAIN_MEMORY_LENGTH(default,never) : UInt; + static var currentDomain(default,never) : ApplicationDomain; } diff --git a/std/flash/system/ApplicationInstaller.hx b/std/flash/system/ApplicationInstaller.hx index 6543e85e..6c658b17 100644 --- a/std/flash/system/ApplicationInstaller.hx +++ b/std/flash/system/ApplicationInstaller.hx @@ -1,7 +1,7 @@ package flash.system; @:final @:require(flash11_3) extern class ApplicationInstaller extends flash.events.EventDispatcher { - var isInstalled(default,null) : Bool; + var isInstalled(default,never) : Bool; function new() : Void; function install(?mode : String) : Void; static function iconDigest(icon : flash.utils.ByteArray) : String; diff --git a/std/flash/system/AuthorizedFeatures.hx b/std/flash/system/AuthorizedFeatures.hx index a08f574e..1eb9a131 100644 --- a/std/flash/system/AuthorizedFeatures.hx +++ b/std/flash/system/AuthorizedFeatures.hx @@ -3,10 +3,12 @@ package flash.system; @:final @:require(flash11_3) extern class AuthorizedFeatures { function new() : Void; function createApplicationInstaller(strings : flash.xml.XML, icon : flash.utils.ByteArray) : ApplicationInstaller; + function enableAVLoader(loader : flash.display.AVLoader) : Bool; function enableAVURLLoader(loader : flash.media.AVURLLoader) : Bool; function enableAVURLStream(stream : flash.media.AVURLStream) : Bool; @:require(flash11_4) function enableDiskCache(stream : flash.net.URLStream) : Bool; @:require(flash11_7) function enableHLSPlayback(stream : flash.media.AVStream) : Bool; + function enableMediaPlayerHLSPlayback(player : Dynamic) : Bool; @:require(flash11_4) function isFeatureEnabled(feature : String, ?data : String) : Bool; @:require(flash11_4) function isNegativeToken() : Bool; } diff --git a/std/flash/system/AuthorizedFeaturesLoader.hx b/std/flash/system/AuthorizedFeaturesLoader.hx index feabe618..6f593456 100644 --- a/std/flash/system/AuthorizedFeaturesLoader.hx +++ b/std/flash/system/AuthorizedFeaturesLoader.hx @@ -1,7 +1,7 @@ package flash.system; @:final @:require(flash11_3) extern class AuthorizedFeaturesLoader extends flash.events.EventDispatcher { - var authorizedFeatures(default,null) : AuthorizedFeatures; + var authorizedFeatures(default,never) : AuthorizedFeatures; function new() : Void; function loadAuthorizedFeatures() : Void; @:require(flash11_7) function loadAuthorizedFeaturesFromData(data : flash.utils.ByteArray) : Void; diff --git a/std/flash/system/Capabilities.hx b/std/flash/system/Capabilities.hx index 30052e42..0fe6f780 100644 --- a/std/flash/system/Capabilities.hx +++ b/std/flash/system/Capabilities.hx @@ -1,39 +1,39 @@ package flash.system; extern class Capabilities { - static var _internal(default,null) : UInt; - static var avHardwareDisable(default,null) : Bool; - @:require(flash10_1) static var cpuArchitecture(default,null) : String; - static var hasAccessibility(default,null) : Bool; - static var hasAudio(default,null) : Bool; - static var hasAudioEncoder(default,null) : Bool; - static var hasEmbeddedVideo(default,null) : Bool; - static var hasIME(default,null) : Bool; - static var hasMP3(default,null) : Bool; - static var hasPrinting(default,null) : Bool; - static var hasScreenBroadcast(default,null) : Bool; - static var hasScreenPlayback(default,null) : Bool; - static var hasStreamingAudio(default,null) : Bool; - static var hasStreamingVideo(default,null) : Bool; - static var hasTLS(default,null) : Bool; - static var hasVideoEncoder(default,null) : Bool; - static var isDebugger(default,null) : Bool; - @:require(flash10) static var isEmbeddedInAcrobat(default,null) : Bool; - static var language(default,null) : String; - static var localFileReadDisable(default,null) : Bool; - static var manufacturer(default,null) : String; - @:require(flash10) static var maxLevelIDC(default,null) : String; - static var os(default,null) : String; - static var pixelAspectRatio(default,null) : Float; - static var playerType(default,null) : String; - static var screenColor(default,null) : String; - static var screenDPI(default,null) : Float; - static var screenResolutionX(default,null) : Float; - static var screenResolutionY(default,null) : Float; - static var serverString(default,null) : String; - @:require(flash10_1) static var supports32BitProcesses(default,null) : Bool; - @:require(flash10_1) static var supports64BitProcesses(default,null) : Bool; - @:require(flash10_1) static var touchscreenType(default,null) : TouchscreenType; - static var version(default,null) : String; + static var _internal(default,never) : UInt; + static var avHardwareDisable(default,never) : Bool; + @:require(flash10_1) static var cpuArchitecture(default,never) : String; + static var hasAccessibility(default,never) : Bool; + static var hasAudio(default,never) : Bool; + static var hasAudioEncoder(default,never) : Bool; + static var hasEmbeddedVideo(default,never) : Bool; + static var hasIME(default,never) : Bool; + static var hasMP3(default,never) : Bool; + static var hasPrinting(default,never) : Bool; + static var hasScreenBroadcast(default,never) : Bool; + static var hasScreenPlayback(default,never) : Bool; + static var hasStreamingAudio(default,never) : Bool; + static var hasStreamingVideo(default,never) : Bool; + static var hasTLS(default,never) : Bool; + static var hasVideoEncoder(default,never) : Bool; + static var isDebugger(default,never) : Bool; + @:require(flash10) static var isEmbeddedInAcrobat(default,never) : Bool; + static var language(default,never) : String; + static var localFileReadDisable(default,never) : Bool; + static var manufacturer(default,never) : String; + @:require(flash10) static var maxLevelIDC(default,never) : String; + static var os(default,never) : String; + static var pixelAspectRatio(default,never) : Float; + static var playerType(default,never) : String; + static var screenColor(default,never) : String; + static var screenDPI(default,never) : Float; + static var screenResolutionX(default,never) : Float; + static var screenResolutionY(default,never) : Float; + static var serverString(default,never) : String; + @:require(flash10_1) static var supports32BitProcesses(default,never) : Bool; + @:require(flash10_1) static var supports64BitProcesses(default,never) : Bool; + @:require(flash10_1) static var touchscreenType(default,never) : TouchscreenType; + static var version(default,never) : String; @:require(flash11) static function hasMultiChannelAudio(type : String) : Bool; } diff --git a/std/flash/system/IME.hx b/std/flash/system/IME.hx index 5d347518..5e94a16d 100644 --- a/std/flash/system/IME.hx +++ b/std/flash/system/IME.hx @@ -3,7 +3,7 @@ package flash.system; extern class IME extends flash.events.EventDispatcher { static var conversionMode : IMEConversionMode; static var enabled : Bool; - @:require(flash10_1) static var isSupported(default,null) : Bool; + @:require(flash10_1) static var isSupported(default,never) : Bool; @:require(flash10_1) static function compositionAbandoned() : Void; @:require(flash10_1) static function compositionSelectionChanged(start : Int, end : Int) : Void; static function doConversion() : Void; diff --git a/std/flash/system/MessageChannel.hx b/std/flash/system/MessageChannel.hx index cc4ebb22..9fcd885f 100644 --- a/std/flash/system/MessageChannel.hx +++ b/std/flash/system/MessageChannel.hx @@ -1,8 +1,8 @@ package flash.system; @:final @:require(flash11_4) extern class MessageChannel extends flash.events.EventDispatcher { - var messageAvailable(default,null) : Bool; - var state(default,null) : MessageChannelState; + var messageAvailable(default,never) : Bool; + var state(default,never) : MessageChannelState; function close() : Void; function receive(blockUntilReceived : Bool = false) : Dynamic; function send(arg : Dynamic, queueLimit : Int = -1) : Void; diff --git a/std/flash/system/MessageChannelState.hx b/std/flash/system/MessageChannelState.hx index bf42eb2c..27d04e81 100644 --- a/std/flash/system/MessageChannelState.hx +++ b/std/flash/system/MessageChannelState.hx @@ -2,7 +2,7 @@ package flash.system; extern class MessageChannelState { function new() : Void; - static var CLOSED : String; - static var CLOSING : String; - static var OPEN : String; + static var CLOSED(default,never) : String; + static var CLOSING(default,never) : String; + static var OPEN(default,never) : String; } diff --git a/std/flash/system/Security.hx b/std/flash/system/Security.hx index 0c0fcdd4..1c5e586f 100644 --- a/std/flash/system/Security.hx +++ b/std/flash/system/Security.hx @@ -1,15 +1,15 @@ package flash.system; extern class Security { - @:require(flash10_1) static var APPLICATION : String; - static var LOCAL_TRUSTED : String; - static var LOCAL_WITH_FILE : String; - static var LOCAL_WITH_NETWORK : String; - static var REMOTE : String; + @:require(flash10_1) static var APPLICATION(default,never) : String; + static var LOCAL_TRUSTED(default,never) : String; + static var LOCAL_WITH_FILE(default,never) : String; + static var LOCAL_WITH_NETWORK(default,never) : String; + static var REMOTE(default,never) : String; static var disableAVM1Loading : Bool; static var exactSettings : Bool; - @:require(flash11) static var pageDomain(default,null) : String; - static var sandboxType(default,null) : String; + @:require(flash11) static var pageDomain(default,never) : String; + static var sandboxType(default,never) : String; static function allowDomain(?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; static function allowInsecureDomain(?p1 : Dynamic, ?p2 : Dynamic, ?p3 : Dynamic, ?p4 : Dynamic, ?p5 : Dynamic) : Void; @:require(flash10_1) static function duplicateSandboxBridgeInputArguments(toplevel : Dynamic, args : Array) : Array; diff --git a/std/flash/system/SecurityDomain.hx b/std/flash/system/SecurityDomain.hx index b31f2a16..0334d7a1 100644 --- a/std/flash/system/SecurityDomain.hx +++ b/std/flash/system/SecurityDomain.hx @@ -1,6 +1,6 @@ package flash.system; extern class SecurityDomain { - @:require(flash11_3) var domainID(default,null) : String; - static var currentDomain(default,null) : SecurityDomain; + @:require(flash11_3) var domainID(default,never) : String; + static var currentDomain(default,never) : SecurityDomain; } diff --git a/std/flash/system/System.hx b/std/flash/system/System.hx index a610e0c8..68110693 100644 --- a/std/flash/system/System.hx +++ b/std/flash/system/System.hx @@ -1,14 +1,14 @@ package flash.system; extern class System { - @:require(flash10_1) static var freeMemory(default,null) : Float; - static var ime(default,null) : IME; - @:require(flash10_1) static var privateMemory(default,null) : Float; - @:require(flash11) static var processCPUUsage(default,null) : Float; - static var totalMemory(default,null) : UInt; - @:require(flash10_1) static var totalMemoryNumber(default,null) : Float; + @:require(flash10_1) static var freeMemory(default,never) : Float; + static var ime(default,never) : IME; + @:require(flash10_1) static var privateMemory(default,never) : Float; + @:require(flash11) static var processCPUUsage(default,never) : Float; + static var totalMemory(default,never) : UInt; + @:require(flash10_1) static var totalMemoryNumber(default,never) : Float; static var useCodePage : Bool; - static var vmVersion(default,null) : String; + static var vmVersion(default,never) : String; @:require(flash10_1) static function disposeXML(node : flash.xml.XML) : Void; static function exit(code : UInt) : Void; static function gc() : Void; diff --git a/std/flash/system/Worker.hx b/std/flash/system/Worker.hx index 246cc45f..bf55de5f 100644 --- a/std/flash/system/Worker.hx +++ b/std/flash/system/Worker.hx @@ -1,13 +1,13 @@ package flash.system; @:final @:require(flash11_4) extern class Worker extends flash.events.EventDispatcher { - var isPrimordial(default,null) : Bool; - var state(default,null) : WorkerState; + var isPrimordial(default,never) : Bool; + var state(default,never) : WorkerState; function createMessageChannel(receiver : Worker) : MessageChannel; function getSharedProperty(key : String) : Dynamic; function setSharedProperty(key : String, value : Dynamic) : Void; function start() : Void; function terminate() : Bool; - static var current(default,null) : Worker; - static var isSupported(default,null) : Bool; + static var current(default,never) : Worker; + static var isSupported(default,never) : Bool; } diff --git a/std/flash/system/WorkerDomain.hx b/std/flash/system/WorkerDomain.hx index 6f0ded11..806db4a0 100644 --- a/std/flash/system/WorkerDomain.hx +++ b/std/flash/system/WorkerDomain.hx @@ -4,6 +4,6 @@ package flash.system; function new() : Void; function createWorker(swf : flash.utils.ByteArray, giveAppPrivileges : Bool = false) : Worker; function listWorkers() : flash.Vector; - static var current(default,null) : WorkerDomain; - static var isSupported(default,null) : Bool; + static var current(default,never) : WorkerDomain; + static var isSupported(default,never) : Bool; } diff --git a/std/flash/text/Font.hx b/std/flash/text/Font.hx index 502d45ca..6a30c089 100644 --- a/std/flash/text/Font.hx +++ b/std/flash/text/Font.hx @@ -1,9 +1,9 @@ package flash.text; extern class Font { - var fontName(default,null) : String; - var fontStyle(default,null) : FontStyle; - var fontType(default,null) : FontType; + var fontName(default,never) : String; + var fontStyle(default,never) : FontStyle; + var fontType(default,never) : FontType; function new() : Void; function hasGlyphs(str : String) : Bool; static function enumerateFonts(enumerateDeviceFonts : Bool = false) : Array; diff --git a/std/flash/text/StaticText.hx b/std/flash/text/StaticText.hx index 85d31473..01d7e7c0 100644 --- a/std/flash/text/StaticText.hx +++ b/std/flash/text/StaticText.hx @@ -1,6 +1,6 @@ package flash.text; @:final extern class StaticText extends flash.display.DisplayObject { - var text(default,null) : String; + var text(default,never) : String; function new() : Void; } diff --git a/std/flash/text/StyleSheet.hx b/std/flash/text/StyleSheet.hx index 45ee43a0..10cb9a44 100644 --- a/std/flash/text/StyleSheet.hx +++ b/std/flash/text/StyleSheet.hx @@ -1,7 +1,7 @@ package flash.text; extern class StyleSheet extends flash.events.EventDispatcher implements Dynamic { - var styleNames(default,null) : Array; + var styleNames(default,never) : Array; function new() : Void; function clear() : Void; function getStyle(styleName : String) : flash.utils.Object; diff --git a/std/flash/text/TextField.hx b/std/flash/text/TextField.hx index c36a3d59..bfdba610 100644 --- a/std/flash/text/TextField.hx +++ b/std/flash/text/TextField.hx @@ -8,35 +8,35 @@ extern class TextField extends flash.display.InteractiveObject { var backgroundColor : UInt; var border : Bool; var borderColor : UInt; - var bottomScrollV(default,null) : Int; - var caretIndex(default,null) : Int; + var bottomScrollV(default,never) : Int; + var caretIndex(default,never) : Int; var condenseWhite : Bool; var defaultTextFormat : TextFormat; var displayAsPassword : Bool; var embedFonts : Bool; var gridFitType : GridFitType; var htmlText : String; - var length(default,null) : Int; + var length(default,never) : Int; var maxChars : Int; - var maxScrollH(default,null) : Int; - var maxScrollV(default,null) : Int; + var maxScrollH(default,never) : Int; + var maxScrollV(default,never) : Int; var mouseWheelEnabled : Bool; var multiline : Bool; - var numLines(default,null) : Int; + var numLines(default,never) : Int; var restrict : String; var scrollH : Int; var scrollV : Int; var selectable : Bool; - var selectedText(default,null) : String; - var selectionBeginIndex(default,null) : Int; - var selectionEndIndex(default,null) : Int; + var selectedText(default,never) : String; + var selectionBeginIndex(default,never) : Int; + var selectionEndIndex(default,never) : Int; var sharpness : Float; var styleSheet : StyleSheet; var text : String; var textColor : UInt; - var textHeight(default,null) : Float; - @:require(flash11) var textInteractionMode(default,null) : TextInteractionMode; - var textWidth(default,null) : Float; + var textHeight(default,never) : Float; + @:require(flash11) var textInteractionMode(default,never) : TextInteractionMode; + var textWidth(default,never) : Float; var thickness : Float; var type : TextFieldType; var useRichTextClipboard : Bool; diff --git a/std/flash/text/TextFormat.hx b/std/flash/text/TextFormat.hx index cc88242e..08d6d455 100644 --- a/std/flash/text/TextFormat.hx +++ b/std/flash/text/TextFormat.hx @@ -20,5 +20,5 @@ extern class TextFormat { var target : String; var underline : Null; var url : String; - function new(?font : String, ?size : Float, ?color : UInt, ?bold : Bool, ?italic : Bool, ?underline : Bool, ?url : String, ?target : String, ?align : TextFormatAlign, ?leftMargin : Float, ?rightMargin : Float, ?indent : Float, ?leading : Float) : Void; + function new(?font : String, size : Null = 0, color : Null = 0, bold : Null = false, italic : Null = false, underline : Null = false, ?url : String, ?target : String, ?align : TextFormatAlign, leftMargin : Null = 0, rightMargin : Null = 0, indent : Null = 0, leading : Null = 0) : Void; } diff --git a/std/flash/text/TextSnapshot.hx b/std/flash/text/TextSnapshot.hx index da929d6b..80598c0d 100644 --- a/std/flash/text/TextSnapshot.hx +++ b/std/flash/text/TextSnapshot.hx @@ -1,7 +1,7 @@ package flash.text; extern class TextSnapshot { - var charCount(default,null) : Int; + var charCount(default,never) : Int; function new() : Void; function findText(beginIndex : Int, textToFind : String, caseSensitive : Bool) : Int; function getSelected(beginIndex : Int, endIndex : Int) : Bool; diff --git a/std/flash/text/engine/ContentElement.hx b/std/flash/text/engine/ContentElement.hx index 0c71b314..c6cb5fbf 100644 --- a/std/flash/text/engine/ContentElement.hx +++ b/std/flash/text/engine/ContentElement.hx @@ -3,13 +3,13 @@ package flash.text.engine; extern class ContentElement { var elementFormat : ElementFormat; var eventMirror : flash.events.EventDispatcher; - var groupElement(default,null) : GroupElement; - var rawText(default,null) : String; - var text(default,null) : String; - var textBlock(default,null) : TextBlock; - var textBlockBeginIndex(default,null) : Int; + var groupElement(default,never) : GroupElement; + var rawText(default,never) : String; + var text(default,never) : String; + var textBlock(default,never) : TextBlock; + var textBlockBeginIndex(default,never) : Int; var textRotation : TextRotation; var userData : Dynamic; function new(?elementFormat : ElementFormat, ?eventMirror : flash.events.EventDispatcher, ?textRotation : TextRotation) : Void; - static var GRAPHIC_ELEMENT : UInt; + static var GRAPHIC_ELEMENT(default,never) : UInt; } diff --git a/std/flash/text/engine/GroupElement.hx b/std/flash/text/engine/GroupElement.hx index c4277878..b48b4294 100644 --- a/std/flash/text/engine/GroupElement.hx +++ b/std/flash/text/engine/GroupElement.hx @@ -1,7 +1,7 @@ package flash.text.engine; @:final extern class GroupElement extends ContentElement { - var elementCount(default,null) : Int; + var elementCount(default,never) : Int; function new(?elements : flash.Vector, ?elementFormat : ElementFormat, ?eventMirror : flash.events.EventDispatcher, ?textRotation : TextRotation) : Void; function getElementAt(index : Int) : ContentElement; function getElementAtCharIndex(charIndex : Int) : ContentElement; diff --git a/std/flash/text/engine/TextBlock.hx b/std/flash/text/engine/TextBlock.hx index 8b5ea940..f59db45e 100644 --- a/std/flash/text/engine/TextBlock.hx +++ b/std/flash/text/engine/TextBlock.hx @@ -7,13 +7,13 @@ package flash.text.engine; var baselineZero : TextBaseline; var bidiLevel : Int; var content : ContentElement; - var firstInvalidLine(default,null) : TextLine; - var firstLine(default,null) : TextLine; - var lastLine(default,null) : TextLine; + var firstInvalidLine(default,never) : TextLine; + var firstLine(default,never) : TextLine; + var lastLine(default,never) : TextLine; var lineRotation : TextRotation; var tabStops : flash.Vector; var textJustifier : TextJustifier; - var textLineCreationResult(default,null) : TextLineCreationResult; + var textLineCreationResult(default,never) : TextLineCreationResult; var userData : Dynamic; function new(?content : ContentElement, ?tabStops : flash.Vector, ?textJustifier : TextJustifier, ?lineRotation : TextRotation, ?baselineZero : TextBaseline, bidiLevel : Int = 0, applyNonLinearFontScaling : Bool = true, ?baselineFontDescription : FontDescription, baselineFontSize : Float = 12) : Void; function createTextLine(?previousLine : TextLine, width : Float = 1000000, lineOffset : Float = 0, fitSomething : Bool = false) : TextLine; diff --git a/std/flash/text/engine/TextJustifier.hx b/std/flash/text/engine/TextJustifier.hx index aa061bcf..7525682f 100644 --- a/std/flash/text/engine/TextJustifier.hx +++ b/std/flash/text/engine/TextJustifier.hx @@ -2,7 +2,7 @@ package flash.text.engine; extern class TextJustifier { var lineJustification : LineJustification; - var locale(default,null) : String; + var locale(default,never) : String; function new(locale : String, lineJustification : LineJustification) : Void; function clone() : TextJustifier; static function getJustifierForLocale(locale : String) : TextJustifier; diff --git a/std/flash/text/engine/TextLine.hx b/std/flash/text/engine/TextLine.hx index e5920cdd..b6e6aabc 100644 --- a/std/flash/text/engine/TextLine.hx +++ b/std/flash/text/engine/TextLine.hx @@ -1,24 +1,24 @@ package flash.text.engine; @:final extern class TextLine extends flash.display.DisplayObjectContainer { - var ascent(default,null) : Float; - var atomCount(default,null) : Int; - var descent(default,null) : Float; - var hasGraphicElement(default,null) : Bool; - @:require(flash10_1) var hasTabs(default,null) : Bool; - var mirrorRegions(default,null) : flash.Vector; - var nextLine(default,null) : TextLine; - var previousLine(default,null) : TextLine; - var rawTextLength(default,null) : Int; - var specifiedWidth(default,null) : Float; - var textBlock(default,null) : TextBlock; - var textBlockBeginIndex(default,null) : Int; - var textHeight(default,null) : Float; - var textWidth(default,null) : Float; - var totalAscent(default,null) : Float; - var totalDescent(default,null) : Float; - var totalHeight(default,null) : Float; - var unjustifiedTextWidth(default,null) : Float; + var ascent(default,never) : Float; + var atomCount(default,never) : Int; + var descent(default,never) : Float; + var hasGraphicElement(default,never) : Bool; + @:require(flash10_1) var hasTabs(default,never) : Bool; + var mirrorRegions(default,never) : flash.Vector; + var nextLine(default,never) : TextLine; + var previousLine(default,never) : TextLine; + var rawTextLength(default,never) : Int; + var specifiedWidth(default,never) : Float; + var textBlock(default,never) : TextBlock; + var textBlockBeginIndex(default,never) : Int; + var textHeight(default,never) : Float; + var textWidth(default,never) : Float; + var totalAscent(default,never) : Float; + var totalDescent(default,never) : Float; + var totalHeight(default,never) : Float; + var unjustifiedTextWidth(default,never) : Float; var userData : Dynamic; var validity : String; function new() : Void; @@ -36,5 +36,5 @@ package flash.text.engine; function getAtomWordBoundaryOnLeft(atomIndex : Int) : Bool; function getBaselinePosition(baseline : String) : Float; function getMirrorRegion(mirror : flash.events.EventDispatcher) : TextLineMirrorRegion; - static var MAX_LINE_WIDTH : Int; + static var MAX_LINE_WIDTH(default,never) : Int; } diff --git a/std/flash/text/engine/TextLineMirrorRegion.hx b/std/flash/text/engine/TextLineMirrorRegion.hx index 238862ce..74f96c89 100644 --- a/std/flash/text/engine/TextLineMirrorRegion.hx +++ b/std/flash/text/engine/TextLineMirrorRegion.hx @@ -1,11 +1,11 @@ package flash.text.engine; @:final extern class TextLineMirrorRegion { - var bounds(default,null) : flash.geom.Rectangle; - var element(default,null) : ContentElement; - var mirror(default,null) : flash.events.EventDispatcher; - var nextRegion(default,null) : TextLineMirrorRegion; - var previousRegion(default,null) : TextLineMirrorRegion; - var textLine(default,null) : TextLine; + var bounds(default,never) : flash.geom.Rectangle; + var element(default,never) : ContentElement; + var mirror(default,never) : flash.events.EventDispatcher; + var nextRegion(default,never) : TextLineMirrorRegion; + var previousRegion(default,never) : TextLineMirrorRegion; + var textLine(default,never) : TextLine; function new() : Void; } diff --git a/std/flash/text/ime/IIMEClient.hx b/std/flash/text/ime/IIMEClient.hx index 2c122da0..12470fdd 100644 --- a/std/flash/text/ime/IIMEClient.hx +++ b/std/flash/text/ime/IIMEClient.hx @@ -1,11 +1,11 @@ package flash.text.ime; extern interface IIMEClient { - var compositionEndIndex(default,null) : Int; - var compositionStartIndex(default,null) : Int; - var selectionActiveIndex(default,null) : Int; - var selectionAnchorIndex(default,null) : Int; - var verticalTextLayout(default,null) : Bool; + var compositionEndIndex(default,never) : Int; + var compositionStartIndex(default,never) : Int; + var selectionActiveIndex(default,never) : Int; + var selectionAnchorIndex(default,never) : Int; + var verticalTextLayout(default,never) : Bool; function confirmComposition(?text : String, preserveSelection : Bool = false) : Void; function getTextBounds(startIndex : Int, endIndex : Int) : flash.geom.Rectangle; function getTextInRange(startIndex : Int, endIndex : Int) : String; diff --git a/std/flash/trace/Trace.hx b/std/flash/trace/Trace.hx index 463ad70b..05902f96 100644 --- a/std/flash/trace/Trace.hx +++ b/std/flash/trace/Trace.hx @@ -1,13 +1,13 @@ package flash.trace; extern class Trace { - static var FILE : Dynamic; - static var LISTENER : Dynamic; - static var METHODS : Int; - static var METHODS_AND_LINES : Int; - static var METHODS_AND_LINES_WITH_ARGS : Int; - static var METHODS_WITH_ARGS : Int; - static var OFF : Int; + static var FILE(default,never) : Dynamic; + static var LISTENER(default,never) : Dynamic; + static var METHODS(default,never) : Int; + static var METHODS_AND_LINES(default,never) : Int; + static var METHODS_AND_LINES_WITH_ARGS(default,never) : Int; + static var METHODS_WITH_ARGS(default,never) : Int; + static var OFF(default,never) : Int; static function getLevel(target : Int = 2) : Int; static function getListener() : Dynamic; static function setLevel(l : Int, target : Int = 2) : Dynamic; diff --git a/std/flash/ui/ContextMenu.hx b/std/flash/ui/ContextMenu.hx index 6cbeb687..89cfe2bc 100644 --- a/std/flash/ui/ContextMenu.hx +++ b/std/flash/ui/ContextMenu.hx @@ -9,5 +9,5 @@ package flash.ui; function new() : Void; function clone() : ContextMenu; function hideBuiltInItems() : Void; - @:require(flash10_1) static var isSupported(default,null) : Bool; + @:require(flash10_1) static var isSupported(default,never) : Bool; } diff --git a/std/flash/ui/GameInput.hx b/std/flash/ui/GameInput.hx index af19827c..3f9671ff 100644 --- a/std/flash/ui/GameInput.hx +++ b/std/flash/ui/GameInput.hx @@ -1,7 +1,7 @@ package flash.ui; @:require(flash11_8) extern class GameInput extends flash.events.EventDispatcher { - static var isSupported(default,null) : Bool; - static var numDevices(default,null) : Int; + static var isSupported(default,never) : Bool; + static var numDevices(default,never) : Int; static function getDeviceAt(index : Int) : GameInputDevice; } diff --git a/std/flash/ui/GameInputControl.hx b/std/flash/ui/GameInputControl.hx index e31fabcb..e6c4314d 100644 --- a/std/flash/ui/GameInputControl.hx +++ b/std/flash/ui/GameInputControl.hx @@ -1,10 +1,10 @@ package flash.ui; extern class GameInputControl extends flash.events.EventDispatcher implements Dynamic { - var device(default,null) : GameInputDevice; - var id(default,null) : String; - var maxValue(default,null) : Float; - var minValue(default,null) : Float; - var value(default,null) : Float; + var device(default,never) : GameInputDevice; + var id(default,never) : String; + var maxValue(default,never) : Float; + var minValue(default,never) : Float; + var value(default,never) : Float; function new() : Void; } diff --git a/std/flash/ui/GameInputDevice.hx b/std/flash/ui/GameInputDevice.hx index dcca8819..ad4b5994 100644 --- a/std/flash/ui/GameInputDevice.hx +++ b/std/flash/ui/GameInputDevice.hx @@ -2,14 +2,14 @@ package flash.ui; @:final @:require(flash11_8) extern class GameInputDevice { var enabled : Bool; - var id(default,null) : String; - var name(default,null) : String; - var numControls(default,null) : Int; + var id(default,never) : String; + var name(default,never) : String; + var numControls(default,never) : Int; var sampleInterval : Int; function new() : Void; function getCachedSamples(data : flash.utils.ByteArray, append : Bool = false) : Int; function getControlAt(i : Int) : GameInputControl; function startCachingSamples(numSamples : Int, controls : flash.Vector) : Void; function stopCachingSamples() : Void; - static var MAX_BUFFER_SIZE : Int; + static var MAX_BUFFER_SIZE(default,never) : Int; } diff --git a/std/flash/ui/Keyboard.hx b/std/flash/ui/Keyboard.hx index 7d70eb0d..4d78de55 100644 --- a/std/flash/ui/Keyboard.hx +++ b/std/flash/ui/Keyboard.hx @@ -1,285 +1,285 @@ package flash.ui; extern class Keyboard { - @:require(flash10_1) static var A : UInt; - @:require(flash10_1) static var ALTERNATE : UInt; - @:require(flash10_2) static var AUDIO : UInt; - @:require(flash10_1) static var B : UInt; - @:require(flash10_2) static var BACK : UInt; - @:require(flash10_1) static var BACKQUOTE : UInt; - @:require(flash10_1) static var BACKSLASH : UInt; - static var BACKSPACE : UInt; - @:require(flash10_2) static var BLUE : UInt; - @:require(flash10_1) static var C : UInt; - static var CAPS_LOCK : UInt; - @:require(flash10_2) static var CHANNEL_DOWN : UInt; - @:require(flash10_2) static var CHANNEL_UP : UInt; - @:require(flash10_1) static var COMMA : UInt; - @:require(flash10_1) static var COMMAND : UInt; - static var CONTROL : UInt; - @:require(flash10_1) static var CharCodeStrings : Array; - @:require(flash10_1) static var D : UInt; - static var DELETE : UInt; - static var DOWN : UInt; - @:require(flash10_2) static var DVR : UInt; - @:require(flash10_1) static var E : UInt; - static var END : UInt; - static var ENTER : UInt; - @:require(flash10_1) static var EQUAL : UInt; - static var ESCAPE : UInt; - @:require(flash10_2) static var EXIT : UInt; - @:require(flash10_1) static var F : UInt; - static var F1 : UInt; - static var F10 : UInt; - static var F11 : UInt; - static var F12 : UInt; - static var F13 : UInt; - static var F14 : UInt; - static var F15 : UInt; - static var F2 : UInt; - static var F3 : UInt; - static var F4 : UInt; - static var F5 : UInt; - static var F6 : UInt; - static var F7 : UInt; - static var F8 : UInt; - static var F9 : UInt; - @:require(flash10_2) static var FAST_FORWARD : UInt; - @:require(flash10_1) static var G : UInt; - @:require(flash10_2) static var GREEN : UInt; - @:require(flash10_2) static var GUIDE : UInt; - @:require(flash10_1) static var H : UInt; - @:require(flash10_2) static var HELP : UInt; - static var HOME : UInt; - @:require(flash10_1) static var I : UInt; - @:require(flash10_2) static var INFO : UInt; - @:require(flash10_2) static var INPUT : UInt; - static var INSERT : UInt; - @:require(flash10_1) static var J : UInt; - @:require(flash10_1) static var K : UInt; - @:require(flash10_1) static var KEYNAME_BEGIN : String; - @:require(flash10_1) static var KEYNAME_BREAK : String; - @:require(flash10_1) static var KEYNAME_CLEARDISPLAY : String; - @:require(flash10_1) static var KEYNAME_CLEARLINE : String; - @:require(flash10_1) static var KEYNAME_DELETE : String; - @:require(flash10_1) static var KEYNAME_DELETECHAR : String; - @:require(flash10_1) static var KEYNAME_DELETELINE : String; - @:require(flash10_1) static var KEYNAME_DOWNARROW : String; - @:require(flash10_1) static var KEYNAME_END : String; - @:require(flash10_1) static var KEYNAME_EXECUTE : String; - @:require(flash10_1) static var KEYNAME_F1 : String; - @:require(flash10_1) static var KEYNAME_F10 : String; - @:require(flash10_1) static var KEYNAME_F11 : String; - @:require(flash10_1) static var KEYNAME_F12 : String; - @:require(flash10_1) static var KEYNAME_F13 : String; - @:require(flash10_1) static var KEYNAME_F14 : String; - @:require(flash10_1) static var KEYNAME_F15 : String; - @:require(flash10_1) static var KEYNAME_F16 : String; - @:require(flash10_1) static var KEYNAME_F17 : String; - @:require(flash10_1) static var KEYNAME_F18 : String; - @:require(flash10_1) static var KEYNAME_F19 : String; - @:require(flash10_1) static var KEYNAME_F2 : String; - @:require(flash10_1) static var KEYNAME_F20 : String; - @:require(flash10_1) static var KEYNAME_F21 : String; - @:require(flash10_1) static var KEYNAME_F22 : String; - @:require(flash10_1) static var KEYNAME_F23 : String; - @:require(flash10_1) static var KEYNAME_F24 : String; - @:require(flash10_1) static var KEYNAME_F25 : String; - @:require(flash10_1) static var KEYNAME_F26 : String; - @:require(flash10_1) static var KEYNAME_F27 : String; - @:require(flash10_1) static var KEYNAME_F28 : String; - @:require(flash10_1) static var KEYNAME_F29 : String; - @:require(flash10_1) static var KEYNAME_F3 : String; - @:require(flash10_1) static var KEYNAME_F30 : String; - @:require(flash10_1) static var KEYNAME_F31 : String; - @:require(flash10_1) static var KEYNAME_F32 : String; - @:require(flash10_1) static var KEYNAME_F33 : String; - @:require(flash10_1) static var KEYNAME_F34 : String; - @:require(flash10_1) static var KEYNAME_F35 : String; - @:require(flash10_1) static var KEYNAME_F4 : String; - @:require(flash10_1) static var KEYNAME_F5 : String; - @:require(flash10_1) static var KEYNAME_F6 : String; - @:require(flash10_1) static var KEYNAME_F7 : String; - @:require(flash10_1) static var KEYNAME_F8 : String; - @:require(flash10_1) static var KEYNAME_F9 : String; - @:require(flash10_1) static var KEYNAME_FIND : String; - @:require(flash10_1) static var KEYNAME_HELP : String; - @:require(flash10_1) static var KEYNAME_HOME : String; - @:require(flash10_1) static var KEYNAME_INSERT : String; - @:require(flash10_1) static var KEYNAME_INSERTCHAR : String; - @:require(flash10_1) static var KEYNAME_INSERTLINE : String; - @:require(flash10_1) static var KEYNAME_LEFTARROW : String; - @:require(flash10_1) static var KEYNAME_MENU : String; - @:require(flash10_1) static var KEYNAME_MODESWITCH : String; - @:require(flash10_1) static var KEYNAME_NEXT : String; - @:require(flash10_1) static var KEYNAME_PAGEDOWN : String; - @:require(flash10_1) static var KEYNAME_PAGEUP : String; - @:require(flash10_1) static var KEYNAME_PAUSE : String; - @:require(flash10_1) static var KEYNAME_PREV : String; - @:require(flash10_1) static var KEYNAME_PRINT : String; - @:require(flash10_1) static var KEYNAME_PRINTSCREEN : String; - @:require(flash10_1) static var KEYNAME_REDO : String; - @:require(flash10_1) static var KEYNAME_RESET : String; - @:require(flash10_1) static var KEYNAME_RIGHTARROW : String; - @:require(flash10_1) static var KEYNAME_SCROLLLOCK : String; - @:require(flash10_1) static var KEYNAME_SELECT : String; - @:require(flash10_1) static var KEYNAME_STOP : String; - @:require(flash10_1) static var KEYNAME_SYSREQ : String; - @:require(flash10_1) static var KEYNAME_SYSTEM : String; - @:require(flash10_1) static var KEYNAME_UNDO : String; - @:require(flash10_1) static var KEYNAME_UPARROW : String; - @:require(flash10_1) static var KEYNAME_USER : String; - @:require(flash10_1) static var L : UInt; - @:require(flash10_2) static var LAST : UInt; - static var LEFT : UInt; - @:require(flash10_1) static var LEFTBRACKET : UInt; - @:require(flash10_2) static var LIVE : UInt; - @:require(flash10_1) static var M : UInt; - @:require(flash10_2) static var MASTER_SHELL : UInt; - @:require(flash10_2) static var MENU : UInt; - @:require(flash10_1) static var MINUS : UInt; - @:require(flash10_1) static var N : UInt; - @:require(flash10_2) static var NEXT : UInt; - @:require(flash10_1) static var NUMBER_0 : UInt; - @:require(flash10_1) static var NUMBER_1 : UInt; - @:require(flash10_1) static var NUMBER_2 : UInt; - @:require(flash10_1) static var NUMBER_3 : UInt; - @:require(flash10_1) static var NUMBER_4 : UInt; - @:require(flash10_1) static var NUMBER_5 : UInt; - @:require(flash10_1) static var NUMBER_6 : UInt; - @:require(flash10_1) static var NUMBER_7 : UInt; - @:require(flash10_1) static var NUMBER_8 : UInt; - @:require(flash10_1) static var NUMBER_9 : UInt; - @:require(flash10_1) static var NUMPAD : UInt; - static var NUMPAD_0 : UInt; - static var NUMPAD_1 : UInt; - static var NUMPAD_2 : UInt; - static var NUMPAD_3 : UInt; - static var NUMPAD_4 : UInt; - static var NUMPAD_5 : UInt; - static var NUMPAD_6 : UInt; - static var NUMPAD_7 : UInt; - static var NUMPAD_8 : UInt; - static var NUMPAD_9 : UInt; - static var NUMPAD_ADD : UInt; - static var NUMPAD_DECIMAL : UInt; - static var NUMPAD_DIVIDE : UInt; - static var NUMPAD_ENTER : UInt; - static var NUMPAD_MULTIPLY : UInt; - static var NUMPAD_SUBTRACT : UInt; - @:require(flash10_1) static var O : UInt; - @:require(flash10_1) static var P : UInt; - static var PAGE_DOWN : UInt; - static var PAGE_UP : UInt; - @:require(flash10_2) static var PAUSE : UInt; - @:require(flash10_1) static var PERIOD : UInt; - @:require(flash10_2) static var PLAY : UInt; - @:require(flash10_2) static var PREVIOUS : UInt; - @:require(flash10_1) static var Q : UInt; - @:require(flash10_1) static var QUOTE : UInt; - @:require(flash10_1) static var R : UInt; - @:require(flash10_2) static var RECORD : UInt; - @:require(flash10_2) static var RED : UInt; - @:require(flash10_2) static var REWIND : UInt; - static var RIGHT : UInt; - @:require(flash10_1) static var RIGHTBRACKET : UInt; - @:require(flash10_1) static var S : UInt; - @:require(flash10_2) static var SEARCH : UInt; - @:require(flash10_1) static var SEMICOLON : UInt; - @:require(flash10_2) static var SETUP : UInt; - static var SHIFT : UInt; - @:require(flash10_2) static var SKIP_BACKWARD : UInt; - @:require(flash10_2) static var SKIP_FORWARD : UInt; - @:require(flash10_1) static var SLASH : UInt; - static var SPACE : UInt; - @:require(flash10_2) static var STOP : UInt; - @:require(flash10_1) static var STRING_BEGIN : String; - @:require(flash10_1) static var STRING_BREAK : String; - @:require(flash10_1) static var STRING_CLEARDISPLAY : String; - @:require(flash10_1) static var STRING_CLEARLINE : String; - @:require(flash10_1) static var STRING_DELETE : String; - @:require(flash10_1) static var STRING_DELETECHAR : String; - @:require(flash10_1) static var STRING_DELETELINE : String; - @:require(flash10_1) static var STRING_DOWNARROW : String; - @:require(flash10_1) static var STRING_END : String; - @:require(flash10_1) static var STRING_EXECUTE : String; - @:require(flash10_1) static var STRING_F1 : String; - @:require(flash10_1) static var STRING_F10 : String; - @:require(flash10_1) static var STRING_F11 : String; - @:require(flash10_1) static var STRING_F12 : String; - @:require(flash10_1) static var STRING_F13 : String; - @:require(flash10_1) static var STRING_F14 : String; - @:require(flash10_1) static var STRING_F15 : String; - @:require(flash10_1) static var STRING_F16 : String; - @:require(flash10_1) static var STRING_F17 : String; - @:require(flash10_1) static var STRING_F18 : String; - @:require(flash10_1) static var STRING_F19 : String; - @:require(flash10_1) static var STRING_F2 : String; - @:require(flash10_1) static var STRING_F20 : String; - @:require(flash10_1) static var STRING_F21 : String; - @:require(flash10_1) static var STRING_F22 : String; - @:require(flash10_1) static var STRING_F23 : String; - @:require(flash10_1) static var STRING_F24 : String; - @:require(flash10_1) static var STRING_F25 : String; - @:require(flash10_1) static var STRING_F26 : String; - @:require(flash10_1) static var STRING_F27 : String; - @:require(flash10_1) static var STRING_F28 : String; - @:require(flash10_1) static var STRING_F29 : String; - @:require(flash10_1) static var STRING_F3 : String; - @:require(flash10_1) static var STRING_F30 : String; - @:require(flash10_1) static var STRING_F31 : String; - @:require(flash10_1) static var STRING_F32 : String; - @:require(flash10_1) static var STRING_F33 : String; - @:require(flash10_1) static var STRING_F34 : String; - @:require(flash10_1) static var STRING_F35 : String; - @:require(flash10_1) static var STRING_F4 : String; - @:require(flash10_1) static var STRING_F5 : String; - @:require(flash10_1) static var STRING_F6 : String; - @:require(flash10_1) static var STRING_F7 : String; - @:require(flash10_1) static var STRING_F8 : String; - @:require(flash10_1) static var STRING_F9 : String; - @:require(flash10_1) static var STRING_FIND : String; - @:require(flash10_1) static var STRING_HELP : String; - @:require(flash10_1) static var STRING_HOME : String; - @:require(flash10_1) static var STRING_INSERT : String; - @:require(flash10_1) static var STRING_INSERTCHAR : String; - @:require(flash10_1) static var STRING_INSERTLINE : String; - @:require(flash10_1) static var STRING_LEFTARROW : String; - @:require(flash10_1) static var STRING_MENU : String; - @:require(flash10_1) static var STRING_MODESWITCH : String; - @:require(flash10_1) static var STRING_NEXT : String; - @:require(flash10_1) static var STRING_PAGEDOWN : String; - @:require(flash10_1) static var STRING_PAGEUP : String; - @:require(flash10_1) static var STRING_PAUSE : String; - @:require(flash10_1) static var STRING_PREV : String; - @:require(flash10_1) static var STRING_PRINT : String; - @:require(flash10_1) static var STRING_PRINTSCREEN : String; - @:require(flash10_1) static var STRING_REDO : String; - @:require(flash10_1) static var STRING_RESET : String; - @:require(flash10_1) static var STRING_RIGHTARROW : String; - @:require(flash10_1) static var STRING_SCROLLLOCK : String; - @:require(flash10_1) static var STRING_SELECT : String; - @:require(flash10_1) static var STRING_STOP : String; - @:require(flash10_1) static var STRING_SYSREQ : String; - @:require(flash10_1) static var STRING_SYSTEM : String; - @:require(flash10_1) static var STRING_UNDO : String; - @:require(flash10_1) static var STRING_UPARROW : String; - @:require(flash10_1) static var STRING_USER : String; - @:require(flash10_2) static var SUBTITLE : UInt; - @:require(flash10_1) static var T : UInt; - static var TAB : UInt; - @:require(flash10_1) static var U : UInt; - static var UP : UInt; - @:require(flash10_1) static var V : UInt; - @:require(flash10_2) static var VOD : UInt; - @:require(flash10_1) static var W : UInt; - @:require(flash10_1) static var X : UInt; - @:require(flash10_1) static var Y : UInt; - @:require(flash10_2) static var YELLOW : UInt; - @:require(flash10_1) static var Z : UInt; - static var capsLock(default,null) : Bool; - @:require(flash10_1) static var hasVirtualKeyboard(default,null) : Bool; - static var numLock(default,null) : Bool; - @:require(flash10_1) static var physicalKeyboardType(default,null) : KeyboardType; + @:require(flash10_1) static var A(default,never) : UInt; + @:require(flash10_1) static var ALTERNATE(default,never) : UInt; + @:require(flash10_2) static var AUDIO(default,never) : UInt; + @:require(flash10_1) static var B(default,never) : UInt; + @:require(flash10_2) static var BACK(default,never) : UInt; + @:require(flash10_1) static var BACKQUOTE(default,never) : UInt; + @:require(flash10_1) static var BACKSLASH(default,never) : UInt; + static var BACKSPACE(default,never) : UInt; + @:require(flash10_2) static var BLUE(default,never) : UInt; + @:require(flash10_1) static var C(default,never) : UInt; + static var CAPS_LOCK(default,never) : UInt; + @:require(flash10_2) static var CHANNEL_DOWN(default,never) : UInt; + @:require(flash10_2) static var CHANNEL_UP(default,never) : UInt; + @:require(flash10_1) static var COMMA(default,never) : UInt; + @:require(flash10_1) static var COMMAND(default,never) : UInt; + static var CONTROL(default,never) : UInt; + @:require(flash10_1) static var CharCodeStrings(default,never) : Array; + @:require(flash10_1) static var D(default,never) : UInt; + static var DELETE(default,never) : UInt; + static var DOWN(default,never) : UInt; + @:require(flash10_2) static var DVR(default,never) : UInt; + @:require(flash10_1) static var E(default,never) : UInt; + static var END(default,never) : UInt; + static var ENTER(default,never) : UInt; + @:require(flash10_1) static var EQUAL(default,never) : UInt; + static var ESCAPE(default,never) : UInt; + @:require(flash10_2) static var EXIT(default,never) : UInt; + @:require(flash10_1) static var F(default,never) : UInt; + static var F1(default,never) : UInt; + static var F10(default,never) : UInt; + static var F11(default,never) : UInt; + static var F12(default,never) : UInt; + static var F13(default,never) : UInt; + static var F14(default,never) : UInt; + static var F15(default,never) : UInt; + static var F2(default,never) : UInt; + static var F3(default,never) : UInt; + static var F4(default,never) : UInt; + static var F5(default,never) : UInt; + static var F6(default,never) : UInt; + static var F7(default,never) : UInt; + static var F8(default,never) : UInt; + static var F9(default,never) : UInt; + @:require(flash10_2) static var FAST_FORWARD(default,never) : UInt; + @:require(flash10_1) static var G(default,never) : UInt; + @:require(flash10_2) static var GREEN(default,never) : UInt; + @:require(flash10_2) static var GUIDE(default,never) : UInt; + @:require(flash10_1) static var H(default,never) : UInt; + @:require(flash10_2) static var HELP(default,never) : UInt; + static var HOME(default,never) : UInt; + @:require(flash10_1) static var I(default,never) : UInt; + @:require(flash10_2) static var INFO(default,never) : UInt; + @:require(flash10_2) static var INPUT(default,never) : UInt; + static var INSERT(default,never) : UInt; + @:require(flash10_1) static var J(default,never) : UInt; + @:require(flash10_1) static var K(default,never) : UInt; + @:require(flash10_1) static var KEYNAME_BEGIN(default,never) : String; + @:require(flash10_1) static var KEYNAME_BREAK(default,never) : String; + @:require(flash10_1) static var KEYNAME_CLEARDISPLAY(default,never) : String; + @:require(flash10_1) static var KEYNAME_CLEARLINE(default,never) : String; + @:require(flash10_1) static var KEYNAME_DELETE(default,never) : String; + @:require(flash10_1) static var KEYNAME_DELETECHAR(default,never) : String; + @:require(flash10_1) static var KEYNAME_DELETELINE(default,never) : String; + @:require(flash10_1) static var KEYNAME_DOWNARROW(default,never) : String; + @:require(flash10_1) static var KEYNAME_END(default,never) : String; + @:require(flash10_1) static var KEYNAME_EXECUTE(default,never) : String; + @:require(flash10_1) static var KEYNAME_F1(default,never) : String; + @:require(flash10_1) static var KEYNAME_F10(default,never) : String; + @:require(flash10_1) static var KEYNAME_F11(default,never) : String; + @:require(flash10_1) static var KEYNAME_F12(default,never) : String; + @:require(flash10_1) static var KEYNAME_F13(default,never) : String; + @:require(flash10_1) static var KEYNAME_F14(default,never) : String; + @:require(flash10_1) static var KEYNAME_F15(default,never) : String; + @:require(flash10_1) static var KEYNAME_F16(default,never) : String; + @:require(flash10_1) static var KEYNAME_F17(default,never) : String; + @:require(flash10_1) static var KEYNAME_F18(default,never) : String; + @:require(flash10_1) static var KEYNAME_F19(default,never) : String; + @:require(flash10_1) static var KEYNAME_F2(default,never) : String; + @:require(flash10_1) static var KEYNAME_F20(default,never) : String; + @:require(flash10_1) static var KEYNAME_F21(default,never) : String; + @:require(flash10_1) static var KEYNAME_F22(default,never) : String; + @:require(flash10_1) static var KEYNAME_F23(default,never) : String; + @:require(flash10_1) static var KEYNAME_F24(default,never) : String; + @:require(flash10_1) static var KEYNAME_F25(default,never) : String; + @:require(flash10_1) static var KEYNAME_F26(default,never) : String; + @:require(flash10_1) static var KEYNAME_F27(default,never) : String; + @:require(flash10_1) static var KEYNAME_F28(default,never) : String; + @:require(flash10_1) static var KEYNAME_F29(default,never) : String; + @:require(flash10_1) static var KEYNAME_F3(default,never) : String; + @:require(flash10_1) static var KEYNAME_F30(default,never) : String; + @:require(flash10_1) static var KEYNAME_F31(default,never) : String; + @:require(flash10_1) static var KEYNAME_F32(default,never) : String; + @:require(flash10_1) static var KEYNAME_F33(default,never) : String; + @:require(flash10_1) static var KEYNAME_F34(default,never) : String; + @:require(flash10_1) static var KEYNAME_F35(default,never) : String; + @:require(flash10_1) static var KEYNAME_F4(default,never) : String; + @:require(flash10_1) static var KEYNAME_F5(default,never) : String; + @:require(flash10_1) static var KEYNAME_F6(default,never) : String; + @:require(flash10_1) static var KEYNAME_F7(default,never) : String; + @:require(flash10_1) static var KEYNAME_F8(default,never) : String; + @:require(flash10_1) static var KEYNAME_F9(default,never) : String; + @:require(flash10_1) static var KEYNAME_FIND(default,never) : String; + @:require(flash10_1) static var KEYNAME_HELP(default,never) : String; + @:require(flash10_1) static var KEYNAME_HOME(default,never) : String; + @:require(flash10_1) static var KEYNAME_INSERT(default,never) : String; + @:require(flash10_1) static var KEYNAME_INSERTCHAR(default,never) : String; + @:require(flash10_1) static var KEYNAME_INSERTLINE(default,never) : String; + @:require(flash10_1) static var KEYNAME_LEFTARROW(default,never) : String; + @:require(flash10_1) static var KEYNAME_MENU(default,never) : String; + @:require(flash10_1) static var KEYNAME_MODESWITCH(default,never) : String; + @:require(flash10_1) static var KEYNAME_NEXT(default,never) : String; + @:require(flash10_1) static var KEYNAME_PAGEDOWN(default,never) : String; + @:require(flash10_1) static var KEYNAME_PAGEUP(default,never) : String; + @:require(flash10_1) static var KEYNAME_PAUSE(default,never) : String; + @:require(flash10_1) static var KEYNAME_PREV(default,never) : String; + @:require(flash10_1) static var KEYNAME_PRINT(default,never) : String; + @:require(flash10_1) static var KEYNAME_PRINTSCREEN(default,never) : String; + @:require(flash10_1) static var KEYNAME_REDO(default,never) : String; + @:require(flash10_1) static var KEYNAME_RESET(default,never) : String; + @:require(flash10_1) static var KEYNAME_RIGHTARROW(default,never) : String; + @:require(flash10_1) static var KEYNAME_SCROLLLOCK(default,never) : String; + @:require(flash10_1) static var KEYNAME_SELECT(default,never) : String; + @:require(flash10_1) static var KEYNAME_STOP(default,never) : String; + @:require(flash10_1) static var KEYNAME_SYSREQ(default,never) : String; + @:require(flash10_1) static var KEYNAME_SYSTEM(default,never) : String; + @:require(flash10_1) static var KEYNAME_UNDO(default,never) : String; + @:require(flash10_1) static var KEYNAME_UPARROW(default,never) : String; + @:require(flash10_1) static var KEYNAME_USER(default,never) : String; + @:require(flash10_1) static var L(default,never) : UInt; + @:require(flash10_2) static var LAST(default,never) : UInt; + static var LEFT(default,never) : UInt; + @:require(flash10_1) static var LEFTBRACKET(default,never) : UInt; + @:require(flash10_2) static var LIVE(default,never) : UInt; + @:require(flash10_1) static var M(default,never) : UInt; + @:require(flash10_2) static var MASTER_SHELL(default,never) : UInt; + @:require(flash10_2) static var MENU(default,never) : UInt; + @:require(flash10_1) static var MINUS(default,never) : UInt; + @:require(flash10_1) static var N(default,never) : UInt; + @:require(flash10_2) static var NEXT(default,never) : UInt; + @:require(flash10_1) static var NUMBER_0(default,never) : UInt; + @:require(flash10_1) static var NUMBER_1(default,never) : UInt; + @:require(flash10_1) static var NUMBER_2(default,never) : UInt; + @:require(flash10_1) static var NUMBER_3(default,never) : UInt; + @:require(flash10_1) static var NUMBER_4(default,never) : UInt; + @:require(flash10_1) static var NUMBER_5(default,never) : UInt; + @:require(flash10_1) static var NUMBER_6(default,never) : UInt; + @:require(flash10_1) static var NUMBER_7(default,never) : UInt; + @:require(flash10_1) static var NUMBER_8(default,never) : UInt; + @:require(flash10_1) static var NUMBER_9(default,never) : UInt; + @:require(flash10_1) static var NUMPAD(default,never) : UInt; + static var NUMPAD_0(default,never) : UInt; + static var NUMPAD_1(default,never) : UInt; + static var NUMPAD_2(default,never) : UInt; + static var NUMPAD_3(default,never) : UInt; + static var NUMPAD_4(default,never) : UInt; + static var NUMPAD_5(default,never) : UInt; + static var NUMPAD_6(default,never) : UInt; + static var NUMPAD_7(default,never) : UInt; + static var NUMPAD_8(default,never) : UInt; + static var NUMPAD_9(default,never) : UInt; + static var NUMPAD_ADD(default,never) : UInt; + static var NUMPAD_DECIMAL(default,never) : UInt; + static var NUMPAD_DIVIDE(default,never) : UInt; + static var NUMPAD_ENTER(default,never) : UInt; + static var NUMPAD_MULTIPLY(default,never) : UInt; + static var NUMPAD_SUBTRACT(default,never) : UInt; + @:require(flash10_1) static var O(default,never) : UInt; + @:require(flash10_1) static var P(default,never) : UInt; + static var PAGE_DOWN(default,never) : UInt; + static var PAGE_UP(default,never) : UInt; + @:require(flash10_2) static var PAUSE(default,never) : UInt; + @:require(flash10_1) static var PERIOD(default,never) : UInt; + @:require(flash10_2) static var PLAY(default,never) : UInt; + @:require(flash10_2) static var PREVIOUS(default,never) : UInt; + @:require(flash10_1) static var Q(default,never) : UInt; + @:require(flash10_1) static var QUOTE(default,never) : UInt; + @:require(flash10_1) static var R(default,never) : UInt; + @:require(flash10_2) static var RECORD(default,never) : UInt; + @:require(flash10_2) static var RED(default,never) : UInt; + @:require(flash10_2) static var REWIND(default,never) : UInt; + static var RIGHT(default,never) : UInt; + @:require(flash10_1) static var RIGHTBRACKET(default,never) : UInt; + @:require(flash10_1) static var S(default,never) : UInt; + @:require(flash10_2) static var SEARCH(default,never) : UInt; + @:require(flash10_1) static var SEMICOLON(default,never) : UInt; + @:require(flash10_2) static var SETUP(default,never) : UInt; + static var SHIFT(default,never) : UInt; + @:require(flash10_2) static var SKIP_BACKWARD(default,never) : UInt; + @:require(flash10_2) static var SKIP_FORWARD(default,never) : UInt; + @:require(flash10_1) static var SLASH(default,never) : UInt; + static var SPACE(default,never) : UInt; + @:require(flash10_2) static var STOP(default,never) : UInt; + @:require(flash10_1) static var STRING_BEGIN(default,never) : String; + @:require(flash10_1) static var STRING_BREAK(default,never) : String; + @:require(flash10_1) static var STRING_CLEARDISPLAY(default,never) : String; + @:require(flash10_1) static var STRING_CLEARLINE(default,never) : String; + @:require(flash10_1) static var STRING_DELETE(default,never) : String; + @:require(flash10_1) static var STRING_DELETECHAR(default,never) : String; + @:require(flash10_1) static var STRING_DELETELINE(default,never) : String; + @:require(flash10_1) static var STRING_DOWNARROW(default,never) : String; + @:require(flash10_1) static var STRING_END(default,never) : String; + @:require(flash10_1) static var STRING_EXECUTE(default,never) : String; + @:require(flash10_1) static var STRING_F1(default,never) : String; + @:require(flash10_1) static var STRING_F10(default,never) : String; + @:require(flash10_1) static var STRING_F11(default,never) : String; + @:require(flash10_1) static var STRING_F12(default,never) : String; + @:require(flash10_1) static var STRING_F13(default,never) : String; + @:require(flash10_1) static var STRING_F14(default,never) : String; + @:require(flash10_1) static var STRING_F15(default,never) : String; + @:require(flash10_1) static var STRING_F16(default,never) : String; + @:require(flash10_1) static var STRING_F17(default,never) : String; + @:require(flash10_1) static var STRING_F18(default,never) : String; + @:require(flash10_1) static var STRING_F19(default,never) : String; + @:require(flash10_1) static var STRING_F2(default,never) : String; + @:require(flash10_1) static var STRING_F20(default,never) : String; + @:require(flash10_1) static var STRING_F21(default,never) : String; + @:require(flash10_1) static var STRING_F22(default,never) : String; + @:require(flash10_1) static var STRING_F23(default,never) : String; + @:require(flash10_1) static var STRING_F24(default,never) : String; + @:require(flash10_1) static var STRING_F25(default,never) : String; + @:require(flash10_1) static var STRING_F26(default,never) : String; + @:require(flash10_1) static var STRING_F27(default,never) : String; + @:require(flash10_1) static var STRING_F28(default,never) : String; + @:require(flash10_1) static var STRING_F29(default,never) : String; + @:require(flash10_1) static var STRING_F3(default,never) : String; + @:require(flash10_1) static var STRING_F30(default,never) : String; + @:require(flash10_1) static var STRING_F31(default,never) : String; + @:require(flash10_1) static var STRING_F32(default,never) : String; + @:require(flash10_1) static var STRING_F33(default,never) : String; + @:require(flash10_1) static var STRING_F34(default,never) : String; + @:require(flash10_1) static var STRING_F35(default,never) : String; + @:require(flash10_1) static var STRING_F4(default,never) : String; + @:require(flash10_1) static var STRING_F5(default,never) : String; + @:require(flash10_1) static var STRING_F6(default,never) : String; + @:require(flash10_1) static var STRING_F7(default,never) : String; + @:require(flash10_1) static var STRING_F8(default,never) : String; + @:require(flash10_1) static var STRING_F9(default,never) : String; + @:require(flash10_1) static var STRING_FIND(default,never) : String; + @:require(flash10_1) static var STRING_HELP(default,never) : String; + @:require(flash10_1) static var STRING_HOME(default,never) : String; + @:require(flash10_1) static var STRING_INSERT(default,never) : String; + @:require(flash10_1) static var STRING_INSERTCHAR(default,never) : String; + @:require(flash10_1) static var STRING_INSERTLINE(default,never) : String; + @:require(flash10_1) static var STRING_LEFTARROW(default,never) : String; + @:require(flash10_1) static var STRING_MENU(default,never) : String; + @:require(flash10_1) static var STRING_MODESWITCH(default,never) : String; + @:require(flash10_1) static var STRING_NEXT(default,never) : String; + @:require(flash10_1) static var STRING_PAGEDOWN(default,never) : String; + @:require(flash10_1) static var STRING_PAGEUP(default,never) : String; + @:require(flash10_1) static var STRING_PAUSE(default,never) : String; + @:require(flash10_1) static var STRING_PREV(default,never) : String; + @:require(flash10_1) static var STRING_PRINT(default,never) : String; + @:require(flash10_1) static var STRING_PRINTSCREEN(default,never) : String; + @:require(flash10_1) static var STRING_REDO(default,never) : String; + @:require(flash10_1) static var STRING_RESET(default,never) : String; + @:require(flash10_1) static var STRING_RIGHTARROW(default,never) : String; + @:require(flash10_1) static var STRING_SCROLLLOCK(default,never) : String; + @:require(flash10_1) static var STRING_SELECT(default,never) : String; + @:require(flash10_1) static var STRING_STOP(default,never) : String; + @:require(flash10_1) static var STRING_SYSREQ(default,never) : String; + @:require(flash10_1) static var STRING_SYSTEM(default,never) : String; + @:require(flash10_1) static var STRING_UNDO(default,never) : String; + @:require(flash10_1) static var STRING_UPARROW(default,never) : String; + @:require(flash10_1) static var STRING_USER(default,never) : String; + @:require(flash10_2) static var SUBTITLE(default,never) : UInt; + @:require(flash10_1) static var T(default,never) : UInt; + static var TAB(default,never) : UInt; + @:require(flash10_1) static var U(default,never) : UInt; + static var UP(default,never) : UInt; + @:require(flash10_1) static var V(default,never) : UInt; + @:require(flash10_2) static var VOD(default,never) : UInt; + @:require(flash10_1) static var W(default,never) : UInt; + @:require(flash10_1) static var X(default,never) : UInt; + @:require(flash10_1) static var Y(default,never) : UInt; + @:require(flash10_2) static var YELLOW(default,never) : UInt; + @:require(flash10_1) static var Z(default,never) : UInt; + static var capsLock(default,never) : Bool; + @:require(flash10_1) static var hasVirtualKeyboard(default,never) : Bool; + static var numLock(default,never) : Bool; + @:require(flash10_1) static var physicalKeyboardType(default,never) : KeyboardType; static function isAccessible() : Bool; } diff --git a/std/flash/ui/Mouse.hx b/std/flash/ui/Mouse.hx index 030432ac..e9070a8e 100644 --- a/std/flash/ui/Mouse.hx +++ b/std/flash/ui/Mouse.hx @@ -2,8 +2,8 @@ package flash.ui; extern class Mouse { @:require(flash10) static var cursor : Dynamic; - @:require(flash10_1) static var supportsCursor(default,null) : Bool; - @:require(flash11) static var supportsNativeCursor(default,null) : Bool; + @:require(flash10_1) static var supportsCursor(default,never) : Bool; + @:require(flash11) static var supportsNativeCursor(default,never) : Bool; static function hide() : Void; @:require(flash10_2) static function registerCursor(name : String, cursor : MouseCursorData) : Void; static function show() : Void; diff --git a/std/flash/ui/MouseCursor.hx b/std/flash/ui/MouseCursor.hx index 56ce0620..b5e62e6c 100644 --- a/std/flash/ui/MouseCursor.hx +++ b/std/flash/ui/MouseCursor.hx @@ -1,9 +1,9 @@ package flash.ui; extern class MouseCursor { - static var ARROW : String; - static var AUTO : String; - static var BUTTON : String; - static var HAND : String; - static var IBEAM : String; + static var ARROW(default,never) : String; + static var AUTO(default,never) : String; + static var BUTTON(default,never) : String; + static var HAND(default,never) : String; + static var IBEAM(default,never) : String; } diff --git a/std/flash/ui/Multitouch.hx b/std/flash/ui/Multitouch.hx index fc528ce6..c1ae7018 100644 --- a/std/flash/ui/Multitouch.hx +++ b/std/flash/ui/Multitouch.hx @@ -3,8 +3,8 @@ package flash.ui; @:require(flash10_1) extern class Multitouch { static var inputMode : MultitouchInputMode; static var mapTouchToMouse : Bool; - static var maxTouchPoints(default,null) : Int; - static var supportedGestures(default,null) : flash.Vector; - static var supportsGestureEvents(default,null) : Bool; - static var supportsTouchEvents(default,null) : Bool; + static var maxTouchPoints(default,never) : Int; + static var supportedGestures(default,never) : flash.Vector; + static var supportsGestureEvents(default,never) : Bool; + static var supportsTouchEvents(default,never) : Bool; } diff --git a/std/flash/utils/ByteArray.hx b/std/flash/utils/ByteArray.hx index cea65bd2..f9008156 100644 --- a/std/flash/utils/ByteArray.hx +++ b/std/flash/utils/ByteArray.hx @@ -1,7 +1,7 @@ package flash.utils; extern class ByteArray implements IDataOutput2 implements IDataInput2 implements ArrayAccess { - var bytesAvailable(default,null) : UInt; + var bytesAvailable(default,never) : UInt; var endian : Endian; var length : UInt; var objectEncoding : UInt; diff --git a/std/flash/utils/Dictionary.hx b/std/flash/utils/Dictionary.hx index 284dd0b8..0082839b 100644 --- a/std/flash/utils/Dictionary.hx +++ b/std/flash/utils/Dictionary.hx @@ -1,5 +1,5 @@ package flash.utils; -extern class Dictionary implements Dynamic { +extern class Dictionary implements ArrayAccess { function new(weakKeys : Bool = false) : Void; } diff --git a/std/flash/utils/IDataInput.hx b/std/flash/utils/IDataInput.hx index 20ae3fd0..0f51a1c1 100644 --- a/std/flash/utils/IDataInput.hx +++ b/std/flash/utils/IDataInput.hx @@ -1,7 +1,7 @@ package flash.utils; extern interface IDataInput { - var bytesAvailable(default,null) : UInt; + var bytesAvailable(default,never) : UInt; var endian : Endian; var objectEncoding : UInt; function readBoolean() : Bool; diff --git a/std/flash/utils/Namespace.hx b/std/flash/utils/Namespace.hx index 61f8a286..8531ba90 100644 --- a/std/flash/utils/Namespace.hx +++ b/std/flash/utils/Namespace.hx @@ -1,7 +1,7 @@ package flash.utils; @:final extern class Namespace { - var prefix(default,null) : Dynamic; - var uri(default,null) : String; + var prefix(default,never) : Dynamic; + var uri(default,never) : String; function new(?prefix : Dynamic, ?uri : Dynamic) : Void; } diff --git a/std/flash/utils/ObjectInput.hx b/std/flash/utils/ObjectInput.hx index f8a88155..871a009e 100644 --- a/std/flash/utils/ObjectInput.hx +++ b/std/flash/utils/ObjectInput.hx @@ -1,7 +1,7 @@ package flash.utils; extern class ObjectInput implements IDataInput { - var bytesAvailable(default,null) : UInt; + var bytesAvailable(default,never) : UInt; var endian : Endian; var objectEncoding : UInt; function new() : Void; diff --git a/std/flash/utils/QName.hx b/std/flash/utils/QName.hx index 1953436c..bf5a4ef9 100644 --- a/std/flash/utils/QName.hx +++ b/std/flash/utils/QName.hx @@ -1,7 +1,7 @@ package flash.utils; @:final extern class QName { - var localName(default,null) : String; - var uri(default,null) : Dynamic; + var localName(default,never) : String; + var uri(default,never) : Dynamic; function new(?namespace : Dynamic, ?name : Dynamic) : Void; } diff --git a/std/flash/utils/RegExp.hx b/std/flash/utils/RegExp.hx index de7e83c1..26b01c3d 100644 --- a/std/flash/utils/RegExp.hx +++ b/std/flash/utils/RegExp.hx @@ -1,13 +1,13 @@ package flash.utils; -@:native("RegExp") extern class RegExp implements Dynamic { - var dotall(default,null) : Bool; - var extended(default,null) : Bool; - var global(default,null) : Bool; - var ignoreCase(default,null) : Bool; +@:realPath("flash.utils.RegExp") @:native("RegExp") extern class RegExp implements Dynamic { + var dotall(default,never) : Bool; + var extended(default,never) : Bool; + var global(default,never) : Bool; + var ignoreCase(default,never) : Bool; var lastIndex : Int; - var multiline(default,null) : Bool; - var source(default,null) : String; + var multiline(default,never) : Bool; + var source(default,never) : String; function new(?pattern : Dynamic, ?options : Dynamic) : Void; @:ns("http://adobe.com/AS3/2006/builtin") function exec(?s : String) : Dynamic; @:ns("http://adobe.com/AS3/2006/builtin") function test(?s : String) : Bool; diff --git a/std/flash/utils/Timer.hx b/std/flash/utils/Timer.hx index 5610b6e3..728f9c5c 100644 --- a/std/flash/utils/Timer.hx +++ b/std/flash/utils/Timer.hx @@ -1,10 +1,10 @@ package flash.utils; extern class Timer extends flash.events.EventDispatcher { - var currentCount(default,null) : Int; + var currentCount(default,never) : Int; var delay : Float; var repeatCount : Int; - var running(default,null) : Bool; + var running(default,never) : Bool; function new(delay : Float, repeatCount : Int = 0) : Void; function reset() : Void; function start() : Void; diff --git a/std/flash/xml/XMLNode.hx b/std/flash/xml/XMLNode.hx index 4262af22..4dc45a57 100644 --- a/std/flash/xml/XMLNode.hx +++ b/std/flash/xml/XMLNode.hx @@ -2,17 +2,17 @@ package flash.xml; extern class XMLNode { var attributes : Dynamic; - var childNodes(default,null) : Array; + var childNodes(default,never) : Array; var firstChild : XMLNode; var lastChild : XMLNode; - var localName(default,null) : String; - var namespaceURI(default,null) : String; + var localName(default,never) : String; + var namespaceURI(default,never) : String; var nextSibling : XMLNode; var nodeName : String; var nodeType : XMLNodeType; var nodeValue : String; var parentNode : XMLNode; - var prefix(default,null) : String; + var prefix(default,never) : String; var previousSibling : XMLNode; function new(type : XMLNodeType, value : String) : Void; function appendChild(node : XMLNode) : Void; diff --git a/std/haxe/CallStack.hx b/std/haxe/CallStack.hx index 6ec69a67..782eb56e 100644 --- a/std/haxe/CallStack.hx +++ b/std/haxe/CallStack.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -126,22 +126,47 @@ class CallStack { for (elem in infos) stack.push(FilePos(null, elem._1, elem._2)); return stack; + #elseif lua + var stack = []; + var infos = lua.Debug.traceback(); + var luastack = infos.split("\n").slice(2,-1); + for (s in luastack){ + var parts = s.split(":"); + var file = parts[0]; + var line = parts[1]; + // TODO: Give more information for FilePos + stack.push(FilePos(null, file, Std.parseInt(line))); + } + return stack; + #elseif hl + try { + throw null; + } catch( e : Dynamic ) { + var st = _getExceptionStack(); + return makeStack(st.length > 2 ? st.sub(2,st.length - 2) : st); + } #else return []; // Unsupported #end } + #if hl + @:hlNative("std", "exception_stack") static function _getExceptionStack() : hl.NativeArray { return null; } + #end + /** Return the exception stack : this is the stack elements between the place the last exception was thrown and the place it was caught, or an empty array if not available. **/ - #if cpp @:noStack #end /* Do not mess up the exception stack */ + #if cpp @:noDebug #end /* Do not mess up the exception stack */ public static function exceptionStack() : Array { #if neko return makeStack(untyped __dollar__excstack()); #elseif as3 return new Array(); + #elseif hl + return makeStack(_getExceptionStack()); #elseif flash var err : flash.errors.Error = untyped flash.Boot.lastError; if( err == null ) return new Array(); @@ -238,8 +263,8 @@ class CallStack { } } - #if cpp @:noStack #end /* Do not mess up the exception stack */ - private static function makeStack(s #if cs : cs.system.diagnostics.StackTrace #end) { + #if cpp @:noDebug #end /* Do not mess up the exception stack */ + private static function makeStack(s #if cs : cs.system.diagnostics.StackTrace #elseif hl : hl.NativeArray #end) { #if neko var a = new Array(); var l = untyped __dollar__asize(s); @@ -328,6 +353,9 @@ class CallStack { var frame = s.GetFrame(i); var m = frame.GetMethod(); + if (m == null) { + continue; + } var method = StackItem.Method(m.ReflectedType.ToString(), m.Name); var fileName = frame.GetFileName(); @@ -339,6 +367,17 @@ class CallStack { stack.push(method); } return stack; + #elseif hl + var stack = []; + var r = ~/^([A-Za-z0-9.$_]+)\.([A-Za-z0-9_]+)\((.+):([0-9]+)\)$/; + for( i in 0...s.length-1 ) { + var str = @:privateAccess String.fromUCS2(s[i]); + if( r.match(str) ) + stack.push(FilePos(Method(r.matched(1), r.matched(2)), r.matched(3), Std.parseInt(r.matched(4)))); + else + stack.push(Module(str)); + } + return stack; #else return null; #end diff --git a/std/haxe/Constraints.hx b/std/haxe/Constraints.hx index 28dad939..8d18b569 100644 --- a/std/haxe/Constraints.hx +++ b/std/haxe/Constraints.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -40,6 +40,21 @@ abstract Function(Dynamic) { } **/ abstract FlatEnum(Dynamic) { } +/** + This type unifies with any instance of classes that have a constructor + which + * is public and + * unifies with the type used for type parameter `T`. + + If a type parameter A is assigned to a type parameter B which is constrained + to `Constructible`, A must be explicitly constrained to + `Constructible` as well. + + It is intended to be used as a type parameter constraint. If used as a real + type, the underlying type will be `Dynamic`. +**/ +abstract Constructible(Dynamic) { } + interface IMap { public function get(k:K):Null; public function set(k:K, v:V):Void; diff --git a/std/haxe/DynamicAccess.hx b/std/haxe/DynamicAccess.hx index e45d7775..64924d71 100644 --- a/std/haxe/DynamicAccess.hx +++ b/std/haxe/DynamicAccess.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/EntryPoint.hx b/std/haxe/EntryPoint.hx new file mode 100644 index 00000000..fafafa26 --- /dev/null +++ b/std/haxe/EntryPoint.hx @@ -0,0 +1,147 @@ +package haxe; + +#if (neko && !macro && !interp) +import neko.vm.Lock; +import neko.vm.Mutex; +import neko.vm.Thread; +#elseif cpp +import cpp.vm.Lock; +import cpp.vm.Mutex; +import cpp.vm.Thread; +#elseif java +import java.vm.Lock; +import java.vm.Mutex; +import java.vm.Thread; +#elseif sys +private class Lock { + public function new() { + } + public inline function release() { + } + public inline function wait( ?t : Float ) { + } +} +private class Mutex { + public function new() { + } + public inline function acquire() { + } + public inline function release() { + } +} +private class Thread { + public static function create( f : Void -> Void ) { + f(); + } +} +#end + +/** + If haxe.MainLoop is kept from DCE, then we will insert an haxe.EntryPoint.run() call just at then end of main(). + This class can be redefined by custom frameworks so they can handle their own main loop logic. +**/ +class EntryPoint { + + #if sys + static var sleepLock = new Lock(); + static var mutex = new Mutex(); + #end + static var pending = new ArrayVoid>(); + + public static var threadCount(default,null) : Int = 0; + + /** + Wakeup a sleeping run() + **/ + public static function wakeup() { + #if sys + sleepLock.release(); + #end + } + + public static function runInMainThread( f : Void -> Void ) { + #if sys + mutex.acquire(); + pending.push(f); + mutex.release(); + wakeup(); + #else + pending.push(f); + #end + } + + public static function addThread( f : Void -> Void ) { + #if sys + mutex.acquire(); + threadCount++; + mutex.release(); + Thread.create(function() { + f(); + mutex.acquire(); + threadCount--; + if( threadCount == 0 ) wakeup(); + mutex.release(); + }); + #else + threadCount++; + pending.push(function() { f(); threadCount--; } ); + #end + } + + static function processEvents() : Float { + // flush all pending calls + while( true ) { + #if sys + mutex.acquire(); + var f = pending.shift(); + mutex.release(); + #else + var f = pending.shift(); + #end + if( f == null ) break; + f(); + } + if( !MainLoop.hasEvents() && threadCount == 0 ) + return -1; + return @:privateAccess MainLoop.tick(); + } + + /** + Start the main loop. Depending on the platform, this can return immediately or will only return when the application exits. + **/ + @:keep public static function run() @:privateAccess { + #if js + + var nextTick = processEvents(); + + #if nodejs + if( nextTick < 0 ) + return; + (untyped setTimeout)(run,nextTick); + #else + var window : Dynamic = js.Browser.window; + var rqf : Dynamic = window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame; + rqf(run); + #end + + #elseif flash + + flash.Lib.current.stage.addEventListener(flash.events.Event.ENTER_FRAME, function(_) processEvents()); + + #elseif sys + while( true ) { + var nextTick = processEvents(); + if( nextTick < 0 ) + break; + if( nextTick > 0 ) + sleepLock.wait(nextTick); // wait until nextTick or wakeup() call + } + #else + + // no implementation available, let's exit immediately + + #end + } +} diff --git a/std/haxe/EnumFlags.hx b/std/haxe/EnumFlags.hx index 5e2feb34..0ed52891 100644 --- a/std/haxe/EnumFlags.hx +++ b/std/haxe/EnumFlags.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,7 +26,7 @@ package haxe; interface for an actual Int. Each flag can be tested/set with the corresponding enum instance. Up to 32 flags can be stored that way. - Enum constructor indices are preserved from haxe syntax, so the first + Enum constructor indices are preserved from Haxe syntax, so the first declared is index 0, the next index 1 etc. The methods are optimized if the enum instance is passed directly, e.g. as has(EnumCtor). Otherwise Type.enumIndex() reflection is used. diff --git a/std/haxe/EnumTools.hx b/std/haxe/EnumTools.hx index caa6c908..93129ee6 100644 --- a/std/haxe/EnumTools.hx +++ b/std/haxe/EnumTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,6 +22,15 @@ package haxe; +/** + This class provides advanced methods on enums. It is ideally used with + `using EnumTools` and then acts as an + [extension](https://haxe.org/manual/lf-static-extension.html) to the + `enum` types. + + If the first argument to any of the methods is null, the result is + unspecified. +**/ extern class EnumTools { /** Returns the name of enum `e`, including its path. @@ -29,12 +38,12 @@ extern class EnumTools { If `e` is inside a package, the package structure is returned dot- separated, with another dot separating the enum name: pack1.pack2.(...).packN.EnumName - If `e` is a sub-type of a haxe module, that module is not part of the + If `e` is a sub-type of a Haxe module, that module is not part of the package structure. If `e` has no package, the enum name is returned. - If `e` is null, the result is unspecified. + If `e` is `null`, the result is unspecified. The enum name does not include any type parameters. **/ @@ -46,7 +55,7 @@ extern class EnumTools { Creates an instance of enum `e` by calling its constructor `constr` with arguments `params`. - If `e` or `constr` is null, or if enum `e` has no constructor named + If `e` or `constr` is `null`, or if enum `e` has no constructor named `constr`, or if the number of elements in `params` does not match the expected number of constructor arguments, or if any argument has an invalid type, the result is unspecified. @@ -59,10 +68,10 @@ extern class EnumTools { Creates an instance of enum `e` by calling its constructor number `index` with arguments `params`. - The constructor indices are preserved from haxe syntax, so the first + The constructor indices are preserved from Haxe syntax, so the first declared is index 0, the next index 1 etc. - If `e` or `index` is null, or if enum `e` has no constructor + If `e` or `index` is `null`, or if enum `e` has no constructor corresponding to index `index`, or if the number of elements in `params` does not match the expected number of constructor arguments, or if any argument has an invalid type, the result is unspecified. @@ -75,14 +84,14 @@ extern class EnumTools { Returns a list of all constructors of enum `e` that require no arguments. - This may return the empty Array [] if all constructors of `e` require + This may return the empty Array `[]` if all constructors of `e` require arguments. Otherwise an instance of `e` constructed through each of its non- argument constructors is returned, in the order of the constructor declaration. - If `e` is null, the result is unspecified. + If `e` is `null`, the result is unspecified. **/ static public inline function createAll(e:Enum):Array { return Type.allEnums(e); @@ -94,22 +103,31 @@ extern class EnumTools { The order of the constructor names in the returned Array is preserved from the original syntax. - If `c` is null, the result is unspecified. + If `c` is `null`, the result is unspecified. **/ static public inline function getConstructors(e:Enum):Array { return Type.getEnumConstructs(e); } } +/** + This class provides advanced methods on enum values. It is ideally used with + `using EnumValueTools` and then acts as an + [extension](https://haxe.org/manual/lf-static-extension.html) to the + `EnumValue` types. + + If the first argument to any of the methods is null, the result is + unspecified. +**/ extern class EnumValueTools { /** Recursively compares two enum instances `a` and `b` by value. Unlike `a == b`, this function performs a deep equality check on the - arguments of the constructors, if exists. + arguments of the constructors (if there are any). - If `a` or `b` are null, the result is unspecified. + If `a` or `b` are `null`, the result is unspecified. **/ static public inline function equals(a:T, b:T):Bool { return Type.enumEq(a, b); @@ -120,7 +138,7 @@ extern class EnumValueTools { The result String does not contain any constructor arguments. - If `e` is null, the result is unspecified. + If `e` is `null`, the result is unspecified. **/ static public inline function getName(e:EnumValue):String { return Type.enumConstructor(e); @@ -129,12 +147,12 @@ extern class EnumValueTools { /** Returns a list of the constructor arguments of enum instance `e`. - If `e` has no arguments, the result is []. + If `e` has no arguments, the result is `[]`. Otherwise the result are the values that were used as arguments to `e`, in the order of their declaration. - If `e` is null, the result is unspecified. + If `e` is `null`, the result is unspecified. **/ static public inline function getParameters(e:EnumValue):Array { return Type.enumParameters(e); @@ -146,19 +164,19 @@ extern class EnumValueTools { This corresponds to the original syntactic position of `e`. The index of the first declared constructor is 0, the next one is 1 etc. - If `e` is null, the result is unspecified. + If `e` is `null`, the result is unspecified. **/ static public inline function getIndex(e:EnumValue):Int { return Type.enumIndex(e); } /** - Matches enum instance `e` against pattern `pattern`, returning true if - matching succeeded and false otherwise. + Matches enum instance `e` against pattern `pattern`, returning `true` if + matching succeeded and `false` otherwise. Example usage: - ``` + ```haxe if (e.match(pattern)) { // codeIfTrue } else { @@ -168,7 +186,7 @@ extern class EnumValueTools { This is equivalent to the following code: - ``` + ```haxe switch (e) { case pattern: // codeIfTrue @@ -183,4 +201,4 @@ extern class EnumValueTools { static public function match(e:EnumValue, pattern:Dynamic):Bool { return false; } -} \ No newline at end of file +} diff --git a/std/haxe/Http.hx b/std/haxe/Http.hx index ac363300..f104502a 100644 --- a/std/haxe/Http.hx +++ b/std/haxe/Http.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,31 +26,21 @@ package haxe; import sys.net.Host; import sys.net.Socket; -private typedef AbstractSocket = { - var input(default,null) : haxe.io.Input; - var output(default,null) : haxe.io.Output; - function connect( host : Host, port : Int ) : Void; - function setTimeout( t : Float ) : Void; - function write( str : String ) : Void; - function close() : Void; - function shutdown( read : Bool, write : Bool ) : Void; -} - #end /** This class can be used to handle Http requests consistently across platforms. There are two intended usages: - - call haxe.Http.requestUrl(url) and receive the result as a String (not - available on flash) - - create a new haxe.Http(url), register your callbacks for onData, onError - and onStatus, then call request(). + - call `haxe.Http.requestUrl(url)` and receive the result as a `String` + (not available on flash) + - create a `new haxe.Http(url)`, register your callbacks for `onData`, + `onError` and `onStatus`, then call `request()`. **/ class Http { /** - The url of `this` request. It is used only by the request() method and + The url of `this` request. It is used only by the `request()` method and can be changed in order to send the same request to different target Urls. **/ @@ -63,8 +53,9 @@ class Http { var chunk_size : Null; var chunk_buf : haxe.io.Bytes; var file : { param : String, filename : String, io : haxe.io.Input, size : Int, mimeType : String }; -#elseif js +#elseif (js && !nodejs) public var async : Bool; + public var withCredentials : Bool; #end var postData : String; var headers : List<{ header:String, value:String }>; @@ -77,10 +68,10 @@ class Http { /** Creates a new Http instance with `url` as parameter. - This does not do a request until request() is called. + This does not do a request until `request()` is called. If `url` is null, the field url must be set to a value before making the - call to request(), or the result is unspecified. + call to `request()`, or the result is unspecified. (Php) Https (SSL) connections are allowed only if the OpenSSL extension is enabled. @@ -90,8 +81,9 @@ class Http { headers = new List<{ header:String, value:String }>(); params = new List<{ param:String, value:String }>(); - #if js + #if (js && !nodejs) async = true; + withCredentials = false; #elseif sys cnxTimeout = 10; #end @@ -153,7 +145,9 @@ class Http { #if (js || flash) - #if js + #if nodejs + var req:js.node.http.ClientRequest; + #elseif js var req:js.html.XMLHttpRequest; #elseif flash var req:flash.net.URLLoader; @@ -182,26 +176,85 @@ class Http { sent as GET request. Depending on the outcome of the request, this method calls the - onStatus(), onError() or onData() callback functions. + `onStatus()`, `onError()` or `onData()` callback functions. If `this.url` is null, the result is unspecified. - If `this.url` is an invalid or inaccessible Url, the onError() callback + If `this.url` is an invalid or inaccessible Url, the `onError()` callback function is called. - (Js) If `this.async` is false, the callback functions are called before + [js] If `this.async` is false, the callback functions are called before this method returns. **/ public function request( ?post : Bool ) : Void { var me = this; - #if js + #if nodejs + me.responseData = null; + var parsedUrl = js.node.Url.parse(url); + var secure = (parsedUrl.protocol == "https:"); + var host = parsedUrl.hostname; + var path = parsedUrl.path; + var port = if (parsedUrl.port != null) Std.parseInt(parsedUrl.port) else (secure ? 443 : 80); + var h:Dynamic = {}; + for (i in headers) { + var arr = Reflect.field(h, i.header); + if (arr == null) { + arr = new Array(); + Reflect.setField(h, i.header, arr); + } + + arr.push(i.value); + } + var uri = postData; + if( uri != null ) + post = true; + else for( p in params ) { + if( uri == null ) + uri = ""; + else + uri += "&"; + uri += StringTools.urlEncode(p.param)+"="+StringTools.urlEncode(p.value); + } + var question = path.split("?").length <= 1; + if (!post && uri != null) path += (if( question ) "?" else "&") + uri; + + var opts = { + protocol: parsedUrl.protocol, + hostname: host, + port: port, + method: post ? 'POST' : 'GET', + path: path, + headers: h + }; + function httpResponse (res) { + var s = res.statusCode; + if (s != null) + me.onStatus(s); + var body = ''; + res.on('data', function (d) { + body += d; + }); + res.on('end', function (_) { + me.responseData = body; + me.req = null; + if (s != null && s >= 200 && s < 400) { + me.onData(body); + } else { + me.onError("Http Error #"+s); + } + }); + } + req = secure ? js.node.Https.request(untyped opts, httpResponse) : js.node.Http.request(untyped opts, httpResponse); + if (post) req.write(uri); + req.end(); + #elseif js me.responseData = null; var r = req = js.Browser.createXMLHttpRequest(); var onreadystatechange = function(_) { if( r.readyState != 4 ) return; var s = try r.status catch( e : Dynamic ) null; - if ( s != null ) { + if ( s != null && untyped __js__('"undefined" !== typeof window') ) { // If the request is local and we have data: assume a success (jQuery approach): var protocol = js.Browser.location.protocol.toLowerCase(); var rlocalProtocol = ~/^(?:about|app|app-storage|.+-extension|file|res|widget):$/; @@ -261,6 +314,7 @@ class Http { onError(e.toString()); return; } + r.withCredentials = withCredentials; if( !Lambda.exists(headers, function(h) return h.header == "Content-Type") && post && postData == null ) r.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); @@ -368,7 +422,7 @@ class Http { this.file = { param : argname, filename : filename, io : file, size : size, mimeType : mimeType }; } - public function customRequest( post : Bool, api : haxe.io.Output, ?sock : AbstractSocket, ?method : String ) { + public function customRequest( post : Bool, api : haxe.io.Output, ?sock : sys.net.Socket, ?method : String ) { this.responseData = null; var url_regexp = ~/^(https?:\/\/)?([a-zA-Z\.0-9_-]+)(:[0-9]+)?(.*)$/; if( !url_regexp.match(url) ) { @@ -382,12 +436,8 @@ class Http { sock = new php.net.SslSocket(); #elseif java sock = new java.net.SslSocket(); - #elseif hxssl - #if neko - sock = new neko.tls.Socket(); - #else + #elseif (!no_ssl && (hxssl || hl || cpp || (neko && !(macro || interp)))) sock = new sys.ssl.Socket(); - #end #else throw "Https is only supported with -lib hxssl"; #end @@ -489,6 +539,7 @@ class Http { else b.add("Content-Length: "+uri.length+"\r\n"); } + b.add("Connection: close\r\n"); for( h in headers ) { b.add(h.header); b.add(": "); @@ -531,7 +582,7 @@ class Http { } } - function readHttpResponse( api : haxe.io.Output, sock : AbstractSocket ) { + function readHttpResponse( api : haxe.io.Output, sock : sys.net.Socket ) { // READ the HTTP header (until \r\n\r\n) var b = new haxe.io.BytesBuffer(); var k = 4; @@ -634,17 +685,23 @@ class Http { var bufsize = 1024; var buf = haxe.io.Bytes.alloc(bufsize); - if( size == null ) { + if( chunked ) { + try { + while( true ) { + var len = sock.input.readBytes(buf,0,bufsize); + if( !readChunk(chunk_re,api,buf,len) ) + break; + } + } catch ( e : haxe.io.Eof ) { + throw "Transfer aborted"; + } + } else if( size == null ) { if( !noShutdown ) sock.shutdown(false,true); try { while( true ) { var len = sock.input.readBytes(buf,0,bufsize); - if( chunked ) { - if( !readChunk(chunk_re,api,buf,len) ) - break; - } else - api.writeBytes(buf,0,len); + api.writeBytes(buf,0,len); } } catch( e : haxe.io.Eof ) { } @@ -653,11 +710,7 @@ class Http { try { while( size > 0 ) { var len = sock.input.readBytes(buf,0,if( size > bufsize ) bufsize else size); - if( chunked ) { - if( !readChunk(chunk_re,api,buf,len) ) - break; - } else - api.writeBytes(buf,0,len); + api.writeBytes(buf,0,len); size -= len; } } catch( e : haxe.io.Eof ) { @@ -734,7 +787,7 @@ class Http { This method is called upon a successful request, with `data` containing the result String. - The intended usage is to bind it to a custom function: + The intended usage is to bind it to a custom function: `httpInstance.onData = function(data) { // handle result }` **/ public dynamic function onData( data : String ) { @@ -744,7 +797,7 @@ class Http { This method is called upon a request error, with `msg` containing the error description. - The intended usage is to bind it to a custom function: + The intended usage is to bind it to a custom function: `httpInstance.onError = function(msg) { // handle error }` **/ public dynamic function onError( msg : String ) { @@ -754,18 +807,18 @@ class Http { This method is called upon a Http status change, with `status` being the new status. - The intended usage is to bind it to a custom function: + The intended usage is to bind it to a custom function: `httpInstance.onStatus = function(status) { // handle status }` **/ public dynamic function onStatus( status : Int ) { } -#if !flash +#if (!flash && !nodejs) /** Makes a synchronous request to `url`. This creates a new Http instance and makes a GET request by calling its - request(false) method. + `request(false)` method. If `url` is null, the result is unspecified. **/ diff --git a/std/haxe/Int32.hx b/std/haxe/Int32.hx index 8cce274a..b37d6371 100644 --- a/std/haxe/Int32.hx +++ b/std/haxe/Int32.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -67,10 +67,26 @@ abstract Int32(Int) from Int to Int { @:op(A - B) public static function floatSub(a:Float, b:Int32):Float; - #if (as3 || js || php || python) + #if (as3 || js || php || python || lua) + #if js + // on JS we want to try using Math.imul, but we have to assign that function to Int32.mul only once, + // or else V8 will deoptimize it, so we need to be a bit funky with this. + // See https://github.com/HaxeFoundation/haxe/issues/5367 for benchmarks. + @:op(A * B) inline static function mul(a:Int32, b:Int32):Int32 + return _mul(a, b); + + static var _mul:Int32->Int32->Int32 = untyped + if (Math.imul != null) + Math.imul + else + function(a:Int32, b:Int32):Int32 + return clamp( (a : Int) * ((b : Int) & 0xFFFF) + clamp( (a : Int) * ((b : Int) >>> 16) << 16 ) ); + + #else @:op(A * B) private static function mul(a:Int32, b:Int32):Int32 return clamp( (a : Int) * ((b : Int) & 0xFFFF) + clamp( (a : Int) * ((b : Int) >>> 16) << 16 ) ); + #end @:op(A * B) @:commutative private static inline function mulInt(a:Int32, b:Int):Int32 return mul(a, b); @@ -128,27 +144,55 @@ abstract Int32(Int) from Int to Int { @:op(A >= B) private static function gteFloat(a:Int32, b:Float):Bool; @:op(A >= B) private static function floatGte(a:Float, b:Int32):Bool; + #if lua + @:op(~A) private static inline function complement( a : Int32 ) : Int32 + return lua.Boot.clamp(~a); + #else @:op(~A) private function complement():Int32; + #end @:op(A & B) private static function and(a:Int32, b:Int32):Int32; @:op(A & B) @:commutative private static function andInt(a:Int32, b:Int):Int32; + #if lua + @:op(A | B) private static function or(a:Int32, b:Int32):Int32 + return clamp((a:Int) | (b:Int)); + @:op(A | B) @:commutative private static function orInt(a:Int32, b:Int):Int32 + return clamp((a:Int) | b); + #else @:op(A | B) private static function or(a:Int32, b:Int32):Int32; @:op(A | B) @:commutative private static function orInt(a:Int32, b:Int):Int32; + #end + #if lua + @:op(A ^ B) private static function xor(a:Int32, b:Int32):Int32 + return clamp((a:Int) ^ (b:Int)); + @:op(A ^ B) @:commutative private static function xorInt(a:Int32, b:Int):Int32 + return clamp((a:Int) ^ b); + #else @:op(A ^ B) private static function xor(a:Int32, b:Int32):Int32; @:op(A ^ B) @:commutative private static function xorInt(a:Int32, b:Int):Int32; + #end +#if lua + @:op(A >> B) private static function shr(a:Int32, b:Int32):Int32 + return clamp((a:Int) >> (b:Int)); + @:op(A >> B) private static function shrInt(a:Int32, b:Int):Int32 + return clamp((a:Int) >> b); + @:op(A >> B) private static function intShr(a:Int, b:Int32):Int32 + return clamp(a >> (b:Int)); +#else @:op(A >> B) private static function shr(a:Int32, b:Int32):Int32; @:op(A >> B) private static function shrInt(a:Int32, b:Int):Int32; @:op(A >> B) private static function intShr(a:Int, b:Int32):Int32; +#end @:op(A >>> B) private static function ushr(a:Int32, b:Int32):Int32; @:op(A >>> B) private static function ushrInt(a:Int32, b:Int):Int32; @:op(A >>> B) private static function intUshr(a:Int, b:Int32):Int32; - #if (php || python) + #if (php || python || lua) // PHP may be 64-bit, so shifts must be clamped @:op(A << B) private static inline function shl(a:Int32, b:Int32):Int32 @@ -158,7 +202,7 @@ abstract Int32(Int) from Int to Int { return clamp( (a : Int) << b ); @:op(A << B) private static inline function intShl(a:Int, b:Int32):Int32 - return clamp( a << (b : Int) ); + return clamp( a << (b : Int) ); #else @@ -168,6 +212,7 @@ abstract Int32(Int) from Int to Int { #end + @:to private inline function toFloat():Float return this; @@ -184,7 +229,8 @@ abstract Int32(Int) from Int to Int { static var extraBits : Int = untyped __php__("PHP_INT_SIZE") * 8 - 32; #end - static inline function clamp( x : Int ) : Int { +#if !lua inline #end + static function clamp( x : Int ) : Int { // force to-int conversion on platforms that require it #if (as3 || js) return x | 0; @@ -193,6 +239,8 @@ abstract Int32(Int) from Int to Int { return (x << extraBits) >> extraBits; #elseif python return python.Syntax.pythonCode("{0} % {1}", (x + python.Syntax.opPow(2, 31)), python.Syntax.opPow(2, 32)) - python.Syntax.opPow(2, 31); + #elseif lua + return lua.Boot.clamp(x); #else return (x); #end diff --git a/std/haxe/Int64.hx b/std/haxe/Int64.hx index a5045470..e803c8da 100644 --- a/std/haxe/Int64.hx +++ b/std/haxe/Int64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -52,7 +52,11 @@ abstract Int64(__Int64) from __Int64 to __Int64 `x` is sign-extended to fill 64 bits. **/ @:from public static inline function ofInt( x : Int ) : Int64 +#if lua + return make( (x:Int32) >> 31, (x:Int32)); +#else return make( x >> 31, x ); +#end /** Returns an Int with the value of the Int64 `x`. @@ -133,18 +137,31 @@ abstract Int64(__Int64) from __Int64 to __Int64 var neg = false; if( i.isNeg() ) { neg = true; - i = -i; + // i = -i; cannot negate here as --9223372036854775808 = -9223372036854775808 } var ten : Int64 = 10; while( i != 0 ) { var r = i.divMod( ten ); - str = r.modulus.low + str; - i = r.quotient; + if (r.modulus.isNeg()) { + str = Int64.neg(r.modulus).low + str; + i = Int64.neg(r.quotient); + } else { + str = r.modulus.low + str; + i = r.quotient; + } } if( neg ) str = "-" + str; return str; } + public static inline function parseString( sParam : String ) : Int64 { + return Int64Helper.parseString( sParam ); + } + + public static inline function fromFloat( f : Float ) : Int64 { + return Int64Helper.fromFloat( f ); + } + /** Performs signed integer divison of `dividend` by `divisor`. Returns `{ quotient : Int64, modulus : Int64 }`. @@ -205,25 +222,27 @@ abstract Int64(__Int64) from __Int64 to __Int64 } @:op(++A) private inline function preIncrement() : Int64 { + this = copy(); this.low++; if( this.low == 0 ) this.high++; return cast this; } @:op(A++) private inline function postIncrement() : Int64 { - var ret = copy(); + var ret = this; preIncrement(); return ret; } @:op(--A) private inline function preDecrement() : Int64 { + this = copy(); if( this.low == 0 ) this.high--; this.low--; return cast this; } @:op(A--) private inline function postDecrement() : Int64 { - var ret = copy(); + var ret = this; preDecrement(); return ret; } @@ -260,7 +279,7 @@ abstract Int64(__Int64) from __Int64 to __Int64 /** Returns the product of `a` and `b`. **/ - @:op(A * B) public static inline function mul( a : Int64, b : Int64 ) : Int64 { + @:op(A * B) public static #if !lua inline #end function mul( a : Int64, b : Int64 ) : Int64 { var mask = 0xFFFF; var al = a.low & mask, ah = a.low >>> 16; var bl = b.low & mask, bh = b.low >>> 16; @@ -402,7 +421,7 @@ abstract Int64(__Int64) from __Int64 to __Int64 @:op(A >> B) public static inline function shr( a : Int64, b : Int) : Int64 { b &= 63; return if( b == 0 ) a.copy() - else if( b < 32 ) make( a.high >> b, (a.high << (32-b)) | (a.low >>> b) ) + else if( b < 32 ) make( a.high >> b, (a.high << (32-b)) | (a.low >>> b) ); else make( a.high >> 31, a.high >> (b - 32) ); } @@ -413,7 +432,7 @@ abstract Int64(__Int64) from __Int64 to __Int64 @:op(A >>> B) public static inline function ushr( a : Int64, b : Int ) : Int64 { b &= 63; return if( b == 0 ) a.copy() - else if( b < 32 ) make( a.high >>> b, (a.high << (32-b)) | (a.low >>> b) ) + else if( b < 32 ) make( a.high >>> b, (a.high << (32-b)) | (a.low >>> b) ); else make( 0, a.high >>> (b - 32) ); } diff --git a/std/haxe/Int64Helper.hx b/std/haxe/Int64Helper.hx new file mode 100644 index 00000000..ba0ab8c6 --- /dev/null +++ b/std/haxe/Int64Helper.hx @@ -0,0 +1,109 @@ +/* + * Copyright (C)2005-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 haxe; + +using haxe.Int64; + +import StringTools; + +/** + Helper for parsing to `Int64` instances. +**/ +class Int64Helper { + /** + Create `Int64` from given string. + **/ + public static function parseString( sParam : String ) : Int64 { + var base = Int64.ofInt(10); + var current = Int64.ofInt(0); + var multiplier = Int64.ofInt(1); + var sIsNegative = false; + + var s = StringTools.trim(sParam); + if (s.charAt(0) == "-") { + sIsNegative = true; + s = s.substring(1, s.length); + } + var len = s.length; + + for (i in 0...len) { + var digitInt = s.charCodeAt(len - 1 - i) - '0'.code; + + if (digitInt < 0 || digitInt > 9) { + throw "NumberFormatError"; + } + + var digit:Int64 = Int64.ofInt(digitInt); + if (sIsNegative) { + current = Int64.sub(current, Int64.mul(multiplier, digit)); + if (!Int64.isNeg(current)) { + throw "NumberFormatError: Underflow"; + } + } else { + current = Int64.add(current, Int64.mul(multiplier, digit)); + if (Int64.isNeg(current)) { + throw "NumberFormatError: Overflow"; + } + } + multiplier = Int64.mul(multiplier, base); + } + return current; + } + + /** + Create `Int64` from given float. + **/ + public static function fromFloat( f : Float ) : Int64 { + if (Math.isNaN(f) || !Math.isFinite(f)) { + throw "Number is NaN or Infinite"; + } + + var noFractions = f - (f % 1); + + // 2^53-1 and -2^53: these are parseable without loss of precision + if (noFractions > 9007199254740991) { + throw "Conversion overflow"; + } + if (noFractions < -9007199254740991) { + throw "Conversion underflow"; + } + + var result = Int64.ofInt(0); + var neg = noFractions < 0; + var rest = neg ? -noFractions : noFractions; + + var i = 0; + while (rest >= 1) { + var curr = rest % 2; + rest = rest / 2; + if (curr >= 1) { + result = Int64.add(result, Int64.shl(Int64.ofInt(1), i)); + } + i++; + } + + if (neg) { + result = Int64.neg(result); + } + return result; + } +} diff --git a/std/haxe/Json.hx b/std/haxe/Json.hx index 98e7385b..1f057ecf 100644 --- a/std/haxe/Json.hx +++ b/std/haxe/Json.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,9 +22,11 @@ package haxe; /** - Crossplatform JSON API : it will automatically use the optimized native API if available. - Use -D haxeJSON to force usage of the Haxe implementation even if a native API is found : this will provide - extra encoding features such as enums (replaced by their index) and StringMaps. + Crossplatform JSON API: it will automatically use the optimized native API if available. + Use `-D haxeJSON` to force usage of the Haxe implementation even if a native API is found: + This will provide extra encoding features such as enums (replaced by their index) and StringMaps. + + @see https://haxe.org/manual/std-Json.html **/ class Json { @@ -32,23 +34,27 @@ class Json { Parses given JSON-encoded `text` and returns the resulting object. JSON objects are parsed into anonymous structures and JSON arrays - are parsed into Array. + are parsed into `Array`. If given `text` is not valid JSON, an exception will be thrown. + + @see https://haxe.org/manual/std-Json-parsing.html **/ public static inline function parse( text : String ) : Dynamic { return haxe.format.JsonParser.parse(text); } /** - Encodes given `value` and returns the resulting JSON string. + Encodes the given `value` and returns the resulting JSON string. - If `replacer` is given and is not null, it is used to retrieve - actual object to be encoded. The `replacer` function two parameters, + If `replacer` is given and is not null, it is used to retrieve the + actual object to be encoded. The `replacer` function takes two parameters, the key and the value being encoded. Initial key value is an empty string. If `space` is given and is not null, the result will be pretty-printed. Successive levels will be indented by this string. + + @see https://haxe.org/manual/std-Json-encoding.html **/ public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space : String ) : String { return haxe.format.JsonPrinter.print(value, replacer, space); diff --git a/std/haxe/Log.hx b/std/haxe/Log.hx index 6a7a944e..8c9b7a94 100644 --- a/std/haxe/Log.hx +++ b/std/haxe/Log.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,8 +22,8 @@ package haxe; /** - Log primarily provides the trace() method, which is invoked upon a call to - trace() in haxe code. + Log primarily provides the `trace()` method, which is invoked upon a call to + `trace()` in Haxe code. **/ class Log { @@ -31,15 +31,17 @@ class Log { Outputs `v` in a platform-dependent way. The second parameter `infos` is injected by the compiler and contains - information about the position where the trace() call was made. + information about the position where the `trace()` call was made. This method can be rebound to a custom function: var oldTrace = haxe.Log.trace; // store old function - haxe.Log.trace = function(v,infos) { // handle trace } + haxe.Log.trace = function(v, ?infos) { + // handle trace + } ... haxe.Log.trace = oldTrace; - If it is bound to null, subsequent calls to trace() will cause an + If it is bound to null, subsequent calls to `trace()` will cause an exception. **/ public static dynamic function trace( v : Dynamic, ?infos : PosInfos ) : Void { @@ -60,6 +62,8 @@ class Log { } #elseif js untyped js.Boot.__trace(v,infos); + #elseif (php && php7) + php.Boot.trace(v, infos); #elseif php if (infos!=null && infos.customParams!=null) { var extra:String = ""; @@ -78,7 +82,7 @@ class Log { } else untyped __trace(v,infos); - #elseif (cs || java) + #elseif (cs || java || lua) var str:String = null; if (infos != null) { str = infos.fileName + ":" + infos.lineNumber + ": " + v; @@ -93,6 +97,9 @@ class Log { cs.system.Console.WriteLine(str); #elseif java untyped __java__("java.lang.System.out.println(str)"); + #elseif lua + if (str == null) str = "null"; + untyped __define_feature__("use._hx_print",_hx_print(str)); #end #elseif (python) var str:String = null; @@ -105,6 +112,11 @@ class Log { str = v; } python.Lib.println(str); + #elseif hl + var pstr = infos == null ? "(null)" : infos.fileName + ":" + infos.lineNumber; + var str = Std.string(v); + if( infos != null && infos.customParams != null ) for( v in infos.customParams ) str += "," + Std.string(v); + Sys.println(pstr+": "+str); #end } diff --git a/std/haxe/MainLoop.hx b/std/haxe/MainLoop.hx new file mode 100644 index 00000000..8a2f4551 --- /dev/null +++ b/std/haxe/MainLoop.hx @@ -0,0 +1,164 @@ +package haxe; +import haxe.EntryPoint; + +class MainEvent { + + var f : Void -> Void; + var prev : MainEvent; + var next : MainEvent; + public var nextRun(default,null) : Float; + public var priority(default,null) : Int; + + function new(f, p) { + this.f = f; + this.priority = p; + nextRun = -1; + } + + /** + Delay the execution of the event for the given time, in seconds. + If t is null, the event will be run at tick() time. + **/ + public function delay( t : Null ) { + nextRun = t == null ? -1 : haxe.Timer.stamp() + t; + } + + /** + Call the event. Will do nothing is the event has been stopped. + **/ + public inline function call() { + if( f != null ) f(); + } + + /** + Stop the event from firing anymore. + **/ + public function stop() { + if( f == null ) return; + f = null; + nextRun = -1; + if( prev == null ) + @:privateAccess MainLoop.pending = next; + else + prev.next = next; + if( next != null ) + next.prev = prev; + } + +} + +@:access(haxe.MainEvent) +class MainLoop { + + static var pending : MainEvent = null; + + public static var threadCount(get, never) : Int; + + inline static function get_threadCount() return EntryPoint.threadCount; + + public inline static function hasEvents() { + return pending != null; + } + + public static function addThread( f : Void -> Void ) { + EntryPoint.addThread(f); + } + + public static function runInMainThread( f : Void -> Void ) { + EntryPoint.runInMainThread(f); + } + + /** + Add a pending event to be run into the main loop. + **/ + public static function add( f : Void -> Void, priority = 0 ) : MainEvent @:privateAccess { + if( f == null ) + throw "Event function is null"; + var e = new MainEvent(f, priority); + var head = pending; + if( head != null ) head.prev = e; + e.next = head; + pending = e; + return e; + } + + static function sortEvents() { + // pending = haxe.ds.ListSort.sort(pending, function(e1, e2) return e1.nextRun > e2.nextRun ? -1 : 1); + // we can't use directly ListSort because it requires prev/next to be public, which we don't want here + // we do then a manual inline, this also allow use to do a Float comparison of nextRun + var list = pending; + + if( list == null ) return; + + var insize = 1, nmerges, psize = 0, qsize = 0; + var p, q, e, tail : MainEvent; + + while( true ) { + p = list; + list = null; + tail = null; + nmerges = 0; + while( p != null ) { + nmerges++; + q = p; + psize = 0; + for( i in 0...insize ) { + psize++; + q = q.next; + if( q == null ) break; + } + qsize = insize; + while( psize > 0 || (qsize > 0 && q != null) ) { + if( psize == 0 ) { + e = q; + q = q.next; + qsize--; + } else if( qsize == 0 || q == null || (p.priority > q.priority || (p.priority == q.priority && p.nextRun <= q.nextRun)) ) { + e = p; + p = p.next; + psize--; + } else { + e = q; + q = q.next; + qsize--; + } + if( tail != null ) + tail.next = e; + else + list = e; + e.prev = tail; + tail = e; + } + p = q; + } + tail.next = null; + if( nmerges <= 1 ) + break; + insize *= 2; + } + list.prev = null; // not cycling + pending = list; + } + + /** + Run the pending events. Return the time for next event. + **/ + static function tick() { + sortEvents(); + var e = pending; + var now = haxe.Timer.stamp(); + var wait = 1e9; + while( e != null ) { + var next = e.next; + var wt = e.nextRun - now; + if( e.nextRun < 0 || wt <= 0 ) { + wait = 0; + e.call(); + } else if( wait > wt ) + wait = wt; + e = next; + } + return wait; + } + +} \ No newline at end of file diff --git a/std/haxe/PosInfos.hx b/std/haxe/PosInfos.hx index 1c9682de..8a18c39d 100644 --- a/std/haxe/PosInfos.hx +++ b/std/haxe/PosInfos.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/Resource.hx b/std/haxe/Resource.hx index 228111a3..683a7061 100644 --- a/std/haxe/Resource.hx +++ b/std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/Serializer.hx b/std/haxe/Serializer.hx index acc92136..5fc4a52e 100644 --- a/std/haxe/Serializer.hx +++ b/std/haxe/Serializer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,28 +22,28 @@ package haxe; /** - The Serializer class can be used to encode values and objects into a String, - from which the Unserializer class can recreate the original representation. + The Serializer class can be used to encode values and objects into a `String`, + from which the `Unserializer` class can recreate the original representation. This class can be used in two ways: - - create a new Serializer() instance, call its serialize() method with + - create a `new Serializer()` instance, call its `serialize()` method with any argument and finally retrieve the String representation from - toString() - - call Serializer.run() to obtain the serialized representation of a + `toString()` + - call `Serializer.run()` to obtain the serialized representation of a single argument Serialization is guaranteed to work for all haxe-defined classes, but may or may not work for instances of external/native classes. The specification of the serialization format can be found here: - `http://haxe.org/manual/serialization/format` + **/ class Serializer { /** If the values you are serializing can contain circular references or - objects repetitions, you should set USE_CACHE to true to prevent + objects repetitions, you should set `USE_CACHE` to true to prevent infinite loops. This may also reduce the size of serialization Strings at the expense of @@ -67,6 +67,7 @@ class Serializer { public static var USE_ENUM_INDEX = false; static var BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%:"; + static var BASE64_CODES = null; var buf : StringBuf; var cache : Array; @@ -110,7 +111,7 @@ class Serializer { Return the String representation of `this` Serializer. The exact format specification can be found here: - http://haxe.org/manual/serialization/format + https://haxe.org/manual/serialization/format **/ public function toString() { return buf.toString(); @@ -258,10 +259,10 @@ class Serializer { case #if (neko || cs || python) "Array" #else cast Array #end: var ucount = 0; buf.add("a"); - #if (flash || python) + #if (flash || python || hl) var v : Array = v; #end - var l = #if (neko || flash || php || cs || java || python) v.length #elseif cpp v.__length() #else __getField(v, "length") #end; + var l = #if (neko || flash || php || cs || java || python || hl || lua) v.length #elseif cpp v.__length() #else __getField(v, "length") #end; for( i in 0...l ) { if( v[i] == null ) ucount++; @@ -333,41 +334,50 @@ class Serializer { var v : haxe.io.Bytes = v; #if neko var chars = new String(base_encode(v.getData(),untyped BASE64.__s)); + buf.add("s"); + buf.add(chars.length); + buf.add(":"); + buf.add(chars); #else + + buf.add("s"); + buf.add(Math.ceil((v.length * 8) / 6)); + buf.add(":"); + var i = 0; var max = v.length - 2; - var charsBuf = new StringBuf(); - var b64 = BASE64; + var b64 = BASE64_CODES; + if( b64 == null ) { + b64 = new haxe.ds.Vector(BASE64.length); + for( i in 0...BASE64.length ) + b64[i] = BASE64.charCodeAt(i); + BASE64_CODES = b64; + } while( i < max ) { var b1 = v.get(i++); var b2 = v.get(i++); var b3 = v.get(i++); - charsBuf.add(b64.charAt(b1 >> 2)); - charsBuf.add(b64.charAt(((b1 << 4) | (b2 >> 4)) & 63)); - charsBuf.add(b64.charAt(((b2 << 2) | (b3 >> 6)) & 63)); - charsBuf.add(b64.charAt(b3 & 63)); + buf.addChar(b64[b1 >> 2]); + buf.addChar(b64[((b1 << 4) | (b2 >> 4)) & 63]); + buf.addChar(b64[((b2 << 2) | (b3 >> 6)) & 63]); + buf.addChar(b64[b3 & 63]); } if( i == max ) { var b1 = v.get(i++); var b2 = v.get(i++); - charsBuf.add(b64.charAt(b1 >> 2)); - charsBuf.add(b64.charAt(((b1 << 4) | (b2 >> 4)) & 63)); - charsBuf.add(b64.charAt((b2 << 2) & 63)); + buf.addChar(b64[b1 >> 2]); + buf.addChar(b64[((b1 << 4) | (b2 >> 4)) & 63]); + buf.addChar(b64[(b2 << 2) & 63]); } else if( i == max + 1 ) { var b1 = v.get(i++); - charsBuf.add(b64.charAt(b1 >> 2)); - charsBuf.add(b64.charAt((b1 << 4) & 63)); + buf.addChar(b64[b1 >> 2]); + buf.addChar(b64[(b1 << 4) & 63]); } - var chars = charsBuf.toString(); #end - buf.add("s"); - buf.add(chars.length); - buf.add(":"); - buf.add(chars); default: if( useCache ) cache.pop(); - if( #if flash try v.hxSerialize != null catch( e : Dynamic ) false #elseif (cs || java || python) Reflect.hasField(v, "hxSerialize") #else v.hxSerialize != null #end ) { + if( #if flash try v.hxSerialize != null catch( e : Dynamic ) false #elseif (cs || java || python) Reflect.hasField(v, "hxSerialize") #elseif (php && php7) php.Global.method_exists(v, 'hxSerialize') #else v.hxSerialize != null #end ) { buf.add("C"); serializeString(Type.getClassName(c)); if( useCache ) cache.push(v); @@ -443,20 +453,17 @@ class Serializer { serialize(p); } #elseif cpp + var enumBase:cpp.EnumBase = v; if( useEnumIndex ) { buf.add(":"); - buf.add(v.__Index()); + buf.add(enumBase.getIndex()); } else - serializeString(v.__Tag()); + serializeString(enumBase.getTag()); buf.add(":"); - var pl : Array = v.__EnumParams(); - if( pl == null ) - buf.add(0); - else { - buf.add(pl.length); - for( p in pl ) - serialize(p); - } + var len = enumBase.getParamCount(); + buf.add(len); + for( p in 0...len ) + serialize( enumBase.getParamI(p)); #elseif php if( useEnumIndex ) { buf.add(":"); @@ -469,10 +476,15 @@ class Serializer { buf.add(0); else { buf.add(l); - for( i in 0...l ) + for( i in 0...l ) { + #if (php && php7) + serialize(v.params[i]); + #elseif php serialize(untyped __field__(v, __php__("params"), i)); + #end + } } - #elseif (java || cs || python) + #elseif (java || cs || python || hl) if( useEnumIndex ) { buf.add(":"); buf.add(Type.enumIndex(v)); diff --git a/std/haxe/Template.hx b/std/haxe/Template.hx index 1855f7fd..26a23e0c 100644 --- a/std/haxe/Template.hx +++ b/std/haxe/Template.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -47,7 +47,7 @@ private typedef ExprToken = { String, and to have some basic logic. A complete documentation of the supported syntax is available at: -
http://haxe.org/manual/std-template.html + **/ class Template { @@ -112,13 +112,16 @@ class Template { } function resolve( v : String ) : Dynamic { - if( Reflect.hasField(context,v) ) - return Reflect.field(context,v); - for( ctx in stack ) - if( Reflect.hasField(ctx,v) ) - return Reflect.field(ctx,v); if( v == "__current__" ) return context; + var value = Reflect.getProperty(context, v); + if( value != null || Reflect.hasField(context,v) ) + return value; + for( ctx in stack ) { + value = Reflect.getProperty(ctx,v); + if( value != null || Reflect.hasField(ctx,v) ) + return value; + } return Reflect.field(globals,v); } @@ -312,13 +315,13 @@ class Template { var e1:Dynamic = makeExpr(l); var p = l.pop(); if( p == null || p.s ) - throw p.p; + throw p; if( p.p == ")" ) return e1; var e2:Dynamic = makeExpr(l); var p2 = l.pop(); if( p2 == null || p2.p != ")" ) - throw p2.p; + throw p2; return switch( p.p ) { case "+": function() { return cast e1() + e2(); }; case "-": function() { return cast e1() - e2(); }; diff --git a/std/haxe/Timer.hx b/std/haxe/Timer.hx index ea192491..ecbca0cc 100644 --- a/std/haxe/Timer.hx +++ b/std/haxe/Timer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -36,19 +36,20 @@ package haxe; the child class. **/ class Timer { - #if (flash || js || java || python) #if (flash || js) private var id : Null; #elseif java private var timer : java.util.Timer; private var task : java.util.TimerTask; + #else + private var event : MainLoop.MainEvent; #end /** Creates a new timer that will run every `time_ms` milliseconds. - After creating the Timer instance, it calls `this].run` repeatedly, + After creating the Timer instance, it calls `this.run` repeatedly, with delays of `time_ms` milliseconds, until `this.stop` is called. The first invocation occurs after `time_ms` milliseconds, not @@ -66,6 +67,13 @@ class Timer { #elseif java timer = new java.util.Timer(); timer.scheduleAtFixedRate(task = new TimerTask(this), haxe.Int64.ofInt(time_ms), haxe.Int64.ofInt(time_ms)); + #else + var dt = time_ms / 1000; + event = MainLoop.add(function() { + @:privateAccess event.nextRun += dt; + run(); + }); + event.delay(dt); #end } @@ -88,9 +96,16 @@ class Timer { #end id = null; #elseif java - timer.cancel(); - timer = null; + if(timer != null) { + timer.cancel(); + timer = null; + } task = null; + #else + if( event != null ) { + event.stop(); + event = null; + } #end } @@ -127,8 +142,6 @@ class Timer { return t; } - #end - /** Measures the time it takes to execute `f`, in seconds with fractions. @@ -153,7 +166,7 @@ class Timer { The value itself might differ depending on platforms, only differences between two values make sense. **/ - public static function stamp() : Float { + public static inline function stamp() : Float { #if flash return flash.Lib.getTimer() / 1000; #elseif (neko || php) @@ -162,8 +175,11 @@ class Timer { return Date.now().getTime() / 1000; #elseif cpp return untyped __global__.__time_stamp(); + #elseif python + return Sys.cpuTime(); #elseif sys return Sys.time(); + #else return 0; #end diff --git a/std/haxe/Ucs2.hx b/std/haxe/Ucs2.hx index f9747104..74db83d2 100644 --- a/std/haxe/Ucs2.hx +++ b/std/haxe/Ucs2.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -128,7 +128,7 @@ abstract Ucs2(String) { If `delimiter` is null, the result is unspecified. Otherwise, `this` Ucs2 is split into parts at each occurence of - `delimiter`. If `this` Ucs2 starts (or ends) with [delimiter}, the + `delimiter`. If `this` Ucs2 starts (or ends) with `delimiter`, the result Array contains a leading (or trailing) empty Ucs2 "" element. Two subsequent delimiters also result in an empty Ucs2 "" element. **/ diff --git a/std/haxe/Unserializer.hx b/std/haxe/Unserializer.hx index 9e189fe5..f66f277a 100644 --- a/std/haxe/Unserializer.hx +++ b/std/haxe/Unserializer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -28,36 +28,39 @@ typedef TypeResolver = { } /** - The Unserializer class is the complement to the Serializer class. It parses - a serialization String and creates objects from the contained data. + The `Unserializer` class is the complement to the `Serializer` class. It parses + a serialization `String` and creates objects from the contained data. This class can be used in two ways: - - create a new Unserializer() instance with a given serialization - String, then call its unserialize() method until all values are + - create a `new Unserializer()` instance with a given serialization + String, then call its `unserialize()` method until all values are extracted - - call Unserializer.run() to unserialize a single value from a given + - call `Unserializer.run()` to unserialize a single value from a given String + + The specification of the serialization format can be found here: + **/ class Unserializer { /** This value can be set to use custom type resolvers. - A type resolver finds a Class or Enum instance from a given String. By - default, the haxe Type Api is used. + A type resolver finds a `Class` or `Enum` instance from a given `String`. + By default, the Haxe `Type` Api is used. A type resolver must provide two methods: - 1. resolveClass(name:String):Class is called to determine a - Class from a class name - 2. resolveEnum(name:String):Enum is called to determine an - Enum from an enum name + 1. `resolveClass(name:String):Class` is called to determine a + `Class` from a class name + 2. `resolveEnum(name:String):Enum` is called to determine an + `Enum` from an enum name - This value is applied when a new Unserializer instance is created. + This value is applied when a new `Unserializer` instance is created. Changing it afterwards has no effect on previously created instances. **/ - public static var DEFAULT_RESOLVER : TypeResolver = Type; + public static var DEFAULT_RESOLVER : TypeResolver = new DefaultResolver(); static var BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%:"; @@ -107,10 +110,10 @@ class Unserializer { cache = new Array(); var r = DEFAULT_RESOLVER; if( r == null ) { - r = Type; + r = new DefaultResolver(); DEFAULT_RESOLVER = r; } - setResolver(r); + resolver = r; } /** @@ -119,14 +122,11 @@ class Unserializer { If `r` is null, a special resolver is used which returns null for all input values. - See DEFAULT_RESOLVER for more information on type resolvers. + See `DEFAULT_RESOLVER` for more information on type resolvers. **/ public function setResolver( r ) { if( r == null ) - resolver = { - resolveClass : function(_) { return null; }, - resolveEnum : function(_) { return null; } - }; + resolver = NullResolver.instance; else resolver = r; } @@ -134,7 +134,7 @@ class Unserializer { /** Gets the type resolver of `this` Unserializer instance. - See DEFAULT_RESOLVER for more information on type resolvers. + See `DEFAULT_RESOLVER` for more information on type resolvers. **/ public function getResolver() { return resolver; @@ -173,6 +173,7 @@ class Unserializer { var p1 = pos; while( true ) { var c = get(pos); + if( StringTools.isEof(c)) break; // + - . , 0-9 if( (c >= 43 && c < 58) || c == "e".code || c == "E".code ) pos++; @@ -222,11 +223,11 @@ class Unserializer { This operation may fail on structurally valid data if a type cannot be resolved or if a field cannot be set. This can happen when unserializing - Strings that were serialized on a different haxe target, in which the + Strings that were serialized on a different Haxe target, in which the serialization side has to make sure not to include platform-specific data. - Classes are created from Type.createEmptyInstance, which means their + Classes are created from `Type.createEmptyInstance`, which means their constructors are not called. **/ public function unserialize() : Dynamic { @@ -261,6 +262,7 @@ class Unserializer { case "a".code: var buf = buf; var a = new Array(); + #if cpp var cachePos = cache.length; #end cache.push(a); while( true ) { var c = get(pos); @@ -275,7 +277,11 @@ class Unserializer { } else a.push(unserialize()); } + #if cpp + return cache[cachePos] = cpp.NativeArray.resolveVirtualArray(a); + #else return a; + #end case "o".code: var o = {}; cache.push(o); @@ -465,3 +471,20 @@ class Unserializer { #end } + +private class DefaultResolver { + public function new() {} + @:final public inline function resolveClass(name:String):Class return Type.resolveClass(name); + @:final public inline function resolveEnum(name:String):Enum return Type.resolveEnum(name); +} + +private class NullResolver { + function new() {} + @:final public inline function resolveClass(name:String):Class return null; + @:final public inline function resolveEnum(name:String):Enum return null; + public static var instance(get,null):NullResolver; + inline static function get_instance():NullResolver { + if (instance == null) instance = new NullResolver(); + return instance; + } +} diff --git a/std/haxe/Utf8.hx b/std/haxe/Utf8.hx index 222c0246..c7d5eb1c 100644 --- a/std/haxe/Utf8.hx +++ b/std/haxe/Utf8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,7 +22,7 @@ package haxe; /** - Since all platforms does not guarantee that String always uses UTF-8 encoding, you + Since not all platforms guarantee that `String` always uses UTF-8 encoding, you can use this crossplatform API to perform operations on such strings. **/ class Utf8 { @@ -44,7 +44,7 @@ class Utf8 { } /** - Returns the buffer converted to a String; + Returns the buffer converted to a String. **/ public inline function toString() : String { return __b; @@ -109,4 +109,4 @@ class Utf8 { return s.substr(pos,len); } -} \ No newline at end of file +} diff --git a/std/haxe/crypto/Adler32.hx b/std/haxe/crypto/Adler32.hx index 4ce234ab..93e3f655 100644 --- a/std/haxe/crypto/Adler32.hx +++ b/std/haxe/crypto/Adler32.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/crypto/Base64.hx b/std/haxe/crypto/Base64.hx index 765be3d2..b7b81194 100644 --- a/std/haxe/crypto/Base64.hx +++ b/std/haxe/crypto/Base64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/crypto/BaseCode.hx b/std/haxe/crypto/BaseCode.hx index ebb8952d..9028c0af 100644 --- a/std/haxe/crypto/BaseCode.hx +++ b/std/haxe/crypto/BaseCode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,7 +22,7 @@ package haxe.crypto; /** - Allows to encode/decode String and bytes using a power of two base dictionnary. + Allows to encode/decode String and bytes using a power of two base dictionary. **/ class BaseCode { diff --git a/std/haxe/crypto/Crc32.hx b/std/haxe/crypto/Crc32.hx index bb4f1176..a74d362a 100644 --- a/std/haxe/crypto/Crc32.hx +++ b/std/haxe/crypto/Crc32.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/crypto/Hmac.hx b/std/haxe/crypto/Hmac.hx index da60d191..e98b6628 100644 --- a/std/haxe/crypto/Hmac.hx +++ b/std/haxe/crypto/Hmac.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/crypto/Md5.hx b/std/haxe/crypto/Md5.hx index c49a4b88..98a87853 100644 --- a/std/haxe/crypto/Md5.hx +++ b/std/haxe/crypto/Md5.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -42,7 +42,7 @@ class Md5 { #if neko return haxe.io.Bytes.ofData(make_md5(b.getData())); #elseif php - return haxe.io.Bytes.ofData(untyped __call__("md5", b.getData(), true)); + return haxe.io.Bytes.ofData( haxe.io.BytesData.ofString(untyped __call__("md5", b.getData().toString(), true))); #else var h = new Md5().doEncode(bytes2blks(b)); var out = haxe.io.Bytes.alloc(16); @@ -113,11 +113,11 @@ class Md5 { //preallocate size var blksSize = nblk * 16; - #if (neko || cs || cpp || java) + #if (neko || cs || cpp || java || hl) blks[blksSize - 1] = 0; #end - #if !(cpp || cs) //C++ and C# will already initialize them with zeroes. + #if !(cpp || cs || hl) //C++ and C# will already initialize them with zeroes. for( i in 0...blksSize ) blks[i] = 0; #end @@ -137,26 +137,30 @@ class Md5 { } static function str2blks( str : String ){ +#if !(neko || cpp || php) + var str = haxe.io.Bytes.ofString(str); +#end var nblk = ((str.length + 8) >> 6) + 1; var blks = new Array(); //preallocate size var blksSize = nblk * 16; - #if (neko || cs || cpp || java) + #if (neko || cs || cpp || java || hl) blks[blksSize - 1] = 0; #end - #if !(cpp || cs) //C++ and C# will already initialize them with zeroes. + #if !(cpp || cs || hl) //C++ and C# will already initialize them with zeroes. for( i in 0...blksSize ) blks[i] = 0; #end var i = 0; - while( i < str.length ) { - blks[i >> 2] |= str.charCodeAt(i) << (((str.length * 8 + i) % 4) * 8); + var max = str.length; + var l = max * 8; + while( i < max ) { + blks[i >> 2] |= #if !(neko || cpp || php) str.get(i) #else StringTools.fastCodeAt(str, i) #end << (((l + i) % 4) * 8); i++; } - blks[i >> 2] |= 0x80 << (((str.length * 8 + i) % 4) * 8); - var l = str.length * 8; + blks[i >> 2] |= 0x80 << (((l + i) % 4) * 8); var k = nblk * 16 - 2; blks[k] = (l & 0xFF); blks[k] |= ((l >>> 8) & 0xFF) << 8; diff --git a/std/haxe/crypto/Sha1.hx b/std/haxe/crypto/Sha1.hx index 9eb038ee..bc3cfbf6 100644 --- a/std/haxe/crypto/Sha1.hx +++ b/std/haxe/crypto/Sha1.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -38,7 +38,7 @@ class Sha1 { public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes { #if php - return haxe.io.Bytes.ofData(untyped __call__("sha1", b.getData(), true)); + return haxe.io.Bytes.ofData(haxe.io.BytesData.ofString(untyped __call__("sha1", b.getData().toString(), true))); #else var h = new Sha1().doEncode(bytes2blks(b)); var out = haxe.io.Bytes.alloc(20); @@ -105,6 +105,9 @@ class Sha1 { Append padding bits and the length, as described in the SHA1 standard. */ static function str2blks( s :String ) : Array { +#if !(neko || cpp || php) + var s = haxe.io.Bytes.ofString(s); +#end var nblk = ((s.length + 8) >> 6) + 1; var blks = new Array(); @@ -112,7 +115,7 @@ class Sha1 { blks[i] = 0; for (i in 0...s.length){ var p = i >> 2; - blks[p] |= s.charCodeAt(i) << (24 - ((i & 3) << 3)); + blks[p] |= #if !(neko || cpp || php) s.get(i) #else StringTools.fastCodeAt(s,i) #end << (24 - ((i & 3) << 3)); } var i = s.length; var p = i >> 2; diff --git a/std/haxe/crypto/Sha224.hx b/std/haxe/crypto/Sha224.hx index a3cd5aad..a511cfe4 100644 --- a/std/haxe/crypto/Sha224.hx +++ b/std/haxe/crypto/Sha224.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,7 +25,7 @@ package haxe.crypto; Creates a Sha224 of a String. */ class Sha224 { - + public static function encode( s:String ) : String { #if php return untyped __call__("hash", "sha224", s); @@ -38,7 +38,7 @@ class Sha224 { public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes { #if php - return haxe.io.Bytes.ofData(untyped __call__("hash", "sha224", b.getData(), true)); + return haxe.io.Bytes.ofData(haxe.io.BytesData.ofString(untyped __call__("hash", "sha224", b.getData().toString(), true))); #else var h = new Sha224().doEncode(b.toString(), b.length*8); var out = haxe.io.Bytes.alloc(28); @@ -52,26 +52,26 @@ class Sha224 { return out; #end } - + public function new() { } - + function doEncode( str : String, strlen : Int ) : Array { var K : Array = [ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, - 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, - 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, - 0xE49B69C1, 0xEFBE4786, 0xFC19DC6 , 0x240CA1CC, - 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0xFC19DC6 , 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, - 0xC6E00BF3, 0xD5A79147, 0x6CA6351 , 0x14292967, + 0xC6E00BF3, 0xD5A79147, 0x6CA6351 , 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, - 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, - 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, - 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 ]; @@ -158,38 +158,38 @@ class Sha224 { function ROTR(X, n) { return ( X >>> n ) | (X << (32 - n)); } - + // ++ function SHR(X, n) { return ( X >>> n ); } - + // ++ function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); } - + // ++ function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); } - + function Sigma0(x) { return ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22); } - + function Sigma1(x) { return ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25); } - + function Gamma0(x) { return ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3); } - + function Gamma1(x) { return ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10); } - + function hex( a : Array ){ var str = ""; for( num in a ) { diff --git a/std/haxe/crypto/Sha256.hx b/std/haxe/crypto/Sha256.hx index 2a08b386..dabddc9e 100644 --- a/std/haxe/crypto/Sha256.hx +++ b/std/haxe/crypto/Sha256.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,7 +25,7 @@ package haxe.crypto; Creates a Sha256 of a String. */ class Sha256 { - + public static function encode( s:String ) : String { #if php return untyped __call__("hash", "sha256", s); @@ -38,7 +38,7 @@ class Sha256 { public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes { #if php - return haxe.io.Bytes.ofData(untyped __call__("hash", "sha256", b.getData(), true)); + return haxe.io.Bytes.ofData(haxe.io.BytesData.ofString(untyped __call__("hash", "sha256", b.getData().toString(), true))); #else var h = new Sha256().doEncode(bytes2blks(b), b.length*8); var out = haxe.io.Bytes.alloc(32); @@ -52,10 +52,10 @@ class Sha256 { return out; #end } - + public function new() { } - + function doEncode( m : Array, l : Int ) : Array { var K : Array = [ 0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B, @@ -107,12 +107,15 @@ class Sha256 { } return HASH; } - + /* Convert a string to a sequence of 16-word blocks, stored as an array. Append padding bits and the length, as described in the SHA1 standard. */ static function str2blks( s :String ) : Array { +#if !(neko || cpp || php) + var s = haxe.io.Bytes.ofString(s); +#end var nblk = ((s.length + 8) >> 6) + 1; var blks = new Array(); @@ -120,7 +123,7 @@ class Sha256 { blks[i] = 0; for (i in 0...s.length){ var p = i >> 2; - blks[p] |= s.charCodeAt(i) << (24 - ((i & 3) << 3)); + blks[p] |= #if !(neko || cpp || php) s.get(i) #else s.charCodeAt(i) #end << (24 - ((i & 3) << 3)); } var i = s.length; var p = i >> 2; @@ -149,41 +152,41 @@ class Sha256 { function S(X, n) { return ( X >>> n ) | (X << (32 - n)); } - + function R(X, n) { return ( X >>> n ); } - + function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); } - + function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); } - + function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); } - + function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); } - + function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); } - + function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); } - + function safeAdd(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } - + function hex( a : Array ){ var str = ""; for( num in a ) { diff --git a/std/haxe/ds/ArraySort.hx b/std/haxe/ds/ArraySort.hx index 4f826e5a..c3ab76c7 100644 --- a/std/haxe/ds/ArraySort.hx +++ b/std/haxe/ds/ArraySort.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/ds/BalancedTree.hx b/std/haxe/ds/BalancedTree.hx index 199ec364..05a5b8f2 100644 --- a/std/haxe/ds/BalancedTree.hx +++ b/std/haxe/ds/BalancedTree.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -207,6 +207,9 @@ class BalancedTree { } } +/** + A tree node of `haxe.ds.BalancedTree`. +**/ class TreeNode { public var left : TreeNode; public var right : TreeNode; diff --git a/std/haxe/ds/Either.hx b/std/haxe/ds/Either.hx index ca18894a..3f405a23 100644 --- a/std/haxe/ds/Either.hx +++ b/std/haxe/ds/Either.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/ds/EnumValueMap.hx b/std/haxe/ds/EnumValueMap.hx index 53d4416e..32f03155 100644 --- a/std/haxe/ds/EnumValueMap.hx +++ b/std/haxe/ds/EnumValueMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/ds/GenericStack.hx b/std/haxe/ds/GenericStack.hx index a165a988..ab022512 100644 --- a/std/haxe/ds/GenericStack.hx +++ b/std/haxe/ds/GenericStack.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,11 @@ */ package haxe.ds; +/** + A cell of `haxe.ds.GenericStack`. + + @see https://haxe.org/manual/std-GenericStack.html +**/ #if (flash || cpp) @:generic #end @@ -53,6 +58,8 @@ private class GenericStackIterator extends cpp.FastIterator { The generated name is an implementation detail and should not be relied upon. + + @see https://haxe.org/manual/std-GenericStack.html **/ #if (flash || cpp) @:generic diff --git a/std/haxe/ds/HashMap.hx b/std/haxe/ds/HashMap.hx index 616e7a8f..b9af364a 100644 --- a/std/haxe/ds/HashMap.hx +++ b/std/haxe/ds/HashMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,27 +21,61 @@ */ package haxe.ds; +/** + HashMap allows mapping of hashable objects to arbitrary values. + + See `Map` for documentation details. + + @see https://haxe.org/manual/std-Map.html +**/ abstract HashMap(HashMapData) { + /** + Creates a new HashMap. + **/ public inline function new() { this = new HashMapData(); } + + /** + See `Map.set` + **/ public inline function set(k:K, v:V) { this.keys.set(k.hashCode(), k); this.values.set(k.hashCode(), v); } + + /** + See `Map.get` + **/ public inline function get(k:K) { return this.values.get(k.hashCode()); } + + /** + See `Map.exists` + **/ public inline function exists(k:K) { return this.values.exists(k.hashCode()); } + + /** + See `Map.remove` + **/ public inline function remove(k:K) { this.values.remove(k.hashCode()); return this.keys.remove(k.hashCode()); } + + /** + See `Map.keys` + **/ public inline function keys() { return this.keys.iterator(); } + + /** + See `Map.iterator` + **/ public inline function iterator() { return this.values.iterator(); } diff --git a/std/haxe/ds/IntMap.hx b/std/haxe/ds/IntMap.hx index 3f9e8bc7..6090889d 100644 --- a/std/haxe/ds/IntMap.hx +++ b/std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,6 +25,8 @@ package haxe.ds; IntMap allows mapping of Int keys to arbitrary values. See `Map` for documentation details. + + @see https://haxe.org/manual/std-Map.html **/ extern class IntMap implements haxe.Constraints.IMap { diff --git a/std/haxe/ds/ListSort.hx b/std/haxe/ds/ListSort.hx index 63feb9c3..a1f76afa 100644 --- a/std/haxe/ds/ListSort.hx +++ b/std/haxe/ds/ListSort.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,7 +24,7 @@ package haxe.ds; /** ListSort provides a stable implementation of merge sort through its `sort` - method. It has a O(N.log(N)) complexity and does not require additional memory allocation + method. It has a O(N.log(N)) complexity and does not require additional memory allocation. **/ class ListSort { @@ -95,7 +95,7 @@ class ListSort { /** - Same as [sort] but on single linked list. + Same as `sort` but on single linked list. **/ public static inline function sortSingleLinked(list:T, cmp : T -> T -> Int) : T { if( list == null ) diff --git a/std/haxe/ds/ObjectMap.hx b/std/haxe/ds/ObjectMap.hx index c4648389..ad55de84 100644 --- a/std/haxe/ds/ObjectMap.hx +++ b/std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -29,6 +29,8 @@ package haxe.ds; to `haxe.ds.WeakMap` for a weak reference version. See `Map` for documentation details. + + @see https://haxe.org/manual/std-Map.html **/ extern class ObjectMap < K: { }, V > implements haxe.Constraints.IMap { diff --git a/std/haxe/ds/Option.hx b/std/haxe/ds/Option.hx index 7a873c6b..69037fcd 100644 --- a/std/haxe/ds/Option.hx +++ b/std/haxe/ds/Option.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,6 +25,8 @@ package haxe.ds; /** An Option is a wrapper type which can either have a value (Some) or not a value (None). + + @see https://haxe.org/manual/std-Option.html **/ enum Option { Some(v:T); diff --git a/std/haxe/ds/StringMap.hx b/std/haxe/ds/StringMap.hx index c6a86b89..ab321c3a 100644 --- a/std/haxe/ds/StringMap.hx +++ b/std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,6 +26,8 @@ package haxe.ds; StringMap allows mapping of String keys to arbitrary values. See `Map` for documentation details. + + @see https://haxe.org/manual/std-Map.html **/ extern class StringMap implements haxe.Constraints.IMap { diff --git a/std/haxe/ds/Vector.hx b/std/haxe/ds/Vector.hx index 175d686d..20ddd11d 100644 --- a/std/haxe/ds/Vector.hx +++ b/std/haxe/ds/Vector.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -33,6 +33,8 @@ private typedef VectorData = #if flash10 cs.NativeArray #elseif java java.NativeArray +#elseif lua + lua.Table #else Array #end @@ -40,6 +42,8 @@ private typedef VectorData = #if flash10 /** A Vector is a storage of fixed size. It can be faster than Array on some targets, and is never slower. + + @see https://haxe.org/manual/std-vector.html **/ abstract Vector(VectorData) { /** @@ -65,10 +69,11 @@ abstract Vector(VectorData) { #elseif java this = new java.NativeArray(length); #elseif cpp - this = new Array(); - untyped this.__SetSizeExact(length); + this = NativeArray.create(length); #elseif python this = python.Syntax.pythonCode("[{0}]*{1}", null, length); + #elseif lua + this = untyped __lua_table__({length:length}); #else this = []; untyped this.length = length; @@ -81,7 +86,7 @@ abstract Vector(VectorData) { If `index` is negative or exceeds `this.length`, the result is unspecified. **/ - @:arrayAccess public inline function get(index:Int):T { + @:op([]) public inline function get(index:Int):T { #if cpp return this.unsafeGet(index); #elseif python @@ -97,7 +102,7 @@ abstract Vector(VectorData) { If `index` is negative or exceeds `this.length`, the result is unspecified. **/ - @:arrayAccess public inline function set(index:Int, val:T):T { + @:op([]) public inline function set(index:Int, val:T):T { #if cpp return this.unsafeSet(index,val); #elseif python @@ -144,9 +149,28 @@ abstract Vector(VectorData) { #elseif cpp dest.toData().blit(destPos,src.toData(), srcPos,len); #else - for (i in 0...len) - { - dest[destPos + i] = src[srcPos + i]; + if (src == dest) { + if (srcPos < destPos) { + var i = srcPos + len; + var j = destPos + len; + for (k in 0...len) { + i--; + j--; + src[j] = src[i]; + } + } else if (srcPos > destPos) { + var i = srcPos; + var j = destPos; + for (k in 0...len) { + src[j] = src[i]; + i++; + j++; + } + } + } else { + for (i in 0...len) { + dest[destPos + i] = src[srcPos + i]; + } } #end } @@ -154,11 +178,13 @@ abstract Vector(VectorData) { /** Creates a new Array, copy the content from the Vector to it, and returns it. **/ - public #if (flash || cpp) inline #end function toArray():Array { + public #if (flash || cpp || js || java) inline #end function toArray():Array { #if cpp return this.copy(); #elseif python return this.copy(); + #elseif js + return this.slice(0); #else var a = new Array(); var len = length; @@ -211,12 +237,100 @@ abstract Vector(VectorData) { return fromData(java.Lib.nativeArray(array,false)); #elseif cs return fromData(cs.Lib.nativeArray(array,false)); + #elseif cpp + return cast array.copy(); + #elseif js + return fromData(array.slice(0)); #else - // TODO: Optimize this for flash (and others?) + // TODO: Optimize this for others? var vec = new Vector(array.length); for (i in 0...array.length) vec.set(i, array[i]); return vec; #end } + + /** + Returns a shallow copy of `this` Vector. + + The elements are not copied and retain their identity, so + `a[i] == a.copy()[i]` is true for any valid `i`. However, + `a == a.copy()` is always false. + **/ + #if cs @:extern #end public inline function copy():Vector { + var r = new Vector(length); + Vector.blit(cast this, 0, r, 0, length); + return r; + } + + /** + Returns a string representation of `this` Vector, with `sep` separating + each element. + + The result of this operation is equal to `Std.string(this[0]) + sep + + Std.string(this[1]) + sep + ... + sep + Std.string(this[this.length-1])` + + If `this` Vector has length 0, the result is the empty String `""`. + If `this` has exactly one element, the result is equal to a call to + `Std.string(this[0])`. + + If `sep` is null, the result is unspecified. + **/ + #if cs @:extern #end public inline function join(sep:String):String { + #if (flash10||cpp) + return this.join(sep); + #else + var b = new StringBuf(); + var i = 0; + var len = length; + for(i in 0...len) { + b.add( Std.string(get(i)) ); + if(i < len-1) { + b.add(sep); + } + } + return b.toString(); + #end + } + + /** + Creates a new Vector by applying function `f` to all elements of `this`. + + The order of elements is preserved. + + If `f` is null, the result is unspecified. + **/ + #if cs @:extern #end public inline function map(f:T->S):Vector { + var length = length; + var r = new Vector(length); + var i = 0; + var len = length; + for(i in 0...len) { + var v = f(get(i)); + r.set(i, v); + } + return r; + } + + /** + Sorts `this` Vector according to the comparison function `f`, where + `f(x,y)` returns 0 if x == y, a positive Int if x > y and a + negative Int if x < y. + + This operation modifies `this` Vector in place. + + The sort operation is not guaranteed to be stable, which means that the + order of equal elements may not be retained. + + If `f` is null, the result is unspecified. + **/ + public inline function sort(f:T->T->Int):Void { + #if (neko || cs || java) + throw "not yet supported"; + #elseif lua + haxe.ds.ArraySort.sort(cast this, f); + #else + this.sort(f); + #end + } } diff --git a/std/haxe/ds/WeakMap.hx b/std/haxe/ds/WeakMap.hx index c3730913..eaf983fa 100644 --- a/std/haxe/ds/WeakMap.hx +++ b/std/haxe/ds/WeakMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -28,6 +28,8 @@ package haxe.ds; The keys are considered to be weak references on static targets. See `Map` for documentation details. + + @see https://haxe.org/manual/std-Map.html **/ class WeakMap implements haxe.Constraints.IMap { diff --git a/std/haxe/extern/AsVar.hx b/std/haxe/extern/AsVar.hx new file mode 100644 index 00000000..3e95a1c5 --- /dev/null +++ b/std/haxe/extern/AsVar.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-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 haxe.extern; + +/** + If this type is used as an argument type, the compiler ensures that + argument expressions are bound to a local variable. +**/ +@:forward +@:analyzer(as_var) +abstract AsVar(T) from T to T {} \ No newline at end of file diff --git a/std/haxe/extern/EitherType.hx b/std/haxe/extern/EitherType.hx index ad027297..264bb1b4 100644 --- a/std/haxe/extern/EitherType.hx +++ b/std/haxe/extern/EitherType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,12 +22,14 @@ package haxe.extern; /** - An abstract type allowing values to be either of `T1` or `T2` type. - Supports implicit casts from/to either types. + An abstract type allowing values to be either of `T1` or `T2` type. + Supports implicit casts from/to either types. - It is useful for interfacing with external code on dynamic platforms - such as JavaScript or Python. + It is useful for interfacing with external code on dynamic platforms + such as JavaScript or Python. - Otherwise, use of this type is discouraged. + Otherwise, use of this type is discouraged. + + @see **/ abstract EitherType(Dynamic) from T1 to T1 from T2 to T2 {} diff --git a/std/haxe/extern/Rest.hx b/std/haxe/extern/Rest.hx index 494ca7c7..f15328a8 100644 --- a/std/haxe/extern/Rest.hx +++ b/std/haxe/extern/Rest.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -23,10 +23,12 @@ package haxe.extern; /** - A special abstract type that represents "rest" function argument. + A special abstract type that represents "rest" function argument. - Should be used as a type for the last argument of an extern method, - representing that arbitrary number of arguments of given type can be - passed to that method. + Should be used as a type for the last argument of an extern method, + representing that arbitrary number of arguments of given type can be + passed to that method. + + @see **/ abstract Rest(Array) {} diff --git a/std/haxe/format/JsonParser.hx b/std/haxe/format/JsonParser.hx index f7bd0fcf..9ba569c5 100644 --- a/std/haxe/format/JsonParser.hx +++ b/std/haxe/format/JsonParser.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,6 +26,8 @@ package haxe.format; This class is used by `haxe.Json` when native JSON implementation is not available. + + @see https://haxe.org/manual/std-Json-parsing.html **/ class JsonParser { @@ -33,7 +35,7 @@ class JsonParser { Parses given JSON-encoded `str` and returns the resulting object. JSON objects are parsed into anonymous structures and JSON arrays - are parsed into Array. + are parsed into `Array`. If given `str` is not valid JSON, an exception will be thrown. @@ -156,7 +158,7 @@ class JsonParser { case 'u'.code: var uc = Std.parseInt("0x" + str.substr(pos, 4)); pos += 4; - #if (neko || php || cpp) + #if (neko || php || cpp || lua) if( uc <= 0x7F ) buf.addChar(uc); else if( uc <= 0x7FF ) { diff --git a/std/haxe/format/JsonPrinter.hx b/std/haxe/format/JsonPrinter.hx index 2ae53c44..38a4e9b4 100644 --- a/std/haxe/format/JsonPrinter.hx +++ b/std/haxe/format/JsonPrinter.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,14 +26,16 @@ package haxe.format; This class is used by `haxe.Json` when native JSON implementation is not available. + + @see https://haxe.org/manual/std-Json-encoding.html **/ class JsonPrinter { /** - Encodes `o` value and returns the resulting JSON string. + Encodes `o`'s value and returns the resulting JSON string. If `replacer` is given and is not null, it is used to retrieve - actual object to be encoded. The `replacer` function two parameters, + actual object to be encoded. The `replacer` function takes two parameters, the key and the value being encoded. Initial key value is an empty string. If `space` is given and is not null, the result will be pretty-printed. @@ -82,7 +84,7 @@ class JsonPrinter { case TObject: objString(v); case TInt: - add(v); + add(#if as3 Std.string(v) #else v #end); case TFloat: add(Math.isFinite(v) ? v : 'null'); case TFunction: @@ -129,7 +131,7 @@ class JsonPrinter { var i : Dynamic = Type.enumIndex(v); add(i); case TBool: - add(#if php (v ? 'true' : 'false') #else v #end); + add(#if (php || as3) (v ? 'true' : 'false') #else v #end); case TNull: add('null'); } diff --git a/std/haxe/io/ArrayBufferView.hx b/std/haxe/io/ArrayBufferView.hx index 1f173980..475775be 100644 --- a/std/haxe/io/ArrayBufferView.hx +++ b/std/haxe/io/ArrayBufferView.hx @@ -1,4 +1,25 @@ -package haxe.io; +/* + * Copyright (C)2005-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 haxe.io; typedef ArrayBufferViewData = ArrayBufferViewImpl; diff --git a/std/haxe/io/BufferInput.hx b/std/haxe/io/BufferInput.hx index cfbdbddf..4802f553 100644 --- a/std/haxe/io/BufferInput.hx +++ b/std/haxe/io/BufferInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/io/Bytes.hx b/std/haxe/io/Bytes.hx index 3be2b22a..a70b1adc 100644 --- a/std/haxe/io/Bytes.hx +++ b/std/haxe/io/Bytes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -44,7 +44,7 @@ class Bytes { #elseif flash return b[pos]; #elseif php - return untyped __call__("ord", b[pos]); + return b.get(pos); #elseif cpp return untyped b[pos]; #elseif java @@ -62,7 +62,7 @@ class Bytes { #elseif flash b[pos] = v; #elseif php - b[pos] = untyped __call__("chr", v); + b.set(pos, v); #elseif cpp untyped b[pos] = v; #elseif java @@ -83,7 +83,7 @@ class Bytes { #if neko try untyped $sblit(b,pos,src.b,srcpos,len) catch( e : Dynamic ) throw Error.OutsideBounds; #elseif php - b = untyped __php__("substr($this->b, 0, $pos) . substr($src->b, $srcpos, $len) . substr($this->b, $pos+$len)"); //__call__("substr", b, 0, pos)+__call__("substr", src.b, srcpos, len)+__call__("substr", b, pos+len); + b.blit(pos, src.b, srcpos, len); #elseif flash b.position = pos; if( len > 0 ) b.writeBytes(src.b,srcpos,len); @@ -142,7 +142,7 @@ class Bytes { b.readBytes(b2,0,len); return new Bytes(len,b2); #elseif php - return new Bytes(len, untyped __call__("substr", b, pos, len)); + return new Bytes(len, b.sub(pos, len)); #elseif java var newarr = new java.NativeArray(len); java.lang.System.arraycopy(b, pos, newarr, 0, len); @@ -188,7 +188,7 @@ class Bytes { b2.endian = flash.utils.Endian.LITTLE_ENDIAN; return length - other.length; #elseif php - return untyped __php__("$this->b < $other->b ? -1 : ($this->b == $other->b ? 0 : 1)"); + return b.compare(other.b); //#elseif cs //TODO: memcmp if unsafe flag is on #elseif cpp @@ -209,7 +209,7 @@ class Bytes { Returns the IEEE double precision value at given position (in low endian encoding). Result is unspecified if reading outside of the bounds **/ - #if (neko_v21 || (cpp && !cppia)) inline #end + #if (neko_v21 || (cpp && !cppia) || flash) inline #end public function getDouble( pos : Int ) : Float { #if neko_v21 return untyped $sgetd(b, pos, false); @@ -228,7 +228,7 @@ class Bytes { Returns the IEEE single precision value at given position (in low endian encoding). Result is unspecified if reading outside of the bounds **/ - #if (neko_v21 || (cpp && !cppia)) inline #end + #if (neko_v21 || (cpp && !cppia) || flash) inline #end public function getFloat( pos : Int ) : Float { #if neko_v21 return untyped $sgetf(b, pos, false); @@ -248,7 +248,7 @@ class Bytes { Store the IEEE double precision value at given position in low endian encoding. Result is unspecified if writing outside of the bounds. **/ - #if neko_v21 inline #end + #if (neko_v21 || flash) inline #end public function setDouble( pos : Int, v : Float ) : Void { #if neko_v21 untyped $ssetd(b, pos, v, false); @@ -271,7 +271,7 @@ class Bytes { Store the IEEE single precision value at given position in low endian encoding. Result is unspecified if writing outside of the bounds. **/ - #if neko_v21 inline #end + #if (neko_v21 || flash) inline #end public function setFloat( pos : Int, v : Float ) : Void { #if neko_v21 untyped $ssetf(b, pos, v, false); @@ -289,7 +289,7 @@ class Bytes { } /** - Returns the 16 bit unsignged integer at given position (in low endian encoding). + Returns the 16 bit unsigned integer at given position (in low endian encoding). **/ public inline function getUInt16( pos : Int ) : Int { #if neko_v21 @@ -300,7 +300,7 @@ class Bytes { } /** - Returns the 16 bit unsignged integer at given position (in low endian encoding). + Store the 16 bit unsigned integer at given position (in low endian encoding). **/ public inline function setUInt16( pos : Int, v : Int ) : Void { #if neko_v21 @@ -319,7 +319,10 @@ class Bytes { return untyped $sget32(b, pos, false); #elseif (php || python) var v = get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos+3) << 24); - return if( v & 0x80000000 != 0 ) v | 0x80000000 else v; + return if( v & 0x80000000 != 0 ) v | 0x80000000 else v; + #elseif lua + var v = get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos+3) << 24); + return lua.Boot.clamp(if( v & 0x80000000 != 0 ) v | 0x80000000 else v); #else return get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos+3) << 24); #end @@ -364,7 +367,7 @@ class Bytes { b.position = pos; return b.readUTFBytes(len); #elseif php - return untyped __call__("substr", b, pos, len); + return b.getString(pos, len); #elseif cpp var result:String=""; untyped __global__.__hxcpp_string_of_bytes(b,result,pos,len); @@ -377,6 +380,10 @@ class Bytes { catch (e:Dynamic) throw e; #elseif python return python.Syntax.pythonCode("self.b[{0}:{0}+{1}].decode('UTF-8','replace')", pos, len); + #elseif lua + var begin = cast(Math.min(pos,b.length),Int); + var end = cast(Math.min(pos+len,b.length),Int); + return [for (i in begin...end) String.fromCharCode(b[i])].join(""); #else var s = ""; var b = b; @@ -420,7 +427,7 @@ class Bytes { b.position = 0; return b.readUTFBytes(length); #elseif php - return cast b; + return b.toString(); #elseif cs return cs.system.text.Encoding.UTF8.GetString(b, 0, length); #elseif java @@ -460,10 +467,10 @@ class Bytes { b.length = length; return new Bytes(length,b); #elseif php - return new Bytes(length, untyped __call__("str_repeat", __call__("chr", 0), length)); + return new Bytes(length, BytesData.alloc(length)); #elseif cpp var a = new BytesData(); - if (length>0) a[length-1] = untyped 0; + if (length>0) cpp.NativeArray.setSize(a, length); return new Bytes(length, a); #elseif cs return new Bytes(length, new cs.NativeArray(length)); @@ -479,6 +486,7 @@ class Bytes { #end } + @:pure public static function ofString( s : String ) : Bytes { #if neko return new Bytes(s.length,untyped __dollar__ssub(s.__s,0,s.length)); @@ -487,8 +495,8 @@ class Bytes { b.writeUTFBytes(s); return new Bytes(b.length,b); #elseif php - return new Bytes(untyped __call__("strlen", s), cast s); -// return ofData(untyped __call__("new _hx_array", __call__("array_values", __call__("unpack", "C*", s)))); + var x = BytesData.ofString(s); + return new Bytes(x.length, x); #elseif cpp var a = new BytesData(); untyped __global__.__hxcpp_bytes_of_string(a,s); @@ -508,6 +516,9 @@ class Bytes { var b:BytesData = new python.Bytearray(s, "UTF-8"); return new Bytes(b.length, b); + #elseif lua + var bytes = [for (c in 0...s.length) StringTools.fastCodeAt(s,c)]; + return new Bytes(bytes.length, bytes); #else var a = new Array(); // utf16-decode and utf8-encode @@ -543,7 +554,7 @@ class Bytes { #elseif neko return new Bytes(untyped __dollar__ssize(b),b); #elseif php - return new Bytes(untyped __call__("strlen", b), b); + return new Bytes(b.length, b); #elseif cs return new Bytes(b.Length,b); #else @@ -561,7 +572,7 @@ class Bytes { #elseif flash return b[pos]; #elseif php - return untyped __call__("ord", b[pos]); + return b.get(pos); #elseif cpp return untyped b.unsafeGet(pos); #elseif java diff --git a/std/haxe/io/BytesBuffer.hx b/std/haxe/io/BytesBuffer.hx index 1619b335..88c69735 100644 --- a/std/haxe/io/BytesBuffer.hx +++ b/std/haxe/io/BytesBuffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -97,7 +97,7 @@ class BytesBuffer { #elseif flash b.writeBytes(src.getData()); #elseif php - b += cast src.getData(); + b += src.getData().toString(); #elseif cs b.Write(src.getData(), 0, src.length); #elseif java @@ -166,7 +166,7 @@ class BytesBuffer { #elseif flash if( len > 0 ) b.writeBytes(src.getData(),pos,len); #elseif php - b += untyped __call__("substr", src.b, pos, len); + b += src.getData().sub(pos, len).toString() ; #elseif cs b.Write(src.getData(), pos, len); #elseif java @@ -196,7 +196,7 @@ class BytesBuffer { var bytes = new Bytes(b.length,b); b.position = 0; #elseif php - var bytes = new Bytes(b.length, cast b); + var bytes = new Bytes(b.length, BytesData.ofString(b)); #elseif cs var buf = b.GetBuffer(); var bytes = new Bytes(cast b.Length, buf); diff --git a/std/haxe/io/BytesData.hx b/std/haxe/io/BytesData.hx index e099af1a..271f42d6 100644 --- a/std/haxe/io/BytesData.hx +++ b/std/haxe/io/BytesData.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,10 +26,11 @@ package haxe.io; #elseif flash typedef BytesData = flash.utils.ByteArray; #elseif php - typedef BytesData = php.NativeString; + typedef BytesData = php.BytesData; +#elseif php + typedef BytesData = php.NativeString; #elseif cpp - extern class Unsigned_char__ { } - typedef BytesData = Array; + typedef BytesData = Array< cpp.UInt8 >; #elseif java typedef BytesData = java.NativeArray; #elseif cs @@ -38,6 +39,27 @@ package haxe.io; typedef BytesData = python.Bytearray; #elseif js typedef BytesData = js.html.ArrayBuffer; +#elseif hl + class BytesDataImpl { + public var bytes : hl.Bytes; + public var length : Int; + public function new(b,length) { + this.bytes = b; + this.length = length; + } + } + @:forward(bytes,length) + abstract BytesDataAbstract(BytesDataImpl) { + public inline function new(b, length) { + this = new BytesDataImpl(b, length); + } + @:arrayAccess inline function get(i:Int) return this.bytes[i]; + @:arrayAccess inline function set(i:Int,v:Int) return this.bytes[i] = v; + @:to inline function toBytes() : hl.Bytes { + return this == null ? null : this.bytes; + } + } + typedef BytesData = BytesDataAbstract; #else typedef BytesData = Array; #end diff --git a/std/haxe/io/BytesInput.hx b/std/haxe/io/BytesInput.hx index 2cc65f59..3ca2a6c2 100644 --- a/std/haxe/io/BytesInput.hx +++ b/std/haxe/io/BytesInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,7 +22,7 @@ package haxe.io; class BytesInput extends Input { - var b : #if js js.html.Uint8Array #else BytesData #end; + var b : #if js js.html.Uint8Array #elseif hl hl.Bytes #else BytesData #end; #if !flash var pos : Int; var len : Int; @@ -50,7 +50,7 @@ class BytesInput extends Input { this.b = ba; this.b.endian = flash.utils.Endian.LITTLE_ENDIAN; #else - this.b = #if js @:privateAccess b.b #else b.getData() #end; + this.b = #if (js || hl) @:privateAccess b.b #else b.getData() #end; this.pos = pos; this.len = len; this.totlen = len; @@ -97,7 +97,7 @@ class BytesInput extends Input { #if neko return untyped __dollar__sget(b,pos++); #elseif php - return untyped __call__("ord", b[pos++]); + return b.get(pos++); #elseif cpp return untyped b[pos++]; #elseif java @@ -141,7 +141,9 @@ class BytesInput extends Input { #if neko try untyped __dollar__sblit(buf.getData(),pos,b,this.pos,len) catch( e : Dynamic ) throw Error.OutsideBounds; #elseif php - untyped __php__("$buf->b = substr($buf->b, 0, $pos) . substr($this->b, $this->pos, $len) . substr($buf->b, $pos+$len)"); + buf.getData().blit(pos, b, this.pos, len); + #elseif hl + @:privateAccess buf.b.blit(pos, b, this.pos, len); #else var b1 = b; var b2 = #if js @:privateAccess buf.b #else buf.getData() #end; diff --git a/std/haxe/io/BytesOutput.hx b/std/haxe/io/BytesOutput.hx index e8f8c008..8f5ea7fa 100644 --- a/std/haxe/io/BytesOutput.hx +++ b/std/haxe/io/BytesOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -122,6 +122,12 @@ class BytesOutput extends Output { #end + /** + Returns the `Bytes` of this output. + + This function should not be called more than once on a given + `BytesOutput` instance. + **/ public function getBytes() : Bytes { #if flash var bytes = b; diff --git a/std/haxe/io/Eof.hx b/std/haxe/io/Eof.hx index 1fa64e7d..1fe3ac7a 100644 --- a/std/haxe/io/Eof.hx +++ b/std/haxe/io/Eof.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,7 +22,7 @@ package haxe.io; /** - This exception is raised when reading while data is no longer available in the [Input]. + This exception is raised when reading while data is no longer available in the `haxe.io.Input`. **/ class Eof { public function new() { diff --git a/std/haxe/io/Error.hx b/std/haxe/io/Error.hx index bdb7316a..86c9dc59 100644 --- a/std/haxe/io/Error.hx +++ b/std/haxe/io/Error.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/io/FPHelper.hx b/std/haxe/io/FPHelper.hx index 117c318c..17a04c35 100644 --- a/std/haxe/io/FPHelper.hx +++ b/std/haxe/io/FPHelper.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -140,7 +140,11 @@ class FPHelper { var af = f < 0 ? -f : f; var exp = Math.floor(Math.log(af) / LN2); if( exp < -127 ) exp = -127 else if( exp > 128 ) exp = 128; - var sig = Math.round((af / Math.pow(2, exp) - 1) * 0x800000) & 0x7FFFFF; + var sig = Math.round((af / Math.pow(2, exp) - 1) * 0x800000); + if( sig == 0x800000 && exp < 128 ){ + sig = 0; + exp++; + } return (f < 0 ? 0x80000000 : 0) | ((exp + 127) << 23) | sig; #end } @@ -191,6 +195,13 @@ class FPHelper { #elseif php return untyped __call__('unpack', 'd', __call__('pack', 'ii', isLittleEndian ? low : high, isLittleEndian ? high : low))[1]; #else + #if python + if (low == 0 && high == 2146435072) { + return Math.POSITIVE_INFINITY; + } else if (low == 0 && high == -1048576 ) { + return Math.NEGATIVE_INFINITY; + } + #end var sign = 1 - ((high >>> 31) << 1); var exp = ((high >> 20) & 0x7FF) - 1023; var sig = (high&0xFFFFF) * 4294967296. + (low>>>31) * 2147483648. + (low&0x7FFFFFFF); @@ -276,6 +287,14 @@ class FPHelper { i64.set_low(0); i64.set_high(0); } + } else if (!Math.isFinite(v)) @:privateAccess { + if (v > 0) { + i64.set_low(0); + i64.set_high(2146435072); + } else { + i64.set_low(0); + i64.set_high(-1048576); + } } else { var av = v < 0 ? -v : v; var exp = Math.floor(Math.log(av) / LN2); diff --git a/std/haxe/io/Float32Array.hx b/std/haxe/io/Float32Array.hx index a45d84ce..2fb078b7 100644 --- a/std/haxe/io/Float32Array.hx +++ b/std/haxe/io/Float32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/io/Float64Array.hx b/std/haxe/io/Float64Array.hx index 6747ee1d..8f5314fe 100644 --- a/std/haxe/io/Float64Array.hx +++ b/std/haxe/io/Float64Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/io/Input.hx b/std/haxe/io/Input.hx index b1f9ff5b..158b7956 100644 --- a/std/haxe/io/Input.hx +++ b/std/haxe/io/Input.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,6 +24,9 @@ package haxe.io; /** An Input is an abstract reader. See other classes in the `haxe.io` package for several possible implementations. + + All functions which read data throw `Eof` when the end of the stream + is reached. **/ class Input { @@ -60,23 +63,25 @@ class Input { **/ public function readBytes( s : Bytes, pos : Int, len : Int ) : Int { var k = len; - var b = #if js @:privateAccess s.b #else s.getData() #end; + var b = #if (js || hl) @:privateAccess s.b #else s.getData() #end; if( pos < 0 || len < 0 || pos + len > s.length ) throw Error.OutsideBounds; - while( k > 0 ) { - #if neko - untyped __dollar__sset(b,pos,readByte()); - #elseif php - b[pos] = untyped __call__("chr", readByte()); - #elseif cpp - b[pos] = untyped readByte(); - #else - b[pos] = cast readByte(); - #end - pos++; - k--; - } - return len; + try { + while( k > 0 ) { + #if neko + untyped __dollar__sset(b,pos,readByte()); + #elseif php + b.set(pos, readByte()); + #elseif cpp + b[pos] = untyped readByte(); + #else + b[pos] = cast readByte(); + #end + pos++; + k--; + } + } catch (eof: haxe.io.Eof){} + return len-k; } /** @@ -117,8 +122,7 @@ class Input { throw Error.Blocked; total.addBytes(buf,0,len); } - } catch( e : Eof ) { - } + } catch( e : Eof ) { } return total.getBytes(); } @@ -130,6 +134,8 @@ class Input { public function readFullBytes( s : Bytes, pos : Int, len : Int ) : Void { while( len > 0 ) { var k = readBytes(s,pos,len); + if (k == 0) + throw Error.Blocked; pos += k; len -= k; } @@ -156,11 +162,11 @@ class Input { The final character is not included in the resulting string. **/ public function readUntil( end : Int ) : String { - var buf = new StringBuf(); + var buf = new BytesBuffer(); var last : Int; while( (last = readByte()) != end ) - buf.addChar( last ); - return buf.toString(); + buf.addByte( last ); + return buf.getBytes().toString(); } /** @@ -169,16 +175,16 @@ class Input { The CR/LF characters are not included in the resulting string. **/ public function readLine() : String { - var buf = new StringBuf(); + var buf = new BytesBuffer(); var last : Int; var s; try { while( (last = readByte()) != 10 ) - buf.addChar( last ); - s = buf.toString(); + buf.addByte( last ); + s = buf.getBytes().toString(); if( s.charCodeAt(s.length-1) == 13 ) s = s.substr(0,-1); } catch( e : Eof ) { - s = buf.toString(); + s = buf.getBytes().toString(); if( s.length == 0 ) #if neko neko.Lib.rethrow #else throw #end (e); } @@ -190,7 +196,7 @@ class Input { Endianness is specified by the `bigEndian` property. **/ - public #if !(flash || python) inline #end function readFloat() : Float { + public function readFloat() : Float { return FPHelper.i32ToFloat(readInt32()); } @@ -278,11 +284,14 @@ class Input { var ch3 = readByte(); var ch4 = readByte(); #if (php || python) - // php will overflow integers. Convert them back to signed 32-bit ints. - var n = bigEndian ? ch4 | (ch3 << 8) | (ch2 << 16) | (ch1 << 24) : ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24); - if (n & 0x80000000 != 0) - return ( n | 0x80000000); - else return n; + // php will overflow integers. Convert them back to signed 32-bit ints. + var n = bigEndian ? ch4 | (ch3 << 8) | (ch2 << 16) | (ch1 << 24) : ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24); + if (n & 0x80000000 != 0) + return ( n | 0x80000000); + else return n; +#elseif lua + var n = bigEndian ? ch4 | (ch3 << 8) | (ch2 << 16) | (ch1 << 24) : ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24); + return lua.Boot.clamp(n); #else return bigEndian ? ch4 | (ch3 << 8) | (ch2 << 16) | (ch1 << 24) : ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24); #end @@ -307,18 +316,15 @@ class Input { static function __init__() untyped { Input.prototype.bigEndian = false; } -#elseif cpp - static var _float_of_bytes = cpp.Lib.load("std","float_of_bytes",2); - static var _double_of_bytes = cpp.Lib.load("std","double_of_bytes",2); #end #if (flash || js || python) function getDoubleSig(bytes:Array) - { - return (((bytes[1]&0xF) << 16) | (bytes[2] << 8) | bytes[3] ) * 4294967296. + - (bytes[4] >> 7) * 2147483648 + - (((bytes[4]&0x7F) << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7]); - } + { + return (((bytes[1]&0xF) << 16) | (bytes[2] << 8) | bytes[3] ) * 4294967296. + + (bytes[4] >> 7) * 2147483648 + + (((bytes[4]&0x7F) << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7]); + } #end } diff --git a/std/haxe/io/Int32Array.hx b/std/haxe/io/Int32Array.hx index 29a04343..56131f81 100644 --- a/std/haxe/io/Int32Array.hx +++ b/std/haxe/io/Int32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/io/Output.hx b/std/haxe/io/Output.hx index 6147ee06..3a830ecb 100644 --- a/std/haxe/io/Output.hx +++ b/std/haxe/io/Output.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -23,8 +23,8 @@ package haxe.io; /** An Output is an abstract write. A specific output implementation will only - have to override the [writeByte] and maybe the [write], [flush] and [close] - methods. See [File.write] and [String.write] for two ways of creating an + have to override the `writeByte` and maybe the `write`, `flush` and `close` + methods. See `File.write` and `String.write` for two ways of creating an Output. **/ class Output { @@ -55,19 +55,21 @@ class Output { See `writeFullBytes` that tries to write the exact amount of specified bytes. **/ public function writeBytes( s : Bytes, pos : Int, len : Int ) : Int { - var k = len; - var b = s.getData(); #if !neko if( pos < 0 || len < 0 || pos + len > s.length ) throw Error.OutsideBounds; #end + var b = #if js @:privateAccess s.b #else s.getData() #end; + var k = len; while( k > 0 ) { #if neko writeByte(untyped __dollar__sget(b,pos)); #elseif php - writeByte(untyped __call__("ord", b[pos])); + writeByte(b.get(pos)); #elseif cpp writeByte(untyped b[pos]); + #elseif hl + writeByte(b[pos]); #else writeByte(untyped b[pos]); #end @@ -130,7 +132,7 @@ class Output { Endianness is specified by the `bigEndian` property. **/ - public #if !(flash || python) inline #end function writeFloat( x : Float ) { + public function writeFloat( x : Float ) { writeInt32(FPHelper.floatToI32(x)); } diff --git a/std/haxe/io/Path.hx b/std/haxe/io/Path.hx index 8a8e9ad9..7bf4906f 100644 --- a/std/haxe/io/Path.hx +++ b/std/haxe/io/Path.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,7 +26,7 @@ package haxe.io; common path formats: - directory1/directory2/filename.extension - - directory1\directory2\filename.excention + - directory1\directory2\filename.extension **/ class Path { @@ -111,7 +111,7 @@ class Path { If `this.directory` or `this.extension` is null, their representation is the empty String "". **/ - public function toString() { + public function toString() : String { return (if( dir == null ) "" else dir + if( backslash ) "\\" else "/") + file + (if( ext == null ) "" else "." + ext); } @@ -120,7 +120,7 @@ class Path { If `path` is null, the result is unspecified. **/ - public static function withoutExtension( path : String ) { + public static function withoutExtension( path : String ) : String { var s = new Path(path); s.ext = null; return s.toString(); @@ -131,7 +131,7 @@ class Path { If `path` is null, the result is unspecified. **/ - public static function withoutDirectory( path ) { + public static function withoutDirectory( path ) : String { var s = new Path(path); s.dir = null; return s.toString(); @@ -140,11 +140,11 @@ class Path { /** Returns the directory of `path`. - If the directory is null, the empty String "" is returned. + If the directory is null, the empty String `""` is returned. If `path` is null, the result is unspecified. **/ - public static function directory( path ) { + public static function directory( path ) : String { var s = new Path(path); if( s.dir == null ) return ""; @@ -154,11 +154,11 @@ class Path { /** Returns the extension of `path`. - If the extension is null, the empty String "" is returned. + If the extension is null, the empty String `""` is returned. If `path` is null, the result is unspecified. **/ - public static function extension( path ) { + public static function extension( path ) : String { var s = new Path(path); if( s.ext == null ) return ""; @@ -172,7 +172,7 @@ class Path { If `path` or `ext` are null, the result is unspecified. **/ - public static function withExtension( path, ext ) { + public static function withExtension( path, ext ) : String { var s = new Path(path); s.ext = ext; return s.toString(); @@ -208,11 +208,9 @@ class Path { If `path` is null, the result is unspecified. **/ public static function normalize(path : String) : String { - var slash = '/'; - path = path.split("\\").join("/"); - if( path == null || path == slash ) { - return slash; - } + var slash = "/"; + path = path.split("\\").join(slash); + if (path == slash) return slash; var target = []; @@ -231,11 +229,11 @@ class Path { var colon = false; var slashes = false; for (i in 0...tmp.length) { - switch (tmp.charCodeAt(i)) { + switch (StringTools.fastCodeAt(tmp, i)) { case ":".code: acc.add(":"); colon = true; - case "/".code if (colon == false): + case "/".code if (!colon): slashes = true; case i: colon = false; @@ -243,11 +241,10 @@ class Path { acc.add("/"); slashes = false; } - acc.add(String.fromCharCode(i)); + acc.addChar(i); } } - var result = acc.toString(); - return result; + return acc.toString(); } /** @@ -258,7 +255,7 @@ class Path { If the last slash in `path` is a slash, or if no slash is found, a slash is appended to `path`. In particular, this applies to the empty String - "". + `""`. If `path` is null, the result is unspecified. **/ diff --git a/std/haxe/io/StringInput.hx b/std/haxe/io/StringInput.hx index 2cf40b93..95b0416b 100644 --- a/std/haxe/io/StringInput.hx +++ b/std/haxe/io/StringInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/io/UInt16Array.hx b/std/haxe/io/UInt16Array.hx index 6fad64a0..978e406c 100644 --- a/std/haxe/io/UInt16Array.hx +++ b/std/haxe/io/UInt16Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/io/UInt32Array.hx b/std/haxe/io/UInt32Array.hx index fe2c5a85..128a39bf 100644 --- a/std/haxe/io/UInt32Array.hx +++ b/std/haxe/io/UInt32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/io/UInt8Array.hx b/std/haxe/io/UInt8Array.hx index e40a6727..5f5f64c6 100644 --- a/std/haxe/io/UInt8Array.hx +++ b/std/haxe/io/UInt8Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/macro/CompilationServer.hx b/std/haxe/macro/CompilationServer.hx new file mode 100644 index 00000000..a30ced04 --- /dev/null +++ b/std/haxe/macro/CompilationServer.hx @@ -0,0 +1,84 @@ +package haxe.macro; + +import haxe.macro.Compiler; + +@:enum +abstract ModuleCheckPolicy(Int) { + /** + Disables file modification checks, avoiding some filesystem operations. + **/ + var NoCheckFileTimeModification = 0; + + /** + If a file is modified, also checks if its content changed. This check + is not free, but useful when .hx files are auto-generated. + **/ + var CheckFileContentModification = 1; + + /** + Disables dependency checks of the module. + **/ + var NoCheckDependencies = 2; + + /** + Disables file shadowing checks. Shadowing can occur when a new file + is added to a class-path that has higher priority than the class-path + of the current module file. + **/ + var NoCheckShadowing = 3; +} + +@:enum abstract ContextOptions(Int) { + /** + Affects only the normal context. + **/ + var NormalContext = 0; + + /** + Affects only the macro context. + **/ + var MacroContext = 1; + + /** + Affects the normal and macro contexts. + **/ + var NormalAndMacroContext = 2; +} + +/** + This class provides some methods which can be invoked from command line using + `--macro server.field(args)`. +**/ +class CompilationServer { + #if macro + + /** + Sets the `ModuleCheckPolicy` of all files whose dot-path matches an + element of `pathFilters`. + + If `recursive` is true, a dot-path is considered matched if it starts + with the path filter. This automatically applies to path filters of + packages. Otherwise an exact match is required. + + If an element in `pathFilters` is the empty String `""` it matches + everything (if `recursive = true`) or only top-level types (if + `recursive = false`). + + The argument `contextOptions` determines which context (normal, macro + or both) this affects. + + If a call to this function is added to the compilation parameters, the + compilation server should be restarted to ensure it takes effect. + **/ + static public function setModuleCheckPolicy(pathFilters:Array, policy:Array, ?recursive = true, ?contextOptions:ContextOptions = NormalContext) { + @:privateAccess Compiler.load("server_add_module_check_policy", 4)(pathFilters, policy, recursive, contextOptions); + } + + /** + Invalidates all files given in `filePaths`, removing them from the cache. + **/ + static public function invalidateFiles(filePaths:Array) { + @:privateAccess Compiler.load("server_invalidate_files", 1)(filePaths); + } + #end +} \ No newline at end of file diff --git a/std/haxe/macro/Compiler.hx b/std/haxe/macro/Compiler.hx index b6be6494..ae170e8d 100644 --- a/std/haxe/macro/Compiler.hx +++ b/std/haxe/macro/Compiler.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,76 +25,143 @@ import haxe.macro.Expr; /** All these methods can be called for compiler configuration macros. **/ +#if hl +@:hlNative("macro") +#end class Compiler { + /** + A conditional compiler flag can be set command line using + `-D key=value`. + + Returns the value of a compiler flag. + + If the compiler flag is defined but no value is set, + `Compiler.getDefine` returns `"1"` (e.g. `-D key`). + If the compiler flag is not defined, `Compiler.getDefine` returns + `null`. + + @see https://haxe.org/manual/lf-condition-compilation.html + **/ macro static public function getDefine( key : String ) { return macro $v{haxe.macro.Context.definedValue(key)}; } -#if neko +#if (neko || (macro && hl)) static var ident = ~/^[A-Za-z_][A-Za-z0-9_]*$/; static var path = ~/^[A-Za-z_][A-Za-z0-9_.]*$/; public static function allowPackage( v : String ) { - untyped load("allow_package", 1)(v.__s); + #if neko + load("allow_package", 1)(v); + #end } - public static function define( flag : String, ?value : String ) untyped { - var v = flag + (value == null ? "" : "=" + value); - load("define", 1)(v.__s); + /** + Set a conditional compiler flag. + **/ + public static function define( flag : String, ?value : String ) { + #if neko + load("define", 2)(flag,value); + #end } + #if !neko + private static function typePatch( cl : String, f : String, stat : Bool, t : String ) { + } + private static function metaPatch( meta : String, cl : String, f : String, stat : Bool ) { + } + private static function addGlobalMetadataImpl(pathFilter:String, meta:String, recursive:Bool, toTypes:Bool, toFields:Bool) { + } + #end + + /** + Removes a (static) field from a given class by name. + An error is thrown when `className` or `field` is invalid. + **/ public static function removeField( className : String, field : String, ?isStatic : Bool ) { if( !path.match(className) ) throw "Invalid "+className; - if( !ident.match(field) ) throw "Invalid "+field; - untyped load("type_patch",4)(className.__s,field.__s,isStatic == true,null); + if( !ident.match(field) ) throw "Invalid " + field; + #if neko + load("type_patch", 4)(className, field, isStatic == true, null); + #else + typePatch(className, field, isStatic == true, null); + #end } + /** + Set the type of a (static) field at a given class by name. + An error is thrown when `className` or `field` is invalid. + **/ public static function setFieldType( className : String, field : String, type : String, ?isStatic : Bool ) { if( !path.match(className) ) throw "Invalid "+className; if( !ident.match((field.charAt(0) == "$") ? field.substr(1) : field) ) throw "Invalid "+field; - untyped load("type_patch",4)(className.__s,field.__s,isStatic == true,type.__s); + #if neko + load("type_patch", 4)(className, field, isStatic == true, type); + #else + typePatch(className, field, isStatic == true, type); + #end } + /** + Add metadata to a (static) field or class by name. + An error is thrown when `className` or `field` is invalid. + **/ public static function addMetadata( meta : String, className : String, ?field : String, ?isStatic : Bool ) { if( !path.match(className) ) throw "Invalid "+className; if( field != null && !ident.match(field) ) throw "Invalid "+field; - untyped load("meta_patch",4)(meta.__s,className.__s,(field == null)?null:field.__s,isStatic == true); + #if neko + load("meta_patch", 4)(meta, className, field, isStatic == true); + #else + metaPatch(meta, className, field, isStatic == true); + #end } public static function addClassPath( path : String ) { - untyped load("add_class_path",1)(path.__s); + #if neko + load("add_class_path", 1)(path); + #end } public static function getOutput() : String { - return new String(untyped load("get_output",0)()); + #if neko + return load("get_output", 0)(); + #else + return null; + #end } public static function setOutput( fileOrDir : String ) { - untyped load("set_output",1)(untyped fileOrDir.__s); + #if neko + load("set_output", 1)(fileOrDir); + #end } public static function getDisplayPos() : Null<{ file : String, pos : Int }> { - var o = untyped load("get_display_pos",0)(); - if( o != null ) - o.file = new String(o.file); - return o; + #if neko + return load("get_display_pos", 0)(); + #else + return null; + #end } /** - Adds a native library depending on the platform (eg : -swf-lib for Flash) + Adds a native library depending on the platform (e.g. `-swf-lib` for Flash). **/ public static function addNativeLib( name : String ) { - untyped load("add_native_lib",1)(name.__s); + #if neko + load("add_native_lib", 1)(name); + #end } /** - Adds an argument to be passed to the native compiler (eg : -javac-arg for Java) + Adds an argument to be passed to the native compiler (e.g. `-javac-arg` for Java). **/ - public static function addNativeArg( argument : String ) - { - untyped load("add_native_arg",1)(argument.__s); + public static function addNativeArg( argument : String ) { + #if neko + load("add_native_arg", 1)(argument); + #end } /** @@ -111,8 +178,9 @@ class Compiler { @param ignore Array of module names to ignore for inclusion. @param classPaths An alternative array of paths (directory names) to use to search for modules to include. Note that if you pass this argument, only the specified paths will be used for inclusion. + @param strict If true and given package wasn't found in any of class paths, fail with an error. **/ - public static function include( pack : String, ?rec = true, ?ignore : Array, ?classPaths : Array ) { + public static function include( pack : String, ?rec = true, ?ignore : Array, ?classPaths : Array, strict = false ) { var skip = if( ignore == null ) { function(c) return false; } else { @@ -138,12 +206,14 @@ class Compiler { } } var prefix = pack == '' ? '' : pack + '.'; + var found = false; for( cp in classPaths ) { var path = pack == '' ? cp : cp + "/" + pack.split(".").join("/"); if( !sys.FileSystem.exists(path) || !sys.FileSystem.isDirectory(path) ) continue; + found = true; for( file in sys.FileSystem.readDirectory(path) ) { - if( StringTools.endsWith(file, ".hx") ) { + if( StringTools.endsWith(file, ".hx") && file.substr(0, file.length - 3).indexOf(".") < 0 ) { var cl = prefix + file.substr(0, file.length - 3); if( skip(cl) ) continue; @@ -152,10 +222,12 @@ class Compiler { include(prefix + file, true, ignore, classPaths); } } + if (strict && !found) + Context.error('Package "$pack" was not found in any of class paths', Context.currentPos()); } /** - Exclude a class or a enum without changing it to @:nativeGen. + Exclude a class or an enum without changing it to `@:nativeGen`. **/ static function excludeBaseType( baseType : Type.BaseType ) : Void { if (!baseType.isExtern) { @@ -168,7 +240,10 @@ class Compiler { } /** - Exclude a given class or a complete package from being generated. + Exclude a specific class, enum, or all classes and enums in a + package from being generated. Excluded types become `extern`. + + @param rec If true, recursively excludes all sub-packages. **/ public static function exclude( pack : String, ?rec = true ) { Context.onGenerate(function(types) { @@ -191,7 +266,7 @@ class Compiler { } /** - Exclude classes listed in an extern file (one per line) from being generated. + Exclude classes and enums listed in an extern file (one per line) from being generated. **/ public static function excludeFile( fileName : String ) { fileName = Context.resolvePath(fileName); @@ -218,7 +293,7 @@ class Compiler { } /** - Load a type patch file that can modify declared classes fields types + Load a type patch file that can modify the field types within declared classes and enums. **/ public static function patchTypes( file : String ) : Void { var file = Context.resolvePath(file); @@ -275,7 +350,7 @@ class Compiler { In order to include module sub-types directly, their full dot path including the containing module has to be used - (e.g. msignal.Signal.Signal0). + (e.g. `msignal.Signal.Signal0`). This operation has no effect if the type has already been loaded, e.g. through `Context.getType`. @@ -309,44 +384,68 @@ class Compiler { through `Context.getType`. **/ public static function addGlobalMetadata(pathFilter:String, meta:String, ?recursive:Bool = true, ?toTypes:Bool = true, ?toFields:Bool = false) { - untyped load("add_global_metadata",5)(untyped pathFilter.__s, meta.__s, recursive, toTypes, toFields); + #if neko + load("add_global_metadata_impl", 5)(pathFilter, meta, recursive, toTypes, toFields); + #else + addGlobalMetadataImpl(pathFilter, meta, recursive, toTypes, toFields); + #end } /** Change the default JS output by using a custom generator callback **/ public static function setCustomJSGenerator( callb : JSGenApi -> Void ) { - load("custom_js",1)(callb); + #if neko + load("set_custom_js_generator", 1)(callb); + #end } - static function load( f, nargs ) : Dynamic { - #if macro - return neko.Lib.load("macro", f, nargs); - #else - return Reflect.makeVarArgs(function(_) return throw "Can't be called outside of macro"); - #end + #if neko + static inline function load( f, nargs ) : Dynamic { + return @:privateAccess Context.load(f, nargs); } + #end #end - #if (js || macro) + #if (js || lua || macro) /** - Embed an on-disk javascript file (can be called into an __init__ method) + Embed a JavaScript file at compile time (can be called by `--macro` or within an `__init__` method). **/ - public static macro function includeFile( fileName : Expr ) { - var str = switch( fileName.expr ) { - case EConst(c): - switch( c ) { - case CString(str): str; - default: null; - } - default: null; + public static #if !macro macro #end function includeFile( file : String, position:IncludePosition = Top ) { + return switch ((position:String).toLowerCase()) { + case Inline: + if (Context.getLocalModule() == "") + Context.error("Cannot use inline mode when includeFile is called by `--macro`", Context.currentPos()); + + var f = try sys.io.File.getContent(Context.resolvePath(file)) catch( e : Dynamic ) Context.error(Std.string(e), Context.currentPos()); + var p = Context.currentPos(); + { expr : EUntyped( { expr : ECall( { expr : EConst(CIdent("__js__")), pos : p }, [ { expr : EConst(CString(f)), pos : p } ]), pos : p } ), pos : p }; + case Top | Closure: + @:privateAccess Context.includeFile(file, position); + macro {}; + case _: + Context.error("unknown includeFile position: " + position, Context.currentPos()); } - if( str == null ) Context.error("Should be a constant string", fileName.pos); - var f = try sys.io.File.getContent(Context.resolvePath(str)) catch( e : Dynamic ) Context.error(Std.string(e), fileName.pos); - var p = Context.currentPos(); - return { expr : EUntyped( { expr : ECall( { expr : EConst(CIdent("__js__")), pos : p }, [ { expr : EConst(CString(f)), pos : p } ]), pos : p } ), pos : p }; } + #end } + +@:enum abstract IncludePosition(String) from String to String { + /** + Prepend the file content to the output file. + */ + var Top = "top"; + /** + Prepend the file content to the body of the top-level closure. + + Since the closure is in strict-mode, there may be run-time error if the input is not strict-mode-compatible. + */ + var Closure = "closure"; + /** + Directly inject the file content at the call site. + */ + var Inline = "inline"; +} diff --git a/std/haxe/macro/ComplexTypeTools.hx b/std/haxe/macro/ComplexTypeTools.hx index e4682f00..cb546f15 100644 --- a/std/haxe/macro/ComplexTypeTools.hx +++ b/std/haxe/macro/ComplexTypeTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,15 +26,15 @@ import haxe.macro.Expr; /** This class provides some utility methods to work with AST-level types. It is - best used through 'using haxe.macro.ComplexTypeTools' syntax and then provides - additional methods on haxe.macro.Expr.ComplexType instances. + best used through `using haxe.macro.ComplexTypeTools` syntax and then provides + additional methods on `haxe.macro.ComplexType` instances. **/ class ComplexTypeTools { /** - Converts type [c] to a human-readable String representation. + Converts type `c` to a human-readable `String` representation. - The result is guaranteed to be valid haxe code, but there may be + The result is guaranteed to be valid Haxe code, but there may be differences from the original lexical syntax. **/ static public function toString( c : ComplexType ) : String @@ -43,12 +43,12 @@ class ComplexTypeTools { #if macro /** - Returns a type corresponding to [c]. + Returns a type corresponding to `c`. - If [c] is null, the result is null. + If `c` is null, the result is null. **/ static public function toType( c : ComplexType ) : Null - return c == null ? null : haxe.macro.Context.typeof( { expr: ECheckType(macro null, c), pos: Context.currentPos() } ); + return c == null ? null : Context.resolveType(c,Context.currentPos()); #end -} \ No newline at end of file +} diff --git a/std/haxe/macro/Context.hl.hx b/std/haxe/macro/Context.hl.hx new file mode 100644 index 00000000..2437d9b7 --- /dev/null +++ b/std/haxe/macro/Context.hl.hx @@ -0,0 +1,243 @@ +/* + * Copyright (C)2005-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 haxe.macro; + +import haxe.macro.Expr; +import haxe.macro.Type.TypedExpr; + +@:noDoc @:hlNative("macro") +class Context { + +#if macro + + public static function error( msg : String, pos : Position ) : Dynamic { + return null; + } + + public static function fatalError( msg : String, pos : Position ) : Dynamic { + return null; + } + + public static function warning( msg : String, pos : Position ) : Void { + } + + public static function resolvePath( file : String ) : String { + return null; + } + + public static function getClassPath() : Array { + return null; + } + + public static function currentPos() : Position { + return null; + } + + @:require(haxe_ver >= 3.1) + public static function getExpectedType():Null { + return null; + } + + @:require(haxe_ver >= 3.2) + public static function getCallArguments():Null> { + return null; + } + + public static function getLocalClass() : Null> { + var l = getLocalType(); + if( l == null ) return null; + return switch( l ) { + case TInst(c,_): c; + default: null; + } + } + + public static function getLocalModule() : String { + return null; + } + + public static function getLocalType() : Null { + return null; + } + + public static function getLocalMethod() : Null { + return null; + } + + public static function getLocalUsing() : Array> { + return null; + } + + public static function getLocalImports() : Array { + return null; + } + + private static function localVars(b:Bool) : Map { + return null; + } + + @:deprecated("Use Context.getLocalTVars() instead") + public static function getLocalVars() : Map { + return cast localVars(false); + } + + @:require(haxe_ver >= 3.102) + public static function getLocalTVars() : Map { + return cast localVars(true); + } + + public static function defined( s : String ) : Bool { + return null; + } + + public static function definedValue( key : String ) : String { + return null; + } + + public static function getDefines() : Map { + return null; + } + + public static function getType( name : String ) : Type { + return null; + } + + public static function getModule( name : String ) : Array { + return null; + } + + static function doParse( expr : String, pos : Position, isInline : Bool ) : Expr { + return null; + } + + public static function parse( expr : String, pos : Position ) : Expr { + return doParse(expr,pos,false); + } + + public static function parseInlineString( expr : String, pos : Position ) : Expr { + return doParse(expr,pos,true); + } + + public static function makeExpr( v : Dynamic, pos : Position ) : Expr { + return null; + } + + public static function signature( v : Dynamic ) : String { + return null; + } + + public static function onGenerate( callback : Array -> Void ) : Void { + } + + @:require(haxe_ver >= 3.1) + public static function onAfterGenerate( callback : Void -> Void ) : Void { + } + + public static function onAfterTyping( callback : Array -> Void ) : Void { + } + + public static function onTypeNotFound ( callback : String -> TypeDefinition ) : Void { + } + + public static function typeof( e : Expr ) : Type { + return null; + } + + @:require(haxe_ver >= 3.1) + public static function typeExpr( e : Expr ) : TypedExpr { + return null; + } + + @:require(haxe_ver >= 3.3) + public static function resolveType( t : ComplexType, p : Position ) : Type { + return null; + } + + public static function toComplexType( t : Type ) : Null { + return null; + } + + public static function unify( t1 : Type, t2 : Type) : Bool { + return false; + } + + public static function follow( t : Type, ?once : Bool ) : Type { + return null; + } + + public static function followWithAbstracts(t : Type, once : Bool = false ) : Type { + return null; + } + + public static function getPosInfos( p : Position ) : { min : Int, max : Int, file : String } { + return null; + } + + public static function makePosition( inf : { min : Int, max : Int, file : String } ) : Position { + return null; + } + + public static function getResources():Map { + return null; + } + + public static function addResource( name : String, data : haxe.io.Bytes ) : Void { + } + + public static function getBuildFields() : Array { + return null; + } + + public static function defineType( t : TypeDefinition ) : Void { + } + + public static function defineModule( modulePath : String, types : Array, ?imports: Array, ?usings : Array ) : Void { + } + + public static function getTypedExpr( t : Type.TypedExpr ) : Expr { + return null; + } + + @:require(haxe_ver >= 3.2) + public static function storeTypedExpr( t : Type.TypedExpr ) : Expr { + return null; + } + + public static function registerModuleDependency( modulePath : String, externFile : String ) : Void { + } + + public static function registerModuleReuseCall( modulePath : String, macroCall : String ) : Void { + } + + public static function onMacroContextReused( callb : Void -> Bool ) : Void { + } + + private static function includeFile( file : String, position : String ) { + } + + private static function sExpr( e : TypedExpr, pretty : Bool ) : String { + return null; + } + +#end + +} diff --git a/std/haxe/macro/Context.hx b/std/haxe/macro/Context.hx index f38b45d5..fc23aaca 100644 --- a/std/haxe/macro/Context.hx +++ b/std/haxe/macro/Context.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -44,7 +44,7 @@ class Context { and aborts the current macro call. **/ public static function error( msg : String, pos : Position ) : Dynamic { - return load("error",2)(untyped msg.__s, pos); + return load("error",2)(msg, pos); } /** @@ -52,14 +52,14 @@ class Context { and aborts the compilation. **/ public static function fatalError( msg : String, pos : Position ) : Dynamic { - return load("fatal_error",2)(untyped msg.__s, pos); + return load("fatal_error",2)(msg, pos); } /** Displays a compilation warning `msg` at the given `Position` `pos`. **/ public static function warning( msg : String, pos : Position ) { - load("warning",2)(untyped msg.__s, pos); + load("warning",2)(msg, pos); } /** @@ -71,8 +71,8 @@ class Context { If a class path was declared relative, this method returns the relative file path. Otherwise it returns the absolute file path. **/ - public static function resolvePath( file : String ) { - return new String(load("resolve",1)(untyped file.__s)); + public static function resolvePath( file : String ) : String { + return load("resolve_path",1)(file); } /** @@ -83,18 +83,14 @@ class Context { can be added using `haxe.macro.Compiler.addClassPath`. **/ public static function getClassPath() : Array { - var c : neko.NativeArray = load("class_path",0)(); - var a = new Array(); - for( i in 0...neko.NativeArray.length(c) ) - a.push(Std.string(c[i])); - return a; + return load("class_path",0)(); } /** Returns the position at which the macro was called. **/ public static function currentPos() : Position { - return load("curpos", 0)(); + return load("current_pos", 0)(); } /** @@ -108,9 +104,7 @@ class Context { **/ @:require(haxe_ver >= 3.1) public static function getExpectedType():Null { - var l : Type = load("expected_type", 0)(); - if( l == null ) return null; - return l; + return load("get_expected_type", 0)(); } /** @@ -121,7 +115,7 @@ class Context { **/ @:require(haxe_ver >= 3.2) public static function getCallArguments():Null> { - return load("call_arguments", 0)(); + return load("get_call_arguments", 0)(); } /** @@ -130,7 +124,7 @@ class Context { If no such class exists, null is returned. **/ public static function getLocalClass() : Null> { - var l : Type = load("local_type", 0)(); + var l : Type = load("get_local_type", 0)(); if( l == null ) return null; return switch( l ) { case TInst(c,_): c; @@ -142,7 +136,7 @@ class Context { Returns the current module path in/on which the macro was called. **/ public static function getLocalModule() : String { - return new String(load("local_module", 0)()); + return load("get_local_module", 0)(); } /** @@ -151,9 +145,7 @@ class Context { If no such type exists, null is returned. **/ public static function getLocalType() : Null { - var l : Type = load("local_type", 0)(); - if( l == null ) return null; - return l; + return load("get_local_type", 0)(); } /** @@ -162,9 +154,7 @@ class Context { If no such method exists, null is returned. **/ public static function getLocalMethod() : Null { - var l : String = load("local_method", 0)(); - if (l == "") return null; - return new String(l); + return load("get_local_method", 0)(); } /** @@ -173,8 +163,17 @@ class Context { Modifying the returned array has no effect on the compiler. **/ - public static function getLocalUsing() : Array> { - return load("local_using", 0)(); + public static function getLocalUsing() : Array> { + return load("get_local_using", 0)(); + } + + /** + Returns an `Array` of all imports in the context the macro was called. + + Modifying the returned array has no effect on the compiler. + **/ + public static function getLocalImports() : Array { + return load("get_local_imports", 0)(); } /** @@ -207,7 +206,7 @@ class Context { by calling `haxe.macro.Compiler.define`. **/ public static function defined( s : String ) : Bool { - return load("defined", 1)(untyped s.__s); + return load("defined", 1)(s); } /** @@ -221,8 +220,7 @@ class Context { The default value is `"1"`. **/ public static function definedValue( key : String ) : String { - var d = load("defined_value", 1)(untyped key.__s); - return d == null ? null : new String(d); + return load("defined_value", 1)(key); } /** @@ -246,7 +244,7 @@ class Context { If no type can be found, an exception of type `String` is thrown. **/ public static function getType( name : String ) : Type { - return load("get_type", 1)(untyped name.__s); + return load("get_type", 1)(name); } /** @@ -259,11 +257,11 @@ class Context { If no module can be found, null is returned. **/ public static function getModule( name : String ) : Array { - return load("get_module", 1)(untyped name.__s); + return load("get_module", 1)(name); } /** - Parses `expr` as haxe code, returning the corresponding AST. + Parses `expr` as Haxe code, returning the corresponding AST. String interpolation of single quote strings within `expr` is not supported. @@ -271,7 +269,7 @@ class Context { The provided `Position` `pos` is used for all generated inner AST nodes. **/ public static function parse( expr : String, pos : Position ) : Expr { - return load("parse", 3)(untyped expr.__s, pos, false); + return load("do_parse", 3)(expr, pos, false); } /** @@ -279,7 +277,7 @@ class Context { String `expr`. **/ public static function parseInlineString( expr : String, pos : Position ) : Expr { - return load("parse", 3)(untyped expr.__s, pos, true); + return load("do_parse", 3)(expr, pos, true); } /** @@ -299,7 +297,7 @@ class Context { Returns a hashed MD5 signature of value `v`. **/ public static function signature( v : Dynamic ) : String { - return new String(load("signature", 1)(v)); + return load("signature", 1)(v); } /** @@ -323,7 +321,19 @@ class Context { **/ @:require(haxe_ver >= 3.1) public static function onAfterGenerate( callback : Void -> Void ) { - load("after_generate",1)(callback); + load("on_after_generate",1)(callback); + } + + /** + Adds a callback function `callback` which is invoked after the compiler + is done typing, but before optimization. The callback receives the types + which have been typed. + + It is possible to define new types in the callback, in which case it + will be called again with the new types as argument. + **/ + public static function onAfterTyping( callback : Array -> Void ) { + load("on_after_typing",1)(callback); } /** @@ -341,7 +351,7 @@ class Context { /** Types expression `e` and returns its type. - Typing the expression may result in an compiler error which can be + Typing the expression may result in a compiler error which can be caught using `try ... catch`. **/ public static function typeof( e : Expr ) : Type { @@ -351,7 +361,7 @@ class Context { /** Types expression `e` and returns the corresponding `TypedExpr`. - Typing the expression may result in an compiler error which can be + Typing the expression may result in a compiler error which can be caught using `try ... catch`. **/ @:require(haxe_ver >= 3.1) @@ -359,17 +369,29 @@ class Context { return load("type_expr", 1)(e); } + /** + Resolve type `t` and returns the corresponding `Type`. + + Resolving the type may result in a compiler error which can be + caught using `try ... catch`. + Resolution is performed based on the current context in which the macro is called. + **/ + @:require(haxe_ver >= 3.3) + public static function resolveType( t : ComplexType, p : Position ) : Type { + return load("resolve_type", 2)(t,p); + } + /** Returns the `ComplexType` corresponding to the given `Type` `t`. See `haxe.macro.TypeTools.toComplexType` for details. **/ public static function toComplexType( t : Type ) : Null { - return load("to_complex", 1)(t); + return load("to_complex_type", 1)(t); } /** - Returns true if `t1` and `t2` unify, false otherwise. + Tries to unify `t1` and `t2` and returns `true` if successful. **/ public static function unify( t1 : Type, t2 : Type) : Bool { return load("unify", 2)(t1, t2); @@ -384,20 +406,27 @@ class Context { return load("follow", 2)(t,once); } + /** + Follows a type, including abstracts' underlying implementation + + See `haxe.macro.TypeTools.followWithAbstracts` for details. + **/ + public static function followWithAbstracts(t : Type, once : Bool = false ) : Type { + return load("follow_with_abstracts", 2)(t,once); + } + /** Returns the information stored in `Position` `p`. **/ public static function getPosInfos( p : Position ) : { min : Int, max : Int, file : String } { - var i = load("get_pos_infos",1)(p); - i.file = new String(i.file); - return i; + return load("get_pos_infos",1)(p); } /** Builds a `Position` from `inf`. **/ public static function makePosition( inf : { min : Int, max : Int, file : String } ) : Position { - return load("make_pos",3)(inf.min,inf.max,untyped inf.file.__s); + return load("make_position",3)(inf.min,inf.max,inf.file); } /** @@ -407,12 +436,7 @@ class Context { `haxe.macro.Context.addResource` to add new resources to the compilation unit. **/ public static function getResources():Map { - var x:haxe.ds.StringMap = load("get_resources",0)(); - var r = new haxe.ds.StringMap(); - for (k in x.keys()) { - r.set(k, haxe.io.Bytes.ofData(x.get(k))); - } - return r; + return load("get_resources",0)(); } /** @@ -421,9 +445,14 @@ class Context { The resource is then available using the `haxe.macro.Resource` API. If a previous resource was bound to `name`, it is overwritten. + + Compilation server : when using the compilation server, the resource is bound + to the Haxe module which calls the macro, so it will be included again if + that module is reused. If this resource concerns several modules, prefix its + name with a $ sign, this will bind it to the macro module instead. **/ public static function addResource( name : String, data : haxe.io.Bytes ) { - load("add_resource",2)(untyped name.__s,data.getData()); + load("add_resource",2)(name,data); } /** @@ -432,7 +461,7 @@ class Context { This is only defined for `@:build/@:autoBuild` macros. **/ public static function getBuildFields() : Array { - return load("build_fields", 0)(); + return load("get_build_fields", 0)(); } /** @@ -451,9 +480,9 @@ class Context { not allowed to have `.*` wildcards or `in s` shorthands. **/ public static function defineModule( modulePath : String, types : Array, ?imports: Array, ?usings : Array ) : Void { - if (imports == null) imports = []; - if (usings == null) usings = []; - load("define_module", 4)(untyped modulePath.__s, untyped types.__neko(), untyped imports.__neko(), untyped usings.__neko()); + if( imports == null ) imports = []; + if( usings == null ) usings = []; + load("define_module", 4)(modulePath, types, imports, usings); } /** @@ -483,6 +512,34 @@ class Context { return load("store_typed_expr",1)(t); } + /** + Evaluates `e` as macro code. + + Any call to this function takes effect when the macro is executed, not + during typing. As a consequence, this function can not introduce new + local variables into the macro context and may have other restrictions. + + Usage example: + + ```haxe + var e = macro function(i) return i * 2; + var f:Int -> Int = haxe.macro.Context.eval(e); + trace(f(2)); // 4 + ``` + + Code passed in from outside the macro cannot reference anything in its + context, such as local variables. However, it is possible to reference + static methods. + + This method should be considered experimental. + + If `e` is null, the result is unspecified. + **/ + //@:require(haxe_ver >= 3.3) + //public static function eval( e : Expr ) : Dynamic { + //return load("eval",1)(e); + //} + /** Manually adds a dependency between module `modulePath` and an external file `externFile`. @@ -493,14 +550,24 @@ class Context { Has no effect if the compilation cache is not used. **/ public static function registerModuleDependency( modulePath : String, externFile : String ) { - load("module_dependency", 2)(untyped modulePath.__s,untyped externFile.__s); + load("register_module_dependency", 2)(modulePath,externFile); } /** - Add a macro call to perform in case the module is reused by the compilation cache. + Register a macro call to be performed everytime the module `modulePath` is reused by the compilation cache, + meaning that neither the module itself nor its dependencies was changed since last compilation. + + The `macroCall` should be a String containing valid Haxe expression, similar to `--init` macros (see https://haxe.org/manual/macro-initialization.html). + Multiple calls with the exact same `macroCall` value will only register the callback once. + + This also triggers loading of given module and its dependencies, if it's not yet loaded, + but given macro call will not be called on the first module load. + + If the compilation cache is not used, `macroCall` expressions will not be called, + but calling this function will still trigger loading of given `modulePath`. **/ public static function registerModuleReuseCall( modulePath : String, macroCall : String ) { - load("module_reuse_call", 2)(untyped modulePath.__s,untyped macroCall.__s); + load("register_module_reuse_call", 2)(modulePath,macroCall); } /** @@ -509,7 +576,7 @@ class Context { returns false, the macro context is discarded and another one is created. **/ public static function onMacroContextReused( callb : Void -> Bool ) { - load("macro_context_reused", 1)(callb); + load("on_macro_context_reused", 1)(callb); } @:allow(haxe.macro.TypeTools) @@ -523,6 +590,14 @@ class Context { #end } + private static function includeFile( file : String, position : String ) { + load("include_file", 2)(file, position); + } + + private static function sExpr( e : TypedExpr, pretty : Bool ) : String { + return haxe.macro.Context.load("s_expr", 2)(e, pretty); + } + #end } diff --git a/std/haxe/macro/ExampleJSGenerator.hx b/std/haxe/macro/ExampleJSGenerator.hx index 389a766f..f6c0a388 100644 --- a/std/haxe/macro/ExampleJSGenerator.hx +++ b/std/haxe/macro/ExampleJSGenerator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/macro/Expr.hx b/std/haxe/macro/Expr.hx index fff72d4c..90af80f4 100644 --- a/std/haxe/macro/Expr.hx +++ b/std/haxe/macro/Expr.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,105 +22,172 @@ package haxe.macro; #if (macro && !doc_gen) -extern enum Position { +@:coreType abstract Position { } #else +/** + Represents a position in a file. +**/ typedef Position = { + /** + Reference to the filename. + **/ var file : String; + + /** + Position of the first character. + **/ var min : Int; + + /** + Position of the last character. + **/ var max : Int; } #end +/** + Represents a constant. + @see https://haxe.org/manual/expression-constants.html +**/ enum Constant { + /** + Represents an integer literal. + **/ CInt( v : String ); + + /** + Represents a float literal. + **/ CFloat( f : String ); + + /** + Represents a string literal. + **/ CString( s : String ); + + /** + Represents an indentifier. + **/ CIdent( s : String ); + + /** + Represents a regular expression literal. + + Example: `~/haxe/i` + * The first argument _haxe_ is a string with regular expression pattern. + * The second argument _i_ is a string with regular expression flags. + + @see https://haxe.org/manual/std-regex.html + **/ CRegexp( r : String, opt : String ); } +/** + A binary operator. + @see https://haxe.org/manual/types-numeric-operators.html +**/ enum Binop { /** `+` **/ OpAdd; + /** `*` **/ OpMult; + /** `/` **/ OpDiv; + /** `-` **/ OpSub; + /** `=` **/ OpAssign; + /** `==` **/ OpEq; + /** `!=` **/ OpNotEq; + /** `>` **/ OpGt; + /** `>=` **/ OpGte; + /** `<` **/ OpLt; + /** `<=` **/ OpLte; + /** `&` **/ OpAnd; + /** `|` **/ OpOr; + /** `^` **/ OpXor; + /** `&&` **/ OpBoolAnd; + /** `||` **/ OpBoolOr; + /** `<<` **/ OpShl; + /** `>>` **/ OpShr; + /** `>>>` **/ OpUShr; + /** `%` **/ OpMod; + /** `+=` `-=` @@ -135,188 +202,670 @@ enum Binop { `%=` **/ OpAssignOp( op : Binop ); + /** `...` **/ OpInterval; + /** `=>` **/ OpArrow; } - +/** + A unary operator. + @see https://haxe.org/manual/types-numeric-operators.html +**/ enum Unop { /** `++` **/ OpIncrement; + /** `--` **/ OpDecrement; + /** `!` **/ OpNot; + /** `-` **/ OpNeg; + /** `~` **/ OpNegBits; } +/** + Represents a node in the AST. + @see https://haxe.org/manual/macro-reification-expression.html +**/ typedef Expr = { + /** + The expression kind. + **/ var expr : ExprDef; + + /** + The position of the expression. + **/ var pos : Position; } +/** + Represents a AST node identical to `Expr`, but it allows constraining the + type of accepted expressions. + @see https://haxe.org/manual/macro-ExprOf.html +**/ typedef ExprOf = Expr; +/** + Represents a switch case. + @see https://haxe.org/manual/expression-switch.html +**/ typedef Case = { + /** + The value expressions of the case. + **/ var values : Array; + + /** + The optional guard expressions of the case, if available. + **/ @:optional var guard : Null; + + /** + The expression of the case, if available. + **/ var expr: Null; } +/** + Represents a variable in the AST. + @see https://haxe.org/manual/expression-var.html +**/ typedef Var = { - name : String, - type : Null, - expr : Null + /** + The name of the variable. + **/ + var name : String; + + /** + The type-hint of the variable, if available. + **/ + var type : Null; + + /** + The expression of the variable, if available. + **/ + var expr : Null; } +/** + Represents a catch in the AST. + @https://haxe.org/manual/expression-try-catch.html +**/ typedef Catch = { - name : String, - type : ComplexType, - expr : Expr + /** + The name of the catch variable. + **/ + var name : String; + + /** + The type of the catch. + **/ + var type : ComplexType; + + /** + The expression of the catch. + **/ + var expr : Expr; } +/** + Represents the kind of a node in the AST. +**/ enum ExprDef { + /** + A constant. + **/ EConst( c : Constant ); + + /** + Array access `e1[e2]`. + **/ EArray( e1 : Expr, e2 : Expr ); + + /** + Binary operator `e1 op e2`. + **/ EBinop( op : Binop, e1 : Expr, e2 : Expr ); + + /** + Field access on `e.field`. + **/ EField( e : Expr, field : String ); + + /** + Parentheses `(e)`. + **/ EParenthesis( e : Expr ); + + /** + An object declaration. + **/ EObjectDecl( fields : Array<{ field : String, expr : Expr }> ); + + /** + An array declaration `[el]`. + **/ EArrayDecl( values : Array ); + + /** + A call `e(params)`. + **/ ECall( e : Expr, params : Array ); + + /** + A constructor call `new t(params)`. + **/ ENew( t : TypePath, params : Array ); + + /** + An unary operator `op` on `e`: + + * e++ (op = OpIncrement, postFix = true) + * e-- (op = OpDecrement, postFix = true) + * ++e (op = OpIncrement, postFix = false) + * --e (op = OpDecrement, postFix = false) + * -e (op = OpNeg, postFix = false) + * !e (op = OpNot, postFix = false) + * ~e (op = OpNegBits, postFix = false) + **/ EUnop( op : Unop, postFix : Bool, e : Expr ); + + /** + Variable declarations. + **/ EVars( vars : Array ); + + /** + A function declaration. + **/ EFunction( name : Null, f : Function ); + + /** + A block of expressions `{exprs}`. + **/ EBlock( exprs : Array ); + + /** + A `for` expression. + **/ EFor( it : Expr, expr : Expr ); + + /** + A `(e1 in e2)` expression. + **/ EIn( e1 : Expr, e2 : Expr ); + + /** + An `if(econd) eif` or `if(econd) eif else eelse` expression. + **/ EIf( econd : Expr, eif : Expr, eelse : Null ); + + /** + Represents a `while` expression. + When `normalWhile` is `true` it is `while (...)`. + When `normalWhile` is `false` it is `do {...} while (...)`. + **/ EWhile( econd : Expr, e : Expr, normalWhile : Bool ); - ESwitch( e : Expr, cases : Array, edef : Null> ); + + /** + Represents a `switch` expression with related cases and an optional. + `default` case if edef != null. + **/ + ESwitch( e : Expr, cases : Array, edef : Null ); + + /** + Represents a `try`-expression with related catches. + **/ ETry( e : Expr, catches : Array ); + + /** + A `return` or `return e` expression. + **/ EReturn( ?e : Null ); + + /** + A `break` expression. + **/ EBreak; + + /** + A `continue` expression. + **/ EContinue; + + /** + An `untyped e` source code. + **/ EUntyped( e : Expr ); + + /** + A `throw e` expression. + **/ EThrow( e : Expr ); + + /** + A `cast e` or `cast (e, m)` expression. + **/ ECast( e : Expr, t : Null ); + + /** + Internally used to provide completion. + **/ EDisplay( e : Expr, isCall : Bool ); + + /** + Internally used to provide completion. + **/ EDisplayNew( t : TypePath ); + + /** + A `(econd) ? eif : eelse` expression. + **/ ETernary( econd : Expr, eif : Expr, eelse : Expr ); + + /** + A `(e:t)` expression. + **/ ECheckType( e : Expr, t : ComplexType ); + + /** + A `@m e` expression. + **/ EMeta( s : MetadataEntry, e : Expr ); } +/** + Represents a type syntax in the AST. +**/ enum ComplexType { + /** + Represents the type path. + **/ TPath( p : TypePath ); + + /** + Represents a function type. + @see https://haxe.org/manual/types-function.html + **/ TFunction( args : Array, ret : ComplexType ); + + /** + Represents an anonymous structure type. + @see https://haxe.org/manual/types-anonymous-structure.html + **/ TAnonymous( fields : Array ); + + /** + Represents parentheses around a type, e.g. the `(Int -> Void)` part in + `(Int -> Void) -> String`. + **/ TParent( t : ComplexType ); + + /** + Represents typedef extensions `> Iterable`. + The array `p` holds the type paths to the given types. + @see https://haxe.org/manual/type-system-extensions.html + **/ TExtend( p : Array, fields : Array ); + + /** + Represents an optional type. + **/ TOptional( t : ComplexType ); } +/** + Represents a type path in the AST. +**/ typedef TypePath = { + /** + Represents the package of the type path. + **/ var pack : Array; + + /** + The name of the type path. + **/ var name : String; + + /** + Optional parameters of the type path. + **/ @:optional var params : Array; + + /** + Sub is set on module sub-type access: + `pack.Module.Type` has name = Module, sub = Type, if available. + **/ @:optional var sub : Null; } +/** + Represents a concrete type parameter in the AST. + + Haxe allows expressions in concrete type parameters, e.g. + `new YourType<["hello", "world"]>`. In that case the value is `TPExpr` while + in the normal case it's `TPType`. +**/ enum TypeParam { + /** + + **/ TPType( t : ComplexType ); + + /** + + **/ TPExpr( e : Expr ); } +/** + Represents a type parameter declaration in the AST. +**/ typedef TypeParamDecl = { + /** + The name of the type parameter. + **/ var name : String; + + /** + The optional constraints of the type parameter. + **/ @:optional var constraints : Array; + + /** + The optional parameters of the type parameter. + **/ @:optional var params : Array; + + /** + The metadata of the type parameter. + **/ + @:optional var meta : Metadata; } +/** + Represents a function in the AST. +**/ typedef Function = { + /** + A list of function arguments. + **/ var args : Array; + + /** + The return type-hint of the function, if available. + **/ var ret : Null; + + /** + The expression of the function body, if available. + **/ var expr : Null; + + /** + An optional list of function parameter type declarations. + **/ @:optional var params : Array; } +/** + Represents a function argument in the AST. +**/ typedef FunctionArg = { + /** + The name of the function argument. + **/ var name : String; + + /** + Whether or not the function argument is optional. + **/ @:optional var opt : Bool; + + /** + The type-hint of the function argument, if available. + **/ var type : Null; + + /** + The optional value of the function argument, if available. + **/ @:optional var value : Null; + + /** + The metadata of the function argument. + **/ + @:optional var meta : Metadata; } +/** + Represents a metadata entry in the AST. +**/ typedef MetadataEntry = { - name : String, - ?params : Array, - pos : Position + /** + The name of the metadata entry. + **/ + var name : String; + + /** + The optional parameters of the metadata entry. + **/ + @:optional var params : Array; + + /** + The position of the metadata entry. + **/ + var pos : Position; } +/** + Represents metadata in the AST. +**/ typedef Metadata = Array; +/** + Represents a field in the AST. +**/ typedef Field = { + /** + The name of the field. + **/ var name : String; + + /** + The documentation of the field, if available. If the field has no + documentation, the value is `null`. + **/ @:optional var doc : Null; + + /** + The access modifiers of the field. By default fields have private access. + @see https://haxe.org/manual/class-field-access-modifier.html + **/ @:optional var access : Array; + + /** + The kind of the field. + **/ var kind : FieldType; + + /** + The position of the field. + **/ var pos : Position; + + /** + The optional metadata of the field. + **/ @:optional var meta : Metadata; } +/** + Represents an access modifier. + @see https://haxe.org/manual/class-field-access-modifier.html +**/ enum Access { + + /** + Public access modifier, grants access from anywhere. + @see https://haxe.org/manual/class-field-visibility.html + **/ APublic; + + /** + Private access modifier, grants access to class and its sub-classes + only. + @see https://haxe.org/manual/class-field-visibility.html + **/ APrivate; + + /** + Static access modifier. + **/ AStatic; + + /** + Override access modifier. + @see https://haxe.org/manual/class-field-override.html + **/ AOverride; + + /** + Dynamic (re-)bindable access modifier. + @see https://haxe.org/manual/class-field-dynamic.html + **/ ADynamic; + + /** + Inline access modifier. Allows expressions to be directly inserted in + place of calls to them. + @see https://haxe.org/manual/class-field-inline.html + **/ AInline; + + /** + Macros access modifier. Allows expression macro functions. These are + normal functions which are executed as soon as they are typed. + **/ AMacro; } +/** + Represents the field type in the AST. +**/ enum FieldType { + /** + Represents a variable field type. + **/ FVar( t : Null, ?e : Null ); + + /** + Represents a function field type. + **/ FFun( f : Function ); + + /** + Represents a property with getter and setter field type. + **/ FProp( get : String, set : String, ?t : Null, ?e : Null ); } +/** + Represents a type definition. +**/ typedef TypeDefinition = { + /** + The package of the type definition. + **/ var pack : Array; + + /** + The name of the type definition. + **/ var name : String; + + /** + The position to the type definition. + **/ var pos : Position; + + /** + The optional metadata of the type definition. + **/ @:optional var meta : Metadata; + + /** + The paramater type declarations of the type definition. + **/ @:optional var params : Array; + + /** + Whether or not the type is extern. + **/ @:optional var isExtern : Bool; + + /** + The kind of the type definition. + **/ var kind : TypeDefKind; + + /** + The fields of the type definition. + **/ var fields : Array; } +/** + Represents a type definition kind. +**/ enum TypeDefKind { + /** + Represents an enum kind. + **/ TDEnum; + + /** + Represents a structure kind. + **/ TDStructure; + + /** + Represents a class kind. + **/ TDClass( ?superClass : TypePath, ?interfaces : Array, ?isInterface : Bool ); + + /** + Represents an alias/typedef kind. + **/ TDAlias( t : ComplexType ); // ignore TypeDefinition.fields + + /** + Represents an abstract kind. + **/ TDAbstract( tthis : Null, ?from : Array, ?to: Array ); } @@ -324,24 +873,65 @@ enum TypeDefKind { This error can be used to handle or produce compilation errors in macros. **/ class Error { + + /** + The error message. + **/ public var message : String; + + /** + The position of the error. + **/ public var pos : Expr.Position; + + /** + Instantiates an error with given message and position. + **/ public function new(m,p) { this.message = m; this.pos = p; } + + /** + Returns the string representation of the error. + **/ function toString() { return message; } } +/** + Represents the import mode. + @see https://haxe.org/manual/type-system-import.html +**/ enum ImportMode { + /** + Represents a default import `import c`. + **/ INormal; + + /** + Represents the alias import `import c as alias`. + **/ IAsName(alias:String); + + /** + Represents the wildcard import `import *`. + **/ IAll; } +/** + Represents the import expression. +**/ typedef ImportExpr = { + /** + The path to the import expression. + **/ var path: Array< { pos: Position, name: String } >; + + /** + The mode of the import expression. + **/ var mode: ImportMode; } diff --git a/std/haxe/macro/ExprTools.hx b/std/haxe/macro/ExprTools.hx index 0352e3a4..b801b05b 100644 --- a/std/haxe/macro/ExprTools.hx +++ b/std/haxe/macro/ExprTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -36,20 +36,20 @@ using Lambda; class ExprTools { /** - Converts expression [e] to a human-readable String representation. + Converts expression `e` to a human-readable String representation. - The result is guaranteed to be valid haxe code, but there may be + The result is guaranteed to be valid Haxe code, but there may be differences from the original lexical syntax. **/ static public function toString( e : Expr ) : String return new Printer().printExpr(e); /** - Calls function [f] on each sub-expression of [e]. + Calls function `f` on each sub-expression of `e`. - If [e] has no sub-expressions, this operation has no effect. + If `e` has no sub-expressions, this operation has no effect. - Otherwise [f] is called once per sub-expression of [e], with the + Otherwise `f` is called once per sub-expression of `e`, with the sub-expression as argument. These calls are done in order of the sub-expression declarations. @@ -57,7 +57,7 @@ class ExprTools { in a recursive function which handles the expression nodes of interest. Usage example: - + ```haxe function findStrings(e:Expr) { switch(e.expr) { case EConst(CString(s)): @@ -66,6 +66,7 @@ class ExprTools { ExprTools.iter(e, findStrings); } } + ``` **/ static public function iter( e : Expr, f : Expr -> Void ) : Void { switch(e.expr) { @@ -131,11 +132,11 @@ class ExprTools { } /** - Transforms the sub-expressions of [e] by calling [f] on each of them. + Transforms the sub-expressions of `e` by calling `f` on each of them. - If [e] has no sub-expressions, this operation returns [e] unchanged. + If `e` has no sub-expressions, this operation returns `e` unchanged. - Otherwise [f] is called once per sub-expression of [e], with the + Otherwise `f` is called once per sub-expression of `e`, with the sub-expression as argument. These calls are done in order of the sub-expression declarations. @@ -143,7 +144,7 @@ class ExprTools { in a recursive function which handles the expression nodes of interest. Usage example: - + ```haxe function capitalizeStrings(e:Expr) { return switch(e.expr) { case EConst(CString(s)): @@ -152,6 +153,7 @@ class ExprTools { ExprTools.map(e, capitalizeStrings); } } + ```haxe **/ static public function map( e : Expr, f : Expr -> Expr ) : Expr { return {pos: e.pos, expr: switch(e.expr) { @@ -213,12 +215,13 @@ class ExprTools { Returns the value `e` represents. Supported expressions are: - - `Int`, `Float` and `String` literals - - identifiers `true`, `false` and `null` - - structure declarations if all their fields are values - - array declarations if all their elements are values - - unary operators `-`, `!` and `~` if the operand is a value - - binary operators except `=>`, `...` and assignments + + - `Int`, `Float` and `String` literals + - identifiers `true`, `false` and `null` + - structure declarations if all their fields are values + - array declarations if all their elements are values + - unary operators `-`, `!` and `~` if the operand is a value + - binary operators except `=>`, `...` and assignments Parentheses, metadata and the `untyped` keyword are ignored. diff --git a/std/haxe/macro/Format.hx b/std/haxe/macro/Format.hx index 2cc73028..9ec9f836 100644 --- a/std/haxe/macro/Format.hx +++ b/std/haxe/macro/Format.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/macro/JSGenApi.hx b/std/haxe/macro/JSGenApi.hx index 93e89c2a..4fbb1f52 100644 --- a/std/haxe/macro/JSGenApi.hx +++ b/std/haxe/macro/JSGenApi.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/macro/MacroStringTools.hx b/std/haxe/macro/MacroStringTools.hx index d22d5def..4af3b5ef 100644 --- a/std/haxe/macro/MacroStringTools.hx +++ b/std/haxe/macro/MacroStringTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -28,6 +28,7 @@ import haxe.macro.Expr; This class provides some utility methods to work with strings in macro context. **/ +#if hl @:hlNative("macro") #end class MacroStringTools { #if macro @@ -39,7 +40,9 @@ class MacroStringTools { elements. **/ static public function formatString(s:String, pos:Position) { - return Context.load("format_string", 2)(untyped s.__s, pos); + #if neko + return Context.load("format_string", 2)(s, pos); + #end } /** @@ -52,10 +55,20 @@ class MacroStringTools { This operation depends on the position of `e`. **/ - static public function isFormatExpr(e:ExprOf) { + static public function isFormatExpr(e:ExprOf) : Bool { + #if neko return Context.load("is_fmt_string", 1)(e.pos); + #else + return isFmtString(e.pos); + #end } + #if !neko + static function isFmtString(p:Position) : Bool { + return false; + } + #end + #end /** diff --git a/std/haxe/macro/MacroType.hx b/std/haxe/macro/MacroType.hx index e95c2073..a1befdd1 100644 --- a/std/haxe/macro/MacroType.hx +++ b/std/haxe/macro/MacroType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/macro/PositionTools.hx b/std/haxe/macro/PositionTools.hx index 2be5e608..1307cb02 100644 --- a/std/haxe/macro/PositionTools.hx +++ b/std/haxe/macro/PositionTools.hx @@ -1,4 +1,25 @@ -package haxe.macro; +/* + * Copyright (C)2005-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 haxe.macro; import haxe.macro.Expr; @@ -10,7 +31,7 @@ class PositionTools { macro public static function here():ExprOf { var positionExpr = Context.makeExpr(Context.getPosInfos(Context.currentPos()), Context.currentPos()); if (Context.defined("macro")) { - return macro Context.makePosition($positionExpr); + return macro haxe.macro.Context.makePosition($positionExpr); } else { return positionExpr; } diff --git a/std/haxe/macro/Printer.hx b/std/haxe/macro/Printer.hx index 49193051..99481b74 100644 --- a/std/haxe/macro/Printer.hx +++ b/std/haxe/macro/Printer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,6 +26,10 @@ import haxe.macro.Expr; using Lambda; using StringTools; +/** + This class provides some utility methods to convert elements from the + macro context to a human-readable String representation. +*/ class Printer { var tabs:String; var tabString:String; @@ -106,7 +110,12 @@ class Printer { // TODO: check if this can cause loops public function printComplexType(ct:ComplexType) return switch(ct) { case TPath(tp): printTypePath(tp); - case TFunction(args, ret): (args.length>0 ? args.map(printComplexType).join(" -> ") : "Void") + " -> " + printComplexType(ret); + case TFunction(args, ret): + function printArg(ct) return switch ct { + case TFunction(_): "(" + printComplexType(ct) + ")"; + default: printComplexType(ct); + }; + (args.length>0 ? args.map(printArg).join(" -> ") :"Void") + " -> " + printComplexType(ret); case TAnonymous(fields): "{ " + [for (f in fields) printField(f) + "; "].join("") + "}"; case TParent(ct): "(" + printComplexType(ct) + ")"; case TOptional(ct): "?" + printComplexType(ct); @@ -244,7 +253,7 @@ class Printer { (printPackage && t.pack.length > 0 && t.pack[0] != "" ? "package " + t.pack.join(".") + ";\n" : "") + (t.meta != null && t.meta.length > 0 ? t.meta.map(printMetadata).join(" ") + " " : "") + (t.isExtern ? "extern " : "") + switch (t.kind) { case TDEnum: - "enum " + t.name + (t.params.length > 0 ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + " {\n" + "enum " + t.name + ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + " {\n" + [for (field in t.fields) tabs + (field.doc != null && field.doc != "" ? "/**\n" + tabs + tabString + StringTools.replace(field.doc, "\n", "\n" + tabs + tabString) + "\n" + tabs + "**/\n" + tabs : "") + (field.meta != null && field.meta.length > 0 ? field.meta.map(printMetadata).join(" ") + " " : "") @@ -256,7 +265,7 @@ class Printer { ].join("\n") + "\n}"; case TDStructure: - "typedef " + t.name + (t.params.length > 0 ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + " = {\n" + "typedef " + t.name + ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + " = {\n" + [for (f in t.fields) { tabs + printField(f) + ";"; }].join("\n") @@ -267,18 +276,11 @@ class Printer { + (interfaces != null ? (isInterface ? [for (tp in interfaces) " extends " + printTypePath(tp)] : [for (tp in interfaces) " implements " + printTypePath(tp)]).join("") : "") + " {\n" + [for (f in t.fields) { - var fstr = printField(f); - tabs + fstr + switch(f.kind) { - case FVar(_, _), FProp(_, _, _, _): ";"; - case FFun({expr:null}): ";"; - case FFun({expr:{expr:EBlock(_)}}): ""; - case FFun(_): ";"; - case _: ""; - }; + tabs + printFieldWithDelimiter(f); }].join("\n") + "\n}"; case TDAlias(ct): - "typedef " + t.name + (t.params.length > 0 ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + " = " + "typedef " + t.name + ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + " = " + (switch(ct) { case TExtend(tpl, fields): printExtension(tpl, fields); case TAnonymous(fields): printStructure(fields); @@ -287,18 +289,13 @@ class Printer { + ";"; case TDAbstract(tthis, from, to): "abstract " + t.name - + (t.params.length > 0 ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + + ((t.params != null && t.params.length > 0) ? "<" + t.params.map(printTypeParamDecl).join(", ") + ">" : "") + (tthis == null ? "" : "(" + printComplexType(tthis) + ")") + (from == null ? "" : [for (f in from) " from " + printComplexType(f)].join("")) + (to == null ? "" : [for (t in to) " to " + printComplexType(t)].join("")) + " {\n" + [for (f in t.fields) { - var fstr = printField(f); - tabs + fstr + switch(f.kind) { - case FVar(_, _), FProp(_, _, _, _): ";"; - case FFun(func) if (func.expr == null): ";"; - case _: ""; - }; + tabs + printFieldWithDelimiter(f); }].join("\n") + "\n}"; } @@ -307,5 +304,16 @@ class Printer { return str; } + function printFieldWithDelimiter(f:Field):String + { + return printField(f) + switch(f.kind) { + case FVar(_, _), FProp(_, _, _, _): ";"; + case FFun({expr:null}): ";"; + case FFun({expr:{expr:EBlock(_)}}): ""; + case FFun(_): ";"; + case _: ""; + }; + } + function opt(v:T, f:T->String, prefix = "") return v == null ? "" : (prefix + f(v)); } diff --git a/std/haxe/macro/Tools.hx b/std/haxe/macro/Tools.hx index 2c429687..56d1e4f5 100644 --- a/std/haxe/macro/Tools.hx +++ b/std/haxe/macro/Tools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,12 +22,32 @@ package haxe.macro; /** - This class can be added via 'using haxe.macro.Tools' in order to enable - 'using' functionality on all macro tool classes listed below. + This class can be added via `using haxe.macro.Tools` in order to enable + `using` functionality on these macro tool classes: + + - `haxe.macro.ExprTools` + - `haxe.macro.ComplexTypeTools` + - `haxe.macro.TypeTools` + - `haxe.macro.MacroStringTools` + - `haxe.macro.TypedExprTools` + - `haxe.macro.PositionTools` + + @see **/ +@:dox(hide) typedef TExprTools = ExprTools; + +@:dox(hide) typedef TComplexTypeTools = ComplexTypeTools; + +@:dox(hide) typedef TTypeTools = TypeTools; + +@:dox(hide) typedef TMacroStringTools = MacroStringTools; + +@:dox(hide) typedef TTypedExprTools = TypedExprTools; + +@:dox(hide) typedef TPositionTools = PositionTools; diff --git a/std/haxe/macro/Type.hx b/std/haxe/macro/Type.hx index 366fafd0..9c8bf976 100644 --- a/std/haxe/macro/Type.hx +++ b/std/haxe/macro/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,58 +25,69 @@ package haxe.macro; Warning: Some of these types correspond to compiler-internal data structures and might change in minor Haxe releases in order to adapt to internal changes. */ + +/** + Represents a reference to internal compiler structure. It exists to avoid + expensive encoding if it is not required and to ensure that physical + equality remains intact. + + A structure is only encoded when user requests it through `ref.get()`. +*/ typedef Ref = { public function get() : T; public function toString() : String; } +/** + Represents a type. +*/ enum Type { /** Represents a monomorph. - @see http://haxe.org/manual/types-monomorph.html + @see https://haxe.org/manual/types-monomorph.html **/ TMono( t : Ref> ); /** Represents an enum instance. - @see http://haxe.org/manual/types-enum-instance.html + @see https://haxe.org/manual/types-enum-instance.html **/ TEnum( t : Ref, params : Array ); /** Represents a class instance. - @see http://haxe.org/manual/types-class-instance.html + @see https://haxe.org/manual/types-class-instance.html **/ TInst( t : Ref, params : Array ); /** Represents a typedef. - @see http://haxe.org/manual/type-system-typedef.html + @see https://haxe.org/manual/type-system-typedef.html **/ TType( t : Ref, params : Array ); /** Represents a function type. - @see http://haxe.org/manual/types-function.html + @see https://haxe.org/manual/types-function.html **/ TFun( args : Array<{ name : String, opt : Bool, t : Type }>, ret : Type ); /** Represents an anonymous structure type. - @see http://haxe.org/manual/types-anonymous-structure.html + @see https://haxe.org/manual/types-anonymous-structure.html **/ TAnonymous( a : Ref ); /** Represents Dynamic. - @see http://haxe.org/manual/types-dynamic.html + @see https://haxe.org/manual/types-dynamic.html **/ TDynamic( t : Null ); @@ -88,109 +99,423 @@ enum Type { /** Represents an abstract type. - @see http://haxe.org/manual/types-abstract.html + @see https://haxe.org/manual/types-abstract.html **/ TAbstract( t : Ref, params : Array ); } +/** + Represents information for anonymous structure types. +*/ typedef AnonType = { + /** + The class fields of the structure. + **/ var fields : Array; + /** + The status/kind of the structure. + **/ var status : AnonStatus; } +/** + Represents the kind of the anonymous structure type. +**/ enum AnonStatus { + /** + A closed structure is considered complete. That is, no further fields + can be added to it. + **/ AClosed; + + /** + An open structure allows having additional fields added to it, which is + used during type inference. It is closed upon unification. + **/ AOpened; + + /** + A const structure is one that appears directly in syntax. It cannot be + assigned to a smaller structure type (that is, it does not allow + structural sub-typing). + **/ AConst; + + /** + Represents a structure which extends one or multiple structures defined + in `tl`. + + @see https://haxe.org/manual/type-system-extensions.html + **/ AExtend( tl:Ref> ); + + /** + A structure that represents the static fields of a class. + **/ AClassStatics( t : Ref ); + + /** + A structure that represents the constructors of an enum. + **/ AEnumStatics( t : Ref ); + + /** + A structure that represents the static fields of an abstract. + **/ AAbstractStatics( t : Ref ); } +/** + Represents the declaration of type parameters. +*/ typedef TypeParameter = { + /** + The name of the type parameter. + **/ var name: String; - var t: Type; -} -typedef BaseType = { - var pack : Array; - var name : String; - var module : String; - var pos : Expr.Position; - var isPrivate : Bool; - var isExtern : Bool; - var params : Array; - var meta : MetaAccess; - var doc : Null; - function exclude() : Void; + /** + The type of the type parameter. It is guaranteed to be a `TInst` with a + `KTypeParameter` kind. + **/ + var t: Type; } +/** + Represents a class field. +*/ typedef ClassField = { + /** + The name of the class field. + **/ var name : String; + + /** + The type of the class field. + **/ var type : Type; + + /** + Whether or not the class field is public. + **/ var isPublic : Bool; + + /** + The type parameters of the class field. + **/ var params : Array; + + /** + The metadata of the class field. + **/ var meta : MetaAccess; + + /** + The class field kind. + **/ var kind : FieldKind; + + /** + Returns the typed expression of the class field. + **/ function expr() : Null; + + /** + The position of the class field. + **/ var pos : Expr.Position; + + /** + The associated documentation of the class field. + **/ var doc : Null; + + /** + The overload fields of the class field. + **/ + var overloads : Ref>; } +/** + Represents an enum constructor. +*/ +typedef EnumField = { + /** + The name of the enum constructor. + **/ + var name : String; + + /** + The type of the enum constructor. + **/ + var type : Type; + + /** + The position of the enum constructor. + **/ + var pos : Expr.Position; + + /** + The metadata of the enum constructor. + **/ + var meta : MetaAccess; + + /** + The index of the enum constructor, i.e. in which position it appears + in the syntax. + **/ + var index : Int; + + /** + The associated documentation of the enum constructor. + **/ + var doc : Null; + + /** + The type parameters of the enum constructor. + **/ + var params : Array; +} + + +/** + Represents the kind of a class. +*/ enum ClassKind { + /** + A normal class. + **/ KNormal; + + /** + A type parameter class with a set of constraints. + **/ KTypeParameter(constraints:Array); + + /** + A structurally extended class. + + @deprecated + **/ KExtension(cl:Ref, params:Array); + + /** + A special kind of class to encode expressions into type parameters. + **/ KExpr(expr:Expr); + + /** + A `@:generic` base class. + **/ KGeneric; + + /** + A concrete `@:generic` instance, referencing the original class and the + applied type parameters. + **/ KGenericInstance(cl:Ref, params:Array); + + /** + A special class for `haxe.macro.MacroType`. + + @deprecated + **/ KMacroType; + + /** + An implementation class of an abstract, i.e. where all its run-time code + is. + **/ KAbstractImpl(a:Ref); + + /** + A `@:genericBuild` class + **/ KGenericBuild; } +/** + The information that all types (`ClassType`, `EnumType`, `DefType`, + `AbstractType`) have in common. +**/ +typedef BaseType = { + /** + The package of the type. + **/ + var pack : Array; + + /** + The name of the type. + **/ + var name : String; + + /** + The module name of the type, which might be different. + **/ + var module : String; + + /** + The position of the type. + **/ + var pos : Expr.Position; + + /** + Whether or not the type is private. + **/ + var isPrivate : Bool; + + /** + Whether or not the type is extern. + **/ + var isExtern : Bool; + + /** + The type parameters of the type. + **/ + var params : Array; + + /** + The metadata of the type. + **/ + var meta : MetaAccess; + + /** + The associated documentation of the class field. + **/ + var doc : Null; + + /** + Allows excluding the type from compilation. + **/ + function exclude() : Void; +} + +/** + Represents a class type. +*/ typedef ClassType = {> BaseType, + /** + The kind of the class. + **/ var kind : ClassKind; + + /** + If true the type is an interface, otherwise it is a class. + **/ var isInterface : Bool; + + /** + The parent class and its type parameters, if available. + **/ var superClass : Null<{ t : Ref, params : Array }>; + + /** + The implemented interfaces and their type parameters. + **/ var interfaces : Array<{ t : Ref, params : Array }>; + + /** + The member fields of the class. + **/ var fields : Ref>; + + /** + The static fields of the class. + **/ var statics : Ref>; + //var dynamic : Null; //var arrayAccess : Null; + + /** + The constructor of the class, if available. + **/ var constructor : Null>; + + /** + The `__init__` expression of the class, if available. + **/ var init : Null; - var overrides : Array>; -} -typedef EnumField = { - var name : String; - var type : Type; - var pos : Expr.Position; - var meta : MetaAccess; - var index : Int; - var doc : Null; - var params : Array; + /** + The list of fields that have override status. + **/ + var overrides : Array>; } +/** + Represents an enum type. +*/ typedef EnumType = {> BaseType, - var constructs : Map; + /** + The available enum constructors. + **/ + var constructs : Map; + + /** + An ordered list of enum constructor names. + **/ var names : Array; } +/** + Represents a typedef. +*/ typedef DefType = {> BaseType, + /** + The target type of the typedef. + **/ var type : Type; } +/** + Represents an abstract type. +*/ typedef AbstractType = {>BaseType, + /** + The underlying type of the abstract. + **/ var type : Type; + + /** + The implementation class of the abstract, if available. + **/ var impl : Null>; + + /** + The defined binary operators of the abstract. + **/ var binops : Array<{op:Expr.Binop, field:ClassField}>; + + /** + The defined unary operators of the abstract. + **/ var unops : Array<{op:Expr.Unop, postFix:Bool, field:ClassField}>; + + /** + The available implicit from-casts of the abstract. + + @see https://haxe.org/manual/types-abstract-implicit-casts.html + **/ var from : Array<{t:Type, field:Null}>; + + /** + The available implicit to-casts of the abstract. + + @see https://haxe.org/manual/types-abstract-implicit-casts.html + **/ var to : Array<{t:Type, field:Null}>; + + /** + The defined array-access fields of the abstract. + **/ var array : Array; + + /** + The method used for resolving unknown field access, if available. + **/ + @:require(haxe_ver >= 3.3) + var resolve : Null; } /** @@ -209,7 +534,7 @@ typedef MetaAccess = { /** Extract metadata entries by given `name`. - If there's no metadata with such name, empty array is returned. + If there's no metadata with such name, empty array `[]` is returned. If `name` is null, compilation fails with an error. **/ @@ -250,100 +575,418 @@ typedef MetaAccess = { function has( name : String ) : Bool; } +/** + Represents a field kind. +*/ enum FieldKind { + /** + A variable of property, depending on the `read` and `write` values. + **/ FVar( read : VarAccess, write : VarAccess ); + + /** + A method + **/ FMethod( k : MethodKind ); } +/** + Represents the variable accessor. +*/ enum VarAccess { + /** + Normal access (`default`). + **/ AccNormal; + + /** + Private access (`null`). + **/ AccNo; + + /** + No access (`never`). + **/ AccNever; + + /** + Unused. + **/ AccResolve; + + /** + Access through accessor function (`get`, `set`, `dynamic`). + **/ AccCall; + + /** + Inline access (`inline`). + **/ AccInline; + + /** + Failed access due to a `@:require` metadata. + **/ AccRequire( r : String, ?msg : String ); } +/** + Represents the method kind. +*/ enum MethodKind { + /** + A normal method. + **/ MethNormal; + + /** + An inline method. + + @see https://haxe.org/manual/class-field-inline.html + **/ MethInline; + + /** + A dynamic, rebindable method. + + @see https://haxe.org/manual/class-field-dynamic.html + **/ MethDynamic; + + /** + A macro method. + **/ MethMacro; } +/** + Represents typed constant. +*/ enum TConstant { + /** + An `Int` literal. + **/ TInt(i:Int); + + /** + A `Float` literal, represented as String to avoid precision loss. + **/ TFloat(s:String); + + /** + A `String` literal. + **/ TString(s:String); + + /** + A `Bool` literal. + **/ TBool(b:Bool); + + /** + The constant `null`. + **/ TNull; + + /** + The constant `this`. + **/ TThis; + + /** + The constant `super`. + **/ TSuper; } +/** + Represents a variable in the typed AST. +*/ typedef TVar = { + /** + The unique ID of the variable. + **/ public var id(default, never):Int; + + /** + The name of the variable. + **/ public var name(default, never):String; + + /** + The type of the variable. + **/ public var t(default, never):Type; + + /** + Whether or not the variable has been captured by a closure. + **/ public var capture(default, never):Bool; + + /** + Special information which is internally used to keep track of closure. + information + **/ public var extra(default,never):Null<{params: Array, expr: Null}>; + + /** + The metadata of the variable. + **/ + public var meta(default,never):Null; } +/** + Represents a module type. These are the types that can be declared in a Haxe + module and which are passed to the generators (except `TTypeDecl`). +*/ enum ModuleType { + /** + A class. + **/ TClassDecl(c:Ref); + + /** + An enum. + **/ TEnumDecl(e:Ref); + + /** + A typedef. + **/ TTypeDecl(t:Ref); + + /** + An abstract. + **/ TAbstract(a:Ref); } +/** + Represents a function in the typed AST. +*/ typedef TFunc = { - args: Array<{v:TVar, value:Null}>, - t: Type, - expr: TypedExpr + /** + A list of function arguments identified by an argument variable `v` and + an optional initialization `value`. + **/ + var args: Array<{v:TVar, value:Null}>; + + /** + The return type of the function. + **/ + var t: Type; + + /** + The expression of the function body. + **/ + var expr: TypedExpr; } +/** + Represents the kind of field access in the typed AST. +*/ enum FieldAccess { + /** + Access of field `cf` on a class instance `c` with type parameters + `params`. + **/ FInstance(c:Ref, params:Array, cf:Ref); + + /** + Static access of a field `cf` on a class `c`. + **/ FStatic(c:Ref, cf:Ref); + + /** + Access of field `cf` on an anonymous structure. + **/ FAnon(cf:Ref); + + /** + Dynamic field access of a field named `s`. + **/ FDynamic(s:String); + + /** + Closure field access of field `cf` on a class instance `c` with type + parameters `params`. + **/ FClosure(c:Null<{c:Ref, params:Array}>, cf:Ref); + + /** + Field access to an enum constructor `ef` of enum `e`. + **/ FEnum(e:Ref, ef:EnumField); } +/** + Represents kind of a node in the typed AST. +*/ enum TypedExprDef { + /** + A constant. + **/ TConst(c:TConstant); + + /** + Reference to a local variable `v`. + **/ TLocal(v:TVar); + + /** + Array access `e1[e2]`. + **/ TArray(e1:TypedExpr, e2:TypedExpr); + + /** + Binary operator `e1 op e2`. + **/ + TBinop(op:Expr.Binop, e1:TypedExpr, e2:TypedExpr); + + /** + Field access on `e` according to `fa`. + **/ TField(e:TypedExpr, fa:FieldAccess); + + /** + Reference to a module type `m`. + **/ TTypeExpr(m:ModuleType); + + /** + Parentheses `(e)`. + **/ TParenthesis(e:TypedExpr); + + /** + An object declaration. + **/ TObjectDecl(fields:Array<{name:String, expr:TypedExpr}>); + + /** + An array declaration `[el]`. + **/ TArrayDecl(el:Array); + + /** + A call `e(el)`. + **/ TCall(e:TypedExpr, el:Array); + + /** + A constructor call `new c(el)`. + **/ TNew(c:Ref, params: Array, el:Array); + + /** + An unary operator `op` on `e`: + + * e++ (op = OpIncrement, postFix = true) + * e-- (op = OpDecrement, postFix = true) + * ++e (op = OpIncrement, postFix = false) + * --e (op = OpDecrement, postFix = false) + * -e (op = OpNeg, postFix = false) + * !e (op = OpNot, postFix = false) + * ~e (op = OpNegBits, postFix = false) + **/ TUnop(op:Expr.Unop, postFix:Bool, e:TypedExpr); + + /** + A function declaration. + **/ TFunction(tfunc:TFunc); + + /** + A variable declaration `var v` or `var v = expr`. + **/ TVar(v:TVar, expr:Null); + + /** + A block declaration `{el}`. + **/ TBlock(el:Array); + + /** + A `for` expression. + **/ TFor(v:TVar, e1:TypedExpr, e2:TypedExpr); + + /** + An `if(econd) eif` or `if(econd) eif else eelse` expression. + **/ TIf(econd:TypedExpr, eif:TypedExpr, eelse:Null); + + /** + Represents a `while` expression. + When `normalWhile` is `true` it is `while (...)`. + When `normalWhile` is `false` it is `do {...} while (...)`. + **/ TWhile(econd:TypedExpr, e:TypedExpr, normalWhile:Bool); + + /** + Represents a `switch` expression with related cases and an optional + `default` case if edef != null. + **/ TSwitch(e:TypedExpr, cases:Array<{values:Array, expr:TypedExpr}>, edef:Null); + + /** + Represents a `try`-expression with related catches. + **/ TTry(e:TypedExpr, catches:Array<{v:TVar, expr:TypedExpr}>); + + /** + A `return` or `return e` expression. + **/ TReturn(e:Null); + + /** + A `break` expression. + **/ TBreak; + + /** + A `continue` expression. + **/ TContinue; + + /** + A `throw e` expression. + **/ TThrow(e:TypedExpr); + + /** + A `cast e` or `cast (e, m)` expression. + **/ TCast(e:TypedExpr, m:Null); + + /** + A `@m e1` expression. + **/ TMeta(m:Expr.MetadataEntry, e1:TypedExpr); + + /** + Access to an enum parameter (generated by the pattern matcher). + **/ TEnumParameter(e1:TypedExpr, ef:EnumField, index:Int); } +/** + Represents a typed AST node. +*/ typedef TypedExpr = { - expr: TypedExprDef, - pos: Expr.Position, - t: Type + /** + The expression kind. + **/ + var expr: TypedExprDef; + + /** + The position of the expression. + **/ + var pos: Expr.Position; + + /** + The type of the expression. + **/ + var t: Type; } diff --git a/std/haxe/macro/TypeTools.hx b/std/haxe/macro/TypeTools.hx index 3bb179a3..16655921 100644 --- a/std/haxe/macro/TypeTools.hx +++ b/std/haxe/macro/TypeTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -33,6 +33,9 @@ using Lambda; best used through 'using haxe.macro.TypeTools' syntax and then provides additional methods on haxe.macro.Type instances. **/ +#if hl +@:hlNative("macro") +#end class TypeTools { static function nullable(complexType : ComplexType) : ComplexType return macro : Null<$complexType>; @@ -173,6 +176,22 @@ class TypeTools { static public inline function follow( t : Type, ?once : Bool ) : Type return Context.follow(t, once); + /** + Like `follow`, follows all typedefs of `t` to reach the actual type. + + Will however follow also abstracts to their underlying implementation, + if they are not a @:coreType abstract + + If `t` is null, an internal exception is thrown. + + Usage example: + var t = Context.typeof(macro new Map()); + trace(t); // TAbstract(Map,[TInst(String,[]),TInst(String,[])]) + trace(t.followWithAbstracts()); // TInst(haxe.ds.StringMap, [TInst(String,[])]) + **/ + static public inline function followWithAbstracts( t : Type, once : Bool = false ) : Type + return Context.followWithAbstracts(t, once); + /** Returns true if `t1` and `t2` unify, false otherwise. **/ @@ -227,8 +246,19 @@ class TypeTools { throw 'Incompatible arguments: ${typeParameters.length} type parameters and ${concreteTypes.length} concrete types'; else if (typeParameters.length == 0) return t; - return Context.load("apply_params", 3)(typeParameters.map(function(tp) return {name:untyped tp.name.__s, t:tp.t}), concreteTypes, t); + #if neko + return Context.load("apply_params", 3)(typeParameters, concreteTypes, t); + #else + return applyParams(typeParameters, concreteTypes, t); + #end + } + + #if !neko + private static function applyParams( typeParameters:Array, concreteTypes:Array, t:Type ) : Type { + return null; } + #end + /** Transforms `t` by calling `f` on each of its subtypes. @@ -312,7 +342,14 @@ class TypeTools { /** Converts type `t` to a human-readable String representation. **/ - static public function toString( t : Type ) : String return new String(Context.load("s_type", 1)(t)); + static public function toString( t : Type ) : String { + #if neko + return Context.load("s_type", 1)(t); + #else + return null; + #end + } + #end /** diff --git a/std/haxe/macro/TypedExprTools.hx b/std/haxe/macro/TypedExprTools.hx index 0a0177c2..b2a2c88d 100644 --- a/std/haxe/macro/TypedExprTools.hx +++ b/std/haxe/macro/TypedExprTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,6 +24,11 @@ package haxe.macro; import haxe.macro.Type; +/** + This class provides some utility methods to work with typed expressions. + It is best used through 'using haxe.macro.TypedExprTools' syntax and then + provides additional methods on `haxe.macro.TypedExpr` instances. +**/ class TypedExprTools { static function with(e:TypedExpr, ?edef:TypedExprDef, ?t:Type) { return { @@ -34,7 +39,7 @@ class TypedExprTools { } /** - Transforms the sub-expressions of [e] by calling [f] on each of them. + Transforms the sub-expressions of `e` by calling `f` on each of them. See `haxe.macro.ExprTools.map` for details on expression mapping in general. This function works the same way, but with a different data @@ -69,7 +74,7 @@ class TypedExprTools { } /** - Calls function [f] on each sub-expression of [e]. + Calls function `f` on each sub-expression of `e`. See `haxe.macro.ExprTools.iter` for details on iterating expressions in general. This function works the same way, but with a different data @@ -112,7 +117,7 @@ class TypedExprTools { } /** - Transforms the sub-expressions of [e] by calling [f] on each of them. + Transforms the sub-expressions of `e` by calling `f` on each of them. Additionally, types are mapped using `ft` and variables are mapped using `fv`. @@ -151,7 +156,7 @@ class TypedExprTools { #if macro static public function toString(t:TypedExpr, ?pretty = false):String { - return new String(haxe.macro.Context.load("s_expr", 2)(t, pretty)); + return @:privateAccess haxe.macro.Context.sExpr(t, pretty); } #end } diff --git a/std/haxe/remoting/AMFConnection.hx b/std/haxe/remoting/AMFConnection.hx index fe0a2920..984704c1 100644 --- a/std/haxe/remoting/AMFConnection.hx +++ b/std/haxe/remoting/AMFConnection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,9 @@ */ package haxe.remoting; +/** + Allows a connection to an AMF Remoting server such as Flash Media Server or AMFPHP. +*/ class AMFConnection implements AsyncConnection implements Dynamic { var __data : { diff --git a/std/haxe/remoting/AsyncAdapter.hx b/std/haxe/remoting/AsyncAdapter.hx index 7812b50b..abbd2ead 100644 --- a/std/haxe/remoting/AsyncAdapter.hx +++ b/std/haxe/remoting/AsyncAdapter.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/remoting/AsyncConnection.hx b/std/haxe/remoting/AsyncConnection.hx index fc290a66..90e515e0 100644 --- a/std/haxe/remoting/AsyncConnection.hx +++ b/std/haxe/remoting/AsyncConnection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,9 @@ */ package haxe.remoting; +/** + For asynchronous connections, where the results are events that will be resolved later in the execution process. +*/ interface AsyncConnection implements Dynamic { function resolve( name : String ) : AsyncConnection; diff --git a/std/haxe/remoting/AsyncDebugConnection.hx b/std/haxe/remoting/AsyncDebugConnection.hx index 4d9425b3..f6ae1d50 100644 --- a/std/haxe/remoting/AsyncDebugConnection.hx +++ b/std/haxe/remoting/AsyncDebugConnection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/remoting/AsyncProxy.hx b/std/haxe/remoting/AsyncProxy.hx index 7b335d19..dafa0a26 100644 --- a/std/haxe/remoting/AsyncProxy.hx +++ b/std/haxe/remoting/AsyncProxy.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/remoting/Connection.hx b/std/haxe/remoting/Connection.hx index 3e798b02..91177bb3 100644 --- a/std/haxe/remoting/Connection.hx +++ b/std/haxe/remoting/Connection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/remoting/Context.hx b/std/haxe/remoting/Context.hx index 0b57bbee..d42f8e99 100644 --- a/std/haxe/remoting/Context.hx +++ b/std/haxe/remoting/Context.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,9 @@ */ package haxe.remoting; +/** + Allows communication between platforms. This is a shared API that can be called on the connection at the client code. +*/ class Context { var objects : haxe.ds.StringMap<{ obj : Dynamic, rec : Bool }>; @@ -58,4 +61,4 @@ class Context { return ctx; } -} \ No newline at end of file +} diff --git a/std/haxe/remoting/ContextAll.hx b/std/haxe/remoting/ContextAll.hx index 830d26db..f8b7c2aa 100644 --- a/std/haxe/remoting/ContextAll.hx +++ b/std/haxe/remoting/ContextAll.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/remoting/DelayedConnection.hx b/std/haxe/remoting/DelayedConnection.hx index aee77926..ccc84e28 100644 --- a/std/haxe/remoting/DelayedConnection.hx +++ b/std/haxe/remoting/DelayedConnection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/remoting/ExternalConnection.hx b/std/haxe/remoting/ExternalConnection.hx index 57c98d61..9f8dcfed 100644 --- a/std/haxe/remoting/ExternalConnection.hx +++ b/std/haxe/remoting/ExternalConnection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -61,7 +61,11 @@ class ExternalConnection implements Connection implements Dynamic { var params = escapeString(s.toString()); var data = null; #if flash - data = flash.external.ExternalInterface.call("haxe.remoting.ExternalConnection.doCall",__data.name,__path.join("."),params); + #if js-unflatten + data = flash.external.ExternalInterface.call("haxe.remoting.ExternalConnection.doCall",__data.name,__path.join("."),params); + #else + data = flash.external.ExternalInterface.call("haxe_remoting_ExternalConnection.doCall",__data.name,__path.join("."),params); + #end #elseif js var fobj : Dynamic = (untyped js.Browser.document)[cast __data.flash]; // FIXME(bruno): Why is this necessary? if( fobj == null ) fobj = js.Browser.document.getElementById(__data.flash); diff --git a/std/haxe/remoting/FlashJsConnection.hx b/std/haxe/remoting/FlashJsConnection.hx index 11ba2b09..316732cd 100644 --- a/std/haxe/remoting/FlashJsConnection.hx +++ b/std/haxe/remoting/FlashJsConnection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/remoting/HttpAsyncConnection.hx b/std/haxe/remoting/HttpAsyncConnection.hx index 9885617d..99091f51 100644 --- a/std/haxe/remoting/HttpAsyncConnection.hx +++ b/std/haxe/remoting/HttpAsyncConnection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,9 @@ */ package haxe.remoting; +/** + Allows an asynchronous connection to the given URL which should link to a Haxe server application. +*/ class HttpAsyncConnection implements AsyncConnection implements Dynamic { var __data : { url : String, error : Dynamic -> Void }; diff --git a/std/haxe/remoting/HttpConnection.hx b/std/haxe/remoting/HttpConnection.hx index 885bea59..efcbecdc 100644 --- a/std/haxe/remoting/HttpConnection.hx +++ b/std/haxe/remoting/HttpConnection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,9 @@ */ package haxe.remoting; +/** + Allows a synchronous connection to the given URL which should link to a Haxe server application. +*/ class HttpConnection implements Connection implements Dynamic { public static var TIMEOUT = 10.; @@ -42,7 +45,7 @@ class HttpConnection implements Connection implements Dynamic { public function call( params : Array ) : Dynamic { var data = null; var h = new haxe.Http(__url); - #if js + #if (js && !nodejs) h.async = false; #end #if (neko && no_remoting_shutdown) @@ -65,7 +68,7 @@ class HttpConnection implements Connection implements Dynamic { return new haxe.Unserializer(data).unserialize(); } - #if (js || neko || php) + #if !flash public static function urlConnect( url : String ) { return new HttpConnection(url,[]); diff --git a/std/haxe/remoting/LocalConnection.hx b/std/haxe/remoting/LocalConnection.hx index 033e25f0..7b534976 100644 --- a/std/haxe/remoting/LocalConnection.hx +++ b/std/haxe/remoting/LocalConnection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,9 @@ */ package haxe.remoting; +/** + Allows communications to a different application that runs on the same client device +*/ class LocalConnection implements AsyncConnection implements Dynamic { static var ID = 0; diff --git a/std/haxe/remoting/Proxy.hx b/std/haxe/remoting/Proxy.hx index e60bf9e9..7a8e5491 100644 --- a/std/haxe/remoting/Proxy.hx +++ b/std/haxe/remoting/Proxy.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,7 +22,7 @@ package haxe.remoting; /** - This class is magic. When you extend it with a class C, it will automaticaly + When you extend it with a class C, it will automatically create a stub class with all public methods forwarding remoting messages over the connection. **/ @@ -34,4 +34,4 @@ class Proxy { __cnx = c; } -} \ No newline at end of file +} diff --git a/std/haxe/remoting/SocketConnection.hx b/std/haxe/remoting/SocketConnection.hx index 9c8c27fb..2e64f879 100644 --- a/std/haxe/remoting/SocketConnection.hx +++ b/std/haxe/remoting/SocketConnection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,6 +22,9 @@ package haxe.remoting; import haxe.remoting.SocketProtocol.Socket; +/** + Allows remoting communications over a socket connection +*/ class SocketConnection implements AsyncConnection implements Dynamic { var __path : Array; diff --git a/std/haxe/remoting/SocketProtocol.hx b/std/haxe/remoting/SocketProtocol.hx index 8342f6bd..6274af5d 100644 --- a/std/haxe/remoting/SocketProtocol.hx +++ b/std/haxe/remoting/SocketProtocol.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -35,15 +35,20 @@ typedef Socket = /** The Haxe Remoting Socket Protocol is composed of serialized string exchanges. Each string is prefixed with a 2-chars header encoding the string size (up to 4KB) - and postfixed with the \0 message delimiting char. + and postfixed with the `\0` message delimiting char. + A request string is composed of the following serialized values : - - the boolean true for a request - - an array of strings representing the object+method path - - an array of parameters + + - the boolean true for a request + - an array of strings representing the object+method path + - an array of parameters + A response string is composed of the following serialized values : - - the boolean false for a response - - a serialized value representing the result - Exceptions are serialized with [serializeException] so they will be thrown immediatly + + - the boolean false for a response + - a serialized value representing the result + + Exceptions are serialized with `serializeException` so they will be thrown immediatly when they are unserialized. **/ class SocketProtocol { diff --git a/std/haxe/remoting/SocketWrapper.hx b/std/haxe/remoting/SocketWrapper.hx index 64022247..c2bc67e9 100644 --- a/std/haxe/remoting/SocketWrapper.hx +++ b/std/haxe/remoting/SocketWrapper.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -23,7 +23,7 @@ package haxe.remoting; import haxe.remoting.SocketProtocol.Socket; /** - See [js.XMLSocket] + @see `js.XMLSocket` **/ class SocketWrapper { diff --git a/std/haxe/remoting/SyncSocketConnection.hx b/std/haxe/remoting/SyncSocketConnection.hx index f3555f47..41cf2104 100644 --- a/std/haxe/remoting/SyncSocketConnection.hx +++ b/std/haxe/remoting/SyncSocketConnection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -51,7 +51,6 @@ class SyncSocketConnection implements Connection implements Dynamic } return proto.processAnswer(data); } - return null; // never reached } public function processRequest() { diff --git a/std/haxe/rtti/CType.hx b/std/haxe/rtti/CType.hx index 2183e959..17578563 100644 --- a/std/haxe/rtti/CType.hx +++ b/std/haxe/rtti/CType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,12 +21,24 @@ */ package haxe.rtti; +/** + The (dot-)path of the runtime type. +**/ typedef Path = String +/** + A list of strings representing the targets where the type is available. +**/ typedef Platforms = List +/** + The function argument runtime type information. +**/ typedef FunctionArgument = { name : String, opt : Bool, t : CType, ?value:String } +/** + The runtime member types. +**/ enum CType { CUnknown; CEnum( name : Path, params : List ); @@ -38,13 +50,30 @@ enum CType { CAbstract( name : Path, params : List ); } +/** + The type parameters in the runtime type information. +**/ typedef PathParams = { + /** + The path of the type. + **/ var path : Path; + + /** + The list of parameters types. + **/ var params : List; } -typedef TypeParams = Array // no contraints +/** + An array of strings representing the names of the type parameters the type + has. As of Haxe 3.2.0, this does not include the constraints. +**/ +typedef TypeParams = Array // no constraints +/** + Represents the runtime rights of a type. +**/ enum Rights { RNormal; RNo; @@ -54,63 +83,258 @@ enum Rights { RInline; } +/** + The list of runtime metadata. +**/ typedef MetaData = Array<{ name : String, params : Array }>; +/** + The runtime class field information. + + @see +**/ typedef ClassField = { + /** + The name of the field. + **/ var name : String; + + /** + The type of the field. + **/ var type : CType; + + /** + Whether or not the field is public. + **/ var isPublic : Bool; + + /** + Whether or not the field overrides another field. + **/ var isOverride : Bool; + + /** + The documentation of the field. This information is only available + if the compiler flag `-D use_rtti_doc` was in place. Otherwise, or + if the field has no documentation, the value is `null`. + **/ var doc : Null; + + /** + The [read access](https://haxe.org/manual/dictionary.html#define-read-access) + behavior of the field. + **/ var get : Rights; + + /** + The [write access](https://haxe.org/manual/dictionary.html#define-write-access) + behavior of the field. + **/ var set : Rights; + + /** + An array of strings representing the names of the type parameters + the field has. + **/ var params : TypeParams; + + /** + A list of strings representing the targets where the field is available. + **/ var platforms : Platforms; + + /** + The meta data the field was annotated with. + **/ var meta : MetaData; + + /** + The line number where the field is defined. This information is only + available if the field has an expression. + Otherwise the value is `null`. + **/ var line : Null; + + /** + The list of available overloads for the fields or `null` if no overloads + exists. + **/ var overloads : Null>; + + /** + The actual expression of the field or `null` if there is no expression. + **/ var expr : Null; } +/** + The general runtime type information. +**/ typedef TypeInfos = { + /** + The type path of the type. + **/ var path : Path; + + /** + The type path of the module containing the type. + **/ var module : Path; + + /** + The full slash path of the .hx file containing the type. + This might be `null` in case there is no such file, e.g. if the + type is defined through a macro. + **/ var file : Null; + + /** + An array of strings representing the names of the type parameters the + type has. + **/ var params : TypeParams; + + /** + The documentation of the type. This information is only available + if the compiler flag `-D use_rtti_doc` was in place. Otherwise, or if + the constructor has no documentation, the value is `null`. + **/ var doc : Null; + + /** + Whether or not the type is [private](https://haxe.org/manual/dictionary.html#define-private-type). + **/ var isPrivate : Bool; + + /** + A list of strings representing the targets where the type is available. + **/ var platforms : Platforms; + + /** + The [metadata](https://haxe.org/manual/lf-metadata.html) the type was + annotated with. + **/ var meta : MetaData; } +/** + The runtime class definition information. +**/ typedef Classdef = {> TypeInfos, + /** + Whether or not the class is [extern](https://haxe.org/manual/lf-externs.html). + **/ var isExtern : Bool; + + /** + Whether or not the class is actually an [interface](https://haxe.org/manual/types-interfaces.html). + **/ var isInterface : Bool; + + /** + The class' parent class defined by its type path and list of type + parameters. + **/ var superClass : Null; + + /** + The list of interfaces defined by their type path and list of type + parameters. + **/ var interfaces : List; + + /** + The list of member [class fields](https://haxe.org/manual/class-field.html). + **/ var fields : List; + + /** + The list of static class fields. + **/ var statics : List; + + /** + The type which is dynamically implemented by the class or `null` if no + such type exists. + **/ var tdynamic : Null; } +/** + The runtime enum constructor information. + + @see +**/ typedef EnumField = { + /** + The name of the constructor. + **/ var name : String; + + /** + The list of arguments the constructor has or `null` if no arguments are + available. + **/ var args : Null>; + + /** + The documentation of the constructor. This information is only available + if the compiler flag `-D use_rtti_doc` was in place. Otherwise, or if + the constructor has no documentation, the value is `null`. + **/ var doc : String; + + /** + A list of strings representing the targets where the constructor is + available. + **/ var platforms : Platforms; + + /** + The meta data the constructor was annotated with. + **/ var meta : MetaData; } +/** + The enum runtime type information. + + @see +**/ typedef Enumdef = {> TypeInfos, + /** + Whether or not the enum is [extern](https://haxe.org/manual/lf-externs.html). + **/ var isExtern : Bool; + + /** + The list of enum constructors. + **/ var constructors : List; } +/** + The typedef runtime information. +**/ typedef Typedef = {> TypeInfos, + /** + The type of the typedef. + **/ var type : CType; + + /** + The types of the typedef, by platform. + **/ var types : Map; // by platform } +/** + The abstract type runtime information. + + @see +**/ typedef Abstractdef = {> TypeInfos, var to : Array<{t:CType, field:Null}>; var from : Array<{t:CType, field:Null}>; @@ -118,6 +342,9 @@ typedef Abstractdef = {> TypeInfos, var athis : CType; } +/** + The tree types of the runtime type. +**/ enum TypeTree { TPackage( name : String, full : String, subs : Array ); TClassdecl( c : Classdef ); @@ -126,8 +353,14 @@ enum TypeTree { TAbstractdecl( a : Abstractdef ); } +/** + List of `TypeTree`. +**/ typedef TypeRoot = Array +/** + Contains type and equality checks functionalities for RTTI. +**/ class TypeApi { public static function typeInfos( t : TypeTree ) : TypeInfos { @@ -142,6 +375,10 @@ class TypeApi { return inf; } + /** + Returns `true` if the given `CType` is a variable or `false` if it is a + function. + **/ public static function isVar( t : CType ) { return switch( t ) { case CFunction(_,_): false; @@ -163,6 +400,12 @@ class TypeApi { return true; } + /** + Unlike `r1 == r2`, this function performs a deep equality check on + the given `Rights` instances. + + If `r1` or `r2` are `null`, the result is unspecified. + **/ public static function rightsEq( r1 : Rights, r2 : Rights ) { if( r1 == r2 ) return true; @@ -178,6 +421,12 @@ class TypeApi { return false; } + /** + Unlike `t1 == t2`, this function performs a deep equality check on + the given `CType` instances. + + If `t1` or `t2` are `null`, the result is unspecified. + **/ public static function typeEq( t1 : CType, t2 : CType ) { switch( t1 ) { case CUnknown: return t2 == CUnknown; @@ -231,6 +480,12 @@ class TypeApi { return false; } + /** + Unlike `f1 == f2`, this function performs a deep equality check on + the given `ClassField` instances. + + If `f1` or `f2` are `null`, the result is unspecified. + **/ public static function fieldEq( f1 : ClassField, f2 : ClassField ) { if( f1.name != f2.name ) return false; @@ -251,6 +506,12 @@ class TypeApi { return true; } + /** + Unlike `c1 == c2`, this function performs a deep equality check on + the arguments of the enum constructors, if exists. + + If `c1` or `c2` are `null`, the result is unspecified. + **/ public static function constructorEq( c1 : EnumField, c2: EnumField ) { if( c1.name != c2.name ) return false; @@ -265,7 +526,14 @@ class TypeApi { } +/** + The CTypeTools class contains some extra functionalities for handling + `CType` instances. +**/ class CTypeTools { + /** + Get the string representation of `CType`. + **/ static public function toString(t:CType):String { return switch (t) { case CUnknown: @@ -276,7 +544,7 @@ class CTypeTools { if (args.length == 0) { "Void -> " +toString(ret); } else { - args.map(functionArgumentName).join(" -> "); + args.map(functionArgumentName).join(" -> ")+" -> "+toString(ret); } case CDynamic(d): if (d == null) { @@ -297,7 +565,7 @@ class CTypeTools { } static function functionArgumentName(arg:FunctionArgument) { - return (arg.opt ? "?" : "") + arg.name + ":" + toString(arg.t) + (arg.value == null ? "" : " = " +arg.value); + return (arg.opt ? "?" : "") + (arg.name == "" ? "" : arg.name + ":") + toString(arg.t) + (arg.value == null ? "" : " = " +arg.value); } static function classField(cf:ClassField) { diff --git a/std/haxe/rtti/Meta.hx b/std/haxe/rtti/Meta.hx index eebfff5f..ec0cac98 100644 --- a/std/haxe/rtti/Meta.hx +++ b/std/haxe/rtti/Meta.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,8 +21,16 @@ */ package haxe.rtti; +private typedef MetaObject = { + ?fields:Dynamic>>>, + ?statics:Dynamic>>>, + ?obj:Dynamic>>, +} + /** - An api to access classes and enums metadata at runtime. + An API to access classes and enums metadata at runtime. + + @see **/ class Meta { @@ -34,18 +42,33 @@ class Meta { return (meta == null || meta.obj == null) ? {} : meta.obj; } - private static function getMeta(t:Dynamic):Dynamic + // Could move this to Type.hx? + private static function isInterface(t:Dynamic):Bool { + #if java + return java.Lib.toNativeType(t).isInterface(); + #elseif cs + return cs.Lib.toNativeType(t).IsInterface; + #elseif (flash && as3) + return untyped flash.Lib.describeType(t).factory.extendsClass.length() == 0; + #elseif (php && !php7) + return untyped __php__("{0} instanceof _hx_interface", t); + #else + throw "Something went wrong"; + #end + } + + private static function getMeta(t:Dynamic):MetaObject { -#if (java || cs) +#if (php && php7) + return php.Boot.getMeta(t.phpClassName); +#elseif (java || cs || php || (flash && as3)) + #if php + t.__ensureMeta__(); + #end var ret = Reflect.field(t, "__meta__"); if (ret == null && Std.is(t,Class)) { -#if java - var interf = java.Lib.toNativeType(t).isInterface(); -#elseif cs - var interf = cs.Lib.toNativeType(t).IsInterface; -#end - if (interf) + if (isInterface(t)) { var name = Type.getClassName(t), cls = Type.resolveClass(name + '_HxMeta'); @@ -54,6 +77,9 @@ class Meta { } } return ret; +#elseif hl + var t : hl.BaseType = t; + return t.__meta__; #else return untyped t.__meta__; #end diff --git a/std/haxe/rtti/Rtti.hx b/std/haxe/rtti/Rtti.hx index a6d7ea2a..c7c0e432 100644 --- a/std/haxe/rtti/Rtti.hx +++ b/std/haxe/rtti/Rtti.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,6 +25,8 @@ import haxe.rtti.CType; /** Rtti is a helper class which supplements the `@:rtti` metadata. + + @see **/ class Rtti { diff --git a/std/haxe/rtti/XmlParser.hx b/std/haxe/rtti/XmlParser.hx index d445664a..70af7628 100644 --- a/std/haxe/rtti/XmlParser.hx +++ b/std/haxe/rtti/XmlParser.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -23,6 +23,12 @@ package haxe.rtti; import haxe.rtti.CType; import haxe.xml.Fast; +/** + XmlParser processes the runtime type information (RTTI) which + is stored as a XML string in a static field `__rtti`. + + @see +**/ class XmlParser { public var root : TypeRoot; diff --git a/std/haxe/unit/TestCase.hx b/std/haxe/unit/TestCase.hx index 8c90e9b8..b8170431 100644 --- a/std/haxe/unit/TestCase.hx +++ b/std/haxe/unit/TestCase.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,17 +22,52 @@ package haxe.unit; import haxe.PosInfos; +/** + This unit test class should be extended to create test cases. Each test + method created in this extended class should start with the name "test". + + These test methods should call the assertion methods: + + * `assertTrue(a)`: Succeeds if `a` is `true`. + * `assertFalse(a)`: Succeeds if `a` is `false`. + * `assertEquals(expected, actual)`: Succeeds if `expected` and `actual` + are equal. + + ```haxe + class MyTestCase extends haxe.unit.TestCase { + function testBasic() { + assertEquals("A", "A"); + } + } + ``` + + The TestCase can be tested using `TestRunner`. + + To run code before or after the test, override the functions `setup` + and `tearDown`. + + @see +**/ @:keepSub @:publicFields class TestCase { + /** + The current test status of the TestRunner. + **/ public var currentTest : TestStatus; public function new( ) { } + /** + Override this method to execute code before the test runs. + **/ public function setup() : Void { } + /** + Override this method to execute code after the test ran. + **/ public function tearDown() : Void { } @@ -40,6 +75,9 @@ class TestCase { haxe.unit.TestRunner.print(v); } + /** + Succeeds if `b` is `true`. + **/ function assertTrue( b:Bool, ?c : PosInfos ) : Void { currentTest.done = true; if (b != true){ @@ -50,6 +88,9 @@ class TestCase { } } + /** + Succeeds if `b` is `false`. + **/ function assertFalse( b:Bool, ?c : PosInfos ) : Void { currentTest.done = true; if (b == true){ @@ -60,7 +101,10 @@ class TestCase { } } - function assertEquals( expected: T , actual: T, ?c : PosInfos ) : Void { + /** + Succeeds if `expected` and `actual` are equal. + **/ + function assertEquals( expected: T , actual: T, ?c : PosInfos ) : Void { currentTest.done = true; if (actual != expected){ currentTest.success = false; @@ -69,5 +113,4 @@ class TestCase { throw currentTest; } } - } diff --git a/std/haxe/unit/TestResult.hx b/std/haxe/unit/TestResult.hx index 94a65888..f906e424 100644 --- a/std/haxe/unit/TestResult.hx +++ b/std/haxe/unit/TestResult.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,10 +21,16 @@ */ package haxe.unit; +/** + TestResult contains the result of the executed unit tests. +**/ class TestResult { - var m_tests : List; - public var success(default,null) : Bool; + + /** + `true` if the unit test succesfully executed the test cases. + **/ + public var success(default, null) : Bool; public function new() { m_tests = new List(); @@ -37,6 +43,9 @@ class TestResult { success = false; } + /** + String representation from the result of the unit test. + **/ public function toString() : String { var buf = new StringBuf(); var failures = 0; diff --git a/std/haxe/unit/TestRunner.hx b/std/haxe/unit/TestRunner.hx index 5937f415..7473d780 100644 --- a/std/haxe/unit/TestRunner.hx +++ b/std/haxe/unit/TestRunner.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,14 +22,41 @@ package haxe.unit; import Reflect; +/** + This class runs unit test cases and prints the result. + + ```haxe + var r = new haxe.unit.TestRunner(); + r.add(new MyTestCase()); + // add other TestCases here + + // finally, run the tests + r.run(); + ``` + + @see +**/ class TestRunner { + /** + The unit test results. Available after the `run()` is called. + **/ public var result(default, null) : TestResult; + var cases : List; #if flash static var tf : flash.text.TextField = null; #end + /** + Prints the given object/value. + + * Flash outputs the result in a new `TextField` on stage. + * JavaScript outputs the result using `console.log`. + * Other targets use native `print` to output the result. + + This function is `dynamic` so it can be overriden in custom setups. + **/ public static dynamic function print( v : Dynamic ) untyped { #if flash if( tf == null ) { @@ -49,11 +76,11 @@ class TestRunner { #elseif js var msg = js.Boot.__string_rec(v,""); var d; - if( __js__("typeof")(document) != "undefined" - && (d = document.getElementById("haxe:trace")) != null ) { - msg = StringTools.htmlEscape(msg).split("\n").join("
"); - d.innerHTML += msg+"
"; - } + if( __js__("typeof")(document) != "undefined" + && (d = document.getElementById("haxe:trace")) != null ) { + msg = StringTools.htmlEscape(msg).split("\n").join("
"); + d.innerHTML += msg+"
"; + } else if ( __js__("typeof process") != "undefined" && __js__("process").stdout != null && __js__("process").stdout.write != null) @@ -69,6 +96,8 @@ class TestRunner { untyped __java__("java.lang.System.out.print(str)"); #elseif python python.Lib.print(v); + #elseif (hl || lua) + Sys.print(Std.string(v)); #end } @@ -81,10 +110,18 @@ class TestRunner { cases = new List(); } + /** + Add TestCase instances to the unit test. + **/ public function add( c:TestCase ) : Void{ cases.add(c); } + /** + Runs the unit tests and prints the results. + + @return `true` if the unit test succesfully executed the test cases. + **/ public function run() : Bool { result = new TestResult(); for ( c in cases ){ diff --git a/std/haxe/unit/TestStatus.hx b/std/haxe/unit/TestStatus.hx index 7f72aa7e..bd885597 100644 --- a/std/haxe/unit/TestStatus.hx +++ b/std/haxe/unit/TestStatus.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,18 +24,49 @@ import haxe.CallStack; import haxe.PosInfos; +/** + The status information of a unit test case method. + + @see +**/ class TestStatus { + /** + `true` when the unit test is executed. + **/ public var done : Bool; + + /** + `true` when succesfully unit tested. + **/ public var success : Bool; + + /** + The error message of the unit test method. + **/ public var error : String; + + /** + The method name of the unit test. + **/ public var method : String; + + /** + The class name of the unit test. + **/ public var classname : String; + + /** + The position information of the unit test. + **/ public var posInfos : PosInfos; + + /** + The representation of the stack exception. + **/ public var backtrace : String; public function new() { done = false; success = false; } - } diff --git a/std/haxe/web/Dispatch.hx b/std/haxe/web/Dispatch.hx index 0fe0dfc6..47526fb4 100644 --- a/std/haxe/web/Dispatch.hx +++ b/std/haxe/web/Dispatch.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/web/Request.hx b/std/haxe/web/Request.hx index c5de4d10..90d86f31 100644 --- a/std/haxe/web/Request.hx +++ b/std/haxe/web/Request.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,10 @@ */ package haxe.web; +#if (!neko && !php && !js) +#error "Not supported on this target" +#end + class Request { /** diff --git a/std/haxe/xml/Check.hx b/std/haxe/xml/Check.hx index 2c467564..d16b5184 100644 --- a/std/haxe/xml/Check.hx +++ b/std/haxe/xml/Check.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/xml/Fast.hx b/std/haxe/xml/Fast.hx index 531e31db..4fac79fe 100644 --- a/std/haxe/xml/Fast.hx +++ b/std/haxe/xml/Fast.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -106,17 +106,106 @@ private class NodeListAccess implements Dynamic> { } +/** + The `haxe.xml.Fast` API helps providing a fast dot-syntax access to the + most common `Xml` methods. +**/ class Fast { - - public var x(default,null) : Xml; + /** + The current corresponding `Xml` node. + **/ + public var x(default, null) : Xml; + + /** + The name of the current element. This is the same as `Xml.nodeName`. + **/ public var name(get,null) : String; + + /** + The inner PCDATA or CDATA of the node. + + An exception is thrown if there is no data or if there not only data + but also other nodes. + **/ public var innerData(get,null) : String; + + /** + The XML string built with all the sub nodes, excluding the current one. + **/ public var innerHTML(get,null) : String; + + /** + Access to the first sub element with the given name. + + An exception is thrown if the element doesn't exists. + Use `hasNode` to check the existence of a node. + + ```haxe + var fast = new haxe.xml.Fast(Xml.parse("John")); + var user = fast.node.user; + var name = user.node.name; + trace(name.innerData); // John + + // Uncaught Error: Document is missing element password + var password = user.node.password; + ``` + **/ public var node(default,null) : NodeAccess; + + /** + Access to the List of elements with the given name. + ```haxe + var fast = new haxe.xml.Fast(Xml.parse(" + + + + ")); + + var users = fast.node.users; + for(user in users.nodes.user) { + trace(user.att.name); + } + ``` + **/ public var nodes(default,null) : NodeListAccess; + + /** + Access to a given attribute. + + An exception is thrown if the attribute doesn't exists. + Use `has` to check the existence of an attribute. + + ```haxe + var f = new haxe.xml.Fast(Xml.parse("")); + var user = f.node.user; + if (user.has.name) { + trace(user.att.name); // Mark + } + ``` + **/ public var att(default,null) : AttribAccess; + + /** + Check the existence of an attribute with the given name. + **/ public var has(default,null) : HasAttribAccess; + + /** + Check the existence of a sub node with the given name. + + ```haxe + var f = new haxe.xml.Fast(Xml.parse("31")); + var user = f.node.user; + if (user.hasNode.age) { + trace(user.node.age.innerData); // 31 + } + ``` + **/ public var hasNode(default,null) : HasNodeAccess; + + /** + The list of all sub-elements which are the nodes with type `Xml.Element`. + **/ public var elements(get,null) : Iterator; public function new( x : Xml ) { @@ -139,12 +228,14 @@ class Fast { if( !it.hasNext() ) throw name+" does not have data"; var v = it.next(); - var n = it.next(); - if( n != null ) { + if( it.hasNext() ) { + var n = it.next(); // handle CDATA if( v.nodeType == Xml.PCData && n.nodeType == Xml.CData && StringTools.trim(v.nodeValue) == "" ) { + if( !it.hasNext() ) + return n.nodeValue; var n2 = it.next(); - if( n2 == null || (n2.nodeType == Xml.PCData && StringTools.trim(n2.nodeValue) == "" && it.next() == null) ) + if( n2.nodeType == Xml.PCData && StringTools.trim(n2.nodeValue) == "" && !it.hasNext() ) return n.nodeValue; } throw name+" does not only have data"; diff --git a/std/haxe/xml/Parser.hx b/std/haxe/xml/Parser.hx index 94607477..76560e45 100644 --- a/std/haxe/xml/Parser.hx +++ b/std/haxe/xml/Parser.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -46,6 +46,59 @@ extern private class S { public static inline var ESCAPE = 18; } +class XmlParserException +{ + /** + * the XML parsing error message + */ + public var message:String; + + /** + * the line number at which the XML parsing error occured + */ + public var lineNumber:Int; + + /** + * the character position in the reported line at which the parsing error occured + */ + public var positionAtLine:Int; + + /** + * the character position in the XML string at which the parsing error occured + */ + public var position:Int; + + /** + * the invalid XML string + */ + public var xml:String; + + public function new(message:String, xml:String, position:Int) + { + this.xml = xml; + this.message = message; + this.position = position; + lineNumber = 1; + positionAtLine = 0; + + for( i in 0...position) + { + var c = xml.fastCodeAt(i); + if (c == '\n'.code) { + lineNumber++; + positionAtLine = 0; + } else { + if (c != '\r'.code) positionAtLine++; + } + } + } + + public function toString():String + { + return Type.getClassName(Type.getClass(this)) + ": " + message + " at line " + lineNumber + " char " + positionAtLine; + } +} + class Parser { static var escapes = { @@ -59,8 +112,10 @@ class Parser } /** - Parses the String into an XML Document. Set strict parsing to true in order to enable a strict check of XML attributes and entities. - **/ + * Parses the String into an XML Document. Set strict parsing to true in order to enable a strict check of XML attributes and entities. + * + * @throws haxe.xml.XmlParserException + */ static public function parse(str:String, strict = false) { var doc = Xml.createDocument(); @@ -144,7 +199,7 @@ class Parser { p += 2; if (str.substr(p, 6).toUpperCase() != "CDATA[") - throw("Expected '.code | '<'.code if( strict ): // HTML allows these in attributes values - throw "Invalid unescaped " + String.fromCharCode(c) + " in attribute value"; + throw new XmlParserException("Invalid unescaped " + String.fromCharCode(c) + " in attribute value", str, p); case _ if (c == attrValQuote): buf.addSub(str, start, p - start); var val = buf.toString(); @@ -264,7 +319,7 @@ class Parser case '>'.code: state = S.BEGIN; default : - throw("Expected >"); + throw new XmlParserException("Expected >", str, p); } case S.WAIT_END_RET: switch(c) @@ -274,17 +329,17 @@ class Parser parent.addChild(Xml.createPCData("")); return p; default : - throw("Expected >"); + throw new XmlParserException("Expected >", str, p); } case S.CLOSE: if (!isValidChar(c)) { if( start == p ) - throw("Expected node name"); + throw new XmlParserException("Expected node name", str, p); var v = str.substr(start,p - start); if (v != parent.nodeName) - throw "Expected "; + throw new XmlParserException("Expected ", str, p); state = S.IGNORE_SPACES; next = S.WAIT_END_RET; @@ -323,7 +378,7 @@ class Parser var c = s.fastCodeAt(1) == 'x'.code ? Std.parseInt("0" +s.substr(1, s.length - 1)) : Std.parseInt(s.substr(1, s.length - 1)); - #if (neko || cpp || php) + #if (neko || cpp || php || lua) if( c >= 128 ) { // UTF8-encode it if( c <= 0x7FF ) { @@ -339,13 +394,13 @@ class Parser buf.addChar(0x80 | ((c >> 6) & 63)); buf.addChar(0x80 | (c & 63)); } else - throw "Cannot encode UTF8-char " + c; + throw new XmlParserException("Cannot encode UTF8-char " + c, str, p); } else #end buf.addChar(c); } else if (!escapes.exists(s)) { if( strict ) - throw 'Undefined entity: $s'; + throw new XmlParserException("Undefined entity: " + s, str, p); buf.add('&$s;'); } else { buf.add(escapes.get(s)); @@ -354,7 +409,7 @@ class Parser state = escapeNext; } else if (!isValidChar(c) && c != "#".code) { if( strict ) - throw 'Invalid character in entity: ' + String.fromCharCode(c); + throw new XmlParserException("Invalid character in entity: " + String.fromCharCode(c), str, p); buf.addChar("&".code); buf.addSub(str, start, p - start); p--; @@ -387,10 +442,10 @@ class Parser return p; } - throw "Unexpected end"; + throw new XmlParserException("Unexpected end", str, p); } static inline function isValidChar(c) { return (c >= 'a'.code && c <= 'z'.code) || (c >= 'A'.code && c <= 'Z'.code) || (c >= '0'.code && c <= '9'.code) || c == ':'.code || c == '.'.code || c == '_'.code || c == '-'.code; } -} \ No newline at end of file +} diff --git a/std/haxe/xml/Printer.hx b/std/haxe/xml/Printer.hx index aa5bd6c9..aa47d1e2 100644 --- a/std/haxe/xml/Printer.hx +++ b/std/haxe/xml/Printer.hx @@ -1,35 +1,37 @@ /* - * Copyright (c)2005-2013, Haxe Foundation + * Copyright (C)2005-2017 Haxe Foundation * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * 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: * - * 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. - * Neither the name of the Haxe Foundation nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 COPYRIGHT HOLDER OR 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 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 haxe.xml; +/** + This class provides utility methods to convert Xml instances to + String representation. +**/ class Printer { - + /** + Convert `Xml` to string representation. + + Set `pretty` to `true` to prettify the result. + **/ static public function print(xml:Xml, ?pretty = false) { var printer = new Printer(pretty); printer.writeNode(xml, ""); @@ -92,8 +94,10 @@ class Printer { } case ProcessingInstruction: write(""); + newline(); case DocType: write(""); + newline(); } } @@ -103,16 +107,16 @@ class Printer { inline function newline() { if (pretty) { - output.add(""); + output.add("\n"); } } function hasChildren(value:Xml):Bool { for (child in value) { switch (child.nodeType) { - case Xml.Element, Xml.PCData: + case Element, PCData: return true; - case Xml.CData, Xml.Comment: + case CData, Comment: if (StringTools.ltrim(child.nodeValue).length != 0) { return true; } @@ -121,4 +125,4 @@ class Printer { } return false; } -} \ No newline at end of file +} diff --git a/std/haxe/xml/Proxy.hx b/std/haxe/xml/Proxy.hx index daad00d7..b607e612 100644 --- a/std/haxe/xml/Proxy.hx +++ b/std/haxe/xml/Proxy.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,18 +26,17 @@ package haxe.xml; It will only allow access to fields which corresponds to an "id" attribute value in the XML file : - [ - class MyXml extends haxe.xml.Proxy<"my.xml",MyStructure> { + ```haxe + class MyXml extends haxe.xml.Proxy<"my.xml", MyStructure> { } - ... + var h = new haxe.ds.StringMap(); // ... fill h with "my.xml" content var m = new MyXml(h.get); trace(m.myNode.structField); - // access to "myNode" is only possible - // if you have an id="myNode" attribute - // in your XML, and completion works as well - ] + // Access to "myNode" is only possible if you have an id="myNode" attribute + // in your XML, and completion works as well. + ``` **/ class Proxy { diff --git a/std/haxe/zip/Compress.hx b/std/haxe/zip/Compress.hx index 308159c3..d87535b5 100644 --- a/std/haxe/zip/Compress.hx +++ b/std/haxe/zip/Compress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/zip/Entry.hx b/std/haxe/zip/Entry.hx index e63b0271..4ca3cf4e 100644 --- a/std/haxe/zip/Entry.hx +++ b/std/haxe/zip/Entry.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/zip/FlushMode.hx b/std/haxe/zip/FlushMode.hx index 071e9ebd..9a529f7b 100644 --- a/std/haxe/zip/FlushMode.hx +++ b/std/haxe/zip/FlushMode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/zip/Huffman.hx b/std/haxe/zip/Huffman.hx index d9696a0b..b1e87443 100644 --- a/std/haxe/zip/Huffman.hx +++ b/std/haxe/zip/Huffman.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/zip/InflateImpl.hx b/std/haxe/zip/InflateImpl.hx index 6f7a7930..f77ff0fb 100644 --- a/std/haxe/zip/InflateImpl.hx +++ b/std/haxe/zip/InflateImpl.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/zip/Reader.hx b/std/haxe/zip/Reader.hx index e5ccffb1..f25be4d1 100644 --- a/std/haxe/zip/Reader.hx +++ b/std/haxe/zip/Reader.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -129,7 +129,7 @@ class Reader { #if neko // enter progressive mode : we use a different input which has // a temporary buffer, this is necessary since we have to uncompress - // progressively, and after that we might have pending readed data + // progressively, and after that we might have pending read data // that needs to be processed var bufSize = 65536; if( buf == null ) { diff --git a/std/haxe/zip/Tools.hx b/std/haxe/zip/Tools.hx index 64299148..c180332a 100644 --- a/std/haxe/zip/Tools.hx +++ b/std/haxe/zip/Tools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/zip/Uncompress.hx b/std/haxe/zip/Uncompress.hx index 53a28d34..3e792b06 100644 --- a/std/haxe/zip/Uncompress.hx +++ b/std/haxe/zip/Uncompress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/haxe/zip/Writer.hx b/std/haxe/zip/Writer.hx index 55a94b02..6b33b8da 100644 --- a/std/haxe/zip/Writer.hx +++ b/std/haxe/zip/Writer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/hl/Abstract.hx b/std/hl/Abstract.hx new file mode 100644 index 00000000..b3b99d7a --- /dev/null +++ b/std/hl/Abstract.hx @@ -0,0 +1,25 @@ +/* + * Copyright (C)2005-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 hl; + +extern class Abstract { +} \ No newline at end of file diff --git a/std/hl/Api.hx b/std/hl/Api.hx new file mode 100644 index 00000000..f79f6d77 --- /dev/null +++ b/std/hl/Api.hx @@ -0,0 +1,41 @@ +/* + * Copyright (C)2005-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 hl; + +extern class Api { + + static inline function rethrow( v : Dynamic ) : Void { untyped $rethrow(v); } + @:hlNative("std","obj_get_field") static function getField( obj : Dynamic, hash : Int ) : Dynamic; + @:hlNative("std","obj_set_field") static function setField( obj : Dynamic, hash : Int, value : Dynamic ) : Void; + @:hlNative("std","obj_has_field") static function hasField( obj : Dynamic, hash : Int ) : Bool; + @:hlNative("std","obj_delete_field") static function deleteField( obj : Dynamic, hash : Int ) : Bool; + @:hlNative("std","call_method") static function callMethod( f : haxe.Constraints.Function, args : NativeArray ) : Dynamic; + @:hlNative("std","get_closure_value") static function getClosureValue( f : haxe.Constraints.Function ) : Dynamic; + @:hlNative("std","no_closure") static function noClosure( f : haxe.Constraints.Function ) : haxe.Constraints.Function; + @:hlNative("std", "value_cast") static function safeCast( v : Dynamic, t : Type ) : Dynamic; + @:hlNative("std", "make_var_args") static function makeVarArgs( v : NativeArray -> Dynamic ) : haxe.Constraints.Function; + @:hlNative("std", "get_virtual_value") static function getVirtualValue( v : Dynamic ) : Dynamic; + @:hlNative("std", "set_error_handler") static function setErrorHandler( v : Dynamic -> Void ) : Void; + @:hlNative("std", "breakpoint") static function breakPoint() : Void; + @:hlNative("std", "sys_is64") static function is64() : Bool; + +} diff --git a/std/hl/BaseType.hx b/std/hl/BaseType.hx new file mode 100644 index 00000000..76eee600 --- /dev/null +++ b/std/hl/BaseType.hx @@ -0,0 +1,67 @@ +/* + * Copyright (C)2005-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 hl; + +@:keep +class BaseType { + public var __type__ : Type; + public var __meta__ : Dynamic; + public var __implementedBy__ : NativeArray; + public function check( v : Dynamic ) { + var t = Type.getDynamic(v); + if( t.kind == HVirtual ) { + var v2 = hl.Api.getVirtualValue(v); + if( v2 != null ) t = Type.getDynamic(v2); + } + if( __implementedBy__ == null ) { + if( t.safeCast(__type__) ) + return true; + return false; + } + for( i in __implementedBy__ ) + if( t.safeCast(i) ) + return true; + return false; + } +} + +@:keep +class Class extends BaseType { + public var __name__ : String; + public var __constructor__ : Dynamic; +} + +@:keep +class Enum extends BaseType { + public var __ename__ : String; + public var __emap__ : hl.types.BytesMap; + public var __constructs__ : Array; + public var __evalues__ : NativeArray; +} + +@:keep +class CoreType extends Class { +} + +@:keep +class CoreEnum extends Enum { +} diff --git a/std/hl/Boot.hx b/std/hl/Boot.hx new file mode 100644 index 00000000..680e2239 --- /dev/null +++ b/std/hl/Boot.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-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 hl; + +import hl.types.ArrayDyn; +import hl.BaseType; + +@:dox(hide) +extern class Boot { +} diff --git a/std/hl/Bytes.hx b/std/hl/Bytes.hx new file mode 100644 index 00000000..0e502ccf --- /dev/null +++ b/std/hl/Bytes.hx @@ -0,0 +1,216 @@ +/* + * Copyright (C)2005-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 hl; + +@:coreType abstract Bytes { + + @:extern public inline function new( v : Int ) { + this = alloc(v); + } + + @:hlNative("std","bytes_blit") public function blit( pos : Int, src : Bytes, srcPos : Int, len : Int ) : Void { + } + + @:extern @:arrayAccess public inline function getUI8( pos : Int ) : Int { + return untyped $bgetui8(this,pos); + } + + @:extern @:arrayAccess public inline function setUI8( pos : Int, value : Int ) : Int { + untyped $bsetui8(this,pos,value); + return value; + } + + @:extern public inline function getI32( pos : Int ) : Int { + return untyped $bgeti32(this,pos); + } + + public inline function getUI16( pos : Int ) : Int { + return untyped $bgetui16(this, pos); + } + + public inline function setUI16( pos : Int, v : Int ) { + untyped $bsetui16(this,pos,v); + } + + @:extern public inline function getF32( pos : Int ) : F32 { + return untyped $bgetf32(this,pos); + } + + @:extern public inline function getF64( pos : Int ) : Float { + return untyped $bgetf64(this,pos); + } + + @:extern public inline function setI32( pos : Int, value : Int ) : Void { + untyped $bseti32(this, pos, value); + } + + @:extern public inline function setF32( pos : Int, value : F32 ) : Void { + untyped $bsetf32(this, pos, value); + } + + @:extern public inline function setF64( pos : Int, value : Float ) : Void { + untyped $bsetf64(this, pos, value); + } + + @:hlNative("std","alloc_bytes") + static function alloc( size : Int ) : Bytes { + return null; + } + + @:hlNative("std","parse_int") + public function parseInt( pos : Int, size : Int ) : Null { + return null; + } + + @:hlNative("std","parse_float") + public function parseFloat( pos : Int, size : Int ) : Float { + return 0.; + } + + @:hlNative("std","bytes_compare") + public function compare( pos : Int, bytes : Bytes, bytesPos : Int, size : Int ) : Int { + return 0; + } + + @:hlNative("std","bytes_find") + public function find( pos : Int, size : Int, bytes : Bytes, bytesPos : Int, bytesSize : Int ) : Int { + return 0; + } + + @:hlNative("std","bytes_fill") + public function fill( pos : Int, size : Int, v : Int ) : Void { + } + + @:hlNative("std","bsort_i32") + public function sortI32( pos : Int, length : Int, f : Int->Int->Int ) : Void { + } + + @:hlNative("std","bsort_f64") + public function sortF64( pos : Int, length : Int, f : Float->Float->Int ) : Void { + } + + + /** + Please note that you need to retain the original unoffset'ed Bytes so it does not get garbage collected, unless the pointer was not GC allocated. + **/ + @:hlNative("std","bytes_offset") + public function offset( delta : Int ) : Bytes { + return null; + } + + /** + Returns an offset between the two pointers. This might overflow in 64 bits if the addresses of the two pointers differs by more than 4GB + **/ + @:hlNative("std","bytes_subtract") + public function subtract( other : Bytes ) : Int { + return 0; + } + + @:hlNative("std", "bytes_address") + static function get_address( b : Bytes, high : Ref ) : Int { + return 0; + } + + @:hlNative("std", "bytes_from_address") + static function from_address( low : Int, high : Int ) : Bytes { + return null; + } + + /** + Creates an pointer at a given memory address (highly unsafe) + **/ + public static inline function fromAddress( h : haxe.Int64 ) : Bytes { + return from_address(h.low, h.high); + } + + /** + Returns the address value of the bytes. On 32 bit system the upper 32 bits will always be 0 + **/ + public function address() : haxe.Int64 { + var high = 0; + var low = get_address(this, high); + return haxe.Int64.make(high,low); + } + + public function sub( pos : Int, size : Int ) { + var b = new Bytes(size); + b.blit(0, this, pos, size); + return b; + } + + @:hlNative("std", "ucs2length") + public function ucs2Length( bytePos : Int ) : Int { + return 0; + } + + @:hlNative("std","hash") + function hash() : Int { + return 0; + } + + @:hlNative("std","utf8_to_utf16") + public function utf8ToUtf16( bytePos : Int, outSize : Ref ) : Bytes { + return null; + } + + @:hlNative("std","utf16_to_utf8") + public function utf16ToUtf8( bytePos : Int, outSize : Ref ) : Bytes { + return null; + } + + @:hlNative("std", "ucs2_upper") + function ucs2Upper( bytePos : Int, size : Int ) : Bytes { + return null; + } + + @:hlNative("std", "ucs2_lower") + function ucs2Lower( bytePos : Int, size : Int ) : Bytes { + return null; + } + + @:hlNative("std", "url_encode") + function urlEncode( outSize : Ref ) : Bytes { + return null; + } + + @:hlNative("std", "url_decode") + function urlDecode( outSize : Ref ) : Bytes { + return null; + } + + @:hlNative("std","value_to_string") + public static function fromValue( v : Dynamic, length : Ref ) : Bytes { + return null; + } + + /** + Get the bytes reference from an array of basic types (no copy occurs) + **/ + @:extern public static inline function getArray( a : Array ) : Bytes { + return untyped $abytes(a); + } + + @:from + public static inline function fromBytes( bytes : haxe.io.Bytes ) { + return @:privateAccess bytes.b; + } +} \ No newline at end of file diff --git a/std/hl/BytesAccess.hx b/std/hl/BytesAccess.hx new file mode 100644 index 00000000..b0c8e326 --- /dev/null +++ b/std/hl/BytesAccess.hx @@ -0,0 +1,51 @@ +/* + * Copyright (C)2005-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 hl; + +@:coreType abstract BytesAccess from Bytes to Bytes { + + public var sizeBits(get, never) : Int; + public var nullValue(get, never) : T; + + + @:extern inline function get_sizeBits() { + return untyped $bytes_sizebits(this); + } + + @:extern inline function get_nullValue() { + return untyped $bytes_nullvalue(this); + } + + @:extern public inline function blit( pos : Int, src : BytesAccess, srcPos : Int, len : Int ) : Void { + (this:Bytes).blit(pos << sizeBits, src, srcPos << sizeBits, len << sizeBits); + } + + @:extern @:arrayAccess public inline function get( pos : Int ) : T { + return untyped $bget(this,pos); + } + + @:extern @:arrayAccess public inline function set( pos : Int, value : T ) : T { + untyped $bset(this,pos,value); + return value; + } + +} \ No newline at end of file diff --git a/std/hl/F32.hx b/std/hl/F32.hx new file mode 100644 index 00000000..8cca901c --- /dev/null +++ b/std/hl/F32.hx @@ -0,0 +1,24 @@ +/* + * Copyright (C)2005-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 hl; + +typedef F32 = Single; \ No newline at end of file diff --git a/std/hl/F64.hx b/std/hl/F64.hx new file mode 100644 index 00000000..02b74c38 --- /dev/null +++ b/std/hl/F64.hx @@ -0,0 +1,24 @@ +/* + * Copyright (C)2005-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 hl; + +typedef F64 = Float; diff --git a/std/hl/Format.hx b/std/hl/Format.hx new file mode 100644 index 00000000..c57d2278 --- /dev/null +++ b/std/hl/Format.hx @@ -0,0 +1,68 @@ +/* + * Copyright (C)2005-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 hl; + +@:enum abstract PixelFormat(Int) { + var RGB = 0; + var BGR = 1; + var RGBX = 2; + var BGRX = 3; + var XBGR = 4; + var XRGB = 5; + var GRAY = 6; + var RGBA = 7; + var BGRA = 8; + var ABGR = 9; + var ARGB = 10; + var CMYK = 11; +} + +/** + These are the bindings for the HL `fmt.hdll` library, which contains various low level formats handling. +**/ +class Format { + + /** + Decode JPG data into the target buffer. + **/ + @:hlNative("fmt","jpg_decode") + public static function decodeJPG( src : hl.Bytes, srcLen : Int, dst : hl.Bytes, width : Int, height : Int, stride : Int, format : PixelFormat, flags : Int ) : Bool { + return false; + } + + /** + Decode PNG data into the target buffer. + **/ + @:hlNative("fmt","png_decode") + public static function decodePNG( src : hl.Bytes, srcLen : Int, dst : hl.Bytes, width : Int, height : Int, stride : Int, format : PixelFormat, flags : Int ) : Bool { + return false; + } + + /** + Upscale/downscale an image. + Currently supported flag bits: 1 = bilinear filtering + **/ + @:hlNative("fmt","img_scale") + public static function scaleImage( out : hl.Bytes, outPos : Int, outStride : Int, outWidth : Int, outHeight : Int, _in : hl.Bytes, inPos : Int, inStride : Int, inWidth : Int, inHeight : Int, flags : Int ) { + } + +} \ No newline at end of file diff --git a/std/hl/Gc.hx b/std/hl/Gc.hx new file mode 100644 index 00000000..e5391590 --- /dev/null +++ b/std/hl/Gc.hx @@ -0,0 +1,47 @@ +/* + * Copyright (C)2005-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 hl; + +class Gc { + + + public static function stats() { + var tot = 0., count = 0., mem = 0.; + _stats(tot, count, mem); + return { totalAllocated : tot, allocationCount : count, currentMemory : mem }; + } + + /** + Dump whole memory into target filename for analysis. + **/ + public static function dumpMemory( ?fileName : String = "hlmemory.dump" ) { + _dump(@:privateAccess fileName.toUtf8()); + } + + @:hlNative("std", "gc_dump_memory") static function _dump( b : hl.Bytes ) : Void {} + + @:hlNative("std", "gc_profile") public static function activeProfileInfos( b : Bool ) : Void {} + @:hlNative("std", "gc_enable") public static function enable( b : Bool ) : Void {} + @:hlNative("std", "gc_major") public static function major() : Void {} + @:hlNative("std", "gc_stats") static function _stats( totalAllocated : hl.Ref, allocationCount : hl.Ref, currentMemory : hl.Ref ) : Void {} + +} diff --git a/std/hl/NativeArray.hx b/std/hl/NativeArray.hx new file mode 100644 index 00000000..d1756caa --- /dev/null +++ b/std/hl/NativeArray.hx @@ -0,0 +1,78 @@ +/* + * Copyright (C)2005-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 hl; + +@:generic class NativeArrayIterator { + var arr : NativeArray; + var pos : Int; + var length : Int; + + public inline function new(arr:NativeArray) { + this.arr = arr; + pos = 0; + length = arr.length; + } + + public inline function hasNext() { + return pos < length; + } + + public inline function next() { + return arr[pos++]; + } +} + +@:coreType abstract NativeArray { + + public var length(get,never):Int; + + @:extern public inline function new( length : Int ) { + this = untyped $aalloc(length); + } + + @:extern inline function get_length() : Int { + return untyped $asize(this); + } + + @:extern @:arrayAccess inline function get( pos : Int ) : T { + return untyped ($aget(this,pos):T); + } + + @:extern @:arrayAccess inline function set( pos : Int, value : T ) : T { + untyped $aset(this,pos,value); + return value; + } + + @:extern public inline function sub( pos : Int, len : Int ) { + var n = new NativeArray(len); + n.blit(0, this, pos, len); + return n; + } + + @:hlNative("std","array_type") public function getType() : Type { + return null; + } + + @:hlNative("std","array_blit") public function blit( pos : Int, src : NativeArray, srcPos : Int, srcLen : Int ) : Void { + } + +} \ No newline at end of file diff --git a/std/hl/Ref.hx b/std/hl/Ref.hx new file mode 100644 index 00000000..b75e7f56 --- /dev/null +++ b/std/hl/Ref.hx @@ -0,0 +1,39 @@ +/* + * Copyright (C)2005-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 hl; + +@:coreType abstract Ref { + + @:extern @:from public static inline function make( v : T ) { + return new Ref(v); + } + + @:extern public inline function new( v : T ) { + this = untyped $ref(v); + } + @:extern public inline function get() : T { + return untyped $unref(this); + } + @:extern public inline function set( v : T ) : Void { + return untyped $setref(this,v); + } +} \ No newline at end of file diff --git a/std/hl/Type.hx b/std/hl/Type.hx new file mode 100644 index 00000000..c34a7796 --- /dev/null +++ b/std/hl/Type.hx @@ -0,0 +1,112 @@ +/* + * Copyright (C)2005-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 hl; + +@:enum +abstract TypeKind(Int) { + public var HVoid = 0; + public var HUI8 = 1; + public var HUI16 = 2; + public var HI32 = 3; + public var HF32 = 4; + public var HF64 = 5; + public var HBool = 6; + public var HBytes = 7; + public var HDyn = 8; + public var HFun = 9; + public var HObj = 10; + public var HArray = 11; + public var HType = 12; + public var HRef = 13; + public var HVirtual = 14; + public var HDynObj = 15; + public var HAbstract = 16; + public var HEnum = 17; + public var HNull = 18; +} + +@:coreType abstract Type { + + public var kind(get,never) : TypeKind; + + @:extern inline function get_kind() : TypeKind { + return untyped $tkind(this); + } + + @:hlNative("std","type_name") function getNameBytes() : Bytes { + return null; + } + + @:extern public static inline function getDynamic( v : Dynamic ) : Type { + return untyped $tdyntype(v); + } + + @:extern public static inline function get( v : T ) : Type { + return untyped $ttype(v); + } + + @:extern public inline function getName() : String { + var s = getNameBytes(); + return @:privateAccess String.fromUCS2(s); + } + + @:hlNative("std", "type_safe_cast") public function safeCast( t : Type ) : Bool { + return false; + } + + @:hlNative("std","type_instance_fields") public function getInstanceFields() : NativeArray { + return null; + } + + @:hlNative("std","type_get_global") public function getGlobal() : Dynamic { + return null; + } + + @:hlNative("std","type_set_global") public function setGlobal( v : Dynamic ) : Bool { + return false; + } + + @:hlNative("std","type_args_count") public function getArgsCount() : Int { + return 0; + } + + @:hlNative("std","type_super") public function getSuper() : Type { + return null; + } + + @:hlNative("std","type_enum_fields") public function getEnumFields() : NativeArray { + return null; + } + + @:hlNative("std","type_enum_values") public function getEnumValues() : NativeArray { + return null; + } + + @:hlNative("std","alloc_obj") public function allocObject() : Dynamic { + return null; + } + + @:hlNative("std", "alloc_enum") public function allocEnum( index : Int, args : NativeArray, nargs : Int ) : Dynamic { + return null; + } + +} \ No newline at end of file diff --git a/std/hl/UI.hx b/std/hl/UI.hx new file mode 100644 index 00000000..109aac5a --- /dev/null +++ b/std/hl/UI.hx @@ -0,0 +1,160 @@ +/* + * Copyright (C)2005-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 hl; + +typedef SentinelHandle = hl.Abstract<"ui_sentinel">; + +abstract Sentinel(SentinelHandle) { + + public function new( timeout, callback ) { + this = create_sentinel(timeout,callback); + } + + public function tick() { + _tick(this); + } + + @:hlNative("ui", "ui_start_sentinel") static function create_sentinel( timeout : Float, callb : Void -> Void ) : SentinelHandle { + return null; + } + + @:hlNative("ui","ui_sentinel_tick") static function _tick( h : SentinelHandle ) : Void {} + +} + +typedef WinHandle = hl.Abstract<"ui_window">; + +class Window { + + var h : WinHandle; + + public function setText( text : String ) { + win_set_text(h, @:privateAccess text.bytes); + } + + public function setEnable( b : Bool ) { + win_set_enable(h, b); + } + + public function destroy() { + win_destroy(h); + } + + + @:hlNative("ui","ui_win_destroy") + static function win_destroy( win : WinHandle ) : Void { + } + + @:hlNative("ui","ui_win_set_text") + static function win_set_text( win : WinHandle, text : hl.Bytes ) : Void { + } + + @:hlNative("ui","ui_win_set_enable") + static function win_set_enable( win : WinHandle, enable : Bool ) : Void { + } + + +} + +class Button extends Window { + + public function new( parent : Window, text : String ) { + h = button_new(parent.h, @:privateAccess text.bytes, function() this.onClick()); + } + + public dynamic function onClick() { + } + + @:hlNative("ui", "ui_button_new") + static function button_new( parent : WinHandle, text : hl.Bytes, onClick : Void -> Void ) : WinHandle { + return null; + } + +} + +class WinLog extends Window { + + public function new( title : String, width, height ) { + h = winlog_new(@:privateAccess title.bytes,width, height); + } + + public function setTextContent( text : String, autoScroll = false ) { + winlog_set_text(h, @:privateAccess text.bytes,autoScroll); + } + + + @:hlNative("ui","ui_winlog_new") + static function winlog_new( text : hl.Bytes, width : Int, height : Int ) : WinHandle { + return null; + } + + @:hlNative("ui","ui_winlog_set_text") + static function winlog_set_text( win : WinHandle, text : hl.Bytes, autoScroll : Bool ) : Void { + } + +} + +enum DialogFlags { + YesNo; + IsError; +} + +@:enum abstract LoopResult(Int) { + var NoMessage = 0; + var HandledMessage = 1; + var Quit = 2; +} + +/** + These are the bindings for the HL `ui.hdll` library, which contains some low level system access. +**/ +class UI { + + @:hlNative("ui","ui_init") static function init() {} + + static function __init__() { + init(); + } + + @:hlNative("ui","ui_dialog") + static function _dialog( title : hl.Bytes, text : hl.Bytes, flags : Int ) : Int { + return 0; + } + + public static function dialog( title : String, text : String, flags : haxe.EnumFlags ) { + @:privateAccess _dialog(title.bytes,text.bytes,flags.toInt()); + } + + @:hlNative("ui","ui_loop") + public static function loop( blocking : Bool ) : LoopResult { + return Quit; + } + + @:hlNative("ui","ui_stop_loop") + public static function stopLoop() : Void { + } + + @:hlNative("ui","ui_close_console") + public static function closeConsole() : Void { + } + +} \ No newline at end of file diff --git a/std/hl/UI16.hx b/std/hl/UI16.hx new file mode 100644 index 00000000..0b77920e --- /dev/null +++ b/std/hl/UI16.hx @@ -0,0 +1,24 @@ +/* + * Copyright (C)2005-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 hl; + +@:coreType @:notNull @:runtimeValue abstract UI16 to Int from Int {} diff --git a/std/hl/UI8.hx b/std/hl/UI8.hx new file mode 100644 index 00000000..e3acda17 --- /dev/null +++ b/std/hl/UI8.hx @@ -0,0 +1,24 @@ +/* + * Copyright (C)2005-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 hl; + +@:coreType @:notNull @:runtimeValue abstract UI8 to Int from Int {} diff --git a/std/hl/_std/Date.hx b/std/hl/_std/Date.hx new file mode 100644 index 00000000..acb92345 --- /dev/null +++ b/std/hl/_std/Date.hx @@ -0,0 +1,144 @@ +/* + * Copyright (C)2005-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. + */ +import hl.Ref; + +@:coreApi @:final class Date { + + private var t : Int; + + public function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void { + t = date_new(year, month, day, hour, min, sec); + } + + public function getTime() : Float { + return date_get_time(t); + } + + public function getFullYear() : Int { + var v = 0; + date_get_inf(t, v, null, null, null, null, null, null); + return v; + } + + public function getMonth() : Int { + var v = 0; + date_get_inf(t, null, v, null, null, null, null, null); + return v; + } + + public function getDate() : Int { + var v = 0; + date_get_inf(t, null, null, v, null, null, null, null); + return v; + } + + public function getHours() : Int { + var v = 0; + date_get_inf(t, null, null, null, v, null, null, null); + return v; + } + + public function getMinutes() : Int { + var v = 0; + date_get_inf(t, null, null, null, null, v, null, null); + return v; + } + + public function getSeconds() : Int { + var v = 0; + date_get_inf(t, null, null, null, null, null, v, null); + return v; + } + + public function getDay() : Int { + var v = 0; + date_get_inf(t, null, null, null, null, null, null, v); + return v; + } + + @:keep public function toString():String { + var outLen = 0; + var bytes = date_to_string(t, outLen); + return @:privateAccess String.__alloc__(bytes,outLen); + } + + public static function now() : Date { + var d : Date = untyped $new(Date); + d.t = date_now(); + return d; + } + + static function fromInt( t : Int ) : Date { + var d : Date = untyped $new(Date); + d.t = t; + return d; + } + + public static function fromTime( t : Float ) : Date { + var d : Date = untyped $new(Date); + d.t = date_from_time(t); + return d; + } + + public static function fromString( s : String ) : Date { + var d : Date = untyped $new(Date); + d.t = date_from_string(@:privateAccess s.bytes, s.length<<1); + return d; + } + + @:hlNative + static function date_new( year : Int, month : Int, day : Int, hours : Int, minutes : Int, seconds : Int ) : Int { + return 0; + } + + @:hlNative + static function date_now() : Int { + return 0; + } + + @:hlNative + static function date_from_time( t : Float ) : Int { + return 0; + } + + @:hlNative + static function date_from_string( b : hl.Bytes, len : Int ) : Int { + return 0; + } + + @:hlNative + static function date_get_time( t : Int ) : Float { + return 0.; + } + + @:hlNative + static function date_get_inf( t : Int, year : Ref, month : Ref, day : Ref, hours : Ref, minutes : Ref, seconds : Ref, wday : Ref ) : Void { + } + + @:hlNative + static function date_to_string( t : Int, outLen : Ref ) : hl.Bytes { + return null; + } + +} + + diff --git a/std/hl/_std/EReg.hx b/std/hl/_std/EReg.hx new file mode 100644 index 00000000..f04a23e7 --- /dev/null +++ b/std/hl/_std/EReg.hx @@ -0,0 +1,200 @@ +/* + * Copyright (C)2005-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. + */ + +private typedef ERegValue = hl.Abstract<"ereg">; + +@:access(String) +@:coreApi @:final class EReg { + + var r : ERegValue; + var last : String; + var global : Bool; + + public function new( r : String, opt : String ) : Void { + var a = opt.split("g"); + global = a.length > 1; + if( global ) + opt = a.join(""); + this.r = regexp_new_options(r.bytes, opt.bytes); + } + + public function match( s : String ) : Bool { + var p = regexp_match(r,s.bytes,0,s.length); + if( p ) + last = s; + else + last = null; + return p; + } + + public function matched( n : Int ) : String { + var len = 0; + var m = regexp_matched_pos(r,n,len); + return m < 0 ? null : last.substr(m, len); + } + + public function matchedLeft() : String { + var p = regexp_matched_pos(r,0,null); + return last.substr(0,p); + } + + public function matchedRight() : String { + var len = 0; + var p = regexp_matched_pos(r,0,len); + return last.substr(p + len); + } + + public function matchedPos() : { pos : Int, len : Int } { + var len = 0; + var p = regexp_matched_pos(r, 0, len); + if( p < 0 ) return null; + return { pos : p, len : len }; + } + + public function matchSub( s : String, pos : Int, len : Int = -1):Bool { + var p = regexp_match(r, s.bytes, pos, len < 0 ? s.length - pos : len); + if( p ) + last = s; + else + last = null; + return p; + } + + public function split( s : String ) : Array { + var pos = 0; + var len = s.length; + var a = new Array(); + var first = true; + do { + if( !regexp_match(r,s.bytes,pos,len) ) + break; + var plen = 0; + var p = regexp_matched_pos(r,0,plen); + if( plen == 0 && !first ) { + if( p == s.length ) + break; + p++; + } + a.push(s.substr(pos,p - pos)); + var tot = p + plen - pos; + pos += tot; + len -= tot; + first = false; + } while( global ); + a.push(s.substr(pos,len)); + return a; + } + + public function replace( s : String, by : String ) : String { + var b = new StringBuf(); + var pos = 0; + var len = s.length; + var a = by.split("$"); + var first = true; + do { + if( !regexp_match(r,s.bytes,pos,len) ) + break; + var plen = 0; + var p = regexp_matched_pos(r,0, plen); + if( plen == 0 && !first ) { + if( p == s.length ) + break; + p++; + } + b.addSub(s,pos,p-pos); + if( a.length > 0 ) + b.add(a[0]); + var i = 1; + while( i < a.length ) { + var k = a[i]; + var c = StringTools.fastCodeAt(k, 0); + // 1...9 + if( c >= 49 && c <= 57 ) { + var plen = 0; + var p = try regexp_matched_pos(r,Std.int(c)-48,plen) catch( e : String ) -1; + if( p < 0 ){ + b.add("$"); + b.add(k); + } else { + if( p >= 0 ) b.addSub(s,p,plen); + b.addSub(k,1,k.length - 1); + } + } else if( c == 0 ) { + b.add("$"); + i++; + var k2 = a[i]; + if( k2 != null && k2.length > 0 ) + b.add(k2); + } else + b.add("$"+k); + i++; + } + var tot = p + plen - pos; + pos += tot; + len -= tot; + first = false; + } while( global ); + b.addSub(s,pos,len); + return b.toString(); + } + + public function map( s : String, f : EReg -> String ) : String { + var offset = 0; + var buf = new StringBuf(); + do { + if (offset >= s.length) + break; + else if (!matchSub(s, offset)) { + buf.add(s.substr(offset)); + break; + } + var plen = 0; + var p = regexp_matched_pos(r,0,plen); + buf.add(s.substr(offset, p - offset)); + buf.add(f(this)); + if (plen == 0) { + buf.add(s.substr(p, 1)); + offset = p + 1; + } + else + offset = p + plen; + } while (global); + if (!global && offset > 0 && offset < s.length) + buf.add(s.substr(offset)); + return buf.toString(); + } + + + @:hlNative("std", "regexp_new_options") static function regexp_new_options( bytes : hl.Bytes, options : hl.Bytes ) : ERegValue { + return null; + } + + @:hlNative("std", "regexp_match") static function regexp_match( r : ERegValue, str : hl.Bytes, pos : Int, size : Int ) : Bool { + return false; + } + + @:hlNative("std", "regexp_matched_pos") static function regexp_matched_pos( r : ERegValue, n : Int, size : hl.Ref ) : Int { + return 0; + } + + +} diff --git a/std/hl/_std/Math.hx b/std/hl/_std/Math.hx new file mode 100644 index 00000000..031a8672 --- /dev/null +++ b/std/hl/_std/Math.hx @@ -0,0 +1,65 @@ +/* + * Copyright (C)2005-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. + */ +@:coreApi +class Math { + + @:hlNative("std","math_sqrt") public static function sqrt( v : Float ) : Float return 0.; + @:hlNative("std","math_abs") public static function abs( v : Float ) : Float return 0.; + @:hlNative("std","math_floor") public static function floor( v : Float ) : Int return 0; + @:hlNative("std","math_round") public static function round( v : Float ) : Int return 0; + @:hlNative("std","math_ceil") public static function ceil( v : Float ) : Int return 0; + @:hlNative("std","math_isfinite") public static function isFinite( f : Float ) : Bool return true; + @:hlNative("std","math_isnan") public static function isNaN( f : Float ) : Bool return false; + + @:hlNative("std","math_ffloor") public static function ffloor( v : Float ) : Float return 0.; + @:hlNative("std","math_fround") public static function fround( v : Float ) : Float return 0.; + @:hlNative("std","math_fceil") public static function fceil( v : Float ) : Float return 0.; + + @:hlNative("std","math_cos") public static function cos( v : Float ) : Float return 0.; + @:hlNative("std","math_sin") public static function sin( v : Float ) : Float return 0.; + @:hlNative("std","math_exp") public static function exp( v : Float ) : Float return 0.; + @:hlNative("std","math_log") public static function log( v : Float ) : Float return 0.; + @:hlNative("std","math_tan") public static function tan( v : Float ) : Float return 0.; + @:hlNative("std","math_atan") public static function atan( v : Float ) : Float return 0.; + @:hlNative("std","math_acos") public static function acos( v : Float ) : Float return 0.; + @:hlNative("std","math_asin") public static function asin( v : Float ) : Float return 0.; + @:hlNative("std","math_pow") public static function pow( v : Float, exp : Float ) : Float return 0.; + @:hlNative("std","math_atan2") public static function atan2( y : Float, x : Float ) : Float return 0.; + + public static function random() : Float return @:privateAccess Std.rnd_float(Std.rnd); + + public static function min( a : Float, b : Float ) : Float return a < b || isNaN(a) ? a : b; + public static function max( a : Float, b : Float ) : Float return a < b || isNaN(b) ? b : a; + + public static var PI(default,null) : Float; + public static var NaN(default,null) : Float; + public static var POSITIVE_INFINITY(default,null) : Float; + public static var NEGATIVE_INFINITY(default,null) : Float; + + static function __init__() : Void { + PI = 3.1415926535897932384626433832795; + NaN = 0. / 0.; + POSITIVE_INFINITY = 1. / 0.; + NEGATIVE_INFINITY = -1. / 0.; + } + +} \ No newline at end of file diff --git a/std/hl/_std/Reflect.hx b/std/hl/_std/Reflect.hx new file mode 100644 index 00000000..14e19942 --- /dev/null +++ b/std/hl/_std/Reflect.hx @@ -0,0 +1,143 @@ +/* + * Copyright (C)2005-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. + */ + +@:coreApi +class Reflect { + + public static function hasField( o : Dynamic, field : String ) : Bool { + if( field == null ) return false; + var hash = @:privateAccess field.bytes.hash(); + return hl.Api.hasField(o,hash); + } + + public static function field( o : Dynamic, field : String ) : Dynamic { + if( field == null ) return null; + var hash = @:privateAccess field.bytes.hash(); + return hl.Api.getField(o,hash); + } + + public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void { + var hash = @:privateAccess field.bytes.hash(); + hl.Api.setField(o,hash,value); + } + + public static function getProperty( o : Dynamic, field : String ) : Dynamic { + var f : Dynamic = Reflect.field(o, "get_" + field); + if( f != null ) + return f(); + return Reflect.field(o,field); + } + + public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void { + var f : Dynamic = Reflect.field(o, "set_" + field); + if( f != null ) + f(value); + else + setField(o, field, value); + } + + public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array ) : Dynamic { + var args : hl.types.ArrayDyn = cast args; + var count = args.length; + + var ft = hl.Type.getDynamic(func); + if( ft.kind != HFun ) + throw "Invalid function " + func; + var need = ft.getArgsCount(); + var cval = hl.Api.getClosureValue(func); + var isClosure = cval != null && need >= 0; + if( o == null ) + o = cval; + else if( !isClosure && count == need ) + o = null; + var nargs = o == null ? count : count + 1; + if( isClosure ) need++; + if( nargs < need ) nargs = need; + var a = new hl.NativeArray(nargs); + if( o == null || need < 0 ) { + for( i in 0...count ) + a[i] = args.getDyn(i); + } else { + func = hl.Api.noClosure(func); + a[0] = o; + for( i in 0...count ) + a[i+1] = args.getDyn(i); + } + return hl.Api.callMethod(func,a); + } + + @:hlNative("std","obj_fields") static function getObjectFields( v : Dynamic ) : hl.NativeArray { + return null; + } + + public static function fields( o : Dynamic ) : Array { + var fields = getObjectFields(o); + if( fields == null ) return []; + return [for( f in fields ) @:privateAccess String.fromUCS2(f)]; + } + + public static inline function isFunction( f : Dynamic ) : Bool { + return hl.Type.getDynamic(f).kind == HFun; + } + + @:hlNative("std","dyn_compare") + public static function compare( a : T, b : T ) : Int { + return 0; + } + + @:hlNative("std","fun_compare") + public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool { + return false; + } + + public static function isObject( v : Dynamic ) : Bool { + var t = hl.Type.getDynamic(v); + return switch( t.kind ) { case HObj, HDynObj, HVirtual: true; default: false; } + } + + public static function isEnumValue( v : Dynamic ) : Bool { + var t = hl.Type.getDynamic(v); + return t.kind == HEnum; + } + + public static function deleteField( o : Dynamic, field : String ) : Bool { + return hl.Api.deleteField(o,@:privateAccess field.bytes.hash()); + } + + @:hlNative("std","obj_copy") + public static function copy( o : T ) : T { + return null; + } + + @:overload(function( f : Array -> Void ) : Dynamic {}) + @:extern public inline static function makeVarArgs( f : Array -> Dynamic ) : Dynamic { + return _makeVarArgs(f); + } + + static function _makeVarArgs( f : Array -> Dynamic ) : Dynamic { + return hl.Api.makeVarArgs(function(args:hl.NativeArray) { + var arr = hl.types.ArrayDyn.alloc(hl.types.ArrayObj.alloc(args), true); + return f(cast arr); + }); + } + +} diff --git a/std/hl/_std/Std.hx b/std/hl/_std/Std.hx new file mode 100644 index 00000000..e4d417d0 --- /dev/null +++ b/std/hl/_std/Std.hx @@ -0,0 +1,120 @@ +/* + * Copyright (C)2005-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. + */ +import hl.Boot; + +private typedef Rand = hl.Abstract<"hl_random">; + +@:coreApi +class Std { + + static var rnd : Rand; + + static function __init__() : Void { + rnd = rnd_sys(); + } + + @:hlNative("std","rnd_init_system") static function rnd_sys() : Rand { return null; } + @:hlNative("std","rnd_int") static function rnd_int( r : Rand ) : Int { return 0; } + @:hlNative("std","rnd_float") static function rnd_float( r : Rand ) : Float { return 0.; } + + public static function random( x : Int ) : Int { + return x <= 0 ? 0 : (rnd_int(rnd) & 0x3FFFFFFF) % x; + } + + public static function is( v : Dynamic, t : Dynamic ) : Bool { + var t : hl.BaseType = t; + if( t == null ) return false; + switch( t.__type__.kind ) { + case HDyn: + return true; + case HF64: + switch( hl.Type.getDynamic(v).kind ) { + case HUI8, HUI16, HI32: + return true; + default: + } + case HI32: + switch( hl.Type.getDynamic(v).kind ) { + case HF32, HF64: + var v : Float = v; + return Std.int(v) == v; + default: + } + default: + } + return t.check(v); + } + + @:extern public inline static function instance( value : T, c : Class ) : S { + var t : hl.BaseType = cast c; + return t.check(value) ? cast value : null; + } + + @:extern public static inline function int( x : Float ) : Int { + return untyped $int(x); + } + + @:keep public static function string( s : Dynamic ) : String { + var len = 0; + var bytes = hl.Bytes.fromValue(s,new hl.Ref(len)); + return @:privateAccess String.__alloc__(bytes,len); + } + + public static function parseInt( x : String ) : Null { + if( x == null ) return null; + return @:privateAccess x.bytes.parseInt(0, x.length<<1); + } + + public static function parseFloat( x : String ) : Float { + if( x == null ) return Math.NaN; + return @:privateAccess x.bytes.parseFloat(0, x.length<<1); + } + + @:keep static function __add__( a : Dynamic, b : Dynamic ) : Dynamic { + var ta = hl.Type.getDynamic(a); + var tb = hl.Type.getDynamic(b); + if( ta == hl.Type.get("") ) + return (a : String) + b; + if( tb == hl.Type.get("") ) + return a + (b : String); + switch(ta.kind) { + case HUI8, HUI16, HI32: + var a : Int = a; + switch( tb.kind ) { + case HUI8, HUI16, HI32: return a + (b:Int); + case HF32, HF64: return a + (b:Float); + default: + } + case HF32, HF64: + var a : Float = a; + switch( tb.kind ) { + case HUI8, HUI16, HI32: return a + (b:Int); + case HF32, HF64: return a + (b:Float); + default: + } + default: + } + throw "Can't add "+a+"("+ta+") and "+b+"("+tb+")"; + return null; + } + +} diff --git a/std/hl/_std/String.hx b/std/hl/_std/String.hx new file mode 100644 index 00000000..880722de --- /dev/null +++ b/std/hl/_std/String.hx @@ -0,0 +1,225 @@ +/* + * Copyright (C)2005-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. + */ +@:coreApi +class String { + + var bytes : hl.Bytes; + public var length(default,null) : Int; + + public function new(string:String) : Void { + bytes = string.bytes; + length = string.length; + } + + public function toUpperCase() : String { + return __alloc__(@:privateAccess bytes.ucs2Upper(0,length), length); + } + + public function toLowerCase() : String { + return __alloc__(@:privateAccess bytes.ucs2Lower(0,length), length); + } + + public function charAt(index : Int) : String { + if( (index:UInt) >= (length:UInt) ) return ""; + var b = new hl.Bytes(4); + b.setUI16(0, bytes.getUI16(index<<1)); + b.setUI16(2,0); + return __alloc__(b,1); + } + + public function charCodeAt( index : Int) : Null { + var idx : UInt = index; + if( idx >= (length:UInt) ) + return null; + return bytes.getUI16(index << 1); + } + + public function indexOf( str : String, ?startIndex : Int ) : Int { + var startByte = 0; + if( startIndex != null && startIndex > 0 ) { + if( startIndex >= length ) + return -1; + startByte = startIndex << 1; + } + var p = bytes.find(startByte, (length << 1) - startByte, str.bytes, 0, str.length << 1); + if( p > 0 ) p >>= 1; + return p; + } + + public function lastIndexOf( str : String, ?startIndex : Int ) : Int { + var last = 0; + var start = this.length; + if( startIndex != null ) + start = startIndex; + start <<= 1; + while( true ) { + var p = bytes.find(last, (length << 1) - last, str.bytes, 0, str.length << 1); + if( p < 0 || p > start ) + return (last >> 1) - 1; + last = p + 2; + } + return -1; + } + + public function split( delimiter : String ) : Array { + var out = []; + if( length == 0 ) { + out.push(""); + return out; + } + if( delimiter.length == 0 ) { + for( i in 0...length ) + out.push(substr(i,1)); + return out; + } + var pos = 0; + var dlen = delimiter.length; + while( true ) { + var p = bytes.find(pos << 1, (length - pos) << 1, delimiter.bytes, 0, dlen << 1); + if( p < 0 ) { + out.push(substr(pos, length-pos)); + break; + } + p >>= 1; + out.push(substr(pos, p - pos)); + pos = p + dlen; + } + return out; + } + + public function substr( pos : Int, ?len : Int ) : String @:privateAccess { + var sl = length; + var len : Int = if( len == null ) sl else len; + if( len == 0 ) return ""; + if( pos != 0 && len < 0 ) + return ""; + if( pos < 0 ) { + pos = sl + pos; + if( pos < 0 ) pos = 0; + } else if( len < 0 ) { + len = sl + len - pos; + if( len < 0 ) return ""; + } + if( ((pos + len) : UInt) > (sl:UInt) ) + len = sl - pos; + if( pos < 0 || len <= 0 ) return ""; + + var b = new hl.Bytes((len + 1) << 1); + b.blit(0, bytes, pos<<1, len << 1); + b.setUI16(len<<1,0); + return __alloc__(b, len); + } + + public function substring( startIndex : Int, ?endIndex : Int ) : String { + var end : Int; + if( endIndex == null ) + end = length; + else { + end = endIndex; + if( end < 0 ) + end = 0; + else if ( end > length ) + end = length; + } + if( startIndex < 0 ) + startIndex = 0; + else if ( startIndex > length ) + startIndex = length; + if( startIndex > end ) { + var tmp = startIndex; + startIndex = end; + end = tmp; + } + return substr( startIndex, end - startIndex ); + } + + public function toString() : String { + return this; + } + + public static function fromCharCode( code : Int ) : String { + if( code >= 0 && code < 0x10000 ) { + if( code >= 0xD800 && code <= 0xDFFF ) throw "Invalid unicode char " + code; + var b = new hl.Bytes(4); + b.setUI16(0, code); + b.setUI16(2, 0); + return __alloc__(b, 1); + } else if( code < 0x110000 ) { + var b = new hl.Bytes(6); + code -= 0x10000; + b.setUI16(0, (code >> 10) + 0xD800); + b.setUI16(2, (code & 1023) + 0xDC00); + b.setUI16(4, 0); + return __alloc__(b, 2); // UTF16 encoding but UCS2 API (same as JS) + } else + throw "Invalid unicode char " + code; + } + + function toUtf8() : hl.Bytes { + return bytes.utf16ToUtf8(0, null); + } + + @:keep function __string() : hl.Bytes { + return bytes; + } + + @:keep function __compare( s : String ) : Int { + var v = bytes.compare(0, s.bytes, 0, (length < s.length ? length : s.length) << 1); + return v == 0 ? length - s.length : v; + } + + @:keep static inline function __alloc__( b : hl.Bytes, length : Int ) : String { + var s : String = untyped $new(String); + s.bytes = b; + s.length = length; + return s; + } + + @:keep static function call_toString( v : Dynamic ) : hl.Bytes { + var s : String = v.toString(); + return s.bytes; + } + + inline static function fromUCS2( b : hl.Bytes ) : String { + var s : String = untyped $new(String); + s.bytes = b; + s.length = @:privateAccess b.ucs2Length(0); + return s; + } + + @:keep static function fromUTF8( b : hl.Bytes ) : String { + var outLen = 0; + var b2 = @:privateAccess b.utf8ToUtf16(0, outLen); + return __alloc__(b2, outLen>>1); + } + + @:keep static function __add__( a : String, b : String ) : String { + if( a == null ) a = "null"; + if( b == null ) b = "null"; + var asize = a.length << 1, bsize = b.length << 1, tot = asize + bsize; + var bytes = new hl.Bytes(tot+2); + bytes.blit(0, a.bytes, 0, asize); + bytes.blit(asize,b.bytes,0,bsize); + bytes.setUI16(tot, 0); + return __alloc__(bytes, tot>>1); + } +} diff --git a/std/hl/_std/StringBuf.hx b/std/hl/_std/StringBuf.hx new file mode 100644 index 00000000..52a5cb71 --- /dev/null +++ b/std/hl/_std/StringBuf.hx @@ -0,0 +1,94 @@ +/* + * Copyright (C)2005-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. + */ +@:coreApi class StringBuf { + + var b : hl.Bytes; + var size : Int; + var pos : Int; + public var length(get,never) : Int; + + public function new() : Void { + pos = 0; + size = 8; // ensure 4 bytes expand for addChar() + b = new hl.Bytes(size); + } + + inline function get_length() : Int { + return pos >> 1; + } + + inline function __expand( need : Int ) : Void { + var nsize = (size * 3) >> 1; + if( need > nsize ) nsize = need; + var b2 = new hl.Bytes(nsize); + b2.blit(0, b, 0, pos); + b = b2; + size = nsize; + } + + inline function __add( bytes : hl.Bytes, spos : Int, ssize : Int ) : Void { + if( pos + ssize > size ) __expand(pos + ssize); + b.blit(pos, bytes, spos, ssize); + pos += ssize; + } + + public function add( x : T ) : Void { + var slen = 0; + var sbytes = hl.Bytes.fromValue(x, new hl.Ref(slen)); + __add(sbytes, 0, slen<<1); + } + + public function addSub( s : String, pos : Int, ?len : Int ) : Void @:privateAccess { + if( pos < 0 ) pos = 0; + if( pos >= s.length ) return; + var slen : Int; + if( len == null ) slen = s.length - pos else { + slen = len; + if( pos + slen > s.length ) slen = s.length - pos; + if( slen <= 0 ) return; + } + __add(s.bytes, pos << 1, slen << 1); + } + + public function addChar( c : Int ) : Void { + if( c >= 0 && c < 0x10000 ) { + if( c >= 0xD800 && c <= 0xDFFF ) throw "Invalid unicode char " + c; + if( pos + 2 > size ) __expand(0); + b.setUI16(pos, c); + pos += 2; + } else if( c < 0x110000 ) { + if( pos + 4 > size ) __expand(0); + c -= 0x10000; + b.setUI16(pos, (c >> 10) + 0xD800); + b.setUI16(pos + 2, (c & 1023) + 0xDC00); + pos += 4; + } else + throw "Invalid unicode char " + c; + } + + public function toString() : String { + if( pos+2 > size ) __expand(0); + b.setUI16(pos,0); + return @:privateAccess String.__alloc__(b, pos>>1); + } + +} diff --git a/std/hl/_std/Sys.hx b/std/hl/_std/Sys.hx new file mode 100644 index 00000000..b98f1779 --- /dev/null +++ b/std/hl/_std/Sys.hx @@ -0,0 +1,173 @@ +/* + * Copyright (C)2005-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. + */ +class SysError { + public var msg : String; + public function new(msg) { + this.msg = msg; + } + @:keep public function toString() { + return "SysError("+msg+")"; + } +} + +@:coreApi +@:keepInit +@:access(String) +class Sys { + + static var utf8Path : Bool; + static function __init__() : Void { + utf8Path = sys_utf8_path(); + } + static function getPath( s : String ) : hl.Bytes { + return utf8Path ? s.bytes.utf16ToUtf8(0, null) : s.bytes; + } + static function makePath( b : hl.Bytes ) : String { + if( b == null ) return null; + return utf8Path ? String.fromUTF8(b) : String.fromUCS2(b); + } + + public static function print( v : Dynamic ) : Void { + sys_print(Std.string(v).bytes); + } + + public static function println( v : Dynamic ) : Void { + sys_print(Std.string(v).bytes); + sys_print("\n".bytes); + } + + public static function args() : Array { + return [for( a in sys_args() ) makePath(a)]; + } + + public static function stdin() : haxe.io.Input { + return @:privateAccess new sys.io.FileInput(file_stdin()); + } + + public static function stdout() : haxe.io.Output { + return @:privateAccess new sys.io.FileOutput(file_stdout()); + } + + public static function stderr() : haxe.io.Output { + return @:privateAccess new sys.io.FileOutput(file_stderr()); + } + + public static function getEnv( s : String ) : String { + var v = get_env(getPath(s)); + if( v == null ) + return null; + return makePath(v); + } + + public static function putEnv( s : String, v : String ) : Void { + if( !put_env(getPath(s), if( v == null ) null else getPath(v)) ) throw "putEnv() failure"; + } + + public static function environment() : Map { + var env = sys_env(); + var h = new haxe.ds.StringMap(); + for( i in 0...env.length >> 1 ) { + var p = i << 1; + h.set(makePath(env[p]), makePath(env[p + 1])); + } + return h; + } + + @:hlNative("std","sys_sleep") + public static function sleep( seconds : Float ) : Void { + } + + public static function setTimeLocale( loc : String ) : Bool { + return set_time_locale(loc.bytes.utf16ToUtf8(0,null)); + } + + public static function getCwd() : String { + return makePath(get_cwd()); + } + + public static function setCwd( s : String ) : Void { + if( !set_cwd(getPath(s)) ) throw new SysError("Failed to set path to " + s); + } + + public static function systemName() : String { + return String.fromUCS2(sys_string()); + } + + public static function command( cmd : String, ?args : Array ) : Int { + var code = 0; + if (args == null) { + code = sys_command(getPath(cmd)); + } else { + switch (systemName()) { + case "Windows": + cmd = [ + for (a in [StringTools.replace(cmd, "/", "\\")].concat(args)) + StringTools.quoteWinArg(a, true) + ].join(" "); + code = sys_command(getPath(cmd)); + case _: + cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" "); + code = sys_command(getPath(cmd)); + } + } + return code; + } + + @:deprecated("Use programPath instead") public static function executablePath() : String { + return makePath(sys_exe_path()); + } + + public static function programPath() : String { + return sys_program_path; + } + private static var sys_program_path = { + var hlFile = sys_hl_file(); + if( hlFile == null ) + makePath( sys_exe_path() ); + else + sys.FileSystem.fullPath( makePath(hlFile) ); + } + + @:hlNative("std", "sys_utf8_path") static function sys_utf8_path() : Bool { return false; } + + @:hlNative("std","sys_time") public static function time() : Float { return 0.; }; + @:hlNative("std","sys_exit") public static function exit( code : Int ) : Void {}; + @:hlNative("std", "sys_cpu_time") public static function cpuTime() : Float { return 0.; }; + @:hlNative("std", "sys_get_char") public static function getChar( echo : Bool ) : Int { return 0; } + + @:hlNative("std","sys_print") static function sys_print( v : hl.Bytes ) : Void {}; + @:hlNative("std", "file_stdin") static function file_stdin() : sys.io.File.FileHandle { return null; } + @:hlNative("std", "file_stdout") static function file_stdout() : sys.io.File.FileHandle { return null; } + @:hlNative("std", "file_stderr") static function file_stderr() : sys.io.File.FileHandle { return null; } + @:hlNative("std", "sys_args") static function sys_args() : hl.NativeArray { return null; } + @:hlNative("std", "sys_get_env") static function get_env( key : hl.Bytes ) : hl.Bytes { return null; } + @:hlNative("std", "sys_put_env") static function put_env( key : hl.Bytes, val : hl.Bytes ) : Bool { return false; } + @:hlNative("std", "sys_env") static function sys_env() : hl.NativeArray { return null; } + @:hlNative("std", "sys_set_time_locale") static function set_time_locale( loc : hl.Bytes ) : Bool { return true; } + @:hlNative("std", "sys_get_cwd") static function get_cwd() : hl.Bytes { return null; } + @:hlNative("std", "sys_set_cwd") static function set_cwd( path : hl.Bytes ) : Bool { return true; } + @:hlNative("std", "sys_command") static function sys_command( cmd : hl.Bytes ) : Int { return 0; } + @:hlNative("std", "sys_exe_path") static function sys_exe_path() : hl.Bytes { return null; } + @:hlNative("std", "sys_hl_file") static function sys_hl_file() : hl.Bytes { return null; } + @:hlNative("std", "sys_string") static function sys_string() : hl.Bytes { return null; } + +} \ No newline at end of file diff --git a/std/hl/_std/Type.hx b/std/hl/_std/Type.hx new file mode 100644 index 00000000..a7ffe06f --- /dev/null +++ b/std/hl/_std/Type.hx @@ -0,0 +1,254 @@ +/* + * Copyright (C)2005-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. + */ + +enum ValueType { + TNull; + TInt; + TFloat; + TBool; + TObject; + TFunction; + TClass( c : Class ); + TEnum( e : Enum ); + TUnknown; +} + +@:coreApi +class Type { + + static var allTypes(get,never) : hl.types.BytesMap; + static inline function get_allTypes() : hl.types.BytesMap return untyped $allTypes(); + + @:keep static function init() : Void { + untyped $allTypes(new hl.types.BytesMap()); + } + + @:keep static function initClass( ct : hl.Type, t : hl.Type, name : hl.Bytes ) : hl.BaseType.Class @:privateAccess { + var c : hl.BaseType.Class = ct.allocObject(); + t.setGlobal(c); + c.__type__ = t; + c.__name__ = String.fromUCS2(name); + register(name, c); + return c; + } + + @:keep static function initEnum( et : hl.Type, t : hl.Type ) : hl.BaseType.Enum @:privateAccess { + var e : hl.BaseType.Enum = et.allocObject(); + e.__type__ = t; + e.__evalues__ = t.getEnumValues(); + e.__ename__ = t.getName(); + e.__emap__ = new hl.types.BytesMap(); + e.__constructs__ = new Array(); + var cl = t.getEnumFields(); + for( i in 0...cl.length ) { + var name = cl[i]; + e.__emap__.set(name, i); + e.__constructs__.push(String.fromUCS2(name)); + } + register(e.__ename__.bytes,e); + t.setGlobal(e); + return e; + } + + @:keep static function register( b : hl.Bytes, t : hl.BaseType ) : Void { + allTypes.set(b, t); + } + + public static function getClass( o : T ) : Class { + var t = hl.Type.getDynamic(o); + if( t.kind == HObj ) + return t.getGlobal(); + return null; + } + + public static function getEnum( o : EnumValue ) : Enum { + var t = hl.Type.getDynamic(o); + if( t.kind == HEnum ) + return t.getGlobal(); + return null; + } + + public static function getSuperClass( c : Class ) : Class @:privateAccess { + var c : hl.BaseType.Class = cast c; + var t = c.__type__.getSuper(); + return t == hl.Type.get((null : Void)) ? null : t.getGlobal(); + } + + public static function getClassName( c : Class ) : String { + var c : hl.BaseType.Class = cast c; + return c.__name__; + } + + public static function getEnumName( e : Enum ) : String { + var e : hl.BaseType.Enum = cast e; + return e.__ename__; + } + + public static function resolveClass( name : String ) : Class { + var t : hl.BaseType = allTypes.get(@:privateAccess name.bytes); + if( t == null || !Std.is(t, hl.BaseType.Class) ) + return null; + return cast t; + } + + public static function resolveEnum( name : String ) : Enum { + var t : hl.BaseType = allTypes.get(@:privateAccess name.bytes); + if( t == null || !Std.is(t, hl.BaseType.Enum) ) + return null; + return cast t; + } + + public static function createInstance( cl : Class, args : Array ) : T { + var c : hl.BaseType.Class = cast cl; + var t = c.__type__; + if( t == hl.Type.get((null : hl.types.ArrayBase.ArrayAccess)) ) + return cast new Array(); + var o = t.allocObject(); + if( c.__constructor__ != null ) Reflect.callMethod(o, c.__constructor__, args); + return o; + } + + public static function createEmptyInstance( cl : Class ) : T { + var c : hl.BaseType.Class = cast cl; + return c.__type__.allocObject(); + } + + public static function createEnum( e : Enum, constr : String, ?params : Array ) : T { + var en : hl.BaseType.Enum = cast e; + var idx : Null = en.__emap__.get(@:privateAccess constr.bytes); + if( idx == null ) throw "Unknown enum constructor " + en.__ename__ +"." + constr; + return createEnumIndex(e,idx,params); + } + + public static function createEnumIndex( e : Enum, index : Int, ?params : Array ) : T { + var e : hl.BaseType.Enum = cast e; + if( index < 0 || index >= e.__constructs__.length ) throw "Invalid enum index " + e.__ename__ +"." + index; + if( params == null || params.length == 0 ) { + var v = index >= e.__evalues__.length ? null : e.__evalues__[index]; + if( v == null ) throw "Constructor " + e.__ename__ +"." + e.__constructs__[index] + " takes parameters"; + return v; + } + var a : hl.types.ArrayDyn = cast params; + var narr; + if( @:privateAccess !a.array.isArrayObj() ) { + narr = new hl.NativeArray(a.length); + for( i in 0...a.length ) + narr[i] = @:privateAccess a.array.getDyn(i); + } else { + var aobj : hl.types.ArrayObj = cast @:privateAccess a.array; + narr = @:privateAccess aobj.array; + } + var v = @:privateAccess e.__type__.allocEnum(index, narr, a.length); + if( v == null ) throw "Constructor " + e.__ename__ +"." + e.__constructs__[index] + " does not takes " + narr.length + " parameters"; + return v; + } + + public static function getInstanceFields( c : Class ) : Array @:privateAccess { + var c : hl.BaseType.Class = cast c; + var fields = c.__type__.getInstanceFields(); + return [for( f in fields ) String.fromUCS2(f)]; + } + + public static function getClassFields( c : Class ) : Array { + var c : hl.BaseType.Class = cast c; + var fields = @:privateAccess Reflect.getObjectFields(c); + var fields = [for( f in fields ) @:privateAccess String.fromUCS2(f)]; + fields.remove("__constructor__"); + fields.remove("__meta__"); + fields.remove("__name__"); + fields.remove("__type__"); + fields.remove("__implementedBy__"); + return fields; + } + + public static function getEnumConstructs( e : Enum ) : Array { + var e : hl.BaseType.Enum = cast e; + return e.__constructs__.copy(); + } + + public static function typeof( v : Dynamic ) : ValueType { + var t = hl.Type.getDynamic(v); + switch( t.kind ) { + case HVoid: + return TNull; + case HUI8, HUI16, HI32: + return TInt; + case HF32, HF64: + return TFloat; + case HBool: + return TBool; + case HDynObj: + return TObject; + case HObj: + var c : Dynamic = Type.getClass(v); + if( c == Class || c == null ) + return TObject; + return TClass(c); + case HEnum: + return TEnum(Type.getEnum(v)); + case HFun: + return TFunction; + case HVirtual: + var v = hl.Api.getVirtualValue(v); + if( v == null ) + return TObject; + return typeof(v); + default: + return TUnknown; + } + } + + @:hlNative("std","type_enum_eq") + public static function enumEq( a : T, b : T ) : Bool { + return false; + } + + public static function enumConstructor( e : EnumValue ) : String { + var en : hl.BaseType.Enum = cast getEnum(e); + return en.__constructs__[Type.enumIndex(e)]; + } + + @:hlNative("std","enum_parameters") + static function _enumParameters( e : EnumValue ) : hl.NativeArray { + return null; + } + + public static function enumParameters( e : EnumValue ) : Array { + var arr = _enumParameters(e); + return cast hl.types.ArrayObj.alloc(arr); + } + + @:extern public inline static function enumIndex( e : EnumValue ) : Int { + return untyped $enumIndex(e); + } + + public static function allEnums( e : Enum ) : Array { + var en : hl.BaseType.Enum = cast e; + var out = []; + for( i in 0...en.__evalues__.length ) { + var v = en.__evalues__[i]; + if( v != null ) out.push(v); + } + return out; + } + +} \ No newline at end of file diff --git a/std/hl/_std/UInt.hx b/std/hl/_std/UInt.hx new file mode 100644 index 00000000..c6a12a44 --- /dev/null +++ b/std/hl/_std/UInt.hx @@ -0,0 +1,190 @@ +/* + * Copyright (C)2005-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. + */ + +@:coreApi +abstract UInt(Int) from Int to Int { + + @:op(A + B) private static inline function add(a:UInt, b:UInt):UInt { + return a.toInt() + b.toInt(); + } + + @:op(A / B) private static inline function div(a:UInt, b:UInt):Float { + return a.toFloat() / b.toFloat(); + } + + @:op(A * B) private static inline function mul(a:UInt, b:UInt):UInt { + return a.toInt() * b.toInt(); + } + + @:op(A - B) private static inline function sub(a:UInt, b:UInt):UInt { + return a.toInt() - b.toInt(); + } + + @:op(A > B) private static function gt(a:UInt, b:UInt):Bool; + + @:op(A >= B) private static function gte(a:UInt, b:UInt):Bool; + + @:op(A < B) private static function lt(a:UInt, b:UInt):Bool; + + @:op(A <= B) private static function lte(a:UInt, b:UInt):Bool; + + @:op(A & B) private static inline function and(a:UInt, b:UInt):UInt { + return a.toInt() & b.toInt(); + } + + @:op(A | B) private static inline function or(a:UInt, b:UInt):UInt { + return a.toInt() | b.toInt(); + } + + @:op(A ^ B) private static inline function xor(a:UInt, b:UInt):UInt { + return a.toInt() ^ b.toInt(); + } + + @:op(A << B) private static inline function shl(a:UInt, b:Int):UInt { + return a.toInt() << b; + } + + @:op(A >> B) private static inline function shr(a:UInt, b:Int):UInt { + return a.toInt() >>> b; + } + + @:op(A >>> B) private static inline function ushr(a:UInt, b:Int):UInt { + return a.toInt() >>> b; + } + + @:op(A % B) private static function mod(a:UInt, b:UInt):UInt; + + @:commutative @:op(A + B) private static inline function addWithFloat(a:UInt, b:Float):Float { + return a.toFloat() + b; + } + + @:commutative @:op(A * B) private static inline function mulWithFloat(a:UInt, b:Float):Float { + return a.toFloat() * b; + } + + @:op(A / B) private static inline function divFloat(a:UInt, b:Float):Float { + return a.toFloat() / b; + } + + @:op(A / B) private static inline function floatDiv(a:Float, b:UInt):Float { + return a / b.toFloat(); + } + + @:op(A - B) private static inline function subFloat(a:UInt, b:Float):Float { + return a.toFloat() - b; + } + + @:op(A - B) private static inline function floatSub(a:Float, b:UInt):Float { + return a - b.toFloat(); + } + + @:op(A > B) private static inline function gtFloat(a:UInt, b:Float):Bool { + return a.toFloat() > b; + } + + @:commutative @:op(A == B) private static inline function equalsInt(a:UInt, b:T):Bool { + return a.toInt() == b; + } + + @:commutative @:op(A != B) private static inline function notEqualsInt(a:UInt, b:T):Bool { + return a.toInt() != b; + } + + @:commutative @:op(A == B) private static inline function equalsFloat(a:UInt, b:T):Bool { + return a.toFloat() == b; + } + + @:commutative @:op(A != B) private static inline function notEqualsFloat(a:UInt, b:T):Bool { + return a.toFloat() != b; + } + + @:op(A >= B) private static inline function gteFloat(a:UInt, b:Float):Bool { + return a.toFloat() >= b; + } + + + @:op(A > B) private static inline function floatGt(a:Float, b:UInt):Bool { + return a > b.toFloat(); + } + + @:op(A >= B) private static inline function floatGte(a:Float, b:UInt):Bool { + return a >= b.toFloat(); + } + + @:op(A < B) private static inline function ltFloat(a:UInt, b:Float):Bool { + return a.toFloat() < b; + } + + @:op(A <= B) private static inline function lteFloat(a:UInt, b:Float):Bool { + return a.toFloat() <= b; + } + + @:op(A < B) private static inline function floatLt(a:Float, b:UInt):Bool { + return a < b.toFloat(); + } + + @:op(A <= B) private static inline function floatLte(a:Float, b:UInt):Bool { + return a <= b.toFloat(); + } + + @:op(A % B) private static inline function modFloat(a:UInt, b:Float):Float { + return a.toFloat() % b; + } + + @:op(A % B) private static inline function floatMod(a:Float, b:UInt):Float { + return a % b.toFloat(); + } + + @:op(~A) private inline function negBits():UInt { + return ~this; + } + + @:op(++A) private inline function prefixIncrement():UInt { + return ++this; + } + + @:op(A++) private inline function postfixIncrement():UInt { + return this++; + } + + @:op(--A) private inline function prefixDecrement():UInt { + return --this; + } + + @:op(A--) private inline function postfixDecrement():UInt { + return this--; + } + + // TODO: radix is just defined to deal with doc_gen issues + private inline function toString(?radix:Int):String { + return Std.string(toFloat()); + } + + private inline function toInt():Int { + return this; + } + + @:to private inline function toFloat():Float { + return cast (this:UInt); + } +} + diff --git a/std/hl/_std/haxe/Resource.hx b/std/hl/_std/haxe/Resource.hx new file mode 100644 index 00000000..cc22a517 --- /dev/null +++ b/std/hl/_std/haxe/Resource.hx @@ -0,0 +1,57 @@ +/* + * Copyright (C)2005-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 haxe; + +private class ResourceContent { + public var name : hl.Bytes; + public var data : hl.Bytes; + public var dataLen : Int; +} + +@:coreApi +class Resource { + + static var content : hl.NativeArray; + + public static function listNames() : Array { + return [for (x in content) @:privateAccess String.fromUCS2(x.name)]; + } + + public static function getString( name : String ) : String { + for( x in content ) + if( x.name.compare(0,@:privateAccess name.bytes,0,(name.length+1)<<1) == 0 ) + return @:privateAccess String.fromUTF8(x.data); + return null; + } + + public static function getBytes( name : String ) : haxe.io.Bytes { + for( x in content ) + if( x.name.compare(0,@:privateAccess name.bytes,0,(name.length+1)<<1) == 0 ) + return @:privateAccess new haxe.io.Bytes(x.data, x.dataLen); + return null; + } + + static function __init__() : Void { + content = untyped $resources(); + } + +} diff --git a/std/js/html/webgl/CompressedTextureS3TC.hx b/std/hl/_std/haxe/ds/IntMap.hx similarity index 50% rename from std/js/html/webgl/CompressedTextureS3TC.hx rename to std/hl/_std/haxe/ds/IntMap.hx index 931b26fd..7e7f66fb 100644 --- a/std/js/html/webgl/CompressedTextureS3TC.hx +++ b/std/hl/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,8 +20,55 @@ * DEALINGS IN THE SOFTWARE. */ -package js.html.webgl; +package haxe.ds; -/** @deprecated Use ExtensionCompressedTextureS3TC instead. */ -@:deprecated("CompressedTextureS3TC is deprecated, use ExtensionCompressedTextureS3TC instead") -typedef CompressedTextureS3TC = ExtensionCompressedTextureS3TC; +@:coreApi +class IntMap implements haxe.Constraints.IMap { + + var h : hl.types.IntMap; + + public function new() : Void { + h = new hl.types.IntMap(); + } + + public function set( key : Int, value : T ) : Void { + @:privateAccess h.set(key,value); + } + + public function get( key : Int ) : Null { + return @:privateAccess h.get(key); + } + + public function exists( key : Int ) : Bool { + return @:privateAccess h.exists(key); + } + + public function remove( key : Int ) : Bool { + return @:privateAccess h.remove(key); + } + + public function keys() : Iterator { + return new hl.NativeArray.NativeArrayIterator(h.keysArray()); + } + + public function iterator() : Iterator { + return h.iterator(); + } + + public function toString() : String { + var s = new StringBuf(); + var keys = h.keysArray(); + var values = h.valuesArray(); + s.addChar('{'.code); + for( i in 0...keys.length ) { + if( i > 0 ) + s.add(", "); + s.add(keys[i]); + s.add(" => "); + s.add(values[i]); + } + s.addChar('}'.code); + return s.toString(); + } + +} diff --git a/std/hl/_std/haxe/ds/ObjectMap.hx b/std/hl/_std/haxe/ds/ObjectMap.hx new file mode 100644 index 00000000..810ca4a4 --- /dev/null +++ b/std/hl/_std/haxe/ds/ObjectMap.hx @@ -0,0 +1,74 @@ +/* + * Copyright (C)2005-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 haxe.ds; + +@:coreApi +class ObjectMap implements haxe.Constraints.IMap { + + var h : hl.types.ObjectMap; + + public function new() : Void { + h = new hl.types.ObjectMap(); + } + + public function set( key : K, value : T ) : Void { + @:privateAccess h.set(key,value); + } + + public function get( key : K ) : Null { + return @:privateAccess h.get(key); + } + + public function exists( key : K ) : Bool { + return @:privateAccess h.exists(key); + } + + public function remove( key : K ) : Bool { + return @:privateAccess h.remove(key); + } + + public function keys() : Iterator { + return new hl.NativeArray.NativeArrayIterator(cast h.keysArray()); + } + + public function iterator() : Iterator { + return h.iterator(); + } + + public function toString() : String { + var s = new StringBuf(); + var keys = h.keysArray(); + var values = h.valuesArray(); + s.addChar('{'.code); + for( i in 0...keys.length ) { + if( i > 0 ) + s.add(", "); + s.add(keys[i]); + s.add(" => "); + s.add(values[i]); + } + s.addChar('}'.code); + return s.toString(); + } + +} diff --git a/std/hl/_std/haxe/ds/StringMap.hx b/std/hl/_std/haxe/ds/StringMap.hx new file mode 100644 index 00000000..9562db1d --- /dev/null +++ b/std/hl/_std/haxe/ds/StringMap.hx @@ -0,0 +1,100 @@ +/* + * Copyright (C)2005-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 haxe.ds; + +private class StringMapKeysIterator { + var arr : hl.NativeArray; + var pos : Int; + var length : Int; + + public inline function new(h:hl.types.BytesMap) { + this.arr = h.keysArray(); + pos = 0; + length = arr.length; + } + + public inline function hasNext() { + return pos < length; + } + + public inline function next() @:privateAccess { + var b = arr[pos++]; + return String.fromUCS2(b); + } + +} + +@:coreApi +class StringMap implements haxe.Constraints.IMap { + + var h : hl.types.BytesMap; + + public function new() : Void { + h = new hl.types.BytesMap(); + } + + public function set( key : String, value : T ) : Void { + @:privateAccess h.set(key.bytes,value); + } + + public function get( key : String ) : Null { + if( key == null ) return null; + return @:privateAccess h.get(key.bytes); + } + + public function exists( key : String ) : Bool { + if( key == null ) return false; + return @:privateAccess h.exists(key.bytes); + } + + public function remove( key : String ) : Bool { + if( key == null ) return false; + return @:privateAccess h.remove(key.bytes); + } + + public function keys() : Iterator { + return new StringMapKeysIterator(h); + } + + public function iterator() : Iterator { + return h.iterator(); + } + + public function toString() : String { + var s = new StringBuf(); + var keys = h.keysArray(); + var values = h.valuesArray(); + s.addChar('{'.code); + for( i in 0...keys.length ) { + if( i > 0 ) + s.add(", "); + var k = keys[i]; + @:privateAccess s.__add(k,0,(@:privateAccess k.ucs2Length(0)) << 1); + s.add(" => "); + s.add(values[i]); + } + s.addChar('}'.code); + return s.toString(); + } + +} diff --git a/std/hl/_std/haxe/ds/Vector.hx b/std/hl/_std/haxe/ds/Vector.hx new file mode 100644 index 00000000..44815ff3 --- /dev/null +++ b/std/hl/_std/haxe/ds/Vector.hx @@ -0,0 +1,89 @@ +/* + * Copyright (C)2005-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 haxe.ds; + +private typedef VectorData = Array + +@:coreApi +abstract Vector(VectorData) { + + public inline function new(length:Int) { + this = []; + if( length > 0 ) this[length-1] = cast null; + } + + @:op([]) public inline function get(index:Int):T { + return this[index]; + } + + @:op([]) public inline function set(index:Int, val:T):T { + return this[index] = val; + } + + public var length(get, never):Int; + + inline function get_length():Int { + return this.length; + } + + public static inline function blit(src:Vector, srcPos:Int, dest:Vector, destPos:Int, len:Int):Void { + (cast dest : hl.types.ArrayBase.ArrayAccess).blit(destPos,(cast src : hl.types.ArrayBase.ArrayAccess),srcPos,len); + } + + public inline function toArray():Array { + return this.copy(); + } + + public inline function toData():VectorData + return this; + + static public inline function fromData(data:VectorData):Vector + return cast data; + + static public inline function fromArrayCopy(array:Array):Vector { + return cast array.copy(); + } + + public inline function copy():Vector { + return cast this.copy(); + } + + public inline function join(sep:String):String { + return this.join(sep); + } + + public inline function sort(f:T->T->Int):Void { + this.sort(f); + } + + public inline function map(f:T->S):Vector { + var length = length; + var r = new Vector(length); + var i = 0; + var len = length; + for(i in 0...len) { + var v = f(get(i)); + r.set(i, v); + } + return r; + } +} diff --git a/std/hl/_std/haxe/io/Bytes.hx b/std/hl/_std/haxe/io/Bytes.hx new file mode 100644 index 00000000..e93ab5f1 --- /dev/null +++ b/std/hl/_std/haxe/io/Bytes.hx @@ -0,0 +1,179 @@ +/* + * Copyright (C)2005-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 haxe.io; + +@:coreApi +class Bytes { + + public var length(default,null) : Int; + var b : hl.Bytes; + + function new(b:hl.Bytes,length:Int) : Void { + this.b = b; + this.length = length; + } + + inline function out(pos:Int) : Bool { + return (pos:UInt) >= (length : UInt); + } + + inline function outRange(pos:Int,len:Int) : Bool { + return pos < 0 || len < 0 || ((pos+len):UInt) > (length : UInt); + } + + public function get( pos : Int ) : Int { + return if( out(pos) ) 0 else b[pos]; + } + + public function set( pos : Int, v : Int ) : Void { + if( out(pos) ) throw Error.OutsideBounds; + b[pos] = v; + } + + public function blit( pos : Int, src : Bytes, srcpos : Int, len : Int ) : Void { + if( outRange(pos, len) || src.outRange(srcpos,len) ) throw Error.OutsideBounds; + b.blit(pos, src.b, srcpos, len); + } + + public function fill( pos : Int, len : Int, value : Int ) : Void { + if( outRange(pos,len) ) throw Error.OutsideBounds; + b.fill(pos, len, value); + } + + public function sub( pos : Int, len : Int ) : Bytes { + if( outRange(pos,len) ) throw Error.OutsideBounds; + return new Bytes(b.sub(pos, len), len); + } + + public function compare( other : Bytes ) : Int { + var len = length < other.length ? length : other.length; + var r = b.compare(0, other.b, 0, len); + if( r == 0 ) + r = length - other.length; + return r; + } + + public function getDouble( pos : Int ) : Float { + return if( out(pos + 7) ) 0. else b.getF64(pos); + } + + public function getFloat( pos : Int ) : Float { + return if( out(pos + 3) ) 0. else b.getF32(pos); + } + + public function setDouble( pos : Int, v : Float ) : Void { + if( out(pos + 7) ) throw Error.OutsideBounds; + b.setF64(pos, v); + } + + public function setFloat( pos : Int, v : Float ) : Void { + if( out(pos + 3) ) throw Error.OutsideBounds; + b.setF32(pos, v); + } + + public inline function getUInt16( pos : Int ) : Int { + return if( out(pos + 1) ) 0 else b.getUI16(pos); + } + + public inline function setUInt16( pos : Int, v : Int ) : Void { + if( out(pos + 1) ) throw Error.OutsideBounds; + b.setUI16(pos, v); + } + + public function getInt32( pos : Int ) : Int { + return if( out(pos + 3) ) 0 else b.getI32(pos); + } + + public function getInt64( pos : Int ) : haxe.Int64 { + if( out(pos + 7) ) + return haxe.Int64.ofInt(0); + return haxe.Int64.make(b.getI32(pos+4), b.getI32(pos)); + } + + public function setInt32( pos : Int, v : Int ) : Void { + if( out(pos + 3) ) throw Error.OutsideBounds; + b.setI32(pos, v); + } + + public inline function setInt64( pos : Int, v : haxe.Int64 ) : Void { + setInt32(pos + 4, v.high); + setInt32(pos, v.low); + } + + public function getString( pos : Int, len : Int ) : String { + if( outRange(pos,len) ) throw Error.OutsideBounds; + + var b = new hl.Bytes(len + 1); + b.blit(0, this.b, pos, len); + b[len] = 0; + return @:privateAccess String.fromUTF8(b); + } + + @:deprecated("readString is deprecated, use getString instead") + @:noCompletion + public inline function readString(pos:Int, len:Int):String { + return getString(pos, len); + } + + public function toString() : String { + return getString(0,length); + } + + public function toHex() : String { + var s = new StringBuf(); + var chars = []; + var str = "0123456789abcdef"; + for( i in 0...str.length ) + chars.push(str.charCodeAt(i)); + for( i in 0...length ) { + var c = get(i); + s.addChar(chars[c >> 4]); + s.addChar(chars[c & 15]); + } + return s.toString(); + } + + public inline function getData() : BytesData { + return new haxe.io.BytesData(b,length); + } + + public static function alloc( length : Int ) : Bytes { + var b = new hl.Bytes(length); + b.fill(0, length, 0); + return new Bytes(b,length); + } + + public static function ofString( s : String ) : Bytes @:privateAccess { + var size = 0; + var b = s.bytes.utf16ToUtf8(0, size); + return new Bytes(b,size); + } + + public static function ofData( b : BytesData ) : Bytes { + return new Bytes(b.bytes,b.length); + } + + public inline static function fastGet( b : BytesData, pos : Int ) : Int { + return b[pos]; + } + +} diff --git a/std/hl/_std/haxe/io/BytesBuffer.hx b/std/hl/_std/haxe/io/BytesBuffer.hx new file mode 100644 index 00000000..c0bd1744 --- /dev/null +++ b/std/hl/_std/haxe/io/BytesBuffer.hx @@ -0,0 +1,106 @@ +/* + * Copyright (C)2005-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 haxe.io; + +@:coreApi +class BytesBuffer { + + var b : hl.Bytes; + var pos : Int; + var size : Int; + + public var length(get,never) : Int; + + public function new() { + pos = 0; + size = 16; // ensure increment of 8 + b = new hl.Bytes(size); + } + + inline function get_length() : Int { + return pos; + } + + public inline function addByte( byte : Int ) : Void { + if( pos == size ) __expand(0); + b[pos++] = byte; + } + + function __expand( req : Int ) : Void { + var nsize = (size * 3) >> 1; + if( nsize < req ) nsize = req; + var b2 = new hl.Bytes(nsize); + b2.blit(0, b, 0, pos); + b = b2; + size = nsize; + } + + function __add( b : hl.Bytes, bpos : Int, blen : Int ) : Void { + if( pos + blen > size ) __expand(pos+blen); + this.b.blit(pos, b, bpos, blen); + pos += blen; + } + + public inline function add( src : Bytes ) : Void { + __add(@:privateAccess src.b, 0, src.length); + } + + public inline function addString( v : String ) : Void { + var len = 0; + @:privateAccess __add(v.bytes.utf16ToUtf8(0, len), 0, len); + } + + public inline function addInt32( v : Int ) : Void { + if( pos + 4 > size ) __expand(0); + b.setI32(pos, v); + pos += 4; + } + + public inline function addInt64( v : haxe.Int64 ) : Void { + if( pos + 8 > size ) __expand(0); + b.setI32(pos, v.low); + b.setI32(pos + 4, v.high); + pos += 8; + } + + public inline function addFloat( v : Float ) : Void { + if( pos + 4 > size ) __expand(0); + b.setF32(pos, v); + pos += 4; + } + + public inline function addDouble( v : Float ) : Void { + if( pos + 8 > size ) __expand(0); + b.setF64(pos, v); + pos += 8; + } + + public inline function addBytes( src : Bytes, pos : Int, len : Int ) : Void { + if( pos < 0 || len < 0 || pos + len > src.length ) throw Error.OutsideBounds; + __add(@:privateAccess src.b, pos, len); + } + + public function getBytes() : Bytes { + return @:privateAccess new haxe.io.Bytes(b, pos); + } + +} diff --git a/std/hl/_std/haxe/io/FPHelper.hx b/std/hl/_std/haxe/io/FPHelper.hx new file mode 100644 index 00000000..f9494247 --- /dev/null +++ b/std/hl/_std/haxe/io/FPHelper.hx @@ -0,0 +1,56 @@ +/* + * Copyright (C)2005-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 haxe.io; + +class FPHelper { + + // note : this is not thread safe, use TLS when available + static var i64tmp = Int64.ofInt(0); + static var helper = new hl.Bytes(8); + + public static function i32ToFloat( i : Int ) : Single { + helper.setI32(0,i); + return helper.getF32(0); + } + + public static function floatToI32( f : Single ) : Int { + helper.setF32(0,f); + return helper.getI32(0); + } + + public static function i64ToDouble( low : Int, high : Int ) : Float { + helper.setI32(0,low); + helper.setI32(4,high); + return helper.getF64(0); + } + + public static function doubleToI64( v : Float ) : Int64 { + helper.setF64(0,v); + var i64 = i64tmp; + @:privateAccess { + i64.set_low(helper.getI32(0)); + i64.set_high(helper.getI32(4)); + } + return i64; + } + +} diff --git a/std/hl/_std/haxe/zip/Compress.hx b/std/hl/_std/haxe/zip/Compress.hx new file mode 100644 index 00000000..e4dbebf5 --- /dev/null +++ b/std/hl/_std/haxe/zip/Compress.hx @@ -0,0 +1,69 @@ +/* + * Copyright (C)2005-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 haxe.zip; + +private typedef Deflater = hl.Abstract<"fmt_zip">; + +@:coreApi @:hlNative("fmt") +class Compress { + + var s : Deflater; + + public function new( level : Int ) : Void { + s = deflate_init(level); + } + + public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { + var read = 0, write = 0; + var done = deflate_buffer(s,src.getData(),srcPos,src.length,dst.getData(),dstPos,dst.length,read,write); + return { done : done, read : read, write : write }; + } + + public function setFlushMode( f : FlushMode ) : Void { + @:privateAccess Uncompress.zip_flush_mode(cast s,f.getIndex()); + } + + public function close() : Void { + @:privateAccess Uncompress.zip_end(cast s); + } + + public static function run( s : haxe.io.Bytes, level : Int ) : haxe.io.Bytes { + var c = new Compress(level); + c.setFlushMode(FlushMode.FINISH); + var out = haxe.io.Bytes.alloc(deflate_bound(c.s,s.length)); + var r = c.execute(s,0,out,0); + c.close(); + if( !r.done || r.read != s.length ) + throw "Compression failed"; + if( r.write < out.length*0.66 ) + return out.sub(0, r.write); + @:privateAccess out.length = r.write; + return out; + } + + static function deflate_init( level : Int ) : Deflater { return null; } + static function deflate_buffer( i : Deflater, bytes : hl.Bytes, bytesPos : Int, bytesLen : Int, dst : hl.Bytes, dstPos : Int, dstLen : Int, read : hl.Ref, write : hl.Ref) : Bool { + return false; + } + static function deflate_bound( i : Deflater, length : Int ) : Int { return 0; } + +} diff --git a/std/hl/_std/haxe/zip/Uncompress.hx b/std/hl/_std/haxe/zip/Uncompress.hx new file mode 100644 index 00000000..94f19dc8 --- /dev/null +++ b/std/hl/_std/haxe/zip/Uncompress.hx @@ -0,0 +1,74 @@ +/* + * Copyright (C)2005-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 haxe.zip; + +private typedef Inflater = hl.Abstract<"fmt_zip">; + +@:coreApi @:hlNative("fmt") +class Uncompress { + + var s : Inflater; + + public function new( ?windowBits : Int ) : Void { + s = inflate_init(windowBits); + } + + public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { + var read = 0, write = 0; + var done = inflate_buffer(s,src.getData(),srcPos,src.length,dst.getData(),dstPos,dst.length,read,write); + return { done : done, read : read, write : write }; + } + + public function setFlushMode( f : FlushMode ) : Void { + zip_flush_mode(s,f.getIndex()); + } + + public function close() : Void { + zip_end(s); + } + + public static function run( src : haxe.io.Bytes, ?bufsize : Int ) : haxe.io.Bytes { + var u = new Uncompress(null); + if( bufsize == null ) bufsize = 1 << 16; // 64K + var tmp = haxe.io.Bytes.alloc(bufsize); + var b = new haxe.io.BytesBuffer(); + var pos = 0; + u.setFlushMode(FlushMode.SYNC); + while( true ) { + var r = u.execute(src,pos,tmp,0); + b.addBytes(tmp,0,r.write); + pos += r.read; + if( r.done ) + break; + } + u.close(); + return b.getBytes(); + } + + static function inflate_init( bits : Int ) : Inflater { return null; } + static function inflate_buffer( i : Inflater, bytes : hl.Bytes, bytesPos : Int, bytesLen : Int, dst : hl.Bytes, dstPos : Int, dstLen : Int, read : hl.Ref, write : hl.Ref) : Bool { + return false; + } + static function zip_end( i : Inflater ) : Void { } + static function zip_flush_mode( i : Inflater, flush : Int ) : Void {} + +} diff --git a/std/hl/_std/sys/FileSystem.hx b/std/hl/_std/sys/FileSystem.hx new file mode 100644 index 00000000..20fdf585 --- /dev/null +++ b/std/hl/_std/sys/FileSystem.hx @@ -0,0 +1,115 @@ +/* + * Copyright (C)2005-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 sys; + +@:coreApi +@:access(Sys) +class FileSystem { + + public static function exists( path : String ) : Bool { + return sys_exists( Sys.getPath(makeCompatiblePath(path)) ); + } + + public static function rename( path : String, newPath : String ) : Void { + if( !sys_rename( Sys.getPath(path), Sys.getPath(newPath) ) ) throw new Sys.SysError("Failed to rename " + path + " to " + newPath); + } + + public static function stat( path : String ) : FileStat { + var values = sys_stat( Sys.getPath(makeCompatiblePath(path)) ); + if( values == null ) throw new Sys.SysError("Failed to stat " + path); + return { + gid : values[0], + uid : values[1], + atime : @:privateAccess Date.fromInt(values[2]), + mtime : @:privateAccess Date.fromInt(values[3]), + ctime : @:privateAccess Date.fromInt(values[4]), + size : values[5], + dev : values[6], + ino : values[7], + nlink : values[8], + rdev : values[9], + mode : values[10], + }; + } + + public static function fullPath( relPath : String ) : String { + return Sys.makePath( sys_full_path(Sys.getPath(relPath)) ); + } + + public static function absolutePath ( relPath : String ) : String { + if (haxe.io.Path.isAbsolute(relPath)) return relPath; + return haxe.io.Path.join([Sys.getCwd(), relPath]); + } + + public static function isDirectory( path : String ) : Bool { + return sys_is_dir(Sys.getPath(makeCompatiblePath(path))); + } + + public static function createDirectory( path : String ) : Void { + var path = haxe.io.Path.addTrailingSlash(path); + var _p = null; + var parts = []; + while (path != (_p = haxe.io.Path.directory(path))) { + parts.unshift(path); + path = _p; + } + for (part in parts) { + if (part.charCodeAt(part.length - 1) != ":".code && !exists(part)) + if( !sys_create_dir(Sys.getPath(part), 493) ) + throw new Sys.SysError("Failed to create directory " + part); + } + } + + public static function deleteFile( path : String ) : Void { + if( !sys_delete(Sys.getPath(path)) ) throw new Sys.SysError("Can't delete file " + path); + } + + public static function deleteDirectory( path : String ) : Void { + if( !sys_remove_dir(Sys.getPath(path)) ) throw new Sys.SysError("Can't delete directory " + path); + } + + public static function readDirectory( path : String ) : Array { + var content = sys_read_dir(Sys.getPath(path)); + if( content == null ) + throw new Sys.SysError("Failed to read directory " + path); + return [for( c in content ) Sys.makePath(c)]; + } + + private static inline function makeCompatiblePath(path:String):String { + return if (path.charCodeAt(1) == ":".code && path.length <= 3) { + haxe.io.Path.addTrailingSlash(path); + } else { + haxe.io.Path.removeTrailingSlashes(path); + } + } + + @:hlNative("std", "sys_read_dir") static function sys_read_dir( path : hl.Bytes ) : hl.NativeArray { return null; } + @:hlNative("std", "sys_create_dir") static function sys_create_dir( path : hl.Bytes, rights : Int ) : Bool { return false; } + @:hlNative("std", "sys_is_dir") static function sys_is_dir( path : hl.Bytes ) : Bool { return false; } + @:hlNative("std", "sys_stat") static function sys_stat( path : hl.Bytes ) : hl.NativeArray { return null; } + @:hlNative("std", "sys_rename") static function sys_rename( path : hl.Bytes, to : hl.Bytes ) : Bool { return true; } + @:hlNative("std", "sys_delete") static function sys_delete( path : hl.Bytes ) : Bool { return true; }; + @:hlNative("std", "sys_full_path") static function sys_full_path( path : hl.Bytes ) : hl.Bytes { return null; } + @:hlNative("std", "sys_remove_dir") static function sys_remove_dir( path : hl.Bytes ) : Bool { return true; } + @:hlNative("std", "sys_exists") static function sys_exists( path : hl.Bytes ) : Bool { return true; } + +} diff --git a/std/hl/_std/sys/db/Sqlite.hx b/std/hl/_std/sys/db/Sqlite.hx new file mode 100644 index 00000000..d4bd0c70 --- /dev/null +++ b/std/hl/_std/sys/db/Sqlite.hx @@ -0,0 +1,278 @@ +/* + * Copyright (C)2005-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 sys.db; +import haxe.crypto.BaseCode; + +private typedef SqliteConnectionHandle = hl.Abstract<"sqlite_database">; +private typedef SqliteResultHandle = hl.Abstract<"sqlite_result">; + +@:hlNative("sqlite") +private class SqliteLib +{ + public static function connect( path : hl.Bytes ) : SqliteConnectionHandle { return null; } + public static function close( c : SqliteConnectionHandle ) : Void { } + public static function request( c : SqliteConnectionHandle, sql : hl.Bytes ) : SqliteResultHandle { return null; } + public static function last_id( c : SqliteConnectionHandle ) : Int { return 0; } + + public static function result_next( c : SqliteResultHandle ) : hl.NativeArray { return null; } + + public static function result_get( c : SqliteResultHandle, n : Int ) : Null { return null; } + public static function result_get_int( c : SqliteResultHandle, n : Int ) : Null { return 0; } + public static function result_get_float( c : SqliteResultHandle, n : Int ) : Null { return .0; } + public static function result_get_length( c : SqliteResultHandle ) : Null { return 0; } + public static function result_get_nfields( c : SqliteResultHandle ) : Int { return 0; } + public static function result_get_fields( c : SqliteResultHandle ) : hl.NativeArray { return null; } +} + + +@:access(Sys) +@:access(String) +private class SqliteConnection implements Connection +{ + + var c : SqliteConnectionHandle; + + public function new( file : String ) + { + c = SqliteLib.connect(Sys.getPath(file)); + } + + public function close( ) : Void + { + SqliteLib.close(c); + } + + public function request( s : String ) : ResultSet + { + try + { + var r : SqliteResultHandle = SqliteLib.request(c, s.bytes); + + return new SqliteResultSet(r); + } + catch ( e : String ) + { + throw 'Error while executing $s ($e)'; + } + + return null; + } + + public function escape( s : String ) : String + { + return s.split("'").join("''"); + } + + public function quote( s : String ) : String + { + if( s.indexOf("\000") >= 0 ) + return "x'" + BaseCode.encode(s, "0123456789ABCDEF") + "'"; + + return "'" + s.split("'").join("''") + "'"; + } + + public function addValue( s : StringBuf, v : Dynamic ) : Void + { + switch( Type.typeof(v) ) + { + case TNull, TInt: s.add(v); + case TBool: s.add( v ? 1 : 0); + case _: s.add(quote(Std.string(v))); + } + } + + public function lastInsertId( ) : Int + { + return SqliteLib.last_id(c); + } + + public function dbName( ) : String + { + return "SQLite"; + } + + public function startTransaction( ) : Void + { + request("BEGIN TRANSACTION"); + } + + public function commit( ) : Void + { + request("COMMIT"); + startTransaction(); // match mysql usage + } + + public function rollback( ) : Void + { + request("ROLLBACK"); + startTransaction(); // match mysql usage + } +} + + + +@:access(String) +private class SqliteResultSet implements ResultSet +{ + public var length(get,null) : Int; + public var nfields(get,null) : Int; + + var names : Array; + var cache : List; + + var r : SqliteResultHandle; + + public function new( r : SqliteResultHandle ) + { + cache = new List(); + this.r = r; + hasNext(); // execute the request + } + + function get_length( ) : Int + { + if ( nfields != 0 ) + { + while ( true ) + { + var c = doNext(); + if( c == null ) + break; + + cache.add(c); + } + + return cache.length; + } + + return SqliteLib.result_get_length(r); + } + + function get_nfields( ) : Int + { + return SqliteLib.result_get_nfields(r); + } + + public function hasNext( ) : Bool + { + var c = next(); + if( c == null ) + return false; + + cache.push(c); + + return true; + } + + public function next( ) : Dynamic + { + var c = cache.pop(); + if( c != null ) + return c; + + return doNext(); + } + + private function doNext( ) : Dynamic + { + var o : Dynamic = {}; + var a = SqliteLib.result_next(r); + if( a == null ) + return null; + + var names = getFieldsNames(); + var i = 0 ; + var l = names.length; + while ( i < l ) + { + var n : String = names[i]; + var v : Dynamic = a[i]; + if ( hl.Type.getDynamic(v).kind == hl.Type.TypeKind.HBytes ) + Reflect.setField(o, n, String.fromUCS2(v)); + else + Reflect.setField(o, n, v); + i++; + } + return o; + } + + public function results( ) : List + { + var l = new List(); + while ( true ) + { + var c = next(); + if( c == null ) + break; + + l.add(c); + } + + return l; + } + + public function getResult( n : Int ) : String + { + var bytes = SqliteLib.result_get(r, n); + if ( bytes == null ) + return null; + + return String.fromUCS2(bytes); + } + + public function getIntResult( n : Int ) : Int + { + return SqliteLib.result_get_int(r,n); + } + + public function getFloatResult( n : Int ) : Float + { + return SqliteLib.result_get_float(r,n); + } + + public function getFieldsNames( ) : Array + { + if ( this.names != null ) + return this.names; + + this.names = []; + var names = SqliteLib.result_get_fields(r); + var i = 0; + var l = names.length; + while ( i < l ) + { + var name = String.fromUCS2(names[i]); + this.names.push(name); + i++; + } + + return this.names; + } +} + +@:coreApi class Sqlite +{ + public static function open( file : String ) : Connection + { + return new SqliteConnection(file); + } +} \ No newline at end of file diff --git a/std/hl/_std/sys/io/File.hx b/std/hl/_std/sys/io/File.hx new file mode 100644 index 00000000..74168e03 --- /dev/null +++ b/std/hl/_std/sys/io/File.hx @@ -0,0 +1,87 @@ +/* + * Copyright (C)2005-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 sys.io; + +#if doc_gen +enum FileHandle { } +#else +typedef FileHandle = hl.Abstract<"hl_fdesc">; +#end + +@:access(Sys) +@:coreApi class File { + + public static function getContent( path : String ) : String { + var bytes = file_contents(Sys.getPath(path), null); + if( bytes == null ) throw new Sys.SysError("Can't read "+path); + return @:privateAccess String.fromUTF8(bytes); + } + + public static function getBytes( path : String ) : haxe.io.Bytes { + var size = 0; + var bytes = file_contents(Sys.getPath(path), size); + if( bytes == null ) throw new Sys.SysError("Can't read "+path); + return @:privateAccess new haxe.io.Bytes(bytes, size); + } + + public static function saveContent( path : String, content : String ) : Void { + var f = write(path); + f.writeString(content); + f.close(); + } + + public static function saveBytes( path : String, bytes : haxe.io.Bytes ) : Void { + var f = write(path); + f.write(bytes); + f.close(); + } + + public static function read( path : String, binary : Bool = true ) : FileInput { + var f = file_open(Sys.getPath(path),0,binary); + if( f == null ) throw new Sys.SysError("Can't open "+path); + return @:privateAccess new FileInput(f); + } + + public static function write( path : String, binary : Bool = true ) : FileOutput { + var f = file_open(Sys.getPath(path),1,binary); + if( f == null ) throw new Sys.SysError("Can't open "+path+" for writing"); + return @:privateAccess new FileOutput(f); + } + + public static function append( path : String, binary : Bool = true ) : FileOutput { + var f = file_open(Sys.getPath(path),2,binary); + if( f == null ) throw new Sys.SysError("Can't open "+path+" for append"); + return @:privateAccess new FileOutput(f); + } + + public static function copy( srcPath : String, dstPath : String ) : Void { + var s = read(srcPath,true); + var d = write(dstPath,true); + d.writeInput(s); + s.close(); + d.close(); + } + + @:hlNative("std", "file_open") static function file_open( path : hl.Bytes, mode : Int, binary : Bool ) : FileHandle { return null; } + @:hlNative("std", "file_contents") static function file_contents( path : hl.Bytes, size : hl.Ref ) : hl.Bytes { return null; } + +} diff --git a/std/hl/_std/sys/io/FileInput.hx b/std/hl/_std/sys/io/FileInput.hx new file mode 100644 index 00000000..070ccac6 --- /dev/null +++ b/std/hl/_std/sys/io/FileInput.hx @@ -0,0 +1,73 @@ +/* + * Copyright (C)2005-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 sys.io; +import sys.io.File; + +@:coreApi class FileInput extends haxe.io.Input { + + private var __f : FileHandle; + + function new(f:FileHandle) : Void { + __f = f; + } + + public override function readByte() : Int { + var c = file_read_char(__f); + if( c < 0 ) throw new haxe.io.Eof(); + return c; + } + + public override function readBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int { + if( p < 0 || l < 0 || p + l > s.length ) throw haxe.io.Error.OutsideBounds; + var v = file_read(__f, s.getData(), p, l); + if( v <= 0 ) throw new haxe.io.Eof(); + return v; + } + + public override function close() : Void { + super.close(); + file_close(__f); + } + + public function seek( p : Int, pos : FileSeek ) : Void { + if( !file_seek(__f,p,switch( pos ) { case SeekBegin: 0; case SeekCur: 1; case SeekEnd: 2; }) ) + throw haxe.io.Error.Custom("seek() failure"); + } + + public function tell() : Int { + var p = file_tell(__f); + if( p < 0 ) throw haxe.io.Error.Custom("tell() failure"); + return p; + } + + public function eof() : Bool { + return file_eof(__f); + } + + @:hlNative("std", "file_eof") static function file_eof( f : FileHandle ) : Bool { return false; } + @:hlNative("std", "file_read") static function file_read( f : FileHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } + @:hlNative("std", "file_read_char") static function file_read_char( f : FileHandle ) : Int { return 0; } + @:hlNative("std", "file_close") static function file_close( f : FileHandle ) : Void { } + @:hlNative("std", "file_seek") static function file_seek( f : FileHandle, pos : Int, from : Int ) : Bool { return true; } + @:hlNative("std", "file_tell") static function file_tell( f : FileHandle ) : Int { return 0; } + +} diff --git a/std/hl/_std/sys/io/FileOutput.hx b/std/hl/_std/sys/io/FileOutput.hx new file mode 100644 index 00000000..132cf282 --- /dev/null +++ b/std/hl/_std/sys/io/FileOutput.hx @@ -0,0 +1,68 @@ +/* + * Copyright (C)2005-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 sys.io; +import sys.io.File; + +@:coreApi class FileOutput extends haxe.io.Output { + + private var __f : FileHandle; + + function new(f:FileHandle) : Void { + __f = f; + } + + public override function writeByte( c : Int ) : Void { + if( !file_write_char(__f, c) ) throw new haxe.io.Eof(); + } + + public override function writeBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int { + if( p < 0 || l < 0 || p + l > s.length ) throw haxe.io.Error.OutsideBounds; + var v = file_write(__f, s.getData(), p, l); + if( v <= 0 ) throw new haxe.io.Eof(); + return v; + } + + public override function flush() : Void { + if( !file_flush(__f) ) throw haxe.io.Error.Custom("flush() failure"); + } + + public override function close() : Void { + super.close(); + @:privateAccess FileInput.file_close(__f); + } + + public function seek( p : Int, pos : FileSeek ) : Void { + if( @:privateAccess !FileInput.file_seek(__f,p,switch( pos ) { case SeekBegin: 0; case SeekCur: 1; case SeekEnd: 2; }) ) + throw haxe.io.Error.Custom("seek() failure"); + } + + public function tell() : Int { + var p = @:privateAccess FileInput.file_tell(__f); + if( p < 0 ) throw haxe.io.Error.Custom("tell() failure"); + return p; + } + + @:hlNative("std","file_flush") static function file_flush( f : FileHandle ) : Bool { return true; } + @:hlNative("std", "file_write") static function file_write( f : FileHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } + @:hlNative("std", "file_write_char") static function file_write_char( f : FileHandle, v : Int ) : Bool { return true; } + +} diff --git a/std/hl/_std/sys/io/Process.hx b/std/hl/_std/sys/io/Process.hx new file mode 100644 index 00000000..7b7c4460 --- /dev/null +++ b/std/hl/_std/sys/io/Process.hx @@ -0,0 +1,182 @@ +/* + * Copyright (C)2005-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 sys.io; + +private typedef ProcessHandle = hl.Abstract<"hl_process">; + +private class Stdin extends haxe.io.Output { + + var p : Dynamic; + var buf : haxe.io.Bytes; + + public function new(p) { + this.p = p; + buf = haxe.io.Bytes.alloc(1); + } + + public override function close() { + super.close(); + _stdin_close(p); + } + + public override function writeByte(c) { + buf.set(0,c); + writeBytes(buf,0,1); + } + + public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { + var v = _stdin_write(p, buf.getData().bytes, pos, len); + if( v < 0 ) throw new haxe.io.Eof(); + return v; + } + + @:hlNative("std","process_stdin_write") static function _stdin_write( p : ProcessHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } + @:hlNative("std", "process_stdin_close") static function _stdin_close( p : ProcessHandle ) : Bool { return false; } + +} + +private class Stdout extends haxe.io.Input { + + var p : ProcessHandle; + var out : Bool; + var buf : haxe.io.Bytes; + + public function new(p,out) { + this.p = p; + this.out = out; + buf = haxe.io.Bytes.alloc(1); + } + + public override function readByte() { + if( readBytes(buf,0,1) == 0 ) + throw haxe.io.Error.Blocked; + return buf.get(0); + } + + public override function readBytes( str : haxe.io.Bytes, pos : Int, len : Int ) : Int { + var v = out ? _stdout_read(p,str.getData().bytes,pos,len) : _stderr_read(p,str.getData().bytes,pos,len); + if( v < 0 ) throw new haxe.io.Eof(); + return v; + } + + @:hlNative("std","process_stdout_read") static function _stdout_read( p : ProcessHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } + @:hlNative("std","process_stderr_read") static function _stderr_read( p : ProcessHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } + +} + +@:access(Sys) +@:coreApi class Process { + + var p : ProcessHandle; + public var stdout(default,null) : haxe.io.Input; + public var stderr(default,null) : haxe.io.Input; + public var stdin(default, null) : haxe.io.Output; + + static var isWin = Sys.systemName() == "Windows"; + + public function new( cmd : String, ?args : Array ) : Void { + var runCmd = cmd; + if( isWin ) { + var b = new StringBuf(); + if( args == null ) { + var exe = Sys.getEnv("COMSPEC"); + if( exe == null ) exe = "cmd.exe"; + b.add("\""); + b.add(exe); + b.add("\" /C \""); + b.add(cmd); + b.addChar('"'.code); + } else { + b.addChar('"'.code); + b.add(cmd); + b.addChar('"'.code); + for( a in args ) { + b.add(" \""); + var bsCount = 0; + for( i in 0...a.length ) { + switch( StringTools.fastCodeAt(a, i) ) { + case '"'.code: + for( i in 0...bsCount * 2 ) + b.addChar('\\'.code); + bsCount = 0; + b.add("\\\""); + case '\\'.code: + bsCount++; + case c: + for( i in 0...bsCount ) + b.addChar('\\'.code); + bsCount = 0; + b.addChar(c); + } + } + // Add remaining backslashes, if any. + for( i in 0...bsCount * 2 ) + b.addChar('\\'.code); + b.addChar('"'.code); + } + args = null; + } + runCmd = b.toString(); + } + @:privateAccess { + var aargs = null; + if( args != null ) { + aargs = new hl.NativeArray(args.length); + for( i in 0...args.length ) + aargs[i] = Sys.getPath(args[i]); + } + p = _run(Sys.getPath(runCmd), aargs); + } + if( p == null ) + throw new Sys.SysError("Process creation failure : "+cmd); + stdin = new Stdin(p); + stdout = new Stdout(p,true); + stderr = new Stdout(p,false); + } + + public function getPid() : Int { + return _pid(p); + } + + public function exitCode( block : Bool = true ) : Null { + var running = false; + var code = _exit(p, block == false ? new hl.Ref(running) : null); + if( block == false ) + return running ? null : code; + return code; + } + + public function close() : Void { + _close(p); + } + + public function kill() : Void { + _kill(p); + } + + @:hlNative("std","process_run") static function _run( cmd : hl.Bytes, args : hl.NativeArray ) : ProcessHandle { return null; } + @:hlNative("std", "process_exit") static function _exit( p : ProcessHandle, running : hl.Ref ) : Int { return 0; } + @:hlNative("std", "process_pid") static function _pid( p : ProcessHandle ) : Int { return 0; } + @:hlNative("std","process_close") static function _close( p : ProcessHandle ) : Void { } + @:hlNative("std","process_kill") static function _kill( p : ProcessHandle ) : Void { } + +} \ No newline at end of file diff --git a/std/hl/_std/sys/net/Host.hx b/std/hl/_std/sys/net/Host.hx new file mode 100644 index 00000000..6f953f5c --- /dev/null +++ b/std/hl/_std/sys/net/Host.hx @@ -0,0 +1,54 @@ +/* + * Copyright (C)2005-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 sys.net; + +@:coreApi +class Host { + + public var host(default,null) : String; + + public var ip(default,null) : Int; + + public function new( name : String ) : Void { + host = name; + ip = host_resolve(@:privateAccess name.bytes.utf16ToUtf8(0,null)); + if( ip == -1 ) throw new Sys.SysError("Unresolved host " + name); + } + + public function toString() : String { + return @:privateAccess String.fromUTF8(host_to_string(ip)); + } + + public function reverse() : String { + return @:privateAccess String.fromUTF8(host_reverse(ip)); + } + + public static function localhost() : String { + return @:privateAccess String.fromUTF8(host_local()); + } + + @:hlNative("std","host_resolve") static function host_resolve( name : hl.Bytes ) : Int { return 0; } + @:hlNative("std","host_reverse") static function host_reverse( host : Int ) : hl.Bytes { return null; } + @:hlNative("std","host_to_string") static function host_to_string( host : Int ) : hl.Bytes { return null; } + @:hlNative("std","host_local") static function host_local() : hl.Bytes { return null; } + +} diff --git a/std/hl/_std/sys/net/Socket.hx b/std/hl/_std/sys/net/Socket.hx new file mode 100644 index 00000000..41579ed0 --- /dev/null +++ b/std/hl/_std/sys/net/Socket.hx @@ -0,0 +1,270 @@ +/* + * Copyright (C)2005-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 sys.net; +import haxe.io.Error; + +#if doc_gen +@:noDoc enum SocketHandle { } +#else +@:noDoc typedef SocketHandle = hl.Abstract<"hl_socket">; +#end + +private class SocketOutput extends haxe.io.Output { + + var sock : Socket; + + public function new(s) { + this.sock = s; + } + + public override function writeByte( c : Int ) { + var k = socket_send_char(@:privateAccess sock.__s, c); + if( k < 0 ) { + if( k == -1 ) throw Blocked; + throw new haxe.io.Eof(); + } + } + + public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int { + if( pos < 0 || len < 0 || pos + len > buf.length ) throw haxe.io.Error.OutsideBounds; + var n = socket_send(@:privateAccess sock.__s, buf.getData().bytes, pos, len); + if( n < 0 ) { + if( n == -1 ) throw Blocked; + throw new haxe.io.Eof(); + } + return n; + } + + public override function close() { + sock.close(); + } + + + @:hlNative("std","socket_send_char") static function socket_send_char( s : SocketHandle, c : Int ) : Int { return 0; } + @:hlNative("std","socket_send") static function socket_send( s : SocketHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } + +} + +private class SocketInput extends haxe.io.Input { + + var sock : Socket; + + public function new(s) { + sock = s; + } + + public override function readByte() : Int { + var c = socket_recv_char(@:privateAccess sock.__s); + if( c < 0 ) { + if( c == -1 ) throw Blocked; + throw new haxe.io.Eof(); + } + return c; + } + + public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { + if( pos < 0 || len < 0 || pos + len > buf.length ) throw haxe.io.Error.OutsideBounds; + var r = socket_recv(@:privateAccess sock.__s,buf.getData().bytes,pos,len); + if( r < 0 ) { + if( r == -1 ) throw Blocked; + throw new haxe.io.Eof(); + } + return r; + } + + public override function close() { + sock.close(); + } + + @:hlNative("std","socket_recv") static function socket_recv( s : SocketHandle, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return 0; } + @:hlNative("std","socket_recv_char") static function socket_recv_char( s : SocketHandle ) : Int { return 0; } + +} + +@:coreApi +@:keepInit +class Socket { + + private var __s : SocketHandle; + public var input(default,null) : haxe.io.Input; + public var output(default,null) : haxe.io.Output; + public var custom : Dynamic; + + static function __init__() : Void { + socket_init(); + } + + public function new() : Void { + init(); + } + + function init() : Void { + __s = socket_new(false); + input = new SocketInput(this); + output = new SocketOutput(this); + } + + public function close() : Void { + if( __s != null ) { + socket_close(__s); + __s = null; + } + } + + public function read() : String { + return input.readAll().toString(); + } + + public function write( content : String ) : Void { + output.writeString(content); + } + + public function connect(host : Host, port : Int) : Void { + if( !socket_connect(__s, host.ip, port) ) + throw new Sys.SysError("Failed to connect on "+host.toString()+":"+port); + } + + public function listen( connections : Int ) : Void { + if( !socket_listen(__s, connections) ) + throw new Sys.SysError("listen() failure"); + } + + public function shutdown( read : Bool, write : Bool ) : Void { + if( !socket_shutdown(__s, read, write) ) + throw new Sys.SysError("shutdown() failure"); + } + + public function bind(host : Host, port : Int) : Void { + if( !socket_bind(__s, host.ip, port) ) + throw new Sys.SysError("Cannot bind socket on " + host + ":" + port); + } + + public function accept() : Socket { + var c = socket_accept(__s); + if( c == null ) + return null; + var s : Socket = untyped $new(Socket); + s.__s = c; + s.input = new SocketInput(s); + s.output = new SocketOutput(s); + return s; + } + + public function peer() : { host : Host, port : Int } { + var ip = 0, port = 0; + if( !socket_peer(__s, ip, port) ) + return null; + var h : Host = untyped $new(Host); + @:privateAccess h.ip = ip; + return { host : h, port : port }; + } + + public function host() : { host : Host, port : Int } { + var ip = 0, port = 0; + if( !socket_host(__s, ip, port) ) + return null; + var h : Host = untyped $new(Host); + @:privateAccess h.ip = ip; + return { host : h, port : port }; + } + + public function setTimeout( timeout : Float ) : Void { + if( !socket_set_timeout(__s, timeout) ) throw new Sys.SysError("setTimeout() failure"); + } + + public function waitForRead() : Void { + select([this],null,null,null); + } + + public function setBlocking( b : Bool ) : Void { + if( !socket_set_blocking(__s, b) ) throw new Sys.SysError("setBlocking() failure"); + } + + public function setFastSend( b : Bool ) : Void { + if( !socket_set_fast_send(__s,b) ) throw new Sys.SysError("setFastSend() failure"); + } + + // TODO : use TLS when multithread added + static var tmp : hl.Bytes = null; + static var curTmpSize = 0; + + static function makeArray( a : Array ) : hl.NativeArray { + if( a == null ) return null; + var arr = new hl.NativeArray(a.length); + for( i in 0...a.length ) + arr[i] = a[i].__s; + return arr; + } + + static function outArray( a : hl.NativeArray, original : Array ) : Array { + var out = []; + if( a == null ) return out; + var i = 0, p = 0; + var max = original.length; + while( i < max ) { + var sh = a[i++]; + if( sh == null ) break; + while( original[p].__s != sh ) p++; + out.push(original[p++]); + } + return out; + } + + public static function select(read : Array, write : Array, others : Array, ?timeout : Float) : {read: Array, write: Array, others: Array} { + var sread = makeArray(read); + var swrite = makeArray(write); + var sothers = makeArray(others); + var tmpSize = 0; + if( sread != null ) tmpSize += socket_fd_size(sread.length); + if( swrite != null ) tmpSize += socket_fd_size(swrite.length); + if( sothers != null ) tmpSize += socket_fd_size(sothers.length); + if( tmpSize > curTmpSize ) { + tmp = new hl.Bytes(tmpSize); + curTmpSize = tmpSize; + } + if( !socket_select(sread, swrite, sothers, tmp, curTmpSize, timeout == null ? -1 : timeout) ) + throw "Error while waiting on socket"; + return { + read : outArray(sread,read), + write : outArray(swrite,write), + others : outArray(sothers,others), + }; + } + + @:hlNative("std", "socket_init") static function socket_init() : Void {} + @:hlNative("std", "socket_new") static function socket_new( udp : Bool ) : SocketHandle { return null; } + @:hlNative("std", "socket_close") static function socket_close( s : SocketHandle ) : Void { } + @:hlNative("std", "socket_connect") static function socket_connect( s : SocketHandle, host : Int, port : Int ) : Bool { return true; } + @:hlNative("std", "socket_listen") static function socket_listen( s : SocketHandle, count : Int ) : Bool { return true; } + @:hlNative("std", "socket_bind") static function socket_bind( s : SocketHandle, host : Int, port : Int ) : Bool { return true; } + @:hlNative("std", "socket_accept") static function socket_accept( s : SocketHandle ) : SocketHandle { return null; } + @:hlNative("std", "socket_peer") static function socket_peer( s : SocketHandle, host : hl.Ref, port : hl.Ref ) : Bool { return true; } + @:hlNative("std", "socket_host") static function socket_host( s : SocketHandle, host : hl.Ref, port : hl.Ref ) : Bool { return true; } + @:hlNative("std", "socket_set_timeout") static function socket_set_timeout( s : SocketHandle, timeout : Float ) : Bool { return true; } + @:hlNative("std", "socket_shutdown") static function socket_shutdown( s : SocketHandle, read : Bool, write : Bool ) : Bool { return true; } + @:hlNative("std", "socket_set_blocking") static function socket_set_blocking( s : SocketHandle, b : Bool ) : Bool { return true; } + @:hlNative("std", "socket_set_fast_send") static function socket_set_fast_send( s : SocketHandle, b : Bool ) : Bool { return true; } + + @:hlNative("std", "socket_fd_size") static function socket_fd_size( count : Int) : Int { return 0; } + @:hlNative("std", "socket_select") static function socket_select( read : hl.NativeArray, write : hl.NativeArray, other : hl.NativeArray, tmpData : hl.Bytes, tmpSize : Int, timeout : Float ) : Bool { return false; } + +} diff --git a/std/hl/_std/sys/ssl/Certificate.hx b/std/hl/_std/sys/ssl/Certificate.hx new file mode 100644 index 00000000..b2db5575 --- /dev/null +++ b/std/hl/_std/sys/ssl/Certificate.hx @@ -0,0 +1,130 @@ +package sys.ssl; +import sys.ssl.Lib; + +@:noDoc +typedef CertificatePtr = hl.Abstract<"hl_ssl_cert">; + +@:coreApi +class Certificate { + + var __h : Null; + var __x : CertificatePtr; + + @:allow(sys.ssl.Socket) + function new( x : CertificatePtr, ?h: Null ){ + __x = x; + __h = h; + } + + public static function loadFile( file : String ) : Certificate { + return new Certificate( cert_load_file( @:privateAccess file.toUtf8() ) ); + } + + public static function loadPath( path : String ) : Certificate { + return new Certificate( cert_load_path( @:privateAccess path.toUtf8() ) ); + } + + public static function fromString( str : String ) : Certificate { + return new Certificate( cert_add_pem(null, @:privateAccess str.toUtf8() ) ); + } + + public static function loadDefaults() : Certificate { + var x = cert_load_defaults(); + if ( x != null ) + return new Certificate( x ); + + var defPaths = null; + switch( Sys.systemName() ){ + case "Linux": + defPaths = [ + "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. + "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL + "/etc/ssl/ca-bundle.pem", // OpenSUSE + "/etc/pki/tls/cacert.pem", // OpenELEC + "/etc/ssl/certs", // SLES10/SLES11 + "/system/etc/security/cacerts" // Android + ]; + case "BSD": + defPaths = [ + "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly + "/etc/ssl/cert.pem", // OpenBSD + "/etc/openssl/certs/ca-certificates.crt", // NetBSD + ]; + case "Android": + defPaths = ["/system/etc/security/cacerts"]; + default: + } + if( defPaths != null ){ + for( path in defPaths ){ + if( sys.FileSystem.exists(path) ){ + if( sys.FileSystem.isDirectory(path) ) + return loadPath(path); + else + return loadFile(path); + } + } + } + return null; + } + + public var commonName(get,null) : Null; + public var altNames(get, null) : Array; + public var notBefore(get,null) : Date; + public var notAfter(get,null) : Date; + + function get_commonName() : Null { + return subject("CN"); + } + + function get_altNames() : Array { + var a = cert_get_altnames(__x); + return [for( e in a ) @:privateAccess String.fromUTF8(e)]; + } + + public function subject( field : String ) : Null { + var s = cert_get_subject(__x, @:privateAccess field.toUtf8() ); + return s==null ? null : new String( cast s ); + } + + public function issuer( field : String ) : Null { + var s = cert_get_issuer(__x, @:privateAccess field.toUtf8()); + return s==null ? null : new String( cast s ); + } + + function get_notBefore() : Date { + var a = cert_get_notbefore( __x ); + return new Date( a[0], a[1] - 1, a[2], a[3], a[4], a[5] ); + } + + function get_notAfter() : Date { + var a = cert_get_notafter( __x ); + return new Date( a[0], a[1] - 1, a[2], a[3], a[4], a[5] ); + } + + public function next() : Null { + var n = cert_get_next(__x); + return n == null ? null : new Certificate( n, __h==null ? this : __h ); + } + + public function add( pem : String ) : Void { + cert_add_pem(__x, @:privateAccess pem.toUtf8()); + } + + public function addDER( der : haxe.io.Bytes ) : Void { + cert_add_der(__x, @:privateAccess der.b, @:privateAccess der.length); + } + + @:hlNative("ssl","cert_load_defaults") static function cert_load_defaults() : CertificatePtr { return null; } + @:hlNative("ssl","cert_load_file") static function cert_load_file( file : hl.Bytes ) : CertificatePtr { return null; } + @:hlNative("ssl","cert_load_path") static function cert_load_path( path : hl.Bytes ) : CertificatePtr { return null; } + @:hlNative("ssl","cert_get_subject") static function cert_get_subject( cert : CertificatePtr, obj : hl.Bytes ) : hl.Bytes { return null; } + @:hlNative("ssl","cert_get_issuer") static function cert_get_issuer( cert : CertificatePtr, obj : hl.Bytes ) : hl.Bytes { return null; } + @:hlNative("ssl","cert_get_altnames") static function cert_get_altnames( cert : CertificatePtr ) : hl.NativeArray { return null; } + @:hlNative("ssl","cert_get_notbefore") static function cert_get_notbefore( cert : CertificatePtr ) : hl.NativeArray { return null; } + @:hlNative("ssl","cert_get_notafter") static function cert_get_notafter( cert : CertificatePtr ) : hl.NativeArray { return null; } + @:hlNative("ssl","cert_get_next") static function cert_get_next( cert : CertificatePtr ) : Null { return null; } + @:hlNative("ssl","cert_add_pem") static function cert_add_pem( cert : Null, data : hl.Bytes ) : CertificatePtr { return null; } + @:hlNative("ssl","cert_add_der") static function cert_add_der( cert : Null, data : hl.Bytes, len : Int ) : CertificatePtr { return null; } + + +} diff --git a/std/hl/_std/sys/ssl/Digest.hx b/std/hl/_std/sys/ssl/Digest.hx new file mode 100644 index 00000000..2b121e68 --- /dev/null +++ b/std/hl/_std/sys/ssl/Digest.hx @@ -0,0 +1,27 @@ +package sys.ssl; +import sys.ssl.Lib; + +@:coreApi +class Digest { + + public static function make( data : haxe.io.Bytes, alg : DigestAlgorithm ) : haxe.io.Bytes { + var size = 0; + var b = @:privateAccess dgst_make( data.b, data.length, (alg:String).toUtf8(), size ); + return @:privateAccess new haxe.io.Bytes(b,size); + } + + public static function sign( data : haxe.io.Bytes, privKey : Key, alg : DigestAlgorithm ) : haxe.io.Bytes { + var size = 0; + var b = @:privateAccess dgst_sign( data.b, data.length, privKey.__k, (alg:String).toUtf8(), size ); + return @:privateAccess new haxe.io.Bytes(b,size); + } + + public static function verify( data : haxe.io.Bytes, signature : haxe.io.Bytes, pubKey : Key, alg : DigestAlgorithm ) : Bool{ + return @:privateAccess dgst_verify( data.b, data.length, signature.b, signature.length, pubKey.__k, (alg:String).toUtf8() ); + } + + @:hlNative("ssl","dgst_make") static function dgst_make( data : hl.Bytes, len : Int, alg : hl.Bytes, size : hl.Ref ) : hl.Bytes { return null; } + @:hlNative("ssl","dgst_sign") static function dgst_sign( data : hl.Bytes, len : Int, key : sys.ssl.Key.KeyPtr, alg : hl.Bytes, size : hl.Ref ) : hl.Bytes { return null; } + @:hlNative("ssl","dgst_verify") static function dgst_verify( data : hl.Bytes, dlen : Int, sign : hl.Bytes, slen : Int, key : sys.ssl.Key.KeyPtr, alg : hl.Bytes ) : Bool { return false; } + +} diff --git a/std/hl/_std/sys/ssl/Key.hx b/std/hl/_std/sys/ssl/Key.hx new file mode 100644 index 00000000..1d62628f --- /dev/null +++ b/std/hl/_std/sys/ssl/Key.hx @@ -0,0 +1,36 @@ +package sys.ssl; +import sys.ssl.Lib; + +@:noDoc +typedef KeyPtr = hl.Abstract<"hl_ssl_pkey">; + +@:coreApi +class Key { + + private var __k : KeyPtr; + + private function new( k : KeyPtr ){ + __k = k; + } + + public static function loadFile( file : String, ?isPublic : Bool, ?pass : String ) : Key { + var data = sys.io.File.getBytes( file ); + var start = data.getString(0,11); + if( start == "-----BEGIN " ) + return readPEM( data.toString(), isPublic==true, pass ); + else + return readDER( data, isPublic==true ); + } + + public static function readPEM( data : String, isPublic : Bool, ?pass : String ) : Key { + return new Key( key_from_pem( @:privateAccess data.toUtf8(), isPublic, pass == null ? null : @:privateAccess pass.toUtf8() ) ); + } + + public static function readDER( data : haxe.io.Bytes, isPublic : Bool ) : Key { + return new Key( key_from_der( @:privateAccess data.b, @:privateAccess data.length, isPublic ) ); + } + + @:hlNative("ssl","key_from_pem") static function key_from_pem( data : hl.Bytes, pub : Bool, pass : Null ) : KeyPtr { return null; } + @:hlNative("ssl","key_from_der") static function key_from_der( data : hl.Bytes, len : Int, pub : Bool ) : KeyPtr { return null; } + +} diff --git a/std/hl/_std/sys/ssl/Lib.hx b/std/hl/_std/sys/ssl/Lib.hx new file mode 100644 index 00000000..c501b647 --- /dev/null +++ b/std/hl/_std/sys/ssl/Lib.hx @@ -0,0 +1,10 @@ +package sys.ssl; + +@:noDoc @:keep +class Lib { + static function __init__() : Void{ + ssl_init(); + } + + @:hlNative("ssl","ssl_init") static function ssl_init(){}; +} diff --git a/std/hl/_std/sys/ssl/Socket.hx b/std/hl/_std/sys/ssl/Socket.hx new file mode 100644 index 00000000..70f9f5a6 --- /dev/null +++ b/std/hl/_std/sys/ssl/Socket.hx @@ -0,0 +1,251 @@ +package sys.ssl; +import sys.ssl.Lib; +import sys.ssl.Key.KeyPtr; +import sys.ssl.Certificate.CertificatePtr; +import sys.net.Socket.SocketHandle; + +private typedef ConfigPtr = hl.Abstract<"mbedtls_ssl_config">; +private typedef ContextPtr = hl.Abstract<"mbedtls_ssl_context">; + +@:keep +private class SNICbResult { + public var cert : CertificatePtr; + public var key : KeyPtr; + public function new( cert : Certificate, key : Key ){ + this.cert = @:privateAccess cert.__x; + this.key = @:privateAccess key.__k; + } +} + +private class SocketInput extends haxe.io.Input { + @:allow(sys.ssl.Socket) private var __s : Socket; + + public function new( s : Socket ) { + this.__s = s; + } + + public override function readByte() { + __s.handshake(); + var r = ssl_recv_char( @:privateAccess __s.ssl ); + if( r == -1 ) + throw haxe.io.Error.Blocked; + else if( r < 0 ) + throw new haxe.io.Eof(); + return r; + } + + public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { + __s.handshake(); + var r = ssl_recv( @:privateAccess __s.ssl, @:privateAccess buf.b, pos, len ); + if( r == -1 ) + throw haxe.io.Error.Blocked; + else if( r < 0 ) + throw new haxe.io.Eof(); + return r; + } + + public override function close() { + super.close(); + if( __s != null ) __s.close(); + } + + @:hlNative("ssl","ssl_recv") static function ssl_recv( ssl : ContextPtr, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return -1; } + @:hlNative("ssl","ssl_recv_char") static function ssl_recv_char( ssl : ContextPtr ) : Int { return -1; } +} + +private class SocketOutput extends haxe.io.Output { + @:allow(sys.ssl.Socket) private var __s : Socket; + + public function new( s : Socket ) { + this.__s = s; + } + + public override function writeByte( c : Int ) { + __s.handshake(); + var r = ssl_send_char( @:privateAccess __s.ssl, c); + if( r == -1 ) + throw haxe.io.Error.Blocked; + else if( r < 0 ) + throw new haxe.io.Eof(); + } + + public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int { + __s.handshake(); + var r = ssl_send( @:privateAccess __s.ssl, @:privateAccess buf.b, pos, len); + if( r == -1 ) + throw haxe.io.Error.Blocked; + else if( r < 0 ) + throw new haxe.io.Eof(); + return r; + } + + public override function close() { + super.close(); + if( __s != null ) __s.close(); + } + + @:hlNative("ssl","ssl_send") static function ssl_send( ssl : ContextPtr, bytes : hl.Bytes, pos : Int, len : Int ) : Int { return -1; } + @:hlNative("ssl","ssl_send_char") static function ssl_send_char( ssl : ContextPtr, c : Int ) : Int { return -1; } + +} + +@:coreApi @:access(sys.net.Socket) +class Socket extends sys.net.Socket { + + public static var DEFAULT_VERIFY_CERT : Null = true; + + public static var DEFAULT_CA : Null; + + private var conf : ConfigPtr; + private var ssl : ContextPtr; + + public var verifyCert : Null; + private var caCert : Null; + private var hostname : String; + + private var ownCert : Null; + private var ownKey : Null; + private var altSNIContexts : NullBool, key: Key, cert: Certificate}>>; + private var sniCallback : hl.Bytes -> SNICbResult; + private var handshakeDone : Bool; + + private override function init() : Void { + __s = sys.net.Socket.socket_new( false ); + input = new SocketInput( this ); + output = new SocketOutput( this ); + if( DEFAULT_VERIFY_CERT && DEFAULT_CA == null ){ + try { + DEFAULT_CA = Certificate.loadDefaults(); + }catch( e : Dynamic ){} + } + verifyCert = DEFAULT_VERIFY_CERT; + caCert = DEFAULT_CA; + } + + public override function connect(host : sys.net.Host, port : Int) : Void { + conf = buildConfig( false ); + ssl = ssl_new( conf ); + ssl_set_socket( ssl, __s ); + handshakeDone = false; + if( hostname == null ) + hostname = host.host; + if( hostname != null ) + ssl_set_hostname( ssl, @:privateAccess hostname.toUtf8() ); + if( !sys.net.Socket.socket_connect( __s, host.ip, port ) ) + throw new Sys.SysError("Failed to connect on "+host.toString()+":"+port); + handshake(); + } + + public function handshake() : Void { + if( !handshakeDone ){ + var r = ssl_handshake( ssl ); + if( r == 0 ) + handshakeDone = true; + else if( r == -1 ) + throw haxe.io.Error.Blocked; + else + throw new haxe.io.Eof(); + } + } + + public function setCA( cert : Certificate ) : Void { + caCert = cert; + } + + public function setHostname( name : String ) : Void { + hostname = name; + } + + public function setCertificate( cert : Certificate, key : Key ) : Void { + ownCert = cert; + ownKey = key; + } + + public override function close() : Void { + if( ssl != null ) ssl_close( ssl ); + if( conf != null ) conf_close( conf ); + if( altSNIContexts != null ) + sniCallback = null; + sys.net.Socket.socket_close( __s ); + var input : SocketInput = cast input; + var output : SocketOutput = cast output; + @:privateAccess input.__s = output.__s = null; + input.close(); + output.close(); + } + + public function addSNICertificate( cbServernameMatch : String->Bool, cert : Certificate, key : Key ) : Void { + if( altSNIContexts == null ) + altSNIContexts = []; + altSNIContexts.push( {match: cbServernameMatch, cert: cert, key: key} ); + } + + public override function bind( host : sys.net.Host, port : Int ) : Void { + conf = buildConfig( true ); + + sys.net.Socket.socket_bind( __s, host.ip, port ); + } + + public override function accept() : Socket { + var c = sys.net.Socket.socket_accept( __s ); + var cssl = ssl_new( conf ); + ssl_set_socket( cssl, c ); + + var s = Type.createEmptyInstance( sys.ssl.Socket ); + s.__s = c; + s.ssl = cssl; + s.input = new SocketInput(s); + s.output = new SocketOutput(s); + s.handshakeDone = false; + + return s; + } + + public function peerCertificate() : sys.ssl.Certificate { + var x = ssl_get_peer_certificate( ssl ); + return x==null ? null : new sys.ssl.Certificate( x ); + } + + private function buildConfig( server : Bool ) : ConfigPtr { + var conf = conf_new( server ); + + if( ownCert != null && ownKey != null ) + conf_set_cert( conf, @:privateAccess ownCert.__x, @:privateAccess ownKey.__k ); + + if ( altSNIContexts != null ) { + sniCallback = function(servername:hl.Bytes) : SNICbResult { + var servername = @:privateAccess String.fromUTF8(servername); + for( c in altSNIContexts ){ + if( c.match(servername) ) + return new SNICbResult(c.cert, c.key); + } + if( ownKey != null && ownCert != null ) + return new SNICbResult(ownCert, ownKey); + return null; + } + conf_set_servername_callback( conf, sniCallback ); + } + + if ( caCert != null ) + conf_set_ca( conf, caCert == null ? null : @:privateAccess caCert.__x ); + conf_set_verify( conf, if( verifyCert ) 1 else if( verifyCert==null ) 2 else 0 ); + + return conf; + } + + + @:hlNative("ssl","ssl_new") static function ssl_new( conf : ConfigPtr ) : ContextPtr { return null; } + @:hlNative("ssl","ssl_close") static function ssl_close( ssl : ContextPtr ) : Void {} + @:hlNative("ssl","ssl_handshake") static function ssl_handshake( ssl : ContextPtr ) : Int { return -1; } + @:hlNative("ssl","ssl_set_socket") static function ssl_set_socket( ssl : ContextPtr, socket : SocketHandle ) : Void { } + @:hlNative("ssl","ssl_set_hostname") static function ssl_set_hostname( ssl : ContextPtr, name : hl.Bytes ) : Void { } + @:hlNative("ssl","ssl_get_peer_certificate") static function ssl_get_peer_certificate( ssl : ContextPtr ) : CertificatePtr { return null; } + + @:hlNative("ssl","conf_new") static function conf_new( server : Bool ) : ConfigPtr { return null; } + @:hlNative("ssl","conf_close") static function conf_close( conf : ConfigPtr ) : Void { } + @:hlNative("ssl","conf_set_ca") static function conf_set_ca( conf : ConfigPtr, ca : CertificatePtr ) : Void { } + @:hlNative("ssl","conf_set_verify") static function conf_set_verify( conf : ConfigPtr, mode : Int ) : Void { } + @:hlNative("ssl","conf_set_cert") static function conf_set_cert( conf : ConfigPtr, cert : CertificatePtr, pkey : KeyPtr ) : Void { } + @:hlNative("ssl","conf_set_servername_callback") static function conf_set_servername_callback( conf : ConfigPtr, cb : hl.Bytes -> SNICbResult ) : Void { } + +} diff --git a/std/hl/types/ArrayBase.hx b/std/hl/types/ArrayBase.hx new file mode 100644 index 00000000..1683850f --- /dev/null +++ b/std/hl/types/ArrayBase.hx @@ -0,0 +1,146 @@ +/* + * Copyright (C)2005-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 hl.types; + +@:keep +class ArrayAccess { + + public function getDyn( pos : Int ) : Dynamic { + throw "Not implemented"; + return 0; + } + + public function setDyn( pos : Int, v : Dynamic ) { + throw "Not implemented"; + } + + public function blit( pos : Int, src : ArrayAccess, srcpos : Int, len : Int ) : Void { + throw "Not implemented"; + } + +} + +@:keep +class ArrayBase extends ArrayAccess { + + public var length(default,null) : Int; + + + public function pushDyn( v : Dynamic ) : Int { + throw "Not implemented"; + return 0; + } + + public function popDyn() : Null { + throw "Not implemented"; + return null; + } + + public function shiftDyn() : Null { + throw "Not implemented"; + return null; + } + + public function unshiftDyn( v : Dynamic ) : Void { + throw "Not implemented"; + } + + public function insertDyn( pos : Int, v : Dynamic ) : Void { + throw "Not implemented"; + } + + public function removeDyn( v : Dynamic ) : Bool { + throw "Not implemented"; + return false; + } + + public function sortDyn( f : Dynamic -> Dynamic -> Int ) : Void { + throw "Not implemented"; + } + + public function slice( pos : Int, ?end : Int ) : ArrayBase{ + throw "Not implemented"; + return null; + } + + public function splice( pos : Int, len : Int ) : ArrayBase{ + throw "Not implemented"; + return null; + } + + public function join( sep : String ) : String { + throw "Not implemented"; + return null; + } + + public function reverse() { + throw "Not implemented"; + } + + public function toString() : String { + throw "Not implemented"; + return null; + } + + function __cast( t : Type ) : Dynamic { + if( t == Type.get(new ArrayDyn()) ) + return ArrayDyn.alloc(this, false); + return null; + } + + function isArrayObj() { + return false; + } + + public static function allocI32( bytes : BytesAccess, length : Int ) @:privateAccess { + var a : ArrayBytes.ArrayI32 = untyped $new(ArrayBytes.ArrayI32); + a.length = length; + a.bytes = bytes; + a.size = length; + return a; + } + + public static function allocUI16( bytes : BytesAccess, length : Int ) @:privateAccess { + var a : ArrayBytes.ArrayUI16 = untyped $new(ArrayBytes.ArrayUI16); + a.length = length; + a.bytes = bytes; + a.size = length; + return a; + } + + public static function allocF32( bytes : BytesAccess, length : Int ) @:privateAccess { + var a : ArrayBytes.ArrayF32 = untyped $new(ArrayBytes.ArrayF32); + a.length = length; + a.bytes = bytes; + a.size = length; + return a; + } + + public static function allocF64( bytes : BytesAccess, length : Int ) @:privateAccess { + var a : ArrayBytes.ArrayF64 = untyped $new(ArrayBytes.ArrayF64); + a.length = length; + a.bytes = bytes; + a.size = length; + return a; + } + +} diff --git a/std/hl/types/ArrayBytes.hx b/std/hl/types/ArrayBytes.hx new file mode 100644 index 00000000..197434fd --- /dev/null +++ b/std/hl/types/ArrayBytes.hx @@ -0,0 +1,304 @@ +/* + * Copyright (C)2005-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 hl.types; + +@:keep +@:generic +class BytesIterator { + var pos : Int; + var a : ArrayBytes; + public function new(a) { + this.a = a; + } + public function hasNext() { + return pos < a.length; + } + public function next() : T { + return @:privateAccess a.bytes.get(pos++); + } +} + +@:keep +@:generic class ArrayBytes extends ArrayBase { + + var bytes : hl.BytesAccess; + var size : Int; + + public function new() { + size = length = 0; + bytes = null; + } + + public function concat( a : ArrayBytes ) : ArrayBytes { + var ac = new ArrayBytes(); + ac.length = ac.size = length + a.length; + ac.bytes = new Bytes(ac.length << bytes.sizeBits); + var offset = length << bytes.sizeBits; + (ac.bytes:Bytes).blit(0, this.bytes, 0, offset); + (ac.bytes:Bytes).blit(offset, a.bytes, 0, a.length << bytes.sizeBits); + return ac; + } + + override function join( sep : String ) : String { + var s = new StringBuf(); + for( i in 0...length ) { + if( i > 0 ) s.add(sep); + s.add(bytes[i]); + } + return s.toString(); + } + + public function pop() : Null { + if( length == 0 ) + return null; + length--; + return bytes[length]; + } + + public function push(x : T) : Int { + var len = length; + if( size == len ) + __expand(len); + else + length++; + bytes[len] = x; + return length; + } + + override function reverse() : Void { + for( i in 0...length >> 1 ) { + var k = length - 1 - i; + var tmp = bytes[i]; + bytes[i] = bytes[k]; + bytes[k] = tmp; + } + } + + public function shift() : Null { + if( length == 0 ) + return null; + var v = bytes[0]; + length--; + (bytes:Bytes).blit(0, bytes, 1 << bytes.sizeBits, length << bytes.sizeBits); + return v; + } + + override function blit( pos : Int, src : ArrayBase.ArrayAccess, srcpos : Int, len : Int ) : Void { + var src = (cast src : ArrayBytes); + if( pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length ) throw haxe.io.Error.OutsideBounds; + (bytes:Bytes).blit(pos << bytes.sizeBits,src.bytes,srcpos< { + if( pos < 0 ) { + pos = this.length + pos; + if( pos < 0 ) + pos = 0; + } + var pend : Int; + if( end == null ) + pend = this.length; + else { + pend = end; + if( pend < 0 ) + pend += this.length; + if( pend > this.length ) + pend = this.length; + } + var len = pend - pos; + if( len < 0 ) + return new ArrayBytes(); + var a = new ArrayBytes(); + a.length = a.size = len; + a.bytes = (bytes:Bytes).sub(pos << bytes.sizeBits, len << bytes.sizeBits); + return a; + } + + public function sort( f : T -> T -> Int ) : Void { + if( Type.get((cast null : T)) == Type.get(0) ) + (bytes:Bytes).sortI32(0, length, cast f); + else + (bytes:Bytes).sortF64(0, length, cast f); + } + + override function splice( pos : Int, len : Int ) : ArrayBytes { + if( len < 0 ) + return new ArrayBytes(); + if( pos < 0 ){ + pos = this.length + pos; + if( pos < 0 ) pos = 0; + } + if( pos > this.length ) { + pos = 0; + len = 0; + } else if( pos + len > this.length ) { + len = this.length - pos; + if( len < 0 ) len = 0; + } + if( len == 0 ) + return new ArrayBytes(); + var ret = new ArrayBytes(); + ret.bytes = (bytes:Bytes).sub(pos << bytes.sizeBits, len << bytes.sizeBits); + ret.size = ret.length = len; + var end = pos + len; + (bytes:Bytes).blit(pos << bytes.sizeBits, bytes, end << bytes.sizeBits, (length - end) << bytes.sizeBits); + length -= len; + return ret; + } + + override function toString() : String { + var b = new StringBuf(); + b.addChar("[".code); + for( i in 0...length ) { + if( i > 0 ) b.addChar(",".code); + b.add(bytes[i]); + } + b.addChar("]".code); + return b.toString(); + } + + public function unshift( x : T ) : Void { + if( length == size ) __expand(length) else length++; + (bytes:Bytes).blit(1< length ) pos = length; + if( length == size ) __expand(length) else length++; + (bytes:Bytes).blit((pos + 1)<= len ) + i = len - 1; + else if( i < 0 ) + i += len; + while( i >= 0 ) { + if( bytes[i] == x ) + return i; + i--; + } + return -1; + } + + public function copy() : ArrayBytes { + var a = new ArrayBytes(); + a.length = a.size = length; + a.bytes = new Bytes(length << bytes.sizeBits); + (a.bytes:Bytes).blit(0, bytes, 0, length << bytes.sizeBits); + return a; + } + + public function iterator() : Iterator { + return new BytesIterator(this); + } + + public function map( f : T -> S ) : ArrayDyn @:privateAccess { + var a = new ArrayObj(); + if( length > 0 ) a.__expand(length - 1); + for( i in 0...length ) + a.array[i] = f(bytes[i]); + return ArrayDyn.alloc(a,true); + } + + public function filter( f : T -> Bool ) : ArrayBytes { + var a = new ArrayBytes(); + for( i in 0...length ) { + var v = bytes[i]; + if( f(v) ) a.push(v); + } + return a; + } + + override function getDyn( pos : Int ) : Dynamic { + var pos : UInt = pos; + if( pos >= length ) + return bytes.nullValue; + return bytes[pos]; + } + + override function setDyn( pos : Int, v : Dynamic ) { + var pos : UInt = pos; + if( pos >= length ) + __expand(pos); + bytes[pos] = v; + } + + override function pushDyn( v : Dynamic ) return push(v); + override function popDyn() : Null return pop(); + override function shiftDyn() : Null return shift(); + override function unshiftDyn( v : Dynamic ) unshift(v); + override function insertDyn( pos : Int, v : Dynamic ) insert(pos, v); + override function removeDyn( v : Dynamic ) return remove(v); + override function sortDyn( f : Dynamic -> Dynamic -> Int ) sort(f); + + // called by compiler when accessing the array outside of its bounds, might trigger resize + function __expand( index : Int ) { + if( index < 0 ) throw "Invalid array index "+index; + var newlen = index + 1; + if( newlen > size ) { + var next = (size * 3) >> 1; + if( next < newlen ) next = newlen; + var bytes2 = new hl.Bytes(next << bytes.sizeBits); + var bsize = length << bytes.sizeBits; + bytes2.blit(0, bytes, 0, bsize); + bytes2.fill(bsize, (next << bytes.sizeBits) - bsize, 0); + bytes = bytes2; + size = next; + } + length = newlen; + } + +} + +typedef ArrayI32 = ArrayBytes; +typedef ArrayUI16 = ArrayBytes; +typedef ArrayF32 = ArrayBytes; +typedef ArrayF64 = ArrayBytes; diff --git a/std/hl/types/ArrayDyn.hx b/std/hl/types/ArrayDyn.hx new file mode 100644 index 00000000..f0b20306 --- /dev/null +++ b/std/hl/types/ArrayDyn.hx @@ -0,0 +1,223 @@ +/* + * Copyright (C)2005-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 hl.types; +import hl.types.ArrayBase; + +class ArrayDynIterator { + var a : ArrayBase; + var len : Int; + var pos : Int; + public function new(a) { + this.a = a; + this.len = a.length; + this.pos = 0; + } + public function hasNext() { + return pos < len; + } + public function next() { + return a.getDyn(pos++); + } +} + +@:keep +class ArrayDyn extends ArrayAccess { + + public var length(get,never) : Int; + var array : ArrayBase; + var allowReinterpret : Bool; + + public function new() { + array = new ArrayObj(); + allowReinterpret = true; + } + + inline function get_length() return array.length; + + override function getDyn(i) { + return array.getDyn(i); + } + + override function setDyn(pos:Int, value:Dynamic) { + array.setDyn(pos, value); + } + + override function blit( pos : Int, src : ArrayAccess, srcpos : Int, len : Int ) : Void { + array.blit(pos, src, srcpos, len); + } + + public function concat( a : ArrayDyn ) : ArrayDyn { + var a1 = array; + var a2 = a.array; + var alen = a1.length; + var anew = new NativeArray(alen + a2.length); + for( i in 0...alen ) + anew[i] = a1.getDyn(i); + for( i in 0...a2.length ) + anew[i+alen] = a2.getDyn(i); + return alloc(ArrayObj.alloc(anew),true); + } + + public function join( sep : String ) : String { + return array.join(sep); + } + + public function pop() : Null { + return array.popDyn(); + } + + public function push(x : Dynamic) : Int { + return array.pushDyn(x); + } + + public function reverse() : Void { + array.reverse(); + } + + public function shift() : Null { + return array.shiftDyn(); + } + + public function slice( pos : Int, ?end : Int ) : ArrayDyn { + return alloc(array.slice(pos,end),true); + } + + public function sort( f : Dynamic -> Dynamic -> Int ) : Void { + array.sortDyn(f); + } + + public function splice( pos : Int, len : Int ) : ArrayDyn { + return alloc(array.splice(pos,len),true); + } + + public function toString() : String { + return array.toString(); + } + + public function unshift( x : Dynamic ) : Void { + array.unshiftDyn(x); + } + + public function insert( pos : Int, x : Dynamic ) : Void { + array.insertDyn(pos,x); + } + + public function remove( x : Dynamic ) : Bool { + return array.removeDyn(x); + } + + public function indexOf( x : Dynamic, ?fromIndex:Int ) : Int { + var i : Int = fromIndex; + var length = length; + var array = array; + while( i < length ) { + if( array.getDyn(i) == x ) + return i; + i++; + } + return -1; + } + + public function lastIndexOf( x : Dynamic, ?fromIndex:Int ) : Int { + var len = length; + var i:Int = fromIndex != null ? fromIndex : len - 1; + if( i >= len ) + i = len - 1; + else if( i < 0 ) + i += len; + while( i >= 0 ) { + if( array.getDyn(i) == x ) + return i; + i--; + } + return -1; + } + + public function copy() : ArrayDyn { + var a = new NativeArray(length); + for( i in 0...length ) + a[i] = array.getDyn(i); + return alloc(ArrayObj.alloc(a),true); + } + + public function iterator() : Iterator { + return new ArrayDynIterator(array); + } + + public function map( f : Dynamic -> Dynamic ) : ArrayDyn { + var a = new NativeArray(length); + for( i in 0...length ) + a[i] = f(array.getDyn(i)); + return alloc(ArrayObj.alloc(a),true); + } + + public function filter( f : Dynamic -> Bool ) : ArrayDyn { + var a = new ArrayObj(); + for( i in 0...length ) { + var v = array.getDyn(i); + if( f(v) ) a.push(v); + } + return alloc(a,true); + } + + function __get_field( fid : Int ) : Dynamic { + if( fid == untyped $hash("length") ) + return length; + return null; + } + + function __cast( t : Type ) : Dynamic { + if( t == Type.getDynamic(array) ) + return array; + if( !allowReinterpret ) + return null; + if( t == Type.get(new ArrayBytes.ArrayI32()) ) { + var a : BytesAccess = null; + a = new Bytes(array.length << a.sizeBits); + for( i in 0...array.length ) + a[i] = array.getDyn(i); + var arr = ArrayBase.allocI32(a, array.length); + array = arr; + allowReinterpret = false; + return arr; + } + if( t == Type.get(new ArrayBytes.ArrayF64()) ) { + var a : BytesAccess = null; + a = new Bytes(array.length << a.sizeBits); + for( i in 0...array.length ) + a[i] = array.getDyn(i); + var arr = ArrayBase.allocF64(a, array.length); + array = arr; + allowReinterpret = false; + return arr; + } + return null; + } + + public static function alloc( a : ArrayBase, allowReinterpret = false ) : ArrayDyn { + var arr : ArrayDyn = untyped $new(ArrayDyn); + arr.array = a; + arr.allowReinterpret = allowReinterpret; + return arr; + } + +} diff --git a/std/hl/types/ArrayObj.hx b/std/hl/types/ArrayObj.hx new file mode 100644 index 00000000..de36c3eb --- /dev/null +++ b/std/hl/types/ArrayObj.hx @@ -0,0 +1,288 @@ +/* + * Copyright (C)2005-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 hl.types; + +@:keep +class ArrayObj extends ArrayBase { + + var array : hl.NativeArray; + + public function new() { + length = 0; + array = new NativeArray(0); + } + + public function concat( a : ArrayObj ) : ArrayObj { + var arr = new hl.NativeArray(length + a.length); + arr.blit(0, array, 0, length); + arr.blit(length, a.array, 0, a.length); + return alloc(cast arr); + } + + override function join( sep : String ) : String { + var b = new StringBuf(); + for( i in 0...length ) { + if( i > 0 ) b.add(sep); + b.add(array[i]); + } + return b.toString(); + } + + override function isArrayObj() { + return true; + } + + public function pop() : Null { + if( length == 0 ) + return null; + length--; + var v = array[length]; + array[length] = null; + return v; + } + + public function push(x : T) : Int { + var len = length; + if( array.length == len ) + __expand(len); + else + length++; + array[len] = x; + return length; + } + + override function reverse() : Void { + for( i in 0...length >> 1 ) { + var k = length - 1 - i; + var tmp = array[i]; + array[i] = array[k]; + array[k] = tmp; + } + } + + public function shift() : Null { + if( length == 0 ) + return null; + length--; + var v = array[0]; + array.blit(0, array, 1, length); + array[length] = null; + return v; + } + + override function slice( pos : Int, ?end : Int ) : ArrayObj { + if( pos < 0 ) { + pos = this.length + pos; + if( pos < 0 ) + pos = 0; + } + var pend : Int; + if( end == null ) + pend = this.length; + else { + pend = end; + if( pend < 0 ) + pend += this.length; + if( pend > this.length ) + pend = this.length; + } + var len = pend - pos; + if( len < 0 ) + return new ArrayObj(); + return alloc(array.sub(pos,len)); + } + + public function sort( f : T -> T -> Int ) : Void { + // TODO : use native call ? + haxe.ds.ArraySort.sort(cast this, f); + } + + override function splice( pos : Int, len : Int ) : ArrayObj { + if( len < 0 ) return new ArrayObj(); + if( pos < 0 ){ + pos = this.length + pos; + if( pos < 0 ) pos = 0; + } + if( pos > this.length ) { + pos = 0; + len = 0; + } else if( pos + len > this.length ) { + len = this.length - pos; + if( len < 0 ) len = 0; + } + var a = this.array; + var ret : ArrayObj = alloc(cast a.sub(pos,len)); + var end = pos + len; + a.blit(pos,a,end,this.length-end); + this.length -= len; + while( --len >= 0 ) + a[this.length + len] = null; + return ret; + } + + override function toString() : String { + var b = new StringBuf(); + b.addChar("[".code); + for( i in 0...length ) { + if( i > 0 ) b.addChar(",".code); + b.add(array[i]); + } + b.addChar("]".code); + return b.toString(); + } + + public function unshift( x : T ) : Void { + if( length == array.length ) __expand(length) else length++; + array.blit(1, array, 0, length - 1); + array[0] = x; + } + + public function insert( pos : Int, x : T ) : Void { + if( pos < 0 ) { + pos = length + pos; + if( pos < 0 ) pos = 0; + } else if( pos > length ) pos = length; + if( length == array.length ) __expand(length) else length++; + array.blit(pos + 1, array, pos, length - pos - 1); + array[pos] = x; + } + + public function remove( x : T ) : Bool { + var i = indexOf(x); + if( i < 0 ) return false; + length--; + array.blit(i,array,i+1,length - i); + array[length] = null; + return true; + } + + public function indexOf( x : T, ?fromIndex:Int ) : Int { + var i : Int = fromIndex; + if( i < 0 ) { + i += length; + if( i < 0 ) i = 0; + } + var length = length; + var array = array; + while( i < length ) { + if( array[i] == x ) + return i; + i++; + } + return -1; + } + + override function blit( pos : Int, src : ArrayBase.ArrayAccess, srcpos : Int, len : Int ) : Void { + var src = (cast src : ArrayObj); + if( pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length ) throw haxe.io.Error.OutsideBounds; + array.blit(pos, src.array, srcpos, len); + } + + public function lastIndexOf( x : T, ?fromIndex:Int ) : Int { + var len = length; + var i:Int = fromIndex != null ? fromIndex : len - 1; + if( i >= len ) + i = len - 1; + else if( i < 0 ) + i += len; + while( i >= 0 ) { + if( array[i] == x ) + return i; + i--; + } + return -1; + } + + public function copy() : ArrayObj { + var n = new NativeArray(length); + n.blit(0, array, 0, length); + return alloc(n); + } + + public function iterator() : Iterator { + var n = new NativeArray.NativeArrayIterator(cast array); + @:privateAccess n.length = length; + return n; + } + + public function map( f : T -> S ) : ArrayDyn { + var a = new ArrayObj(); + if( length > 0 ) a.__expand(length - 1); + for( i in 0...length ) + a.array[i] = f(array[i]); + return ArrayDyn.alloc(a,true); + } + + public function filter( f : T -> Bool ) : ArrayObj { + var a = new ArrayObj(); + for( i in 0...length ) { + var v = array[i]; + if( f(v) ) a.push(v); + } + return a; + } + + // called by compiler when accessing the array outside of its bounds, might trigger resize + function __expand( index : Int ) { + if( index < 0 ) throw "Invalid array index " + index; + var newlen = index + 1; + var size : Int = array.length; + if( newlen > size ) { + var next = (size * 3) >> 1; + if( next < newlen ) next = newlen; + var arr2 = new hl.NativeArray(next); + arr2.blit(0,array,0,length); + array = arr2; + } + length = newlen; + } + + override function getDyn( pos : Int ) : Dynamic { + var pos : UInt = pos; + if( pos >= length ) + return null; + return array[pos]; + } + + override function setDyn( pos : Int, v : Dynamic ) { + var pos : UInt = pos; + if( pos >= length ) + __expand(pos); + array[pos] = Api.safeCast(v,array.getType()); + } + + override function pushDyn( v : Dynamic ) return push(v); + override function popDyn() : Null return pop(); + override function shiftDyn() : Null return shift(); + override function unshiftDyn( v : Dynamic ) unshift(v); + override function insertDyn( pos : Int, v : Dynamic ) insert(pos, v); + override function removeDyn( v : Dynamic ) return remove(v); + override function sortDyn( f : Dynamic -> Dynamic -> Int ) sort(f); + + public static function alloc( a : hl.NativeArray ) : ArrayObj { + var arr : ArrayObj = untyped $new(ArrayObj); + arr.array = a; + arr.length = a.length; + return arr; + } + +} diff --git a/std/hl/types/BytesMap.hx b/std/hl/types/BytesMap.hx new file mode 100644 index 00000000..ea947d91 --- /dev/null +++ b/std/hl/types/BytesMap.hx @@ -0,0 +1,69 @@ +/* + * Copyright (C)2005-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 hl.types; + +typedef BytesMapData = Abstract<"hl_bytes_map">; + +abstract BytesMap(BytesMapData) { + + @:extern public inline function new() { + this = alloc(); + } + + @:hlNative("std","hballoc") static function alloc() : BytesMapData { + return null; + } + + @:hlNative("std","hbset") + public function set( key : Bytes, value : Dynamic ) { + } + + @:hlNative("std","hbexists") + public function exists( key : Bytes ) : Bool { + return false; + } + + @:hlNative("std","hbget") + public function get( key : Bytes ) : Dynamic { + return null; + } + + @:hlNative("std","hbremove") + public function remove( key : Bytes ) : Bool { + return false; + } + + @:hlNative("std","hbkeys") + public function keysArray() : NativeArray { + return null; + } + + @:hlNative("std","hbvalues") + public function valuesArray() : NativeArray { + return null; + } + + @:extern public inline function iterator() { + return new NativeArray.NativeArrayIterator(valuesArray()); + } + +} \ No newline at end of file diff --git a/std/hl/types/IntMap.hx b/std/hl/types/IntMap.hx new file mode 100644 index 00000000..f07674a4 --- /dev/null +++ b/std/hl/types/IntMap.hx @@ -0,0 +1,69 @@ +/* + * Copyright (C)2005-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 hl.types; + +typedef IntMapData = Abstract<"hl_int_map">; + +abstract IntMap(IntMapData) { + + @:extern public inline function new() { + this = alloc(); + } + + @:hlNative("std","hialloc") static function alloc() : IntMapData { + return null; + } + + @:hlNative("std","hiset") + public function set( key : Int, value : Dynamic ) { + } + + @:hlNative("std","hiexists") + public function exists( key : Int ) : Bool { + return false; + } + + @:hlNative("std","higet") + public function get( key : Int ) : Dynamic { + return null; + } + + @:hlNative("std","hiremove") + public function remove( key : Int ) : Bool { + return false; + } + + @:hlNative("std","hikeys") + public function keysArray() : NativeArray { + return null; + } + + @:hlNative("std","hivalues") + public function valuesArray() : NativeArray { + return null; + } + + @:extern public inline function iterator() { + return new NativeArray.NativeArrayIterator(valuesArray()); + } + +} \ No newline at end of file diff --git a/std/hl/types/ObjectMap.hx b/std/hl/types/ObjectMap.hx new file mode 100644 index 00000000..5a342fba --- /dev/null +++ b/std/hl/types/ObjectMap.hx @@ -0,0 +1,69 @@ +/* + * Copyright (C)2005-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 hl.types; + +typedef ObjectMapData = Abstract<"hl_obj_map">; + +abstract ObjectMap(ObjectMapData) { + + @:extern public inline function new() { + this = alloc(); + } + + @:hlNative("std","hoalloc") static function alloc() : ObjectMapData { + return null; + } + + @:hlNative("std","hoset") + public function set( key : Dynamic, value : Dynamic ) { + } + + @:hlNative("std","hoexists") + public function exists( key : Dynamic ) : Bool { + return false; + } + + @:hlNative("std","hoget") + public function get( key : Dynamic ) : Dynamic { + return null; + } + + @:hlNative("std","horemove") + public function remove( key : Dynamic ) : Bool { + return false; + } + + @:hlNative("std","hokeys") + public function keysArray() : NativeArray { + return null; + } + + @:hlNative("std","hovalues") + public function valuesArray() : NativeArray { + return null; + } + + @:extern public inline function iterator() { + return new NativeArray.NativeArrayIterator(valuesArray()); + } + +} \ No newline at end of file diff --git a/std/java/Boot.hx b/std/java/Boot.hx index 24d4197c..3dc116a8 100644 --- a/std/java/Boot.hx +++ b/std/java/Boot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,7 +24,8 @@ import java.internal.Exceptions; import java.internal.Function; import java.internal.HxObject; import java.internal.Runtime; -import java.internal.Iterator; +// TODO (see Gencommon.IteratorsInterfaceModf) +//import java.internal.Iterator; import java.Lib; //import java.internal.StringExt; import java.StdTypes; @@ -45,6 +46,7 @@ import java.lang.Throwable; import java.internal.StringExt; import java.internal.FieldLookup; +@:dox(hide) extern class Boot { diff --git a/std/java/Lib.hx b/std/java/Lib.hx index b7aa3a89..06a8e84c 100644 --- a/std/java/Lib.hx +++ b/std/java/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -23,7 +23,7 @@ package java; /** Platform-specific Java Library. Provides some platform-specific functions for the Java target, - such as conversion from haxe types to native types and vice-versa. + such as conversion from Haxe types to native types and vice-versa. **/ //we cannot use the java package for custom classes, so we're redefining it as "haxe.java.Lib" @:native('haxe.java.Lib') class Lib @@ -33,7 +33,7 @@ package java; Returns a native array from the supplied Array. This native array is unsafe to be written on, as it may or may not be linked to the actual Array implementation. - If equalLengthRequired is true, the result might be a copy of an array with the correct size. + If `equalLengthRequired` is true, the result might be a copy of an array with the correct size. **/ inline public static function nativeArray(arr:Array, equalLengthRequired:Bool):NativeArray { diff --git a/std/java/NativeArray.hx b/std/java/NativeArray.hx index 14b153ac..c427450b 100644 --- a/std/java/NativeArray.hx +++ b/std/java/NativeArray.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/StdTypes.hx b/std/java/StdTypes.hx index b03e7e95..8d39212e 100644 --- a/std/java/StdTypes.hx +++ b/std/java/StdTypes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,10 +21,10 @@ */ package java; -@:notNull @:runtimeValue @:coreType abstract Int8 from Int {} -@:notNull @:runtimeValue @:coreType abstract Int16 from Int {} -@:notNull @:runtimeValue @:coreType abstract Char16 from Int {} -@:notNull @:runtimeValue @:coreType abstract Int64 from Int from Float +@:notNull @:runtimeValue @:coreType extern abstract Int8 from Int {} +@:notNull @:runtimeValue @:coreType extern abstract Int16 from Int {} +@:notNull @:runtimeValue @:coreType extern abstract Char16 from Int {} +@:notNull @:runtimeValue @:coreType extern abstract Int64 from Int from Float { @:op(A+B) public static function addI(lhs:Int64, rhs:Int):Int64; @:op(A+B) public static function add(lhs:Int64, rhs:Int64):Int64; diff --git a/std/java/_std/Array.hx b/std/java/_std/Array.hx index 1dd1113c..cac869ea 100644 --- a/std/java/_std/Array.hx +++ b/std/java/_std/Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/Date.hx b/std/java/_std/Date.hx index a16b5550..03609efc 100644 --- a/std/java/_std/Date.hx +++ b/std/java/_std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/EReg.hx b/std/java/_std/EReg.hx index e8a0964d..7f13c9a7 100644 --- a/std/java/_std/EReg.hx +++ b/std/java/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/Math.hx b/std/java/_std/Math.hx index 6f159c06..13f44871 100644 --- a/std/java/_std/Math.hx +++ b/std/java/_std/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/Reflect.hx b/std/java/_std/Reflect.hx index a0e77934..a9395fd6 100644 --- a/std/java/_std/Reflect.hx +++ b/std/java/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,7 +25,7 @@ import java.internal.HxObject; import java.internal.Runtime; import java.Boot; -@:keep @:coreApi class Reflect { +@:coreApi class Reflect { public static function hasField( o : Dynamic, field : String ) : Bool { @@ -35,6 +35,7 @@ import java.Boot; return Runtime.slowHasField(o, field); } + @:keep public static function field( o : Dynamic, field : String ) : Dynamic { if (Std.is(o, IHxObject)) { @@ -43,6 +44,7 @@ import java.Boot; return Runtime.slowGetField(o, field, false); } + @:keep public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void { if (Std.is(o, IHxObject)) { @@ -79,6 +81,7 @@ import java.Boot; return untyped (func : Function).__hx_invokeDynamic(args); } + @:keep public static function fields( o : Dynamic ) : Array { if (Std.is(o, IHxObject)) { diff --git a/std/java/_std/Std.hx b/std/java/_std/Std.hx index b1fff425..4556baf2 100644 --- a/std/java/_std/Std.hx +++ b/std/java/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -57,7 +57,7 @@ import java.internal.Exceptions; return cast(s, String) + ""; } - public static inline function int( x : Float ) : Int { + public static function int( x : Float ) : Int { return cast x; } diff --git a/std/java/_std/String.hx b/std/java/_std/String.hx index 76a176d9..c51ee32a 100644 --- a/std/java/_std/String.hx +++ b/std/java/_std/String.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/StringBuf.hx b/std/java/_std/StringBuf.hx index c1285104..bb03d30a 100644 --- a/std/java/_std/StringBuf.hx +++ b/std/java/_std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/Sys.hx b/std/java/_std/Sys.hx index 3e0eba06..dde0f251 100644 --- a/std/java/_std/Sys.hx +++ b/std/java/_std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -112,11 +112,29 @@ using haxe.Int64; public static function command( cmd : String, ?args : Array ) : Int { - var proc:Process = new Process(cmd, args == null ? [] : args); - var ret = proc.exitCode(); - proc.close(); - - return ret; + var pb = Process.createProcessBuilder(cmd, args); +#if java6 + pb.redirectErrorStream(true); +#else + pb.redirectOutput(java.lang.ProcessBuilder.ProcessBuilder_Redirect.INHERIT); + pb.redirectError(java.lang.ProcessBuilder.ProcessBuilder_Redirect.INHERIT); +#end + var proc = pb.start(); +#if java6 + var reader = new java.io.NativeInput(proc.getInputStream()); + try + { + while(true) { + var ln = reader.readLine(); + Sys.println(ln); + } + } + catch(e:haxe.io.Eof) {} +#end + proc.waitFor(); + var exitCode = proc.exitValue(); + proc.destroy(); + return exitCode; } public static function exit( code : Int ) : Void @@ -126,7 +144,7 @@ using haxe.Int64; public static function time() : Float { - return cast(System.currentTimeMillis().div(Int64.ofInt(1000)), Float); + return cast(System.currentTimeMillis(), Float) / 1000; } public static function cpuTime() : Float @@ -134,11 +152,18 @@ using haxe.Int64; return cast(System.nanoTime(), Float) / 1000000000; } - public static function executablePath() : String + @:deprecated("Use programPath instead") public static function executablePath() : String { return getCwd(); } + public static function programPath() : String { + return java.Lib.toNativeType(Sys) + .getProtectionDomain() + .getCodeSource() + .getLocation().toURI().getPath(); + } + public static function getChar( echo : Bool ) : Int { //TODO diff --git a/std/java/_std/Type.hx b/std/java/_std/Type.hx index e077e2cf..c92832c0 100644 --- a/std/java/_std/Type.hx +++ b/std/java/_std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,7 +24,7 @@ import java.internal.HxObject; using StringTools; -@:keep enum ValueType { +enum ValueType { TNull; TInt; TFloat; @@ -36,7 +36,7 @@ using StringTools; TUnknown; } -@:keep @:coreApi class Type { +@:coreApi class Type { public static function getClass( o : T ) : Class { @@ -243,11 +243,18 @@ using StringTools; return null; } - public static function createEmptyInstance( cl : Class ) : T untyped - { - if (Reflect.hasField(cl, "__hx_createEmpty")) - return cl.__hx_createEmpty(); - return createInstance(cl, []); + // cache empty constructor arguments so we don't allocate it on each createEmptyInstance call + @:protected @:readOnly static var __createEmptyInstance_EMPTY_TYPES = java.NativeArray.make(java.Lib.toNativeEnum(java.internal.Runtime.EmptyObject)); + @:protected @:readOnly static var __createEmptyInstance_EMPTY_ARGS = java.NativeArray.make(java.internal.Runtime.EmptyObject.EMPTY); + + public static function createEmptyInstance( cl : Class ) : T { + var t = java.Lib.toNativeType(cl); + try { + var ctor = t.getConstructor(__createEmptyInstance_EMPTY_TYPES); + return ctor.newInstance(__createEmptyInstance_EMPTY_ARGS); + } catch (_:java.lang.NoSuchMethodException) { + return t.newInstance(); + } } @:functionCode(' diff --git a/std/java/_std/haxe/Int64.hx b/std/java/_std/haxe/Int64.hx index 602c26eb..5d2d2a54 100644 --- a/std/java/_std/haxe/Int64.hx +++ b/std/java/_std/haxe/Int64.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,6 +22,8 @@ package haxe; using haxe.Int64; +import haxe.Int64Helper; + private typedef __Int64 = java.StdTypes.Int64; @:coreApi @@ -29,7 +31,7 @@ abstract Int64(__Int64) from __Int64 to __Int64 { public static inline function make( high : Int32, low : Int32 ) : Int64 - return new Int64( (cast(high, __Int64) << 32) | (cast(low, __Int64)& untyped __java__('0xffffffffL')) ); + return new Int64( (cast(high, __Int64) << 32) | (cast(low, __Int64)& (untyped __java__('0xffffffffL') : Int64)) ); private inline function new(x : __Int64) this = x; @@ -93,6 +95,15 @@ abstract Int64(__Int64) from __Int64 to __Int64 private inline function toString() : String return '$this'; + public static function parseString( sParam : String ) : Int64 { + // can this be done?: return new Int64( java.lang.Long.LongClass.parseLong( sParam ) ); + return Int64Helper.parseString( sParam ); + } + + public static function fromFloat( f : Float ) : Int64 { + return Int64Helper.fromFloat( f ); + } + @:op(-A) public static function neg( x : Int64 ) : Int64 return -x.val; diff --git a/std/java/_std/haxe/Resource.hx b/std/java/_std/haxe/Resource.hx index 973ba68d..38a24322 100644 --- a/std/java/_std/haxe/Resource.hx +++ b/std/java/_std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/haxe/ds/IntMap.hx b/std/java/_std/haxe/ds/IntMap.hx index 4b5a0d0d..9dc4a85e 100644 --- a/std/java/_std/haxe/ds/IntMap.hx +++ b/std/java/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/haxe/ds/ObjectMap.hx b/std/java/_std/haxe/ds/ObjectMap.hx index 997e4f02..7e7c6c1b 100644 --- a/std/java/_std/haxe/ds/ObjectMap.hx +++ b/std/java/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/haxe/ds/StringMap.hx b/std/java/_std/haxe/ds/StringMap.hx index 12caac8c..ddc81156 100644 --- a/std/java/_std/haxe/ds/StringMap.hx +++ b/std/java/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/haxe/ds/WeakMap.hx b/std/java/_std/haxe/ds/WeakMap.hx index 8e43c0a0..17f74704 100644 --- a/std/java/_std/haxe/ds/WeakMap.hx +++ b/std/java/_std/haxe/ds/WeakMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/haxe/zip/Compress.hx b/std/java/_std/haxe/zip/Compress.hx index 45e07493..41050626 100644 --- a/std/java/_std/haxe/zip/Compress.hx +++ b/std/java/_std/haxe/zip/Compress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/haxe/zip/Uncompress.hx b/std/java/_std/haxe/zip/Uncompress.hx index fe698257..e6c1f1f5 100644 --- a/std/java/_std/haxe/zip/Uncompress.hx +++ b/std/java/_std/haxe/zip/Uncompress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/sys/FileSystem.hx b/std/java/_std/sys/FileSystem.hx index 1bcc3ed7..366ac0a9 100644 --- a/std/java/_std/sys/FileSystem.hx +++ b/std/java/_std/sys/FileSystem.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/sys/db/Mysql.hx b/std/java/_std/sys/db/Mysql.hx index 0b9beb4e..5984291f 100644 --- a/std/java/_std/sys/db/Mysql.hx +++ b/std/java/_std/sys/db/Mysql.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/sys/db/Sqlite.hx b/std/java/_std/sys/db/Sqlite.hx index 15830912..21e6b903 100644 --- a/std/java/_std/sys/db/Sqlite.hx +++ b/std/java/_std/sys/db/Sqlite.hx @@ -1,4 +1,25 @@ -package sys.db; +/* + * Copyright (C)2005-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 sys.db; class Sqlite { diff --git a/std/java/_std/sys/io/File.hx b/std/java/_std/sys/io/File.hx index 34d5b311..179f99cb 100644 --- a/std/java/_std/sys/io/File.hx +++ b/std/java/_std/sys/io/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -112,6 +112,8 @@ class File { r = read(srcPath); w = write(dstPath); w.writeInput(r); + r.close(); + w.close(); } catch (e:Dynamic) diff --git a/std/java/_std/sys/io/FileInput.hx b/std/java/_std/sys/io/FileInput.hx index 4c98c6db..9cb37473 100644 --- a/std/java/_std/sys/io/FileInput.hx +++ b/std/java/_std/sys/io/FileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/sys/io/FileOutput.hx b/std/java/_std/sys/io/FileOutput.hx index 6fad33c8..d4281864 100644 --- a/std/java/_std/sys/io/FileOutput.hx +++ b/std/java/_std/sys/io/FileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/_std/sys/io/Process.hx b/std/java/_std/sys/io/Process.hx index 75396d2a..70a2a8b1 100644 --- a/std/java/_std/sys/io/Process.hx +++ b/std/java/_std/sys/io/Process.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -35,23 +35,51 @@ class Process { public var stdin(default, null) : haxe.io.Output; private var proc:java.lang.Process; - - public function new( cmd : String, args : Array ) : Void - { - var pargs = new NativeArray(args.length + 1); - pargs[0] = cmd; - for (i in 0...args.length) - { - pargs[i + 1] = args[i]; + @:allow(Sys) + private static function createProcessBuilder(cmd:String, ?args:Array):java.lang.ProcessBuilder { + var sysName = Sys.systemName(); + var pargs; + if (args == null) { + var cmdStr = cmd; + switch (sysName) { + case "Windows": + pargs = new NativeArray(3); + pargs[0] = cmd = switch (Sys.getEnv("COMSPEC")) { + case null: "cmd.exe"; + case comspec: comspec; + } + pargs[1] = '/C'; + pargs[2] = '"$cmdStr"'; + case _: + pargs = new NativeArray(3); + pargs[0] = cmd = "/bin/sh"; + pargs[1] = "-c"; + pargs[2] = cmdStr; + } + } else { + pargs = new NativeArray(args.length + 1); + switch (sysName) { + case "Windows": + pargs[0] = StringTools.quoteWinArg(cmd, false); + for (i in 0...args.length) + { + pargs[i + 1] = StringTools.quoteWinArg(args[i], false); + } + case _: + pargs[0] = cmd; + for (i in 0...args.length) + { + pargs[i + 1] = args[i]; + } + } } - try - { - proc = new java.lang.ProcessBuilder(pargs).start(); - } - catch (e:Dynamic) { throw e; } //wrapping typed exceptions + return new java.lang.ProcessBuilder(pargs); + } - var p = proc; + public function new( cmd : String, ?args : Array ) : Void + { + var p = proc = createProcessBuilder(cmd, args).start(); stderr = new ProcessInput(p.getErrorStream()); stdout = new ProcessInput(p.getInputStream()); stdin = new java.io.NativeOutput(p.getOutputStream()); @@ -64,8 +92,16 @@ class Process { return -1; } - public function exitCode() : Int + public function exitCode( block : Bool = true ) : Null { + if( block == false ) { + try { + return proc.exitValue(); + } catch( e : Dynamic ) { + return null; + } + } + cast(stdout, ProcessInput).bufferContents(); cast(stderr, ProcessInput).bufferContents(); try diff --git a/std/java/_std/sys/net/Host.hx b/std/java/_std/sys/net/Host.hx index c0e65486..665776bc 100644 --- a/std/java/_std/sys/net/Host.hx +++ b/std/java/_std/sys/net/Host.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -23,12 +23,14 @@ package sys.net; import java.net.InetAddress; class Host { + public var host(default,null) : String; public var ip(default,null) : Int; @:allow(sys.net) private var wrapped:InetAddress; public function new( name : String ) : Void { + host = name; try this.wrapped = InetAddress.getByName(name) catch(e:Dynamic) throw e; diff --git a/std/java/_std/sys/net/Socket.hx b/std/java/_std/sys/net/Socket.hx index 52202d12..a1462e56 100644 --- a/std/java/_std/sys/net/Socket.hx +++ b/std/java/_std/sys/net/Socket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -137,6 +137,11 @@ class Socket { var local = sock.getLocalAddress(); var host = new Host(null); host.wrapped = local; + + if (boundAddr != null) + { + return { host: host, port: server.getLocalPort() }; + } return { host: host, port: sock.getLocalPort() }; } diff --git a/std/java/db/Jdbc.hx b/std/java/db/Jdbc.hx index c1e00704..0f3aae53 100644 --- a/std/java/db/Jdbc.hx +++ b/std/java/db/Jdbc.hx @@ -1,4 +1,25 @@ -package java.db; +/* + * Copyright (C)2005-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 java.db; import java.util.concurrent.atomic.AtomicInteger; import haxe.io.Bytes; import java.sql.Types; diff --git a/std/java/internal/Exceptions.hx b/std/java/internal/Exceptions.hx index 88e98ba3..34cd57d1 100644 --- a/std/java/internal/Exceptions.hx +++ b/std/java/internal/Exceptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -73,6 +73,15 @@ class Exceptions { { return "Haxe Exception: " + obj; } + + @:overload override public function getMessage():String + { + return switch (super.getMessage()) + { + case null: Std.string(obj); + case message: message; + } + } public static function wrap(obj:Dynamic):RuntimeException { @@ -82,9 +91,9 @@ class Exceptions { else if (Std.is(obj, String)) ret = new HaxeException(obj, obj, null); else if (Std.is(obj, Throwable)) - ret = new HaxeException(obj, null, obj); + ret = new HaxeException(obj, Std.string(obj), obj); else - ret = new HaxeException(obj, null, null); + ret = new HaxeException(obj, Std.string(obj), null); return ret; } } diff --git a/std/java/internal/FieldLookup.hx b/std/java/internal/FieldLookup.hx index c0c6f71e..9018cce8 100644 --- a/std/java/internal/FieldLookup.hx +++ b/std/java/internal/FieldLookup.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/internal/Function.hx b/std/java/internal/Function.hx index 4bcae251..25d6bd17 100644 --- a/std/java/internal/Function.hx +++ b/std/java/internal/Function.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/internal/HxObject.hx b/std/java/internal/HxObject.hx index 875a265f..c6bcf82a 100644 --- a/std/java/internal/HxObject.hx +++ b/std/java/internal/HxObject.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -38,7 +38,6 @@ interface IHxObject } @:native('haxe.lang.DynamicObject') -@:replaceReflection @:keep class DynamicObject extends HxObject implements Dynamic { diff --git a/std/java/internal/IEquatable.hx b/std/java/internal/IEquatable.hx index d04115ac..699ddd4e 100644 --- a/std/java/internal/IEquatable.hx +++ b/std/java/internal/IEquatable.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/internal/Iterator.hx b/std/java/internal/Iterator.hx index 98982e07..dca2df64 100644 --- a/std/java/internal/Iterator.hx +++ b/std/java/internal/Iterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ package java.internal; - +/* TODO (see Gencommon.IteratorsInterfaceModf) @:native('haxe.lang.Iterator') @:keep interface Iterator @@ -39,4 +39,4 @@ interface Iterable public function iterator():Iterator; -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/std/java/internal/Runtime.hx b/std/java/internal/Runtime.hx index 79d696dd..a29542c5 100644 --- a/std/java/internal/Runtime.hx +++ b/std/java/internal/Runtime.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -143,6 +143,11 @@ package java.internal; return 0; } + public static function toLong(obj:Dynamic):haxe.Int64 + { + return obj == null ? 0 : (obj : java.lang.Number).longValue(); + } + @:functionCode(' if (obj != null && obj instanceof java.lang.Number) { @@ -156,18 +161,18 @@ package java.internal; return false; } - @:functionCode(' - if (obj != null && obj instanceof java.lang.Number) - { - java.lang.Number n = (java.lang.Number) obj; + @:overload public static function isInt(obj:Dynamic):Bool + { + if (Std.is(obj, java.lang.Number)) { + var n:java.lang.Number = obj; return n.doubleValue() == n.intValue(); } else { return false; } - ') - public static function isInt(obj:Dynamic):Bool - { - return false; + } + + @:overload public static function isInt(num:java.lang.Number):Bool { + return num != null && num.doubleValue() == num.intValue(); } @:functionCode(' @@ -568,8 +573,8 @@ package java.internal; if (obj == null) return null; - if (isInt(obj)) - return (cast(obj, Int)) + ""; + if (Std.is(obj, java.lang.Number) && !Std.is(obj, java.lang.Integer.IntegerClass) && isInt( (obj : java.lang.Number) )) + return java.lang.Integer._toString(toInt(obj)); return untyped obj.toString(); } @@ -579,7 +584,7 @@ package java.internal; } } -@:keep @:native("haxe.lang.EmptyObject") private enum EmptyObject +@:keep @:native("haxe.lang.EmptyObject") enum EmptyObject { EMPTY; } diff --git a/std/java/internal/StringExt.hx b/std/java/internal/StringExt.hx index f2923532..0b65ea2c 100644 --- a/std/java/internal/StringExt.hx +++ b/std/java/internal/StringExt.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -42,7 +42,7 @@ private typedef NativeString = String; if ( index >= me.length() || index < 0 ) return null; else - return me.codePointAt(index); + return (int) me.charAt(index); ') public static function charCodeAt(me:NativeString, index:Int):Null { diff --git a/std/java/io/NativeInput.hx b/std/java/io/NativeInput.hx index a9dcd03d..4343bb33 100644 --- a/std/java/io/NativeInput.hx +++ b/std/java/io/NativeInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/io/NativeOutput.hx b/std/java/io/NativeOutput.hx index 20ebb756..daa9f72e 100644 --- a/std/java/io/NativeOutput.hx +++ b/std/java/io/NativeOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/lang/Boolean.hx b/std/java/lang/Boolean.hx index 0d76ef10..01f631a1 100644 --- a/std/java/lang/Boolean.hx +++ b/std/java/lang/Boolean.hx @@ -1,27 +1,34 @@ -package java.lang; +/* + * Copyright (C)2005-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 java.lang; @:native("") // make sure the generator won't see this -@:forward abstract Boolean(BooleanClass) from BooleanClass to BooleanClass +@:forward +@:forwardStatics abstract Boolean(BooleanClass) from BooleanClass to BooleanClass { @:to @:extern inline public function toBool():Bool return this.booleanValue(); @:from @:extern inline public static function fromBool(b:Bool):Boolean return BooleanClass.valueOf(b); - - @:extern public static var FALSE(get,set):Boolean; - @:extern static inline function get_FALSE():Boolean return BooleanClass.FALSE; - @:extern static inline function set_FALSE(val:Boolean):Boolean return BooleanClass.FALSE = val; - @:extern public static var TRUE(get,set):Boolean; - @:extern static inline function get_TRUE():Boolean return BooleanClass.TRUE; - @:extern static inline function set_TRUE(val:Boolean):Boolean return BooleanClass.TRUE = val; - @:extern public static var TYPE(get,set):Class; - @:extern static inline function get_TYPE():Class return BooleanClass.TYPE; - @:extern static inline function set_TYPE(val:Class):Class return BooleanClass.TYPE = val; - @:extern @:overload inline public static function compare(param1:Bool, param2:Bool):Int return BooleanClass.compare(param1, param2); - @:extern @:overload inline public static function getBoolean(param1:String):Bool return BooleanClass.getBoolean(param1); - @:extern @:overload inline public static function parseBoolean(param1:String):Bool return BooleanClass.parseBoolean(param1); - @:extern @:overload inline public static function _toString(param1:Bool):String return BooleanClass._toString(param1); - @:extern @:overload inline public static function valueOf(param1:Bool):Boolean return BooleanClass.valueOf(param1); } @:native("java.lang.Boolean") extern class BooleanClass extends Number implements Comparable diff --git a/std/java/lang/Byte.hx b/std/java/lang/Byte.hx index bcfb3893..54a943a2 100644 --- a/std/java/lang/Byte.hx +++ b/std/java/lang/Byte.hx @@ -1,27 +1,34 @@ -package java.lang; +/* + * Copyright (C)2005-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 java.lang; @:native("") // make sure the generator won't see this +@:forwardStatics @:forward abstract Byte(ByteClass) from ByteClass to ByteClass { @:to @:extern inline public function toByte():java.types.Int8 return this.byteValue(); @:from @:extern inline public static function fromByte(b:java.types.Int8):Byte return ByteClass.valueOf(b); - - @:extern public static var MAX_VALUE(get,never):java.types.Int8; - @:extern static inline function get_MAX_VALUE():java.types.Int8 return ByteClass.MAX_VALUE; - @:extern public static var MIN_VALUE(get,never):java.types.Int8; - @:extern static inline function get_MIN_VALUE():java.types.Int8 return ByteClass.MIN_VALUE; - @:extern public static var SIZE(get,never):Int; - @:extern static inline function get_SIZE():Int return ByteClass.SIZE; - @:extern public static var TYPE(get,set):Class; - @:extern static inline function get_TYPE():Class return ByteClass.TYPE; - @:extern static inline function set_TYPE(val:Class):Class return ByteClass.TYPE = val; - @:extern @:overload inline public static function compare(param1:java.types.Int8, param2:java.types.Int8):Int return ByteClass.compare(param1, param2); - @:extern @:overload inline public static function decode(param1:String):Byte return ByteClass.decode(param1); - @:extern @:overload inline public static function parseByte(param1:String, param2:Int):java.types.Int8 return ByteClass.parseByte(param1, param2); - @:extern @:overload inline public static function _toString(param1:java.types.Int8):String return ByteClass._toString(param1); - @:extern @:overload inline public static function valueOf(param1:java.types.Int8):Byte return ByteClass.valueOf(param1); } @:native("java.lang.Byte") extern class ByteClass extends Number implements Comparable diff --git a/std/java/lang/Character.hx b/std/java/lang/Character.hx index 42ff5354..0856a4dc 100644 --- a/std/java/lang/Character.hx +++ b/std/java/lang/Character.hx @@ -1,194 +1,34 @@ -package java.lang; +/* + * Copyright (C)2005-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 java.lang; @:native("") // make sure the generator won't see this +@:forwardStatics @:forward abstract Character(CharacterClass) from CharacterClass to CharacterClass { @:to @:extern inline public function toCharacter():java.types.Char16 return this.charValue(); @:from @:extern inline public static function fromCharacter(b:java.types.Char16):Character return CharacterClass.valueOf(b); - - @:extern public static var COMBINING_SPACING_MARK(get,never):java.types.Char16; - @:extern static inline function get_COMBINING_SPACING_MARK():java.types.Char16 return CharacterClass.COMBINING_SPACING_MARK; - @:extern public static var CONNECTOR_PUNCTUATION(get,never):java.types.Char16; - @:extern static inline function get_CONNECTOR_PUNCTUATION():java.types.Char16 return CharacterClass.CONNECTOR_PUNCTUATION; - @:extern public static var CONTROL(get,never):java.types.Char16; - @:extern static inline function get_CONTROL():java.types.Char16 return CharacterClass.CONTROL; - @:extern public static var CURRENCY_SYMBOL(get,never):java.types.Char16; - @:extern static inline function get_CURRENCY_SYMBOL():java.types.Char16 return CharacterClass.CURRENCY_SYMBOL; - @:extern public static var DASH_PUNCTUATION(get,never):java.types.Char16; - @:extern static inline function get_DASH_PUNCTUATION():java.types.Char16 return CharacterClass.DASH_PUNCTUATION; - @:extern public static var DECIMAL_DIGIT_NUMBER(get,never):java.types.Char16; - @:extern static inline function get_DECIMAL_DIGIT_NUMBER():java.types.Char16 return CharacterClass.DECIMAL_DIGIT_NUMBER; - @:extern public static var DIRECTIONALITY_ARABIC_NUMBER(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_ARABIC_NUMBER():java.types.Char16 return CharacterClass.DIRECTIONALITY_ARABIC_NUMBER; - @:extern public static var DIRECTIONALITY_BOUNDARY_NEUTRAL(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_BOUNDARY_NEUTRAL():java.types.Char16 return CharacterClass.DIRECTIONALITY_BOUNDARY_NEUTRAL; - @:extern public static var DIRECTIONALITY_COMMON_NUMBER_SEPARATOR(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_COMMON_NUMBER_SEPARATOR():java.types.Char16 return CharacterClass.DIRECTIONALITY_COMMON_NUMBER_SEPARATOR; - @:extern public static var DIRECTIONALITY_EUROPEAN_NUMBER(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_EUROPEAN_NUMBER():java.types.Char16 return CharacterClass.DIRECTIONALITY_EUROPEAN_NUMBER; - @:extern public static var DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR():java.types.Char16 return CharacterClass.DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR; - @:extern public static var DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR():java.types.Char16 return CharacterClass.DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR; - @:extern public static var DIRECTIONALITY_LEFT_TO_RIGHT(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_LEFT_TO_RIGHT():java.types.Char16 return CharacterClass.DIRECTIONALITY_LEFT_TO_RIGHT; - @:extern public static var DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING():java.types.Char16 return CharacterClass.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING; - @:extern public static var DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE():java.types.Char16 return CharacterClass.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE; - @:extern public static var DIRECTIONALITY_NONSPACING_MARK(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_NONSPACING_MARK():java.types.Char16 return CharacterClass.DIRECTIONALITY_NONSPACING_MARK; - @:extern public static var DIRECTIONALITY_OTHER_NEUTRALS(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_OTHER_NEUTRALS():java.types.Char16 return CharacterClass.DIRECTIONALITY_OTHER_NEUTRALS; - @:extern public static var DIRECTIONALITY_PARAGRAPH_SEPARATOR(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_PARAGRAPH_SEPARATOR():java.types.Char16 return CharacterClass.DIRECTIONALITY_PARAGRAPH_SEPARATOR; - @:extern public static var DIRECTIONALITY_POP_DIRECTIONAL_FORMAT(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_POP_DIRECTIONAL_FORMAT():java.types.Char16 return CharacterClass.DIRECTIONALITY_POP_DIRECTIONAL_FORMAT; - @:extern public static var DIRECTIONALITY_RIGHT_TO_LEFT(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_RIGHT_TO_LEFT():java.types.Char16 return CharacterClass.DIRECTIONALITY_RIGHT_TO_LEFT; - @:extern public static var DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC():java.types.Char16 return CharacterClass.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC; - @:extern public static var DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING():java.types.Char16 return CharacterClass.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING; - @:extern public static var DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE():java.types.Char16 return CharacterClass.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE; - @:extern public static var DIRECTIONALITY_SEGMENT_SEPARATOR(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_SEGMENT_SEPARATOR():java.types.Char16 return CharacterClass.DIRECTIONALITY_SEGMENT_SEPARATOR; - @:extern public static var DIRECTIONALITY_UNDEFINED(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_UNDEFINED():java.types.Char16 return CharacterClass.DIRECTIONALITY_UNDEFINED; - @:extern public static var DIRECTIONALITY_WHITESPACE(get,never):java.types.Char16; - @:extern static inline function get_DIRECTIONALITY_WHITESPACE():java.types.Char16 return CharacterClass.DIRECTIONALITY_WHITESPACE; - @:extern public static var ENCLOSING_MARK(get,never):java.types.Char16; - @:extern static inline function get_ENCLOSING_MARK():java.types.Char16 return CharacterClass.ENCLOSING_MARK; - @:extern public static var END_PUNCTUATION(get,never):java.types.Char16; - @:extern static inline function get_END_PUNCTUATION():java.types.Char16 return CharacterClass.END_PUNCTUATION; - @:extern public static var FINAL_QUOTE_PUNCTUATION(get,never):java.types.Char16; - @:extern static inline function get_FINAL_QUOTE_PUNCTUATION():java.types.Char16 return CharacterClass.FINAL_QUOTE_PUNCTUATION; - @:extern public static var FORMAT(get,never):java.types.Char16; - @:extern static inline function get_FORMAT():java.types.Char16 return CharacterClass.FORMAT; - @:extern public static var INITIAL_QUOTE_PUNCTUATION(get,never):java.types.Char16; - @:extern static inline function get_INITIAL_QUOTE_PUNCTUATION():java.types.Char16 return CharacterClass.INITIAL_QUOTE_PUNCTUATION; - @:extern public static var LETTER_NUMBER(get,never):java.types.Char16; - @:extern static inline function get_LETTER_NUMBER():java.types.Char16 return CharacterClass.LETTER_NUMBER; - @:extern public static var LINE_SEPARATOR(get,never):java.types.Char16; - @:extern static inline function get_LINE_SEPARATOR():java.types.Char16 return CharacterClass.LINE_SEPARATOR; - @:extern public static var LOWERCASE_LETTER(get,never):java.types.Char16; - @:extern static inline function get_LOWERCASE_LETTER():java.types.Char16 return CharacterClass.LOWERCASE_LETTER; - @:extern public static var MATH_SYMBOL(get,never):java.types.Char16; - @:extern static inline function get_MATH_SYMBOL():java.types.Char16 return CharacterClass.MATH_SYMBOL; - @:extern public static var MAX_CODE_POINT(get,never):Int; - @:extern static inline function get_MAX_CODE_POINT():Int return CharacterClass.MAX_CODE_POINT; - @:extern public static var MAX_HIGH_SURROGATE(get,never):java.types.Char16; - @:extern static inline function get_MAX_HIGH_SURROGATE():java.types.Char16 return CharacterClass.MAX_HIGH_SURROGATE; - @:extern public static var MAX_LOW_SURROGATE(get,never):java.types.Char16; - @:extern static inline function get_MAX_LOW_SURROGATE():java.types.Char16 return CharacterClass.MAX_LOW_SURROGATE; - @:extern public static var MAX_RADIX(get,never):Int; - @:extern static inline function get_MAX_RADIX():Int return CharacterClass.MAX_RADIX; - @:extern public static var MAX_SURROGATE(get,never):java.types.Char16; - @:extern static inline function get_MAX_SURROGATE():java.types.Char16 return CharacterClass.MAX_SURROGATE; - @:extern public static var MAX_VALUE(get,never):java.types.Char16; - @:extern static inline function get_MAX_VALUE():java.types.Char16 return CharacterClass.MAX_VALUE; - @:extern public static var MIN_CODE_POINT(get,never):Int; - @:extern static inline function get_MIN_CODE_POINT():Int return CharacterClass.MIN_CODE_POINT; - @:extern public static var MIN_HIGH_SURROGATE(get,never):java.types.Char16; - @:extern static inline function get_MIN_HIGH_SURROGATE():java.types.Char16 return CharacterClass.MIN_HIGH_SURROGATE; - @:extern public static var MIN_LOW_SURROGATE(get,never):java.types.Char16; - @:extern static inline function get_MIN_LOW_SURROGATE():java.types.Char16 return CharacterClass.MIN_LOW_SURROGATE; - @:extern public static var MIN_RADIX(get,never):Int; - @:extern static inline function get_MIN_RADIX():Int return CharacterClass.MIN_RADIX; - @:extern public static var MIN_SUPPLEMENTARY_CODE_POINT(get,never):Int; - @:extern static inline function get_MIN_SUPPLEMENTARY_CODE_POINT():Int return CharacterClass.MIN_SUPPLEMENTARY_CODE_POINT; - @:extern public static var MIN_SURROGATE(get,never):java.types.Char16; - @:extern static inline function get_MIN_SURROGATE():java.types.Char16 return CharacterClass.MIN_SURROGATE; - @:extern public static var MIN_VALUE(get,never):java.types.Char16; - @:extern static inline function get_MIN_VALUE():java.types.Char16 return CharacterClass.MIN_VALUE; - @:extern public static var MODIFIER_LETTER(get,never):java.types.Char16; - @:extern static inline function get_MODIFIER_LETTER():java.types.Char16 return CharacterClass.MODIFIER_LETTER; - @:extern public static var MODIFIER_SYMBOL(get,never):java.types.Char16; - @:extern static inline function get_MODIFIER_SYMBOL():java.types.Char16 return CharacterClass.MODIFIER_SYMBOL; - @:extern public static var NON_SPACING_MARK(get,never):java.types.Char16; - @:extern static inline function get_NON_SPACING_MARK():java.types.Char16 return CharacterClass.NON_SPACING_MARK; - @:extern public static var OTHER_LETTER(get,never):java.types.Char16; - @:extern static inline function get_OTHER_LETTER():java.types.Char16 return CharacterClass.OTHER_LETTER; - @:extern public static var OTHER_NUMBER(get,never):java.types.Char16; - @:extern static inline function get_OTHER_NUMBER():java.types.Char16 return CharacterClass.OTHER_NUMBER; - @:extern public static var OTHER_PUNCTUATION(get,never):java.types.Char16; - @:extern static inline function get_OTHER_PUNCTUATION():java.types.Char16 return CharacterClass.OTHER_PUNCTUATION; - @:extern public static var OTHER_SYMBOL(get,never):java.types.Char16; - @:extern static inline function get_OTHER_SYMBOL():java.types.Char16 return CharacterClass.OTHER_SYMBOL; - @:extern public static var PARAGRAPH_SEPARATOR(get,never):java.types.Char16; - @:extern static inline function get_PARAGRAPH_SEPARATOR():java.types.Char16 return CharacterClass.PARAGRAPH_SEPARATOR; - @:extern public static var PRIVATE_USE(get,never):java.types.Char16; - @:extern static inline function get_PRIVATE_USE():java.types.Char16 return CharacterClass.PRIVATE_USE; - @:extern public static var SIZE(get,never):Int; - @:extern static inline function get_SIZE():Int return CharacterClass.SIZE; - @:extern public static var SPACE_SEPARATOR(get,never):java.types.Char16; - @:extern static inline function get_SPACE_SEPARATOR():java.types.Char16 return CharacterClass.SPACE_SEPARATOR; - @:extern public static var START_PUNCTUATION(get,never):java.types.Char16; - @:extern static inline function get_START_PUNCTUATION():java.types.Char16 return CharacterClass.START_PUNCTUATION; - @:extern public static var SURROGATE(get,never):java.types.Char16; - @:extern static inline function get_SURROGATE():java.types.Char16 return CharacterClass.SURROGATE; - @:extern public static var TITLECASE_LETTER(get,never):java.types.Char16; - @:extern static inline function get_TITLECASE_LETTER():java.types.Char16 return CharacterClass.TITLECASE_LETTER; - @:extern public static var TYPE(get,set):Class; - @:extern static inline function get_TYPE():Class return CharacterClass.TYPE; - @:extern static inline function set_TYPE(val:Class):Class return CharacterClass.TYPE = val; - @:extern public static var UNASSIGNED(get,never):java.types.Char16; - @:extern static inline function get_UNASSIGNED():java.types.Char16 return CharacterClass.UNASSIGNED; - @:extern public static var UPPERCASE_LETTER(get,never):java.types.Char16; - @:extern static inline function get_UPPERCASE_LETTER():java.types.Char16 return CharacterClass.UPPERCASE_LETTER; - @:extern @:overload inline public static function charCount(param1:Int):Int return CharacterClass.charCount(param1); - @:extern @:overload inline public static function codePointAt(param1:CharSequence, param2:Int):Int return CharacterClass.codePointAt(param1, param2); - @:extern @:overload inline public static function codePointBefore(param1:CharSequence, param2:Int):Int return CharacterClass.codePointBefore(param1, param2); - @:extern @:overload inline public static function codePointCount(param1:CharSequence, param2:Int, param3:Int):Int return CharacterClass.codePointCount(param1, param2, param3); - @:extern @:overload inline public static function compare(param1:java.types.Char16, param2:java.types.Char16):Int return CharacterClass.compare(param1, param2); - @:extern @:overload inline public static function digit(param1:java.types.Char16, param2:Int):Int return CharacterClass.digit(param1, param2); - @:extern @:overload inline public static function forDigit(param1:Int, param2:Int):java.types.Char16 return CharacterClass.forDigit(param1, param2); - @:extern @:overload inline public static function getDirectionality(param1:java.types.Char16):java.types.Char16 return CharacterClass.getDirectionality(param1); - @:extern @:overload inline public static function getName(param1:Int):String return CharacterClass.getName(param1); - @:extern @:overload inline public static function getNumericValue(param1:java.types.Char16):Int return CharacterClass.getNumericValue(param1); - @:extern @:overload inline public static function getType(param1:java.types.Char16):Int return CharacterClass.getType(param1); - @:extern @:overload inline public static function highSurrogate(param1:Int):java.types.Char16 return CharacterClass.highSurrogate(param1); - @:extern @:overload inline public static function isAlphabetic(param1:Int):Bool return CharacterClass.isAlphabetic(param1); - @:extern @:overload inline public static function isBmpCodePoint(param1:Int):Bool return CharacterClass.isBmpCodePoint(param1); - @:extern @:overload inline public static function isDefined(param1:java.types.Char16):Bool return CharacterClass.isDefined(param1); - @:extern @:overload inline public static function isDigit(param1:java.types.Char16):Bool return CharacterClass.isDigit(param1); - @:extern @:overload inline public static function isHighSurrogate(param1:java.types.Char16):Bool return CharacterClass.isHighSurrogate(param1); - @:extern @:overload inline public static function isISOControl(param1:java.types.Char16):Bool return CharacterClass.isISOControl(param1); - @:extern @:overload inline public static function isIdentifierIgnorable(param1:java.types.Char16):Bool return CharacterClass.isIdentifierIgnorable(param1); - @:extern @:overload inline public static function isIdeographic(param1:Int):Bool return CharacterClass.isIdeographic(param1); - @:extern @:overload inline public static function isJavaIdentifierPart(param1:java.types.Char16):Bool return CharacterClass.isJavaIdentifierPart(param1); - @:extern @:overload inline public static function isJavaIdentifierStart(param1:java.types.Char16):Bool return CharacterClass.isJavaIdentifierStart(param1); - - - @:extern @:overload inline public static function isLetter(param1:java.types.Char16):Bool return CharacterClass.isLetter(param1); - @:extern @:overload inline public static function isLetterOrDigit(param1:java.types.Char16):Bool return CharacterClass.isLetterOrDigit(param1); - @:extern @:overload inline public static function isLowSurrogate(param1:java.types.Char16):Bool return CharacterClass.isLowSurrogate(param1); - @:extern @:overload inline public static function isLowerCase(param1:java.types.Char16):Bool return CharacterClass.isLowerCase(param1); - @:extern @:overload inline public static function isMirrored(param1:java.types.Char16):Bool return CharacterClass.isMirrored(param1); - - @:extern @:overload inline public static function isSpaceChar(param1:java.types.Char16):Bool return CharacterClass.isSpaceChar(param1); - @:extern @:overload inline public static function isSupplementaryCodePoint(param1:Int):Bool return CharacterClass.isSupplementaryCodePoint(param1); - @:extern @:overload inline public static function isSurrogate(param1:java.types.Char16):Bool return CharacterClass.isSurrogate(param1); - @:extern @:overload inline public static function isSurrogatePair(param1:java.types.Char16, param2:java.types.Char16):Bool return CharacterClass.isSurrogatePair(param1, param2); - @:extern @:overload inline public static function isTitleCase(param1:java.types.Char16):Bool return CharacterClass.isTitleCase(param1); - @:extern @:overload inline public static function isUnicodeIdentifierPart(param1:java.types.Char16):Bool return CharacterClass.isUnicodeIdentifierPart(param1); - @:extern @:overload inline public static function isUnicodeIdentifierStart(param1:java.types.Char16):Bool return CharacterClass.isUnicodeIdentifierStart(param1); - @:extern @:overload inline public static function isUpperCase(param1:java.types.Char16):Bool return CharacterClass.isUpperCase(param1); - @:extern @:overload inline public static function isValidCodePoint(param1:Int):Bool return CharacterClass.isValidCodePoint(param1); - @:extern @:overload inline public static function isWhitespace(param1:java.types.Char16):Bool return CharacterClass.isWhitespace(param1); - @:extern @:overload inline public static function lowSurrogate(param1:Int):java.types.Char16 return CharacterClass.lowSurrogate(param1); - @:extern @:overload inline public static function offsetByCodePoints(param1:CharSequence, param2:Int, param3:Int):Int return CharacterClass.offsetByCodePoints(param1, param2, param3); - @:extern @:overload inline public static function reverseBytes(param1:java.types.Char16):java.types.Char16 return CharacterClass.reverseBytes(param1); - @:extern @:overload inline public static function toChars(param1:Int, param2:java.NativeArray, param3:Int):Int return CharacterClass.toChars(param1, param2, param3); - @:extern @:overload inline public static function toCodePoint(param1:java.types.Char16, param2:java.types.Char16):Int return CharacterClass.toCodePoint(param1, param2); - @:extern @:overload inline public static function toLowerCase(param1:java.types.Char16):java.types.Char16 return CharacterClass.toLowerCase(param1); - @:extern @:overload inline public static function _toString(param1:java.types.Char16):String return CharacterClass._toString(param1); - @:extern @:overload inline public static function toTitleCase(param1:java.types.Char16):java.types.Char16 return CharacterClass.toTitleCase(param1); - @:extern @:overload inline public static function toUpperCase(param1:java.types.Char16):java.types.Char16 return CharacterClass.toUpperCase(param1); - @:extern @:overload inline public static function valueOf(param1:java.types.Char16):Character return CharacterClass.valueOf(param1); } @:native("java.lang.Character") extern class CharacterClass implements Comparable diff --git a/std/java/lang/Double.hx b/std/java/lang/Double.hx index d50df17f..06f7c690 100644 --- a/std/java/lang/Double.hx +++ b/std/java/lang/Double.hx @@ -1,44 +1,34 @@ -package java.lang; +/* + * Copyright (C)2005-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 java.lang; @:native("") // make sure the generator won't see this +@:forwardStatics @:forward abstract Double(DoubleClass) from DoubleClass to DoubleClass { @:to @:extern inline public function toFloat():Float return this.doubleValue(); @:from @:extern inline public static function fromFloat(b:Float):Double return DoubleClass.valueOf(b); - - @:extern public static var MAX_EXPONENT(get,never):Int; - @:extern static inline function get_MAX_EXPONENT():Int return DoubleClass.MAX_EXPONENT; - @:extern public static var MAX_VALUE(get,never):Float; - @:extern static inline function get_MAX_VALUE():Float return DoubleClass.MAX_VALUE; - @:extern public static var MIN_EXPONENT(get,never):Int; - @:extern static inline function get_MIN_EXPONENT():Int return DoubleClass.MIN_EXPONENT; - @:extern public static var MIN_NORMAL(get,never):Float; - @:extern static inline function get_MIN_NORMAL():Float return DoubleClass.MIN_NORMAL; - @:extern public static var MIN_VALUE(get,never):Float; - @:extern static inline function get_MIN_VALUE():Float return DoubleClass.MIN_VALUE; - @:extern public static var NEGATIVE_INFINITY(get,never):Float; - @:extern static inline function get_NEGATIVE_INFINITY():Float return DoubleClass.NEGATIVE_INFINITY; - @:extern public static var NaN(get,never):Float; - @:extern static inline function get_NaN():Float return DoubleClass.NaN; - @:extern public static var POSITIVE_INFINITY(get,never):Float; - @:extern static inline function get_POSITIVE_INFINITY():Float return DoubleClass.POSITIVE_INFINITY; - @:extern public static var SIZE(get,never):Int; - @:extern static inline function get_SIZE():Int return DoubleClass.SIZE; - @:extern public static var TYPE(get,set):Class; - @:extern static inline function get_TYPE():Class return DoubleClass.TYPE; - @:extern static inline function set_TYPE(val:Class):Class return DoubleClass.TYPE = val; - @:extern @:overload inline public static function compare(param1:Float, param2:Float):Int return DoubleClass.compare(param1, param2); - @:extern @:overload inline public static function doubleToLongBits(param1:Float):haxe.Int64 return DoubleClass.doubleToLongBits(param1); - @:extern @:overload inline public static function doubleToRawLongBits(param1:Float):haxe.Int64 return DoubleClass.doubleToRawLongBits(param1); - @:extern @:overload inline public static function _isInfinite(param1:Float):Bool return DoubleClass._isInfinite(param1); - @:extern @:overload inline public static function _isNaN(param1:Float):Bool return DoubleClass._isNaN(param1); - @:extern @:overload inline public static function longBitsToDouble(param1:haxe.Int64):Float return DoubleClass.longBitsToDouble(param1); - @:extern @:overload inline public static function parseDouble(param1:String):Float return DoubleClass.parseDouble(param1); - @:extern @:overload inline public static function toHexString(param1:Float):String return DoubleClass.toHexString(param1); - @:extern @:overload inline public static function _toString(param1:Float):String return DoubleClass._toString(param1); - @:extern @:overload inline public static function valueOf(param1:String):Double return DoubleClass.valueOf(param1); } @:native("java.lang.Double") extern class DoubleClass extends Number implements Comparable diff --git a/std/java/lang/Float.hx b/std/java/lang/Float.hx index 3f107fa2..c3adcc5f 100644 --- a/std/java/lang/Float.hx +++ b/std/java/lang/Float.hx @@ -1,44 +1,34 @@ -package java.lang; +/* + * Copyright (C)2005-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 java.lang; @:native("") // make sure the generator won't see this +@:forwardStatics @:forward abstract Float(FloatClass) from FloatClass to FloatClass { @:to @:extern inline public function toFloat():std.StdTypes.Float return this.floatValue(); @:from @:extern inline public static function fromFloat(b:std.StdTypes.Single):Float return FloatClass.valueOf(b); - - @:extern public static var MAX_EXPONENT(get,never):Int; - @:extern static inline function get_MAX_EXPONENT():Int return FloatClass.MAX_EXPONENT; - @:extern public static var MAX_VALUE(get,never):Single; - @:extern static inline function get_MAX_VALUE():Single return FloatClass.MAX_VALUE; - @:extern public static var MIN_EXPONENT(get,never):Int; - @:extern static inline function get_MIN_EXPONENT():Int return FloatClass.MIN_EXPONENT; - @:extern public static var MIN_NORMAL(get,never):Single; - @:extern static inline function get_MIN_NORMAL():Single return FloatClass.MIN_NORMAL; - @:extern public static var MIN_VALUE(get,never):Single; - @:extern static inline function get_MIN_VALUE():Single return FloatClass.MIN_VALUE; - @:extern public static var NEGATIVE_INFINITY(get,never):Single; - @:extern static inline function get_NEGATIVE_INFINITY():Single return FloatClass.NEGATIVE_INFINITY; - @:extern public static var NaN(get,never):Single; - @:extern static inline function get_NaN():Single return FloatClass.NaN; - @:extern public static var POSITIVE_INFINITY(get,never):Single; - @:extern static inline function get_POSITIVE_INFINITY():Single return FloatClass.POSITIVE_INFINITY; - @:extern public static var SIZE(get,never):Int; - @:extern static inline function get_SIZE():Int return FloatClass.SIZE; - @:extern public static var TYPE(get,set):Class; - @:extern static inline function get_TYPE():Class return FloatClass.TYPE; - @:extern static inline function set_TYPE(val:Class):Class return FloatClass.TYPE = val; - @:extern @:overload inline public static function compare(param1:Single, param2:Single):Int return FloatClass.compare(param1, param2); - @:extern @:overload inline public static function floatToIntBits(param1:Single):Int return FloatClass.floatToIntBits(param1); - @:extern @:overload inline public static function floatToRawIntBits(param1:Single):Int return FloatClass.floatToRawIntBits(param1); - @:extern @:overload inline public static function intBitsToFloat(param1:Int):Single return FloatClass.intBitsToFloat(param1); - @:extern @:overload inline public static function _isInfinite(param1:Single):Bool return FloatClass._isInfinite(param1); - @:extern @:overload inline public static function _isNaN(param1:Single):Bool return FloatClass._isNaN(param1); - @:extern @:overload inline public static function parseFloat(param1:String):Single return FloatClass.parseFloat(param1); - @:extern @:overload inline public static function toHexString(param1:Single):String return FloatClass.toHexString(param1); - @:extern @:overload inline public static function _toString(param1:Single):String return FloatClass._toString(param1); - @:extern @:overload inline public static function valueOf(param1:String):Float return FloatClass.valueOf(param1); } @:native("java.lang.Float") extern class FloatClass extends Number implements Comparable diff --git a/std/java/lang/Integer.hx b/std/java/lang/Integer.hx index e740f677..51a28372 100644 --- a/std/java/lang/Integer.hx +++ b/std/java/lang/Integer.hx @@ -1,41 +1,34 @@ -package java.lang; +/* + * Copyright (C)2005-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 java.lang; @:native("") // make sure the generator won't see this +@:forwardStatics @:forward abstract Integer(IntegerClass) from IntegerClass to IntegerClass { @:to @:extern inline public function toInt():Int return this.intValue(); @:from @:extern inline public static function fromInt(b:Int):Integer return IntegerClass.valueOf(b); - - @:extern public static var MAX_VALUE(get,never):Int; - @:extern static inline function get_MAX_VALUE():Int return IntegerClass.MAX_VALUE; - @:extern public static var MIN_VALUE(get,never):Int; - @:extern static inline function get_MIN_VALUE():Int return IntegerClass.MIN_VALUE; - @:extern public static var SIZE(get,never):Int; - @:extern static inline function get_SIZE():Int return IntegerClass.SIZE; - @:extern public static var TYPE(get,set):Class; - @:extern static inline function get_TYPE():Class return IntegerClass.TYPE; - @:extern static inline function set_TYPE(val:Class):Class return IntegerClass.TYPE = val; - @:extern @:overload inline public static function bitCount(param1:Int):Int return IntegerClass.bitCount(param1); - @:extern @:overload inline public static function compare(param1:Int, param2:Int):Int return IntegerClass.compare(param1, param2); - @:extern @:overload inline public static function decode(param1:String):Integer return IntegerClass.decode(param1); - @:extern @:overload inline public static function getInteger(param1:String):Integer return IntegerClass.getInteger(param1); - @:extern @:overload inline public static function highestOneBit(param1:Int):Int return IntegerClass.highestOneBit(param1); - @:extern @:overload inline public static function lowestOneBit(param1:Int):Int return IntegerClass.lowestOneBit(param1); - @:extern @:overload inline public static function numberOfLeadingZeros(param1:Int):Int return IntegerClass.numberOfLeadingZeros(param1); - @:extern @:overload inline public static function numberOfTrailingZeros(param1:Int):Int return IntegerClass.numberOfTrailingZeros(param1); - @:extern @:overload inline public static function parseInt(param1:String, param2:Int):Int return IntegerClass.parseInt(param1, param2); - @:extern @:overload inline public static function reverse(param1:Int):Int return IntegerClass.reverse(param1); - @:extern @:overload inline public static function reverseBytes(param1:Int):Int return IntegerClass.reverseBytes(param1); - @:extern @:overload inline public static function rotateLeft(param1:Int, param2:Int):Int return IntegerClass.rotateLeft(param1, param2); - @:extern @:overload inline public static function rotateRight(param1:Int, param2:Int):Int return IntegerClass.rotateRight(param1, param2); - @:extern @:overload inline public static function signum(param1:Int):Int return IntegerClass.signum(param1); - @:extern @:overload inline public static function toBinaryString(param1:Int):String return IntegerClass.toBinaryString(param1); - @:extern @:overload inline public static function toHexString(param1:Int):String return IntegerClass.toHexString(param1); - @:extern @:overload inline public static function toOctalString(param1:Int):String return IntegerClass.toOctalString(param1); - @:extern @:overload inline public static function _toString(param1:Int, param2:Int):String return IntegerClass._toString(param1, param2); - @:extern @:overload inline public static function valueOf(param1:String, param2:Int):Integer return IntegerClass.valueOf(param1, param2); } @:native("java.lang.Integer") extern class IntegerClass extends Number implements Comparable diff --git a/std/java/lang/Long.hx b/std/java/lang/Long.hx index e9722fe4..4ff65e13 100644 --- a/std/java/lang/Long.hx +++ b/std/java/lang/Long.hx @@ -1,41 +1,34 @@ -package java.lang; +/* + * Copyright (C)2005-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 java.lang; @:native("") // make sure the generator won't see this +@:forwardStatics @:forward abstract Long(LongClass) from LongClass to LongClass { @:to @:extern inline public function toLong():haxe.Int64 return this.longValue(); @:from @:extern inline public static function fromLong(b:haxe.Int64):Long return LongClass.valueOf(b); - - @:extern public static var MAX_VALUE(get,never):haxe.Int64; - @:extern static inline function get_MAX_VALUE():haxe.Int64 return LongClass.MAX_VALUE; - @:extern public static var MIN_VALUE(get,never):haxe.Int64; - @:extern static inline function get_MIN_VALUE():haxe.Int64 return LongClass.MIN_VALUE; - @:extern public static var SIZE(get,never):Int; - @:extern static inline function get_SIZE():Int return LongClass.SIZE; - @:extern public static var TYPE(get,set):Class; - @:extern static inline function get_TYPE():Class return LongClass.TYPE; - @:extern static inline function set_TYPE(val:Class):Class return LongClass.TYPE = val; - @:extern @:overload inline public static function bitCount(param1:haxe.Int64):Int return LongClass.bitCount(param1); - @:extern @:overload inline public static function compare(param1:haxe.Int64, param2:haxe.Int64):Int return LongClass.compare(param1, param2); - @:extern @:overload inline public static function decode(param1:String):Long return LongClass.decode(param1); - @:extern @:overload inline public static function getLong(param1:String, param2:Long):Long return LongClass.getLong(param1, param2); - @:extern @:overload inline public static function highestOneBit(param1:haxe.Int64):haxe.Int64 return LongClass.highestOneBit(param1); - @:extern @:overload inline public static function lowestOneBit(param1:haxe.Int64):haxe.Int64 return LongClass.lowestOneBit(param1); - @:extern @:overload inline public static function numberOfLeadingZeros(param1:haxe.Int64):Int return LongClass.numberOfLeadingZeros(param1); - @:extern @:overload inline public static function numberOfTrailingZeros(param1:haxe.Int64):Int return LongClass.numberOfTrailingZeros(param1); - @:extern @:overload inline public static function parseLong(param1:String):haxe.Int64 return LongClass.parseLong(param1); - @:extern @:overload inline public static function reverse(param1:haxe.Int64):haxe.Int64 return LongClass.reverse(param1); - @:extern @:overload inline public static function reverseBytes(param1:haxe.Int64):haxe.Int64 return LongClass.reverseBytes(param1); - @:extern @:overload inline public static function rotateLeft(param1:haxe.Int64, param2:Int):haxe.Int64 return LongClass.rotateLeft(param1, param2); - @:extern @:overload inline public static function rotateRight(param1:haxe.Int64, param2:Int):haxe.Int64 return LongClass.rotateRight(param1, param2); - @:extern @:overload inline public static function signum(param1:haxe.Int64):Int return LongClass.signum(param1); - @:extern @:overload inline public static function toBinaryString(param1:haxe.Int64):String return LongClass.toBinaryString(param1); - @:extern @:overload inline public static function toHexString(param1:haxe.Int64):String return LongClass.toHexString(param1); - @:extern @:overload inline public static function toOctalString(param1:haxe.Int64):String return LongClass.toOctalString(param1); - @:extern @:overload inline public static function _toString(param1:haxe.Int64):String return LongClass._toString(param1); - @:extern @:overload inline public static function valueOf(param1:haxe.Int64):Long return LongClass.valueOf(param1); } @:native("java.lang.Long") extern class LongClass extends Number implements Comparable diff --git a/std/java/lang/Short.hx b/std/java/lang/Short.hx index 91f7f01a..d61fadaf 100644 --- a/std/java/lang/Short.hx +++ b/std/java/lang/Short.hx @@ -1,28 +1,34 @@ -package java.lang; +/* + * Copyright (C)2005-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 java.lang; @:native("") // make sure the generator won't see this +@:forwardStatics @:forward abstract Short(ShortClass) from ShortClass to ShortClass { @:to @:extern inline public function toShort():java.types.Int16 return this.shortValue(); @:from @:extern inline public static function fromShort(b:java.types.Int16):Short return ShortClass.valueOf(b); - - @:extern public static var MAX_VALUE(get,never):java.types.Int16; - @:extern static inline function get_MAX_VALUE():java.types.Int16 return ShortClass.MAX_VALUE; - @:extern public static var MIN_VALUE(get,never):java.types.Int16; - @:extern static inline function get_MIN_VALUE():java.types.Int16 return ShortClass.MIN_VALUE; - @:extern public static var SIZE(get,never):Int; - @:extern static inline function get_SIZE():Int return ShortClass.SIZE; - @:extern public static var TYPE(get,set):Class; - @:extern static inline function get_TYPE():Class return ShortClass.TYPE; - @:extern static inline function set_TYPE(val:Class):Class return ShortClass.TYPE = val; - @:extern @:overload inline public static function compare(param1:java.types.Int16, param2:java.types.Int16):Int return ShortClass.compare(param1, param2); - @:extern @:overload inline public static function decode(param1:String):Short return ShortClass.decode(param1); - @:extern @:overload inline public static function parseShort(param1:String, param2:Int):java.types.Int16 return ShortClass.parseShort(param1, param2); - @:extern @:overload inline public static function reverseBytes(param1:java.types.Int16):java.types.Int16 return ShortClass.reverseBytes(param1); - @:extern @:overload inline public static function _toString(param1:java.types.Int16):String return ShortClass._toString(param1); - @:extern @:overload inline public static function valueOf(param1:String, param2:Int):Short return ShortClass.valueOf(param1, param2); } @:native("java.lang.Short") extern class ShortClass extends Number implements Comparable diff --git a/std/java/net/SslSocket.hx b/std/java/net/SslSocket.hx index 6b333e25..60e543a8 100644 --- a/std/java/net/SslSocket.hx +++ b/std/java/net/SslSocket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/java/types/Char16.hx b/std/java/types/Char16.hx index 171e3ee7..893366d5 100644 --- a/std/java/types/Char16.hx +++ b/std/java/types/Char16.hx @@ -1,3 +1,24 @@ -package java.types; +/* + * Copyright (C)2005-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 java.types; typedef Char16 = java.StdTypes.Char16; diff --git a/std/java/types/Int16.hx b/std/java/types/Int16.hx index 227cb043..a28857a7 100644 --- a/std/java/types/Int16.hx +++ b/std/java/types/Int16.hx @@ -1,3 +1,24 @@ -package java.types; +/* + * Copyright (C)2005-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 java.types; typedef Int16 = java.StdTypes.Int16; diff --git a/std/java/types/Int8.hx b/std/java/types/Int8.hx index ad7fecec..e5b50b17 100644 --- a/std/java/types/Int8.hx +++ b/std/java/types/Int8.hx @@ -1,3 +1,24 @@ -package java.types; +/* + * Copyright (C)2005-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 java.types; typedef Int8 = java.StdTypes.Int8; diff --git a/std/java/vm/AtomicList.hx b/std/java/vm/AtomicList.hx index fe55d4d5..29671dd7 100644 --- a/std/java/vm/AtomicList.hx +++ b/std/java/vm/AtomicList.hx @@ -1,4 +1,25 @@ -package java.vm; +/* + * Copyright (C)2005-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 java.vm; import java.util.concurrent.atomic.AtomicReference; diff --git a/std/java/vm/Deque.hx b/std/java/vm/Deque.hx index d9282880..b85cbfe5 100644 --- a/std/java/vm/Deque.hx +++ b/std/java/vm/Deque.hx @@ -1,4 +1,25 @@ -package java.vm; +/* + * Copyright (C)2005-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 java.vm; import java.Lib; /** diff --git a/std/java/vm/Gc.hx b/std/java/vm/Gc.hx index f6d58862..afa2f578 100644 --- a/std/java/vm/Gc.hx +++ b/std/java/vm/Gc.hx @@ -1,4 +1,25 @@ -package java.vm; +/* + * Copyright (C)2005-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 java.vm; @:native('haxe.java.vm.Gc') class Gc { diff --git a/std/java/vm/Lock.hx b/std/java/vm/Lock.hx index e7ebe3ac..fc4128d7 100644 --- a/std/java/vm/Lock.hx +++ b/std/java/vm/Lock.hx @@ -1,4 +1,25 @@ -package java.vm; +/* + * Copyright (C)2005-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 java.vm; import java.Lib; import java.lang.System; using haxe.Int64; diff --git a/std/java/vm/Mutex.hx b/std/java/vm/Mutex.hx index 9a87876e..6077bda1 100644 --- a/std/java/vm/Mutex.hx +++ b/std/java/vm/Mutex.hx @@ -1,9 +1,30 @@ -package java.vm; -import java.util.concurrent.Semaphore; +/* + * Copyright (C)2005-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 java.vm; +import java.util.concurrent.locks.ReentrantLock; @:native('haxe.java.vm.Mutex') class Mutex { - @:private var lock:Semaphore; + @:private var lock:ReentrantLock; /** Creates a mutex, which can be used to acquire a temporary lock to access some resource. @@ -11,7 +32,7 @@ import java.util.concurrent.Semaphore; **/ public function new() { - this.lock = new Semaphore(1); + this.lock = new ReentrantLock(); } /** @@ -19,7 +40,7 @@ import java.util.concurrent.Semaphore; **/ public function tryAcquire():Bool { - return this.lock.tryAcquire(); + return this.lock.tryLock(); } /** @@ -28,7 +49,7 @@ import java.util.concurrent.Semaphore; **/ public function acquire():Void { - this.lock.acquire(); + this.lock.lock(); } /** @@ -36,6 +57,6 @@ import java.util.concurrent.Semaphore; **/ public function release():Void { - this.lock.release(); + this.lock.unlock(); } } diff --git a/std/java/vm/Thread.hx b/std/java/vm/Thread.hx index 4bb31128..84bb1dae 100644 --- a/std/java/vm/Thread.hx +++ b/std/java/vm/Thread.hx @@ -1,4 +1,25 @@ -package java.vm; +/* + * Copyright (C)2005-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 java.vm; import java.Lib; @:native('haxe.java.vm.Thread') class Thread diff --git a/std/java/vm/Tls.hx b/std/java/vm/Tls.hx index 01fcdae5..375b4778 100644 --- a/std/java/vm/Tls.hx +++ b/std/java/vm/Tls.hx @@ -1,4 +1,25 @@ -package java.vm; +/* + * Copyright (C)2005-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 java.vm; /** Thread-local Storage implementation diff --git a/std/js/Boot.hx b/std/js/Boot.hx old mode 100755 new mode 100644 index a8f03722..de0bfa87 --- a/std/js/Boot.hx +++ b/std/js/Boot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -31,6 +31,10 @@ private class HaxeError extends js.Error { this.message = String(val); if (js.Error.captureStackTrace) js.Error.captureStackTrace(this, HaxeError); } + + public static function wrap(val:Dynamic):Dynamic untyped { + return if (__instanceof__(val, js.Error)) val else new HaxeError(val); + } } @:dox(hide) @@ -187,7 +191,7 @@ class Boot { return false; switch( cl ) { case Int: - return (untyped __js__("(o|0) === o")); + return (untyped __js__("typeof"))(o) == "number" && untyped __js__("(o|0) === o"); case Float: return (untyped __js__("typeof"))(o) == "number"; case Bool: @@ -226,7 +230,7 @@ class Boot { else throw "Cannot cast " +Std.string(o) + " to " +Std.string(t); } - static var __toStr = untyped __js__("{}.toString"); + static var __toStr = untyped ({}).toString; // get native JS [[Class]] static function __nativeClassName(o:Dynamic):String { var name = untyped __toStr.call(o).slice(8, -1); diff --git a/std/js/Browser.hx b/std/js/Browser.hx index 03bb3332..aaf01421 100644 --- a/std/js/Browser.hx +++ b/std/js/Browser.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/js/Cookie.hx b/std/js/Cookie.hx index 679460fa..0b0cc4f9 100644 --- a/std/js/Cookie.hx +++ b/std/js/Cookie.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,7 +24,7 @@ package js; class Cookie { /** Create or update a cookie. - expireDelay (seconds), if null, the cookie expires at end of session + @param expireDelay In seconds. If null, the cookie expires at end of session. **/ public static function set( name : String, value : String, ?expireDelay : Int, ?path : String, ?domain : String ){ var s = name+"="+StringTools.urlEncode(value); @@ -42,7 +42,7 @@ class Cookie { } /** - Returns all cookies + Returns all cookies. **/ public static function all(){ var h = new haxe.ds.StringMap(); @@ -65,14 +65,14 @@ class Cookie { } /** - Returns true if a cookie [name] exists + Returns true if a cookie `name` exists. **/ public static function exists( name : String ){ return all().exists(name); } /** - Remove a cookie + Remove a cookie. **/ public static function remove( name : String, ?path : String, ?domain : String ){ set(name,"",-10,path,domain); diff --git a/std/js/Error.hx b/std/js/Error.hx index bf727f8a..e960866c 100644 --- a/std/js/Error.hx +++ b/std/js/Error.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/js/JQuery.hx b/std/js/JQuery.hx index 7e7c0683..2c2273cd 100644 --- a/std/js/JQuery.hx +++ b/std/js/JQuery.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,6 +24,7 @@ package js; import js.html.Window; import js.html.Element; +@:deprecated("Use js.jquery.Event instead.") typedef JqEvent = { var target : Element; var currentTarget : Element; @@ -62,6 +63,7 @@ typedef JqEvent = { function stopPropagation() : Void; } +@:deprecated("Use js.jquery.Helper instead.") extern class JQueryHelper { @:overload(function(j:JQuery):JQuery{}) @:overload(function(j:Window):JQuery{}) @@ -79,6 +81,7 @@ extern class JQueryHelper { } +@:deprecated("Use js.jquery.JQuery instead.") @:initPackage extern class JQuery implements ArrayAccess { @@ -337,6 +340,7 @@ extern class JQuery implements ArrayAccess { // JQuery 1.7+ @:overload(function(events:DynamicVoid>):JQuery{}) + @:overload(function(events : String, selector : String, callb : JqEvent -> Void ):JQuery{}) function on( events : String, callb : JqEvent -> Void ) : JQuery; // queue @@ -397,8 +401,7 @@ extern class JQuery implements ArrayAccess { private static function __init__() : Void untyped { #if embed_js - if( untyped __js__("typeof($) == 'undefined'") ) - haxe.macro.Compiler.includeFile("js/jquery-latest.min.js"); + #error "Haxe no longer bundle third-party JS libraries. Please remove `-D embed-js`. You may download the JS files and use `haxe.macro.Compiler.includeFile`." #end var q : Dynamic = (untyped js.Browser.window).jQuery; untyped __js__("var js = js || {}"); diff --git a/std/js/Lib.hx b/std/js/Lib.hx index 2efce59a..45499e35 100644 --- a/std/js/Lib.hx +++ b/std/js/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,10 @@ */ package js; +/** + Platform-specific JavaScript Library. Provides some platform-specific functions + for the JavaScript target. +**/ class Lib { /** @@ -50,7 +54,7 @@ class Lib { This is only supported in environments where `require` function is available, such as Node.js or RequireJS. **/ - public static inline function require( module:String ) : Dynamic { + @:extern public static inline function require( module:String ) : Dynamic { return untyped __js__("require")(module); } @@ -100,4 +104,13 @@ class Lib { @:extern static inline function get_global() : Dynamic { return untyped __define_feature__("js.Lib.global", __js__("$global")); // $global is generated by the compiler } + + /** + Re-throw last cathed exception, preserving original stack information. + + Calling this only makes sense inside a catch statement. + **/ + @:extern public static inline function rethrow() { + untyped __define_feature__("js.Lib.rethrow", __rethrow__()); + } } diff --git a/std/js/Promise.hx b/std/js/Promise.hx index 694fc53d..ff827297 100644 --- a/std/js/Promise.hx +++ b/std/js/Promise.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -29,7 +29,7 @@ extern class Promise { @:overload(function(promise : Promise) : Promise {}) @:overload(function(thenable : Thenable) : Promise {}) - static function resolve( value : T ) : Promise; + static function resolve( ?value : T ) : Promise; static function reject( ?value : Dynamic ) : Promise; @@ -40,7 +40,7 @@ extern class Promise /** @throws DOMError */ function new( init : (T -> Void) -> (Dynamic -> Void) -> Void ) : Void; - function then( ?fulfillCallback : PromiseCallback, ?rejectCallback : EitherType Void, PromiseCallback> ) : Promise; + function then( fulfillCallback : Null>, ?rejectCallback : EitherType Void, PromiseCallback> ) : Promise; @:native("catch") function catchError( rejectCallback : EitherType Void, PromiseCallback> ) : Promise; @@ -49,5 +49,5 @@ extern class Promise typedef PromiseCallback = EitherType TOut, T -> Promise>; typedef Thenable = { - then : EitherType<(T -> Void) -> (Dynamic -> Void) -> Void, (T -> Void) -> Void> + function then(resolve:T->Void, ?reject:Dynamic->Void):Void; } diff --git a/std/js/RegExp.hx b/std/js/RegExp.hx index c211f08d..b34014c0 100644 --- a/std/js/RegExp.hx +++ b/std/js/RegExp.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,7 +24,8 @@ /** Native JavaScript regular expressions. - For cross-platform regular expressions, use haxe `EReg` class or regexp literals. + For cross-platform regular expressions, use Haxe `EReg` class or + [regexp literals](https://haxe.org/manual/std-regex.html). **/ @:native("RegExp") extern class RegExp { diff --git a/std/js/SWFObject.hx b/std/js/SWFObject.hx index fcf88798..382e358c 100644 --- a/std/js/SWFObject.hx +++ b/std/js/SWFObject.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,7 @@ */ package js; +@:deprecated("Use js.swfobject.SWFObject instead.") @:initPackage extern class SWFObject { @@ -33,7 +34,7 @@ extern class SWFObject { private static function __init__() : Void untyped { #if embed_js - haxe.macro.Compiler.includeFile("js/swfobject-1.5.js"); + #error "Haxe no longer bundle third-party JS libraries. Please remove `-D embed-js`. You may download the JS files and use `haxe.macro.Compiler.includeFile`." #end js.SWFObject = deconcept.SWFObject; } diff --git a/std/js/Selection.hx b/std/js/Selection.hx index 1cc18957..83c03b09 100644 --- a/std/js/Selection.hx +++ b/std/js/Selection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/js/XMLSocket.hx b/std/js/XMLSocket.hx index e5463846..db867530 100644 --- a/std/js/XMLSocket.hx +++ b/std/js/XMLSocket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,7 +22,8 @@ package js; /** - By compiling the [haxe.remoting.SocketWrapper] into a SWF, you can create and use XMLSockets directly from Javascript. + By compiling the `haxe.remoting.SocketWrapper` into a SWF, you can create + and use XMLSockets directly from Javascript. **/ class XMLSocket { diff --git a/std/js/_std/Array.hx b/std/js/_std/Array.hx index af9c5dde..45b642ac 100644 --- a/std/js/_std/Array.hx +++ b/std/js/_std/Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -45,7 +45,7 @@ extern class Array { return @:privateAccess HxOverrides.remove(this,x); } -#if js_es5 +#if (js_es >= 5) function indexOf( x : T, ?fromIndex:Int ) : Int; function lastIndexOf( x : T, ?fromIndex:Int ) : Int; diff --git a/std/js/_std/Date.hx b/std/js/_std/Date.hx index 20ac34fb..5a7c7ff7 100644 --- a/std/js/_std/Date.hx +++ b/std/js/_std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,31 +21,29 @@ */ @:coreApi extern class Date { - function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void; - function getTime() : Float; - function getHours() : Int; - function getMinutes() : Int; - function getSeconds() : Int; - function getFullYear() : Int; - function getMonth() : Int; - function getDate() : Int; - function getDay() : Int; + @:pure function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void; + @:pure function getTime() : Float; + @:pure function getHours() : Int; + @:pure function getMinutes() : Int; + @:pure function getSeconds() : Int; + @:pure function getFullYear() : Int; + @:pure function getMonth() : Int; + @:pure function getDate() : Int; + @:pure function getDay() : Int; - inline function toString() : String { + @:pure inline function toString() : String { return untyped HxOverrides.dateStr(this); } - static inline function now() : Date { + @:pure static inline function now() : Date { return untyped __new__(Date); } - static inline function fromTime( t : Float ) : Date { - var d : Date = untyped __new__(Date); - untyped d["setTime"]( t ); - return d; + @:pure static inline function fromTime( t : Float ) : Date { + return untyped __new__(Date, t); } - static inline function fromString( s : String ) : Date { + @:pure static inline function fromString( s : String ) : Date { return untyped HxOverrides.strDate(s); } } diff --git a/std/js/_std/EReg.hx b/std/js/_std/EReg.hx index 30614594..e4b8951d 100644 --- a/std/js/_std/EReg.hx +++ b/std/js/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -23,9 +23,8 @@ var r : HaxeRegExp; - public function new( r : String, opt : String ) : Void { - opt = opt.split("u").join(""); // 'u' (utf8) depends on page encoding - this.r = new HaxeRegExp(r, opt); + public inline function new( r : String, opt : String ) : Void { + this.r = new HaxeRegExp(r, opt.split("u").join("")); // 'u' (utf8) depends on page encoding } public function match( s : String ) : Bool { @@ -81,7 +80,7 @@ return untyped s.replace(r,d).split(d); } - public function replace( s : String, by : String ) : String { + public inline function replace( s : String, by : String ) : String { return untyped s.replace(r,by); } diff --git a/std/js/_std/HxOverrides.hx b/std/js/_std/HxOverrides.hx index eeb44934..8b0d9fe8 100644 --- a/std/js/_std/HxOverrides.hx +++ b/std/js/_std/HxOverrides.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -62,19 +62,27 @@ class HxOverrides { static function cca( s : String, index : Int ) : Null { var x = (cast s).charCodeAt(index); if( x != x ) // fast isNaN - return untyped undefined; // isNaN will still return true + return js.Lib.undefined; // isNaN will still return true return x; } static function substr( s : String, pos : Int, ?len : Int ) : String { - if( pos != null && pos != 0 && len != null && len < 0 ) return ""; - if( len == null ) len = s.length; - if( pos < 0 ){ + if (len == null) { + len = s.length; + } else if (len < 0) { + if (pos == 0) + len = s.length + len; + else + return ""; + } + + #if (js_es < 5) + if (pos < 0) { pos = s.length + pos; - if( pos < 0 ) pos = 0; - }else if( len < 0 ){ - len = s.length + len - pos; + if (pos < 0) + pos = 0; } + #end return (untyped s).substr(pos, len); } @@ -130,7 +138,7 @@ class HxOverrides { } static function __init__() untyped { -#if !js_es5 +#if (js_es < 5) __feature__('HxOverrides.indexOf', if( Array.prototype.indexOf ) __js__("HxOverrides").indexOf = function(a,o,i) return Array.prototype.indexOf.call(a, o, i)); __feature__('HxOverrides.lastIndexOf', if( Array.prototype.lastIndexOf ) __js__("HxOverrides").lastIndexOf = function(a,o,i) return Array.prototype.lastIndexOf.call(a, o, i)); #end diff --git a/std/js/_std/Math.hx b/std/js/_std/Math.hx index 9538df64..659344fe 100644 --- a/std/js/_std/Math.hx +++ b/std/js/_std/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -29,56 +29,56 @@ extern class Math static var PI(default,null) : Float; static var NEGATIVE_INFINITY(get, null) : Float; - private static inline function get_NEGATIVE_INFINITY () : Float { + @:pure private static inline function get_NEGATIVE_INFINITY () : Float { return -(untyped __js__("Infinity")); } static var POSITIVE_INFINITY(get,null) : Float; - private static inline function get_POSITIVE_INFINITY () : Float { + @:pure private static inline function get_POSITIVE_INFINITY () : Float { return (untyped __js__("Infinity")); } static var NaN(get, null) : Float; - private static inline function get_NaN () : Float { + @:pure private static inline function get_NaN () : Float { return (untyped __js__("NaN")); } - static function abs(v:Float):Float; - static function acos(v:Float):Float; - static function asin(v:Float):Float; - static function atan(v:Float):Float; - static function atan2(y:Float, x:Float):Float; - static function ceil(v:Float):Int; - static function cos(v:Float):Float; - static function exp(v:Float):Float; - static function floor(v:Float):Int; - static function log(v:Float):Float; - static function max(a:Float, b:Float):Float; - static function min(a:Float, b:Float):Float; - static function pow(v:Float, exp:Float):Float; + @:pure static function abs(v:Float):Float; + @:pure static function acos(v:Float):Float; + @:pure static function asin(v:Float):Float; + @:pure static function atan(v:Float):Float; + @:pure static function atan2(y:Float, x:Float):Float; + @:pure static function ceil(v:Float):Int; + @:pure static function cos(v:Float):Float; + @:pure static function exp(v:Float):Float; + @:pure static function floor(v:Float):Int; + @:pure static function log(v:Float):Float; + @:pure static function max(a:Float, b:Float):Float; + @:pure static function min(a:Float, b:Float):Float; + @:pure static function pow(v:Float, exp:Float):Float; static function random() : Float; - static function round(v:Float):Int; - static function sin(v:Float):Float; - static function sqrt(v:Float):Float; - static function tan(v:Float):Float; + @:pure static function round(v:Float):Int; + @:pure static function sin(v:Float):Float; + @:pure static function sqrt(v:Float):Float; + @:pure static function tan(v:Float):Float; - static inline function ffloor( v : Float ) : Float { + @:pure static inline function ffloor( v : Float ) : Float { return floor(v); } - static inline function fceil( v : Float ) : Float { + @:pure static inline function fceil( v : Float ) : Float { return ceil(v); } - static inline function fround( v : Float ) : Float { + @:pure static inline function fround( v : Float ) : Float { return round(v); } - static inline function isFinite( f : Float ) : Bool { + @:pure static inline function isFinite( f : Float ) : Bool { return (untyped __js__("isFinite"))(f); } - static inline function isNaN( f : Float ) : Bool { + @:pure static inline function isNaN( f : Float ) : Bool { return (untyped __js__("isNaN"))(f); } diff --git a/std/js/_std/Reflect.hx b/std/js/_std/Reflect.hx index ce374a31..78642e0a 100644 --- a/std/js/_std/Reflect.hx +++ b/std/js/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,7 @@ */ @:coreApi class Reflect { + @:pure public inline static function hasField( o : Dynamic, field : String ) : Bool { return untyped __js__('Object').prototype.hasOwnProperty.call(o, field); } diff --git a/std/js/_std/Std.hx b/std/js/_std/Std.hx index 81c72f12..9dbcb968 100644 --- a/std/js/_std/Std.hx +++ b/std/js/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -32,6 +32,7 @@ import js.Boot; return untyped __instanceof__(value, c) ? cast value : null; } + @:pure public static function string( s : Dynamic ) : String { return untyped js.Boot.__string_rec(s,""); } @@ -40,6 +41,7 @@ import js.Boot; return (cast x) | 0; } + @:pure public static function parseInt( x : String ) : Null { var v = untyped __js__("parseInt")(x, 10); // parse again if hexadecimal @@ -55,7 +57,7 @@ import js.Boot; } public static function random( x : Int ) : Int { - return untyped x <= 0 ? 0 : Math.floor(Math.random()*x); + return x <= 0 ? 0 : Math.floor(Math.random()*x); } static function __init__() : Void untyped { @@ -91,7 +93,7 @@ import js.Boot; var Void = __feature__("Type.resolveEnum", $hxClasses["Void"] = { __ename__ : ["Void"] }, { __ename__ : ["Void"] }); }); -#if !js_es5 +#if (js_es < 5) __feature__("Array.map", if( Array.prototype.map == null ) Array.prototype.map = function(f) { diff --git a/std/js/_std/String.hx b/std/js/_std/String.hx index 65198b9d..e3c53178 100644 --- a/std/js/_std/String.hx +++ b/std/js/_std/String.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/js/_std/Type.hx b/std/js/_std/Type.hx old mode 100755 new mode 100644 index f2949eb4..45634a0a --- a/std/js/_std/Type.hx +++ b/std/js/_std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + enum ValueType { TNull; TInt; @@ -96,10 +97,21 @@ enum ValueType { return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6]); case 8: return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]); + case 9: + return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]); + case 10: + return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]); + case 11: + return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]); + case 12: + return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]); + case 13: + return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]); + case 14: + return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]); default: throw "Too many arguments"; } - return null; } public static function createEmptyInstance( cl : Class ) : T untyped { @@ -144,9 +156,8 @@ enum ValueType { return a; } - public static function getEnumConstructs( e : Enum ) : Array { - var a : Array = untyped e.__constructs__; - return a.copy(); + public static inline function getEnumConstructs( e : Enum ) : Array { + return ((cast e).__constructs__ : Array).copy(); } public static function typeof( v : Dynamic ) : ValueType untyped { @@ -209,8 +220,8 @@ enum ValueType { return untyped e[1]; } - public static function allEnums( e : Enum ) : Array { - return untyped e.__empty_constructs__; + public inline static function allEnums( e : Enum ) : Array { + return untyped __define_feature__("Type.allEnums", e.__empty_constructs__); } } diff --git a/std/js/_std/haxe/Json.hx b/std/js/_std/haxe/Json.hx index 0d2bd412..fa414840 100644 --- a/std/js/_std/haxe/Json.hx +++ b/std/js/_std/haxe/Json.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/js/_std/haxe/ds/IntMap.hx b/std/js/_std/haxe/ds/IntMap.hx index 6f9fd0e8..795b1936 100644 --- a/std/js/_std/haxe/ds/IntMap.hx +++ b/std/js/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -49,12 +49,7 @@ package haxe.ds; public function keys() : Iterator { var a = []; - untyped { - __js__("for( var key in this.h ) {"); - if( h.hasOwnProperty(key) ) - a.push(key|0); - __js__("}"); - } + untyped __js__("for( var key in {0} ) {1}", h, if( h.hasOwnProperty(key) ) a.push(key|0)); return a.iterator(); } diff --git a/std/js/_std/haxe/ds/ObjectMap.hx b/std/js/_std/haxe/ds/ObjectMap.hx index 155fded5..ee103cd3 100644 --- a/std/js/_std/haxe/ds/ObjectMap.hx +++ b/std/js/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of h software and associated documentation files (the "Software"), @@ -38,12 +38,11 @@ class ObjectMap implements haxe.Constraints.IMap { var h : { }; public function new() : Void { - h = { }; - untyped h.__keys__ = { }; + h = { __keys__: {} }; } public function set(key:K, value:V):Void untyped { - var id : Int = untyped key.__id__ || assignId(key); + var id : Int = getId(key) || assignId(key); h[id] = value; h.__keys__[id] = key; } diff --git a/std/js/_std/haxe/ds/StringMap.hx b/std/js/_std/haxe/ds/StringMap.hx index cce32827..1a875f7d 100644 --- a/std/js/_std/haxe/ds/StringMap.hx +++ b/std/js/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -134,7 +134,7 @@ private class StringMapIterator { s.add(k); s.add(" => "); s.add(Std.string(get(k))); - if( i < keys.length ) + if( i < keys.length-1 ) s.add(", "); } s.add("}"); diff --git a/std/js/_std/haxe/io/ArrayBufferView.hx b/std/js/_std/haxe/io/ArrayBufferView.hx index a983272e..0026057a 100644 --- a/std/js/_std/haxe/io/ArrayBufferView.hx +++ b/std/js/_std/haxe/io/ArrayBufferView.hx @@ -1,12 +1,37 @@ -package haxe.io; +/* + * Copyright (C)2005-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 haxe.io; typedef ArrayBufferViewData = js.html.ArrayBufferView; abstract ArrayBufferView(ArrayBufferViewData) { public static var EMULATED(get,never) : Bool; - static function get_EMULATED() { + static inline function get_EMULATED() { + #if nodejs + return false; + #else return (cast js.html.ArrayBuffer) == js.html.compat.ArrayBuffer; + #end } public var buffer(get,never) : haxe.io.Bytes; @@ -19,16 +44,12 @@ abstract ArrayBufferView(ArrayBufferViewData) { inline function get_byteOffset() return this.byteOffset; inline function get_byteLength() return this.byteLength; - function get_buffer() : haxe.io.Bytes { + inline function get_buffer() : haxe.io.Bytes { return haxe.io.Bytes.ofData(this.buffer); } public inline function sub( begin : Int, ?length : Int ) { - #if js return fromData(new js.html.Uint8Array(this.buffer.slice(begin, length == null ? null : begin+length))); - #else - return fromData(this.sub(begin,length)); - #end } public inline function getData() : ArrayBufferViewData { diff --git a/std/js/_std/haxe/io/Bytes.hx b/std/js/_std/haxe/io/Bytes.hx index d2eea72f..0f67ad8b 100644 --- a/std/js/_std/haxe/io/Bytes.hx +++ b/std/js/_std/haxe/io/Bytes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,8 +20,11 @@ * DEALINGS IN THE SOFTWARE. */ package haxe.io; + +#if !nodejs import js.html.compat.Uint8Array; import js.html.compat.DataView; +#end @:coreApi class Bytes { @@ -50,7 +53,7 @@ class Bytes { public function blit( pos : Int, src : Bytes, srcpos : Int, len : Int ) : Void { if( pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length ) throw Error.OutsideBounds; - if( srcpos == 0 && len == src.length ) + if( srcpos == 0 && len == src.b.byteLength ) b.set(src.b,pos); else b.set(src.b.subarray(srcpos,srcpos+len),pos); @@ -187,7 +190,7 @@ class Bytes { return untyped b.bufferValue; } - public static function alloc( length : Int ) : Bytes { + public static inline function alloc( length : Int ) : Bytes { return new Bytes(new BytesData(length)); } diff --git a/std/js/_std/haxe/io/Float32Array.hx b/std/js/_std/haxe/io/Float32Array.hx index aaf256bb..fb065ef0 100644 --- a/std/js/_std/haxe/io/Float32Array.hx +++ b/std/js/_std/haxe/io/Float32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,7 +21,9 @@ */ package haxe.io; +#if !nodejs import js.html.compat.Float32Array; +#end typedef Float32ArrayData = js.html.Float32Array; @@ -64,7 +66,7 @@ abstract Float32Array(Float32ArrayData) { return this; } - public static function fromData( d : Float32ArrayData ) : Float32Array { + public inline static function fromData( d : Float32ArrayData ) : Float32Array { return cast d; } diff --git a/std/js/_std/haxe/io/Float64Array.hx b/std/js/_std/haxe/io/Float64Array.hx index a4a8c1a0..bf0fd36b 100644 --- a/std/js/_std/haxe/io/Float64Array.hx +++ b/std/js/_std/haxe/io/Float64Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,7 +21,9 @@ */ package haxe.io; +#if !nodejs import js.html.compat.Float64Array; +#end typedef Float64ArrayData = js.html.Float64Array; @@ -64,7 +66,7 @@ abstract Float64Array(Float64ArrayData) { return this; } - public static function fromData( d : Float64ArrayData ) : Float64Array { + public static inline function fromData( d : Float64ArrayData ) : Float64Array { return cast d; } diff --git a/std/js/_std/haxe/io/Int32Array.hx b/std/js/_std/haxe/io/Int32Array.hx index a705bdd8..dc0f045b 100644 --- a/std/js/_std/haxe/io/Int32Array.hx +++ b/std/js/_std/haxe/io/Int32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -62,7 +62,7 @@ abstract Int32Array(Int32ArrayData) { return this; } - public static function fromData( d : Int32ArrayData ) : Int32Array { + public static inline function fromData( d : Int32ArrayData ) : Int32Array { return cast d; } diff --git a/std/js/_std/haxe/io/UInt16Array.hx b/std/js/_std/haxe/io/UInt16Array.hx index a85c44e4..62eb8be3 100644 --- a/std/js/_std/haxe/io/UInt16Array.hx +++ b/std/js/_std/haxe/io/UInt16Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -62,7 +62,7 @@ abstract UInt16Array(UInt16ArrayData) { return this; } - public static function fromData( d : UInt16ArrayData ) : UInt16Array { + public static inline function fromData( d : UInt16ArrayData ) : UInt16Array { return cast d; } diff --git a/std/js/_std/haxe/io/UInt32Array.hx b/std/js/_std/haxe/io/UInt32Array.hx index 70099a58..87c9a910 100644 --- a/std/js/_std/haxe/io/UInt32Array.hx +++ b/std/js/_std/haxe/io/UInt32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -62,7 +62,7 @@ abstract UInt32Array(UInt32ArrayData) { return this; } - public static function fromData( d : UInt32ArrayData ) : UInt32Array { + public static inline function fromData( d : UInt32ArrayData ) : UInt32Array { return cast d; } diff --git a/std/js/_std/haxe/io/UInt8Array.hx b/std/js/_std/haxe/io/UInt8Array.hx index 93df4a36..cc781fc2 100644 --- a/std/js/_std/haxe/io/UInt8Array.hx +++ b/std/js/_std/haxe/io/UInt8Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -62,7 +62,7 @@ abstract UInt8Array(UInt8ArrayData) { return this; } - public static function fromData( d : UInt8ArrayData ) : UInt8Array { + public static inline function fromData( d : UInt8ArrayData ) : UInt8Array { return cast d; } diff --git a/std/js/html/AlignSetting.hx b/std/js/html/AlignSetting.hx index 896e410b..8f7ed577 100644 --- a/std/js/html/AlignSetting.hx +++ b/std/js/html/AlignSetting.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/VTTCue.webidl line 12:0. Do not edit! +// This file is generated from mozilla\VTTCue.webidl. Do not edit! package js.html; diff --git a/std/js/html/AnchorElement.hx b/std/js/html/AnchorElement.hx index 10b1c91f..951c3115 100644 --- a/std/js/html/AnchorElement.hx +++ b/std/js/html/AnchorElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,25 +20,80 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLAnchorElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLAnchorElement.webidl. Do not edit! package js.html; +/** + The `HTMLAnchorElement` interface represents hyperlink elements and provides special properties and methods (beyond those of the regular `HTMLElement` object interface they also have available to them by inheritance) for manipulating the layout and presentation of such elements. + + Documentation [HTMLAnchorElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLAnchorElement") extern class AnchorElement extends Element { + + /** + Is a `DOMString` that reflects the `target` HTML attribute, indicating where to display the linked resource. + **/ var target : String; + + /** + Is a `DOMString` indicating that the linked resource is intended to be downloaded rather than displayed in the browser. The value represent the proposed name of the file. If the name is not a valid filename of the underlying OS, browser will adapt it. The value is a URL with a scheme like `http:`, `file:`, `data:` or even `blob:` (created with `URL.createObjectURL`). + **/ var download : String; var ping : String; + + /** + Is a `DOMString` that reflects the `rel` HTML attribute, specifying the relationship of the target object to the linked object. + **/ var rel : String; + + /** + Returns a `DOMTokenList` that reflects the `rel` HTML attribute, as a list of tokens. + **/ var relList(default,null) : DOMTokenList; + + /** + Is a `DOMString` that reflects the `hreflang` HTML attribute, indicating the language of the linked resource. + **/ var hreflang : String; + + /** + Is a `DOMString` that reflects the `type` HTML attribute, indicating the MIME type of the linked resource. + **/ var type : String; + + /** + Is a `DOMString` being a synonym for the `Node.textContent` property. + **/ var text : String; + + /** + Is a `DOMString` representing a comma-separated list of coordinates. + **/ var coords : String; + + /** + Is a `DOMString` representing the character encoding of the linked resource. + **/ var charset : String; + + /** + Is a `DOMString` representing the anchor name. + **/ var name : String; + + /** + Is a `DOMString` representing that the `rev` HTML attribute, specifying the relationship of the link object to the target object. + **/ var rev : String; + + /** + Is a `DOMString` representing the shape of the active area. + **/ var shape : String; var href : String; var origin(default,null) : String; @@ -51,6 +106,5 @@ extern class AnchorElement extends Element var pathname : String; var search : String; var hash : String; - var searchParams : URLSearchParams; } \ No newline at end of file diff --git a/std/js/html/Animation.hx b/std/js/html/Animation.hx index bb4d8719..ca489992 100644 --- a/std/js/html/Animation.hx +++ b/std/js/html/Animation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,105 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Animation.webidl line 14:0. Do not edit! +// This file is generated from mozilla\Animation.webidl. Do not edit! package js.html; +/** + The `Animation` interface of the Web Animations API represents a single animation player and provides playback controls and a timeline for an animation node or source. + + Documentation [Animation](https://developer.mozilla.org/en-US/docs/Web/API/Animation) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Animation$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Animation") -extern class Animation +extern class Animation extends EventTarget { - var effect(default,null) : AnimationEffect; - var target(default,null) : Element; + /** + Gets and sets the `String` used to identify the animation. + **/ + var id : String; + + /** + Gets and sets the `AnimationEffectReadOnly` associated with this animation. This will usually be a `KeyframeEffect` object. + **/ + var effect(default,null) : AnimationEffectReadOnly; + + /** + Gets or sets the `AnimationTimeline` associated with this animation. + **/ + var timeline(default,null) : AnimationTimeline; + + /** + Gets or sets the scheduled time when an animation's playback should begin. + **/ + var startTime : Float; + + /** + The current time value of the animation in milliseconds, whether running or paused. If the animation lacks a `AnimationTimeline`, is inactive or hasn't been played yet, its value is `null`. + **/ + var currentTime : Float; + + /** + Gets or sets the playback rate of the animation. + **/ + var playbackRate : Float; + + /** + Returns an enumerated value describing the playback state of an animation. + **/ + var playState(default,null) : AnimationPlayState; + + /** + Returns the current ready Promise for this animation. + **/ + var ready(default,null) : Promise; + + /** + Returns the current finished Promise for this animation. + **/ + var finished(default,null) : Promise; + + /** + Gets and sets the event handler for the `finish` event. + **/ + var onfinish : haxe.Constraints.Function; + + /** + Gets and sets the event handler for the `cancel` event. + **/ + var oncancel : haxe.Constraints.Function; + + /** @throws DOMError */ + function new( ?effect : KeyframeEffectReadOnly, ?timeline : AnimationTimeline ) : Void; + + /** + Clears all `KeyframeEffect` caused by this animation and aborts its playback. + **/ + function cancel() : Void; + /** @throws DOMError */ + + /** + Seeks either end of an animation, depending on whether the animation is playing or reversing. + **/ + function finish() : Void; + /** @throws DOMError */ + + /** + Starts or resumes playing of an animation, or begins the animation again if it previously finished. + **/ + function play() : Void; + /** @throws DOMError */ + + /** + Suspends playing of an animation. + **/ + function pause() : Void; + /** @throws DOMError */ + + /** + Reverses playback direction, stopping at the start of the animation. If the animation is finished or unplayed, it will play from end to beginning. + **/ + function reverse() : Void; } \ No newline at end of file diff --git a/std/js/html/AnimationEffectReadOnly.hx b/std/js/html/AnimationEffectReadOnly.hx new file mode 100644 index 00000000..23a6007c --- /dev/null +++ b/std/js/html/AnimationEffectReadOnly.hx @@ -0,0 +1,48 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\AnimationEffectReadOnly.webidl. Do not edit! + +package js.html; + +/** + The `AnimationEffectReadOnly` interface of the Web Animations API defines current and future animation effects like `KeyframeEffect`, which can be passed to `Animation` objects for playing, and `KeyframeEffectReadOnly` (which is used by CSS Animations and Transitions). + + Documentation [AnimationEffectReadOnly](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffectReadOnly) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffectReadOnly$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("AnimationEffectReadOnly") +extern class AnimationEffectReadOnly +{ + + /** + The `AnimationEffectTimingReadOnly` object associated with the animation containing all the animation's timing values. + **/ + var timing(default,null) : AnimationEffectTimingReadOnly; + + + /** + Returns the calculated timing properties for this Animation Effect. + **/ + function getComputedTiming() : ComputedTimingProperties; +} \ No newline at end of file diff --git a/std/js/html/AnimationEffectTiming.hx b/std/js/html/AnimationEffectTiming.hx new file mode 100644 index 00000000..2a29b116 --- /dev/null +++ b/std/js/html/AnimationEffectTiming.hx @@ -0,0 +1,37 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\AnimationEffectTiming.webidl. Do not edit! + +package js.html; + +/** + The `AnimationEffectTiming` interface of the Web Animations API is comprised of timing properties. It is returned by the `timing` attribute of a `KeyframeEffect`. + + Documentation [AnimationEffectTiming](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffectTiming) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffectTiming$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("AnimationEffectTiming") +extern class AnimationEffectTiming extends AnimationEffectTimingReadOnly +{ +} \ No newline at end of file diff --git a/std/js/html/AnimationPlayer.hx b/std/js/html/AnimationEffectTimingProperties.hx similarity index 69% rename from std/js/html/AnimationPlayer.hx rename to std/js/html/AnimationEffectTimingProperties.hx index 6874ba8d..a3f85107 100644 --- a/std/js/html/AnimationPlayer.hx +++ b/std/js/html/AnimationEffectTimingProperties.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,19 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AnimationPlayer.webidl line 16:0. Do not edit! +// This file is generated from mozilla\AnimationEffectReadOnly.webidl. Do not edit! package js.html; -@:native("AnimationPlayer") -extern class AnimationPlayer +typedef AnimationEffectTimingProperties = { - var source(default,null) : Animation; - var timeline(default,null) : AnimationTimeline; - var startTime(default,null) : Float; - var currentTime(default,null) : Float; - var playState(default,null) : AnimationPlayState; - - function play() : Void; - function pause() : Void; + @:optional var delay : Float; + @:optional var direction : PlaybackDirection; + @:optional var duration : haxe.extern.EitherType; + @:optional var easing : String; + @:optional var endDelay : Float; + @:optional var fill : FillMode; + @:optional var iterationStart : Float; + @:optional var iterations : Float; } \ No newline at end of file diff --git a/std/js/html/AnimationEffectTimingReadOnly.hx b/std/js/html/AnimationEffectTimingReadOnly.hx new file mode 100644 index 00000000..c278f13e --- /dev/null +++ b/std/js/html/AnimationEffectTimingReadOnly.hx @@ -0,0 +1,78 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\AnimationEffectTimingReadOnly.webidl. Do not edit! + +package js.html; + +/** + The `AnimationEffectTimingReadOnly` interface of the Web Animations API is comprised of timing properties. + + Documentation [AnimationEffectTimingReadOnly](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffectTimingReadOnly) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffectTimingReadOnly$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("AnimationEffectTimingReadOnly") +extern class AnimationEffectTimingReadOnly +{ + + /** + The number of milliseconds to delay the start of the animation. Defaults to `0`. + **/ + var delay(default,null) : Float; + + /** + The number of milliseconds to delay after the end of an animation. This is primarily of use when sequencing animations based on the end time of another animation. Defaults to `0`. + **/ + var endDelay(default,null) : Float; + + /** + Dictates whether the animation's effects should be reflected by the element(s) state prior to playing (`backwards`), retained after the animation has completed playing (`forwards`), or `both`. Defaults to `none`. + **/ + var fill(default,null) : FillMode; + + /** + A number representing which repetition the animation begins at and its progress through it. + **/ + var iterationStart(default,null) : Float; + + /** + The number of times the animation should repeat. Defaults to `1`, and can also take a value of infinity to make it repeat infinitely. + **/ + var iterations(default,null) : Float; + + /** + The number of milliseconds each iteration of the animation takes to complete. Defaults to `0`. + **/ + var duration(default,null) : haxe.extern.EitherType; + + /** + Whether the animation runs forwards (`normal`), backwards (`reverse`), switches direction after each iteration (`alternate`), or runs backwards and switches direction after each iteration (`alternate-reverse`). Defaults to `normal`. + **/ + var direction(default,null) : PlaybackDirection; + + /** + The rate of the animation's change over time. Accepts the pre-defined values `linear`, `ease`, `ease-in`, `ease-out`, and `ease-in-out`, or a custom cubic-bezier value like `cubic-bezier(0.42, 0, 0.58, 1)`. Defaults to `linear`. + **/ + var easing(default,null) : String; + +} \ No newline at end of file diff --git a/std/js/html/AnimationEvent.hx b/std/js/html/AnimationEvent.hx index 769fbcbe..3d5dcc76 100644 --- a/std/js/html/AnimationEvent.hx +++ b/std/js/html/AnimationEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AnimationEvent.webidl line 15:0. Do not edit! +// This file is generated from mozilla\AnimationEvent.webidl. Do not edit! package js.html; +/** + The `AnimationEvent` interface represents events providing information related to animations. + + Documentation [AnimationEvent](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AnimationEvent") extern class AnimationEvent extends Event { + + /** + Is a `DOMString` containing the value of the `animation-name` CSS property associated with the transition. + **/ var animationName(default,null) : String; + + /** + Is a `float` giving the amount of time the animation has been running, in seconds, when this event fired, excluding any time the animation was paused. For an `"animationstart"` event, `elapsedTime` is `0.0` unless there was a negative value for `animation-delay`, in which case the event will be fired with `elapsedTime` containing  `(-1 * `delay`)`. + **/ var elapsedTime(default,null) : Float; + + /** + Is a `DOMString`, starting with `'::'`, containing the name of the pseudo-element the animation runs on. If the animation doesn't run on a pseudo-element but on the element, an empty string: `''``.` + **/ var pseudoElement(default,null) : String; /** @throws DOMError */ diff --git a/std/js/html/AnimationEventInit.hx b/std/js/html/AnimationEventInit.hx index 0414fd91..25c284e0 100644 --- a/std/js/html/AnimationEventInit.hx +++ b/std/js/html/AnimationEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AnimationEvent.webidl line 21:0. Do not edit! +// This file is generated from mozilla\AnimationEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/AnimationPlayState.hx b/std/js/html/AnimationPlayState.hx index cf2b4605..243a7b97 100644 --- a/std/js/html/AnimationPlayState.hx +++ b/std/js/html/AnimationPlayState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AnimationPlayer.webidl line 13:0. Do not edit! +// This file is generated from mozilla\Animation.webidl. Do not edit! package js.html; diff --git a/std/js/html/AnimationTimeline.hx b/std/js/html/AnimationTimeline.hx index a9cfdb9f..a52c2622 100644 --- a/std/js/html/AnimationTimeline.hx +++ b/std/js/html/AnimationTimeline.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AnimationTimeline.webidl line 14:0. Do not edit! +// This file is generated from mozilla\AnimationTimeline.webidl. Do not edit! package js.html; +/** + The `AnimationTimeline` interface of the Web Animations API represents the timeline of an animation. This interface exists to define timeline features (inherited by `DocumentTimeline` and future timeline types) and is not itself directly used by developers. Anywhere you see `AnimationTimeline`, you should use `DocumentTimeline` or any other timeline type instead. + + Documentation [AnimationTimeline](https://developer.mozilla.org/en-US/docs/Web/API/AnimationTimeline) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AnimationTimeline$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AnimationTimeline") extern class AnimationTimeline { + + /** + Returns the time value in milliseconds for this timeline or `null` if this timeline is inactive. + **/ var currentTime(default,null) : Float; } \ No newline at end of file diff --git a/std/js/html/AppletElement.hx b/std/js/html/AppletElement.hx index 7cb9fa3d..11d8a178 100644 --- a/std/js/html/AppletElement.hx +++ b/std/js/html/AppletElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLAppletElement.webidl line 16:0. Do not edit! +// This file is generated from mozilla\HTMLAppletElement.webidl. Do not edit! package js.html; diff --git a/std/js/html/ApplicationCache.hx b/std/js/html/ApplicationCache.hx index 716bda88..1267649b 100644 --- a/std/js/html/ApplicationCache.hx +++ b/std/js/html/ApplicationCache.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/OfflineResourceList.webidl line 5:0. Do not edit! +// This file is generated from mozilla\OfflineResourceList.webidl. Do not edit! package js.html; diff --git a/std/js/html/AreaElement.hx b/std/js/html/AreaElement.hx index b4998412..8885f48c 100644 --- a/std/js/html/AreaElement.hx +++ b/std/js/html/AreaElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,21 +20,60 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLAreaElement.webidl line 16:0. Do not edit! +// This file is generated from mozilla\HTMLAreaElement.webidl. Do not edit! package js.html; +/** + The `HTMLAreaElement` interface provides special properties and methods (beyond those of the regular object `HTMLElement` interface it also has available to it by inheritance) for manipulating the layout and presentation of area elements. + + Documentation [HTMLAreaElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLAreaElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLAreaElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLAreaElement") extern class AreaElement extends Element { + + /** + Is a `DOMString` that reflects the `alt` HTML attribute, containing alternative text for the element. + **/ var alt : String; + + /** + Is a `DOMString` that reflects the `coords` HTML attribute, containing coordinates to define the hot-spot region. + **/ var coords : String; + + /** + Is a `DOMString` that reflects the `shape` HTML attribute, indicating the shape of the hot-spot, limited to known values. + **/ var shape : String; + + /** + Is a `DOMString` that reflects the `target` HTML attribute, indicating the browsing context in which to open the linked resource. + **/ var target : String; + + /** + Is a `DOMString` indicating that the linked resource is intended to be downloaded rather than displayed in the browser. The value represent the proposed name of the file. If the name is not a valid filename of the underlying OS, browser will adapt it. + **/ var download : String; var ping : String; + + /** + Is a `DOMString` that reflects the `rel` HTML attribute, indicating relationships of the current document to the linked resource. + **/ var rel : String; + + /** + Returns a `DOMTokenList` that reflects the `rel` HTML attribute, indicating relationships of the current document to the linked resource, as a list of tokens. + **/ var relList(default,null) : DOMTokenList; + + /** + Is a `Boolean` flag indicating if the area is inactive (`true`) or active (`false`). + **/ var noHref : Bool; var href : String; var origin(default,null) : String; @@ -47,6 +86,5 @@ extern class AreaElement extends Element var pathname : String; var search : String; var hash : String; - var searchParams : URLSearchParams; } \ No newline at end of file diff --git a/std/js/html/ArrayBuffer.hx b/std/js/html/ArrayBuffer.hx index cb507e8b..9ee2b246 100644 --- a/std/js/html/ArrayBuffer.hx +++ b/std/js/html/ArrayBuffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl line 12:0. Do not edit! +// This file is generated from typedarray.webidl. Do not edit! package js.html; +// Explicitly include the compatibility class +import js.html.compat.ArrayBuffer; + @:native("ArrayBuffer") extern class ArrayBuffer { diff --git a/std/js/html/ArrayBufferView.hx b/std/js/html/ArrayBufferView.hx index 99ddaa8f..51eacc96 100644 --- a/std/js/html/ArrayBufferView.hx +++ b/std/js/html/ArrayBufferView.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl line 21:0. Do not edit! +// This file is generated from typedarray.webidl. Do not edit! package js.html; +/** + `ArrayBufferView` is a helper type representing any of the following JavaScript `TypedArray` types: + + Documentation [ArrayBufferView](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("ArrayBufferView") extern class ArrayBufferView { diff --git a/std/js/html/Attr.hx b/std/js/html/Attr.hx index 1fe07a1c..75c944cd 100644 --- a/std/js/html/Attr.hx +++ b/std/js/html/Attr.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Attr.webidl line 13:0. Do not edit! +// This file is generated from mozilla\Attr.webidl. Do not edit! package js.html; +/** + This type represents a DOM element's attribute as an object. In most DOM methods, you will probably directly retrieve the attribute as a string (e.g., `Element.getAttribute()`, but certain functions (e.g., `Element.getAttributeNode()`) or means of iterating give `Attr` types. + + Documentation [Attr](https://developer.mozilla.org/en-US/docs/Web/API/Attr) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Attr$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Attr") extern class Attr extends Node { diff --git a/std/js/html/Audio.hx b/std/js/html/Audio.hx index f2477243..75f98f5b 100644 --- a/std/js/html/Audio.hx +++ b/std/js/html/Audio.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from namedConstructors.webidl line 2:0. Do not edit! +// This file is generated from namedConstructors.webidl. Do not edit! package js.html; diff --git a/std/js/html/AudioChannel.hx b/std/js/html/AudioChannel.hx index 26353526..4a1b4568 100644 --- a/std/js/html/AudioChannel.hx +++ b/std/js/html/AudioChannel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioChannel.webidl line 41:0. Do not edit! +// This file is generated from mozilla\AudioChannel.webidl. Do not edit! package js.html; @@ -33,4 +33,5 @@ package js.html; var TELEPHONY = "telephony"; var RINGER = "ringer"; var PUBLICNOTIFICATION = "publicnotification"; + var SYSTEM = "system"; } \ No newline at end of file diff --git a/std/js/html/AudioContextState.hx b/std/js/html/AudioContextState.hx new file mode 100644 index 00000000..cc5aada0 --- /dev/null +++ b/std/js/html/AudioContextState.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\AudioContext.webidl. Do not edit! + +package js.html; + +@:enum abstract AudioContextState(String) +{ + var SUSPENDED = "suspended"; + var RUNNING = "running"; + var CLOSED = "closed"; +} \ No newline at end of file diff --git a/std/js/html/AudioElement.hx b/std/js/html/AudioElement.hx index b07e1bc0..c9aaf1f5 100644 --- a/std/js/html/AudioElement.hx +++ b/std/js/html/AudioElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLAudioElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLAudioElement.webidl. Do not edit! package js.html; +/** + The `HTMLAudioElement` interface provides access to the properties of `audio` elements, as well as methods to manipulate them. It derives from the `HTMLMediaElement` interface. + + Documentation [HTMLAudioElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLAudioElement") extern class AudioElement extends MediaElement { diff --git a/std/js/html/AudioStreamTrack.hx b/std/js/html/AudioStreamTrack.hx index 623ac47f..0aecfe18 100644 --- a/std/js/html/AudioStreamTrack.hx +++ b/std/js/html/AudioStreamTrack.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioStreamTrack.webidl line 14:0. Do not edit! +// This file is generated from mozilla\AudioStreamTrack.webidl. Do not edit! package js.html; diff --git a/std/js/html/AudioTrack.hx b/std/js/html/AudioTrack.hx index 8f078f1e..f421d647 100644 --- a/std/js/html/AudioTrack.hx +++ b/std/js/html/AudioTrack.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioTrack.webidl line 11:0. Do not edit! +// This file is generated from mozilla\AudioTrack.webidl. Do not edit! package js.html; diff --git a/std/js/html/AudioTrackList.hx b/std/js/html/AudioTrackList.hx index 8e8baa1a..1bd14237 100644 --- a/std/js/html/AudioTrackList.hx +++ b/std/js/html/AudioTrackList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioTrackList.webidl line 11:0. Do not edit! +// This file is generated from mozilla\AudioTrackList.webidl. Do not edit! package js.html; diff --git a/std/js/html/BRElement.hx b/std/js/html/BRElement.hx index 789fe051..90407625 100644 --- a/std/js/html/BRElement.hx +++ b/std/js/html/BRElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLBRElement.webidl line 16:0. Do not edit! +// This file is generated from mozilla\HTMLBRElement.webidl. Do not edit! package js.html; +/** + The `HTMLBRElement` interface represents a HTML line break element (`br`). It inherits from `HTMLElement`. + + Documentation [HTMLBRElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLBRElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLBRElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLBRElement") extern class BRElement extends Element { + + /** + Is a `DOMString` indicating the flow of text around floating objects. + **/ var clear : String; } \ No newline at end of file diff --git a/std/js/html/BarProp.hx b/std/js/html/BarProp.hx index d5179471..ed75b50e 100644 --- a/std/js/html/BarProp.hx +++ b/std/js/html/BarProp.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/BarProp.webidl line 7:0. Do not edit! +// This file is generated from mozilla\BarProp.webidl. Do not edit! package js.html; diff --git a/std/js/html/BaseElement.hx b/std/js/html/BaseElement.hx index 1f213ac4..02c63de3 100644 --- a/std/js/html/BaseElement.hx +++ b/std/js/html/BaseElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLBaseElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLBaseElement.webidl. Do not edit! package js.html; +/** + The `HTMLBaseElement` interface contains the base URI for a document. This object inherits all of the properties and methods as described in the `HTMLElement` interface. + + Documentation [HTMLBaseElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLBaseElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLBaseElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLBaseElement") extern class BaseElement extends Element { + + /** + Is a `DOMString` that reflects the `href` HTML attribute, containing a base URL for relative URLs in the document. + **/ var href : String; + + /** + Is a `DOMString` that reflects the `target` HTML attribute, containing a default target browsing context or frame for elements that do not have a target reference specified. + **/ var target : String; } \ No newline at end of file diff --git a/std/js/html/BatteryManager.hx b/std/js/html/BatteryManager.hx index 5bf79204..82a7d2cf 100644 --- a/std/js/html/BatteryManager.hx +++ b/std/js/html/BatteryManager.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,20 +20,59 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/BatteryManager.webidl line 13:0. Do not edit! +// This file is generated from mozilla\BatteryManager.webidl. Do not edit! package js.html; +/** + The `BatteryManager` interface provides ways to get information about the system's battery charge level. + + Documentation [BatteryManager](https://developer.mozilla.org/en-US/docs/Web/API/BatteryManager) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/BatteryManager$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("BatteryManager") extern class BatteryManager extends EventTarget { + + /** + A Boolean value indicating whether or not the battery is currently being charged. + **/ var charging(default,null) : Bool; + + /** + A number representing the remaining time in seconds until the battery is fully charged, or 0 if the battery is already fully charged. + **/ var chargingTime(default,null) : Float; + + /** + A number representing the remaining time in seconds until the battery is completely discharged and the system will suspend. + **/ var dischargingTime(default,null) : Float; + + /** + A number representing the system's battery charge level scaled to a value between 0.0 and 1.0. + **/ var level(default,null) : Float; + + /** + A handler for the `chargingchange` event; This event is sent when the battery charging state is updated. + **/ var onchargingchange : haxe.Constraints.Function; + + /** + A handler for the `chargingtimechange` event; This event is sent when the battery charging time is updated + **/ var onchargingtimechange : haxe.Constraints.Function; + + /** + A handler for the `dischargingtimechange` event; This event is sent when the battery discharging time is updated. + **/ var ondischargingtimechange : haxe.Constraints.Function; + + /** + A handler for the `levelchange` event; This event is sent when the battery level is updated. + **/ var onlevelchange : haxe.Constraints.Function; } \ No newline at end of file diff --git a/std/js/html/BeforeUnloadEvent.hx b/std/js/html/BeforeUnloadEvent.hx index 2581bc8d..64927263 100644 --- a/std/js/html/BeforeUnloadEvent.hx +++ b/std/js/html/BeforeUnloadEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/BeforeUnloadEvent.webidl line 10:0. Do not edit! +// This file is generated from mozilla\BeforeUnloadEvent.webidl. Do not edit! package js.html; +/** + The `beforeunload` event is fired when the window, the document and its resources are about to be unloaded. + + Documentation [BeforeUnloadEvent](https://developer.mozilla.org/en-US/docs/Web/API/BeforeUnloadEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/BeforeUnloadEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("BeforeUnloadEvent") extern class BeforeUnloadEvent extends Event { diff --git a/std/js/html/BinaryType.hx b/std/js/html/BinaryType.hx index 73ac085c..337e2c92 100644 --- a/std/js/html/BinaryType.hx +++ b/std/js/html/BinaryType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebSocket.webidl line 13:0. Do not edit! +// This file is generated from mozilla\WebSocket.webidl. Do not edit! package js.html; diff --git a/std/js/html/Blob.hx b/std/js/html/Blob.hx index b513adcc..543cc4d9 100644 --- a/std/js/html/Blob.hx +++ b/std/js/html/Blob.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,19 +20,38 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Blob.webidl line 16:0. Do not edit! +// This file is generated from mozilla\Blob.webidl. Do not edit! package js.html; +/** + A `Blob` object represents a file-like object of immutable, raw data. Blobs represent data that isn't necessarily in a JavaScript-native format. The `File` interface is based on `Blob`, inheriting blob functionality and expanding it to support files on the user's system. + + Documentation [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Blob$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Blob") extern class Blob { + + /** + The size, in bytes, of the data contained in the `Blob` object. + **/ var size(default,null) : Int; + + /** + A string indicating the MIME type of the data contained in the `Blob`. If the type is unknown, this string is empty. + **/ var type(default,null) : String; /** @throws DOMError */ @:overload( function() : Void {} ) function new( blobParts : Array>>>, ?options : BlobPropertyBag ) : Void; /** @throws DOMError */ + + /** + Returns a new `Blob` object containing the data in the specified range of bytes of the source `Blob`. + **/ function slice( ?start : Int, ?end : Int, ?contentType : String = "" ) : Blob; } \ No newline at end of file diff --git a/std/js/html/BlobPropertyBag.hx b/std/js/html/BlobPropertyBag.hx index ae55ce7e..b1111dd3 100644 --- a/std/js/html/BlobPropertyBag.hx +++ b/std/js/html/BlobPropertyBag.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Blob.webidl line 37:0. Do not edit! +// This file is generated from mozilla\Blob.webidl. Do not edit! package js.html; diff --git a/std/js/html/BodyElement.hx b/std/js/html/BodyElement.hx index 4aa1d1d3..e38b050f 100644 --- a/std/js/html/BodyElement.hx +++ b/std/js/html/BodyElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,18 +20,49 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLBodyElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLBodyElement.webidl. Do not edit! package js.html; +/** + The `HTMLBodyElement` interface provides special properties (beyond those of the regular `HTMLElement` interface they also inherit) for manipulating body elements. + + Documentation [HTMLBodyElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLBodyElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLBodyElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLBodyElement") extern class BodyElement extends Element { + + /** + Is a `DOMString` that represents the foreground color of text. + **/ var text : String; + + /** + Is a `DOMString` that represents the color of unvisited links. + **/ var link : String; + + /** + Is a `DOMString` that represents the color of visited links. + **/ var vLink : String; + + /** + Is a `DOMString` that represents the color of active hyperlinks. + **/ var aLink : String; + + /** + Is a `DOMString` that represents the background color for the document. + **/ var bgColor : String; + + /** + Is a `DOMString` that represents the description of the location of the background image resource. Note that this is not an URI, though some older version of some browsers do expect it. + **/ var background : String; var onafterprint : haxe.Constraints.Function; var onbeforeprint : haxe.Constraints.Function; @@ -44,7 +75,7 @@ extern class BodyElement extends Element var onpagehide : haxe.Constraints.Function; var onpageshow : haxe.Constraints.Function; var onpopstate : haxe.Constraints.Function; - var onresize : haxe.Constraints.Function; + var onstorage : haxe.Constraints.Function; var onunload : haxe.Constraints.Function; } \ No newline at end of file diff --git a/std/js/html/BroadcastChannel.hx b/std/js/html/BroadcastChannel.hx new file mode 100644 index 00000000..c9cac75b --- /dev/null +++ b/std/js/html/BroadcastChannel.hx @@ -0,0 +1,61 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\BroadcastChannel.webidl. Do not edit! + +package js.html; + +/** + The `BroadcastChannel` interface represents a named channel that any browsing context of a given origin can subscribe to. It allows communication between different documents (in different windows, tabs, frames or iframes) of the same origin. Messages are broadcasted via a `message` event fired at all `BroadcastChannel` objects listening to the channel. + + Documentation [BroadcastChannel](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("BroadcastChannel") +extern class BroadcastChannel extends EventTarget +{ + + /** + Returns a `DOMString`, the name of the channel. + **/ + var name(default,null) : String; + + /** + Is an `EventHandler` property that specifies the function to execute when a `message` event is fired on this object. + **/ + var onmessage : haxe.Constraints.Function; + + /** @throws DOMError */ + function new( channel : String ) : Void; + /** @throws DOMError */ + + /** + Sends the message, of any type of object, to each `BroadcastChannel` object listening to the same channel. + **/ + function postMessage( message : Dynamic ) : Void; + + /** + Closes the channel object, indicating it won't get any new messages, and allowing it to be, eventually, garbage collected. + **/ + function close() : Void; +} \ No newline at end of file diff --git a/std/js/html/ButtonElement.hx b/std/js/html/ButtonElement.hx index a2ebe8ef..61524fb2 100644 --- a/std/js/html/ButtonElement.hx +++ b/std/js/html/ButtonElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,26 +20,94 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLButtonElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLButtonElement.webidl. Do not edit! package js.html; +/** + The `HTMLButtonElement` interface provides properties and methods (beyond the `button` object interface it also has available to them by inheritance) for manipulating the layout and presentation of button elements. + + Documentation [HTMLButtonElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLButtonElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLButtonElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLButtonElement") extern class ButtonElement extends Element { + + /** + Is a `Boolean` indicating whether or not the control should have input focus when the page loads, unless the user overrides it, for example by typing in a different control. Only one form-associated element in a document can have this attribute specified. + **/ var autofocus : Bool; + + /** + Is a `Boolean` indicating whether or not the control is disabled, meaning that it does not accept any clicks. + **/ var disabled : Bool; + + /** + Is a `HTMLFormElement` reflecting the form that this button is associated with. If the button is a descendant of a form element, then this attribute is the ID of that form element. + + If the button is not a descendant of a form element, then the attribute can be the ID of any form element in the same document it is related to, or the `null` value if none matches. + **/ var form(default,null) : FormElement; + + /** + Is a `DOMString` reflecting the URI of a resource that processes information submitted by the button. If specified, this attribute overrides the `action` attribute of the `form` element that owns this element. + **/ var formAction : String; var formEnctype : String; + + /** + Is a `DOMString` reflecting the HTTP method that the browser uses to submit the form. If specified, this attribute overrides the `method` attribute of the `form` element that owns this element. + **/ var formMethod : String; + + /** + Is a `Boolean` indicating that the form is not to be validated when it is submitted. If specified, this attribute overrides the `novalidate` attribute of the `form` element that owns this element. + **/ var formNoValidate : Bool; + + /** + Is a `DOMString` reflecting a name or keyword indicating where to display the response that is received after submitting the form. If specified, this attribute overrides the `target` attribute of the `form` element that owns this element. + **/ var formTarget : String; + + /** + Is a `DOMString` representing the name of the object when submitted with a form. {{HTMLVersionInline(5)}} If specified, it must not be the empty string. + **/ var name : String; + + /** + Is a `DOMString` indicating the behavior of the button. This is an enumerated attribute with the following possible values: + + `"submit"`: The button submits the form. This is the default value if the attribute is not specified, {{HTMLVersionInline(5)}} or if it is dynamically changed to an empty or invalid value. + `"reset"`: The button resets the form. + `"button"`: The button does nothing. + `"menu"`: The button displays a menu. (experimental) + + + **/ var type : String; + + /** + Is a `DOMString` representing the current form control value of the button. + **/ var value : String; + + /** + Is a `Boolean` indicating whether the button is a candidate for constraint validation. It is `false` if any conditions bar it from constraint validation. + **/ var willValidate(default,null) : Bool; + + /** + Is a `ValidityState` representing the validity states that this button is in. + **/ var validity(default,null) : ValidityState; + + /** + Is a `DOMString` representing the localized message that describes the validation constraints that the control does not satisfy (if any). This attribute is the empty string if the control is not a candidate for constraint validation (`willValidate` is `false`), or it satisfies its constraints. + **/ var validationMessage(default,null) : String; function checkValidity() : Bool; diff --git a/std/js/html/CDATASection.hx b/std/js/html/CDATASection.hx index 8696d2c6..481d0c7b 100644 --- a/std/js/html/CDATASection.hx +++ b/std/js/html/CDATASection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CDATASection.webidl line 7:0. Do not edit! +// This file is generated from mozilla\CDATASection.webidl. Do not edit! package js.html; +/** + The `CDATASection` interface represents a CDATA section that can be used within XML to include extended portions of unescaped text, such that the symbols and & do not need escaping as they normally do within XML when used as text. + + Documentation [CDATASection](https://developer.mozilla.org/en-US/docs/Web/API/CDATASection) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CDATASection$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CDATASection") extern class CDATASection extends Text { diff --git a/std/js/html/CSS.hx b/std/js/html/CSS.hx index d637fda6..87960024 100644 --- a/std/js/html/CSS.hx +++ b/std/js/html/CSS.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,22 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CSS.webidl line 13:0. Do not edit! +// This file is generated from mozilla\CSS.webidl. Do not edit! package js.html; +/** + The `CSS` interface holds useful CSS-related methods. No object with this interface are implemented: it contains only static methods and therefore is a utilitarian interface. + + Documentation [CSS](https://developer.mozilla.org/en-US/docs/Web/API/CSS) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSS$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CSS") extern class CSS { /** @throws DOMError */ @:overload( function( property : String, value : String ) : Bool {} ) static function supports( conditionText : String ) : Bool; - /** @throws DOMError */ static function escape( ident : String ) : String; } \ No newline at end of file diff --git a/std/js/html/ServiceWorkerClient.hx b/std/js/html/CSSAnimation.hx similarity index 82% rename from std/js/html/ServiceWorkerClient.hx rename to std/js/html/CSSAnimation.hx index c11c89c6..1d9d90fc 100644 --- a/std/js/html/ServiceWorkerClient.hx +++ b/std/js/html/CSSAnimation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ServiceWorkerClient.webidl line 12:0. Do not edit! +// This file is generated from mozilla\CSSAnimation.webidl. Do not edit! package js.html; -@:native("ServiceWorkerClient") -extern class ServiceWorkerClient +@:native("CSSAnimation") +extern class CSSAnimation extends Animation { - var id(default,null) : Int; + var animationName(default,null) : String; } \ No newline at end of file diff --git a/std/js/html/CSSCharsetRule.hx b/std/js/html/CSSCharsetRule.hx index 6dc0d137..b8066e42 100644 --- a/std/js/html/CSSCharsetRule.hx +++ b/std/js/html/CSSCharsetRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl line 62:2. Do not edit! +// This file is generated from cssrule.webidl. Do not edit! package js.html; diff --git a/std/js/html/CSSFontFaceRule.hx b/std/js/html/CSSFontFaceRule.hx index 1e0389ec..68b154b1 100644 --- a/std/js/html/CSSFontFaceRule.hx +++ b/std/js/html/CSSFontFaceRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl line 42:2. Do not edit! +// This file is generated from cssrule.webidl. Do not edit! package js.html; diff --git a/std/js/html/CSSImportRule.hx b/std/js/html/CSSImportRule.hx index 3be02ce6..217e4afe 100644 --- a/std/js/html/CSSImportRule.hx +++ b/std/js/html/CSSImportRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl line 55:2. Do not edit! +// This file is generated from cssrule.webidl. Do not edit! package js.html; diff --git a/std/js/html/CSSMediaRule.hx b/std/js/html/CSSMediaRule.hx index 50c8a06b..99ff0843 100644 --- a/std/js/html/CSSMediaRule.hx +++ b/std/js/html/CSSMediaRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl line 31:2. Do not edit! +// This file is generated from cssrule.webidl. Do not edit! package js.html; +/** + The `CSSMediaRule` is an interface representing a single CSS `@media` rule. It implements the `CSSConditionRule` interface, and therefore the `CSSGroupingRule` and the `CSSRule` interface with a type value of `4` (`CSSRule.MEDIA_RULE`). + + Documentation [CSSMediaRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSMediaRule) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSMediaRule$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CSSMediaRule") extern class CSSMediaRule extends CSSRule { + + /** + Specifies a `MediaList` representing the intended destination medium for style information. + **/ var media(default,null) : MediaList; var cssRules(default,null) : CSSRuleList; diff --git a/std/js/html/CSSPageRule.hx b/std/js/html/CSSPageRule.hx index 55570be6..082ec61e 100644 --- a/std/js/html/CSSPageRule.hx +++ b/std/js/html/CSSPageRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl line 47:2. Do not edit! +// This file is generated from cssrule.webidl. Do not edit! package js.html; +/** + `CSSPageRule` is an interface representing a single CSS `@page` rule. It implements the `CSSRule` interface with a type value of `6` (`CSSRule.PAGE_RULE`). + + Documentation [CSSPageRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSPageRule) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSPageRule$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CSSPageRule") extern class CSSPageRule extends CSSRule { + + /** + Represents the text of the page selector associated with the at-rule. + **/ var selectorText : String; + + /** + Returns the declaration block associated with the at-rule. + **/ var style(default,null) : CSSStyleDeclaration; } \ No newline at end of file diff --git a/std/js/html/CSSPrimitiveValue.hx b/std/js/html/CSSPrimitiveValue.hx index 595ec2b8..7eaf4db7 100644 --- a/std/js/html/CSSPrimitiveValue.hx +++ b/std/js/html/CSSPrimitiveValue.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CSSPrimitiveValue.webidl line 9:0. Do not edit! +// This file is generated from mozilla\CSSPrimitiveValue.webidl. Do not edit! package js.html; +/** + The `CSSPrimitiveValue` interface derives from the `CSSValue` interface and represents the current computed value of a CSS property. + + Documentation [CSSPrimitiveValue](https://developer.mozilla.org/en-US/docs/Web/API/CSSPrimitiveValue) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSPrimitiveValue$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CSSPrimitiveValue") extern class CSSPrimitiveValue extends CSSValue { @@ -54,20 +61,165 @@ extern class CSSPrimitiveValue extends CSSValue static inline var CSS_RECT : Int = 24; static inline var CSS_RGBCOLOR : Int = 25; + + /** + An unsigned short representing the type of the value. Possible values are: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConstantDescription
CSS_ATTRThe value is an attr() function. The value can be obtained by using the getStringValue() method.
CSS_CMThe value is a length in centimeters. The value can be obtained by using the getFloatValue() method.
CSS_COUNTERThe value is a counter or counters function. The value can be obtained by using the getCounterValue() method.
CSS_DEGThe value is an angle in degrees. The value can be obtained by using the getFloatValue() method.
CSS_DIMENSIONThe value is a number with an unknown dimension. The value can be obtained by using the getFloatValue() method.
CSS_EMSThe value is a length in em units. The value can be obtained by using the getFloatValue() method.
CSS_EXSThe value is a length in ex units. The value can be obtained by using the getFloatValue() method.
CSS_GRADThe value is an angle in grads. The value can be obtained by using the getFloatValue() method.
CSS_HZThe value is a frequency in Hertz. The value can be obtained by using the getFloatValue method.
CSS_IDENTThe value is an identifier. The value can be obtained by using the getStringValue() method.
CSS_INThe value is a length in inches. The value can be obtained by using the getFloatValue() method.
CSS_KHZThe value is a frequency in Kilohertz. The value can be obtained by using the getFloatValue() method.
CSS_MMThe value is a length in millimeters. The value can be obtained by using the getFloatValue() method.
CSS_MSThe value is a time in milliseconds. The value can be obtained by using the getFloatValue() method.
CSS_NUMBERThe value is a simple number. The value can be obtained by using the getFloatValue() method.
CSS_PCThe value is a length in picas. The value can be obtained by using the getFloatValue() method.
CSS_PERCENTAGEThe value is a percentage. The value can be obtained by using the getFloatValue() method.
CSS_PTThe value is a length in points. The value can be obtained by using the getFloatValue() method.
CSS_PXThe value is a length in pixels. The value can be obtained by using the getFloatValue() method.
CSS_RADThe value is an angle in radians. The value can be obtained by using the getFloatValue() method.
CSS_RECTThe value is a shape function. The value can be obtained by using the getRectValue() method.
CSS_RGBCOLORThe value is an color. The value can be obtained by using the getRGBColorValue() method.
CSS_SThe value is a time in seconds. The value can be obtained by using the getFloatValue() method.
CSS_STRINGThe value is a string. The value can be obtained by using the getStringValue() method.
CSS_UNKNOWNThe value is not a recognized CSS2 value. The value can only be obtained by using the CSSValue.cssText attribute.
CSS_URIThe value is a uri. The value can be obtained by using the getStringValue() method.
+ + **/ var primitiveType(default,null) : Int; /** @throws DOMError */ + + /** + A method to set the float value with a specified unit. If the property attached with this value can not accept the specified unit or the float value, the value will be unchanged and a `DOMException` will be raised. + **/ function setFloatValue( unitType : Int, floatValue : Float ) : Void; /** @throws DOMError */ + + /** + This method is used to get a float value in a specified unit. If this CSS value doesn't contain a float value or can't be converted into the specified unit, a `DOMException` is raised. + **/ function getFloatValue( unitType : Int ) : Float; /** @throws DOMError */ + + /** + A method to set the string value with the specified unit. If the property attached to this value can't accept the specified unit or the string value, the value will be unchanged and a `DOMException` will be raised. + **/ function setStringValue( stringType : Int, stringValue : String ) : Void; /** @throws DOMError */ + + /** + This method is used to get the string value. If the CSS value doesn't contain a string value, a `DOMException` is raised. + **/ function getStringValue() : String; /** @throws DOMError */ + + /** + This method is used to get the counter value. If this CSS value doesn't contain a counter value, a `DOMException` is raised. Modification to the corresponding style property can be achieved using the `Counter` interface. + **/ function getCounterValue() : Dynamic/*MISSING Counter*/; /** @throws DOMError */ + + /** + This method is used to get the Rect value. If this CSS value doesn't contain a rect value, a `DOMException` is raised. Modification to the corresponding style property can be achieved using the `Rect` interface. + **/ function getRectValue() : Rect; /** @throws DOMError */ + + /** + This method is used to get the RGB color. If this CSS value doesn't contain a RGB color value, a `DOMException` is raised. Modification to the corresponding style property can be achieved using the `RGBColor` interface. + **/ function getRGBColorValue() : RGBColor; } \ No newline at end of file diff --git a/std/js/html/MediaEncryptedEvent.hx b/std/js/html/CSSPseudoElement.hx similarity index 71% rename from std/js/html/MediaEncryptedEvent.hx rename to std/js/html/CSSPseudoElement.hx index 3b9d16d8..5a72edc0 100644 --- a/std/js/html/MediaEncryptedEvent.hx +++ b/std/js/html/CSSPseudoElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaEncryptedEvent.webidl line 14:0. Do not edit! +// This file is generated from mozilla\CSSPseudoElement.webidl. Do not edit! package js.html; -@:native("MediaEncryptedEvent") -extern class MediaEncryptedEvent extends Event +@:native("CSSPseudoElement") +extern class CSSPseudoElement { - var initDataType(default,null) : String; - var initData(default,null) : ArrayBuffer; + var type(default,null) : String; + var parentElement(default,null) : Element; /** @throws DOMError */ - function new( type : String, ?eventInitDict : MediaKeyNeededEventInit ) : Void; + function animate( frames : Dynamic, ?options : haxe.extern.EitherType ) : Animation; + function getAnimations() : Array; } \ No newline at end of file diff --git a/std/js/html/CSSRule.hx b/std/js/html/CSSRule.hx index ab83fcc0..fefc8aab 100644 --- a/std/js/html/CSSRule.hx +++ b/std/js/html/CSSRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl line 3:2. Do not edit! +// This file is generated from cssrule.webidl. Do not edit! package js.html; +/** + The `CSSRule` interface represents a single CSS rule. There are several types of rules, listed in the Type constants section below. + + Documentation [CSSRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSRule) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSRule$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CSSRule") extern class CSSRule { diff --git a/std/js/html/CSSRuleList.hx b/std/js/html/CSSRuleList.hx index 5c7af250..9f77b36a 100644 --- a/std/js/html/CSSRuleList.hx +++ b/std/js/html/CSSRuleList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CSSRuleList.webidl line 7:0. Do not edit! +// This file is generated from mozilla\CSSRuleList.webidl. Do not edit! package js.html; +/** + A `CSSRuleList` is an (indirect-modify only) array-like object containing an ordered collection of `CSSRule` objects. + + Documentation [CSSRuleList](https://developer.mozilla.org/en-US/docs/Web/API/CSSRuleList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSRuleList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CSSRuleList") extern class CSSRuleList implements ArrayAccess { diff --git a/std/js/html/CSSStyleDeclaration.hx b/std/js/html/CSSStyleDeclaration.hx index 74586586..b44b68bd 100644 --- a/std/js/html/CSSStyleDeclaration.hx +++ b/std/js/html/CSSStyleDeclaration.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CSSStyleDeclaration.webidl line 12:0. Do not edit! +// This file is generated from mozilla\CSSStyleDeclaration.webidl. Do not edit! package js.html; +/** + `CSSStyleDeclaration` represents a collection of CSS property-value pairs. It is used in a few APIs: + + Documentation [CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CSSStyleDeclaration") extern class CSSStyleDeclaration implements ArrayAccess { diff --git a/std/js/html/CSSStyleRule.hx b/std/js/html/CSSStyleRule.hx index afa1765f..f94707ef 100644 --- a/std/js/html/CSSStyleRule.hx +++ b/std/js/html/CSSStyleRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl line 23:2. Do not edit! +// This file is generated from cssrule.webidl. Do not edit! package js.html; +/** + `CSSStyleRule` represents a single CSS style rule. It implements the `CSSRule` interface with a type value of `1` (`CSSRule.STYLE_RULE`). + + Documentation [CSSStyleRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleRule) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleRule$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CSSStyleRule") extern class CSSStyleRule extends CSSRule { diff --git a/std/js/html/CSSStyleSheet.hx b/std/js/html/CSSStyleSheet.hx index 4779d225..d6a03461 100644 --- a/std/js/html/CSSStyleSheet.hx +++ b/std/js/html/CSSStyleSheet.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CSSStyleSheet.webidl line 12:0. Do not edit! +// This file is generated from mozilla\CSSStyleSheet.webidl. Do not edit! package js.html; +/** + The `CSSStyleSheet` interface represents a single CSS style sheet. It inherits properties and methods from its parent, `StyleSheet`. + + Documentation [CSSStyleSheet](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CSSStyleSheet") extern class CSSStyleSheet extends StyleSheet { diff --git a/std/js/html/CSSTransition.hx b/std/js/html/CSSTransition.hx new file mode 100644 index 00000000..0fc88083 --- /dev/null +++ b/std/js/html/CSSTransition.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\CSSTransition.webidl. Do not edit! + +package js.html; + +@:native("CSSTransition") +extern class CSSTransition extends Animation +{ + var transitionProperty(default,null) : String; + +} \ No newline at end of file diff --git a/std/js/html/CSSUnknownRule.hx b/std/js/html/CSSUnknownRule.hx index 5a50d326..f093ea41 100644 --- a/std/js/html/CSSUnknownRule.hx +++ b/std/js/html/CSSUnknownRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from cssrule.webidl line 69:2. Do not edit! +// This file is generated from cssrule.webidl. Do not edit! package js.html; diff --git a/std/js/html/CSSValue.hx b/std/js/html/CSSValue.hx index 825b8acd..0f3aea68 100644 --- a/std/js/html/CSSValue.hx +++ b/std/js/html/CSSValue.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CSSValue.webidl line 7:0. Do not edit! +// This file is generated from mozilla\CSSValue.webidl. Do not edit! package js.html; +/** + The `CSSValue` interface represents the current computed value of a CSS property. + + Documentation [CSSValue](https://developer.mozilla.org/en-US/docs/Web/API/CSSValue) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSValue$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CSSValue") extern class CSSValue { @@ -32,7 +39,40 @@ extern class CSSValue static inline var CSS_VALUE_LIST : Int = 2; static inline var CSS_CUSTOM : Int = 3; + + /** + A `DOMString` representing the current value. + **/ var cssText : String; + + /** + An unsigned short representing a code defining the type of the value. Possible values are: + + + + + + + + + + + + + + + + + + + + + + + +
ConstantDescription
CSS_CUSTOMThe value is a custom value.
CSS_INHERITThe value is inherited and the cssText contains "inherit".
CSS_PRIMITIVE_VALUEThe value is a primitive value and an instance of the CSSPrimitiveValue interface can be obtained by using binding-specific casting methods on this instance of the CSSValue interface.
CSS_VALUE_LISTThe value is a CSSValue list and an instance of the CSSValueList interface can be obtained by using binding-specific casting methods on this instance of the CSSValue interface.
+ + **/ var cssValueType(default,null) : Int; } \ No newline at end of file diff --git a/std/js/html/CSSValueList.hx b/std/js/html/CSSValueList.hx index b8f771f2..dac04577 100644 --- a/std/js/html/CSSValueList.hx +++ b/std/js/html/CSSValueList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CSSValueList.webidl line 7:0. Do not edit! +// This file is generated from mozilla\CSSValueList.webidl. Do not edit! package js.html; +/** + The `CSSValueList` interface derives from the `CSSValue` interface and provides the abstraction of an ordered collection of CSS values. + + Documentation [CSSValueList](https://developer.mozilla.org/en-US/docs/Web/API/CSSValueList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CSSValueList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CSSValueList") extern class CSSValueList extends CSSValue implements ArrayAccess { + + /** + An `unsigned long` representing the number of `CSSValues` in the list. + **/ var length(default,null) : Int; + + /** + This method is used to retrieve a `CSSValue` by ordinal index. The order in this collection represents the order of the values in the CSS style property. If index is greater than or equal to the number of values in the list, this returns `null`. + **/ function item( index : Int ) : CSSValue; } \ No newline at end of file diff --git a/std/js/html/CanvasElement.hx b/std/js/html/CanvasElement.hx index d67528a7..ca6b006a 100644 --- a/std/js/html/CanvasElement.hx +++ b/std/js/html/CanvasElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,21 +20,48 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLCanvasElement.webidl line 17:0. Do not edit! +// This file is generated from mozilla\HTMLCanvasElement.webidl. Do not edit! package js.html; +/** + The `HTMLCanvasElement` interface provides properties and methods for manipulating the layout and presentation of canvas elements. The `HTMLCanvasElement` interface also inherits the properties and methods of the `HTMLElement` interface. + + Documentation [HTMLCanvasElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLCanvasElement") extern class CanvasElement extends Element { + + /** + Is a positive `integer` reflecting the `width` HTML attribute of the `canvas` element interpreted in CSS pixels. When the attribute is not specified, or if it is set to an invalid value, like a negative, the default value of `300` is used. + **/ var width : Int; + + /** + Is a positive `integer` reflecting the `height` HTML attribute of the `canvas` element interpreted in CSS pixels. When the attribute is not specified, or if it is set to an invalid value, like a negative, the default value of `150` is used. + **/ var height : Int; /** @throws DOMError */ + + /** + Returns a drawing context on the canvas, or null if the context ID is not supported. A drawing context lets you draw on the canvas. Calling getContext with `"2d"` returns a `CanvasRenderingContext2D` object, whereas calling it with `"experimental-webgl"` (or `"webgl"`) returns a `WebGLRenderingContext` object. This context is only available on browsers that implement WebGL. + **/ function getContext( contextId : String, ?contextOptions : Dynamic ) : Dynamic/*MISSING nsISupports*/; /** @throws DOMError */ + + /** + Returns a data-URL containing a representation of the image in the format specified by the `type` parameter (defaults to `png`). The returned image is in a resolution of 96dpi. + **/ function toDataURL( ?type : String = "", ?encoderOptions : Dynamic ) : String; /** @throws DOMError */ + + /** + Creates a `Blob` object representing the image contained in the canvas; this file may be cached on the disk or stored in memory at the discretion of the user agent. + **/ function toBlob( callback : Blob -> Void, ?type : String = "", ?encoderOptions : Dynamic ) : Void; /** Shorthand for getting a CanvasRenderingContext2D. */ diff --git a/std/js/html/CanvasGradient.hx b/std/js/html/CanvasGradient.hx index 29d12322..55e9da09 100644 --- a/std/js/html/CanvasGradient.hx +++ b/std/js/html/CanvasGradient.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CanvasRenderingContext2D.webidl line 285:0. Do not edit! +// This file is generated from mozilla\CanvasRenderingContext2D.webidl. Do not edit! package js.html; +/** + The `CanvasGradient` interface represents an opaque object describing a gradient. It is returned by the methods `CanvasRenderingContext2D.createLinearGradient()` or `CanvasRenderingContext2D.createRadialGradient()`. + + Documentation [CanvasGradient](https://developer.mozilla.org/en-US/docs/Web/API/CanvasGradient) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CanvasGradient$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CanvasGradient") extern class CanvasGradient { /** @throws DOMError */ + + /** + Adds a new stop, defined by an `offset` and a `color`, to the gradient. If the offset is not between `0` and `1` an `INDEX_SIZE_ERR` is raised, if the color can't be parsed as a CSS `color`, a `SYNTAX_ERR` is raised. + **/ function addColorStop( offset : Float, color : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/CanvasPattern.hx b/std/js/html/CanvasPattern.hx index 553446d2..b7f4bcec 100644 --- a/std/js/html/CanvasPattern.hx +++ b/std/js/html/CanvasPattern.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,12 +20,23 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CanvasRenderingContext2D.webidl line 292:0. Do not edit! +// This file is generated from mozilla\CanvasRenderingContext2D.webidl. Do not edit! package js.html; +/** + The `CanvasPattern` interface represents an opaque object describing a pattern, based on an image, a canvas or a video, created by the `CanvasRenderingContext2D.createPattern()` method. + + Documentation [CanvasPattern](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CanvasPattern") extern class CanvasPattern { + + /** + Applies an `SVGMatrix` representing a linear transform to the pattern. + **/ function setTransform( matrix : js.html.svg.Matrix ) : Void; } \ No newline at end of file diff --git a/std/js/html/CanvasRenderingContext2D.hx b/std/js/html/CanvasRenderingContext2D.hx index fbfc6ebc..2f57327e 100644 --- a/std/js/html/CanvasRenderingContext2D.hx +++ b/std/js/html/CanvasRenderingContext2D.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CanvasRenderingContext2D.webidl line 28:0. Do not edit! +// This file is generated from mozilla\CanvasRenderingContext2D.webidl. Do not edit! package js.html; +/** + To get an object of this interface, call `getContext()` on a `canvas element`, supplying "2d" as the argument: + + Documentation [CanvasRenderingContext2D](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CanvasRenderingContext2D") extern class CanvasRenderingContext2D { @@ -65,7 +72,7 @@ extern class CanvasRenderingContext2D /** @throws DOMError */ function createRadialGradient( x0 : Float, y0 : Float, r0 : Float, x1 : Float, y1 : Float, r1 : Float ) : CanvasGradient; /** @throws DOMError */ - function createPattern( image : haxe.extern.EitherType>, repetition : String ) : CanvasPattern; + function createPattern( image : haxe.extern.EitherType>>, repetition : String ) : CanvasPattern; function clearRect( x : Float, y : Float, w : Float, h : Float ) : Void; function fillRect( x : Float, y : Float, w : Float, h : Float ) : Void; function strokeRect( x : Float, y : Float, w : Float, h : Float ) : Void; @@ -74,6 +81,7 @@ extern class CanvasRenderingContext2D function fill( path : Path2D, ?winding : CanvasWindingRule = "nonzero" ) : Void; @:overload( function() : Void {} ) function stroke( path : Path2D ) : Void; + /** @throws DOMError */ function drawFocusIfNeeded( element : Element ) : Void; function drawCustomFocusRing( element : Element ) : Bool; @:overload( function( ?winding : CanvasWindingRule = "nonzero" ) : Void {} ) @@ -89,9 +97,9 @@ extern class CanvasRenderingContext2D /** @throws DOMError */ function measureText( text : String ) : TextMetrics; /** @throws DOMError */ - @:overload( function( image : haxe.extern.EitherType>, dx : Float, dy : Float ) : Void {} ) - @:overload( function( image : haxe.extern.EitherType>, dx : Float, dy : Float, dw : Float, dh : Float ) : Void {} ) - function drawImage( image : haxe.extern.EitherType>, sx : Float, sy : Float, sw : Float, sh : Float, dx : Float, dy : Float, dw : Float, dh : Float ) : Void; + @:overload( function( image : haxe.extern.EitherType>>, dx : Float, dy : Float ) : Void {} ) + @:overload( function( image : haxe.extern.EitherType>>, dx : Float, dy : Float, dw : Float, dh : Float ) : Void {} ) + function drawImage( image : haxe.extern.EitherType>>, sx : Float, sy : Float, sw : Float, sh : Float, dx : Float, dy : Float, dw : Float, dh : Float ) : Void; /** @throws DOMError */ function addHitRegion( ?options : HitRegionOptions ) : Void; function removeHitRegion( id : String ) : Void; @@ -104,6 +112,7 @@ extern class CanvasRenderingContext2D /** @throws DOMError */ @:overload( function( imagedata : ImageData, dx : Float, dy : Float ) : Void {} ) function putImageData( imagedata : ImageData, dx : Float, dy : Float, dirtyX : Float, dirtyY : Float, dirtyWidth : Float, dirtyHeight : Float ) : Void; + /** @throws DOMError */ function setLineDash( segments : Array ) : Void; function getLineDash() : Array; function closePath() : Void; @@ -116,4 +125,6 @@ extern class CanvasRenderingContext2D function rect( x : Float, y : Float, w : Float, h : Float ) : Void; /** @throws DOMError */ function arc( x : Float, y : Float, radius : Float, startAngle : Float, endAngle : Float, ?anticlockwise : Bool = false ) : Void; + /** @throws DOMError */ + function ellipse( x : Float, y : Float, radiusX : Float, radiusY : Float, rotation : Float, startAngle : Float, endAngle : Float, ?anticlockwise : Bool = false ) : Void; } \ No newline at end of file diff --git a/std/js/html/CanvasWindingRule.hx b/std/js/html/CanvasWindingRule.hx index 892e7971..c0b6c6c2 100644 --- a/std/js/html/CanvasWindingRule.hx +++ b/std/js/html/CanvasWindingRule.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CanvasRenderingContext2D.webidl line 14:0. Do not edit! +// This file is generated from mozilla\CanvasRenderingContext2D.webidl. Do not edit! package js.html; diff --git a/std/js/html/CaretPosition.hx b/std/js/html/CaretPosition.hx index b1a65e77..45f5fede 100644 --- a/std/js/html/CaretPosition.hx +++ b/std/js/html/CaretPosition.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CaretPosition.webidl line 5:0. Do not edit! +// This file is generated from mozilla\CaretPosition.webidl. Do not edit! package js.html; +/** + The `CaretPosition` interface represents the caret postion, an indicator for the text insertion point. You can get a `CaretPosition` using the `document.caretPositionFromPoint` method. + + Documentation [CaretPosition](https://developer.mozilla.org/en-US/docs/Web/API/CaretPosition) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CaretPosition$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CaretPosition") extern class CaretPosition { + + /** + Returns a `Node` containing the found node at the caret's position. + **/ var offsetNode(default,null) : Node; + + /** + Returns a `long` representing the character offset in the caret position node. + **/ var offset(default,null) : Int; function getClientRect() : DOMRect; diff --git a/std/js/html/CharacterData.hx b/std/js/html/CharacterData.hx index 65f6df85..a7456958 100644 --- a/std/js/html/CharacterData.hx +++ b/std/js/html/CharacterData.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,27 +20,62 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CharacterData.webidl line 13:0. Do not edit! +// This file is generated from mozilla\CharacterData.webidl. Do not edit! package js.html; +/** + The `CharacterData` abstract interface represents a `Node` object that contains characters. This is an abstract interface, meaning there aren't any object of type `CharacterData`: it is implemented by other interfaces, like `Text`, `Comment`, or `ProcessingInstruction` which aren't abstract. + + Documentation [CharacterData](https://developer.mozilla.org/en-US/docs/Web/API/CharacterData) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CharacterData$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CharacterData") extern class CharacterData extends Node { + + /** + Is a `DOMString` representing the textual data contained in this object. + **/ var data : String; + + /** + Returns an `unsigned long` representing the size of the string contained in `CharacterData.data`. + **/ var length(default,null) : Int; var previousElementSibling(default,null) : Element; var nextElementSibling(default,null) : Element; /** @throws DOMError */ + + /** + Returns a `DOMString` containing the part of `CharacterData.data` of the specified length and starting at the specified offset. + **/ function substringData( offset : Int, count : Int ) : String; /** @throws DOMError */ + + /** + Appends the given `DOMString` to the `CharacterData.data` string; when this method returns, `data` contains the concatenated `DOMString`. + **/ function appendData( data : String ) : Void; /** @throws DOMError */ + + /** + Inserts the specified characters, at the specified offset, in the `CharacterData.data` string; when this method returns, `data` contains the modified `DOMString`. + **/ function insertData( offset : Int, data : String ) : Void; /** @throws DOMError */ + + /** + Removes the specified amount of characters, starting at the specified offset, from the `CharacterData.data` string; when this method returns, `data` contains the shortened `DOMString`. + **/ function deleteData( offset : Int, count : Int ) : Void; /** @throws DOMError */ + + /** + Replaces the specified amount of characters, starting at the specified offset, with the specified `DOMString`; when this method returns, `data` contains the modified `DOMString`. + **/ function replaceData( offset : Int, count : Int, data : String ) : Void; function remove() : Void; } \ No newline at end of file diff --git a/std/js/html/ChromeFilePropertyBag.hx b/std/js/html/ChromeFilePropertyBag.hx index 786aa81d..e8efadc6 100644 --- a/std/js/html/ChromeFilePropertyBag.hx +++ b/std/js/html/ChromeFilePropertyBag.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/File.webidl line 35:0. Do not edit! +// This file is generated from mozilla\File.webidl. Do not edit! package js.html; diff --git a/std/js/html/Client.hx b/std/js/html/Client.hx new file mode 100644 index 00000000..3018a17c --- /dev/null +++ b/std/js/html/Client.hx @@ -0,0 +1,59 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Client.webidl. Do not edit! + +package js.html; + +/** + The `Client` interface of the ServiceWorker API represents the scope of a service worker client. A service worker client is either a document in a browser context or a `SharedWorker`, which is controlled by an active worker. A client object acts as a snapshot representation of its associated service worker client in the scope of a service worker. + + Documentation [Client](https://developer.mozilla.org/en-US/docs/Web/API/Client) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Client$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("Client") +extern class Client +{ + + /** + The URL of the current service worker client. + **/ + var url(default,null) : String; + + /** + Indicates the type of browsing context of the current client. This value can be one of `auxiliary`, `top-level`, `nested`, or `none`. + **/ + var frameType(default,null) : FrameType; + + /** + Returns the universally unique identifier of the `Client` object. + **/ + var id(default,null) : String; + + /** @throws DOMError */ + + /** + Allows a service worker to send a message to a `ServiceWorkerClient`. + **/ + function postMessage( message : Dynamic, ?transfer : Array ) : Void; +} \ No newline at end of file diff --git a/std/js/html/ClientQueryOptions.hx b/std/js/html/ClientQueryOptions.hx new file mode 100644 index 00000000..cea59eb2 --- /dev/null +++ b/std/js/html/ClientQueryOptions.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Clients.webidl. Do not edit! + +package js.html; + +typedef ClientQueryOptions = +{ + @:optional var includeUncontrolled : Bool; + @:optional var type : Dynamic/*MISSING ClientType*/; +} \ No newline at end of file diff --git a/std/js/html/Clients.hx b/std/js/html/Clients.hx new file mode 100644 index 00000000..ba9535c1 --- /dev/null +++ b/std/js/html/Clients.hx @@ -0,0 +1,52 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Clients.webidl. Do not edit! + +package js.html; + +/** + The `Clients` interface of the Service Workers API represents a container for a list of `Client` objects. + + Documentation [Clients](https://developer.mozilla.org/en-US/docs/Web/API/Clients) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Clients$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("Clients") +extern class Clients +{ + + /** + Gets a service worker client matching a given `id` and returns it in a `Promise`. + **/ + function get( id : String ) : Promise; + + /** + Gets a list of service worker clients and returns them in a `Promise`. Include the `options` parameter to return all service worker clients whose origin is the same as the associated service worker's origin. If `options` are not included, the method returns only the service worker clients controlled by the service worker.  + **/ + function matchAll( ?options : ClientQueryOptions ) : Promise>; + + /** + Allows an active Service Worker to set itself as the active worker for a client page when the worker and the page are in the same scope.  + **/ + function claim() : Promise; +} \ No newline at end of file diff --git a/std/js/html/ClipboardEvent.hx b/std/js/html/ClipboardEvent.hx index 446f2ac3..da5f9c61 100644 --- a/std/js/html/ClipboardEvent.hx +++ b/std/js/html/ClipboardEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ClipboardEvent.webidl line 14:0. Do not edit! +// This file is generated from mozilla\ClipboardEvent.webidl. Do not edit! package js.html; +/** + The `ClipboardEvent` interface represents events providing information related to modification of the clipboard, that is `cut`, `copy`, and `paste` events. + + Documentation [ClipboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("ClipboardEvent") extern class ClipboardEvent extends Event { + + /** + Is a `DataTransfer` object containing the data affected by the user-initiated `cut`, `copy`, or `paste` operation, along with its MIME type. + **/ var clipboardData(default,null) : DataTransfer; /** @throws DOMError */ diff --git a/std/js/html/ClipboardEventInit.hx b/std/js/html/ClipboardEventInit.hx index b1ecb795..87ffbc32 100644 --- a/std/js/html/ClipboardEventInit.hx +++ b/std/js/html/ClipboardEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ClipboardEvent.webidl line 19:0. Do not edit! +// This file is generated from mozilla\ClipboardEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/CloseEvent.hx b/std/js/html/CloseEvent.hx index ab1ed8f2..752e41fa 100644 --- a/std/js/html/CloseEvent.hx +++ b/std/js/html/CloseEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,19 +20,151 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CloseEvent.webidl line 14:0. Do not edit! +// This file is generated from mozilla\CloseEvent.webidl. Do not edit! package js.html; +/** + A `CloseEvent` is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the `WebSocket` object's `onclose` attribute. + + Documentation [CloseEvent](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CloseEvent") extern class CloseEvent extends Event { + + /** + Returns a `Boolean` that Indicates whether or not the connection was cleanly closed. + **/ var wasClean(default,null) : Bool; + + /** + Returns an unsigned short containing the close code send by the server. The following values are permitted status codes. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Status codeNameDescription
0999 Reserved and not used.
1000CLOSE_NORMALNormal closure; the connection successfully completed whatever purpose for which it was created.
1001CLOSE_GOING_AWAYThe endpoint is going away, either because of a server failure or because the browser is navigating away from the page that opened the connection.
1002CLOSE_PROTOCOL_ERRORThe endpoint is terminating the connection due to a protocol error.
1003CLOSE_UNSUPPORTEDThe connection is being terminated because the endpoint received data of a type it cannot accept (for example, a text-only endpoint received binary data).
1004 Reserved. A meaning might be defined in the future.
1005CLOSE_NO_STATUSReserved.  Indicates that no status code was provided even though one was expected.
1006CLOSE_ABNORMALReserved. Used to indicate that a connection was closed abnormally (that is, with no close frame being sent) when a status code is expected.
1007Unsupported DataThe endpoint is terminating the connection because a message was received that contained inconsistent data (e.g., non-UTF-8 data within a text message).
1008Policy ViolationThe endpoint is terminating the connection because it received a message that violates its policy. This is a generic status code, used when codes 1003 and 1009 are not suitable.
1009CLOSE_TOO_LARGEThe endpoint is terminating the connection because a data frame was received that is too large.
1010Missing ExtensionThe client is terminating the connection because it expected the server to negotiate one or more extension, but the server didn't.
1011Internal ErrorThe server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.
1012Service RestartThe server is terminating the connection because it is restarting. [Ref]
1013Try Again LaterThe server is terminating the connection due to a temporary condition, e.g. it is overloaded and is casting off some of its clients. [Ref]
1014 Reserved for future use by the WebSocket standard.
1015TLS HandshakeReserved. Indicates that the connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified).
10161999 Reserved for future use by the WebSocket standard.
20002999 Reserved for use by WebSocket extensions.
30003999 Available for use by libraries and frameworks. May not be used by applications. Available for registration at the IANA via first-come, first-serve.
40004999 Available for use by applications.
+ + **/ var code(default,null) : Int; + + /** + Returns a `DOMString` indicating the reason the server closed the connection. This is specific to the particular server and sub-protocol. + **/ var reason(default,null) : String; /** @throws DOMError */ function new( type : String, ?eventInitDict : CloseEventInit ) : Void; - /** @throws DOMError */ - function initCloseEvent( aType : String, aCanBubble : Bool, aCancelable : Bool, aWasClean : Bool, aReasonCode : Int, aReason : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/CloseEventInit.hx b/std/js/html/CloseEventInit.hx index e4ae96c1..11bcd080 100644 --- a/std/js/html/CloseEventInit.hx +++ b/std/js/html/CloseEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CloseEvent.webidl line 29:0. Do not edit! +// This file is generated from mozilla\CloseEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/CommandEvent.hx b/std/js/html/CommandEvent.hx index 694e721f..39b76356 100644 --- a/std/js/html/CommandEvent.hx +++ b/std/js/html/CommandEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CommandEvent.webidl line 7:0. Do not edit! +// This file is generated from mozilla\CommandEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/Comment.hx b/std/js/html/Comment.hx index bd732b55..675e435a 100644 --- a/std/js/html/Comment.hx +++ b/std/js/html/Comment.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Comment.webidl line 14:0. Do not edit! +// This file is generated from mozilla\Comment.webidl. Do not edit! package js.html; +/** + The `Comment` interface represents textual notations within markup; although it is generally not visually shown, such comments are available to be read in the source view. Comments are represented in HTML and XML as content between '`!--`' and '`--`'. In XML, the character sequence '`--`' cannot be used within a comment. + + Documentation [Comment](https://developer.mozilla.org/en-US/docs/Web/API/Comment) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Comment$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Comment") extern class Comment extends CharacterData { diff --git a/std/js/html/CompositeOperation.hx b/std/js/html/CompositeOperation.hx new file mode 100644 index 00000000..4190eadb --- /dev/null +++ b/std/js/html/CompositeOperation.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Keyframe.webidl. Do not edit! + +package js.html; + +@:enum abstract CompositeOperation(String) +{ + var REPLACE = "replace"; + var ADD = "add"; + var ACCUMULATE = "accumulate"; +} \ No newline at end of file diff --git a/std/js/html/CompositionEvent.hx b/std/js/html/CompositionEvent.hx index f4ba7fd1..c09a9ede 100644 --- a/std/js/html/CompositionEvent.hx +++ b/std/js/html/CompositionEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,22 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CompositionEvent.webidl line 12:0. Do not edit! +// This file is generated from mozilla\CompositionEvent.webidl. Do not edit! package js.html; +/** + The DOM `CompositionEvent` represents events that occur due to the user indirectly entering text. + + Documentation [CompositionEvent](https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CompositionEvent") extern class CompositionEvent extends UIEvent { var data(default,null) : String; var locale(default,null) : String; - /** @throws DOMError */ function initCompositionEvent( typeArg : String, canBubbleArg : Bool, cancelableArg : Bool, viewArg : Window, dataArg : String, localeArg : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/CreateFileOptions.hx b/std/js/html/ComputedTimingProperties.hx similarity index 74% rename from std/js/html/CreateFileOptions.hx rename to std/js/html/ComputedTimingProperties.hx index dbf2ebfc..df1ca05b 100644 --- a/std/js/html/CreateFileOptions.hx +++ b/std/js/html/ComputedTimingProperties.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,12 +20,16 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Directory.webidl line 95:0. Do not edit! +// This file is generated from mozilla\AnimationEffectReadOnly.webidl. Do not edit! package js.html; -typedef CreateFileOptions = +typedef ComputedTimingProperties = { - @:optional var data : haxe.extern.EitherType>>; - @:optional var ifExists : Dynamic/*MISSING CreateIfExistsMode*/; + > AnimationEffectTimingProperties, + @:optional var activeDuration : Float; + @:optional var currentIteration : Float; + @:optional var endTime : Float; + @:optional var localTime : Float; + @:optional var progress : Float; } \ No newline at end of file diff --git a/std/js/html/Console.hx b/std/js/html/Console.hx index a623ed61..893c25a7 100644 --- a/std/js/html/Console.hx +++ b/std/js/html/Console.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,30 +20,128 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Console.webidl line 9:0. Do not edit! +// This file is generated from mozilla\Console.webidl. Do not edit! package js.html; +/** + The `Console` object provides access to the browser's debugging console (e.g., the Web Console in Firefox). The specifics of how it works vary from browser to browser, but there is a de facto set of features that are typically provided. + + Documentation [Console](https://developer.mozilla.org/en-US/docs/Web/API/Console) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Console$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Console") extern class Console { + + /** + For general output of logging information. You may use string substitution and additional arguments with this method. + **/ function log( data : haxe.extern.Rest ) : Void; + + /** + Informative logging information. You may use string substitution and additional arguments with this method. + **/ function info( data : haxe.extern.Rest ) : Void; + + /** + Outputs a warning message. You may use string substitution and additional arguments with this method. + **/ function warn( data : haxe.extern.Rest ) : Void; + + /** + Outputs an error message. You may use string substitution and additional arguments with this method. + **/ function error( data : haxe.extern.Rest ) : Void; + + /** + An alias for `error()` + **/ function exception( data : haxe.extern.Rest ) : Void; + + /** + An alias for `log()` + **/ function debug( data : haxe.extern.Rest ) : Void; + + /** + Displays tabular data as a table. + **/ function table( data : haxe.extern.Rest ) : Void; + + /** + Outputs a stack trace. + **/ function trace() : Void; + + /** + Displays an interactive listing of the properties of a specified JavaScript object. This listing lets you use disclosure triangles to examine the contents of child objects. + **/ function dir( data : haxe.extern.Rest ) : Void; + + /** + + Displays an XML/HTML Element representation of the specified object if possible or the JavaScript Object view if it is not. + + **/ + function dirxml( data : haxe.extern.Rest ) : Void; + + /** + Creates a new inline group, indenting all following output by another level. To move back out a level, call `groupEnd()`. + **/ function group( data : haxe.extern.Rest ) : Void; + + /** + Creates a new inline group, indenting all following output by another level; unlike `group()`, this starts with the inline group collapsed, requiring the use of a disclosure button to expand it. To move back out a level, call `groupEnd()`. + **/ function groupCollapsed( data : haxe.extern.Rest ) : Void; + + /** + Exits the current inline group. + **/ function groupEnd( data : haxe.extern.Rest ) : Void; + + /** + Starts a timer with a name specified as an input parameter. Up to 10,000 simultaneous timers can run on a given page. + **/ function time( ?time : Dynamic ) : Void; + + /** + Stops the specified timer and logs the elapsed time in seconds since its start. + **/ function timeEnd( ?time : Dynamic ) : Void; + + /** + Adds a marker to the browser's Timeline or Waterfall tool. + **/ + function timeStamp( ?data : Dynamic ) : Void; + + /** + Starts the browser's build-in profiler (for example, the Firefox performance tool). You can specify an optional name for the profile. + **/ function profile( data : haxe.extern.Rest ) : Void; + + /** + Stops the profiler. You can see the resulting profile in the browser's performance tool (for example, the Firefox performance tool). + **/ function profileEnd( data : haxe.extern.Rest ) : Void; + + /** + Log a message and stack trace to console if first argument is `false`. + **/ function assert( condition : Bool, data : haxe.extern.Rest ) : Void; + + /** + Log the number of times this line has been called with the given label. + **/ function count( data : haxe.extern.Rest ) : Void; + + /** + Clear the console. + **/ function clear() : Void; + function markTimeline() : Void; + function timeline() : Void; + function timelineEnd() : Void; } \ No newline at end of file diff --git a/std/js/html/ContentElement.hx b/std/js/html/ContentElement.hx index c9e7050d..eaade210 100644 --- a/std/js/html/ContentElement.hx +++ b/std/js/html/ContentElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLContentElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLContentElement.webidl. Do not edit! package js.html; +/** + The `HTMLContentElement` interface represents a `content` HTML Element, which is used in Shadow DOM. + + Documentation [HTMLContentElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLContentElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLContentElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLContentElement") extern class ContentElement extends Element { + + /** + Is a `DOMString` that reflects the `select` HTML attribute. The value is a comma-separated list of CSS selectors that select the content to insert in place of the `content` element. + **/ var select : String; + + /** + Returns a static `NodeList` of the `distributed nodes` associated with this `content` element.  + **/ function getDistributedNodes() : NodeList; } \ No newline at end of file diff --git a/std/js/html/ConvertCoordinateOptions.hx b/std/js/html/ConvertCoordinateOptions.hx index be181908..438ff080 100644 --- a/std/js/html/ConvertCoordinateOptions.hx +++ b/std/js/html/ConvertCoordinateOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/GeometryUtils.webidl line 19:0. Do not edit! +// This file is generated from mozilla\GeometryUtils.webidl. Do not edit! package js.html; diff --git a/std/js/html/Coordinates.hx b/std/js/html/Coordinates.hx index a90f642d..a8e23a02 100644 --- a/std/js/html/Coordinates.hx +++ b/std/js/html/Coordinates.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,19 +20,54 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Coordinates.webidl line 14:0. Do not edit! +// This file is generated from mozilla\Coordinates.webidl. Do not edit! package js.html; +/** + The `Coordinates` interface represents the position and altitude of the device on Earth, as well as the accuracy with which these properties are calculated. + + Documentation [Coordinates](https://developer.mozilla.org/en-US/docs/Web/API/Coordinates) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Coordinates$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Coordinates") extern class Coordinates { + + /** + Returns a `double` representing the position's latitude in decimal degrees. + **/ var latitude(default,null) : Float; + + /** + Returns a `double` representing the position's longitude in decimal degrees. + **/ var longitude(default,null) : Float; + + /** + Returns a `double` representing the position's altitude in metres, relative to sea level. This value can be `null` if the implementation cannot provide the data. + **/ var altitude(default,null) : Float; + + /** + Returns a `double` representing the accuracy of the `latitude` and `longitude` properties, expressed in meters. + **/ var accuracy(default,null) : Float; + + /** + Returns a `double` representing the accuracy of the `altitude` expressed in meters. This value can be `null`. + **/ var altitudeAccuracy(default,null) : Float; + + /** + Returns a `double` representing the direction in which the device is traveling. This value, specified in degrees, indicates how far off from heading true north the device is. `0` degrees represents true north, and the direction is determined clockwise (which means that east is `90` degrees and west is `270` degrees). If `speed` is `0`, `heading` is `NaN`. If the device is unable to provide `heading` information, this value is `null`. + **/ var heading(default,null) : Float; + + /** + Returns a `double` representing the velocity of the device in meters per second. This value can be `null`. + **/ var speed(default,null) : Float; } \ No newline at end of file diff --git a/std/js/html/Crypto.hx b/std/js/html/Crypto.hx index 62a151b9..5ab5abab 100644 --- a/std/js/html/Crypto.hx +++ b/std/js/html/Crypto.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Crypto.webidl line 18:0. Do not edit! +// This file is generated from mozilla\Crypto.webidl. Do not edit! package js.html; +/** + The `Crypto` interface represents basic cryptography features available in the current context. It allows access to a cryptographically strong random number generator and to cryptographic primitives. + + Documentation [Crypto](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Crypto$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Crypto") extern class Crypto { + + /** + Returns a `SubtleCrypto` object providing access to common cryptographic primitives, like hashing, signing, encryption or decryption. + **/ var subtle(default,null) : SubtleCrypto; /** @throws DOMError */ diff --git a/std/js/html/CryptoKey.hx b/std/js/html/CryptoKey.hx index 58dca6f6..ba143b1c 100644 --- a/std/js/html/CryptoKey.hx +++ b/std/js/html/CryptoKey.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,39 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SubtleCrypto.webidl line 142:0. Do not edit! +// This file is generated from mozilla\SubtleCrypto.webidl. Do not edit! package js.html; +/** + The `CryptoKey` interface represents a cryptographic key derived from a specific key algorithm. + + Documentation [CryptoKey](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CryptoKey") extern class CryptoKey { + + /** + Returns an enumerated value representing the type of the key, a secret key (for symmetric algorithm), a public or a private key (for an asymmetric algorithm) + **/ var type(default,null) : String; + + /** + Returns a `Boolean` indicating if the raw information may be exported to the application or not. + **/ var extractable(default,null) : Bool; + + /** + Returns an opaque object representing a particular cipher the key has to be used with. + **/ var algorithm(default,null) : Dynamic; + + /** + Returns an array of enumerated values indicating what the key can be used for. + **/ var usages(default,null) : Array; } \ No newline at end of file diff --git a/std/js/html/CustomEvent.hx b/std/js/html/CustomEvent.hx index f86667d3..9d74ae09 100644 --- a/std/js/html/CustomEvent.hx +++ b/std/js/html/CustomEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,17 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CustomEvent.webidl line 14:0. Do not edit! +// This file is generated from mozilla\CustomEvent.webidl. Do not edit! package js.html; +/** + This interface inherits properties from its parent, `Event`: + + Documentation [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("CustomEvent") extern class CustomEvent extends Event { + + /** + Any data passed when initializing the event. + **/ var detail(default,null) : Dynamic; /** @throws DOMError */ function new( type : String, ?eventInitDict : CustomEventInit ) : Void; /** @throws DOMError */ + + /** + + Initializes a `CustomEvent` object. If the event has already being dispatched, this method does nothing. + + **/ function initCustomEvent( type : String, canBubble : Bool, cancelable : Bool, detail : Dynamic ) : Void; } \ No newline at end of file diff --git a/std/js/html/CustomEventInit.hx b/std/js/html/CustomEventInit.hx index 2cc3549d..381f111c 100644 --- a/std/js/html/CustomEventInit.hx +++ b/std/js/html/CustomEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CustomEvent.webidl line 26:0. Do not edit! +// This file is generated from mozilla\CustomEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/DListElement.hx b/std/js/html/DListElement.hx index 6c4e52a9..05a76ec2 100644 --- a/std/js/html/DListElement.hx +++ b/std/js/html/DListElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLDListElement.webidl line 16:0. Do not edit! +// This file is generated from mozilla\HTMLDListElement.webidl. Do not edit! package js.html; +/** + The `HTMLDListElement` interface provides special properties (beyond those of the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating definition list elements. + + Documentation [HTMLDListElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDListElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDListElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLDListElement") extern class DListElement extends Element { + + /** + Is a `Boolean` indicating that spacing between list items should be reduced. + **/ var compact : Bool; } \ No newline at end of file diff --git a/std/js/html/DOMApplicationCache.hx b/std/js/html/DOMApplicationCache.hx deleted file mode 100644 index 61887d9d..00000000 --- a/std/js/html/DOMApplicationCache.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html; - -/** @deprecated Use ApplicationCache instead. */ -@:deprecated("DOMApplicationCache is deprecated, use ApplicationCache instead") -typedef DOMApplicationCache = ApplicationCache; diff --git a/std/js/html/DOMCoreException.hx b/std/js/html/DOMCoreException.hx deleted file mode 100644 index e18ca368..00000000 --- a/std/js/html/DOMCoreException.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html; - -/** @deprecated Use DOMException instead. */ -@:deprecated("DOMCoreException is deprecated, use DOMException instead") -typedef DOMCoreException = DOMException; diff --git a/std/js/html/DOMCursor.hx b/std/js/html/DOMCursor.hx index 175663df..d44bf548 100644 --- a/std/js/html/DOMCursor.hx +++ b/std/js/html/DOMCursor.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMCursor.webidl line 6:0. Do not edit! +// This file is generated from mozilla\DOMCursor.webidl. Do not edit! package js.html; diff --git a/std/js/html/DOMElement.hx b/std/js/html/DOMElement.hx index bee3892a..eb6dd65b 100644 --- a/std/js/html/DOMElement.hx +++ b/std/js/html/DOMElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Element.webidl line 16:0. Do not edit! +// This file is generated from mozilla\Element.webidl. Do not edit! package js.html; +/** + The `Element` interface represents an object of a `Document`. This interface describes methods and properties common to all kinds of elements. Specific behaviors are described in interfaces which inherit from `Element` but add additional functionality. + + Documentation [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Element$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Element") extern class DOMElement extends Node { @@ -37,11 +44,12 @@ extern class DOMElement extends Node var lang : String; var dir : String; var dataset(default,null) : DOMStringMap; + var innerText : String; var itemScope : Bool; - var itemType(default,null) : DOMSettableTokenList; + var itemType(default,null) : DOMTokenList; var itemId : String; - var itemRef(default,null) : DOMSettableTokenList; - var itemProp(default,null) : DOMSettableTokenList; + var itemRef(default,null) : DOMTokenList; + var itemProp(default,null) : DOMTokenList; var properties(default,null) : HTMLPropertiesCollection; var itemValue : Dynamic; var hidden : Bool; @@ -57,7 +65,6 @@ extern class DOMElement extends Node var oncopy : haxe.Constraints.Function; var oncut : haxe.Constraints.Function; var onpaste : haxe.Constraints.Function; - var innerText : String; var offsetParent(default,null) : Element; var offsetTop(default,null) : Int; var offsetLeft(default,null) : Int; @@ -117,6 +124,7 @@ extern class DOMElement extends Node var onprogress : haxe.Constraints.Function; var onratechange : haxe.Constraints.Function; var onreset : haxe.Constraints.Function; + var onresize : haxe.Constraints.Function; var onscroll : haxe.Constraints.Function; var onseeked : haxe.Constraints.Function; var onseeking : haxe.Constraints.Function; @@ -138,6 +146,8 @@ extern class DOMElement extends Node var onpointerleave : haxe.Constraints.Function; var ongotpointercapture : haxe.Constraints.Function; var onlostpointercapture : haxe.Constraints.Function; + var onfullscreenchange : haxe.Constraints.Function; + var onfullscreenerror : haxe.Constraints.Function; var onpointerlockchange : haxe.Constraints.Function; var onpointerlockerror : haxe.Constraints.Function; var previousElementSibling(default,null) : Element; @@ -152,6 +162,7 @@ extern class DOMElement extends Node var ontouchmove : haxe.Constraints.Function; var ontouchcancel : haxe.Constraints.Function; + function getAttributeNames() : Array; function getAttribute( name : String ) : String; function getAttributeNS( namespace_ : String, localName : String ) : String; /** @throws DOMError */ @@ -169,11 +180,17 @@ extern class DOMElement extends Node function closest( selector : String ) : Element; /** @throws DOMError */ function matches( selector : String ) : Bool; + /** @throws DOMError */ + function webkitMatchesSelector( selector : String ) : Bool; function getElementsByTagName( localName : String ) : HTMLCollection; /** @throws DOMError */ function getElementsByTagNameNS( namespace_ : String, localName : String ) : HTMLCollection; function getElementsByClassName( classNames : String ) : HTMLCollection; /** @throws DOMError */ + + /** + Designates a specific element as the capture target of future `PointerEvent`. + **/ function setPointerCapture( pointerId : Int ) : Void; /** @throws DOMError */ function releasePointerCapture( pointerId : Int ) : Void; @@ -188,7 +205,6 @@ extern class DOMElement extends Node function getAttributeNodeNS( namespaceURI : String, localName : String ) : Attr; /** @throws DOMError */ function setAttributeNodeNS( newAttr : Attr ) : Attr; - function requestFullscreen() : Void; function click() : Void; /** @throws DOMError */ function focus() : Void; @@ -212,8 +228,24 @@ extern class DOMElement extends Node function querySelectorAll( selectors : String ) : NodeList; /** @throws DOMError */ function createShadowRoot() : ShadowRoot; + + /** + … + **/ function getDestinationInsertionPoints() : NodeList; - function getAnimationPlayers() : Array; + /** @throws DOMError */ + function requestFullscreen( ?options : Dynamic ) : Void; + /** @throws DOMError */ + + /** + A shortcut method to create and run an animation on an element. Returns the created Animation object instance. + **/ + function animate( frames : Dynamic, ?options : haxe.extern.EitherType ) : Animation; + + /** + Returns an array of Animation objects currently active on the element. + **/ + function getAnimations() : Array; function remove() : Void; /** @throws DOMError */ function convertQuadFromNode( quad : DOMQuad, from : haxe.extern.EitherType>, ?options : ConvertCoordinateOptions ) : DOMQuad; diff --git a/std/js/html/DOMError.hx b/std/js/html/DOMError.hx index 818a4d00..620d181d 100644 --- a/std/js/html/DOMError.hx +++ b/std/js/html/DOMError.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMError.webidl line 15:0. Do not edit! +// This file is generated from mozilla\DOMError.webidl. Do not edit! package js.html; +/** + The `DOMError` interface describes an error object that contains an error name. + + Documentation [DOMError](https://developer.mozilla.org/en-US/docs/Web/API/DOMError) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMError$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMError") extern class DOMError { + + /** + Returns a `DOMString` representing one of the error type names (see below). + **/ var name(default,null) : String; var message(default,null) : String; diff --git a/std/js/html/DOMException.hx b/std/js/html/DOMException.hx index 314b8e77..f916d101 100644 --- a/std/js/html/DOMException.hx +++ b/std/js/html/DOMException.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMException.webidl line 78:0. Do not edit! +// This file is generated from mozilla\DOMException.webidl. Do not edit! package js.html; +/** + The `DOMException` interface represents an abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API. This is basically how error conditions are described in web APIs. + + Documentation [DOMException](https://developer.mozilla.org/en-US/docs/Web/API/DOMException) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMException$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMException") extern class DOMException { @@ -60,8 +67,9 @@ extern class DOMException var filename(default,null) : String; var lineNumber(default,null) : Int; var columnNumber(default,null) : Int; - var inner(default,null) : Dynamic/*MISSING nsISupports*/; var data(default,null) : Dynamic/*MISSING nsISupports*/; var stack(default,null) : String; + /** @throws DOMError */ + function new( ?message : String = "", ?name : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/DOMImplementation.hx b/std/js/html/DOMImplementation.hx index 45e98ee5..23b8178d 100644 --- a/std/js/html/DOMImplementation.hx +++ b/std/js/html/DOMImplementation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,18 +20,41 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMImplementation.webidl line 14:0. Do not edit! +// This file is generated from mozilla\DOMImplementation.webidl. Do not edit! package js.html; +/** + The `DOMImplementation` interface represent an object providing methods which are not dependent on any particular document. Such an object is returned by the `Document.implementation` property. + + Documentation [DOMImplementation](https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMImplementation") extern class DOMImplementation { + + /** + Returns a `Boolean` indicating if a given feature is supported or not. This function is unreliable and kept for compatibility purpose alone: except for SVG-related queries, it always returns `true`. Old browsers are very inconsistent in their behavior. + **/ function hasFeature( feature : String, version : String ) : Bool; /** @throws DOMError */ + + /** + Creates and returns a `DocumentType`. + **/ function createDocumentType( qualifiedName : String, publicId : String, systemId : String ) : DocumentType; /** @throws DOMError */ + + /** + Creates and returns an `XMLDocument`. + **/ function createDocument( namespace_ : String, qualifiedName : String, ?doctype : DocumentType ) : HTMLDocument; /** @throws DOMError */ + + /** + Creates and returns an HTML `Document`. + **/ function createHTMLDocument( ?title : String ) : HTMLDocument; } \ No newline at end of file diff --git a/std/js/html/DOMMatrix.hx b/std/js/html/DOMMatrix.hx index cf613f2b..2382e8b0 100644 --- a/std/js/html/DOMMatrix.hx +++ b/std/js/html/DOMMatrix.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMMatrix.webidl line 89:0. Do not edit! +// This file is generated from mozilla\DOMMatrix.webidl. Do not edit! package js.html; +/** + The `DOMMatrix` interface represents 4x4 matrices, suitable for 2D and 3D operations. + + Documentation [DOMMatrix](https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrix) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrix$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMMatrix") extern class DOMMatrix extends DOMMatrixReadOnly { @@ -36,16 +43,60 @@ extern class DOMMatrix extends DOMMatrixReadOnly function new( numberSequence : Array ) : Void; function multiplySelf( other : DOMMatrix ) : DOMMatrix; function preMultiplySelf( other : DOMMatrix ) : DOMMatrix; + + /** + Returns itself, a `DOMMatrix`, with its new content being the result of the matrix being translated by the given vector. + **/ function translateSelf( tx : Float, ty : Float, ?tz : Float = 0.0 ) : DOMMatrix; + + /** + Returns itself, a `DOMMatrix`, with its new content being the result of the matrix x and y dimensions being scaled by the given factor, centered on the origin given. + **/ function scaleSelf( scale : Float, ?originX : Float = 0.0, ?originY : Float = 0.0 ) : DOMMatrix; + + /** + Returns itself, a `DOMMatrix`, with its new content being the result of the matrix x, y and z dimension being scaled by the given factor, centered on the origin given. + **/ function scale3dSelf( scale : Float, ?originX : Float = 0.0, ?originY : Float = 0.0, ?originZ : Float = 0.0 ) : DOMMatrix; + + /** + Returns itself, a `DOMMatrix`, with its new content being the result of the matrix x, y and z dimension being scaled by the given factor for each dimension, centered on the origin given. + **/ function scaleNonUniformSelf( scaleX : Float, ?scaleY : Float = 1.0, ?scaleZ : Float = 1.0, ?originX : Float = 0.0, ?originY : Float = 0.0, ?originZ : Float = 0.0 ) : DOMMatrix; + + /** + Returns itself, a `DOMMatrix`, with its new content being the result of the original matrix being rotated by the given angle, with the rotation centered on the origin given. + **/ function rotateSelf( angle : Float, ?originX : Float = 0.0, ?originY : Float = 0.0 ) : DOMMatrix; + + /** + Returns itself, a `DOMMatrix`, with its new content being the result of the original matrix being rotated by the angle between the given vector and (1,0), centered on the origin given. + **/ function rotateFromVectorSelf( x : Float, y : Float ) : DOMMatrix; + + /** + Returns itself, a `DOMMatrix`, with its new content being the result of the original matrix being rotated by the given angle and the give vector. + **/ function rotateAxisAngleSelf( x : Float, y : Float, z : Float, angle : Float ) : DOMMatrix; + + /** + Returns itself, a `DOMMatrix`, with its new content being the result of the original matrix being skewed along the x-axis by the given factor. + **/ function skewXSelf( sx : Float ) : DOMMatrix; + + /** + Returns itself, a `DOMMatrix`, with its new content being the result of the original matrix being skewed along the y-axis by the given factor. + **/ function skewYSelf( sy : Float ) : DOMMatrix; + + /** + Returns itself,  a `DOMMatrix`, with its new content being the result of the original matrix being inverted. If the matrix cannot be inverted, all its components are set to `NaN` and `is2D()` returns `false`. + **/ function invertSelf() : DOMMatrix; /** @throws DOMError */ + + /** + Returns itself, a `DOMMatrix`, with its describing the matrix representing the same transformation as the CSS `transform` functions given in parameter. + **/ function setMatrixValue( transformList : String ) : DOMMatrix; } \ No newline at end of file diff --git a/std/js/html/DOMMatrixReadOnly.hx b/std/js/html/DOMMatrixReadOnly.hx index 2d46028c..840621a4 100644 --- a/std/js/html/DOMMatrixReadOnly.hx +++ b/std/js/html/DOMMatrixReadOnly.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,19 +20,69 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMMatrix.webidl line 14:0. Do not edit! +// This file is generated from mozilla\DOMMatrix.webidl. Do not edit! package js.html; +/** + The `DOMMatrixReadOnly` interface represents 4x4 matrices, suitable for 2D and 3D operations. If this interface defines only read-only matrices, the `DOMMatrix` interface which inherits from it, add all the properties and the methods to allow to have modifiable matrices. + + Documentation [DOMMatrixReadOnly](https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrixReadOnly) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrixReadOnly$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMMatrixReadOnly") extern class DOMMatrixReadOnly { + + /** + Are double representing each component of a 4x4 matrix needed for 2D rotations and translations. They are aliases for some components of the 4x4 matrix: + + + + 2D + 3D equivalent + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
am11
bm12
cm21
dm22
em41
fm42
+ They are read-only, but their counterpart, with the same name, in DOMMatrix aren't. + **/ var a(default,null) : Float; var b(default,null) : Float; var c(default,null) : Float; var d(default,null) : Float; var e(default,null) : Float; var f(default,null) : Float; + + /** + Are `double` representing each component of a 4x4 matrix. They are read-only, but their counterpart, with the same name, in `DOMMatrix` aren't. + **/ var m11(default,null) : Float; var m12(default,null) : Float; var m13(default,null) : Float; @@ -49,25 +99,89 @@ extern class DOMMatrixReadOnly var m42(default,null) : Float; var m43(default,null) : Float; var m44(default,null) : Float; + + /** + Is a `Boolean` indicating if the matrix contains a 2D matrix and only accept 2D transformations. + **/ var is2D(default,null) : Bool; var identity(default,null) : Bool; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the matrix being translated by the given vector. The original matrix is not modified. + **/ function translate( tx : Float, ty : Float, ?tz : Float = 0.0 ) : DOMMatrix; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the matrix x and y dimensions being scaled by the given factor, centered on the origin given. The original matrix is not modified. + **/ function scale( scale : Float, ?originX : Float = 0.0, ?originY : Float = 0.0 ) : DOMMatrix; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the matrix x, y and z dimension being scaled by the given factor, centered on the origin given. The original matrix is not modified. + **/ function scale3d( scale : Float, ?originX : Float = 0.0, ?originY : Float = 0.0, ?originZ : Float = 0.0 ) : DOMMatrix; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the matrix x, y and z dimension being scaled by the given factor for each dimension, centered on the origin given. The original matrix is not modified. + **/ function scaleNonUniform( scaleX : Float, ?scaleY : Float = 1.0, ?scaleZ : Float = 1.0, ?originX : Float = 0.0, ?originY : Float = 0.0, ?originZ : Float = 0.0 ) : DOMMatrix; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being rotated by the given angle, with the rotation centered on the origin given. The original matrix is not modified. + **/ function rotate( angle : Float, ?originX : Float = 0.0, ?originY : Float = 0.0 ) : DOMMatrix; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being rotated by the angle between the given vector and (1,0), centered on the origin given. The original matrix is not modified. + **/ function rotateFromVector( x : Float, y : Float ) : DOMMatrix; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being rotated by the given angle and the give vector. The original matrix is not modified. + **/ function rotateAxisAngle( x : Float, y : Float, z : Float, angle : Float ) : DOMMatrix; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being skewed along the x-axis by the given factor. The original matrix is not modified. + **/ function skewX( sx : Float ) : DOMMatrix; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being skewed along the y-axis by the given factor. The original matrix is not modified. + **/ function skewY( sy : Float ) : DOMMatrix; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being multiplied by the given `DOMMatrix`. The original matrix is not modified. + **/ function multiply( other : DOMMatrix ) : DOMMatrix; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being flipped around the x-axis, that is multiplied by the `DOMMatrix(-1, 0, 0, 1, 0, 0)`. The original matrix is not modified. + **/ function flipX() : DOMMatrix; + + /** + Returns a `DOMMatrix` containing a new matrix being the result of the original matrix being flipped around the y-axis, that is multiplied by the `DOMMatrix(1, 0, 0, -1, 0, 0)`. The original matrix is not modified. + **/ function flipY() : DOMMatrix; function inverse() : DOMMatrix; + + /** + Returns a `DOMPoint` that is the point given in parameter multiplied by the matrix. Bot the original point and the matrix aren't modified. + **/ function transformPoint( ?point : DOMPointInit ) : DOMPoint; /** @throws DOMError */ + + /** + Returns a `Float32Array` containing the 6 components (`a`, `b`, `c`, `d`, `e`, `f`) in the case of a 2D matrix or the 16 components (`m11`, `m12`, `m13`, `m14`, `m21`, `m22`, `m23`, `m24`, `m31`, `m32`, `m33`, `m34`, `m41`, `m42`, `m43`, `m44`) for a 3D matrix. + **/ function toFloat32Array() : Float32Array; /** @throws DOMError */ + + /** + Returns a `Float64Array` containing the 6 components (`a`, `b`, `c`, `d`, `e`, `f`) in the case of a 2D matrix or the 16 components (`m11`, `m12`, `m13`, `m14`, `m21`, `m22`, `m23`, `m24`, `m31`, `m32`, `m33`, `m34`, `m41`, `m42`, `m43`, `m44`) for a 3D matrix. + **/ function toFloat64Array() : Float64Array; } \ No newline at end of file diff --git a/std/js/html/DOMMimeType.hx b/std/js/html/DOMMimeType.hx deleted file mode 100644 index c58ee610..00000000 --- a/std/js/html/DOMMimeType.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html; - -/** @deprecated Use MimeType instead. */ -@:deprecated("DOMMimeType is deprecated, use MimeType instead") -typedef DOMMimeType = MimeType; diff --git a/std/js/html/DOMMimeTypeArray.hx b/std/js/html/DOMMimeTypeArray.hx deleted file mode 100644 index e805872b..00000000 --- a/std/js/html/DOMMimeTypeArray.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html; - -/** @deprecated Use MimeTypeArray instead. */ -@:deprecated("DOMMimeTypeArray is deprecated, use MimeTypeArray instead") -typedef DOMMimeTypeArray = MimeTypeArray; diff --git a/std/js/html/DOMParser.hx b/std/js/html/DOMParser.hx index 56a81d11..c194a513 100644 --- a/std/js/html/DOMParser.hx +++ b/std/js/html/DOMParser.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMParser.webidl line 25:0. Do not edit! +// This file is generated from mozilla\DOMParser.webidl. Do not edit! package js.html; +/** + `DOMParser` can parse XML or HTML source stored in a string into a DOM Document. `DOMParser` is specified in DOM Parsing and Serialization. + + Documentation [DOMParser](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMParser") extern class DOMParser { diff --git a/std/js/html/DOMPluginArray.hx b/std/js/html/DOMPluginArray.hx deleted file mode 100644 index 64b37bcf..00000000 --- a/std/js/html/DOMPluginArray.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html; - -/** @deprecated Use PluginArray instead. */ -@:deprecated("DOMPluginArray is deprecated, use PluginArray instead") -typedef DOMPluginArray = PluginArray; diff --git a/std/js/html/DOMPoint.hx b/std/js/html/DOMPoint.hx index 12699f90..6608b2bb 100644 --- a/std/js/html/DOMPoint.hx +++ b/std/js/html/DOMPoint.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMPoint.webidl line 25:0. Do not edit! +// This file is generated from mozilla\DOMPoint.webidl. Do not edit! package js.html; +/** + A `DOMPoint` represents a 2D or 3D point in a coordinate system. + + Documentation [DOMPoint](https://developer.mozilla.org/en-US/docs/Web/API/DOMPoint) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMPoint$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMPoint") extern class DOMPoint extends DOMPointReadOnly { diff --git a/std/js/html/DOMPointInit.hx b/std/js/html/DOMPointInit.hx index 1dc524ed..54dee931 100644 --- a/std/js/html/DOMPointInit.hx +++ b/std/js/html/DOMPointInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMPoint.webidl line 32:0. Do not edit! +// This file is generated from mozilla\DOMPoint.webidl. Do not edit! package js.html; diff --git a/std/js/html/DOMPointReadOnly.hx b/std/js/html/DOMPointReadOnly.hx index 91baf268..9a4f7c88 100644 --- a/std/js/html/DOMPointReadOnly.hx +++ b/std/js/html/DOMPointReadOnly.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,39 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMPoint.webidl line 14:0. Do not edit! +// This file is generated from mozilla\DOMPoint.webidl. Do not edit! package js.html; +/** + The `DOMPointReadOnly` interface specifies the standard properties used by `DOMPoint` to define a 2D or 3D point in a coordinate system. + + Documentation [DOMPointReadOnly](https://developer.mozilla.org/en-US/docs/Web/API/DOMPointReadOnly) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMPointReadOnly$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMPointReadOnly") extern class DOMPointReadOnly { + + /** + The x coordinate of the `DOMPoint`. + **/ var x(default,null) : Float; + + /** + The y coordinate of the `DOMPoint`. + **/ var y(default,null) : Float; + + /** + The z coordinate of the `DOMPoint`. + **/ var z(default,null) : Float; + + /** + The perspective value of the `DOMPoint`. + **/ var w(default,null) : Float; } \ No newline at end of file diff --git a/std/js/html/DOMQuad.hx b/std/js/html/DOMQuad.hx index f3579691..9915a5d7 100644 --- a/std/js/html/DOMQuad.hx +++ b/std/js/html/DOMQuad.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMQuad.webidl line 17:0. Do not edit! +// This file is generated from mozilla\DOMQuad.webidl. Do not edit! package js.html; diff --git a/std/js/html/DOMRect.hx b/std/js/html/DOMRect.hx index e7d09891..5e3de87d 100644 --- a/std/js/html/DOMRect.hx +++ b/std/js/html/DOMRect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMRect.webidl line 16:0. Do not edit! +// This file is generated from mozilla\DOMRect.webidl. Do not edit! package js.html; +/** + A `DOMRect` represents a rectangle. + + Documentation [DOMRect](https://developer.mozilla.org/en-US/docs/Web/API/DOMRect) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMRect$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMRect") extern class DOMRect extends DOMRectReadOnly { diff --git a/std/js/html/DOMRectList.hx b/std/js/html/DOMRectList.hx index 5341176d..01be0eb5 100644 --- a/std/js/html/DOMRectList.hx +++ b/std/js/html/DOMRectList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMRectList.webidl line 8:0. Do not edit! +// This file is generated from mozilla\DOMRectList.webidl. Do not edit! package js.html; diff --git a/std/js/html/DOMRectReadOnly.hx b/std/js/html/DOMRectReadOnly.hx index b6c35ed2..66f743e3 100644 --- a/std/js/html/DOMRectReadOnly.hx +++ b/std/js/html/DOMRectReadOnly.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,20 +20,59 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMRect.webidl line 23:0. Do not edit! +// This file is generated from mozilla\DOMRect.webidl. Do not edit! package js.html; +/** + The `DOMRectReadOnly` interface specifies the standard properties used by `DOMRect` to define a rectangle. + + Documentation [DOMRectReadOnly](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMRectReadOnly$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMRectReadOnly") extern class DOMRectReadOnly { + + /** + The x coordinate of the `DOMRect`'s origin. + **/ var x(default,null) : Float; + + /** + The y coordinate of the `DOMRect`'s origin. + **/ var y(default,null) : Float; + + /** + The width of the `DOMRect`. + **/ var width(default,null) : Float; + + /** + The height of the `DOMRect`. + **/ var height(default,null) : Float; + + /** + Returns the top coordinate value of the `DOMRect` (usually the same as `y`.) + **/ var top(default,null) : Float; + + /** + Returns the right coordinate value of the `DOMRect` (usually the same as `x + width`). + **/ var right(default,null) : Float; + + /** + Returns the bottom coordinate value of the `DOMRect` (usually the same as y + height). + **/ var bottom(default,null) : Float; + + /** + Returns the left coordinate value of the `DOMRect` (usually the same as `x`). + **/ var left(default,null) : Float; } \ No newline at end of file diff --git a/std/js/html/DOMRequest.hx b/std/js/html/DOMRequest.hx index fc58ce1e..21b49822 100644 --- a/std/js/html/DOMRequest.hx +++ b/std/js/html/DOMRequest.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMRequest.webidl line 19:0. Do not edit! +// This file is generated from mozilla\DOMRequest.webidl. Do not edit! package js.html; @@ -33,5 +33,6 @@ extern class DOMRequest extends EventTarget var onsuccess : haxe.Constraints.Function; var onerror : haxe.Constraints.Function; - function then( ?fulfillCallback : haxe.Constraints.Function, ?rejectCallback : haxe.Constraints.Function ) : Promise; + /** @throws DOMError */ + function then( ?fulfillCallback : haxe.Constraints.Function, ?rejectCallback : haxe.Constraints.Function ) : Dynamic; } \ No newline at end of file diff --git a/std/js/html/DOMRequestReadyState.hx b/std/js/html/DOMRequestReadyState.hx index fabe2429..6935f230 100644 --- a/std/js/html/DOMRequestReadyState.hx +++ b/std/js/html/DOMRequestReadyState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMRequest.webidl line 6:0. Do not edit! +// This file is generated from mozilla\DOMRequest.webidl. Do not edit! package js.html; diff --git a/std/js/html/DOMSelection.hx b/std/js/html/DOMSelection.hx deleted file mode 100644 index a42b4c02..00000000 --- a/std/js/html/DOMSelection.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html; - -/** @deprecated Use Selection instead. */ -@:deprecated("DOMSelection is deprecated, use Selection instead") -typedef DOMSelection = Selection; diff --git a/std/js/html/DOMStringList.hx b/std/js/html/DOMStringList.hx index 6ee5d141..2b8c6bd9 100644 --- a/std/js/html/DOMStringList.hx +++ b/std/js/html/DOMStringList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMStringList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\DOMStringList.webidl. Do not edit! package js.html; +/** + A type returned by some APIs which contains a list of DOMString (strings). + + Documentation [DOMStringList](https://developer.mozilla.org/en-US/docs/Web/API/DOMStringList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMStringList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMStringList") extern class DOMStringList implements ArrayAccess { + + /** + Returns the length of the list, + **/ var length(default,null) : Int; + + /** + Returns a `DOMString`. + **/ function item( index : Int ) : String; + + /** + Returns `Boolean` indicating if the given string is in the list + **/ function contains( string : String ) : Bool; } \ No newline at end of file diff --git a/std/js/html/DOMStringMap.hx b/std/js/html/DOMStringMap.hx index 55cfcc4a..b4fed2b3 100644 --- a/std/js/html/DOMStringMap.hx +++ b/std/js/html/DOMStringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMStringMap.webidl line 15:0. Do not edit! +// This file is generated from mozilla\DOMStringMap.webidl. Do not edit! package js.html; +/** + Used by the `dataset` HTML attribute to represent data for custom attributes added to elements. + + Documentation [DOMStringMap](https://developer.mozilla.org/en-US/docs/Web/API/DOMStringMap) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMStringMap$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMStringMap") extern class DOMStringMap implements Dynamic { diff --git a/std/js/html/DOMTokenList.hx b/std/js/html/DOMTokenList.hx index a6d4808f..438d4fff 100644 --- a/std/js/html/DOMTokenList.hx +++ b/std/js/html/DOMTokenList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,22 +20,54 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMTokenList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\DOMTokenList.webidl. Do not edit! package js.html; +/** + The `DOMTokenList` interface represents a set of space-separated tokens. Such a set is returned by `Element.classList`, `HTMLLinkElement.relList`, `HTMLAnchorElement.relList` or `HTMLAreaElement.relList`. It is indexed beginning with `0` as with JavaScript `Array` objects. `DOMTokenList` is always case-sensitive. + + Documentation [DOMTokenList](https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DOMTokenList") extern class DOMTokenList implements ArrayAccess { + + /** + Is an `integer` representing the number of objects stored in the object. + **/ var length(default,null) : Int; + var value : String; + + /** + Returns an item in the list by its index (or undefined if the number is greater than or equal to the length of the list, prior to `7.0` returned null) + **/ function item( index : Int ) : String; /** @throws DOMError */ + + /** + Returns `true` if the underlying string contains token, otherwise `false` + **/ function contains( token : String ) : Bool; /** @throws DOMError */ + + /** + Adds token to the underlying string + **/ function add( tokens : haxe.extern.Rest ) : Void; /** @throws DOMError */ + + /** + Removes token from the underlying string + **/ function remove( tokens : haxe.extern.Rest ) : Void; /** @throws DOMError */ + + /** + Removes token from string and returns false. If token doesn't exist it's added and the function returns true + **/ function toggle( token : String, ?force : Bool ) : Bool; } \ No newline at end of file diff --git a/std/js/html/DOMTransaction.hx b/std/js/html/DOMTransaction.hx index ff18e747..834ffeca 100644 --- a/std/js/html/DOMTransaction.hx +++ b/std/js/html/DOMTransaction.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMTransaction.webidl line 15:9. Do not edit! +// This file is generated from mozilla\DOMTransaction.webidl. Do not edit! package js.html; diff --git a/std/js/html/DOMTransactionEvent.hx b/std/js/html/DOMTransactionEvent.hx index cfd11ff8..73417bf4 100644 --- a/std/js/html/DOMTransactionEvent.hx +++ b/std/js/html/DOMTransactionEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMTransactionEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\DOMTransactionEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/DOMTransactionEventInit.hx b/std/js/html/DOMTransactionEventInit.hx index 15c63813..fa6c9f4f 100644 --- a/std/js/html/DOMTransactionEventInit.hx +++ b/std/js/html/DOMTransactionEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMTransactionEvent.webidl line 13:0. Do not edit! +// This file is generated from mozilla\DOMTransactionEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/DataElement.hx b/std/js/html/DataElement.hx index 59473ee2..2ee7b221 100644 --- a/std/js/html/DataElement.hx +++ b/std/js/html/DataElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLDataElement.webidl line 10:0. Do not edit! +// This file is generated from mozilla\HTMLDataElement.webidl. Do not edit! package js.html; +/** + The `HTMLDataElement` interface provides special properties (beyond the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating `data` elements. + + Documentation [HTMLDataElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDataElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDataElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLDataElement") extern class DataElement extends Element { + + /** + Is a `DOMString` reflecting the `value` HTML attribute, containing a machine-readable form of the element's value. + **/ var value : String; } \ No newline at end of file diff --git a/std/js/html/DataListElement.hx b/std/js/html/DataListElement.hx index d75cc051..fa26bd17 100644 --- a/std/js/html/DataListElement.hx +++ b/std/js/html/DataListElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLDataListElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLDataListElement.webidl. Do not edit! package js.html; +/** + The `HTMLDataListElement` interface provides special properties (beyond the `HTMLElement` object interface it also has available to it by inheritance) to manipulate `datalist` elements and their content. + + Documentation [HTMLDataListElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDataListElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDataListElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLDataListElement") extern class DataListElement extends Element { + + /** + Is a `HTMLCollection` representing a collection of the contained option elements. + **/ var options(default,null) : HTMLCollection; } \ No newline at end of file diff --git a/std/js/html/DataTransfer.hx b/std/js/html/DataTransfer.hx index addf094c..22ae8411 100644 --- a/std/js/html/DataTransfer.hx +++ b/std/js/html/DataTransfer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,28 +20,71 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DataTransfer.webidl line 11:0. Do not edit! +// This file is generated from mozilla\DataTransfer.webidl. Do not edit! package js.html; +/** + The `DataTransfer` object is used to hold the data that is being dragged during a drag and drop operation. It may hold one or more data items, each of one or more data types. For more information about drag and drop, see HTML Drag and Drop API. + + Documentation [DataTransfer](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DataTransfer") extern class DataTransfer { + + /** + Gets the type of drag-and-drop operation currently selected or sets the operation to a new type. The value must be `none`, `copy`, `link` or `move`. + **/ var dropEffect : String; + + /** + Provides all of the types of operations that are possible. Must be one of `none`, `copy`, `copyLink`, `copyMove`, `link`, `linkMove`, `move`, `all` or `uninitialized`. + **/ var effectAllowed : String; + + /** + An array of `DOMString` giving the formats that were set in the `dragstart` event. + **/ var types(default,null) : DOMStringList; + + /** + Contains a list of all the local files available on the data transfer. If the drag operation doesn't involve dragging files, this property is an empty list. + **/ var files(default,null) : FileList; /** @throws DOMError */ function new( eventType : String, isExternal : Bool ) : Void; /** @throws DOMError */ + + /** + Set the image to be used for dragging if a custom one is desired. + **/ function setDragImage( image : Element, x : Int, y : Int ) : Void; /** @throws DOMError */ + + /** + Retrieves the data for a given type, or an empty string if data for that type does not exist or the data transfer contains no data. + **/ function getData( format : String ) : String; /** @throws DOMError */ + + /** + Set the data for a given type. If data for the type does not exist, it is added at the end, such that the last item in the types list will be the new format. If data for the type already exists, the existing data is replaced in the same position. + **/ function setData( format : String, data : String ) : Void; /** @throws DOMError */ + + /** + Remove the data associated with a given type. The type argument is optional. If the type is empty or not specified, the data associated with all types is removed. If data for the specified type does not exist, or the data transfer contains no data, this method will have no effect. + **/ function clearData( ?format : String ) : Void; /** @throws DOMError */ + + /** + Sets the drag source to the given element. + **/ function addElement( element : Element ) : Void; } \ No newline at end of file diff --git a/std/js/html/DataView.hx b/std/js/html/DataView.hx index f4ff2936..5e7643db 100644 --- a/std/js/html/DataView.hx +++ b/std/js/html/DataView.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,23 +20,26 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl line 217:0. Do not edit! +// This file is generated from typedarray.webidl. Do not edit! package js.html; +// Explicitly include the compatibility class +import js.html.compat.DataView; + @:native("DataView") extern class DataView extends ArrayBufferView { /** @throws DOMError */ function new( buffer : ArrayBuffer, ?byteOffset : Int, ?byteLength : Int ) : Void; - function getInt8( byteOffset : Int ) : Int; - function getUint8( byteOffset : Int ) : Int; - function getInt16( byteOffset : Int, ?littleEndian : Bool ) : Int; - function getUint16( byteOffset : Int, ?littleEndian : Bool ) : Int; - function getInt32( byteOffset : Int, ?littleEndian : Bool ) : Int; - function getUint32( byteOffset : Int, ?littleEndian : Bool ) : Int; - function getFloat32( byteOffset : Int, ?littleEndian : Bool ) : Float; - function getFloat64( byteOffset : Int, ?littleEndian : Bool ) : Float; + @:pure function getInt8( byteOffset : Int ) : Int; + @:pure function getUint8( byteOffset : Int ) : Int; + @:pure function getInt16( byteOffset : Int, ?littleEndian : Bool ) : Int; + @:pure function getUint16( byteOffset : Int, ?littleEndian : Bool ) : Int; + @:pure function getInt32( byteOffset : Int, ?littleEndian : Bool ) : Int; + @:pure function getUint32( byteOffset : Int, ?littleEndian : Bool ) : Int; + @:pure function getFloat32( byteOffset : Int, ?littleEndian : Bool ) : Float; + @:pure function getFloat64( byteOffset : Int, ?littleEndian : Bool ) : Float; function setInt8( byteOffset : Int, value : Int ) : Void; function setUint8( byteOffset : Int, value : Int ) : Void; function setInt16( byteOffset : Int, value : Int, ?littleEndian : Bool ) : Void; diff --git a/std/js/html/DedicatedWorkerGlobalScope.hx b/std/js/html/DedicatedWorkerGlobalScope.hx index 78494ff4..944cb1d5 100644 --- a/std/js/html/DedicatedWorkerGlobalScope.hx +++ b/std/js/html/DedicatedWorkerGlobalScope.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DedicatedWorkerGlobalScope.webidl line 17:0. Do not edit! +// This file is generated from mozilla\DedicatedWorkerGlobalScope.webidl. Do not edit! package js.html; +/** + The `DedicatedWorkerGlobalScope` object (the `Worker` global scope) is accessible through the `self` keyword. Some additional global functions, namespaces objects, and constructors, not typically associated with the worker global scope, but available on it, are listed in the JavaScript Reference. See also: Functions available to workers. + + Documentation [DedicatedWorkerGlobalScope](https://developer.mozilla.org/en-US/docs/Web/API/DedicatedWorkerGlobalScope) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DedicatedWorkerGlobalScope$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DedicatedWorkerGlobalScope") extern class DedicatedWorkerGlobalScope extends WorkerGlobalScope { + + /** + Is an `EventHandler` representing the code to be called when the `message` event is raised. These events are of type `MessageEvent` and will be called when the worker receives a message from the document that started it (i.e. from the `Worker.postMessage` method.) + **/ var onmessage : haxe.Constraints.Function; /** @throws DOMError */ diff --git a/std/js/html/DesktopNotification.hx b/std/js/html/DesktopNotification.hx index 1acdfc3e..c6ba12e6 100644 --- a/std/js/html/DesktopNotification.hx +++ b/std/js/html/DesktopNotification.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DesktopNotification.webidl line 18:0. Do not edit! +// This file is generated from mozilla\DesktopNotification.webidl. Do not edit! package js.html; diff --git a/std/js/html/DesktopNotificationCenter.hx b/std/js/html/DesktopNotificationCenter.hx index 561b5792..08e09851 100644 --- a/std/js/html/DesktopNotificationCenter.hx +++ b/std/js/html/DesktopNotificationCenter.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DesktopNotification.webidl line 10:0. Do not edit! +// This file is generated from mozilla\DesktopNotification.webidl. Do not edit! package js.html; diff --git a/std/js/html/DeviceAcceleration.hx b/std/js/html/DeviceAcceleration.hx index b98c70a8..ae83f1ac 100644 --- a/std/js/html/DeviceAcceleration.hx +++ b/std/js/html/DeviceAcceleration.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DeviceMotionEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\DeviceMotionEvent.webidl. Do not edit! package js.html; +/** + A `DeviceAcceleration` object provides information about the amount of acceleration the device is experiencing along all three axes. + + Documentation [DeviceAcceleration](https://developer.mozilla.org/en-US/docs/Web/API/DeviceAcceleration) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DeviceAcceleration$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DeviceAcceleration") extern class DeviceAcceleration { + + /** + The amount of acceleration along the X axis. Read only. + **/ var x(default,null) : Float; + + /** + The amount of acceleration along the Y axis. Read only. + **/ var y(default,null) : Float; + + /** + The amount of acceleration along the Z axis. Read only. + **/ var z(default,null) : Float; } \ No newline at end of file diff --git a/std/js/html/DeviceAccelerationInit.hx b/std/js/html/DeviceAccelerationInit.hx index 13737325..3f904339 100644 --- a/std/js/html/DeviceAccelerationInit.hx +++ b/std/js/html/DeviceAccelerationInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DeviceMotionEvent.webidl line 29:0. Do not edit! +// This file is generated from mozilla\DeviceMotionEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/DeviceMotionEvent.hx b/std/js/html/DeviceMotionEvent.hx index 1074f70f..6be1a83e 100644 --- a/std/js/html/DeviceMotionEvent.hx +++ b/std/js/html/DeviceMotionEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,20 +20,42 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DeviceMotionEvent.webidl line 22:0. Do not edit! +// This file is generated from mozilla\DeviceMotionEvent.webidl. Do not edit! package js.html; +/** + The `DeviceMotionEvent` provides web developers with information about the speed of changes for the device's position and orientation. + + Documentation [DeviceMotionEvent](https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DeviceMotionEvent") extern class DeviceMotionEvent extends Event { + + /** + An object giving the acceleration of the device on the three axis X, Y and Z. Acceleration is expressed in m/s2. + **/ var acceleration(default,null) : DeviceAcceleration; + + /** + An object giving the acceleration of the device on the three axis X, Y and Z with the effect of gravity. Acceleration is expressed in m/s2. + **/ var accelerationIncludingGravity(default,null) : DeviceAcceleration; + + /** + An object giving the rate of change of the device's orientation on the three orientation axis alpha, beta and gamma. Rotation rate is express in degrees per seconds. + **/ var rotationRate(default,null) : DeviceRotationRate; + + /** + A number representing the interval of time, in milliseconds, at which data is obtained from the device. + **/ var interval(default,null) : Float; /** @throws DOMError */ function new( type : String, ?eventInitDict : DeviceMotionEventInit ) : Void; - /** @throws DOMError */ function initDeviceMotionEvent( type : String, canBubble : Bool, cancelable : Bool, acceleration : DeviceAccelerationInit, accelerationIncludingGravity : DeviceAccelerationInit, rotationRate : DeviceRotationRateInit, interval : Float ) : Void; } \ No newline at end of file diff --git a/std/js/html/DeviceMotionEventInit.hx b/std/js/html/DeviceMotionEventInit.hx index 2e3dae23..ba1c89a0 100644 --- a/std/js/html/DeviceMotionEventInit.hx +++ b/std/js/html/DeviceMotionEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DeviceMotionEvent.webidl line 41:0. Do not edit! +// This file is generated from mozilla\DeviceMotionEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/DeviceOrientationEvent.hx b/std/js/html/DeviceOrientationEvent.hx index 3b3d6ea7..31c6735d 100644 --- a/std/js/html/DeviceOrientationEvent.hx +++ b/std/js/html/DeviceOrientationEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,20 +20,42 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DeviceOrientationEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\DeviceOrientationEvent.webidl. Do not edit! package js.html; +/** + The `DeviceOrientationEvent` provides web developers with information from the physical orientation of the device running the web page. + + Documentation [DeviceOrientationEvent](https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DeviceOrientationEvent") extern class DeviceOrientationEvent extends Event { + + /** + A number representing the motion of the device around the z axis, express in degrees with values ranging from 0 to 360 + **/ var alpha(default,null) : Float; + + /** + A number representing the motion of the device around the x axis, express in degrees with values ranging from -180 to 180. This represents a front to back motion of the device. + **/ var beta(default,null) : Float; + + /** + A number representing the motion of the device around the y axis, express in degrees with values ranging from -90 to 90. This represents a left to right motion of the device. + **/ var gamma(default,null) : Float; + + /** + A boolean that indicates whether or not the device is providing orientation data absolutely. + **/ var absolute(default,null) : Bool; /** @throws DOMError */ function new( type : String, ?eventInitDict : DeviceOrientationEventInit ) : Void; - /** @throws DOMError */ function initDeviceOrientationEvent( type : String, canBubble : Bool, cancelable : Bool, alpha : Float, beta : Float, gamma : Float, absolute : Bool ) : Void; } \ No newline at end of file diff --git a/std/js/html/DeviceOrientationEventInit.hx b/std/js/html/DeviceOrientationEventInit.hx index 0bbec8a4..a47d5949 100644 --- a/std/js/html/DeviceOrientationEventInit.hx +++ b/std/js/html/DeviceOrientationEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DeviceOrientationEvent.webidl line 26:0. Do not edit! +// This file is generated from mozilla\DeviceOrientationEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/DeviceRotationRate.hx b/std/js/html/DeviceRotationRate.hx index 5fd59468..17d6d183 100644 --- a/std/js/html/DeviceRotationRate.hx +++ b/std/js/html/DeviceRotationRate.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DeviceMotionEvent.webidl line 15:0. Do not edit! +// This file is generated from mozilla\DeviceMotionEvent.webidl. Do not edit! package js.html; +/** + A `DeviceRotationRate` object provides information about the rate at which the device is rotating around all three axes. + + Documentation [DeviceRotationRate](https://developer.mozilla.org/en-US/docs/Web/API/DeviceRotationRate) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DeviceRotationRate$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DeviceRotationRate") extern class DeviceRotationRate { diff --git a/std/js/html/DeviceRotationRateInit.hx b/std/js/html/DeviceRotationRateInit.hx index 722437ee..180cb102 100644 --- a/std/js/html/DeviceRotationRateInit.hx +++ b/std/js/html/DeviceRotationRateInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DeviceMotionEvent.webidl line 35:0. Do not edit! +// This file is generated from mozilla\DeviceMotionEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/DirectionSetting.hx b/std/js/html/DirectionSetting.hx index 0f8a7912..b9027c70 100644 --- a/std/js/html/DirectionSetting.hx +++ b/std/js/html/DirectionSetting.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/VTTCue.webidl line 20:0. Do not edit! +// This file is generated from mozilla\VTTCue.webidl. Do not edit! package js.html; diff --git a/std/js/html/Directory.hx b/std/js/html/Directory.hx index e7273ec7..149e7cb1 100644 --- a/std/js/html/Directory.hx +++ b/std/js/html/Directory.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Directory.webidl line 16:0. Do not edit! +// This file is generated from mozilla\Directory.webidl. Do not edit! package js.html; @@ -28,10 +28,7 @@ package js.html; extern class Directory { var name(default,null) : String; + var path(default,null) : String; - function createFile( path : String, ?options : CreateFileOptions ) : Promise; - function createDirectory( path : String ) : Promise; - function get( path : String ) : Promise>; - function remove( path : haxe.extern.EitherType> ) : Promise; - function removeDeep( path : haxe.extern.EitherType> ) : Promise; + function getFilesAndDirectories() : Promise>>; } \ No newline at end of file diff --git a/std/js/html/DirectoryElement.hx b/std/js/html/DirectoryElement.hx index 9b3c2f1b..0e54e1dc 100644 --- a/std/js/html/DirectoryElement.hx +++ b/std/js/html/DirectoryElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLDirectoryElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLDirectoryElement.webidl. Do not edit! package js.html; diff --git a/std/js/html/DivElement.hx b/std/js/html/DivElement.hx index f83befc1..85598fa3 100644 --- a/std/js/html/DivElement.hx +++ b/std/js/html/DivElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLDivElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLDivElement.webidl. Do not edit! package js.html; +/** + The `HTMLDivElement` interface provides special properties (beyond the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating div elements. + + Documentation [HTMLDivElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDivElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDivElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLDivElement") extern class DivElement extends Element { + + /** + Is a `DOMString` representing an enumerated property indicating alignment of the element's contents with respect to the surrounding context. The possible values are `"left"`, `"right"`, `"justify"`, and `"center"`. + **/ var align : String; } \ No newline at end of file diff --git a/std/js/html/Document.hx b/std/js/html/Document.hx index 2d8af382..c1362995 100644 --- a/std/js/html/Document.hx +++ b/std/js/html/Document.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,51 +20,195 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Document.webidl line 18:0. Do not edit! +// This file is generated from mozilla\Document.webidl. Do not edit! package js.html; +/** + The `Document` interface represents any web page loaded in the browser and serves as an entry point into the web page's content, which is the DOM tree. The DOM tree includes elements such as `body` and `table`, among many others. It provides functionality global to the document, like how to obtain the page's URL and create new elements in the document. + + Documentation [Document](https://developer.mozilla.org/en-US/docs/Web/API/Document) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Document$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Document") extern class Document extends Node { + + /** + Returns the DOM implementation associated with the current document. + **/ var implementation(default,null) : DOMImplementation; + + /** + Returns the document location as a string. + **/ var URL(default,null) : String; + + /** + Returns the document location as a string. + **/ var documentURI(default,null) : String; + + /** + Indicates whether the document is rendered in quirks or strict mode. + **/ var compatMode(default,null) : String; + + /** + Returns the character set being used by the document. + **/ var characterSet(default,null) : String; + + /** + Alias of `Document.characterSet`. Use this property instead. + **/ + var charset(default,null) : String; + + /** + Alias of `Document.characterSet`. Use this property instead. + **/ + var inputEncoding(default,null) : String; + + /** + Returns the Content-Type from the MIME Header of the current document. + **/ var contentType(default,null) : String; + + /** + Returns the Document Type Definition (DTD) of the current document. + **/ var doctype(default,null) : DocumentType; + + /** + Returns the `Element` that is a direct child of the document. For HTML documents, this is normally the `html` element. + **/ var documentElement(default,null) : Element; - var inputEncoding(default,null) : String; - var fullscreenEnabled(default,null) : Bool; - var fullscreenElement(default,null) : Element; - var onfullscreenchange : haxe.Constraints.Function; - var onfullscreenerror : haxe.Constraints.Function; + + /** + Returns the URI of the current document. + **/ var location(default,null) : Location; + + /** + Returns the URI of the page that linked to this page. + **/ var referrer(default,null) : String; + + /** + Returns the date on which the document was last modified. + **/ var lastModified(default,null) : String; + + /** + Returns loading status of the document. + **/ var readyState(default,null) : String; + + /** + Sets or gets title of the current document. + **/ var title : String; + + /** + Gets/sets directionality (rtl/ltr) of the document. + **/ var dir : String; + + /** + Returns a reference to the window object. + **/ var defaultView(default,null) : Window; + + /** + Returns the currently focused element. + **/ var activeElement(default,null) : Element; + + /** + Represents the event handling code for the `readystatechange` event. + **/ var onreadystatechange : haxe.Constraints.Function; + + /** + Represents the event handling code for the `wheel` event. + **/ var onwheel : haxe.Constraints.Function; + + /** + Represents the event handling code for the `copy` event. + **/ var oncopy : haxe.Constraints.Function; + + /** + Represents the event handling code for the `cut` event. + **/ var oncut : haxe.Constraints.Function; + + /** + Represents the event handling code for the `paste` event. + **/ var onpaste : haxe.Constraints.Function; + + /** + Represents the event handling code for the `beforescriptexecute` event. + **/ var onbeforescriptexecute : haxe.Constraints.Function; + + /** + Represents the event handling code for the `afterscriptexecute` event. + **/ var onafterscriptexecute : haxe.Constraints.Function; var currentScript(default,null) : Element; + var fullscreenEnabled(default,null) : Bool; + var fullscreenElement(default,null) : Element; + + /** + Returns the element set as the target for mouse events while the pointer is locked. `null` if lock is pending, pointer is unlocked, or if the target is in another document. + **/ var pointerLockElement(default,null) : Element; + + /** + … + **/ var hidden(default,null) : Bool; + + /** + + Returns a `string` denoting the visibility state of the document. Possible values are `visible`,  `hidden`,  `prerender`, and `unloaded`. + + **/ var visibilityState(default,null) : VisibilityState; + + /** + Returns a list of the style sheet objects on the current document. + **/ var styleSheets(default,null) : StyleSheetList; + + /** + Returns which style sheet set is currently in use. + **/ var selectedStyleSheetSet : String; + + /** + Returns the name of the style sheet set that was last enabled. Has the value `null` until the style sheet is changed by setting the value of `document.selectedStyleSheetSet`. + **/ var lastStyleSheetSet(default,null) : String; + + /** + Returns the preferred style sheet set as specified by the page author. + **/ var preferredStyleSheetSet(default,null) : String; + + /** + Returns a list of the style sheet sets available on the document. + **/ var styleSheetSets(default,null) : DOMStringList; - var timeline(default,null) : AnimationTimeline; + + /** + … + **/ + var timeline(default,null) : DocumentTimeline; var fonts(default,null) : FontFaceSet; var onabort : haxe.Constraints.Function; var onblur : haxe.Constraints.Function; @@ -107,6 +251,7 @@ extern class Document extends Node var onprogress : haxe.Constraints.Function; var onratechange : haxe.Constraints.Function; var onreset : haxe.Constraints.Function; + var onresize : haxe.Constraints.Function; var onscroll : haxe.Constraints.Function; var onseeked : haxe.Constraints.Function; var onseeking : haxe.Constraints.Function; @@ -128,7 +273,25 @@ extern class Document extends Node var onpointerleave : haxe.Constraints.Function; var ongotpointercapture : haxe.Constraints.Function; var onlostpointercapture : haxe.Constraints.Function; + + /** + Is an `EventHandler` representing the code to be called when the `fullscreenchange` event is raised. + **/ + var onfullscreenchange : haxe.Constraints.Function; + + /** + Is an `EventHandler` representing the code to be called when the `fullscreenerror` event is raised. + **/ + var onfullscreenerror : haxe.Constraints.Function; + + /** + Represents the event handling code for the `pointerlockchange` event. + **/ var onpointerlockchange : haxe.Constraints.Function; + + /** + Represetnts the event handling code for the `pointerlockerror` event. + **/ var onpointerlockerror : haxe.Constraints.Function; var onerror : haxe.Constraints.Function; var children(default,null) : HTMLCollection; @@ -142,57 +305,171 @@ extern class Document extends Node /** @throws DOMError */ function new() : Void; + + /** + Returns a list of elements with the given tag name. + **/ function getElementsByTagName( localName : String ) : HTMLCollection; /** @throws DOMError */ + + /** + Returns a list of elements with the given tag name and namespace. + **/ function getElementsByTagNameNS( namespace_ : String, localName : String ) : HTMLCollection; + + /** + Returns a list of elements with the given class name. + **/ function getElementsByClassName( classNames : String ) : HTMLCollection; function getElementById( elementId : String ) : Element; /** @throws DOMError */ @:overload( function( localName : String ) : Element {} ) + + /** + Creates a new element with the given tag name. + **/ function createElement( localName : String, typeExtension : String ) : Element; /** @throws DOMError */ @:overload( function( namespace_ : String, qualifiedName : String ) : Element {} ) + + /** + Creates a new element with the given tag name and namespace URI. + **/ function createElementNS( namespace_ : String, qualifiedName : String, typeExtension : String ) : Element; + + /** + Creates a new document fragment. + **/ function createDocumentFragment() : DocumentFragment; + + /** + Creates a text node. + **/ function createTextNode( data : String ) : Text; + + /** + Creates a new comment node and returns it. + **/ function createComment( data : String ) : Comment; /** @throws DOMError */ + + /** + Creates a new `ProcessingInstruction` object. + **/ function createProcessingInstruction( target : String, data : String ) : ProcessingInstruction; /** @throws DOMError */ + + /** + Returns a clone of a node from an external document. + **/ function importNode( node : Node, ?deep : Bool = false ) : Node; /** @throws DOMError */ + + /** + Adopt node from an external document. + **/ function adoptNode( node : Node ) : Node; /** @throws DOMError */ + + /** + Creates an event object. + **/ function createEvent( interface_ : String ) : Event; /** @throws DOMError */ + + /** + Creates a `Range` object. + **/ function createRange() : Range; /** @throws DOMError */ + + /** + Creates a `NodeIterator` object. + **/ function createNodeIterator( root : Node, ?whatToShow : Int = cast 4294967295, ?filter : NodeFilter ) : NodeIterator; /** @throws DOMError */ + + /** + Creates a `TreeWalker` object. + **/ function createTreeWalker( root : Node, ?whatToShow : Int = cast 4294967295, ?filter : NodeFilter ) : TreeWalker; /** @throws DOMError */ + + /** + Creates a new CDATA node and returns it. + **/ function createCDATASection( data : String ) : CDATASection; /** @throws DOMError */ + + /** + Creates a new `Attr` object and returns it. + **/ function createAttribute( name : String ) : Attr; /** @throws DOMError */ + + /** + Creates a new attribute node in a given namespace and returns it. + **/ function createAttributeNS( namespace_ : String, name : String ) : Attr; - function exitFullscreen() : Void; /** @throws DOMError */ function hasFocus() : Bool; + + /** + Releases the current mouse capture if it's on an element in this document. + **/ function releaseCapture() : Void; + function exitFullscreen() : Void; + + /** + Release the pointer lock. + **/ function exitPointerLock() : Void; /** @throws DOMError */ + + /** + Registers a web component. + **/ function registerElement( name : String, ?options : ElementRegistrationOptions ) : Dynamic; + + /** + Enables the style sheets for the specified style sheet set. + **/ function enableStyleSheetsForSet( name : String ) : Void; + + /** + Returns the topmost element at the specified coordinates.  + **/ function elementFromPoint( x : Float, y : Float ) : Element; + + /** + Returns an array of all elements at the specified coordinates. + **/ + function elementsFromPoint( x : Float, y : Float ) : Array; + + /** + Gets the `CaretPosition` at or near the specified coordinates. + **/ function caretPositionFromPoint( x : Float, y : Float ) : CaretPosition; /** @throws DOMError */ function querySelector( selectors : String ) : Element; /** @throws DOMError */ function querySelectorAll( selectors : String ) : NodeList; + + /** + Returns an array of all `Animation` objects currently in effect whose target elements are descendants of the `document`. + **/ + function getAnimations() : Array; + + /** + Creates a `Touch` object. + **/ function createTouch( ?view : Window, ?target : EventTarget, ?identifier : Int = 0, ?pageX : Int = 0, ?pageY : Int = 0, ?screenX : Int = 0, ?screenY : Int = 0, ?clientX : Int = 0, ?clientY : Int = 0, ?radiusX : Int = 0, ?radiusY : Int = 0, ?rotationAngle : Float = 0.0, ?force : Float = 0.0 ) : Touch; @:overload( function( touch : Touch, touches : haxe.extern.Rest ) : TouchList {} ) @:overload( function() : TouchList {} ) + + /** + Creates a `TouchList` object. + **/ function createTouchList( touches : Array ) : TouchList; /** @throws DOMError */ function convertQuadFromNode( quad : DOMQuad, from : haxe.extern.EitherType>, ?options : ConvertCoordinateOptions ) : DOMQuad; diff --git a/std/js/html/DocumentFragment.hx b/std/js/html/DocumentFragment.hx index 82aad0da..9b070b88 100644 --- a/std/js/html/DocumentFragment.hx +++ b/std/js/html/DocumentFragment.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DocumentFragment.webidl line 15:0. Do not edit! +// This file is generated from mozilla\DocumentFragment.webidl. Do not edit! package js.html; +/** + The `DocumentFragment` interface represents a minimal document object that has no parent. It is used as a light-weight version of `Document` to store well-formed or potentially non-well-formed fragments of XML. + + Documentation [DocumentFragment](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DocumentFragment") extern class DocumentFragment extends Node { @@ -34,9 +41,21 @@ extern class DocumentFragment extends Node /** @throws DOMError */ function new() : Void; + + /** + Returns the first `Element` node within the DocumentFragment`, in document order, that matches the specified ID. + **/ function getElementById( elementId : String ) : Element; /** @throws DOMError */ + + /** + Returns the first `Element` node within the `DocumentFragment`, in document order, that matches the specified selectors. + **/ function querySelector( selectors : String ) : Element; /** @throws DOMError */ + + /** + Returns a `NodeList` of all the `Element` nodes within the `DocumentFragment` that match the specified selectors. + **/ function querySelectorAll( selectors : String ) : NodeList; } \ No newline at end of file diff --git a/std/js/html/DocumentTimeline.hx b/std/js/html/DocumentTimeline.hx new file mode 100644 index 00000000..b804bdaf --- /dev/null +++ b/std/js/html/DocumentTimeline.hx @@ -0,0 +1,37 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\DocumentTimeline.webidl. Do not edit! + +package js.html; + +/** + The `DocumentTimeline` interface of the the Web Animations API represents animation timelines, including the default document timeline (accessed via `Document.timeline`). + + Documentation [DocumentTimeline](https://developer.mozilla.org/en-US/docs/Web/API/DocumentTimeline) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DocumentTimeline$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("DocumentTimeline") +extern class DocumentTimeline extends AnimationTimeline +{ +} \ No newline at end of file diff --git a/std/js/html/DocumentType.hx b/std/js/html/DocumentType.hx index a2757828..7c341350 100644 --- a/std/js/html/DocumentType.hx +++ b/std/js/html/DocumentType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,17 +20,35 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DocumentType.webidl line 13:0. Do not edit! +// This file is generated from mozilla\DocumentType.webidl. Do not edit! package js.html; +/** + The `DocumentType` interface represents a `Node` containing a doctype. + + Documentation [DocumentType](https://developer.mozilla.org/en-US/docs/Web/API/DocumentType) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DocumentType$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DocumentType") extern class DocumentType extends Node { + + /** + ... + **/ var name(default,null) : String; + + /** + ... + **/ var publicId(default,null) : String; + + /** + ... + **/ var systemId(default,null) : String; - var internalSubset(default,null) : String; function remove() : Void; } \ No newline at end of file diff --git a/std/js/html/DragEvent.hx b/std/js/html/DragEvent.hx index 49e177fd..424bec01 100644 --- a/std/js/html/DragEvent.hx +++ b/std/js/html/DragEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,23 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DragEvent.webidl line 7:0. Do not edit! +// This file is generated from mozilla\DragEvent.webidl. Do not edit! package js.html; +/** + The `DragEvent` interface is a `DOM event` that represents a drag and drop interaction. The user initiates a drag by placing a pointer device (such as a mouse) on the touch surface and then dragging the pointer to a new location (such as another DOM element). Applications are free to interpret a drag and drop interaction in an application-specific way. + + Documentation [DragEvent](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DragEvent") extern class DragEvent extends MouseEvent { var dataTransfer(default,null) : DataTransfer; /** @throws DOMError */ + function new( type : String, ?eventInitDict : DragEventInit ) : Void; function initDragEvent( type : String, canBubble : Bool, cancelable : Bool, aView : Window, aDetail : Int, aScreenX : Int, aScreenY : Int, aClientX : Int, aClientY : Int, aCtrlKey : Bool, aAltKey : Bool, aShiftKey : Bool, aMetaKey : Bool, aButton : Int, aRelatedTarget : EventTarget, aDataTransfer : DataTransfer ) : Void; } \ No newline at end of file diff --git a/std/js/html/ClientRectList.hx b/std/js/html/DragEventInit.hx similarity index 84% rename from std/js/html/ClientRectList.hx rename to std/js/html/DragEventInit.hx index 072cdd57..4dce79cc 100644 --- a/std/js/html/ClientRectList.hx +++ b/std/js/html/DragEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,8 +20,12 @@ * DEALINGS IN THE SOFTWARE. */ +// This file is generated from mozilla\DragEvent.webidl. Do not edit! + package js.html; -/** @deprecated Use DOMRectList instead. */ -@:deprecated("ClientRectList is deprecated, use DOMRectList instead") -typedef ClientRectList = DOMRectList; +typedef DragEventInit = +{ + > MouseEventInit, + @:optional var dataTransfer : DataTransfer; +} \ No newline at end of file diff --git a/std/js/html/DummyInterface.hx b/std/js/html/DummyInterface.hx index 90479047..b8bfebcc 100644 --- a/std/js/html/DummyInterface.hx +++ b/std/js/html/DummyInterface.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DummyBinding.webidl line 10:0. Do not edit! +// This file is generated from mozilla\DummyBinding.webidl. Do not edit! package js.html; @@ -28,4 +28,5 @@ package js.html; extern class DummyInterface { function lifecycleCallbacks( ?arg : LifecycleCallbacks ) : Void; + function promiseJobCallback( arg : Void -> Void ) : Void; } \ No newline at end of file diff --git a/std/js/html/DummyInterfaceWorkers.hx b/std/js/html/DummyInterfaceWorkers.hx index aef05206..a1a29861 100644 --- a/std/js/html/DummyInterfaceWorkers.hx +++ b/std/js/html/DummyInterfaceWorkers.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DummyBinding.webidl line 14:0. Do not edit! +// This file is generated from mozilla\DummyBinding.webidl. Do not edit! package js.html; diff --git a/std/js/html/Element.hx b/std/js/html/Element.hx index 910229d8..ac44555c 100644 --- a/std/js/html/Element.hx +++ b/std/js/html/Element.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLElement.webidl. Do not edit! package js.html; +/** + The `HTMLElement` interface represents any HTML element. Some elements directly implement this interface, others implement it via an interface that inherits it. + + Documentation [HTMLElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLElement") extern class Element extends DOMElement { diff --git a/std/js/html/ElementRegistrationOptions.hx b/std/js/html/ElementRegistrationOptions.hx index a415bfa1..e522066f 100644 --- a/std/js/html/ElementRegistrationOptions.hx +++ b/std/js/html/ElementRegistrationOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebComponents.webidl line 25:0. Do not edit! +// This file is generated from mozilla\WebComponents.webidl. Do not edit! package js.html; diff --git a/std/js/html/EmbedElement.hx b/std/js/html/EmbedElement.hx index 74c871bb..e05f2286 100644 --- a/std/js/html/EmbedElement.hx +++ b/std/js/html/EmbedElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,18 +20,49 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLEmbedElement.webidl line 17:0. Do not edit! +// This file is generated from mozilla\HTMLEmbedElement.webidl. Do not edit! package js.html; +/** + The `HTMLEmbedElement` interface, which provides special properties (beyond the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating `embed` elements. + + Documentation [HTMLEmbedElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLEmbedElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLEmbedElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLEmbedElement") extern class EmbedElement extends Element { + + /** + Is a `DOMString` that reflects the `src` HTML attribute, containing the address of the resource. + **/ var src : String; + + /** + Is a `DOMString` that reflects the `type` HTML attribute, containing the type of the resource. + **/ var type : String; + + /** + Is a `DOMString` that reflects the `width` HTML attribute, containing the displayed width of the resource. + **/ var width : String; + + /** + Is a `DOMString` representing an enumerated property indicating alignment of the element's contents with respect to the surrounding context. The possible values are `"left"`, `"right"`, `"center"`, and `"justify"`. + **/ var height : String; + + /** + Is a `DOMString` reflecting the `height` HTML attribute, containing the displayed height of the resource. + **/ var align : String; + + /** + Is a `DOMString` representing the name of the embedded object. + **/ var name : String; function getSVGDocument() : HTMLDocument; diff --git a/std/js/html/ErrorEvent.hx b/std/js/html/ErrorEvent.hx index a4569156..1221553b 100644 --- a/std/js/html/ErrorEvent.hx +++ b/std/js/html/ErrorEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,17 +20,44 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ErrorEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\ErrorEvent.webidl. Do not edit! package js.html; +/** + The `ErrorEvent` interface represents events providing information related to errors in scripts or in files. + + Documentation [ErrorEvent](https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("ErrorEvent") extern class ErrorEvent extends Event { + + /** + Is a `DOMString` containing a human-readable error message describing the problem. + **/ var message(default,null) : String; + + /** + Is a `DOMString` containing the name of the script file in which the error occurred. + **/ var filename(default,null) : String; + + /** + Is an `integer` containing the line number of the script file on which the error occurred. + **/ var lineno(default,null) : Int; + + /** + Is an `integer` containing the column number of the script file on which the error occurred. + **/ var colno(default,null) : Int; + + /** + Is a JavaScript `Object` that is concerned by the event. + **/ var error(default,null) : Dynamic; /** @throws DOMError */ diff --git a/std/js/html/ErrorEventInit.hx b/std/js/html/ErrorEventInit.hx index 4dc08a6a..7c371192 100644 --- a/std/js/html/ErrorEventInit.hx +++ b/std/js/html/ErrorEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ErrorEvent.webidl line 17:0. Do not edit! +// This file is generated from mozilla\ErrorEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/Event.hx b/std/js/html/Event.hx index d12ea088..6c29755d 100644 --- a/std/js/html/Event.hx +++ b/std/js/html/Event.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Event.webidl line 15:0. Do not edit! +// This file is generated from mozilla\Event.webidl. Do not edit! package js.html; +/** + The `Event` interface represents any event which takes place in the DOM; some are user-generated (such as mouse or keyboard events), while others are generated by APIs (such as events that indicate an animation has finished running, a video has been paused, and so forth). There are many types of event, some of which use are other interfaces based on the main `Event` interface. `Event` itself contains the properties and methods which are common to all events. + + Documentation [Event](https://developer.mozilla.org/en-US/docs/Web/API/Event) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Event$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Event") extern class Event { @@ -36,24 +43,87 @@ extern class Event static inline var SHIFT_MASK : Int = 4; static inline var META_MASK : Int = 8; + + /** + The name of the event (case-insensitive). + **/ var type(default,null) : String; + + /** + A reference to the target to which the event was originally dispatched. + **/ var target(default,null) : EventTarget; + + /** + A reference to the currently registered target for the event. This is the object to which the event is currently slated to be sent to; it's possible this has been changed along the way through retargeting. + **/ var currentTarget(default,null) : EventTarget; + + /** + Indicates which phase of the event flow is being processed. + **/ var eventPhase(default,null) : Int; + + /** + A Boolean indicating whether the event bubbles up through the DOM or not. + **/ var bubbles(default,null) : Bool; + + /** + A Boolean indicating whether the event is cancelable. + **/ var cancelable(default,null) : Bool; + + /** + Indicates whether or not `event.preventDefault()` has been called on the event. + **/ var defaultPrevented(default,null) : Bool; + + /** + Indicates whether or not the event was initiated by the browser (after a user click for instance) or by a script (using an event creation method, like event.initEvent) + **/ var isTrusted(default,null) : Bool; + + /** + The time at which the event was created, in milliseconds. By specification, this value is time since epoch, but in reality browsers' definitions vary; in addition, work is underway to change this to be a `DOMHighResTimeStamp` instead. + **/ var timeStamp(default,null) : Float; + + /** + The original target of the event, before any retargetings (Mozilla-specific). + **/ var originalTarget(default,null) : EventTarget; + + /** + The explicit original target of the event (Mozilla-specific). + **/ var explicitOriginalTarget(default,null) : EventTarget; /** @throws DOMError */ function new( type : String, ?eventInitDict : EventInit ) : Void; + + /** + Stops the propagation of events further along in the DOM. + **/ function stopPropagation() : Void; + + /** + For this particular event, no other listener will be called. Neither those attached on the same element, nor those attached on elements which will be traversed later (in capture phase, for instance) + **/ function stopImmediatePropagation() : Void; + + /** + Cancels the event (if it is cancelable). + **/ function preventDefault() : Void; - /** @throws DOMError */ + + /** + Initializes the value of an Event created. If the event has already being dispatched, this method does nothing. + **/ function initEvent( type : String, bubbles : Bool, cancelable : Bool ) : Void; + + /** + Non-standard. Returns the value of `Event.defaultPrevented`. Use `Event.defaultPrevented` instead. + **/ function getPreventDefault() : Bool; } \ No newline at end of file diff --git a/std/js/html/EventInit.hx b/std/js/html/EventInit.hx index 175f7479..48d93255 100644 --- a/std/js/html/EventInit.hx +++ b/std/js/html/EventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Event.webidl line 65:0. Do not edit! +// This file is generated from mozilla\Event.webidl. Do not edit! package js.html; diff --git a/std/js/html/EventListener.hx b/std/js/html/EventListener.hx index a6d30e6f..09ff04ac 100644 --- a/std/js/html/EventListener.hx +++ b/std/js/html/EventListener.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from events.webidl line 14:0. Do not edit! +// This file is generated from events.webidl. Do not edit! package js.html; +/** + This method is called whenever an event occurs of the type for which the `EventListener` interface was registered. + + Documentation [EventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventListener) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EventListener$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("EventListener") extern class EventListener { diff --git a/std/js/html/EventModifierInit.hx b/std/js/html/EventModifierInit.hx new file mode 100644 index 00000000..8f83f274 --- /dev/null +++ b/std/js/html/EventModifierInit.hx @@ -0,0 +1,43 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\UIEvent.webidl. Do not edit! + +package js.html; + +typedef EventModifierInit = +{ + > UIEventInit, + @:optional var altKey : Bool; + @:optional var ctrlKey : Bool; + @:optional var metaKey : Bool; + @:optional var modifierAltGraph : Bool; + @:optional var modifierCapsLock : Bool; + @:optional var modifierFn : Bool; + @:optional var modifierFnLock : Bool; + @:optional var modifierNumLock : Bool; + @:optional var modifierOS : Bool; + @:optional var modifierScrollLock : Bool; + @:optional var modifierSymbol : Bool; + @:optional var modifierSymbolLock : Bool; + @:optional var shiftKey : Bool; +} \ No newline at end of file diff --git a/std/js/html/EventSource.hx b/std/js/html/EventSource.hx index c46ef5bf..a56297b4 100644 --- a/std/js/html/EventSource.hx +++ b/std/js/html/EventSource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/EventSource.webidl line 16:0. Do not edit! +// This file is generated from mozilla\EventSource.webidl. Do not edit! package js.html; +/** + The `EventSource` interface is used to receive server-sent events. It connects to a server over HTTP and receives events in `text/event-stream` format without closing the connection. + + Documentation [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EventSource$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("EventSource") extern class EventSource extends EventTarget { @@ -31,14 +38,38 @@ extern class EventSource extends EventTarget static inline var OPEN : Int = 1; static inline var CLOSED : Int = 2; + + /** + A `DOMString` representing the URL of the source. + **/ var url(default,null) : String; var withCredentials(default,null) : Bool; + + /** + An `unsigned short` representing the state of the connection. Possible values are `CONNECTING` (`0`), `OPEN` (`1`), or `CLOSED` (`2`). + **/ var readyState(default,null) : Int; + + /** + Is an `EventHandler` being called when an `open` event is received, that is when the connection was just opened. + **/ var onopen : haxe.Constraints.Function; + + /** + Is an `EventHandler` being called when a `message` event is received, that is when a message is coming from the source. + **/ var onmessage : haxe.Constraints.Function; + + /** + Is an `EventHandler` being called when an error occurs and the `error` event is dispatched on this object. + **/ var onerror : haxe.Constraints.Function; /** @throws DOMError */ function new( url : String, ?eventSourceInitDict : EventSourceInit ) : Void; + + /** + Closes the connection, if any, and sets the `readyState` attribute to `CLOSED`. If the connection is already closed, the method does nothing. + **/ function close() : Void; } \ No newline at end of file diff --git a/std/js/html/EventSourceInit.hx b/std/js/html/EventSourceInit.hx index 44675c49..f3fd6bc3 100644 --- a/std/js/html/EventSourceInit.hx +++ b/std/js/html/EventSourceInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/EventSource.webidl line 35:0. Do not edit! +// This file is generated from mozilla\EventSource.webidl. Do not edit! package js.html; diff --git a/std/js/html/EventTarget.hx b/std/js/html/EventTarget.hx index db540ea9..f2e6d949 100644 --- a/std/js/html/EventTarget.hx +++ b/std/js/html/EventTarget.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,19 +20,38 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/EventTarget.webidl line 14:0. Do not edit! +// This file is generated from mozilla\EventTarget.webidl. Do not edit! package js.html; +/** + `EventTarget` is an interface implemented by objects that can receive events and may have listeners for them. + + Documentation [EventTarget](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("EventTarget") extern class EventTarget { /** @throws DOMError */ @:overload( function( type : String, listener : EventListener, ?capture : Bool = false, ?wantsUntrusted : Bool ) : Void {} ) + + /** + Register an event handler of a specific event type on the `EventTarget`. + **/ function addEventListener( type : String, listener : haxe.Constraints.Function, ?capture : Bool = false ) : Void; /** @throws DOMError */ @:overload( function( type : String, listener : EventListener, ?capture : Bool = false ) : Void {} ) + + /** + Removes an event listener from the `EventTarget`. + **/ function removeEventListener( type : String, listener : haxe.Constraints.Function, ?capture : Bool = false ) : Void; /** @throws DOMError */ + + /** + Dispatch an event to this `EventTarget`. + **/ function dispatchEvent( event : Event ) : Bool; } \ No newline at end of file diff --git a/std/js/html/Exception.hx b/std/js/html/Exception.hx index 1f1d7d25..aeeb4545 100644 --- a/std/js/html/Exception.hx +++ b/std/js/html/Exception.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMException.webidl line 67:0. Do not edit! +// This file is generated from mozilla\DOMException.webidl. Do not edit! package js.html; @@ -33,7 +33,6 @@ extern class Exception var filename(default,null) : String; var lineNumber(default,null) : Int; var columnNumber(default,null) : Int; - var inner(default,null) : Dynamic/*MISSING nsISupports*/; var data(default,null) : Dynamic/*MISSING nsISupports*/; var stack(default,null) : String; diff --git a/std/js/html/ExtendableEvent.hx b/std/js/html/ExtendableEvent.hx new file mode 100644 index 00000000..a99f2cc2 --- /dev/null +++ b/std/js/html/ExtendableEvent.hx @@ -0,0 +1,41 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\ExtendableEvent.webidl. Do not edit! + +package js.html; + +/** + The `ExtendableEvent` interface extends the lifetime of the `install` and `activate` events dispatched on the global scope as part of the service worker lifecycle. This ensures that any functional events (like `FetchEvent`) are not dispatched until it upgrades database schemas and deletes the outdated cache entries. + + Documentation [ExtendableEvent](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("ExtendableEvent") +extern class ExtendableEvent extends Event +{ + /** @throws DOMError */ + function new( type : String, ?eventInitDict : ExtendableEventInit ) : Void; + /** @throws DOMError */ + function waitUntil( p : Promise ) : Void; +} \ No newline at end of file diff --git a/std/js/html/DOMURL.hx b/std/js/html/ExtendableEventInit.hx similarity index 86% rename from std/js/html/DOMURL.hx rename to std/js/html/ExtendableEventInit.hx index ffad05c1..826fda5b 100644 --- a/std/js/html/DOMURL.hx +++ b/std/js/html/ExtendableEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,8 +20,11 @@ * DEALINGS IN THE SOFTWARE. */ +// This file is generated from mozilla\ExtendableEvent.webidl. Do not edit! + package js.html; -/** @deprecated Use URL instead. */ -@:deprecated("DOMURL is deprecated, use URL instead") -typedef DOMURL = URL; +typedef ExtendableEventInit = +{ + > EventInit, +} \ No newline at end of file diff --git a/std/js/html/ExtendableMessageEvent.hx b/std/js/html/ExtendableMessageEvent.hx new file mode 100644 index 00000000..a269066a --- /dev/null +++ b/std/js/html/ExtendableMessageEvent.hx @@ -0,0 +1,65 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\ExtendableMessageEvent.webidl. Do not edit! + +package js.html; + +/** + The `ExtendableMessageEvent` interface of the `ServiceWorker API` represents the event object of a `message` event fired on a service worker (when a channel message is received on the `ServiceWorkerGlobalScope` from another context) — extends the lifetime of such events. + + Documentation [ExtendableMessageEvent](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableMessageEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableMessageEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("ExtendableMessageEvent") +extern class ExtendableMessageEvent extends ExtendableEvent +{ + + /** + Returns the event's data. It can be any data type. + **/ + var data(default,null) : Dynamic; + + /** + Returns the origin of the `ServiceWorkerClient` that sent the message + **/ + var origin(default,null) : String; + + /** + Represents, in server-sent events, the last event ID of the event source. + **/ + var lastEventId(default,null) : String; + + /** + Returns a reference to the service worker that sent the message. + **/ + var source(default,null) : haxe.extern.EitherType>; + + /** + Returns the array containing the `MessagePort` objects representing the ports of the associated message channel. + **/ + var ports(default,null) : MessagePortList; + + /** @throws DOMError */ + function new( type : String, ?eventInitDict : ExtendableMessageEventInit ) : Void; +} \ No newline at end of file diff --git a/std/js/html/ExtendableMessageEventInit.hx b/std/js/html/ExtendableMessageEventInit.hx new file mode 100644 index 00000000..9bf184e0 --- /dev/null +++ b/std/js/html/ExtendableMessageEventInit.hx @@ -0,0 +1,35 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\ExtendableMessageEvent.webidl. Do not edit! + +package js.html; + +typedef ExtendableMessageEventInit = +{ + > ExtendableEventInit, + @:optional var data : Dynamic; + @:optional var lastEventId : String; + @:optional var origin : String; + @:optional var ports : Array; + @:optional var source : haxe.extern.EitherType>; +} \ No newline at end of file diff --git a/std/js/html/External.hx b/std/js/html/External.hx index be776ca8..b5f8f207 100644 --- a/std/js/html/External.hx +++ b/std/js/html/External.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/External.webidl line 8:0. Do not edit! +// This file is generated from mozilla\External.webidl. Do not edit! package js.html; diff --git a/std/js/html/FetchEvent.hx b/std/js/html/FetchEvent.hx new file mode 100644 index 00000000..6682fc09 --- /dev/null +++ b/std/js/html/FetchEvent.hx @@ -0,0 +1,61 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\FetchEvent.webidl. Do not edit! + +package js.html; + +/** + The parameter passed into the `ServiceWorkerGlobalScope.onfetch` handler, `FetchEvent` represents a fetch action that is dispatched on the `ServiceWorkerGlobalScope` of a `ServiceWorker`. It contains information about the request and resulting response, and provides the `FetchEvent.respondWith()` method, which allows us to provide an arbitrary response back to the controlled page. + + Documentation [FetchEvent](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("FetchEvent") +extern class FetchEvent extends ExtendableEvent +{ + + /** + Returns the `Request` that triggered the event handler. + **/ + var request(default,null) : Request; + + /** + Returns the id of the client that the current service worker is controlling. + **/ + var clientId(default,null) : String; + + /** + Returns a `Boolean` that is `true` if the event was dispatched with the user's intention for the page to reload, and `false` otherwise. Typically, pressing the refresh button in a browser is a reload, while clicking a link and pressing the back button is not. + **/ + var isReload(default,null) : Bool; + + /** @throws DOMError */ + function new( type : String, eventInitDict : FetchEventInit ) : Void; + /** @throws DOMError */ + + /** + Resolves by returning a `Response` or a network error  to Fetch`. + **/ + function respondWith( r : Promise ) : Void; +} \ No newline at end of file diff --git a/std/js/html/MediaKeyNeededEventInit.hx b/std/js/html/FetchEventInit.hx similarity index 81% rename from std/js/html/MediaKeyNeededEventInit.hx rename to std/js/html/FetchEventInit.hx index 98f0c8a2..9592ae47 100644 --- a/std/js/html/MediaKeyNeededEventInit.hx +++ b/std/js/html/FetchEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,14 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaEncryptedEvent.webidl line 20:0. Do not edit! +// This file is generated from mozilla\FetchEvent.webidl. Do not edit! package js.html; -typedef MediaKeyNeededEventInit = +typedef FetchEventInit = { > EventInit, - @:optional var initData : ArrayBuffer; - @:optional var initDataType : String; + @:optional var clientId : String; + @:optional var isReload : Bool; + var request : Request; } \ No newline at end of file diff --git a/std/js/html/FieldSetElement.hx b/std/js/html/FieldSetElement.hx index 64c7c900..c5251b81 100644 --- a/std/js/html/FieldSetElement.hx +++ b/std/js/html/FieldSetElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLFieldSetElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLFieldSetElement.webidl. Do not edit! package js.html; +/** + The `HTMLFieldSetElement` interface has special properties and methods (beyond the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating the layout and presentation of field-set elements. + + Documentation [HTMLFieldSetElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFieldSetElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFieldSetElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLFieldSetElement") extern class FieldSetElement extends Element { diff --git a/std/js/html/File.hx b/std/js/html/File.hx index ac1433cf..7e7b2c7c 100644 --- a/std/js/html/File.hx +++ b/std/js/html/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/File.webidl line 18:0. Do not edit! +// This file is generated from mozilla\File.webidl. Do not edit! package js.html; +/** + The `File` interface provides information about files and allows JavaScript in a web page to access their content. + + Documentation [File](https://developer.mozilla.org/en-US/docs/Web/API/File) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/File$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("File") extern class File extends Blob { + + /** + Returns the name of the file referenced by the `File` object. + **/ var name(default,null) : String; + + /** + Returns the last modified time of the file, in millisecond since the UNIX epoch (January 1st, 1970 at Midnight). + **/ var lastModified(default,null) : Int; + + /** + Returns the last modified `Date` of the file referenced by the `File` object. + **/ var lastModifiedDate(default,null) : Date; /** @throws DOMError */ diff --git a/std/js/html/FileList.hx b/std/js/html/FileList.hx index c5d0fa69..558bafbe 100644 --- a/std/js/html/FileList.hx +++ b/std/js/html/FileList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/FileList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\FileList.webidl. Do not edit! package js.html; +/** + An object of this type is returned by the `files` property of the HTML `input` element; this lets you access the list of files selected with the `input type="file"` element. It's also used for a list of files dropped into web content when using the drag and drop API; see the `DataTransfer` object for details on this usage. + + Documentation [FileList](https://developer.mozilla.org/en-US/docs/Web/API/FileList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FileList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("FileList") extern class FileList implements ArrayAccess { diff --git a/std/js/html/FileMode.hx b/std/js/html/FileMode.hx index f1551944..9452e350 100644 --- a/std/js/html/FileMode.hx +++ b/std/js/html/FileMode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/FileMode.webidl line 5:0. Do not edit! +// This file is generated from mozilla\FileMode.webidl. Do not edit! package js.html; diff --git a/std/js/html/FilePropertyBag.hx b/std/js/html/FilePropertyBag.hx index 1bf53d50..6a1af2ad 100644 --- a/std/js/html/FilePropertyBag.hx +++ b/std/js/html/FilePropertyBag.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/File.webidl line 28:0. Do not edit! +// This file is generated from mozilla\File.webidl. Do not edit! package js.html; diff --git a/std/js/html/FileReader.hx b/std/js/html/FileReader.hx index f61213e0..c9002b78 100644 --- a/std/js/html/FileReader.hx +++ b/std/js/html/FileReader.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/FileReader.webidl line 14:0. Do not edit! +// This file is generated from mozilla\FileReader.webidl. Do not edit! package js.html; +/** + The `FileReader` object lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user's computer, using `File` or `Blob` objects to specify the file or data to read. + + Documentation [FileReader](https://developer.mozilla.org/en-US/docs/Web/API/FileReader) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FileReader$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("FileReader") extern class FileReader extends EventTarget { @@ -31,26 +38,102 @@ extern class FileReader extends EventTarget static inline var LOADING : Int = 1; static inline var DONE : Int = 2; + + /** + A number indicating the state of the FileReader. This is one of the following: + + + + + + + + + + + + + + + + + + +
EMPTY0No data has been loaded yet.
LOADING1Data is currently being loaded.
DONE2The entire read request has been completed.
+ + **/ var readyState(default,null) : Int; + + /** + The file's contents. This property is only valid after the read operation is complete, and the format of the data depends on which of the methods was used to initiate the read operation. + **/ var result(default,null) : Dynamic; + + /** + A `DOMError` representing the error that occurred while reading the file. + **/ var error(default,null) : DOMError; + + /** + A handler for the `loadstart` event. This event is triggered each time the reading is starting. + **/ var onloadstart : haxe.Constraints.Function; + + /** + A handler for the `progress` event. This event is triggered while reading a `Blob` content. + **/ var onprogress : haxe.Constraints.Function; + + /** + A handler for the `load` event. This event is triggered each time the reading operation is successfully completed. + **/ var onload : haxe.Constraints.Function; + + /** + A handler for the `abort` event. This event is triggered each time the reading operation is aborted. + **/ var onabort : haxe.Constraints.Function; + + /** + A handler for the `error` event. This event is triggered each time the reading operation encounter an error. + **/ var onerror : haxe.Constraints.Function; + + /** + A handler for the `loadend` event. This event is triggered each time the reading operation is completed (either in success or failure). + **/ var onloadend : haxe.Constraints.Function; /** @throws DOMError */ function new() : Void; /** @throws DOMError */ + + /** + Starts reading the contents of the specified `Blob`, once finished, the `result` attribute contains an `ArrayBuffer` representing the file's data. + **/ function readAsArrayBuffer( blob : Blob ) : Void; /** @throws DOMError */ + + /** + Starts reading the contents of the specified `Blob`, once finished, the `result` attribute contains the contents of the file as a text string. + **/ function readAsText( blob : Blob, ?label : String = "" ) : Void; /** @throws DOMError */ + + /** + Starts reading the contents of the specified `Blob`, once finished, the `result` attribute contains a `data:` URL representing the file's data. + **/ function readAsDataURL( blob : Blob ) : Void; /** @throws DOMError */ + + /** + Aborts the read operation. Upon return, the `readyState` will be `DONE`. + **/ function abort() : Void; /** @throws DOMError */ + + /** + Starts reading the contents of the specified `Blob`, once finished, the `result` attribute contains the raw binary data from the file as a string. + **/ function readAsBinaryString( filedata : Blob ) : Void; } \ No newline at end of file diff --git a/std/js/html/FileReaderSync.hx b/std/js/html/FileReaderSync.hx index db5b9ff5..986dc542 100644 --- a/std/js/html/FileReaderSync.hx +++ b/std/js/html/FileReaderSync.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/FileReaderSync.webidl line 15:0. Do not edit! +// This file is generated from mozilla\FileReaderSync.webidl. Do not edit! package js.html; +/** + The `FileReaderSync` interface allows to read `File` or `Blob` objects in a synchronous way. + + Documentation [FileReaderSync](https://developer.mozilla.org/en-US/docs/Web/API/FileReaderSync) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FileReaderSync$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("FileReaderSync") extern class FileReaderSync { diff --git a/std/js/html/FillMode.hx b/std/js/html/FillMode.hx new file mode 100644 index 00000000..19b8ba1c --- /dev/null +++ b/std/js/html/FillMode.hx @@ -0,0 +1,34 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\AnimationEffectReadOnly.webidl. Do not edit! + +package js.html; + +@:enum abstract FillMode(String) +{ + var NONE = "none"; + var FORWARDS = "forwards"; + var BACKWARDS = "backwards"; + var BOTH = "both"; + var AUTO = "auto"; +} \ No newline at end of file diff --git a/std/js/html/Float32Array.hx b/std/js/html/Float32Array.hx index e4a9d1f3..6f8336c0 100644 --- a/std/js/html/Float32Array.hx +++ b/std/js/html/Float32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl line 179:0. Do not edit! +// This file is generated from typedarray.webidl. Do not edit! package js.html; +// Explicitly include the compatibility class +import js.html.compat.Float32Array; + @:native("Float32Array") extern class Float32Array extends ArrayBufferView implements ArrayAccess { @@ -36,9 +39,7 @@ extern class Float32Array extends ArrayBufferView implements ArrayAccess @:overload( function( array : Float32Array ) : Void {} ) @:overload( function( array : Array ) : Void {} ) function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; - function get( index : Int ) : Float; - @:overload( function( index : Int, value : Float ) : Void {} ) @:overload( function( array : Float32Array, ?offset : Int ) : Void {} ) function set( array : Array, ?offset : Int ) : Void; - function subarray( start : Int, end : Int ) : Float32Array; + function subarray( start : Int, ?end : Int ) : Float32Array; } \ No newline at end of file diff --git a/std/js/html/Float64Array.hx b/std/js/html/Float64Array.hx index bdaa6471..0fa72c2f 100644 --- a/std/js/html/Float64Array.hx +++ b/std/js/html/Float64Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl line 199:0. Do not edit! +// This file is generated from typedarray.webidl. Do not edit! package js.html; +// Explicitly include the compatibility class +import js.html.compat.Float64Array; + @:native("Float64Array") extern class Float64Array extends ArrayBufferView implements ArrayAccess { @@ -36,9 +39,7 @@ extern class Float64Array extends ArrayBufferView implements ArrayAccess @:overload( function( array : Float64Array ) : Void {} ) @:overload( function( array : Array ) : Void {} ) function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; - function get( index : Int ) : Float; - @:overload( function( index : Int, value : Float ) : Void {} ) @:overload( function( array : Float64Array, ?offset : Int ) : Void {} ) function set( array : Array, ?offset : Int ) : Void; - function subarray( start : Int, end : Int ) : Float64Array; + function subarray( start : Int, ?end : Int ) : Float64Array; } \ No newline at end of file diff --git a/std/js/html/FocusEvent.hx b/std/js/html/FocusEvent.hx index 00816de2..5193ceaf 100644 --- a/std/js/html/FocusEvent.hx +++ b/std/js/html/FocusEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/FocusEvent.webidl line 14:0. Do not edit! +// This file is generated from mozilla\FocusEvent.webidl. Do not edit! package js.html; +/** + The `FocusEvent` interface represents focus-related events like `focus`, `blur`, `focusin`, or `focusout`. + + Documentation [FocusEvent](https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("FocusEvent") extern class FocusEvent extends UIEvent { + + /** + Is an `EventTarget` representing a secondary target for this event. As in some cases (like when tabbing in or out a page), this property may be set to `null` for security reasons. + **/ var relatedTarget(default,null) : EventTarget; /** @throws DOMError */ diff --git a/std/js/html/FocusEventInit.hx b/std/js/html/FocusEventInit.hx index 1d50a549..ae2dd7ad 100644 --- a/std/js/html/FocusEventInit.hx +++ b/std/js/html/FocusEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/FocusEvent.webidl line 19:0. Do not edit! +// This file is generated from mozilla\FocusEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/FontElement.hx b/std/js/html/FontElement.hx index 08104b7b..1e669db0 100644 --- a/std/js/html/FontElement.hx +++ b/std/js/html/FontElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLFontElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLFontElement.webidl. Do not edit! package js.html; diff --git a/std/js/html/FontFace.hx b/std/js/html/FontFace.hx index 82bff96a..953a5d70 100644 --- a/std/js/html/FontFace.hx +++ b/std/js/html/FontFace.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,25 +20,72 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/FontFace.webidl line 32:0. Do not edit! +// This file is generated from mozilla\FontFace.webidl. Do not edit! package js.html; +/** + The `FontFace` interface represents a single usable font face. It allows control of the source of the font face, being a URL to an external resource, or a buffer; it also allows control of when the font face is loaded and its current status. + + Documentation [FontFace](https://developer.mozilla.org/en-US/docs/Web/API/FontFace) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FontFace$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("FontFace") extern class FontFace { + + /** + Is a `DOMString` that contains the family of the font. It is equivalent to the `@font-face/family` descriptor. + **/ var family : String; + + /** + Is a `DOMString` that contains the style of the font. It is equivalent to the `@font-face/style` descriptor. + **/ var style : String; + + /** + Is a `DOMString` that contains the weight of the font. It is equivalent to the `@font-face/weight` descriptor. + **/ var weight : String; + + /** + Is a `DOMString` that contains how the font stretches. It is equivalent to the `@font-face/stretch` descriptor. + **/ var stretch : String; + + /** + Is a `DOMString` that contains the range of code encompassed the font. It is equivalent to the `@font-face/unicode-range` descriptor. + **/ var unicodeRange : String; + + /** + Is a `DOMString` that contains the variant of the font. It is equivalent to the `@font-face/range` descriptor. + **/ var variant : String; + + /** + Is a `DOMString` that contains the features of the font. It is equivalent to the `@font-face/feature-settings` descriptor. + **/ var featureSettings : String; + + /** + Returns an enumerated value indicating the status of the font. It can be one of the following: `"unloaded"`, `"loading"`, `"loaded"`, or `"error"`. + **/ var status(default,null) : FontFaceLoadStatus; + + /** + Returns a `Promise` to a `FontFace` that fulfills when the font is completely loaded and rejects when an error happens. + **/ var loaded(default,null) : Promise; /** @throws DOMError */ function new( family : String, source : haxe.extern.EitherType>, ?descriptors : FontFaceDescriptors ) : Void; /** @throws DOMError */ + + /** + Loads the font, returning a `Promise` to a `FontFace` that fulfills when the font is completely loaded and rejects when an error happens. + **/ function load() : Promise; } \ No newline at end of file diff --git a/std/js/html/FontFaceDescriptors.hx b/std/js/html/FontFaceDescriptors.hx index d99979c3..609299f2 100644 --- a/std/js/html/FontFaceDescriptors.hx +++ b/std/js/html/FontFaceDescriptors.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,12 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/FontFace.webidl line 15:0. Do not edit! +// This file is generated from mozilla\FontFace.webidl. Do not edit! package js.html; typedef FontFaceDescriptors = { + @:optional var display : String; @:optional var featureSettings : String; @:optional var stretch : String; @:optional var style : String; diff --git a/std/js/html/FontFaceLoadStatus.hx b/std/js/html/FontFaceLoadStatus.hx index 0a0199b4..178e14e6 100644 --- a/std/js/html/FontFaceLoadStatus.hx +++ b/std/js/html/FontFaceLoadStatus.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/FontFace.webidl line 24:0. Do not edit! +// This file is generated from mozilla\FontFace.webidl. Do not edit! package js.html; diff --git a/std/js/html/FontFaceSet.hx b/std/js/html/FontFaceSet.hx index 087b1967..2f8bf669 100644 --- a/std/js/html/FontFaceSet.hx +++ b/std/js/html/FontFaceSet.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,27 +20,54 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/FontFaceSet.webidl line 18:0. Do not edit! +// This file is generated from mozilla\FontFaceSet.webidl. Do not edit! package js.html; +/** + The `FontFaceSet` interface of the CSS Font Loading API is an interface for loading font faces and checking their download statuses. + + Documentation [FontFaceSet](https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("FontFaceSet") -extern class FontFaceSet extends EventTarget implements ArrayAccess +extern class FontFaceSet extends EventTarget { + var size(default,null) : Int; + + /** + An `EventListener` property called whenever an event of type `loading` is fired, indicating that a font face set has started to load. + **/ var onloading : haxe.Constraints.Function; + + /** + An `EventListener` property called whenever an event of type `loadingdone` is fired, indicating that a font face set has finished loading. + **/ var onloadingdone : haxe.Constraints.Function; + + /** + An `EventListener` property called whenever an event of type `loadingerror` is fired, indicating that an error occurred during the loading of a font face set. + **/ var onloadingerror : haxe.Constraints.Function; var ready(default,null) : Promise; + + /** + Indicates the font face's loading status. It will be one of `'loading'` or `'loaded'`. + **/ var status(default,null) : FontFaceSetLoadStatus; - var length(default,null) : Int; /** @throws DOMError */ function add( font : FontFace ) : Void; function has( font : FontFace ) : Bool; - /** @throws DOMError */ @:native("delete") function delete_( font : FontFace ) : Bool; function clear() : Void; + function entries() : FontFaceSetIterator; + function values() : FontFaceSetIterator; /** @throws DOMError */ + function forEach( cb : FontFace -> FontFace -> FontFaceSet -> Void, ?thisArg : Dynamic ) : Void; function load( font : String, ?text : String = " " ) : Promise>; + /** @throws DOMError */ + function check( font : String, ?text : String = " " ) : Bool; } \ No newline at end of file diff --git a/std/js/html/FontFaceSetIterator.hx b/std/js/html/FontFaceSetIterator.hx new file mode 100644 index 00000000..2ecf87aa --- /dev/null +++ b/std/js/html/FontFaceSetIterator.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\FontFaceSet.webidl. Do not edit! + +package js.html; + +@:native("FontFaceSetIterator") +extern class FontFaceSetIterator +{ + /** @throws DOMError */ + function next() : FontFaceSetIteratorResult; +} \ No newline at end of file diff --git a/std/js/html/GetNotificationOptions.hx b/std/js/html/FontFaceSetIteratorResult.hx similarity index 85% rename from std/js/html/GetNotificationOptions.hx rename to std/js/html/FontFaceSetIteratorResult.hx index acf2757f..686f4613 100644 --- a/std/js/html/GetNotificationOptions.hx +++ b/std/js/html/FontFaceSetIteratorResult.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,12 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Notification.webidl line 68:0. Do not edit! +// This file is generated from mozilla\FontFaceSet.webidl. Do not edit! package js.html; -typedef GetNotificationOptions = +typedef FontFaceSetIteratorResult = { - @:optional var tag : String; + var done : Bool; + var value : Dynamic; } \ No newline at end of file diff --git a/std/js/html/FontFaceSetLoadStatus.hx b/std/js/html/FontFaceSetLoadStatus.hx index d395ad7f..c2fbc317 100644 --- a/std/js/html/FontFaceSetLoadStatus.hx +++ b/std/js/html/FontFaceSetLoadStatus.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/FontFaceSet.webidl line 13:0. Do not edit! +// This file is generated from mozilla\FontFaceSet.webidl. Do not edit! package js.html; diff --git a/std/js/html/FormData.hx b/std/js/html/FormData.hx index 292f52f3..80f6966a 100644 --- a/std/js/html/FormData.hx +++ b/std/js/html/FormData.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,71 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/FormData.webidl line 11:0. Do not edit! +// This file is generated from mozilla\FormData.webidl. Do not edit! package js.html; +/** + The `FormData` interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the `XMLHttpRequest.send()` method. It uses the same format a form would use if the encoding type were set to `"multipart/form-data"`. + + Documentation [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/FormData$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("FormData") extern class FormData { /** @throws DOMError */ function new( ?form : FormElement ) : Void; + /** @throws DOMError */ @:overload( function( name : String, value : Blob, ?filename : String ) : Void {} ) + + /** + Appends a new value onto an existing key inside a `FormData` object, or adds the key if it does not already exist. + **/ function append( name : String, value : String ) : Void; + @:native("delete") + function delete_( name : String ) : Void; + + /** + Returns the first value associated with a given key from within a `FormData` object. + **/ + function get( name : String ) : haxe.extern.EitherType; + + /** + Returns an array of all the values associated with a given key from within a `FormData`. + **/ + function getAll( name : String ) : Array>; + + /** + Returns a boolean stating whether a `FormData` object contains a certain key/value pair. + **/ + function has( name : String ) : Bool; + /** @throws DOMError */ + @:overload( function( name : String, value : Blob, ?filename : String ) : Void {} ) + + /** + Sets a new value for an existing key inside a `FormData `object, or adds the key/value if it does not already exist. + **/ + function set( name : String, value : String ) : Void; + /** @throws DOMError */ + + /** + Returns an `Iteration_protocols` allowing to go through all key/value pairs contained in this object. + **/ + function entries() : FormDataIterator; + /** @throws DOMError */ + + /** + Returns an `Iteration_protocols` allowing to go through all keys of the key/value pairs contained in this object. + **/ + function keys() : FormDataIterator; + /** @throws DOMError */ + + /** + Returns an `Iteration_protocols` allowing to go through all values of the key/value pairs contained in this object. + **/ + function values() : FormDataIterator; + /** @throws DOMError */ + function forEach( callback : Dynamic, ?thisArg : Dynamic ) : Void; } \ No newline at end of file diff --git a/std/js/html/FormDataIterator.hx b/std/js/html/FormDataIterator.hx new file mode 100644 index 00000000..2738acda --- /dev/null +++ b/std/js/html/FormDataIterator.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\FormData.webidl. Do not edit! + +package js.html; + +@:native("FormDataIterator") +extern class FormDataIterator +{ + /** @throws DOMError */ + function next() : Dynamic; +} \ No newline at end of file diff --git a/std/js/html/FormElement.hx b/std/js/html/FormElement.hx index 68002c2e..062e78b2 100644 --- a/std/js/html/FormElement.hx +++ b/std/js/html/FormElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,21 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLFormElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLFormElement.webidl. Do not edit! package js.html; +/** + The `HTMLFormElement` interface provides methods to create and modify `form` elements. + document.forms - returns an array of HTMLFormElement objects referencing all forms on the page. + document.forms[index] - returns an HTMLFormElement object referencing the form at the specified index. + document.forms['id'] - returns an HTMLFormElement object referencing the form with the specified id. + document.forms['name'] - returns an HTMLFormElement object referencing the form with the specified name. + + Documentation [HTMLFormElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLFormElement") extern class FormElement extends Element implements ArrayAccess { diff --git a/std/js/html/FrameElement.hx b/std/js/html/FrameElement.hx index c4a06e8d..204f617c 100644 --- a/std/js/html/FrameElement.hx +++ b/std/js/html/FrameElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLFrameElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLFrameElement.webidl. Do not edit! package js.html; diff --git a/std/js/html/FrameSetElement.hx b/std/js/html/FrameSetElement.hx index 2567d668..7ddbb9a7 100644 --- a/std/js/html/FrameSetElement.hx +++ b/std/js/html/FrameSetElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLFrameSetElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLFrameSetElement.webidl. Do not edit! package js.html; +/** + The `HTMLFrameSetElement` interface provides special properties (beyond those of the regular `HTMLElement` interface they also inherit) for manipulating `frameset` elements. + + Documentation [HTMLFrameSetElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFrameSetElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFrameSetElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLFrameSetElement") extern class FrameSetElement extends Element { + + /** + Is a `DOMString` that represents the foreground color of text. + **/ var cols : String; + + /** + Is a `DOMString` that represents the color of visited links. + **/ var rows : String; var onafterprint : haxe.Constraints.Function; var onbeforeprint : haxe.Constraints.Function; @@ -40,7 +55,7 @@ extern class FrameSetElement extends Element var onpagehide : haxe.Constraints.Function; var onpageshow : haxe.Constraints.Function; var onpopstate : haxe.Constraints.Function; - var onresize : haxe.Constraints.Function; + var onstorage : haxe.Constraints.Function; var onunload : haxe.Constraints.Function; } \ No newline at end of file diff --git a/std/js/html/MediaWaitingFor.hx b/std/js/html/FrameType.hx similarity index 83% rename from std/js/html/MediaWaitingFor.hx rename to std/js/html/FrameType.hx index 0aae617c..e196fccb 100644 --- a/std/js/html/MediaWaitingFor.hx +++ b/std/js/html/FrameType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,14 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLMediaElement.webidl line 141:0. Do not edit! +// This file is generated from mozilla\Client.webidl. Do not edit! package js.html; -@:enum abstract MediaWaitingFor(String) +@:enum abstract FrameType(String) { + var AUXILIARY = "auxiliary"; + var TOP_LEVEL = "top-level"; + var NESTED = "nested"; var NONE = "none"; - var DATA = "data"; - var KEY = "key"; } \ No newline at end of file diff --git a/std/js/html/Gamepad.hx b/std/js/html/Gamepad.hx index 4eea2372..0036ee3b 100644 --- a/std/js/html/Gamepad.hx +++ b/std/js/html/Gamepad.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,19 +20,54 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Gamepad.webidl line 18:0. Do not edit! +// This file is generated from mozilla\Gamepad.webidl. Do not edit! package js.html; +/** + The `Gamepad` interface of the Gamepad API defines an individual gamepad or other controller, allowing access to information such as button presses, axis positions, and id. + + Documentation [Gamepad](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Gamepad") extern class Gamepad { + + /** + A `DOMString` containing identifying information about the controller. + **/ var id(default,null) : String; + + /** + An integer that is auto-incremented to be unique for each device currently connected to the system. + **/ var index(default,null) : Int; + + /** + A string indicating whether the browser has remapped the controls on the device to a known layout. + **/ var mapping(default,null) : GamepadMappingType; + + /** + A boolean indicating whether the gamepad is still connected to the system. + **/ var connected(default,null) : Bool; + + /** + An array of `gamepadButton` objects representing the buttons present on the device. + **/ var buttons(default,null) : Array; + + /** + An array representing the controls with axes present on the device (e.g. analog thumb sticks). + **/ var axes(default,null) : Array; + + /** + A `DOMHighResTimeStamp` representing the last time the data for this gamepad was updated. Note that this property is not currently supported anywhere. + **/ var timestamp(default,null) : Float; } \ No newline at end of file diff --git a/std/js/html/GamepadButton.hx b/std/js/html/GamepadButton.hx index ee5a3805..1aa6f3df 100644 --- a/std/js/html/GamepadButton.hx +++ b/std/js/html/GamepadButton.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Gamepad.webidl line 7:0. Do not edit! +// This file is generated from mozilla\Gamepad.webidl. Do not edit! package js.html; +/** + The `GamepadButton` interface defines an individual button of a gamepad or other controller, allowing access to the current state of different types of buttons available on the control device. + + Documentation [GamepadButton](https://developer.mozilla.org/en-US/docs/Web/API/GamepadButton) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/GamepadButton$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("GamepadButton") extern class GamepadButton { + + /** + A boolean value indicating whether the button is currently pressed (`true`) or unpressed (`false`). + **/ var pressed(default,null) : Bool; + + /** + A double value used to represent the current state of analog buttons, such as the triggers on many modern gamepads. The values are normalized to the range 0.0 —1.0, with 0.0 representing a button that is not pressed, and 1.0 representing a button that is fully pressed. + **/ var value(default,null) : Float; } \ No newline at end of file diff --git a/std/js/html/GamepadMappingType.hx b/std/js/html/GamepadMappingType.hx index bb54f426..28c6e77c 100644 --- a/std/js/html/GamepadMappingType.hx +++ b/std/js/html/GamepadMappingType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Gamepad.webidl line 12:0. Do not edit! +// This file is generated from mozilla\Gamepad.webidl. Do not edit! package js.html; diff --git a/std/js/html/Geolocation.hx b/std/js/html/Geolocation.hx index 6b2f6c1d..7da368a1 100644 --- a/std/js/html/Geolocation.hx +++ b/std/js/html/Geolocation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,35 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Geolocation.webidl line 20:0. Do not edit! +// This file is generated from mozilla\Geolocation.webidl. Do not edit! package js.html; +/** + The `Geolocation` interface represents an object able to programmatically obtain the position of the device. It gives Web content access to the location of the device. This allows a Web site or app to offer customized results based on the user's location. + + Documentation [Geolocation](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Geolocation") extern class Geolocation { /** @throws DOMError */ + + /** + Determines the device's current location and gives back a `Position` object with the data. + **/ function getCurrentPosition( successCallback : Position -> Void, ?errorCallback : PositionError -> Void, ?options : PositionOptions ) : Void; /** @throws DOMError */ + + /** + Returns a `long` value representing the newly established callback function to be invoked whenever the device location changes. + **/ function watchPosition( successCallback : Position -> Void, ?errorCallback : PositionError -> Void, ?options : PositionOptions ) : Int; + + /** + Removes the particular handler previously installed using `watchPosition()`. + **/ function clearWatch( watchId : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/GetUserMediaRequest.hx b/std/js/html/GetUserMediaRequest.hx index 1c1d64b4..ab01b4c3 100644 --- a/std/js/html/GetUserMediaRequest.hx +++ b/std/js/html/GetUserMediaRequest.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/GetUserMediaRequest.webidl line 10:0. Do not edit! +// This file is generated from mozilla\GetUserMediaRequest.webidl. Do not edit! package js.html; diff --git a/std/js/html/HRElement.hx b/std/js/html/HRElement.hx index 459bcdd2..a2309eac 100644 --- a/std/js/html/HRElement.hx +++ b/std/js/html/HRElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLHRElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLHRElement.webidl. Do not edit! package js.html; +/** + The `HTMLHRElement` interface provides special properties (beyond those of the `HTMLElement` interface it also has available to it by inheritance) for manipulating `hr` elements. + + Documentation [HTMLHRElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHRElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHRElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLHRElement") extern class HRElement extends Element { diff --git a/std/js/html/HTMLAllCollection.hx b/std/js/html/HTMLAllCollection.hx index 2990f280..466b12dd 100644 --- a/std/js/html/HTMLAllCollection.hx +++ b/std/js/html/HTMLAllCollection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLAllCollection.webidl line 6:0. Do not edit! +// This file is generated from mozilla\HTMLAllCollection.webidl. Do not edit! package js.html; diff --git a/std/js/html/HTMLCollection.hx b/std/js/html/HTMLCollection.hx index 8f5057bc..756e731d 100644 --- a/std/js/html/HTMLCollection.hx +++ b/std/js/html/HTMLCollection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLCollection.webidl line 13:0. Do not edit! +// This file is generated from mozilla\HTMLCollection.webidl. Do not edit! package js.html; +/** + The `HTMLCollection` interface represents a generic collection (array-like object similar to arguments) of elements (in document order) and offers methods and properties for selecting from the list. + + Documentation [HTMLCollection](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLCollection") extern class HTMLCollection implements ArrayAccess { + + /** + Returns the number of items in the collection. + **/ var length(default,null) : Int; + + /** + Returns the specific node at the given zero-based `index` into the list. Returns `null` if the `index` is out of range. + **/ function item( index : Int ) : Element; + + /** + Returns the specific node whose ID or, as a fallback, name matches the string specified by `name`. Matching by name is only done as a last resort, only in HTML, and only if the referenced element supports the `name` attribute. Returns `null` if no node exists by the given name. + **/ function namedItem( name : String ) : Element; } \ No newline at end of file diff --git a/std/js/html/HTMLDocument.hx b/std/js/html/HTMLDocument.hx index 50ae5e93..7e80b469 100644 --- a/std/js/html/HTMLDocument.hx +++ b/std/js/html/HTMLDocument.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLDocument.webidl line 8:0. Do not edit! +// This file is generated from mozilla\HTMLDocument.webidl. Do not edit! package js.html; +/** + `HTMLDocument` is an abstract interface of the DOM which provides access to special properties and methods not present by default on a regular (XML) document. + + Documentation [HTMLDocument](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDocument) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDocument$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLDocument") extern class HTMLDocument extends Document { diff --git a/std/js/html/HTMLFormControlsCollection.hx b/std/js/html/HTMLFormControlsCollection.hx index 33bfbd82..e65a3437 100644 --- a/std/js/html/HTMLFormControlsCollection.hx +++ b/std/js/html/HTMLFormControlsCollection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLFormControlsCollection.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLFormControlsCollection.webidl. Do not edit! package js.html; +/** + The `HTMLFormControlsCollection` interface represents a collection of HTML form control elements. It replaces one method of `HTMLCollection`. + + Documentation [HTMLFormControlsCollection](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormControlsCollection) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormControlsCollection$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLFormControlsCollection") extern class HTMLFormControlsCollection extends HTMLCollection { diff --git a/std/js/html/HTMLOptionsCollection.hx b/std/js/html/HTMLOptionsCollection.hx index 0d941cb3..1e2a03de 100644 --- a/std/js/html/HTMLOptionsCollection.hx +++ b/std/js/html/HTMLOptionsCollection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLOptionsCollection.webidl line 13:0. Do not edit! +// This file is generated from mozilla\HTMLOptionsCollection.webidl. Do not edit! package js.html; +/** + `HTMLOptionsCollection` is an interface representing a collection of HTML option elements (in document order) and offers methods and properties for traversing the list as well as optionally altering its items. This type is returned solely by the "options" property of select. + + Documentation [HTMLOptionsCollection](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOptionsCollection) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOptionsCollection$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLOptionsCollection") extern class HTMLOptionsCollection extends HTMLCollection { diff --git a/std/js/html/HTMLPropertiesCollection.hx b/std/js/html/HTMLPropertiesCollection.hx index c3150c28..9b2125c8 100644 --- a/std/js/html/HTMLPropertiesCollection.hx +++ b/std/js/html/HTMLPropertiesCollection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLPropertiesCollection.webidl line 13:0. Do not edit! +// This file is generated from mozilla\HTMLPropertiesCollection.webidl. Do not edit! package js.html; diff --git a/std/js/html/HashChangeEvent.hx b/std/js/html/HashChangeEvent.hx index e7659bea..68d54951 100644 --- a/std/js/html/HashChangeEvent.hx +++ b/std/js/html/HashChangeEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HashChangeEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\HashChangeEvent.webidl. Do not edit! package js.html; +/** + The `hashchange` event is fired when the fragment identifier of the URL has changed (the part of the URL that follows the # symbol, including the # symbol). + + Documentation [HashChangeEvent](https://developer.mozilla.org/en-US/docs/Web/API/HashChangeEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HashChangeEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HashChangeEvent") extern class HashChangeEvent extends Event { @@ -32,6 +39,5 @@ extern class HashChangeEvent extends Event /** @throws DOMError */ function new( type : String, ?eventInitDict : HashChangeEventInit ) : Void; - /** @throws DOMError */ function initHashChangeEvent( typeArg : String, canBubbleArg : Bool, cancelableArg : Bool, oldURLArg : String, newURLArg : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/HashChangeEventInit.hx b/std/js/html/HashChangeEventInit.hx index d5a248a9..b3d918e7 100644 --- a/std/js/html/HashChangeEventInit.hx +++ b/std/js/html/HashChangeEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HashChangeEvent.webidl line 21:0. Do not edit! +// This file is generated from mozilla\HashChangeEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/HeadElement.hx b/std/js/html/HeadElement.hx index f0da6992..c1f1e8b1 100644 --- a/std/js/html/HeadElement.hx +++ b/std/js/html/HeadElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLHeadElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLHeadElement.webidl. Do not edit! package js.html; +/** + The `HTMLHeadElement` interface contains the descriptive information, or metadata, for a document. This object inherits all of the properties and methods described in the `HTMLElement` interface. + + Documentation [HTMLHeadElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHeadElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHeadElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLHeadElement") extern class HeadElement extends Element { diff --git a/std/js/html/Headers.hx b/std/js/html/Headers.hx new file mode 100644 index 00000000..a93c36d6 --- /dev/null +++ b/std/js/html/Headers.hx @@ -0,0 +1,92 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Headers.webidl. Do not edit! + +package js.html; + +/** + The `Headers` interface of the Fetch API allows you to perform various actions on HTTP request and response headers. These actions include retrieving, setting, adding to, and removing. A `Headers` object has an associated header list, which is initially empty and consists of zero or more name and value pairs.  You can add to this using methods like `append()` (see Examples.) In all methods of this interface, header names are matched by case-insensitive byte sequence. + + Documentation [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Headers$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("Headers") +extern class Headers +{ + /** @throws DOMError */ + function new( ?init : haxe.extern.EitherType>,Dynamic/*MISSING ByteStringMozMap*/>> ) : Void; + /** @throws DOMError */ + + /** + Appends a new value onto an existing header inside a `Headers` object, or adds the header if it does not already exist. + **/ + function append( name : String, value : String ) : Void; + /** @throws DOMError */ + @:native("delete") + function delete_( name : String ) : Void; + /** @throws DOMError */ + + /** + Returns the first value of a given header from within a `Headers` object. + **/ + function get( name : String ) : String; + /** @throws DOMError */ + + /** + Returns an array of all the values of a header within a `Headers` object with a given name. + **/ + function getAll( name : String ) : Array; + /** @throws DOMError */ + + /** + Returns a boolean stating whether a `Headers` object contains a certain header. + **/ + function has( name : String ) : Bool; + /** @throws DOMError */ + + /** + Sets a new value for an existing header inside a `Headers` object, or adds the header if it does not already exist. + **/ + function set( name : String, value : String ) : Void; + /** @throws DOMError */ + + /** + Returns an `Iteration_protocols` allowing to go through all key/value pairs contained in this object. + **/ + function entries() : HeadersIterator; + /** @throws DOMError */ + + /** + Returns an `Iteration_protocols` allowing to go through all keys f the key/value pairs contained in this object. + **/ + function keys() : HeadersIterator; + /** @throws DOMError */ + + /** + Returns an `Iteration_protocols` allowing to go through all values of the key/value pairs contained in this object. + **/ + function values() : HeadersIterator; + /** @throws DOMError */ + function forEach( callback : Dynamic, ?thisArg : Dynamic ) : Void; +} \ No newline at end of file diff --git a/std/js/html/SessionType.hx b/std/js/html/HeadersIterator.hx similarity index 83% rename from std/js/html/SessionType.hx rename to std/js/html/HeadersIterator.hx index 2948ba23..258e329a 100644 --- a/std/js/html/SessionType.hx +++ b/std/js/html/HeadersIterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,12 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaKeys.webidl line 14:0. Do not edit! +// This file is generated from mozilla\Headers.webidl. Do not edit! package js.html; -@:enum abstract SessionType(String) +@:native("HeadersIterator") +extern class HeadersIterator { - var TEMPORARY = "temporary"; - var PERSISTENT = "persistent"; + /** @throws DOMError */ + function next() : Dynamic; } \ No newline at end of file diff --git a/std/js/html/HeadingElement.hx b/std/js/html/HeadingElement.hx index bb5dd0c1..e954f2c8 100644 --- a/std/js/html/HeadingElement.hx +++ b/std/js/html/HeadingElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLHeadingElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLHeadingElement.webidl. Do not edit! package js.html; +/** + The `HTMLHeadingElement` interface represents the different heading elements. It inherits methods and properties from the `HTMLElement` interface. + + Documentation [HTMLHeadingElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHeadingElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHeadingElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLHeadingElement") extern class HeadingElement extends Element { + + /** + Is a `DOMString` representing an enumerated attribute indicating alignment of the heading with respect to the surrounding context. + **/ var align : String; } \ No newline at end of file diff --git a/std/js/html/History.hx b/std/js/html/History.hx index 86251b9a..86612d8c 100644 --- a/std/js/html/History.hx +++ b/std/js/html/History.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,24 +20,70 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/History.webidl line 14:0. Do not edit! +// This file is generated from mozilla\History.webidl. Do not edit! package js.html; +/** + The `History` interface allows to manipulate the browser session history, that is the pages visited in the tab or frame that the current page is loaded in. + + Documentation [History](https://developer.mozilla.org/en-US/docs/Web/API/History) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/History$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("History") extern class History { + + /** + Returns an `Integer` representing the number of elements in the session history, including the currently loaded page. For example, for a page loaded in a new tab this property returns `1`. + **/ var length(default,null) : Int; + + /** + Allows web applications to explicitly set default scroll restoration behavior on history navigation. This property can be either `auto` or `manual`. + **/ + var scrollRestoration : ScrollRestoration; + + /** + Returns an `any` value representing the state at the top of the history stack. This is a way to look at the state without having to wait for a `popstate` event. + **/ var state(default,null) : Dynamic; /** @throws DOMError */ + + /** + Loads a page from the session history, identified by its relative location to the current page, for example -1 for the previous page or 1  for the next page. If you specify an out-of-bounds value (for instance, specifying -1 when there are no previously-visited pages in the session history), this method silently has no effect. Calling `go()` without parameters or a value of 0 reloads the current page. + Internet Explorer lets you specify a string to go to a specific page in the history list; you should avoid this feature because it is non-standard. + + **/ function go( ?delta : Int = 0 ) : Void; /** @throws DOMError */ + + /** + Goes to the previous page in session history, the same action as when the user clicks the browser's Back button. Equivalent to `history.go(-1)`. + Calling this method to go back beyond the first page in the session history has no effect and doesn't raise an exception. + + **/ function back() : Void; /** @throws DOMError */ + + /** + Goes to the next page in session history, the same action as when the user clicks the browser's Forward button; this is equivalent to `history.go(1)`. + Calling this method to go forward beyond the most recent page in the session history has no effect and doesn't raise an exception. + + **/ function forward() : Void; /** @throws DOMError */ + + /** + Pushes the given data onto the session history stack with the specified title and, if provided, URL. The data is treated as opaque by the DOM; you may specify any JavaScript object that can be serialized.  Note that Firefox currently ignores the title parameter; for more information, see manipulating the browser history. + **/ function pushState( data : Dynamic, title : String, ?url : String ) : Void; /** @throws DOMError */ + + /** + Updates the most recent entry on the history stack to have the specified data, title, and, if provided, URL. The data is treated as opaque by the DOM; you may specify any JavaScript object that can be serialized.  Note that Firefox currently ignores the title parameter; for more information, see manipulating the browser history. + **/ function replaceState( data : Dynamic, title : String, ?url : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/HitRegionOptions.hx b/std/js/html/HitRegionOptions.hx index 99452c5b..698cffa8 100644 --- a/std/js/html/HitRegionOptions.hx +++ b/std/js/html/HitRegionOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CanvasRenderingContext2D.webidl line 23:0. Do not edit! +// This file is generated from mozilla\CanvasRenderingContext2D.webidl. Do not edit! package js.html; @@ -28,4 +28,5 @@ typedef HitRegionOptions = { @:optional var control : Element; @:optional var id : String; + @:optional var path : Path2D; } \ No newline at end of file diff --git a/std/js/html/HtmlElement.hx b/std/js/html/HtmlElement.hx index c717b4f0..bf7eb56e 100644 --- a/std/js/html/HtmlElement.hx +++ b/std/js/html/HtmlElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLHtmlElement.webidl line 16:0. Do not edit! +// This file is generated from mozilla\HTMLHtmlElement.webidl. Do not edit! package js.html; +/** + The `HTMLHtmlElement` interface serves as the root node for a given HTML document.  This object inherits the properties and methods described in the `HTMLElement` interface. + + Documentation [HTMLHtmlElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHtmlElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHtmlElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLHtmlElement") extern class HtmlElement extends Element { + + /** + Is a `DOMString` representing the version of the HTML Document Type Definition (DTD) that governs this document. This property should not be used any more as it is non-conforming. Simply omit it. + **/ var version : String; } \ No newline at end of file diff --git a/std/js/html/IFrameElement.hx b/std/js/html/IFrameElement.hx index fae23d54..70bafa1e 100644 --- a/std/js/html/IFrameElement.hx +++ b/std/js/html/IFrameElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,27 +20,90 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLIFrameElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLIFrameElement.webidl. Do not edit! package js.html; +/** + The `HTMLIFrameElement` interface provides special properties and methods (beyond those of the `HTMLElement` interface it also has available to it by inheritance) for manipulating the layout and presentation of inline frame elements. + + Documentation [HTMLIFrameElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLIFrameElement") extern class IFrameElement extends Element { + + /** + Is a `DOMString` that reflects the `src` HTML attribute, containing the address of the content to be embedded. + **/ var src : String; + + /** + Is a `DOMString` that represents the content to display in the frame. + **/ var srcdoc : String; + + /** + Is a `DOMString` that reflects the `name` HTML attribute, containing a name by which to refer to the frame. + **/ var name : String; - var sandbox(default,null) : DOMSettableTokenList; + + /** + Is a `DOMSettableTokenList` that reflects the `sandbox` HTML attribute, indicating extra restrictions on the behavior of the nested content. + **/ + var sandbox(default,null) : DOMTokenList; var allowFullscreen : Bool; + + /** + Is a `DOMString` that reflects the `width` HTML attribute, indicating the width of the frame. + **/ var width : String; + + /** + Is a `DOMString` that reflects the `height` HTML attribute, indicating the height of the frame. + **/ var height : String; + + /** + Returns a `Document`, the active document in the inline frame's nested browsing context. + **/ var contentDocument(default,null) : HTMLDocument; + + /** + Returns a `WindowProxy`, the window proxy for the nested browsing context. + **/ var contentWindow(default,null) : Window; + + /** + Is a `DOMString` that specifies the alignment of the frame with respect to the surrounding context. + **/ var align : String; + + /** + Is a `DOMString` that indicates whether the browser should provide scrollbars for the frame. + **/ var scrolling : String; + + /** + Is a `DOMString` that indicates whether to create borders between frames. + **/ var frameBorder : String; + + /** + Is a `DOMString` that contains the URI of a long description of the frame. + **/ var longDesc : String; + + /** + Is a `DOMString` being the height of the frame margin. + **/ var marginHeight : String; + + /** + Is a `DOMString` being the width of the frame margin. + **/ var marginWidth : String; function getSVGDocument() : HTMLDocument; diff --git a/std/js/html/Image.hx b/std/js/html/Image.hx index 37f036ee..f0e71f92 100644 --- a/std/js/html/Image.hx +++ b/std/js/html/Image.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from namedConstructors.webidl line 6:0. Do not edit! +// This file is generated from namedConstructors.webidl. Do not edit! package js.html; diff --git a/std/js/html/ImageBitmap.hx b/std/js/html/ImageBitmap.hx new file mode 100644 index 00000000..501ca2b4 --- /dev/null +++ b/std/js/html/ImageBitmap.hx @@ -0,0 +1,55 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\ImageBitmap.webidl. Do not edit! + +package js.html; + +/** + The `ImageBitmap` interface represents a bitmap image which can be drawn to a `canvas` without undue latency. It can be created from a variety of source objects using the `createImageBitmap()` factory method. `ImageBitmap` provides an asynchronous and resource efficient pathway to prepare textures for rendering in WebGL. + + Documentation [ImageBitmap](https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("ImageBitmap") +extern class ImageBitmap +{ + + /** + Is an `unsigned` `long` representing the width, in CSS pixels, of the `ImageData`. + **/ + var width(default,null) : Int; + + /** + Is an `unsigned` `long` representing the height, in CSS pixels, of the `ImageData`. + **/ + var height(default,null) : Int; + + + /** + + Disposes of all graphical resources associated with an `ImageBitmap`. + + **/ + function close() : Void; +} \ No newline at end of file diff --git a/std/js/html/ImageBitmapRenderingContext.hx b/std/js/html/ImageBitmapRenderingContext.hx new file mode 100644 index 00000000..4ec41100 --- /dev/null +++ b/std/js/html/ImageBitmapRenderingContext.hx @@ -0,0 +1,44 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\ImageBitmapRenderingContext.webidl. Do not edit! + +package js.html; + +/** + The `ImageBitmapRenderingContext` interface is a canvas rendering context which only provides the functionality to replace the canvas's contents with the given `ImageBitmap`. Its context id (the first argument to `HTMLCanvasElement.getContext()` or `OffscreenCanvas.getContext()`  is `"bitmaprenderer"`. + + Documentation [ImageBitmapRenderingContext](https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmapRenderingContext) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmapRenderingContext$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("ImageBitmapRenderingContext") +extern class ImageBitmapRenderingContext +{ + + /** + + Displays the given `ImageBitmap` in the canvas associated with this rendering context. Ownership of the `ImageBitmap` is transferred to the canvas. + + **/ + function transferImageBitmap( bitmap : ImageBitmap ) : Void; +} \ No newline at end of file diff --git a/std/js/html/ImageCapture.hx b/std/js/html/ImageCapture.hx index f19cc13e..ba0cd404 100644 --- a/std/js/html/ImageCapture.hx +++ b/std/js/html/ImageCapture.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ImageCapture.webidl line 14:0. Do not edit! +// This file is generated from mozilla\ImageCapture.webidl. Do not edit! package js.html; diff --git a/std/js/html/ImageData.hx b/std/js/html/ImageData.hx index 8316e779..c29546b1 100644 --- a/std/js/html/ImageData.hx +++ b/std/js/html/ImageData.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ImageData.webidl line 16:0. Do not edit! +// This file is generated from mozilla\ImageData.webidl. Do not edit! package js.html; +/** + The `ImageData` interface represents the underlying pixel data of an area of a `canvas` element. It is created using the `ImageData()` constructor or creator methods on the `CanvasRenderingContext2D` object associated with a canvas: `createImageData()` and `getImageData()`. It can also be used to set a part of the canvas by using `putImageData()`. + + Documentation [ImageData](https://developer.mozilla.org/en-US/docs/Web/API/ImageData) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ImageData$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("ImageData") extern class ImageData { + + /** + Is an `unsigned` `long` representing the actual width, in pixels, of the `ImageData`. + **/ var width(default,null) : Int; + + /** + Is an `unsigned` `long` representing the actual height, in pixels, of the `ImageData`. + **/ var height(default,null) : Int; + + /** + Is a `Uint8ClampedArray` representing a one-dimensional array containing the data in the RGBA order, with integer values between `0` and `255` (included). + **/ var data(default,null) : Uint8ClampedArray; /** @throws DOMError */ diff --git a/std/js/html/ImageElement.hx b/std/js/html/ImageElement.hx index 2fa477f6..eedc0903 100644 --- a/std/js/html/ImageElement.hx +++ b/std/js/html/ImageElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,34 +20,125 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLImageElement.webidl line 21:0. Do not edit! +// This file is generated from mozilla\HTMLImageElement.webidl. Do not edit! package js.html; +/** + The `HTMLImageElement` interface provides special properties and methods  for manipulating the layout and presentation of `img` elements. + + Documentation [HTMLImageElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLImageElement") extern class ImageElement extends Element { + + /** + Is a `DOMString` that reflects the `alt` HTML attribute,  thus indicating fallback context for the image. + **/ var alt : String; + + /** + Is a `DOMString` that reflects the `src` HTML attribute, containing the full URL of the image including base URI. + **/ var src : String; + + /** + Is a `DOMString` reflecting the `srcset` HTML attribute, containing a list of candidate images, separated by a comma (`',', U+002C COMMA`). A candidate image is a URL followed by a `'w'` with the width of the images, or an `'x'` followed by the pixel density. + **/ var srcset : String; + + /** + Is a `DOMString` representing the CORS setting for this image element. See CORS settings attributes for further details. + **/ var crossOrigin : String; + + /** + Is a `DOMString` that reflects the `usemap` HTML attribute, containing a partial URL of a map element. + **/ var useMap : String; + + /** + Is a `Boolean` that reflects the `ismap` HTML attribute, indicating that the image is part of a server-side image map. + **/ var isMap : Bool; + + /** + Is a `unsigned long` that reflects the `width` HTML attribute, indicating the rendered width of the image in CSS pixels. + **/ var width : Int; + + /** + Is a `unsigned long` that reflects the `height` HTML attribute, indicating the rendered height of the image in CSS pixels. + **/ var height : Int; + + /** + Returns a `unsigned long` representing the intrinsic width of the image in CSS pixels, if it is available; otherwise, it will show `0`. + **/ var naturalWidth(default,null) : Int; + + /** + Returns a `unsigned long` representing the intrinsic height of the image in CSS pixels, if it is available; else, it shows `0`. + **/ var naturalHeight(default,null) : Int; + + /** + Returns a `Boolean` that is `true` if the browser has finished fetching the image, whether successful or not. It also shows true, if the image has no `HTMLImageElement.src` value. + **/ var complete(default,null) : Bool; + + /** + Is a `DOMString` representing the name of the element. + **/ var name : String; + + /** + Is a `DOMString` indicating the alignment of the image with respect to the surrounding context. + **/ var align : String; + + /** + Is a `long` representing the space on either side of the image. + **/ var hspace : Int; + + /** + Is a `long` representing the space above and below the image. + **/ var vspace : Int; + + /** + Is a `DOMString` representing the URI of a long description of the image. + **/ var longDesc : String; + + /** + Is a `DOMString` that is responsible for the width of the border surrounding the image. This is now deprecated and the CSS `border` property should be used instead. + **/ var border : String; + + /** + Is a `DOMString` reflecting the `sizes` HTML attribute. + **/ var sizes : String; + + /** + Returns a `DOMString` representing the URL to the currently displayed image (which may change, for example in response to media queries). + **/ var currentSrc(default,null) : String; var lowsrc : String; + + /** + Returns a `long` representing the horizontal offset from the nearest layer. This property mimics an old Netscape 4 behavior. + **/ var x(default,null) : Int; + + /** + Returns a `long` representing the vertical offset from the nearest layer. This property is also similar to behavior of an old Netscape 4. + **/ var y(default,null) : Int; } \ No newline at end of file diff --git a/std/js/html/InputElement.hx b/std/js/html/InputElement.hx index 36c0e3a8..59b821ca 100644 --- a/std/js/html/InputElement.hx +++ b/std/js/html/InputElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLInputElement.webidl line 24:0. Do not edit! +// This file is generated from mozilla\HTMLInputElement.webidl. Do not edit! package js.html; +/** + The `HTMLInputElement` interface provides special properties and methods for manipulating the layout and presentation of input elements. + + Documentation [HTMLInputElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLInputElement") extern class InputElement extends Element { @@ -67,13 +74,43 @@ extern class InputElement extends Element var selectionStart : Int; var selectionEnd : Int; var selectionDirection : String; + + /** + `string:` represents the alignment of the element. Use CSS instead. + **/ var align : String; + + /** + `string:` represents a client-side image map. + **/ var useMap : String; var textLength(default,null) : Int; /** @throws DOMError */ + + /** + Increments the `value` by (`step` * n), where n defaults to 1 if not specified. Throws an INVALID_STATE_ERR exception: + + if the method is not applicable to for the current `type` value., + if the element has no `step` value, + if the `value` cannot be converted to a number, + if the resulting value is above the `max` or below the `min`. + + + **/ function stepUp( ?n : Int = 1 ) : Void; /** @throws DOMError */ + + /** + Decrements the `value` by (`step` * n), where n defaults to 1 if not specified. Throws an INVALID_STATE_ERR exception: + + if the method is not applicable to for the current `type` value, + if the element has no `step` value, + if the `value` cannot be converted to a number, + if the resulting value is above the `max` or below the `min`.  + + + **/ function stepDown( ?n : Int = 1 ) : Void; function checkValidity() : Bool; function setCustomValidity( error : String ) : Void; diff --git a/std/js/html/InputEvent.hx b/std/js/html/InputEvent.hx index c8ab1702..e2be4261 100644 --- a/std/js/html/InputEvent.hx +++ b/std/js/html/InputEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/InputEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\InputEvent.webidl. Do not edit! package js.html; +/** + The `InputEvent` interface represents an event notifying of editable content change. + + Documentation [InputEvent](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("InputEvent") extern class InputEvent extends UIEvent { + + /** + Returns a `Boolean` value indicating if the event is fired after `compositionstart` and before `compositionend`. + **/ var isComposing(default,null) : Bool; /** @throws DOMError */ diff --git a/std/js/html/InputEventInit.hx b/std/js/html/InputEventInit.hx index 0e9738f4..ecde91eb 100644 --- a/std/js/html/InputEventInit.hx +++ b/std/js/html/InputEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/InputEvent.webidl line 13:0. Do not edit! +// This file is generated from mozilla\InputEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/Int16Array.hx b/std/js/html/Int16Array.hx index 2e1b664d..ef0c92bd 100644 --- a/std/js/html/Int16Array.hx +++ b/std/js/html/Int16Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl line 99:0. Do not edit! +// This file is generated from typedarray.webidl. Do not edit! package js.html; @@ -36,9 +36,7 @@ extern class Int16Array extends ArrayBufferView implements ArrayAccess @:overload( function( array : Int16Array ) : Void {} ) @:overload( function( array : Array ) : Void {} ) function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; - function get( index : Int ) : Int; - @:overload( function( index : Int, value : Int ) : Void {} ) @:overload( function( array : Int16Array, ?offset : Int ) : Void {} ) function set( array : Array, ?offset : Int ) : Void; - function subarray( start : Int, end : Int ) : Int16Array; + function subarray( start : Int, ?end : Int ) : Int16Array; } \ No newline at end of file diff --git a/std/js/html/Int32Array.hx b/std/js/html/Int32Array.hx index e984b262..5bb64340 100644 --- a/std/js/html/Int32Array.hx +++ b/std/js/html/Int32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl line 139:0. Do not edit! +// This file is generated from typedarray.webidl. Do not edit! package js.html; @@ -36,9 +36,7 @@ extern class Int32Array extends ArrayBufferView implements ArrayAccess @:overload( function( array : Int32Array ) : Void {} ) @:overload( function( array : Array ) : Void {} ) function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; - function get( index : Int ) : Int; - @:overload( function( index : Int, value : Int ) : Void {} ) @:overload( function( array : Int32Array, ?offset : Int ) : Void {} ) function set( array : Array, ?offset : Int ) : Void; - function subarray( start : Int, end : Int ) : Int32Array; + function subarray( start : Int, ?end : Int ) : Int32Array; } \ No newline at end of file diff --git a/std/js/html/Int8Array.hx b/std/js/html/Int8Array.hx index 9738deba..777a31cb 100644 --- a/std/js/html/Int8Array.hx +++ b/std/js/html/Int8Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl line 37:0. Do not edit! +// This file is generated from typedarray.webidl. Do not edit! package js.html; @@ -36,9 +36,7 @@ extern class Int8Array extends ArrayBufferView implements ArrayAccess @:overload( function( array : Int8Array ) : Void {} ) @:overload( function( array : Array ) : Void {} ) function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; - function get( index : Int ) : Int; - @:overload( function( index : Int, value : Int ) : Void {} ) @:overload( function( array : Int8Array, ?offset : Int ) : Void {} ) function set( array : Array, ?offset : Int ) : Void; - function subarray( start : Int, end : Int ) : Int8Array; + function subarray( start : Int, ?end : Int ) : Int8Array; } \ No newline at end of file diff --git a/std/js/html/IterationCompositeOperation.hx b/std/js/html/IterationCompositeOperation.hx new file mode 100644 index 00000000..ffeaea4f --- /dev/null +++ b/std/js/html/IterationCompositeOperation.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\KeyframeEffect.webidl. Do not edit! + +package js.html; + +@:enum abstract IterationCompositeOperation(String) +{ + var REPLACE = "replace"; + var ACCUMULATE = "accumulate"; +} \ No newline at end of file diff --git a/std/js/html/KeyEvent.hx b/std/js/html/KeyEvent.hx index f7cdf940..163e2106 100644 --- a/std/js/html/KeyEvent.hx +++ b/std/js/html/KeyEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/KeyEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\KeyEvent.webidl. Do not edit! package js.html; @@ -213,6 +213,5 @@ extern class KeyEvent static inline var DOM_VK_PA1 : Int = 253; static inline var DOM_VK_WIN_OEM_CLEAR : Int = 254; - /** @throws DOMError */ function initKeyEvent( type : String, canBubble : Bool, cancelable : Bool, view : Window, ctrlKey : Bool, altKey : Bool, shiftKey : Bool, metaKey : Bool, keyCode : Int, charCode : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/KeyboardEvent.hx b/std/js/html/KeyboardEvent.hx index 9a72e409..3ac8d4fc 100644 --- a/std/js/html/KeyboardEvent.hx +++ b/std/js/html/KeyboardEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/KeyboardEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\KeyboardEvent.webidl. Do not edit! package js.html; +/** + `KeyboardEvent` objects describe a user interaction with the keyboard. Each event describes a key; the event type (`keydown`, `keypress`, or `keyup`) identifies what kind of activity was performed. + + Documentation [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("KeyboardEvent") extern class KeyboardEvent extends UIEvent { @@ -31,8 +38,6 @@ extern class KeyboardEvent extends UIEvent static inline var DOM_KEY_LOCATION_LEFT : Int = 1; static inline var DOM_KEY_LOCATION_RIGHT : Int = 2; static inline var DOM_KEY_LOCATION_NUMPAD : Int = 3; - static inline var DOM_KEY_LOCATION_MOBILE : Int = 4; - static inline var DOM_KEY_LOCATION_JOYSTICK : Int = 5; static inline var DOM_VK_CANCEL : Int = 3; static inline var DOM_VK_HELP : Int = 6; static inline var DOM_VK_BACK_SPACE : Int = 8; @@ -219,20 +224,71 @@ extern class KeyboardEvent extends UIEvent static inline var DOM_VK_PA1 : Int = 253; static inline var DOM_VK_WIN_OEM_CLEAR : Int = 254; + + /** + Returns a `Number` representing the Unicode reference number of the key; this attribute is used only by the `keypress` event. For keys whose `char` attribute contains multiple characters, this is the Unicode value of the first character in that attribute. In Firefox 26 this returns codes for printable characters. + Warning: This attribute is deprecated; you should use `KeyboardEvent.key` instead, if available. + + **/ var charCode(default,null) : Int; + + /** + Returns a `Number` representing a system and implementation dependent numerical code identifying the unmodified value of the pressed key. + Warning: This attribute is deprecated; you should use `KeyboardEvent.key` instead, if available. + + **/ var keyCode(default,null) : Int; + + /** + Returns a `Boolean` that is `true` if the Alt ( Option or ⌥ on OS X) key was active when the key event was generated. + **/ var altKey(default,null) : Bool; + + /** + Returns a `Boolean` that is `true` if the Ctrl key was active when the key event was generated. + **/ var ctrlKey(default,null) : Bool; + + /** + Returns a `Boolean` that is `true` if the Shift key was active when the key event was generated. + **/ var shiftKey(default,null) : Bool; + + /** + Returns a `Boolean` that is `true` if the Meta key (on Mac keyboards, the ⌘ Command key; on Windows keyboards, the Windows key (⊞)) was active when the key event was generated. + **/ var metaKey(default,null) : Bool; + + /** + Returns a `Number` representing the location of the key on the keyboard or other input device. + **/ var location(default,null) : Int; + + /** + Returns a `Boolean` that is `true` if the key is being held down such that it is automatically repeating. + **/ var repeat(default,null) : Bool; + + /** + Returns a `Boolean` that is `true` if the event is fired between after `compositionstart` and before `compositionend`. + **/ var isComposing(default,null) : Bool; + + /** + Returns a `DOMString` representing the key value of the key represented by the event. + **/ var key(default,null) : String; /** @throws DOMError */ function new( typeArg : String, ?keyboardEventInitDict : KeyboardEventInit ) : Void; + + /** + Returns a `Boolean` indicating if the modifier key, like Alt, Shift, Ctrl, or Meta, was pressed when the event was created. + **/ function getModifierState( key : String ) : Bool; - /** @throws DOMError */ + + /** + Initializes a `KeyboardEvent` object. This has only been implemented by Gecko (others used `KeyboardEvent.initKeyboardEvent()`) and should not be used any more. The standard modern way is to use the `KeyboardEvent.KeyboardEvent` constructor. + **/ function initKeyEvent( type : String, canBubble : Bool, cancelable : Bool, view : Window, ctrlKey : Bool, altKey : Bool, shiftKey : Bool, metaKey : Bool, keyCode : Int, charCode : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/KeyboardEventInit.hx b/std/js/html/KeyboardEventInit.hx index 6b50299c..cc0d151d 100644 --- a/std/js/html/KeyboardEventInit.hx +++ b/std/js/html/KeyboardEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,23 +20,19 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/KeyboardEvent.webidl line 36:0. Do not edit! +// This file is generated from mozilla\KeyboardEvent.webidl. Do not edit! package js.html; typedef KeyboardEventInit = { - > UIEventInit, - @:optional var altKey : Bool; + > EventModifierInit, @:optional var charCode : Int; @:optional var code : String; - @:optional var ctrlKey : Bool; @:optional var isComposing : Bool; @:optional var key : String; @:optional var keyCode : Int; @:optional var location : Int; - @:optional var metaKey : Bool; @:optional var repeat : Bool; - @:optional var shiftKey : Bool; @:optional var which : Int; } \ No newline at end of file diff --git a/std/js/html/KeyframeEffect.hx b/std/js/html/KeyframeEffect.hx new file mode 100644 index 00000000..7463cf95 --- /dev/null +++ b/std/js/html/KeyframeEffect.hx @@ -0,0 +1,39 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\KeyframeEffect.webidl. Do not edit! + +package js.html; + +/** + The `KeyframeEffect` interface of the Web Animations API lets us create sets of animatable properties and values, called keyframes. These can then be played using the `Animation()` constructor. + + Documentation [KeyframeEffect](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("KeyframeEffect") +extern class KeyframeEffect extends KeyframeEffectReadOnly +{ + /** @throws DOMError */ + function new( target : haxe.extern.EitherType, frames : Dynamic, ?options : haxe.extern.EitherType ) : Void; +} \ No newline at end of file diff --git a/std/js/html/KeyframeEffectReadOnly.hx b/std/js/html/KeyframeEffectReadOnly.hx new file mode 100644 index 00000000..1601473c --- /dev/null +++ b/std/js/html/KeyframeEffectReadOnly.hx @@ -0,0 +1,62 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\KeyframeEffect.webidl. Do not edit! + +package js.html; + +/** + The `KeyframeEffectReadOnly` interface of the Web Animations API describes sets of animatable properties and values that can be played using the `Animation.Animation()` constructor, and which are inherited by `KeyframeEffect`. + + Documentation [KeyframeEffectReadOnly](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffectReadOnly) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffectReadOnly$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("KeyframeEffectReadOnly") +extern class KeyframeEffectReadOnly extends AnimationEffectReadOnly +{ + + /** + The element or pseudo-element being animated by this object. This may be `null` for animations that do not target a specific element. + **/ + var target(default,null) : haxe.extern.EitherType; + + /** + The iteration composite operation for resolving the property value changes of this keyframe effect. + **/ + var iterationComposite(default,null) : IterationCompositeOperation; + + /** + The composite operation property for resolving the property value changes between this and other keyframe effects. + **/ + var composite(default,null) : CompositeOperation; + + /** + The temporal spacing of the keyframe effect's iterations + **/ + var spacing(default,null) : String; + + /** @throws DOMError */ + function new( target : haxe.extern.EitherType, frames : Dynamic, ?options : haxe.extern.EitherType ) : Void; + /** @throws DOMError */ + function getFrames() : Array; +} \ No newline at end of file diff --git a/std/js/html/LIElement.hx b/std/js/html/LIElement.hx index d37929cf..6f2d582c 100644 --- a/std/js/html/LIElement.hx +++ b/std/js/html/LIElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLLIElement.webidl line 16:0. Do not edit! +// This file is generated from mozilla\HTMLLIElement.webidl. Do not edit! package js.html; +/** + The `HTMLLIElement` interface expose specific properties and methods (beyond those defined by regular `HTMLElement` interface it also has available to it by inheritance) for manipulating list elements. + + Documentation [HTMLLIElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLIElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLIElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLLIElement") extern class LIElement extends Element { + + /** + Is a `long` indicating the ordinal position of the list element inside a given `ol`. It reflects the `value` attribute of the HTML `li` element, and can be smaller than `0`. If the `li` element is not a child of an `ol` element, the property has no meaning. + **/ var value : Int; + + /** + Is a `DOMString` representing the type of the bullets, `"disc"`, `"square"` or `"circle"`. As the standard way of defining the list type is via the CSS `list-style-type` property, use the CSSOM methods to set it via a script. + **/ var type : String; } \ No newline at end of file diff --git a/std/js/html/LabelElement.hx b/std/js/html/LabelElement.hx index d2b2a57c..1dbcff2b 100644 --- a/std/js/html/LabelElement.hx +++ b/std/js/html/LabelElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLLabelElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLLabelElement.webidl. Do not edit! package js.html; +/** + The `HTMLLabelElement` interface gives access to properties specific to `label` elements. It inherits methods and properties from the base `HTMLElement` interface. + + Documentation [HTMLLabelElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLLabelElement") extern class LabelElement extends Element { + + /** + Is a `HTMLFormElement` object representing the form with which the labeled control is associated, or `null` if there is no associated control, or if that control isn't associated with a form. In other words, this is just a shortcut for `HTMLLabelElement.control.form`. + **/ var form(default,null) : FormElement; + + /** + Is a string containing the ID of the labeled control. This reflects the `for` attribute. + **/ var htmlFor : String; + + /** + Is a `HTMLElement` representing the control with which the label is associated. + **/ var control(default,null) : Element; } \ No newline at end of file diff --git a/std/js/html/LegendElement.hx b/std/js/html/LegendElement.hx index ed688fac..fb9de635 100644 --- a/std/js/html/LegendElement.hx +++ b/std/js/html/LegendElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLLegendElement.webidl line 16:0. Do not edit! +// This file is generated from mozilla\HTMLLegendElement.webidl. Do not edit! package js.html; +/** + The `HTMLLegendElement` is an interface allowing to access properties of the `legend` elements. It inherits properties and methods from the `HTMLElement` interface. + + Documentation [HTMLLegendElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLegendElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLegendElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLLegendElement") extern class LegendElement extends Element { diff --git a/std/js/html/LifecycleCallbacks.hx b/std/js/html/LifecycleCallbacks.hx index 3627ac3b..cc0d09a9 100644 --- a/std/js/html/LifecycleCallbacks.hx +++ b/std/js/html/LifecycleCallbacks.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebComponents.webidl line 18:0. Do not edit! +// This file is generated from mozilla\WebComponents.webidl. Do not edit! package js.html; diff --git a/std/js/html/LinkElement.hx b/std/js/html/LinkElement.hx index dcd64e2c..20edd9ce 100644 --- a/std/js/html/LinkElement.hx +++ b/std/js/html/LinkElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,27 +20,83 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLLinkElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLLinkElement.webidl. Do not edit! package js.html; +/** + The `HTMLLinkElement` interface represents reference information for external resources and the relationship of those resources to a document and vice-versa. This object inherits all of the properties and methods of the `HTMLElement` interface. + + Documentation [HTMLLinkElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLinkElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLinkElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLLinkElement") extern class LinkElement extends Element { + + /** + Is a `Boolean` which represents whether the link is disabled; currently only used with style sheet links. + **/ var disabled : Bool; + + /** + Is a `DOMString` representing the URI for the target resource. + **/ var href : String; + + /** + Is a `DOMString` that corresponds to the CORS setting for this link element. See CORS settings attributes for details. + **/ var crossOrigin : String; + + /** + Is a `DOMString` representing the forward relationship of the linked resource from the document to the resource. + **/ var rel : String; + + /** + Is a `DOMTokenList` that reflects the `rel` HTML attribute, as a list of tokens. + **/ var relList(default,null) : DOMTokenList; + + /** + Is a `DOMString` representing a list of one or more media formats to which the resource applies. + **/ var media : String; + + /** + Is a `DOMString` representing the language code for the linked resource. + **/ var hreflang : String; + + /** + Is a `DOMString` representing the MIME type of the linked resource. + **/ var type : String; - var sizes(default,null) : DOMSettableTokenList; + + /** + Is a `DOMSettableTokenList` that reflects the `sizes` HTML attribute, as a list of tokens. + **/ + var sizes(default,null) : DOMTokenList; + + /** + Is a `DOMString` representing the character encoding for the target resource. + **/ var charset : String; + + /** + Is a `DOMString` representing the reverse relationship of the linked resource from the resource to the document. + **/ var rev : String; + + /** + Is a `DOMString` representing the name of the target frame to which the resource applies. + **/ var target : String; @:native("import") var import_(default,null) : HTMLDocument; + var integrity : String; var sheet(default,null) : StyleSheet; } \ No newline at end of file diff --git a/std/js/html/LocalMediaStream.hx b/std/js/html/LocalMediaStream.hx index 66f457b2..a046321f 100644 --- a/std/js/html/LocalMediaStream.hx +++ b/std/js/html/LocalMediaStream.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,12 +20,23 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/LocalMediaStream.webidl line 13:0. Do not edit! +// This file is generated from mozilla\LocalMediaStream.webidl. Do not edit! package js.html; +/** + The `LocalMediaStream` interface represents a stream of media content fetched from a local data source. This is the interface returned by `getUserMedia()`. + + Documentation [LocalMediaStream](https://developer.mozilla.org/en-US/docs/Web/API/LocalMediaStream) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/LocalMediaStream$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("LocalMediaStream") extern class LocalMediaStream extends MediaStream { + + /** + Stops the stream. When the source of the stream is a connected device (such as a camera or microphone), stops capture on the device. + **/ function stop() : Void; } \ No newline at end of file diff --git a/std/js/html/Location.hx b/std/js/html/Location.hx index 7b6d2d49..8686bcf4 100644 --- a/std/js/html/Location.hx +++ b/std/js/html/Location.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,29 +20,82 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Location.webidl line 15:0. Do not edit! +// This file is generated from mozilla\Location.webidl. Do not edit! package js.html; +/** + The `Location` interface represents the location (URL) of the object it is linked to. Changes done on it are reflected on the object it relates to. Both the `Document` and `Window` interface have such a linked `Location`, accessible via `Document.location` and `Window.location` respectively. + + Documentation [Location](https://developer.mozilla.org/en-US/docs/Web/API/Location) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Location$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Location") extern class Location { + + /** + Is a `DOMString` containing the entire URL. If changed, the associated document navigates to the new page. It can be set from a different origin than the associated document. + **/ var href : String; + + /** + Returns a `DOMString` containing the canonical form of the origin of the specific location. + **/ var origin(default,null) : String; + + /** + Is a `DOMString` containing the protocol scheme of the URL, including the final `':'`. + **/ var protocol : String; - var username : String; - var password : String; + + /** + Is a `DOMString` containing the host, that is the hostname, a `':'`, and the port of the URL. + **/ var host : String; + + /** + Is a `DOMString` containing the domain of the URL. + **/ var hostname : String; + + /** + Is a `DOMString` containing the port number of the URL. + **/ var port : String; + + /** + Is a `DOMString` containing an initial `'/'` followed by the path of the URL. + **/ var pathname : String; + + /** + Is a `DOMString` containing a `'?'` followed by the parameters of the URL. Also known as "querystring". + **/ var search : String; + + /** + Is a `DOMString` containing a `'#'` followed by the fragment identifier of the URL. + **/ var hash : String; /** @throws DOMError */ + + /** + Loads the resource at the URL provided in parameter. + **/ function assign( url : String ) : Void; /** @throws DOMError */ + + /** + Replaces the current resource with the one at the provided URL. The difference from the `assign()` method is that after using `replace()` the current page will not be saved in session `History`, meaning the user won't be able to use the back button to navigate to it. + **/ function replace( url : String ) : Void; /** @throws DOMError */ + + /** + Reloads the resource from the current URL. Its optional unique parameter is a `Boolean`, which, when it is `true`, causes the page to always be reloaded from the server. If it is `false` or not specified, the browser may reload the page from its cache. + **/ function reload( ?forceget : Bool = false ) : Void; } \ No newline at end of file diff --git a/std/js/html/MapElement.hx b/std/js/html/MapElement.hx index 2de2f297..672e2581 100644 --- a/std/js/html/MapElement.hx +++ b/std/js/html/MapElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLMapElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLMapElement.webidl. Do not edit! package js.html; +/** + The `HTMLMapElement` interface provides special properties and methods (beyond those of the regular object `HTMLElement` interface it also has available to it by inheritance) for manipulating the layout and presentation of map elements. + + Documentation [HTMLMapElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMapElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMapElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLMapElement") extern class MapElement extends Element { + + /** + Is a `DOMString` representing the `map` element for referencing it other context. If the `id` attribute is set, this must have the same value; and it cannot be `null` or empty. + **/ var name : String; + + /** + Is a live `HTMLCollection` representing the `area` elements associated to this `map`. + **/ var areas(default,null) : HTMLCollection; } \ No newline at end of file diff --git a/std/js/html/MediaElement.hx b/std/js/html/MediaElement.hx index adb33529..21fb1b0a 100644 --- a/std/js/html/MediaElement.hx +++ b/std/js/html/MediaElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLMediaElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLMediaElement.webidl. Do not edit! package js.html; +/** + The `HTMLMediaElement` interface adds to `HTMLElement` the properties and methods needed to support basic media-related capabilities that are common to audio and video. The `HTMLVideoElement` and `HTMLAudioElement` elements both inherit this interface. + + Documentation [HTMLMediaElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLMediaElement") extern class MediaElement extends Element { @@ -37,44 +44,177 @@ extern class MediaElement extends Element static inline var HAVE_FUTURE_DATA : Int = 3; static inline var HAVE_ENOUGH_DATA : Int = 4; + + /** + Returns a `MediaError` object for the most recent error, or `null` if there has not been an error. + **/ var error(default,null) : MediaError; + + /** + Is a `DOMString` that reflects the `src` HTML attribute, which contains the URL of a media resource to use. + **/ var src : String; + + /** + Returns a `DOMString` with the absolute URL of the chosen media resource. + **/ var currentSrc(default,null) : String; + + /** + Is a `DOMString` indicating the CORS setting for this media element. + **/ var crossOrigin : String; + + /** + Returns a `unsigned short` (enumeration) indicating the current state of fetching the media over the network. + **/ var networkState(default,null) : Int; + + /** + Is a `DOMString` that reflects the `preload` HTML attribute, indicating what data should be preloaded, if any. Possible values are: `none`, `metadata`, `auto`. + **/ var preload : String; + + /** + Returns a `TimeRanges` object that indicates the ranges of the media source that the browser has buffered (if any) at the moment the `buffered` property is accessed. + **/ var buffered(default,null) : TimeRanges; + + /** + Returns a `unsigned short` (enumeration) indicating the readiness state of the media. + **/ var readyState(default,null) : Int; + + /** + Returns a `Boolean` that indicates whether the media is in the process of seeking to a new position. + **/ var seeking(default,null) : Bool; + + /** + Is a `double` indicating the current playback time in seconds. Setting this value seeks the media to the new time. + **/ var currentTime : Float; + + /** + Returns a `double` indicating the length of the media in seconds, or 0 if no media data is available. + **/ var duration(default,null) : Float; + + /** + Returns a `Boolean` that indicates whether the media element is paused. + **/ var paused(default,null) : Bool; + + /** + Is a `double` indicating the default playback rate for the media. + **/ var defaultPlaybackRate : Float; + + /** + Is a `double` that indicates the rate at which the media is being played back.  + **/ var playbackRate : Float; + + /** + Returns a `TimeRanges` object that contains the ranges of the media source that the browser has played, if any. + **/ var played(default,null) : TimeRanges; + + /** + Returns a `TimeRanges` object that contains the time ranges that the user is able to seek to, if any. + **/ var seekable(default,null) : TimeRanges; + + /** + Returns a `Boolean` that indicates whether the media element has finished playing. + **/ var ended(default,null) : Bool; + + /** + Is a `Boolean` that reflects the `autoplay` HTML attribute, indicating whether playback should automatically begin as soon as enough media is available to do so without interruption. + **/ var autoplay : Bool; + + /** + Is a `Boolean` that reflects the `loop` HTML attribute, which indicates whether the media element should start over when it reaches the end. + **/ var loop : Bool; + + /** + Is a `Boolean` that reflects the `controls` HTML attribute, indicating whether user interface items for controlling the resource should be displayed. + **/ var controls : Bool; + + /** + Is a `double` indicating the audio volume, from 0.0 (silent) to 1.0 (loudest). + **/ var volume : Float; + + /** + Is a `Boolean` that determines whether audio is muted. `true` if the audio is muted and `false` otherwise. + **/ var muted : Bool; + + /** + Is a `Boolean` that reflects the `muted` HTML attribute, which indicates whether the media element's audio output should be muted by default. + **/ var defaultMuted : Bool; + + /** + Is a `AudioTrackList` that lists the `AudioTrack` objects contained in the element. + **/ var audioTracks(default,null) : AudioTrackList; + + /** + Returns the list of `VideoTrack` objects contained in the element. + + Note: Gecko supports only single track playback, and the parsing of tracks' metadata is only available for media with the Ogg container format. + + + **/ var videoTracks(default,null) : VideoTrackList; + + /** + Returns the list of `TextTrack` objects contained in the element. + **/ var textTracks(default,null) : TextTrackList; - var mediaKeys(default,null) : MediaKeys; - var onencrypted : haxe.Constraints.Function; - var waitingFor(default,null) : MediaWaitingFor; + /** + Is a `MediaStream` representing the media to play or that has played in the current `HTMLMediaElement`. + **/ + var srcObject : MediaStream; + + + /** + Resets the media element and restarts the media resource. Any pending events are discarded. How much media data is fetched is still affected by the `preload` attribute. This method can be useful for releasing resources after any `src` attribute and `source` element descendants have been removed. Otherwise, it is usually unnecessary to use this method, unless required to rescan `source` element children after dynamic changes. + **/ function load() : Void; + + /** + Determines whether the specified media type can be played back. + **/ function canPlayType( type : String ) : String; /** @throws DOMError */ + + /** + Directly seeks to the given time. + **/ function fastSeek( time : Float ) : Void; /** @throws DOMError */ + + /** + Begins playback of the media. + **/ function play() : Void; /** @throws DOMError */ + + /** + Pauses the media playback. + **/ function pause() : Void; + + /** + Adds a text track (such as a track for subtitles) to a media element. + **/ function addTextTrack( kind : TextTrackKind, ?label : String = "", ?language : String = "" ) : TextTrack; - function setMediaKeys( mediaKeys : MediaKeys ) : Promise; } \ No newline at end of file diff --git a/std/js/html/MediaError.hx b/std/js/html/MediaError.hx index 2a3f66df..44436096 100644 --- a/std/js/html/MediaError.hx +++ b/std/js/html/MediaError.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaError.webidl line 14:0. Do not edit! +// This file is generated from mozilla\MediaError.webidl. Do not edit! package js.html; +/** + The `MediaError` interface represents an error associated to a media, like a `HTMLMediaElement`. + + Documentation [MediaError](https://developer.mozilla.org/en-US/docs/Web/API/MediaError) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MediaError$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MediaError") extern class MediaError { @@ -32,6 +39,42 @@ extern class MediaError static inline var MEDIA_ERR_DECODE : Int = 3; static inline var MEDIA_ERR_SRC_NOT_SUPPORTED : Int = 4; + + /** + An unsigned short that represents the error: + + + + Name + Value + Description + + + + + + + + + + + + + + + + + + + + + + + + +
MEDIA_ERR_ABORTED1The fetching of the associated ressource has been aborted by the user
MEDIA_ERR_NETWORK2A network error caused the ressource to stop being fetched.
MEDIA_ERR_DECODE3A decoding error caused the ressource to stop being fetched.
MEDIA_ERR_SRC_NOT_SUPPORTED4The associated ressource has been detected to be not suitable.
+ + **/ var code(default,null) : Int; } \ No newline at end of file diff --git a/std/js/html/MediaKeyMessageEventInit.hx b/std/js/html/MediaKeyMessageEventInit.hx deleted file mode 100644 index 03ef760e..00000000 --- a/std/js/html/MediaKeyMessageEventInit.hx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C)2005-2015 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. - */ - -// This file is generated from mozilla/MediaKeyMessageEvent.webidl line 26:0. Do not edit! - -package js.html; - -typedef MediaKeyMessageEventInit = -{ - > EventInit, - @:optional var message : ArrayBuffer; - @:optional var messageType : MediaKeyMessageType; -} \ No newline at end of file diff --git a/std/js/html/MediaKeyMessageType.hx b/std/js/html/MediaKeyMessageType.hx deleted file mode 100644 index 3f8f38a1..00000000 --- a/std/js/html/MediaKeyMessageType.hx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C)2005-2015 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. - */ - -// This file is generated from mozilla/MediaKeyMessageEvent.webidl line 13:0. Do not edit! - -package js.html; - -@:enum abstract MediaKeyMessageType(String) -{ - var LICENSE_REQUEST = "license-request"; - var LICENSE_RENEWAL = "license-renewal"; - var LICENSE_RELEASE = "license-release"; -} \ No newline at end of file diff --git a/std/js/html/MediaKeySession.hx b/std/js/html/MediaKeySession.hx deleted file mode 100644 index e7cbf8f2..00000000 --- a/std/js/html/MediaKeySession.hx +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C)2005-2015 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. - */ - -// This file is generated from mozilla/MediaKeySession.webidl line 14:0. Do not edit! - -package js.html; - -@:native("MediaKeySession") -extern class MediaKeySession extends EventTarget -{ - var error(default,null) : MediaKeyError; - var keySystem(default,null) : String; - var sessionId(default,null) : String; - var expiration(default,null) : Float; - var closed(default,null) : Promise; - - function generateRequest( initDataType : String, initData : haxe.extern.EitherType ) : Promise; - function load( sessionId : String ) : Promise; - function update( response : haxe.extern.EitherType ) : Promise; - function close() : Promise; - function remove() : Promise; - function getUsableKeyIds() : Promise>; -} \ No newline at end of file diff --git a/std/js/html/MediaKeyStatusMapIterator.hx b/std/js/html/MediaKeyStatusMapIterator.hx new file mode 100644 index 00000000..22e9ed07 --- /dev/null +++ b/std/js/html/MediaKeyStatusMapIterator.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\MediaKeyStatusMap.webidl. Do not edit! + +package js.html; + +@:native("MediaKeyStatusMapIterator") +extern class MediaKeyStatusMapIterator +{ + /** @throws DOMError */ + function next() : Dynamic; +} \ No newline at end of file diff --git a/std/js/html/MediaKeySystemAccess.hx b/std/js/html/MediaKeySystemAccess.hx deleted file mode 100644 index 0295ac77..00000000 --- a/std/js/html/MediaKeySystemAccess.hx +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C)2005-2015 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. - */ - -// This file is generated from mozilla/MediaKeySystemAccess.webidl line 30:0. Do not edit! - -package js.html; - -@:native("MediaKeySystemAccess") -extern class MediaKeySystemAccess -{ - var keySystem(default,null) : String; - - function createMediaKeys() : Promise; -} \ No newline at end of file diff --git a/std/js/html/MediaKeySystemOptions.hx b/std/js/html/MediaKeySystemOptions.hx deleted file mode 100644 index 6f376da7..00000000 --- a/std/js/html/MediaKeySystemOptions.hx +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C)2005-2015 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. - */ - -// This file is generated from mozilla/MediaKeySystemAccess.webidl line 19:0. Do not edit! - -package js.html; - -typedef MediaKeySystemOptions = -{ - @:optional var audioCapability : String; - @:optional var audioType : String; - @:optional var initDataType : String; - @:optional var stateful : Dynamic/*MISSING MediaKeysRequirement*/; - @:optional var uniqueidentifier : Dynamic/*MISSING MediaKeysRequirement*/; - @:optional var videoCapability : String; - @:optional var videoType : String; -} \ No newline at end of file diff --git a/std/js/html/MediaList.hx b/std/js/html/MediaList.hx index a9806cc9..2c9632cf 100644 --- a/std/js/html/MediaList.hx +++ b/std/js/html/MediaList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaList.webidl line 9:0. Do not edit! +// This file is generated from mozilla\MediaList.webidl. Do not edit! package js.html; diff --git a/std/js/html/MediaQueryList.hx b/std/js/html/MediaQueryList.hx index c847c52b..43a24b12 100644 --- a/std/js/html/MediaQueryList.hx +++ b/std/js/html/MediaQueryList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaQueryList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\MediaQueryList.webidl. Do not edit! package js.html; +/** + A `MediaQueryList` object maintains a list of media queries on a `document`, and handles sending notifications to listeners when the media queries on the document change. + + Documentation [MediaQueryList](https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MediaQueryList") extern class MediaQueryList { diff --git a/std/js/html/MediaRecorder.hx b/std/js/html/MediaRecorder.hx index caa58109..5f79ea5b 100644 --- a/std/js/html/MediaRecorder.hx +++ b/std/js/html/MediaRecorder.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,39 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaRecorder.webidl line 18:0. Do not edit! +// This file is generated from mozilla\MediaRecorder.webidl. Do not edit! package js.html; +/** + The `MediaRecorder` interface of the MediaStream Recording API provides functionality to easily record media. It is created by the invocation of the `MediaRecorder()` constructor. + + Documentation [MediaRecorder](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MediaRecorder") extern class MediaRecorder extends EventTarget { + static + /** +  Returns a `Boolean` value indicating if the given MIME type is supported by the current user agent .  + **/ + function isTypeSupported( type : String ) : Bool; + + /** + Returns the stream that was passed into the constructor when the `MediaRecorder` was created. + **/ var stream(default,null) : MediaStream; + + /** + Returns the current state of the `MediaRecorder` object (`inactive`, `recording`, or `paused`.) + **/ var state(default,null) : RecordingState; + + /** + Returns the MIME type that was selected as the recording container for the `MediaRecorder` object when it was created. + **/ var mimeType(default,null) : String; var ondataavailable : haxe.Constraints.Function; var onerror : haxe.Constraints.Function; @@ -40,13 +64,33 @@ extern class MediaRecorder extends EventTarget @:overload( function( stream : MediaStream, ?options : MediaRecorderOptions ) : Void {} ) function new( node : js.html.audio.AudioNode, ?output : Int = 0, ?options : MediaRecorderOptions ) : Void; /** @throws DOMError */ + + /** + Begins recording media; this method can optionally be passed a `timeslice` argument with a value in milliseconds. If this is specified, the media will be captured in separate chunks of that duration, rather than the default behavior of recording the media in a single large chunk. + **/ function start( ?timeSlice : Int ) : Void; /** @throws DOMError */ + + /** + Stops recording, at which point a `dataavailable` event containing the final `Blob` of saved data is fired. No more recording occurs. + **/ function stop() : Void; /** @throws DOMError */ + + /** + Pauses the recording of media. + **/ function pause() : Void; /** @throws DOMError */ + + /** + Resumes recording of media after having been paused. + **/ function resume() : Void; /** @throws DOMError */ + + /** + Requests a `Blob` containing the saved data received thus far (or since the last time `requestData()` was called. After calling this method, recording continues, but in a new `Blob`. + **/ function requestData() : Void; } \ No newline at end of file diff --git a/std/js/html/MediaRecorderOptions.hx b/std/js/html/MediaRecorderOptions.hx index 9ede33d4..1884f3e8 100644 --- a/std/js/html/MediaRecorderOptions.hx +++ b/std/js/html/MediaRecorderOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,14 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaRecorder.webidl line 52:0. Do not edit! +// This file is generated from mozilla\MediaRecorder.webidl. Do not edit! package js.html; typedef MediaRecorderOptions = { + @:optional var audioBitsPerSecond : Int; + @:optional var bitsPerSecond : Int; @:optional var mimeType : String; + @:optional var videoBitsPerSecond : Int; } \ No newline at end of file diff --git a/std/js/html/MediaSource.hx b/std/js/html/MediaSource.hx index 46f40839..52554005 100644 --- a/std/js/html/MediaSource.hx +++ b/std/js/html/MediaSource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,25 +20,64 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaSource.webidl line 25:0. Do not edit! +// This file is generated from mozilla\MediaSource.webidl. Do not edit! package js.html; +/** + The `MediaSource` interface represents a source of media data for an `HTMLMediaElement` object. A `MediaSource` object can be attached to a `HTMLMediaElement` to be played in the user agent. + + Documentation [MediaSource](https://developer.mozilla.org/en-US/docs/Web/API/MediaSource) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MediaSource$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MediaSource") extern class MediaSource extends EventTarget { - static function isTypeSupported( type : String ) : Bool; + static + /** + Returns a `Boolean` value indicating if the given MIME type is supported by the current user agent — this is, if it can successfully create `SourceBuffer` objects for that MIME type. + **/ + function isTypeSupported( type : String ) : Bool; + + /** + Returns a `SourceBufferList` object containing the list of `SourceBuffer` objects associated with this `MediaSource`. + **/ var sourceBuffers(default,null) : SourceBufferList; + + /** + Returns a `SourceBufferList` object containing a subset of the `SourceBuffer` objects contained within `SourceBuffers` — the list of objects providing the selected video track,  enabled audio tracks, and shown/hidden text tracks. + **/ var activeSourceBuffers(default,null) : SourceBufferList; + + /** + Returns an enum representing the state of the current `MediaSource`, whether it is not currently attached to a media element (`closed`), attached and ready to receive `SourceBuffer` objects (`open`), or attached but the stream has been ended via `MediaSource.endOfStream()` (`ended`.) + **/ var readyState(default,null) : MediaSourceReadyState; + + /** + Gets and sets the duration of the current media being presented. + **/ var duration : Float; /** @throws DOMError */ function new() : Void; /** @throws DOMError */ + + /** + Creates a new `SourceBuffer` of the given MIME type and adds it to the `MediaSource`'s `SourceBuffers` list. + **/ function addSourceBuffer( type : String ) : SourceBuffer; /** @throws DOMError */ + + /** + Removes the given `SourceBuffer` from the `SourceBuffers` list associated with this `MediaSource` object. + **/ function removeSourceBuffer( sourceBuffer : SourceBuffer ) : Void; /** @throws DOMError */ + + /** + Signals the end of the stream. + **/ function endOfStream( ?error : MediaSourceEndOfStreamError ) : Void; } \ No newline at end of file diff --git a/std/js/html/MediaSourceEndOfStreamError.hx b/std/js/html/MediaSourceEndOfStreamError.hx index 773aae35..6c4f437b 100644 --- a/std/js/html/MediaSourceEndOfStreamError.hx +++ b/std/js/html/MediaSourceEndOfStreamError.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaSource.webidl line 19:0. Do not edit! +// This file is generated from mozilla\MediaSource.webidl. Do not edit! package js.html; diff --git a/std/js/html/MediaSourceReadyState.hx b/std/js/html/MediaSourceReadyState.hx index d5ddb0cb..73af387f 100644 --- a/std/js/html/MediaSourceReadyState.hx +++ b/std/js/html/MediaSourceReadyState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaSource.webidl line 13:0. Do not edit! +// This file is generated from mozilla\MediaSource.webidl. Do not edit! package js.html; diff --git a/std/js/html/MediaStream.hx b/std/js/html/MediaStream.hx index 50385b21..83db10f9 100644 --- a/std/js/html/MediaStream.hx +++ b/std/js/html/MediaStream.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,50 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaStream.webidl line 30:0. Do not edit! +// This file is generated from mozilla\MediaStream.webidl. Do not edit! package js.html; +/** + The `MediaStream` interface represents a stream of media content. A stream consists of several tracks such as video or audio tracks. Each track is specified as an instance of `MediaStreamTrack`. + + Documentation [MediaStream](https://developer.mozilla.org/en-US/docs/Web/API/MediaStream) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MediaStream$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MediaStream") extern class MediaStream extends EventTarget { + + /** + A `DOMString` containing 36 characters denoting a universally unique identifier (UUID) for the object. + **/ + var id(default,null) : String; var currentTime(default,null) : Float; + /** @throws DOMError */ + @:overload( function() : Void {} ) + @:overload( function( stream : MediaStream ) : Void {} ) + function new( tracks : Array ) : Void; function getAudioTracks() : Array; + + /** + Returns a list of the `MediaStreamTrack` objects stored in the `MediaStream` object that have their `kind` attribute set to `"video"`. The order is not defined, and may not only vary from one browser to another, but also from one call to another. + **/ function getVideoTracks() : Array; + + /** + Returns a list of all `MediaStreamTrack` objects stored in the `MediaStream` object, regardless of the value of the `kind` attribute. The order is not defined, and may not only vary from one browser to another, but also from one call to another. + **/ function getTracks() : Array; + + /** + Stores a copy of the `MediaStreamTrack` given as argument. If the track has already been added to the `MediaStream` object, nothing happens. + **/ + function addTrack( track : MediaStreamTrack ) : Void; + + /** + Removes the `MediaStreamTrack` given as argument. If the track is not part of the MediaStream` object, nothing happens. + **/ + function removeTrack( track : MediaStreamTrack ) : Void; } \ No newline at end of file diff --git a/std/js/html/MediaStreamConstraints.hx b/std/js/html/MediaStreamConstraints.hx index bec5e36a..e270f6ef 100644 --- a/std/js/html/MediaStreamConstraints.hx +++ b/std/js/html/MediaStreamConstraints.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,23 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaStream.webidl line 16:0. Do not edit! +// This file is generated from mozilla\MediaStream.webidl. Do not edit! package js.html; +/** + The `MediaStreamConstraints` dictionary is used when calling `getUserMedia()` to specify what kinds of tracks should be included in the returned `MediaStream`, and, optionally, to establish constraints for those tracks' settings. + + Documentation [MediaStreamConstraints](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ typedef MediaStreamConstraints = { - @:optional var audio : haxe.extern.EitherType; + @:optional var audio : haxe.extern.EitherType; @:optional var fake : Bool; @:optional var fakeTracks : Bool; @:optional var peerIdentity : String; @:optional var picture : Bool; - @:optional var video : haxe.extern.EitherType; + @:optional var video : haxe.extern.EitherType; } \ No newline at end of file diff --git a/std/js/html/MediaStreamError.hx b/std/js/html/MediaStreamError.hx index 64510974..5ddb4144 100644 --- a/std/js/html/MediaStreamError.hx +++ b/std/js/html/MediaStreamError.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaStreamError.webidl line 17:0. Do not edit! +// This file is generated from mozilla\MediaStreamError.webidl. Do not edit! package js.html; @@ -29,6 +29,6 @@ extern class MediaStreamError { var name(default,null) : String; var message(default,null) : String; - var constraintName(default,null) : String; + var constraint(default,null) : String; } \ No newline at end of file diff --git a/std/js/html/MediaStreamTrack.hx b/std/js/html/MediaStreamTrack.hx index 88cbf1c5..c275ed3b 100644 --- a/std/js/html/MediaStreamTrack.hx +++ b/std/js/html/MediaStreamTrack.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,17 +20,42 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaStreamTrack.webidl line 27:0. Do not edit! +// This file is generated from mozilla\MediaStreamTrack.webidl. Do not edit! package js.html; +/** + The `MediaStreamTrack` interface represents a single media track within a stream; typically, these are audio or video tracks, but other track types may exist as well. + + Documentation [MediaStreamTrack](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MediaStreamTrack") -extern class MediaStreamTrack +extern class MediaStreamTrack extends EventTarget { + + /** + Returns a `DOMString` set to `"audio"` if the track is an audio track and to `"video"`, if it is a video track. It doesn't change if the track is deassociated from its source. + **/ var kind(default,null) : String; + + /** + Returns a `DOMString` containing a unique identifier (GUID) for the track; it is generated by the browser. + **/ var id(default,null) : String; + + /** + Returns a `DOMString` containing a user agent-assigned label that identifies the track source, as in `"internal microphone"`. The string may be left empty and is empty as long as no source has been connected. When the track is deassociated from its source, the label is not changed. + **/ var label(default,null) : String; + + /** + A Boolean value with a value of `true` if the track is enabled, that is allowed to render the media source stream; or `false` if it is disabled, that is not rendering the media source stream but silence and blackness. If the track has been disconnected, this value can be changed but has no more effect. + **/ var enabled : Bool; function stop() : Void; + /** @throws DOMError */ + function applyConstraints( ?constraints : MediaTrackConstraints ) : Promise; } \ No newline at end of file diff --git a/std/js/html/MediaTrackConstraintSet.hx b/std/js/html/MediaTrackConstraintSet.hx new file mode 100644 index 00000000..e3a1237a --- /dev/null +++ b/std/js/html/MediaTrackConstraintSet.hx @@ -0,0 +1,42 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\MediaStreamTrack.webidl. Do not edit! + +package js.html; + +typedef MediaTrackConstraintSet = +{ + @:optional var browserWindow : Int; + @:optional var deviceId : haxe.extern.EitherType,Dynamic/*MISSING ConstrainDOMStringParameters*/>>; + @:optional var echoCancellation : haxe.extern.EitherType; + @:optional var facingMode : haxe.extern.EitherType,Dynamic/*MISSING ConstrainDOMStringParameters*/>>; + @:optional var frameRate : haxe.extern.EitherType; + @:optional var height : haxe.extern.EitherType; + @:optional var mediaSource : String; + @:optional var scrollWithPage : Bool; + @:optional var viewportHeight : haxe.extern.EitherType; + @:optional var viewportOffsetX : haxe.extern.EitherType; + @:optional var viewportOffsetY : haxe.extern.EitherType; + @:optional var viewportWidth : haxe.extern.EitherType; + @:optional var width : haxe.extern.EitherType; +} \ No newline at end of file diff --git a/std/js/html/MediaTrackConstraints.hx b/std/js/html/MediaTrackConstraints.hx new file mode 100644 index 00000000..78555138 --- /dev/null +++ b/std/js/html/MediaTrackConstraints.hx @@ -0,0 +1,38 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\MediaStreamTrack.webidl. Do not edit! + +package js.html; + +/** + The `MediaTrackConstraints` dictionary is used to describe a set of capabilities and the value or values each can take on. A constraints dictionary is passed into `applyConstraints()` to allow a script to establish a set of exact (required) values or ranges and/or preferred values or ranges of values for the track, and the most recently-requested set of custom constraints can be retrieved by calling `getConstraints()`. + + Documentation [MediaTrackConstraints](https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +typedef MediaTrackConstraints = +{ + > MediaTrackConstraintSet, + @:optional var advanced : Array; +} \ No newline at end of file diff --git a/std/js/html/MenuElement.hx b/std/js/html/MenuElement.hx index 6d19b5ba..34fa3c40 100644 --- a/std/js/html/MenuElement.hx +++ b/std/js/html/MenuElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLMenuElement.webidl line 18:0. Do not edit! +// This file is generated from mozilla\HTMLMenuElement.webidl. Do not edit! package js.html; diff --git a/std/js/html/MenuItemElement.hx b/std/js/html/MenuItemElement.hx index 70c5b615..1801ad8e 100644 --- a/std/js/html/MenuItemElement.hx +++ b/std/js/html/MenuItemElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLMenuItemElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLMenuItemElement.webidl. Do not edit! package js.html; diff --git a/std/js/html/MessageChannel.hx b/std/js/html/MessageChannel.hx new file mode 100644 index 00000000..ab0dae15 --- /dev/null +++ b/std/js/html/MessageChannel.hx @@ -0,0 +1,50 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\MessageChannel.webidl. Do not edit! + +package js.html; + +/** + The `MessageChannel` interface of the Channel Messaging API allows us to create a new message channel and send data through it via its two `MessagePort` properties. + + Documentation [MessageChannel](https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("MessageChannel") +extern class MessageChannel +{ + + /** + Returns port1 of the channel. + **/ + var port1(default,null) : MessagePort; + + /** + Returns port2 of the channel. + **/ + var port2(default,null) : MessagePort; + + /** @throws DOMError */ + function new() : Void; +} \ No newline at end of file diff --git a/std/js/html/MessageEvent.hx b/std/js/html/MessageEvent.hx index 1a7abe7c..d27fcaf8 100644 --- a/std/js/html/MessageEvent.hx +++ b/std/js/html/MessageEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,19 +20,47 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MessageEvent.webidl line 12:0. Do not edit! +// This file is generated from mozilla\MessageEvent.webidl. Do not edit! package js.html; +/** + A `MessageEvent` is the interface representing a message received by a target, being a `WebSocket` or a WebRTC `RTCDataChannel` + + Documentation [MessageEvent](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MessageEvent") extern class MessageEvent extends Event { + + /** + Returns a `DOMString`, `Blob` or an `ArrayBuffer` containing the data send by the emitter. + **/ var data(default,null) : Dynamic; + + /** + Is a `DOMString` … + **/ var origin(default,null) : String; var lastEventId(default,null) : String; + + /** + … + **/ var source(default,null) : haxe.extern.EitherType; + + /** + … + **/ var ports(default,null) : MessagePortList; /** @throws DOMError */ function new( type : String, ?eventInitDict : MessageEventInit ) : Void; + + /** + … Do not use this anymore: use the `MessageEvent.MessageEvent` constructor instead. + **/ + function initMessageEvent( type : String, bubbles : Bool, cancelable : Bool, data : Dynamic, origin : String, lastEventId : String, source : haxe.extern.EitherType, ports : Array ) : Void; } \ No newline at end of file diff --git a/std/js/html/MessageEventInit.hx b/std/js/html/MessageEventInit.hx index 203ec162..34eb0f35 100644 --- a/std/js/html/MessageEventInit.hx +++ b/std/js/html/MessageEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MessageEvent.webidl line 46:0. Do not edit! +// This file is generated from mozilla\MessageEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/MessagePort.hx b/std/js/html/MessagePort.hx index b4b568ef..7eb33a8f 100644 --- a/std/js/html/MessagePort.hx +++ b/std/js/html/MessagePort.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MessagePort.webidl line 11:0. Do not edit! +// This file is generated from mozilla\MessagePort.webidl. Do not edit! package js.html; +/** + The `MessagePort` interface of the Channel Messaging API represents one of the two ports of a `MessageChannel`, allowing sending of messages from one port and listening out for them arriving at the other. + + Documentation [MessagePort](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MessagePort") extern class MessagePort extends EventTarget { diff --git a/std/js/html/MessagePortList.hx b/std/js/html/MessagePortList.hx index 284f510d..7982e9a1 100644 --- a/std/js/html/MessagePortList.hx +++ b/std/js/html/MessagePortList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MessagePortList.webidl line 8:0. Do not edit! +// This file is generated from mozilla\MessagePortList.webidl. Do not edit! package js.html; diff --git a/std/js/html/MetaElement.hx b/std/js/html/MetaElement.hx index 0ede2756..4dbac3f9 100644 --- a/std/js/html/MetaElement.hx +++ b/std/js/html/MetaElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLMetaElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLMetaElement.webidl. Do not edit! package js.html; +/** + The `HTMLMetaElement` interface contains descriptive metadata about a document. It inherits all of the properties and methods described in the `HTMLElement` interface. + + Documentation [HTMLMetaElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMetaElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMetaElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLMetaElement") extern class MetaElement extends Element { diff --git a/std/js/html/MeterElement.hx b/std/js/html/MeterElement.hx index e423d1d1..0cc1ac5f 100644 --- a/std/js/html/MeterElement.hx +++ b/std/js/html/MeterElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLMeterElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLMeterElement.webidl. Do not edit! package js.html; +/** + The HTML `meter` elements expose the `HTMLMeterElement` interface, which provides special properties and methods (beyond the `HTMLElement` object interface they also have available to them by inheritance) for manipulating the layout and presentation of `meter` elements. + + Documentation [HTMLMeterElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMeterElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMeterElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLMeterElement") extern class MeterElement extends Element { diff --git a/std/js/html/MimeType.hx b/std/js/html/MimeType.hx index 64f20640..66ab2d74 100644 --- a/std/js/html/MimeType.hx +++ b/std/js/html/MimeType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MimeType.webidl line 7:0. Do not edit! +// This file is generated from mozilla\MimeType.webidl. Do not edit! package js.html; diff --git a/std/js/html/MimeTypeArray.hx b/std/js/html/MimeTypeArray.hx index 5b61d944..4914a8af 100644 --- a/std/js/html/MimeTypeArray.hx +++ b/std/js/html/MimeTypeArray.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MimeTypeArray.webidl line 7:0. Do not edit! +// This file is generated from mozilla\MimeTypeArray.webidl. Do not edit! package js.html; diff --git a/std/js/html/ModElement.hx b/std/js/html/ModElement.hx index 30b161f2..d0d78c66 100644 --- a/std/js/html/ModElement.hx +++ b/std/js/html/ModElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLModElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLModElement.webidl. Do not edit! package js.html; +/** + The `HTMLModElement` interface provides special properties (beyond the regular methods and properties available through the `HTMLElement` interface they also have available to them by inheritance) for manipulating modification elements, that is `del` and `ins`. + + Documentation [HTMLModElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLModElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLModElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLModElement") extern class ModElement extends Element { + + /** + Is a `DOMString` reflecting the `cite` HTML attribute, containing a URI of a resource explaining the change. + **/ var cite : String; var dateTime : String; diff --git a/std/js/html/MouseEvent.hx b/std/js/html/MouseEvent.hx index 54709c23..9d415b5d 100644 --- a/std/js/html/MouseEvent.hx +++ b/std/js/html/MouseEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,33 +20,116 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MouseEvent.webidl line 13:0. Do not edit! +// This file is generated from mozilla\MouseEvent.webidl. Do not edit! package js.html; +/** + The `MouseEvent` interface represents events that occur due to the user interacting with a pointing device (such as a mouse). Common events using this interface include `click`, `dblclick`, `mouseup`, `mousedown`. + + Documentation [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MouseEvent") extern class MouseEvent extends UIEvent { + + /** + The X coordinate of the mouse pointer in global (screen) coordinates. + **/ var screenX(default,null) : Int; + + /** + The Y coordinate of the mouse pointer in global (screen) coordinates. + **/ var screenY(default,null) : Int; + + /** + The X coordinate of the mouse pointer in local (DOM content) coordinates. + **/ var clientX(default,null) : Int; + + /** + The Y coordinate of the mouse pointer in local (DOM content) coordinates. + **/ var clientY(default,null) : Int; + + /** + The X coordinate of the mouse pointer relative to the position of the padding edge of the target node. + **/ + var offsetX(default,null) : Int; + + /** + The Y coordinate of the mouse pointer relative to the position of the padding edge of the target node. + **/ + var offsetY(default,null) : Int; + + /** + Returns `true` if the control key was down when the mouse event was fired. + **/ var ctrlKey(default,null) : Bool; + + /** + Returns `true` if the shift key was down when the mouse event was fired. + **/ var shiftKey(default,null) : Bool; + + /** + Returns `true` if the alt key was down when the mouse event was fired. + **/ var altKey(default,null) : Bool; + + /** + Returns `true` if the meta key was down when the mouse event was fired. + **/ var metaKey(default,null) : Bool; + + /** + The button number that was pressed when the mouse event was fired.  + **/ var button(default,null) : Int; + + /** + + The buttons being pressed when the mouse event was fired + + **/ var buttons(default,null) : Int; + + /** + + The secondary target for the event, if there is one. + + **/ var relatedTarget(default,null) : EventTarget; + + /** + Returns the id of the hit region affected by the event. If no hit region is affected, `null` is returned. + **/ var region(default,null) : String; + + /** + The X coordinate of the mouse pointer relative to the position of the last `mousemove` event. + **/ var movementX(default,null) : Int; + + /** + The Y coordinate of the mouse pointer relative to the position of the last `mousemove` event. + **/ var movementY(default,null) : Int; /** @throws DOMError */ function new( typeArg : String, ?mouseEventInitDict : MouseEventInit ) : Void; - /** @throws DOMError */ + + /** + Initializes the value of a `MouseEvent` created. If the event has already being dispatched, this method does nothing. + **/ function initMouseEvent( typeArg : String, canBubbleArg : Bool, cancelableArg : Bool, viewArg : Window, detailArg : Int, screenXArg : Int, screenYArg : Int, clientXArg : Int, clientYArg : Int, ctrlKeyArg : Bool, altKeyArg : Bool, shiftKeyArg : Bool, metaKeyArg : Bool, buttonArg : Int, relatedTargetArg : EventTarget ) : Void; + + /** + Returns the current state of the specified modifier key. See the `KeyboardEvent.getModifierState`() for details. + **/ function getModifierState( keyArg : String ) : Bool; - /** @throws DOMError */ function initNSMouseEvent( typeArg : String, canBubbleArg : Bool, cancelableArg : Bool, viewArg : Window, detailArg : Int, screenXArg : Int, screenYArg : Int, clientXArg : Int, clientYArg : Int, ctrlKeyArg : Bool, altKeyArg : Bool, shiftKeyArg : Bool, metaKeyArg : Bool, buttonArg : Int, relatedTargetArg : EventTarget, pressure : Float, inputSourceArg : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/MouseEventInit.hx b/std/js/html/MouseEventInit.hx index 85acb900..2f9893c4 100644 --- a/std/js/html/MouseEventInit.hx +++ b/std/js/html/MouseEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,22 +20,20 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MouseEvent.webidl line 55:0. Do not edit! +// This file is generated from mozilla\MouseEvent.webidl. Do not edit! package js.html; typedef MouseEventInit = { - > UIEventInit, - @:optional var altKey : Bool; + > EventModifierInit, @:optional var button : Int; @:optional var buttons : Int; @:optional var clientX : Int; @:optional var clientY : Int; - @:optional var ctrlKey : Bool; - @:optional var metaKey : Bool; + @:optional var movementX : Int; + @:optional var movementY : Int; @:optional var relatedTarget : EventTarget; @:optional var screenX : Int; @:optional var screenY : Int; - @:optional var shiftKey : Bool; } \ No newline at end of file diff --git a/std/js/html/MouseScrollEvent.hx b/std/js/html/MouseScrollEvent.hx index 101a712f..53702724 100644 --- a/std/js/html/MouseScrollEvent.hx +++ b/std/js/html/MouseScrollEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MouseScrollEvent.webidl line 7:0. Do not edit! +// This file is generated from mozilla\MouseScrollEvent.webidl. Do not edit! package js.html; +/** + The `MouseScrollEvent` interface represents events that occur due to the user moving a mouse wheel or similar input device. + + Documentation [MouseScrollEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseScrollEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MouseScrollEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MouseScrollEvent") extern class MouseScrollEvent extends MouseEvent { @@ -32,6 +39,5 @@ extern class MouseScrollEvent extends MouseEvent var axis(default,null) : Int; - /** @throws DOMError */ function initMouseScrollEvent( type : String, canBubble : Bool, cancelable : Bool, view : Window, detail : Int, screenX : Int, screenY : Int, clientX : Int, clientY : Int, ctrlKey : Bool, altKey : Bool, shiftKey : Bool, metaKey : Bool, button : Int, relatedTarget : EventTarget, axis : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/MutationEvent.hx b/std/js/html/MutationEvent.hx index 8997f5ab..cf174e51 100644 --- a/std/js/html/MutationEvent.hx +++ b/std/js/html/MutationEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MutationEvent.webidl line 12:0. Do not edit! +// This file is generated from mozilla\MutationEvent.webidl. Do not edit! package js.html; +/** + Provides event properties that are specific to modifications to the Document Object Model (DOM) hierarchy and nodes. + + Documentation [MutationEvent](https://developer.mozilla.org/en-US/docs/Web/API/MutationEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MutationEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MutationEvent") extern class MutationEvent extends Event { diff --git a/std/js/html/MutationObserver.hx b/std/js/html/MutationObserver.hx index d7195a21..4c5c2ce3 100644 --- a/std/js/html/MutationObserver.hx +++ b/std/js/html/MutationObserver.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MutationObserver.webidl line 34:0. Do not edit! +// This file is generated from mozilla\MutationObserver.webidl. Do not edit! package js.html; +/** + `MutationObserver` provides developers a way to react to changes in a DOM. It is designed as a replacement for Mutation Events defined in the DOM3 Events specification. + + Documentation [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MutationObserver") extern class MutationObserver { diff --git a/std/js/html/MutationObserverInit.hx b/std/js/html/MutationObserverInit.hx index 086c14c5..99b4efa9 100644 --- a/std/js/html/MutationObserverInit.hx +++ b/std/js/html/MutationObserverInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,17 +20,19 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MutationObserver.webidl line 48:0. Do not edit! +// This file is generated from mozilla\MutationObserver.webidl. Do not edit! package js.html; typedef MutationObserverInit = { + @:optional var animations : Bool; @:optional var attributeFilter : Array; @:optional var attributeOldValue : Bool; @:optional var attributes : Bool; @:optional var characterData : Bool; @:optional var characterDataOldValue : Bool; @:optional var childList : Bool; + @:optional var nativeAnonymousChildList : Bool; @:optional var subtree : Bool; } \ No newline at end of file diff --git a/std/js/html/MutationRecord.hx b/std/js/html/MutationRecord.hx index 9d05f567..00f70549 100644 --- a/std/js/html/MutationRecord.hx +++ b/std/js/html/MutationRecord.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MutationObserver.webidl line 10:0. Do not edit! +// This file is generated from mozilla\MutationObserver.webidl. Do not edit! package js.html; +/** + A `MutationRecord` represents an individual DOM mutation. It is the object that is passed to `MutationObserver`'s callback. + + Documentation [MutationRecord](https://developer.mozilla.org/en-US/docs/Web/API/MutationRecord) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MutationRecord$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MutationRecord") extern class MutationRecord { diff --git a/std/js/html/NamedNodeMap.hx b/std/js/html/NamedNodeMap.hx index becfc8c2..3710f83e 100644 --- a/std/js/html/NamedNodeMap.hx +++ b/std/js/html/NamedNodeMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,24 +20,63 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/NamedNodeMap.webidl line 6:0. Do not edit! +// This file is generated from mozilla\NamedNodeMap.webidl. Do not edit! package js.html; +/** + The `NamedNodeMap` interface represents a collection of `Attr` objects. Objects inside a `NamedNodeMap` are not in any particular order, unlike `NodeList`, although they may be accessed by an index as in an array. + + Documentation [NamedNodeMap](https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("NamedNodeMap") extern class NamedNodeMap implements ArrayAccess { + + /** + Returns the amount of objects in the map. + **/ var length(default,null) : Int; + + /** + Returns a `Attr`, corresponding to the given name. + **/ function getNamedItem( name : String ) : Attr; /** @throws DOMError */ + + /** + Replaces, or adds, the `Attr` identified in the map by the given name. + **/ function setNamedItem( arg : Attr ) : Attr; /** @throws DOMError */ + + /** + Removes the `Attr` identified by the given map. + **/ function removeNamedItem( name : String ) : Attr; + + /** + Returns the `Attr` at the given index, or `null` if the index is higher or equal to the number of nodes. + **/ function item( index : Int ) : Attr; + + /** + Returns a `Attr` identified by a namespace and related local name. + **/ function getNamedItemNS( namespaceURI : String, localName : String ) : Attr; /** @throws DOMError */ + + /** + Replaces, or adds, the `Attr` identified in the map by the given namespace and related local name. + **/ function setNamedItemNS( arg : Attr ) : Attr; /** @throws DOMError */ + + /** + Removes the `Attr` identified by the given namespace and related local name. + **/ function removeNamedItemNS( namespaceURI : String, localName : String ) : Attr; } \ No newline at end of file diff --git a/std/js/html/Navigator.hx b/std/js/html/Navigator.hx index 7531933b..ae288284 100644 --- a/std/js/html/Navigator.hx +++ b/std/js/html/Navigator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,24 +20,69 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Navigator.webidl line 23:0. Do not edit! +// This file is generated from mozilla\Navigator.webidl. Do not edit! package js.html; +/** + The `Navigator` interface represents the state and the identity of the user agent. It allows scripts to query it and to register themselves to carry on some activities. + + Documentation [Navigator](https://developer.mozilla.org/en-US/docs/Web/API/Navigator) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Navigator$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Navigator") extern class Navigator { + + /** + Returns a `Permissions` object that can be used to query and update permission status of APIs covered by the Permissions API. + **/ + var permissions(default,null) : Permissions; var mimeTypes(default,null) : MimeTypeArray; var plugins(default,null) : PluginArray; + + /** + Reports the value of the user's do-not-track preference. When this value is "yes", your web site or application should not track the user. + **/ var doNotTrack(default,null) : String; + + /** + Returns a `BatteryManager` object you can use to get information about the battery charging status. + **/ + var battery(default,null) : BatteryManager; var maxTouchPoints(default,null) : Int; + + /** + Returns a string that represents the current operating system. + **/ var oscpu(default,null) : String; + + /** + Returns the vendor name of the current browser (e.g., "Netscape6"). + **/ var vendor(default,null) : String; + + /** + Returns the vendor version number (e.g. "6.1"). + **/ var vendorSub(default,null) : String; + + /** + Returns the build number of the current browser (e.g., "20060909"). + **/ var productSub(default,null) : String; + + /** + Returns a boolean indicating whether cookies are enabled in the browser or not. + **/ var cookieEnabled(default,null) : Bool; var buildID(default,null) : String; - var battery(default,null) : BatteryManager; + var hardwareConcurrency(default,null) : Int; + + /** + Returns a `Geolocation` object allowing accessing the location of the device. + **/ var geolocation(default,null) : Geolocation; var appCodeName(default,null) : String; var appName(default,null) : String; @@ -49,6 +94,8 @@ extern class Navigator var languages(default,null) : Array; var onLine(default,null) : Bool; + /** @throws DOMError */ + function getBattery() : Promise; @:overload( function( duration : Int ) : Bool {} ) function vibrate( pattern : Array ) : Bool; /** @throws DOMError */ @@ -57,7 +104,6 @@ extern class Navigator function getGamepads() : Array; /** @throws DOMError */ function sendBeacon( url : String, ?data : haxe.extern.EitherType>> ) : Bool; - function requestMediaKeySystemAccess( keySystem : String, ?supportedConfigurations : Array ) : Promise; /** @throws DOMError */ function registerProtocolHandler( scheme : String, url : String, title : String ) : Void; /** @throws DOMError */ diff --git a/std/js/html/Node.hx b/std/js/html/Node.hx index b2ca7725..b1c8e110 100644 --- a/std/js/html/Node.hx +++ b/std/js/html/Node.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Node.webidl line 16:0. Do not edit! +// This file is generated from mozilla\Node.webidl. Do not edit! package js.html; +/** + A `Node` is an interface from which a number of DOM types inherit, and allows these various types to be treated (or tested) similarly. + + Documentation [Node](https://developer.mozilla.org/en-US/docs/Web/API/Node) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Node$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Node") extern class Node extends EventTarget { @@ -46,39 +53,222 @@ extern class Node extends EventTarget static inline var DOCUMENT_POSITION_CONTAINED_BY : Int = 16; static inline var DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : Int = 32; + + /** + Returns an unsigned short representing the type of the node. Possible values are: + + + + Name + Value + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ELEMENT_NODE1
ATTRIBUTE_NODE (deprecated)2
TEXT_NODE3
CDATA_SECTION_NODE (deprecated)4
ENTITY_REFERENCE_NODE (deprecated)5
ENTITY_NODE (deprecated)6
PROCESSING_INSTRUCTION_NODE7
COMMENT_NODE8
DOCUMENT_NODE9
DOCUMENT_TYPE_NODE10
DOCUMENT_FRAGMENT_NODE11
NOTATION_NODE (deprecated)12
+ + **/ var nodeType(default,null) : Int; + + /** + Returns a `DOMString` containing the name of the `Node`. The structure of the name will differ with the name type. E.g. An `HTMLElement` will contain the name of the corresponding tag, like `'audio'` for an `HTMLAudioElement`, a `Text` node will have the `'#text'` string, or a `Document` node will have the `'#document'` string. + **/ var nodeName(default,null) : String; + + /** + Returns a `DOMString` representing the base URL. The concept of base URL changes from one language to another; in HTML, it corresponds to the protocol, the domain name and the directory structure, that is all until the last `'/'`. + **/ var baseURI(default,null) : String; + + /** + Returns the `Document` that this node belongs to. If no document is associated with it, returns `null`. + **/ var ownerDocument(default,null) : HTMLDocument; + + /** + Returns a `Node` that is the parent of this node. If there is no such node, like if this node is the top of the tree or if doesn't participate in a tree, this property returns `null`. + **/ var parentNode(default,null) : Node; + + /** + Returns an `Element` that is the parent of this node. If the node has no parent, or if that parent is not an `Element`, this property returns `null`. + **/ var parentElement(default,null) : Element; + + /** + Returns a live `NodeList` containing all the children of this node. `NodeList` being live means that if the children of the `Node` change, the `NodeList` object is automatically updated. + **/ var childNodes(default,null) : NodeList; + + /** + Returns a `Node` representing the first direct child node of the node, or `null` if the node has no child. + **/ var firstChild(default,null) : Node; + + /** + Returns a `Node` representing the last direct child node of the node, or `null` if the node has no child. + **/ var lastChild(default,null) : Node; + + /** + Returns a `Node` representing the previous node in the tree, or `null` if there isn't such node. + **/ var previousSibling(default,null) : Node; + + /** + Returns a `Node` representing the next node in the tree, or `null` if there isn't such node. + **/ var nextSibling(default,null) : Node; + + /** + Returns / Sets the value of the current node + **/ var nodeValue : String; + + /** + Returns / Sets the textual content of an element and all its descendants. + **/ var textContent : String; + + /** + The namespace URI of this node, or `null` if it is no namespace. + + Note: In Firefox 3.5 and earlier, HTML elements are in no namespace. In later versions, HTML elements are in the `https://www.w3.org/1999/xhtml/` namespace in both HTML and XML trees. `1.9.2` + + + **/ var namespaceURI(default,null) : String; + + /** + Is a `DOMString` representing the namespace prefix of the node, or `null` if no prefix is specified. + **/ var prefix(default,null) : String; + + /** + Returns a `DOMString` representing the local part of the qualified name of an element. + + Note: In Firefox 3.5 and earlier, the property upper-cases the local name for HTML elements (but not XHTML elements). In later versions, this does not happen, so the property is in lower case for both HTML and XHTML. `1.9.2` + + + **/ var localName(default,null) : String; + + /** + Returns a `Boolean` indicating if the element has any child nodes, or not. + **/ function hasChildNodes() : Bool; /** @throws DOMError */ + + /** + Inserts the first `Node` given in a parameter immediately before the second, child of this element, `Node`. + **/ function insertBefore( node : Node, child : Node ) : Node; /** @throws DOMError */ + + /** + Adds the specified childNode argument as the last child to the current node. + + If the argument referenced an existing node on the DOM tree, the node will be detached from its current position and attached at the new position. + **/ function appendChild( node : Node ) : Node; /** @throws DOMError */ + + /** + Replaces one child `Node` of the current one with the second one given in parameter. + **/ function replaceChild( node : Node, child : Node ) : Node; /** @throws DOMError */ + + /** + Removes a child node from the current element, which must be a child of the current node. + **/ function removeChild( child : Node ) : Node; + + /** + Clean up all the text nodes under this element (merge adjacent, remove empty). + **/ function normalize() : Void; /** @throws DOMError */ + + /** + Clone a `Node`, and optionally, all of its contents. By default, it clones the content of the node. + **/ function cloneNode( ?deep : Bool = false ) : Node; + + /** + Returns a `Boolean` which indicates whether or not two nodes are of the same type and all their defining data points match. + **/ function isEqualNode( node : Node ) : Bool; + + /** + Returns the context objects root which optionally includes the shadow root if it is available.  + **/ function compareDocumentPosition( other : Node ) : Int; + + /** + Returns the context objects root which optionally includes the shadow root if it is available.  + **/ function contains( other : Node ) : Bool; + + /** + Clean up all the text nodes under this element (merge adjacent, remove empty). + **/ function lookupPrefix( namespace_ : String ) : String; + + /** + Clean up all the text nodes under this element (merge adjacent, remove empty). + **/ function lookupNamespaceURI( prefix : String ) : String; + + /** + Returns a `Boolean` which indicates whether or not two nodes are of the same type and all their defining data points match. + **/ function isDefaultNamespace( namespace_ : String ) : Bool; } \ No newline at end of file diff --git a/std/js/html/NodeFilter.hx b/std/js/html/NodeFilter.hx index d295f990..9384f059 100644 --- a/std/js/html/NodeFilter.hx +++ b/std/js/html/NodeFilter.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/NodeFilter.webidl line 10:9. Do not edit! +// This file is generated from mozilla\NodeFilter.webidl. Do not edit! package js.html; +/** + A `NodeFilter` interface represents an object used to filter the nodes in a `NodeIterator` or `TreeWalker`. They don't know anything about the DOM or how to traverse nodes; they just know how to evaluate a single node against the provided filter. + + Documentation [NodeFilter](https://developer.mozilla.org/en-US/docs/Web/API/NodeFilter) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/NodeFilter$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("NodeFilter") extern class NodeFilter { @@ -44,5 +51,30 @@ extern class NodeFilter static inline var SHOW_DOCUMENT_FRAGMENT : Int = 1024; static inline var SHOW_NOTATION : Int = 2048; + + /** + Returns an unsigned short that will be used to tell if a given Node must be accepted or not by the NodeIterator or TreeWalker iteration algorithm. This method is expected to be written by the user of a NodeFilter. Possible return values are: + + + + + + + + + + + + + + + + + + + +
ConstantDescription
FILTER_ACCEPTValue returned by the NodeFilter.acceptNode() method when a node should be accepted.
FILTER_REJECTValue to be returned by the NodeFilter.acceptNode() method when a node should be rejected. For TreeWalker, child nodes are also rejected. For NodeIterator, this flag is synonymous with FILTER_SKIP.
FILTER_SKIPValue to be returned by NodeFilter.acceptNode() for nodes to be skipped by the NodeIterator or TreeWalker object. The children of skipped nodes are still considered. This is treated as "skip this node but not its children".
+ + **/ function acceptNode( node : Node ) : Int; } \ No newline at end of file diff --git a/std/js/html/NodeIterator.hx b/std/js/html/NodeIterator.hx index 26c4be7d..436b43dd 100644 --- a/std/js/html/NodeIterator.hx +++ b/std/js/html/NodeIterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,22 +20,136 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/NodeIterator.webidl line 13:0. Do not edit! +// This file is generated from mozilla\NodeIterator.webidl. Do not edit! package js.html; +/** + The `NodeIterator` interface represents an iterator over the members of a list of the nodes in a subtree of the DOM. The nodes will be returned in document order. + + Documentation [NodeIterator](https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("NodeIterator") extern class NodeIterator { + + /** + Returns a `Node` representing the root node as specified when the `NodeIterator` was created. + **/ var root(default,null) : Node; + + /** + Returns the `Node` to which the iterator is anchored. + **/ var referenceNode(default,null) : Node; + + /** + Returns a `Boolean` flag that indicates whether the `NodeIterator` is anchored before, the flag being `true`, or after, the flag being `false`, the anchor node. + **/ var pointerBeforeReferenceNode(default,null) : Bool; + + /** + Returns an unsigned long being a bitmask made of constants describing the types of Node that must to be presented. Non-matching nodes are skipped, but their children may be included, if relevant. The possible values are: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConstantNumerical valueDescription
NodeFilter.SHOW_ALL-1 (that is the max value of unsigned long)Shows all nodes.
NodeFilter.SHOW_ATTRIBUTE (deprecated)2Shows attribute Attr nodes. This is meaningful only when creating a NodeIterator with an Attr node as its root; in this case, it means that the attribute node will appear in the first position of the iteration or traversal. Since attributes are never children of other nodes, they do not appear when traversing over the document tree.
NodeFilter.SHOW_CDATA_SECTION (deprecated)8Shows CDATASection nodes.
NodeFilter.SHOW_COMMENT128Shows Comment nodes.
NodeFilter.SHOW_DOCUMENT256Shows Document nodes.
NodeFilter.SHOW_DOCUMENT_FRAGMENT1024Shows DocumentFragment nodes.
NodeFilter.SHOW_DOCUMENT_TYPE512Shows DocumentType nodes.
NodeFilter.SHOW_ELEMENT1Shows Element nodes.
NodeFilter.SHOW_ENTITY (deprecated)32Shows Entity nodes. This is meaningful only when creating a NodeIterator with an Entity node as its root; in this case, it means that the Entity node will appear in the first position of the traversal. Since entities are not part of the document tree, they do not appear when traversing over the document tree.
NodeFilter.SHOW_ENTITY_REFERENCE (deprecated)16Shows EntityReference nodes.
NodeFilter.SHOW_NOTATION (deprecated)2048Shows Notation nodes. This is meaningful only when creating a NodeIterator with a Notation node as its root; in this case, it means that the Notation node will appear in the first position of the traversal. Since entities are not part of the document tree, they do not appear when traversing over the document tree.
NodeFilter.SHOW_PROCESSING_INSTRUCTION64Shows ProcessingInstruction nodes.
NodeFilter.SHOW_TEXT4Shows Text nodes.
+ + **/ var whatToShow(default,null) : Int; + + /** + Returns a `NodeFilter` used to select the relevant nodes. + **/ var filter(default,null) : NodeFilter; /** @throws DOMError */ + + /** + Returns the next `Node` in the document, or `null` if there are none. + **/ function nextNode() : Node; /** @throws DOMError */ + + /** + Returns the previous `Node` in the document, or `null` if there are none. + **/ function previousNode() : Node; + + /** + This operation is a no-op. It doesn't do anything. Previously it was telling the engine that the `NodeIterator` was no more used, but this is now useless. + **/ function detach() : Void; } \ No newline at end of file diff --git a/std/js/html/NodeList.hx b/std/js/html/NodeList.hx index 7fa171d4..a15e9e0f 100644 --- a/std/js/html/NodeList.hx +++ b/std/js/html/NodeList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/NodeList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\NodeList.webidl. Do not edit! package js.html; +/** + `NodeList` objects are collections of nodes such as those returned by `Node.childNodes` and the `document.querySelectorAll` method. + + Documentation [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/NodeList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("NodeList") extern class NodeList implements ArrayAccess { + + /** + The number of nodes in the `NodeList`. + **/ var length(default,null) : Int; + + /** + Returns an item in the list by its index, or `null` if the index is out-of-bounds; can be used as an alternative to simply accessing `nodeList[idx]` (which instead returns  `undefined` when `idx` is out-of-bounds). + **/ function item( index : Int ) : Node; } \ No newline at end of file diff --git a/std/js/html/Notification.hx b/std/js/html/Notification.hx index 4ec4b03f..5a311fb5 100644 --- a/std/js/html/Notification.hx +++ b/std/js/html/Notification.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,32 +20,87 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Notification.webidl line 16:0. Do not edit! +// This file is generated from mozilla\Notification.webidl. Do not edit! package js.html; +/** + The `Notification` interface of the Notifications API is used to configure and display desktop notifications to the user. + + Documentation [Notification](https://developer.mozilla.org/en-US/docs/Web/API/Notification) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Notification$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Notification") extern class Notification extends EventTarget { - static var permission(default,null) : NotificationPermission; + static + /** + A string representing the current permission to display notifications. Possible value are: `denied` (the user refuses to have notifications displayed), `granted` (the user accepts having notifications displayed), or `default` (the user choice is unknown and therefore the browser will act as if the value were denied). + **/ + var permission(default,null) : NotificationPermission; - /** @throws DOMError */ - static function requestPermission( ?permissionCallback : NotificationPermission -> Void ) : Void; - /** @throws DOMError */ - static function get( ?filter : GetNotificationOptions ) : Promise>; + + /** + A handler for the `click` event. It is triggered each time the user clicks on the notification. + **/ var onclick : haxe.Constraints.Function; + + /** + A handler for the `show` event. It is triggered when the notification is displayed. + **/ var onshow : haxe.Constraints.Function; + + /** + A handler for the `error` event. It is triggered each time the notification encounters an error. + **/ var onerror : haxe.Constraints.Function; + + /** + A handler for the `close` event. It is triggered when the user closes the notification. + **/ var onclose : haxe.Constraints.Function; + + /** + The title of the notification as specified in the first parameter of the constructor. + **/ var title(default,null) : String; + + /** + The text direction of the notification as specified in the options parameter of the constructor. + **/ var dir(default,null) : NotificationDirection; + + /** + The language code of the notification as specified in the options parameter of the constructor. + **/ var lang(default,null) : String; + + /** + The body string of the notification as specified in the options parameter of the constructor. + **/ var body(default,null) : String; + + /** + The ID of the notification (if any) as specified in the options parameter of the constructor. + **/ var tag(default,null) : String; + + /** + The URL of the image used as an icon of the notification as specified in the options parameter of the constructor. + **/ var icon(default,null) : String; + + /** + Returns a structured clone of the notification’s data. + **/ var data(default,null) : Dynamic; /** @throws DOMError */ function new( title : String, ?options : NotificationOptions ) : Void; + + /** + Programmatically closes a notification. + **/ function close() : Void; } \ No newline at end of file diff --git a/std/js/html/NotificationDirection.hx b/std/js/html/NotificationDirection.hx index 10a05148..b8d5713d 100644 --- a/std/js/html/NotificationDirection.hx +++ b/std/js/html/NotificationDirection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Notification.webidl line 88:0. Do not edit! +// This file is generated from mozilla\Notification.webidl. Do not edit! package js.html; diff --git a/std/js/html/ServiceWorkerClients.hx b/std/js/html/NotificationEvent.hx similarity index 77% rename from std/js/html/ServiceWorkerClients.hx rename to std/js/html/NotificationEvent.hx index 60901b58..3aebae36 100644 --- a/std/js/html/ServiceWorkerClients.hx +++ b/std/js/html/NotificationEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,15 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ServiceWorkerClients.webidl line 12:0. Do not edit! +// This file is generated from mozilla\NotificationEvent.webidl. Do not edit! package js.html; -@:native("ServiceWorkerClients") -extern class ServiceWorkerClients +@:native("NotificationEvent") +extern class NotificationEvent extends ExtendableEvent { + var notification(default,null) : Notification; + /** @throws DOMError */ - function getServiced() : Promise>; - /** @throws DOMError */ - function reloadAll() : Promise; + function new( type : String, eventInitDict : NotificationEventInit ) : Void; } \ No newline at end of file diff --git a/std/js/html/NotificationEventInit.hx b/std/js/html/NotificationEventInit.hx new file mode 100644 index 00000000..81f88ae2 --- /dev/null +++ b/std/js/html/NotificationEventInit.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\NotificationEvent.webidl. Do not edit! + +package js.html; + +typedef NotificationEventInit = +{ + > ExtendableEventInit, + var notification : Notification; +} \ No newline at end of file diff --git a/std/js/html/NotificationOptions.hx b/std/js/html/NotificationOptions.hx index 0590c806..f517f731 100644 --- a/std/js/html/NotificationOptions.hx +++ b/std/js/html/NotificationOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Notification.webidl line 58:0. Do not edit! +// This file is generated from mozilla\Notification.webidl. Do not edit! package js.html; diff --git a/std/js/html/NotificationPermission.hx b/std/js/html/NotificationPermission.hx index 5107fa87..7f73684d 100644 --- a/std/js/html/NotificationPermission.hx +++ b/std/js/html/NotificationPermission.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Notification.webidl line 80:0. Do not edit! +// This file is generated from mozilla\Notification.webidl. Do not edit! package js.html; diff --git a/std/js/html/NotifyPaintEvent.hx b/std/js/html/NotifyPaintEvent.hx index 20138667..f95a7d47 100644 --- a/std/js/html/NotifyPaintEvent.hx +++ b/std/js/html/NotifyPaintEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/NotifyPaintEvent.webidl line 9:0. Do not edit! +// This file is generated from mozilla\NotifyPaintEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/OListElement.hx b/std/js/html/OListElement.hx index 2692d673..bff816e6 100644 --- a/std/js/html/OListElement.hx +++ b/std/js/html/OListElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,47 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLOListElement.webidl line 16:0. Do not edit! +// This file is generated from mozilla\HTMLOListElement.webidl. Do not edit! package js.html; +/** + The `HTMLOListElement` interface provides special properties (beyond those defined on the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating ordered list elements. + + Documentation [HTMLOListElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOListElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOListElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLOListElement") extern class OListElement extends Element { + + /** + Is a `Boolean` value reflecting the `reversed` and defining if the numbering is descending, that is its value is `true`, or ascending (`false`). + **/ var reversed : Bool; + + /** + Is a `long` value reflecting the `start` and defining the value of the first number of the first element of the list. + **/ var start : Int; + + /** + Is a `DOMString` value reflecting the `type` and defining the kind of marker to be used to display. It can have the following values: + + `'1'` meaning that decimal numbers are used: `1`, `2`, `3`, `4`, `5`, … + `'a'` meaning that the lowercase latin alphabet is used:  `a`, `b`, `c`, `d`, `e`, … + `'A'` meaning that the uppercase latin alphabet is used: `A`, `B`, `C`, `D`, `E`, … + `'i'` meaning that the lowercase latin numerals are used: `i`, `ii`, `iii`, `iv`, `v`, … + `'I'` meaning that the uppercase latin numerals are used: `I`, `II`, `III`, `IV`, `V`, … + + + **/ var type : String; + + /** + Is a `Boolean` indicating that spacing between list items should be reduced. This property reflects the `compact` attribute only, it doesn't consider the `line-height` CSS property used for that behavior in modern pages. + **/ var compact : Bool; } \ No newline at end of file diff --git a/std/js/html/ObjectElement.hx b/std/js/html/ObjectElement.hx index 33774f71..8e27581f 100644 --- a/std/js/html/ObjectElement.hx +++ b/std/js/html/ObjectElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,38 +20,145 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLObjectElement.webidl line 17:0. Do not edit! +// This file is generated from mozilla\HTMLObjectElement.webidl. Do not edit! package js.html; +/** + The `HTMLObjectElement` interface provides special properties and methods (beyond those on the `HTMLElement` interface it also has available to it by inheritance) for manipulating the layout and presentation of `object` element, representing external resources. + + Documentation [HTMLObjectElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLObjectElement") extern class ObjectElement extends Element { + + /** + Is a `DOMString` that reflects the `data` HTML attribute, specifying the address of a resource's data. + **/ var data : String; + + /** + Is a `DOMString` that reflects the `type` HTML attribute, specifying the MIME type of the resource. + **/ var type : String; + + /** + Is a `Boolean` that reflects the `typeMustMatch` HTML attribute, indicating if the resource specified by `data` must only be played if it matches the `type` attribute. + **/ var typeMustMatch : Bool; + + /** + Is a `DOMString` that reflects the `name` HTML attribute, specifying the name of the browsing context. + **/ var name : String; + + /** + Is a `DOMString` that reflects the `usemap` HTML attribute, specifying a `map` element to use. + **/ var useMap : String; + + /** + Retuns a `HTMLFormElement` representing the object element's form owner, or null if there isn't one. + **/ var form(default,null) : FormElement; + + /** + Is a `DOMString` that reflects the `width` HTML attribute, specifying the displayed width of the resource in CSS pixels. + **/ var width : String; + + /** + Is a `DOMString` that reflects the `height` HTML attribute, specifying the displayed height of the resource in CSS pixels. + **/ var height : String; + + /** + Returns a `Document` representing the active document of the object element's nested browsing context, if any; otherwise `null`. + **/ var contentDocument(default,null) : HTMLDocument; + + /** + Returns a `WindowProxy` representing the window proxy of the object element's nested browsing context, if any; otherwise `null`. + **/ var contentWindow(default,null) : Window; + + /** + Returns a `Boolean` that indicates whether the element is a candidate for constraint validation. Always `false` for `HTMLObjectElement` objects. + **/ var willValidate(default,null) : Bool; + + /** + Returns a `ValidityState` with the validity states that this element is in. + **/ var validity(default,null) : ValidityState; + + /** + Returns a `DOMString` representing a localized message that describes the validation constraints that the control does not satisfy (if any). This is the empty string if the control is not a candidate for constraint validation (`willValidate` is `false`), or it satisfies its constraints. + **/ var validationMessage(default,null) : String; + + /** + Is a `DOMString` representing an enumerated property indicating alignment of the element's contents with respect to the surrounding context. The possible values are `"left"`, `"right"`, `"justify"`, and `"center"`. + **/ var align : String; + + /** + Is a `DOMString` that reflects the `archive` HTML attribute, containing a list of archives for resources for this object. + **/ var archive : String; + + /** + Is a `DOMString` representing the name of an applet class file, containing either the applet's subclass, or the path to get to the class, including the class file itself. + **/ var code : String; + + /** + Is a `Boolean` that reflects the `declare` HTML attribute, indicating that this is a declaration, not an instantiation, of the object. + **/ var declare : Bool; + + /** + Is a `long` representing the horizontal space in pixels around the control. + **/ var hspace : Int; + + /** + Is a `DOMString` that reflects the `standby` HTML attribute, specifying a message to display while the object loads. + **/ var standby : String; + + /** + Is a `long` representing the horizontal space in pixels around the control. + **/ var vspace : Int; + + /** + Is a `DOMString` that reflects the `codebase` HTML attribute, specifying the base path to use to resolve relative URIs. + **/ var codeBase : String; + + /** + Is a `DOMString` that reflects the `codetype` HTML attribute, specifying the content type of the data. + **/ var codeType : String; + + /** + Is a `DOMString` that reflects the `border` HTML attribute, specifying the width of a border around the object. + **/ var border : String; + + /** + Retuns a `Boolean` that always is `true`, because `object` objects are never candidates for constraint validation. + **/ function checkValidity() : Bool; + + /** + Sets a custom validity message for the element. If this message is not the empty string, then the element is suffering from a custom validity error, and does not validate. + **/ function setCustomValidity( error : String ) : Void; function getSVGDocument() : HTMLDocument; } \ No newline at end of file diff --git a/std/js/html/ObjectURLOptions.hx b/std/js/html/ObjectURLOptions.hx index b9127b68..ee990a34 100644 --- a/std/js/html/ObjectURLOptions.hx +++ b/std/js/html/ObjectURLOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/URL.webidl line 32:0. Do not edit! +// This file is generated from mozilla\URL.webidl. Do not edit! package js.html; diff --git a/std/js/html/OptGroupElement.hx b/std/js/html/OptGroupElement.hx index 4e45a2aa..685ed40d 100644 --- a/std/js/html/OptGroupElement.hx +++ b/std/js/html/OptGroupElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLOptGroupElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLOptGroupElement.webidl. Do not edit! package js.html; +/** + The `HTMLOptGroupElement` interface provides special properties and methods (beyond the regular `HTMLElement` object interface they also have available to them by inheritance) for manipulating the layout and presentation of `optgroup` elements. + + Documentation [HTMLOptGroupElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOptGroupElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOptGroupElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLOptGroupElement") extern class OptGroupElement extends Element { + + /** + Is a `boolean` representing whether or not the whole list of children `option` is disabled (true) or not (false). + **/ var disabled : Bool; + + /** + Is a `DOMString` representing the label for the group. + **/ var label : String; } \ No newline at end of file diff --git a/std/js/html/OptionElement.hx b/std/js/html/OptionElement.hx index 2b286f9f..87791e78 100644 --- a/std/js/html/OptionElement.hx +++ b/std/js/html/OptionElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLOptionElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLOptionElement.webidl. Do not edit! package js.html; +/** + The `HTMLOptionElement` interface represents `option` elements and inherits all classes and methods of the `HTMLElement` interface. + + Documentation [HTMLOptionElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOptionElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOptionElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLOptionElement") extern class OptionElement extends Element { diff --git a/std/js/html/OrientationLockType.hx b/std/js/html/OrientationLockType.hx new file mode 100644 index 00000000..036fe7d9 --- /dev/null +++ b/std/js/html/OrientationLockType.hx @@ -0,0 +1,37 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\ScreenOrientation.webidl. Do not edit! + +package js.html; + +@:enum abstract OrientationLockType(String) +{ + var ANY = "any"; + var NATURAL = "natural"; + var LANDSCAPE = "landscape"; + var PORTRAIT = "portrait"; + var PORTRAIT_PRIMARY = "portrait-primary"; + var PORTRAIT_SECONDARY = "portrait-secondary"; + var LANDSCAPE_PRIMARY = "landscape-primary"; + var LANDSCAPE_SECONDARY = "landscape-secondary"; +} \ No newline at end of file diff --git a/std/js/html/OrientationType.hx b/std/js/html/OrientationType.hx new file mode 100644 index 00000000..719bb9f5 --- /dev/null +++ b/std/js/html/OrientationType.hx @@ -0,0 +1,33 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\ScreenOrientation.webidl. Do not edit! + +package js.html; + +@:enum abstract OrientationType(String) +{ + var PORTRAIT_PRIMARY = "portrait-primary"; + var PORTRAIT_SECONDARY = "portrait-secondary"; + var LANDSCAPE_PRIMARY = "landscape-primary"; + var LANDSCAPE_SECONDARY = "landscape-secondary"; +} \ No newline at end of file diff --git a/std/js/html/OutputElement.hx b/std/js/html/OutputElement.hx index 078823f7..e2d496b4 100644 --- a/std/js/html/OutputElement.hx +++ b/std/js/html/OutputElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,21 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLOutputElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLOutputElement.webidl. Do not edit! package js.html; +/** + The `HTMLOutputElement` interface provides properties and methods (beyond those inherited from `HTMLElement`) for manipulating the layout and presentation of `output` elements. + + Documentation [HTMLOutputElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOutputElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOutputElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLOutputElement") extern class OutputElement extends Element { - var htmlFor(default,null) : DOMSettableTokenList; + var htmlFor(default,null) : DOMTokenList; var form(default,null) : FormElement; var name : String; var type(default,null) : String; diff --git a/std/js/html/PageTransitionEvent.hx b/std/js/html/PageTransitionEvent.hx index a3717391..8b6d56a2 100644 --- a/std/js/html/PageTransitionEvent.hx +++ b/std/js/html/PageTransitionEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PageTransitionEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\PageTransitionEvent.webidl. Do not edit! package js.html; +/** + Page transition events fire when a webpage is being loaded or unloaded. + + Documentation [PageTransitionEvent](https://developer.mozilla.org/en-US/docs/Web/API/PageTransitionEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PageTransitionEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("PageTransitionEvent") extern class PageTransitionEvent extends Event { diff --git a/std/js/html/PageTransitionEventInit.hx b/std/js/html/PageTransitionEventInit.hx index 9e4a014a..80bf178e 100644 --- a/std/js/html/PageTransitionEventInit.hx +++ b/std/js/html/PageTransitionEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PageTransitionEvent.webidl line 13:0. Do not edit! +// This file is generated from mozilla\PageTransitionEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/PaintRequest.hx b/std/js/html/PaintRequest.hx index 1f7ced38..3a283300 100644 --- a/std/js/html/PaintRequest.hx +++ b/std/js/html/PaintRequest.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PaintRequest.webidl line 10:0. Do not edit! +// This file is generated from mozilla\PaintRequest.webidl. Do not edit! package js.html; diff --git a/std/js/html/PaintRequestList.hx b/std/js/html/PaintRequestList.hx index 044dff8b..4ec1466b 100644 --- a/std/js/html/PaintRequestList.hx +++ b/std/js/html/PaintRequestList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PaintRequestList.webidl line 7:0. Do not edit! +// This file is generated from mozilla\PaintRequestList.webidl. Do not edit! package js.html; diff --git a/std/js/html/ParagraphElement.hx b/std/js/html/ParagraphElement.hx index 61ec87b3..9c7e2322 100644 --- a/std/js/html/ParagraphElement.hx +++ b/std/js/html/ParagraphElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLParagraphElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLParagraphElement.webidl. Do not edit! package js.html; +/** + The `HTMLParagraphElement` interface provides special properties (beyond those of the regular `HTMLElement` object interface it inherits) for manipulating `p` elements. + + Documentation [HTMLParagraphElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLParagraphElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLParagraphElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLParagraphElement") extern class ParagraphElement extends Element { diff --git a/std/js/html/ParamElement.hx b/std/js/html/ParamElement.hx index 38cbb984..b2afaef5 100644 --- a/std/js/html/ParamElement.hx +++ b/std/js/html/ParamElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,39 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLParamElement.webidl line 16:0. Do not edit! +// This file is generated from mozilla\HTMLParamElement.webidl. Do not edit! package js.html; +/** + The `HTMLParamElement` interface provides special properties (beyond those of the regular `HTMLElement` object interface it inherits) for manipulating `param` elements, representing a pair of a key and a value that acts as a parameter for an `object` element. + + Documentation [HTMLParamElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLParamElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLParamElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLParamElement") extern class ParamElement extends Element { + + /** + Is a `DOMString` representing the name of the parameter. It reflects the `name` attribute. + **/ var name : String; + + /** + Is a `DOMString` representing the value associated to the parameter. It reflects the `value` attribute. + **/ var value : String; + + /** + Is a `DOMString` containing the type of the parameter when `valueType` has the `"ref"` value. It reflects the `type` attribute. + **/ var type : String; + + /** + Is a `DOMString` containing the type of the `value`. It reflects the ``valuetype`` attribute and has one of the values: `"data"`, `"ref"`, or `"object"`. + **/ var valueType : String; } \ No newline at end of file diff --git a/std/js/html/Path2D.hx b/std/js/html/Path2D.hx index 4be08a0f..9ffbcb23 100644 --- a/std/js/html/Path2D.hx +++ b/std/js/html/Path2D.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CanvasRenderingContext2D.webidl line 330:0. Do not edit! +// This file is generated from mozilla\CanvasRenderingContext2D.webidl. Do not edit! package js.html; +/** + The `Path2D` interface of the Canvas 2D API is used to declare paths that are then later used on `CanvasRenderingContext2D` objects. The path methods of the `CanvasRenderingContext2D` interface are present on this interface as well and are allowing you to create paths that you can retain and replay as required on a canvas. + + Documentation [Path2D](https://developer.mozilla.org/en-US/docs/Web/API/Path2D) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Path2D$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Path2D") extern class Path2D { @@ -31,6 +38,10 @@ extern class Path2D @:overload( function() : Void {} ) @:overload( function( other : Path2D ) : Void {} ) function new( pathString : String ) : Void; + + /** + Adds a path to the current path. + **/ function addPath( path : Path2D, ?transformation : js.html.svg.Matrix ) : Void; function closePath() : Void; function moveTo( x : Float, y : Float ) : Void; @@ -42,4 +53,6 @@ extern class Path2D function rect( x : Float, y : Float, w : Float, h : Float ) : Void; /** @throws DOMError */ function arc( x : Float, y : Float, radius : Float, startAngle : Float, endAngle : Float, ?anticlockwise : Bool = false ) : Void; + /** @throws DOMError */ + function ellipse( x : Float, y : Float, radiusX : Float, radiusY : Float, rotation : Float, startAngle : Float, endAngle : Float, ?anticlockwise : Bool = false ) : Void; } \ No newline at end of file diff --git a/std/js/html/Performance.hx b/std/js/html/Performance.hx index 6b5db190..67db12f2 100644 --- a/std/js/html/Performance.hx +++ b/std/js/html/Performance.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Performance.webidl line 17:0. Do not edit! +// This file is generated from mozilla\Performance.webidl. Do not edit! package js.html; +/** + The `Performance` interface represents timing-related performance information for the given page. + + Documentation [Performance](https://developer.mozilla.org/en-US/docs/Web/API/Performance) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Performance$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Performance") extern class Performance { + + /** + Is a `PerformanceTiming` object containing latency-related performance information. + **/ var timing(default,null) : PerformanceTiming; + + /** + Is a `PerformanceNavigation` object representing the type of navigation that occurs in the given browsing context, like the amount of redirections needed to fetch the resource. + **/ var navigation(default,null) : PerformanceNavigation; + + /** + Returns a `DOMHighResTimeStamp` representing the amount of milliseconds elapsed since a reference instant. + **/ function now() : Float; } \ No newline at end of file diff --git a/std/js/html/PerformanceEntry.hx b/std/js/html/PerformanceEntry.hx index a418648f..8b1579ff 100644 --- a/std/js/html/PerformanceEntry.hx +++ b/std/js/html/PerformanceEntry.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,39 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PerformanceEntry.webidl line 13:0. Do not edit! +// This file is generated from mozilla\PerformanceEntry.webidl. Do not edit! package js.html; +/** + The `PerformanceEntry` object encapsulates a single performance metric that is part of the performance timeline. A performance entry can be directly created by making a performance `mark` or `measure` (for example by calling the `mark()` method) at an explicit point in an application. Performance entries are also created in indirect ways such as loading a resource (such as an image). + + Documentation [PerformanceEntry](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("PerformanceEntry") extern class PerformanceEntry { + + /** + A `DOMString` representing the name of a performance entry when the metric was created. + **/ var name(default,null) : String; + + /** + A `DOMString` representing the type of performance metric such as "`mark`". See `PerformanceEntry.entryType` for a list of valid values. + **/ var entryType(default,null) : String; + + /** + A `DOMHighResTimeStamp` representing the starting time for the performance metric. + **/ var startTime(default,null) : Float; + + /** + A `DOMHighResTimeStamp` representing the time value of the duration of the performance event. + **/ var duration(default,null) : Float; } \ No newline at end of file diff --git a/std/js/html/PerformanceMark.hx b/std/js/html/PerformanceMark.hx new file mode 100644 index 00000000..52705bdd --- /dev/null +++ b/std/js/html/PerformanceMark.hx @@ -0,0 +1,37 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\PerformanceMark.webidl. Do not edit! + +package js.html; + +/** + `PerformanceMark` is an abstract interface for `performance entries` with an `entry type` of "`mark`". Entries of this type are created by calling `performance.mark()` to add a named `DOMHighResTimeStamp` (the mark) to the browser's performance timeline. + + Documentation [PerformanceMark](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMark) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMark$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("PerformanceMark") +extern class PerformanceMark extends PerformanceEntry +{ +} \ No newline at end of file diff --git a/std/js/html/PerformanceMeasure.hx b/std/js/html/PerformanceMeasure.hx new file mode 100644 index 00000000..b7fc2695 --- /dev/null +++ b/std/js/html/PerformanceMeasure.hx @@ -0,0 +1,37 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\PerformanceMeasure.webidl. Do not edit! + +package js.html; + +/** + `PerformanceMeasure` is an abstract interface for `performance entries` with an `entry type` of "`measure`". Entries of this type are created by calling `performance.measure()` to add a named `DOMHighResTimeStamp` (the measure) between two marks to the browser's performance timeline. + + Documentation [PerformanceMeasure](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMeasure) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMeasure$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("PerformanceMeasure") +extern class PerformanceMeasure extends PerformanceEntry +{ +} \ No newline at end of file diff --git a/std/js/html/PerformanceNavigation.hx b/std/js/html/PerformanceNavigation.hx index 2725f3f6..b8fad9bf 100644 --- a/std/js/html/PerformanceNavigation.hx +++ b/std/js/html/PerformanceNavigation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PerformanceNavigation.webidl line 13:0. Do not edit! +// This file is generated from mozilla\PerformanceNavigation.webidl. Do not edit! package js.html; +/** + The `PerformanceNavigation` interface represents information about how the navigation to the current document was done. + + Documentation [PerformanceNavigation](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigation) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigation$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("PerformanceNavigation") extern class PerformanceNavigation { @@ -32,7 +39,47 @@ extern class PerformanceNavigation static inline var TYPE_BACK_FORWARD : Int = 2; static inline var TYPE_RESERVED : Int = 255; + + /** + Is an unsigned short containing a constant describing how the navigation to this page was done. Possible values are: + + + + Value + Constant name + Meaning + + + + + + + + + + + + + + + + + + + + + + + + +
0TYPE_NAVIGATEThe page was accessed by following a link, a bookmark, a form submission, a script, or typing the URL in the address bar.
1TYPE_RELOADThe page was accessed by clicking the Reload button or via the Location.reload() method.
2TYPE_BACK_FORWARDThe page was accessed by navigating into the history.
255TYPE_RESERVEDAny other way.
+ + **/ var type(default,null) : Int; + + /** + Is an `unsigned short` representing the number of REDIRECTs done before reaching the page. + **/ var redirectCount(default,null) : Int; } \ No newline at end of file diff --git a/std/js/html/PerformanceResourceTiming.hx b/std/js/html/PerformanceResourceTiming.hx index b22b22a9..77bf68ad 100644 --- a/std/js/html/PerformanceResourceTiming.hx +++ b/std/js/html/PerformanceResourceTiming.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,22 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PerformanceResourceTiming.webidl line 13:0. Do not edit! +// This file is generated from mozilla\PerformanceResourceTiming.webidl. Do not edit! package js.html; +/** + The `PerformanceResourceTiming` interface enables retrieving and analyzing detailed network timing data regarding the loading of an application's resources. An application can use the timing metrics to determine, for example, the length of time it takes to fetch a specific resource, such as an `XMLHttpRequest`, `SVG`, image, or script. + + Documentation [PerformanceResourceTiming](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("PerformanceResourceTiming") extern class PerformanceResourceTiming extends PerformanceEntry { var initiatorType(default,null) : String; + var nextHopProtocol(default,null) : String; var redirectStart(default,null) : Float; var redirectEnd(default,null) : Float; var fetchStart(default,null) : Float; @@ -39,5 +47,8 @@ extern class PerformanceResourceTiming extends PerformanceEntry var requestStart(default,null) : Float; var responseStart(default,null) : Float; var responseEnd(default,null) : Float; + var transferSize(default,null) : Int; + var encodedBodySize(default,null) : Int; + var decodedBodySize(default,null) : Int; } \ No newline at end of file diff --git a/std/js/html/PerformanceTiming.hx b/std/js/html/PerformanceTiming.hx index b6ae21f2..69329f14 100644 --- a/std/js/html/PerformanceTiming.hx +++ b/std/js/html/PerformanceTiming.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,32 +20,119 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PerformanceTiming.webidl line 13:0. Do not edit! +// This file is generated from mozilla\PerformanceTiming.webidl. Do not edit! package js.html; +/** + The `PerformanceTiming` interface represents timing-related performance information for the given page. + + Documentation [PerformanceTiming](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("PerformanceTiming") extern class PerformanceTiming { + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, right after the prompt for unload terminates on the previous document in the same browsing context. If there is no previous document, this value will be the same as `PerformanceTiming.fetchStart`. + **/ var navigationStart(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, the `unload` event has been thrown. If there is no previous document, or if the previous document, or one of the needed redirects, is not of the same origin, the value returned is `0`. + **/ var unloadEventStart(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, the `unload` event handler finishes. If there is no previous document, or if the previous document, or one of the needed redirects, is not of the same origin, the value returned is `0`. + **/ var unloadEventEnd(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, the first HTTP redirect starts. If there is no redirect, or if one of the redirects is not of the same origin, the value returned is `0`. + **/ var redirectStart(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, the last HTTP redirect is completed, that is when the last byte of the HTTP response has been received. If there is no redirect, or if one of the redirect is not of the same origin, the value returned is `0`. + **/ var redirectEnd(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, the browser is ready to fetch the document using an HTTP request. This moment is before the check to any application cache. + **/ var fetchStart(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, where the domain lookup starts. If a persistent connection is used, or the information is stored in a cache or a local resource, the value will be the same as `PerformanceTiming.fetchStart`. + **/ var domainLookupStart(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, where the domain lookup is finished. If a persistent connection is used, or the information is stored in a cache or a local resource, the value will be the same as `PerformanceTiming.fetchStart`. + **/ var domainLookupEnd(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, where the request to open a connection is sent to the network. If the transport layer reports an error and the connection establishment is started again, the last connection establisment start time is given. If a persistent connection is used, the value will be the same as `PerformanceTiming.fetchStart`. + **/ var connectStart(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, where the connection is opened network. If the transport layer reports an error and the connection establishment is started again, the last connection establisment end time is given. If a persistent connection is used, the value will be the same as `PerformanceTiming.fetchStart`. A connection is considered as opened when all secure connection handshake, or SOCKS authentication, is terminated. + **/ var connectEnd(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, when the browser sent the request to obtain the actual document, from the server or from a cache. If the transport layer fails after the start of the request and the connection is reopened, this property will be set to the time corresponding to the new request. + **/ var requestStart(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, when the browser received the first byte of the response, from the server from a cache, of from a local resource. + **/ var responseStart(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, when the browser received the last byte of the response, or when the connection is closed if this happened first, from the server from a cache, of from a local resource. + **/ var responseEnd(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, when the parser started its work, that is when its `Document.readyState` changes to `'loading'` and the corresponding `readystatechange` event is thrown. + **/ var domLoading(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, when the parser finished its work on the main document, that is when its `Document.readyState` changes to `'interactive'` and the corresponding `readystatechange` event is thrown. + **/ var domInteractive(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, right before the parser sent the `DOMContentLoaded` event, that is right after all the scripts that need to be executed right after parsing has been executed. + **/ var domContentLoadedEventStart(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, right after all the scripts that need to be executed as soon as possible, in order or not, has been executed. + **/ var domContentLoadedEventEnd(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, when the parser finished its work on the main document, that is when its `Document.readyState` changes to `'complete'` and the corresponding `readystatechange` event is thrown. + **/ var domComplete(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, when the `load` event was sent for the current document. If this event has not yet been sent, it returns `0.` + **/ var loadEventStart(default,null) : Int; + + /** + Is an `unsigned long long` representing the moment, in miliseconds since the UNIX epoch, when the `load` event handler terminated, that is when the load event is completed. If this event has not yet been sent, or is not yet completed, it returns `0.` + **/ var loadEventEnd(default,null) : Int; } \ No newline at end of file diff --git a/std/js/html/MediaKeyError.hx b/std/js/html/PermissionState.hx similarity index 82% rename from std/js/html/MediaKeyError.hx rename to std/js/html/PermissionState.hx index 469674dd..1b32bb50 100644 --- a/std/js/html/MediaKeyError.hx +++ b/std/js/html/PermissionState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaKeyError.webidl line 17:0. Do not edit! +// This file is generated from mozilla\PermissionStatus.webidl. Do not edit! package js.html; -@:native("MediaKeyError") -extern class MediaKeyError extends Event +@:enum abstract PermissionState(String) { - var systemCode(default,null) : Int; - + var GRANTED = "granted"; + var DENIED = "denied"; + var PROMPT = "prompt"; } \ No newline at end of file diff --git a/std/js/html/PermissionStatus.hx b/std/js/html/PermissionStatus.hx new file mode 100644 index 00000000..a04711c5 --- /dev/null +++ b/std/js/html/PermissionStatus.hx @@ -0,0 +1,48 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\PermissionStatus.webidl. Do not edit! + +package js.html; + +/** + The `PermissionStatus` interface of the Permissions API provides the state of an object and an event handler for monitoring changes to said state. + + Documentation [PermissionStatus](https://developer.mozilla.org/en-US/docs/Web/API/PermissionStatus) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PermissionStatus$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("PermissionStatus") +extern class PermissionStatus extends EventTarget +{ + + /** + Returns the state of a requested permission; one of `'granted'`, `'denied'`, or `'prompt'`. + **/ + var state(default,null) : PermissionState; + + /** + An event called whenever `PermissionStatus.status` changes. + **/ + var onchange : haxe.Constraints.Function; + +} \ No newline at end of file diff --git a/std/js/html/Permissions.hx b/std/js/html/Permissions.hx new file mode 100644 index 00000000..b73a5c34 --- /dev/null +++ b/std/js/html/Permissions.hx @@ -0,0 +1,47 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Permissions.webidl. Do not edit! + +package js.html; + +/** + Documentation [Permissions](https://developer.mozilla.org/en-US/docs/Web/API/Permissions) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Permissions$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("Permissions") +extern class Permissions +{ + /** @throws DOMError */ + + /** + Returns the user permission status for a given API. + **/ + function query( permission : Dynamic ) : Promise; + /** @throws DOMError */ + + /** + Revokes the permission currently set on a given API. + **/ + function revoke( permission : Dynamic ) : Promise; +} \ No newline at end of file diff --git a/std/js/html/PictureElement.hx b/std/js/html/PictureElement.hx index a3932c7e..c59af13e 100644 --- a/std/js/html/PictureElement.hx +++ b/std/js/html/PictureElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLPictureElement.webidl line 8:0. Do not edit! +// This file is generated from mozilla\HTMLPictureElement.webidl. Do not edit! package js.html; +/** + The `HTMLPictureElement` interface represents a `picture` HTML element. It doesn't implement specific properties or methods. + + Documentation [HTMLPictureElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLPictureElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLPictureElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLPictureElement") extern class PictureElement extends Element { diff --git a/std/js/html/PlaybackDirection.hx b/std/js/html/PlaybackDirection.hx new file mode 100644 index 00000000..25a780f5 --- /dev/null +++ b/std/js/html/PlaybackDirection.hx @@ -0,0 +1,33 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\AnimationEffectReadOnly.webidl. Do not edit! + +package js.html; + +@:enum abstract PlaybackDirection(String) +{ + var NORMAL = "normal"; + var REVERSE = "reverse"; + var ALTERNATE = "alternate"; + var ALTERNATE_REVERSE = "alternate-reverse"; +} \ No newline at end of file diff --git a/std/js/html/Plugin.hx b/std/js/html/Plugin.hx index cbf25ad8..bda6b165 100644 --- a/std/js/html/Plugin.hx +++ b/std/js/html/Plugin.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Plugin.webidl line 7:0. Do not edit! +// This file is generated from mozilla\Plugin.webidl. Do not edit! package js.html; +/** + The `Plugin` interface provides information about a browser plugin. + + Documentation [Plugin](https://developer.mozilla.org/en-US/docs/Web/API/Plugin) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Plugin$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Plugin") extern class Plugin implements ArrayAccess { diff --git a/std/js/html/PluginArray.hx b/std/js/html/PluginArray.hx index ade9cd79..4e10f4d4 100644 --- a/std/js/html/PluginArray.hx +++ b/std/js/html/PluginArray.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PluginArray.webidl line 7:0. Do not edit! +// This file is generated from mozilla\PluginArray.webidl. Do not edit! package js.html; +/** + The `PluginArray` interface is used to store a list of `Plugin` objects describing the available plugins; it's returned by the `window.navigator.plugins` property. The `PluginArray` is not a JavaScript array, but has the `length` property and supports accessing individual items using bracket notation (`plugins[2]`), as well as via `item(index)` and `namedItem("name")` methods. + + Documentation [PluginArray](https://developer.mozilla.org/en-US/docs/Web/API/PluginArray) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PluginArray$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("PluginArray") extern class PluginArray implements ArrayAccess { diff --git a/std/js/html/PointerEvent.hx b/std/js/html/PointerEvent.hx index 90323aa1..b777a117 100644 --- a/std/js/html/PointerEvent.hx +++ b/std/js/html/PointerEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PointerEvent.webidl line 14:0. Do not edit! +// This file is generated from mozilla\PointerEvent.webidl. Do not edit! package js.html; +/** + The `PointerEvent` interface represents the state of a DOM event produced by a pointer such as the geometry of the contact point, the device type that generated the event, the amount of pressure that was applied on the contact surface, etc. + + Documentation [PointerEvent](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("PointerEvent") extern class PointerEvent extends MouseEvent { diff --git a/std/js/html/PointerEventInit.hx b/std/js/html/PointerEventInit.hx index 7ed0b82a..9e12ec2f 100644 --- a/std/js/html/PointerEventInit.hx +++ b/std/js/html/PointerEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PointerEvent.webidl line 26:0. Do not edit! +// This file is generated from mozilla\PointerEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/PopStateEvent.hx b/std/js/html/PopStateEvent.hx index ff7e3df8..76c12269 100644 --- a/std/js/html/PopStateEvent.hx +++ b/std/js/html/PopStateEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PopStateEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\PopStateEvent.webidl. Do not edit! package js.html; +/** + An event handler for the `popstate` event on the window. + + Documentation [PopStateEvent](https://developer.mozilla.org/en-US/docs/Web/API/PopStateEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PopStateEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("PopStateEvent") extern class PopStateEvent extends Event { diff --git a/std/js/html/PopStateEventInit.hx b/std/js/html/PopStateEventInit.hx index 68cb71f6..a7ee176d 100644 --- a/std/js/html/PopStateEventInit.hx +++ b/std/js/html/PopStateEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PopStateEvent.webidl line 13:0. Do not edit! +// This file is generated from mozilla\PopStateEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/PopupBlockedEvent.hx b/std/js/html/PopupBlockedEvent.hx index fe20c579..a98d95e7 100644 --- a/std/js/html/PopupBlockedEvent.hx +++ b/std/js/html/PopupBlockedEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PopupBlockedEvent.webidl line 9:0. Do not edit! +// This file is generated from mozilla\PopupBlockedEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/PopupBlockedEventInit.hx b/std/js/html/PopupBlockedEventInit.hx index 4f9538bf..138d5650 100644 --- a/std/js/html/PopupBlockedEventInit.hx +++ b/std/js/html/PopupBlockedEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PopupBlockedEvent.webidl line 17:0. Do not edit! +// This file is generated from mozilla\PopupBlockedEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/Position.hx b/std/js/html/Position.hx index 2c55bf0c..a93ca6a5 100644 --- a/std/js/html/Position.hx +++ b/std/js/html/Position.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Position.webidl line 14:0. Do not edit! +// This file is generated from mozilla\Position.webidl. Do not edit! package js.html; +/** + The `Position` interface represents the position of the concerned device at a given time. The position, represented by a `Coordinates` object, comprehends the 2D position of the device, on a spheroid representing the Earth, but also its altitude and its speed. + + Documentation [Position](https://developer.mozilla.org/en-US/docs/Web/API/Position) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Position$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Position") extern class Position { + + /** + Returns a `Coordinates` object defining the current location. + **/ var coords(default,null) : Coordinates; + + /** + Returns a `DOMTimeStamp` representing the time at which the location was retrieved. + **/ var timestamp(default,null) : Int; } \ No newline at end of file diff --git a/std/js/html/PositionError.hx b/std/js/html/PositionError.hx index e4f8647d..d2756f41 100644 --- a/std/js/html/PositionError.hx +++ b/std/js/html/PositionError.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PositionError.webidl line 14:0. Do not edit! +// This file is generated from mozilla\PositionError.webidl. Do not edit! package js.html; +/** + The `PositionError` interface represents the reason of an error occurring when using the geolocating device. + + Documentation [PositionError](https://developer.mozilla.org/en-US/docs/Web/API/PositionError) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PositionError$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("PositionError") extern class PositionError { @@ -31,7 +38,40 @@ extern class PositionError static inline var POSITION_UNAVAILABLE : Int = 2; static inline var TIMEOUT : Int = 3; + + /** + Returns an unsigned short representing the error code. The following values are possible: + + + + Value + Associated constant + Description + + + + + + + + + + + + + + + + + +
1PERMISSION_DENIEDThe acquisition of the geolocation information failed because the page didn't have the permission to do it.
2POSITION_UNAVAILABLEThe acquisition of the geolocation failed because at least one internal source of position returned an internal error.
3TIMEOUTThe time allowed to acquire the geolocation, defined by PositionOptions.timeout information was reached before the information was obtained.
+ + **/ var code(default,null) : Int; + + /** + Returns a human-readable `DOMString` describing the details of the error. Specifications note that this is primarily intended for debugging use and not to be shown directly in a user interface. + **/ var message(default,null) : String; } \ No newline at end of file diff --git a/std/js/html/PositionOptions.hx b/std/js/html/PositionOptions.hx index 5ccd9b2b..46946e5d 100644 --- a/std/js/html/PositionOptions.hx +++ b/std/js/html/PositionOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,32 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Geolocation.webidl line 13:0. Do not edit! +// This file is generated from mozilla\Geolocation.webidl. Do not edit! package js.html; +/** + The `PositionOptions` interface describes an object containing option properties to pass as a parameter of `Geolocation.getCurrentPosition()` and `Geolocation.watchPosition()`. + + Documentation [PositionOptions](https://developer.mozilla.org/en-US/docs/Web/API/PositionOptions) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PositionOptions$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ typedef PositionOptions = { - @:optional var enableHighAccuracy : Bool; - @:optional var maximumAge : Int; - @:optional var timeout : Int; + @:optional + /** + Is a `Boolean` that indicates the application would like to receive the best possible results. If `true` and if the device is able to provide a more accurate position, it will do so. Note that this can result in slower response times or increased power consumption (with a GPS chip on a mobile device for example). On the other hand, if `false`, the device can take the liberty to save resources by responding more quickly and/or using less power. Default: `false`. + **/ + var enableHighAccuracy : Bool; + @:optional + /** + Is a positive `long` value indicating the maximum age in milliseconds of a possible cached position that is acceptable to return. If set to `0`, it means that the device cannot use a cached position and must attempt to retrieve the real current position. If set to `Infinity` the device must return a cached position regardless of its age. Default: 0. + **/ + var maximumAge : Int; + @:optional + /** + Is a positive `long` value representing the maximum length of time (in milliseconds) the device is allowed to take in order to return a position. The default value is `Infinity`, meaning that `getCurrentPosition()` won't return until the position is available. + **/ + var timeout : Int; } \ No newline at end of file diff --git a/std/js/html/PreElement.hx b/std/js/html/PreElement.hx index 01a2a465..06addf10 100644 --- a/std/js/html/PreElement.hx +++ b/std/js/html/PreElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLPreElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLPreElement.webidl. Do not edit! package js.html; +/** + The `HTMLPreElement` interface expose specific properties and methods (beyond those defined by regular `HTMLElement` interface it also has available to it by inheritance) for manipulating block of preformatted text. + + Documentation [HTMLPreElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLPreElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLPreElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLPreElement") extern class PreElement extends Element { + + /** + Is a `long` value reflecting the obsolete `width` attribute, containing a fixed-size length for the `pre` element. + **/ var width : Int; } \ No newline at end of file diff --git a/std/js/html/ProcessingInstruction.hx b/std/js/html/ProcessingInstruction.hx index 4cfa309b..917f1f4c 100644 --- a/std/js/html/ProcessingInstruction.hx +++ b/std/js/html/ProcessingInstruction.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ProcessingInstruction.webidl line 13:0. Do not edit! +// This file is generated from mozilla\ProcessingInstruction.webidl. Do not edit! package js.html; +/** + A processing instruction provides an opportunity for application-specific instructions to be embedded within XML and which can be ignored by XML processors which do not support processing their instructions (outside of their having a place in the DOM). + + Documentation [ProcessingInstruction](https://developer.mozilla.org/en-US/docs/Web/API/ProcessingInstruction) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ProcessingInstruction$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("ProcessingInstruction") extern class ProcessingInstruction extends CharacterData { diff --git a/std/js/html/ProgressElement.hx b/std/js/html/ProgressElement.hx index 6f0052f4..ec57f46d 100644 --- a/std/js/html/ProgressElement.hx +++ b/std/js/html/ProgressElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLProgressElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLProgressElement.webidl. Do not edit! package js.html; +/** + The `HTMLProgressElement` interface provides special properties and methods (beyond the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating the layout and presentation of `progress` elements. + + Documentation [HTMLProgressElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLProgressElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLProgressElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLProgressElement") extern class ProgressElement extends Element { + + /** + Is a `double` value that reflects the current value; if the progress bar is an indeterminate progress bar, it returns `0`. + **/ var value : Float; + + /** + Is a `double` value reflecting the content attribute of the same name, limited to numbers greater than zero. Its default value is `1.0`. + **/ var max : Float; + + /** + Returns a `double` value returning the result of dividing the current value (`value`) by the maximum value (`max`); if the progress bar is an indeterminate progress bar, it returns `-1`. + **/ var position(default,null) : Float; } \ No newline at end of file diff --git a/std/js/html/ProgressEvent.hx b/std/js/html/ProgressEvent.hx index e0ade5ad..28953291 100644 --- a/std/js/html/ProgressEvent.hx +++ b/std/js/html/ProgressEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ProgressEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\ProgressEvent.webidl. Do not edit! package js.html; +/** + The `ProgressEvent` interface represents events measuring progress of an underlying process, like an HTTP request (for an `XMLHttpRequest`, or the loading of the underlying resource of an `img`, `audio`, `video`, `style` or `link`). + + Documentation [ProgressEvent](https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("ProgressEvent") extern class ProgressEvent extends Event { + + /** + Is a `Boolean` flag indicating if the total work to be done, and the amount of work already done, by the underlying process is calculable. In other words, it tells if the progress is measurable or not. + **/ var lengthComputable(default,null) : Bool; + + /** + Is an `unsigned long long` representing the amount of work already performed by the underlying process. The ratio of work done can be calculated with the property and `ProgressEvent.total`. When downloading a resource using HTTP, this only represent the part of the content itself, not headers and other overhead. + **/ var loaded(default,null) : Int; + + /** + Is an `unsigned long long` representing the total amount of work that the underlying process is in the progress of performing. When downloading a resource using HTTP, this only represent the content itself, not headers and other overhead. + **/ var total(default,null) : Int; /** @throws DOMError */ diff --git a/std/js/html/ProgressEventInit.hx b/std/js/html/ProgressEventInit.hx index 8b1e81cf..be916a48 100644 --- a/std/js/html/ProgressEventInit.hx +++ b/std/js/html/ProgressEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ProgressEvent.webidl line 15:0. Do not edit! +// This file is generated from mozilla\ProgressEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/PropertyNodeList.hx b/std/js/html/PropertyNodeList.hx index 99b7991b..a1537f91 100644 --- a/std/js/html/PropertyNodeList.hx +++ b/std/js/html/PropertyNodeList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLPropertiesCollection.webidl line 21:0. Do not edit! +// This file is generated from mozilla\HTMLPropertiesCollection.webidl. Do not edit! package js.html; diff --git a/std/js/html/QuoteElement.hx b/std/js/html/QuoteElement.hx index 563eb5ac..25a0f42a 100644 --- a/std/js/html/QuoteElement.hx +++ b/std/js/html/QuoteElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLQuoteElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLQuoteElement.webidl. Do not edit! package js.html; +/** + The `HTMLQuoteElement` interface provides special properties and methods (beyond the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating quoting elements, like `blockquote` and `q`, but not the `cite` element. + + Documentation [HTMLQuoteElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLQuoteElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLQuoteElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLQuoteElement") extern class QuoteElement extends Element { + + /** + Is a `DOMString` reflecting the `cite` HTML attribute, containing a URL for the source of the quotation. + **/ var cite : String; } \ No newline at end of file diff --git a/std/js/html/RGBColor.hx b/std/js/html/RGBColor.hx index 0677a75a..bc79cade 100644 --- a/std/js/html/RGBColor.hx +++ b/std/js/html/RGBColor.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RGBColor.webidl line 10:0. Do not edit! +// This file is generated from mozilla\RGBColor.webidl. Do not edit! package js.html; diff --git a/std/js/html/RadioNodeList.hx b/std/js/html/RadioNodeList.hx index a3805c75..017a54dc 100644 --- a/std/js/html/RadioNodeList.hx +++ b/std/js/html/RadioNodeList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RadioNodeList.webidl line 14:0. Do not edit! +// This file is generated from mozilla\RadioNodeList.webidl. Do not edit! package js.html; +/** + The `RadioNodeList` interface represents a collection of elements in a `form` or a `fieldset` element. + + Documentation [RadioNodeList](https://developer.mozilla.org/en-US/docs/Web/API/RadioNodeList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/RadioNodeList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("RadioNodeList") extern class RadioNodeList extends NodeList { + + /** + If the underlying element collection contains radio buttons, the `value` property represents the checked radio button. On retrieving the `value` property, the `value` of the currently `checked` radio button is returned as a string. If the collection does not contain any radio buttons or none of the radio buttons in the collection is in `checked` state, the empty string is returned. On setting the `value` property, the first radio button input element whose `value` property is equal to the new value will be set to `checked`. + **/ var value : String; } \ No newline at end of file diff --git a/std/js/html/Range.hx b/std/js/html/Range.hx index af3a63b0..fae6c7eb 100644 --- a/std/js/html/Range.hx +++ b/std/js/html/Range.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Range.webidl line 16:0. Do not edit! +// This file is generated from mozilla\Range.webidl. Do not edit! package js.html; +/** + The `Range` interface represents a fragment of a document that can contain nodes and parts of text nodes. + + Documentation [Range](https://developer.mozilla.org/en-US/docs/Web/API/Range) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Range$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Range") extern class Range { @@ -32,11 +39,35 @@ extern class Range static inline var END_TO_END : Int = 2; static inline var END_TO_START : Int = 3; + + /** + Returns the `Node` within which the `Range` starts. + **/ var startContainer(default,null) : Node; + + /** + Returns a number representing where in the `startContainer` the `Range` starts. + **/ var startOffset(default,null) : Int; + + /** + Returns the `Node` within which the `Range` ends. + **/ var endContainer(default,null) : Node; + + /** + Returns a number representing where in the `endContainer` the `Range` ends. + **/ var endOffset(default,null) : Int; + + /** + Returns a `Boolean` indicating whether the range's start and end points are at the same position. + **/ var collapsed(default,null) : Bool; + + /** + Returns the deepest `Node` that contains the `startContainer` and `endContainer` nodes. + **/ var commonAncestorContainer(default,null) : Node; /** @throws DOMError */ diff --git a/std/js/html/RecordErrorEvent.hx b/std/js/html/RecordErrorEvent.hx index 104833b5..982a5acc 100644 --- a/std/js/html/RecordErrorEvent.hx +++ b/std/js/html/RecordErrorEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RecordErrorEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\RecordErrorEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/RecordErrorEventInit.hx b/std/js/html/RecordErrorEventInit.hx index 48830254..fafd0143 100644 --- a/std/js/html/RecordErrorEventInit.hx +++ b/std/js/html/RecordErrorEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RecordErrorEvent.webidl line 13:0. Do not edit! +// This file is generated from mozilla\RecordErrorEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/RecordingState.hx b/std/js/html/RecordingState.hx index 5cab041e..e30d6810 100644 --- a/std/js/html/RecordingState.hx +++ b/std/js/html/RecordingState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaRecorder.webidl line 13:0. Do not edit! +// This file is generated from mozilla\MediaRecorder.webidl. Do not edit! package js.html; diff --git a/std/js/html/Rect.hx b/std/js/html/Rect.hx index d420283e..b928fbd8 100644 --- a/std/js/html/Rect.hx +++ b/std/js/html/Rect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Rect.webidl line 7:0. Do not edit! +// This file is generated from mozilla\Rect.webidl. Do not edit! package js.html; diff --git a/std/js/html/ReferrerPolicy.hx b/std/js/html/ReferrerPolicy.hx new file mode 100644 index 00000000..0ee82879 --- /dev/null +++ b/std/js/html/ReferrerPolicy.hx @@ -0,0 +1,35 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Request.webidl. Do not edit! + +package js.html; + +@:enum abstract ReferrerPolicy(String) +{ + var NONE = ""; + var NO_REFERRER = "no-referrer"; + var NO_REFERRER_WHEN_DOWNGRADE = "no-referrer-when-downgrade"; + var ORIGIN_ONLY = "origin-only"; + var ORIGIN_WHEN_CROSS_ORIGIN = "origin-when-cross-origin"; + var UNSAFE_URL = "unsafe-url"; +} \ No newline at end of file diff --git a/std/js/html/Request.hx b/std/js/html/Request.hx new file mode 100644 index 00000000..321a35a0 --- /dev/null +++ b/std/js/html/Request.hx @@ -0,0 +1,102 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Request.webidl. Do not edit! + +package js.html; + +/** + The `Request` interface of the Fetch API represents a resource request. + + Documentation [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Request$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("Request") +extern class Request +{ + + /** + Contains the request's method (`GET`, `POST`, etc.) + **/ + var method(default,null) : String; + + /** + Contains the URL of the request. + **/ + var url(default,null) : String; + + /** + Contains the associated `Headers` object of the request. + **/ + var headers(default,null) : Headers; + + /** + Contains the referrer of the request (e.g., `client`). + **/ + var referrer(default,null) : String; + + /** + Contains the referrer policy of the request (e.g., `no-referrer`). + **/ + var referrerPolicy(default,null) : ReferrerPolicy; + + /** + Contains the mode of the request (e.g., `cors`, `no-cors`, `same-origin`, `navigate`.) + **/ + var mode(default,null) : RequestMode; + + /** + Contains the credentials of the request (e.g., `omit`, `same-origin`). + **/ + var credentials(default,null) : RequestCredentials; + + /** + Contains the cache mode of the request (e.g., `default`, `reload`, `no-cache`). + **/ + var cache(default,null) : RequestCache; + + /** + Contains the mode for how redirects are handled. It may be one of `follow`, `error`, or `manual`. + **/ + var redirect(default,null) : RequestRedirect; + var bodyUsed(default,null) : Bool; + + /** @throws DOMError */ + function new( input : haxe.extern.EitherType, ?init : RequestInit ) : Void; + /** @throws DOMError */ + + /** + Creates a copy of the current `Request` object. + **/ + function clone() : Request; + /** @throws DOMError */ + function arrayBuffer() : Promise; + /** @throws DOMError */ + function blob() : Promise; + /** @throws DOMError */ + function formData() : Promise; + /** @throws DOMError */ + function json() : Promise; + /** @throws DOMError */ + function text() : Promise; +} \ No newline at end of file diff --git a/std/js/html/RequestCache.hx b/std/js/html/RequestCache.hx new file mode 100644 index 00000000..a0b5c781 --- /dev/null +++ b/std/js/html/RequestCache.hx @@ -0,0 +1,34 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Request.webidl. Do not edit! + +package js.html; + +@:enum abstract RequestCache(String) +{ + var DEFAULT_ = "default"; + var NO_STORE = "no-store"; + var RELOAD = "reload"; + var NO_CACHE = "no-cache"; + var FORCE_CACHE = "force-cache"; +} \ No newline at end of file diff --git a/std/js/html/RequestCredentials.hx b/std/js/html/RequestCredentials.hx new file mode 100644 index 00000000..b6857fbf --- /dev/null +++ b/std/js/html/RequestCredentials.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Request.webidl. Do not edit! + +package js.html; + +@:enum abstract RequestCredentials(String) +{ + var OMIT = "omit"; + var SAME_ORIGIN = "same-origin"; + var INCLUDE = "include"; +} \ No newline at end of file diff --git a/std/js/html/RequestInit.hx b/std/js/html/RequestInit.hx new file mode 100644 index 00000000..beb7a587 --- /dev/null +++ b/std/js/html/RequestInit.hx @@ -0,0 +1,38 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Request.webidl. Do not edit! + +package js.html; + +typedef RequestInit = +{ + @:optional var body : haxe.extern.EitherType>>>>; + @:optional var cache : RequestCache; + @:optional var credentials : RequestCredentials; + @:optional var headers : haxe.extern.EitherType>,Dynamic/*MISSING ByteStringMozMap*/>>; + @:optional var method : String; + @:optional var mode : RequestMode; + @:optional var redirect : RequestRedirect; + @:optional var referrer : String; + @:optional var referrerPolicy : ReferrerPolicy; +} \ No newline at end of file diff --git a/std/js/html/RequestMode.hx b/std/js/html/RequestMode.hx new file mode 100644 index 00000000..d625aa83 --- /dev/null +++ b/std/js/html/RequestMode.hx @@ -0,0 +1,33 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Request.webidl. Do not edit! + +package js.html; + +@:enum abstract RequestMode(String) +{ + var SAME_ORIGIN = "same-origin"; + var NO_CORS = "no-cors"; + var CORS = "cors"; + var NAVIGATE = "navigate"; +} \ No newline at end of file diff --git a/std/js/html/AnimationEffect.hx b/std/js/html/RequestRedirect.hx similarity index 83% rename from std/js/html/AnimationEffect.hx rename to std/js/html/RequestRedirect.hx index ea84d01e..0f13da35 100644 --- a/std/js/html/AnimationEffect.hx +++ b/std/js/html/RequestRedirect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AnimationEffect.webidl line 14:0. Do not edit! +// This file is generated from mozilla\Request.webidl. Do not edit! package js.html; -@:native("AnimationEffect") -extern class AnimationEffect +@:enum abstract RequestRedirect(String) { - var name(default,null) : String; - + var FOLLOW = "follow"; + var ERROR = "error"; + var MANUAL = "manual"; } \ No newline at end of file diff --git a/std/js/html/Response.hx b/std/js/html/Response.hx new file mode 100644 index 00000000..7a1d0e02 --- /dev/null +++ b/std/js/html/Response.hx @@ -0,0 +1,98 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Response.webidl. Do not edit! + +package js.html; + +/** + The `Response` interface of the Fetch API represents the response to a request. + + Documentation [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Response$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("Response") +extern class Response +{ + static + /** + Returns a new `Response` object associated with a network error. + **/ + function error() : Response; + /** @throws DOMError */ + static + /** + Creates a new response with a different URL. + **/ + function redirect( url : String, ?status : Int = 302 ) : Response; + + /** + Contains the type of the response (e.g., `basic`, `cors`). + **/ + var type(default,null) : ResponseType; + + /** + Contains the URL of the response. + **/ + var url(default,null) : String; + + /** + Contains the status code of the response (e.g., `200` for a success). + **/ + var status(default,null) : Int; + + /** + Contains a boolean stating whether the response was successful (status in the range 200-299) or not. + **/ + var ok(default,null) : Bool; + + /** + Contains the status message corresponding to the status code (e.g., `OK` for `200`). + **/ + var statusText(default,null) : String; + + /** + Contains the `Headers` object associated with the response. + **/ + var headers(default,null) : Headers; + var bodyUsed(default,null) : Bool; + + /** @throws DOMError */ + function new( ?body : haxe.extern.EitherType>>>>, ?init : ResponseInit ) : Void; + /** @throws DOMError */ + + /** + Creates a clone of a `Response` object. + **/ + function clone() : Response; + /** @throws DOMError */ + function arrayBuffer() : Promise; + /** @throws DOMError */ + function blob() : Promise; + /** @throws DOMError */ + function formData() : Promise; + /** @throws DOMError */ + function json() : Promise; + /** @throws DOMError */ + function text() : Promise; +} \ No newline at end of file diff --git a/std/js/html/ResponseInit.hx b/std/js/html/ResponseInit.hx new file mode 100644 index 00000000..28177a50 --- /dev/null +++ b/std/js/html/ResponseInit.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Response.webidl. Do not edit! + +package js.html; + +typedef ResponseInit = +{ + @:optional var headers : haxe.extern.EitherType>,Dynamic/*MISSING ByteStringMozMap*/>>; + @:optional var status : Int; + @:optional var statusText : String; +} \ No newline at end of file diff --git a/std/js/html/ResponseType.hx b/std/js/html/ResponseType.hx new file mode 100644 index 00000000..f920563d --- /dev/null +++ b/std/js/html/ResponseType.hx @@ -0,0 +1,35 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Response.webidl. Do not edit! + +package js.html; + +@:enum abstract ResponseType(String) +{ + var BASIC = "basic"; + var CORS = "cors"; + var DEFAULT_ = "default"; + var ERROR = "error"; + var OPAQUE = "opaque"; + var OPAQUEREDIRECT = "opaqueredirect"; +} \ No newline at end of file diff --git a/std/js/html/Screen.hx b/std/js/html/Screen.hx index a825ea96..31cd640e 100644 --- a/std/js/html/Screen.hx +++ b/std/js/html/Screen.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Screen.webidl line 6:0. Do not edit! +// This file is generated from mozilla\Screen.webidl. Do not edit! package js.html; +/** + The `Screen` interface represents a screen, usually the one on which the current window is being rendered. + + Documentation [Screen](https://developer.mozilla.org/en-US/docs/Web/API/Screen) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Screen$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Screen") extern class Screen extends EventTarget { @@ -37,5 +44,6 @@ extern class Screen extends EventTarget var left(default,null) : Int; var availTop(default,null) : Int; var availLeft(default,null) : Int; + var orientation(default,null) : ScreenOrientation; } \ No newline at end of file diff --git a/std/js/html/MediaKeyMessageEvent.hx b/std/js/html/ScreenOrientation.hx similarity index 71% rename from std/js/html/MediaKeyMessageEvent.hx rename to std/js/html/ScreenOrientation.hx index f5495275..41dfcad7 100644 --- a/std/js/html/MediaKeyMessageEvent.hx +++ b/std/js/html/ScreenOrientation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,19 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaKeyMessageEvent.webidl line 20:0. Do not edit! +// This file is generated from mozilla\ScreenOrientation.webidl. Do not edit! package js.html; -@:native("MediaKeyMessageEvent") -extern class MediaKeyMessageEvent extends Event +@:native("ScreenOrientation") +extern class ScreenOrientation extends EventTarget { - var messageType(default,null) : MediaKeyMessageType; - var message(default,null) : ArrayBuffer; + var type(default,null) : OrientationType; + var angle(default,null) : Int; + var onchange : haxe.Constraints.Function; /** @throws DOMError */ - function new( type : String, ?eventInitDict : MediaKeyMessageEventInit ) : Void; + function lock( orientation : OrientationLockType ) : Promise; + /** @throws DOMError */ + function unlock() : Void; } \ No newline at end of file diff --git a/std/js/html/ScriptElement.hx b/std/js/html/ScriptElement.hx index 3ca3942a..de273488 100644 --- a/std/js/html/ScriptElement.hx +++ b/std/js/html/ScriptElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLScriptElement.webidl line 11:0. Do not edit! +// This file is generated from mozilla\HTMLScriptElement.webidl. Do not edit! package js.html; +/** + HTML script elements expose the `HTMLScriptElement` interface, which provides special properties and methods (beyond the regular `HTMLElement` object interface they also have available to them by inheritance) for manipulating the layout and presentation of `script` elements. + + Documentation [HTMLScriptElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLScriptElement") extern class ScriptElement extends Element { @@ -36,5 +43,6 @@ extern class ScriptElement extends Element var text : String; var event : String; var htmlFor : String; + var integrity : String; } \ No newline at end of file diff --git a/std/js/html/ScrollAreaEvent.hx b/std/js/html/ScrollAreaEvent.hx index 0cea34ed..6fb50c6e 100644 --- a/std/js/html/ScrollAreaEvent.hx +++ b/std/js/html/ScrollAreaEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ScrollAreaEvent.webidl line 7:0. Do not edit! +// This file is generated from mozilla\ScrollAreaEvent.webidl. Do not edit! package js.html; @@ -32,6 +32,5 @@ extern class ScrollAreaEvent extends UIEvent var width(default,null) : Float; var height(default,null) : Float; - /** @throws DOMError */ function initScrollAreaEvent( type : String, canBubble : Bool, cancelable : Bool, view : Window, detail : Int, x : Float, y : Float, width : Float, height : Float ) : Void; } \ No newline at end of file diff --git a/std/js/html/ScrollIntoViewOptions.hx b/std/js/html/ScrollIntoViewOptions.hx index 4a80ea28..8843fe0b 100644 --- a/std/js/html/ScrollIntoViewOptions.hx +++ b/std/js/html/ScrollIntoViewOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Element.webidl line 161:0. Do not edit! +// This file is generated from mozilla\Element.webidl. Do not edit! package js.html; diff --git a/std/js/html/ScrollOptions.hx b/std/js/html/ScrollOptions.hx index fd8f9af4..032c623e 100644 --- a/std/js/html/ScrollOptions.hx +++ b/std/js/html/ScrollOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Window.webidl line 151:0. Do not edit! +// This file is generated from mozilla\Window.webidl. Do not edit! package js.html; diff --git a/std/js/html/CSSMatrix.hx b/std/js/html/ScrollRestoration.hx similarity index 84% rename from std/js/html/CSSMatrix.hx rename to std/js/html/ScrollRestoration.hx index c1add5ca..f060d7de 100644 --- a/std/js/html/CSSMatrix.hx +++ b/std/js/html/ScrollRestoration.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,8 +20,12 @@ * DEALINGS IN THE SOFTWARE. */ +// This file is generated from mozilla\History.webidl. Do not edit! + package js.html; -/** @deprecated Use DOMMatrix instead. */ -@:deprecated("CSSMatrix is deprecated, use DOMMatrix instead") -typedef CSSMatrix = DOMMatrix; +@:enum abstract ScrollRestoration(String) +{ + var AUTO = "auto"; + var MANUAL = "manual"; +} \ No newline at end of file diff --git a/std/js/html/ScrollToOptions.hx b/std/js/html/ScrollToOptions.hx index f75d7f9b..f7b842b4 100644 --- a/std/js/html/ScrollToOptions.hx +++ b/std/js/html/ScrollToOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Window.webidl line 155:0. Do not edit! +// This file is generated from mozilla\Window.webidl. Do not edit! package js.html; diff --git a/std/js/html/SelectElement.hx b/std/js/html/SelectElement.hx index 72cc373a..eff6b77a 100644 --- a/std/js/html/SelectElement.hx +++ b/std/js/html/SelectElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,34 +20,125 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLSelectElement.webidl line 10:0. Do not edit! +// This file is generated from mozilla\HTMLSelectElement.webidl. Do not edit! package js.html; +/** + The `HTMLSelectElement` interface represents a `select` HTML Element. These elements also share all of the properties and methods of other HTML elements via the `HTMLElement` interface. + + Documentation [HTMLSelectElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLSelectElement") extern class SelectElement extends Element implements ArrayAccess { + + /** + Is a `Boolean` that reflects the `autofocus` HTML attribute, which indicates whether the control should have input focus when the page loads, unless the user overrides it, for example by typing in a different control. Only one form-associated element in a document can have this attribute specified. `2.0` + **/ var autofocus : Bool; + + /** + Is a `Boolean` that reflects the `disabled` HTML attribute, which indicates whether the control is disabled. If it is disabled, it does not accept clicks. + **/ var disabled : Bool; + + /** + Returns a `HTMLFormElement` representing the form that this element is associated with. If the element is not associated with of a `form` element, then it returns `null`. + **/ var form(default,null) : FormElement; + + /** + Is a `Boolean` that reflects the `multiple` HTML attribute, which indicates whether multiple items can be selected. + **/ var multiple : Bool; + + /** + Is a `DOMString` that reflects the `name` HTML attribute, containing the name of this control used by servers and DOM search functions. + **/ var name : String; + + /** + Is a `Boolean` that reflects the `required` HTML attribute, which indicates whether the user is required to select a value before submitting the form. `2.0` + **/ var required : Bool; + + /** + Is a `long` that reflects the `size` HTML attribute, which contains the number of visible items in the control. The default is 1, unless `multiple` is true, in which case it is 4. + **/ var size : Int; + + /** + Returns a `DOMString` the form control's type. When `multiple` is `true`, it returns `"select-multiple"`; otherwise, it returns `"select-one"`. + **/ var type(default,null) : String; + + /** + Returns a `HTMLOptionsCollection` containing the set of `option` elements contained by this element. + **/ var options(default,null) : HTMLOptionsCollection; + + /** + Is a `unsigned long` representing the number of `option` elements in this `select` element. + **/ var length : Int; + + /** + Returns a live `HTMLCollection` containing the set of options that are selected. + **/ var selectedOptions(default,null) : HTMLCollection; + + /** + Is a `long` that reflects the index of the first selected `option` element. The value `-1` indicates no element is selected. + **/ var selectedIndex : Int; + + /** + Is a `DOMString` representing the value of the form control (the first selected option). + **/ var value : String; + + /** + Is a `Boolean` that indicates whether the button is a candidate for constraint validation. It is false if any conditions bar it from constraint validation. + **/ var willValidate(default,null) : Bool; + + /** + Returns a `ValidityState` representing the validity state that this control is in. + **/ var validity(default,null) : ValidityState; + + /** + Returns a `DOMString` containing a localized message that describes the validation constraints that the control does not satisfy (if any). This attribute is the empty string if the control is not a candidate for constraint validation (`willValidate` is false), or it satisfies its constraints. + **/ var validationMessage(default,null) : String; + + /** + Gets an item from the options collection for this `select` element. You can also access an item by specifying the index in array-style brackets or parentheses, without calling this method explicitly. + **/ function item( index : Int ) : Element; + + /** + Gets the item in the options collection with the specified name. The name string can match either the `id` or the `name` attribute of an option node. You can also access an item by specifying the name in array-style brackets or parentheses, without calling this method explicitly. + **/ function namedItem( name : String ) : OptionElement; /** @throws DOMError */ + + /** + Adds an element to the collection of `option` elements for this `select` element. + **/ function add( element : haxe.extern.EitherType, ?before : haxe.extern.EitherType ) : Void; + + /** + Checks whether the element has any constraints and whether it satisfies them. If the element fails its constraints, the browser fires a cancelable `invalid` event at the element (and returns `false`). + **/ function checkValidity() : Bool; + + /** + Sets the custom validity message for the selection element to the specified message. Use the empty string to indicate that the element does not have a custom validity error. + **/ function setCustomValidity( error : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/Selection.hx b/std/js/html/Selection.hx index 9d040a73..65ddaf4a 100644 --- a/std/js/html/Selection.hx +++ b/std/js/html/Selection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,42 +20,122 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Selection.webidl line 13:0. Do not edit! +// This file is generated from mozilla\Selection.webidl. Do not edit! package js.html; +/** + Calling the `Selection.toString()` method returns the text contained in the selection, e.g.: + + Documentation [Selection](https://developer.mozilla.org/en-US/docs/Web/API/Selection) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Selection$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Selection") extern class Selection { + + /** + Returns the `Node` in which the selection begins. + **/ var anchorNode(default,null) : Node; + + /** + Returns a number representing the offset of the selection's anchor within the anchorNode. If anchorNode is a text node, this is the number of characters within anchorNode preceding the anchor. If anchorNode is an element, this is the number of child nodes of the anchorNode preceding the anchor. + **/ var anchorOffset(default,null) : Int; + + /** + Returns the `Node` in which the selection ends. + **/ var focusNode(default,null) : Node; + + /** + Returns a number representing the offset of the selection's anchor within the focusNode. If focusNode is a text node, this is the number of characters within focusNode preceding the focus. If focusNode is an element, this is the number of child nodes of the focusNode preceding the focus. + **/ var focusOffset(default,null) : Int; + + /** + Returns a Boolean indicating whether the selection's start and end points are at the same position. + **/ var isCollapsed(default,null) : Bool; + + /** + Returns the number of ranges in the selection. + **/ var rangeCount(default,null) : Int; + var caretBidiLevel : Int; /** @throws DOMError */ + + /** + Collapses the current selection to a single point. + **/ function collapse( node : Node, offset : Int ) : Void; /** @throws DOMError */ + + /** + Collapses the selection to the start of the first range in the selection. + **/ function collapseToStart() : Void; /** @throws DOMError */ + + /** + Collapses the selection to the end of the last range in the selection. + **/ function collapseToEnd() : Void; /** @throws DOMError */ + + /** + Moves the focus of the selection to a specified point. + **/ function extend( node : Node, offset : Int ) : Void; /** @throws DOMError */ + + /** + Adds all the children of the specified node to the selection. + **/ function selectAllChildren( node : Node ) : Void; /** @throws DOMError */ + + /** + Deletes the selection's content from the document. + **/ function deleteFromDocument() : Void; /** @throws DOMError */ + + /** + Returns a `Range` object representing one of the ranges currently selected. + **/ function getRangeAt( index : Int ) : Range; /** @throws DOMError */ + + /** + A `Range` object that will be added to the selection. + **/ function addRange( range : Range ) : Void; /** @throws DOMError */ + + /** + Removes a range from the selection. + **/ function removeRange( range : Range ) : Void; /** @throws DOMError */ + + /** + Removes all ranges from the selection. + **/ function removeAllRanges() : Void; /** @throws DOMError */ + + /** + Indicates if a certain node is part of the selection. + **/ function containsNode( node : Node, allowPartialContainment : Bool ) : Bool; /** @throws DOMError */ + + /** + Changes the current selection. + **/ function modify( alter : String, direction : String, granularity : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/SelectionMode.hx b/std/js/html/SelectionMode.hx index 7a4a19cb..d1a0b259 100644 --- a/std/js/html/SelectionMode.hx +++ b/std/js/html/SelectionMode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLInputElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLInputElement.webidl. Do not edit! package js.html; diff --git a/std/js/html/ServiceWorker.hx b/std/js/html/ServiceWorker.hx new file mode 100644 index 00000000..b4d18a4c --- /dev/null +++ b/std/js/html/ServiceWorker.hx @@ -0,0 +1,56 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\ServiceWorker.webidl. Do not edit! + +package js.html; + +/** + The `ServiceWorker` interface of the ServiceWorker API provides a reference to a service worker. Multiple browsing contexts (e.g. pages, workers, etc.) can be associated with the same service worker, each through a unique `ServiceWorker` object. + + Documentation [ServiceWorker](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorker) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorker$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("ServiceWorker") +extern class ServiceWorker extends EventTarget +{ + + /** + Returns the `ServiceWorker` serialized script URL defined as part of `ServiceWorkerRegistration`. The URL must be on the same origin as the document that registers the `ServiceWorker`. + **/ + var scriptURL(default,null) : String; + + /** + Returns the state of the service worker. It returns one of the following values: `installing`, `installed,` `activating`, `activated`, or `redundant`. + **/ + var state(default,null) : ServiceWorkerState; + + /** + An `EventListener` property called whenever an event of type `statechange` is fired; it is basically fired anytime the `ServiceWorker.state` changes. + **/ + var onstatechange : haxe.Constraints.Function; + var onerror : haxe.Constraints.Function; + + /** @throws DOMError */ + function postMessage( message : Dynamic, ?transferable : Array ) : Void; +} \ No newline at end of file diff --git a/std/js/html/ServiceWorkerGlobalScope.hx b/std/js/html/ServiceWorkerGlobalScope.hx index 4bcfb6a3..6a05b4f6 100644 --- a/std/js/html/ServiceWorkerGlobalScope.hx +++ b/std/js/html/ServiceWorkerGlobalScope.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,23 +20,70 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ServiceWorkerGlobalScope.webidl line 15:0. Do not edit! +// This file is generated from mozilla\ServiceWorkerGlobalScope.webidl. Do not edit! package js.html; +/** + The `ServiceWorkerGlobalScope` interface of the ServiceWorker API represents the global execution context of a service worker. + + Documentation [ServiceWorkerGlobalScope](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("ServiceWorkerGlobalScope") extern class ServiceWorkerGlobalScope extends WorkerGlobalScope { - var clients(default,null) : ServiceWorkerClients; - var scope(default,null) : String; + + /** + Contains the `Clients` object associated with the service worker. + **/ + var clients(default,null) : Clients; + + /** + Contains the `ServiceWorkerRegistration` object that represents the service worker's registration. + **/ + var registration(default,null) : ServiceWorkerRegistration; + + /** + An event handler fired whenever an `install` event occurs — when a `ServiceWorkerRegistration` acquires a new `ServiceWorkerRegistration.installing` worker. + **/ var oninstall : haxe.Constraints.Function; + + /** + An event handler fired whenever an `activate` event occurs — when a `ServiceWorkerRegistration` acquires a new `ServiceWorkerRegistration.active` worker. + **/ var onactivate : haxe.Constraints.Function; + + /** + An event handler fired whenever a `fetch` event occurs — when a `GlobalFetch.fetch` is called. + **/ var onfetch : haxe.Constraints.Function; - var onbeforeevicted : haxe.Constraints.Function; - var onevicted : haxe.Constraints.Function; + + /** + An event handler fired whenever a `message` event occurs — when incoming messages are received. Controlled pages can use the `MessagePort.postMessage()` method to send messages to service workers. The service worker can optionally send a response back via the `MessagePort` exposed in `event.data.port`, corresponding to the controlled page. + **/ var onmessage : haxe.Constraints.Function; - function update() : Void; + /** + An event handler fired whenever a `push` event occurs — when a server push notification is received. + **/ + var onpush : haxe.Constraints.Function; + + /** + An event handler fired whenever a `pushsubscriptionchange` event occurs — when a push subscription has been invalidated, or is about to be invalidated (e.g. when a push service sets an expiration time.) + **/ + var onpushsubscriptionchange : haxe.Constraints.Function; + + /** + An event handler fired whenever a `notificationclick` event occurs — when a user clicks on a displayed notification. + **/ + var onnotificationclick : haxe.Constraints.Function; + /** @throws DOMError */ - function unregister() : Promise; + + /** + Allows the current service worker registration to progress from waiting to active state while service worker clients are using it. + **/ + function skipWaiting() : Promise; } \ No newline at end of file diff --git a/std/js/html/ServiceWorkerRegistration.hx b/std/js/html/ServiceWorkerRegistration.hx new file mode 100644 index 00000000..921343e3 --- /dev/null +++ b/std/js/html/ServiceWorkerRegistration.hx @@ -0,0 +1,75 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\ServiceWorkerRegistration.webidl. Do not edit! + +package js.html; + +/** + The `ServiceWorkerRegistration` interface of the ServiceWorker API represents the service worker registration. You register a service worker to control one or more pages that share the same origin. + + Documentation [ServiceWorkerRegistration](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("ServiceWorkerRegistration") +extern class ServiceWorkerRegistration extends EventTarget +{ + + /** + Returns a service worker whose state is `installing`. This is initially set to `null`. + **/ + var installing(default,null) : ServiceWorker; + + /** + Returns a service worker whose state is `installed`. This is initially set to `null`. + **/ + var waiting(default,null) : ServiceWorker; + + /** + Returns a service worker whose state is either `activating` or `activated`. This is initially set to `null`. An active worker will control a `ServiceWorkerClient` if the client's URL falls within the scope of the registration (the `scope` option set when `ServiceWorkerContainer.register` is first called.) + **/ + var active(default,null) : ServiceWorker; + + /** + Returns a unique identifier for a service worker registration. This must be on the same origin as the document that registers the `ServiceWorker`. + **/ + var scope(default,null) : String; + + /** + An `EventListener` property called whenever an event of type `updatefound` is fired; it is fired any time the `ServiceWorkerRegistration.installing` property acquires a new service worker. + **/ + var onupdatefound : haxe.Constraints.Function; + + /** @throws DOMError */ + + /** + Checks the server for an updated version of the service worker without consulting caches. + **/ + function update() : Promise; + /** @throws DOMError */ + + /** + Unregisters the service worker registration and returns a promise (see `Promise`). The service worker will finish any ongoing operations before it is unregistered. + **/ + function unregister() : Promise; +} \ No newline at end of file diff --git a/std/js/html/ServiceWorkerState.hx b/std/js/html/ServiceWorkerState.hx new file mode 100644 index 00000000..29c7469d --- /dev/null +++ b/std/js/html/ServiceWorkerState.hx @@ -0,0 +1,41 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\ServiceWorker.webidl. Do not edit! + +package js.html; + +/** + The `ServiceWorkerState` is associated with its `ServiceWorker`'s state. + + Documentation [ServiceWorkerState](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerState) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerState$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:enum abstract ServiceWorkerState(String) +{ + var INSTALLING = "installing"; + var INSTALLED = "installed"; + var ACTIVATING = "activating"; + var ACTIVATED = "activated"; + var REDUNDANT = "redundant"; +} \ No newline at end of file diff --git a/std/js/html/ShadowElement.hx b/std/js/html/ShadowElement.hx index 8adc450c..eec7102c 100644 --- a/std/js/html/ShadowElement.hx +++ b/std/js/html/ShadowElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLShadowElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLShadowElement.webidl. Do not edit! package js.html; +/** + The `HTMLShadowElement` interface represents a `shadow` HTML Element, which is used in Shadow DOM. + + Documentation [HTMLShadowElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLShadowElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLShadowElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLShadowElement") extern class ShadowElement extends Element { diff --git a/std/js/html/ShadowRoot.hx b/std/js/html/ShadowRoot.hx index eb24668d..8e42ae61 100644 --- a/std/js/html/ShadowRoot.hx +++ b/std/js/html/ShadowRoot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ShadowRoot.webidl line 14:0. Do not edit! +// This file is generated from mozilla\ShadowRoot.webidl. Do not edit! package js.html; +/** + The `ShadowRoot` interface of the Shadow DOM API is the root node of a DOM subtree that is rendered separately from a document's main DOM tree. + + Documentation [ShadowRoot](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("ShadowRoot") extern class ShadowRoot extends DocumentFragment { + + /** + The DOM tree inside the `ShadowRoot`. + **/ var innerHTML : String; + + /** + A DOM element to which the `ShadowRoot` is attatched. + **/ var host(default,null) : Element; var olderShadowRoot(default,null) : ShadowRoot; var applyAuthorStyles : Bool; diff --git a/std/js/html/SharedWorker.hx b/std/js/html/SharedWorker.hx index 466b5274..77c92404 100644 --- a/std/js/html/SharedWorker.hx +++ b/std/js/html/SharedWorker.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SharedWorker.webidl line 9:0. Do not edit! +// This file is generated from mozilla\SharedWorker.webidl. Do not edit! package js.html; +/** + The `SharedWorker` interface represents a specific kind of worker that can be accessed from several browsing contexts, such as several windows, iframes or even workers. They implement an interface different than dedicated workers and have a different global scope, `SharedWorkerGlobalScope`. + + Documentation [SharedWorker](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SharedWorker") extern class SharedWorker extends EventTarget { + + /** + Returns a `MessagePort` object used to communicate and control the shared worker. + **/ var port(default,null) : MessagePort; var onerror : haxe.Constraints.Function; diff --git a/std/js/html/SharedWorkerGlobalScope.hx b/std/js/html/SharedWorkerGlobalScope.hx index e99fe6be..fab9857a 100644 --- a/std/js/html/SharedWorkerGlobalScope.hx +++ b/std/js/html/SharedWorkerGlobalScope.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SharedWorkerGlobalScope.webidl line 17:0. Do not edit! +// This file is generated from mozilla\SharedWorkerGlobalScope.webidl. Do not edit! package js.html; +/** + The `SharedWorkerGlobalScope` object (the `SharedWorker` global scope) is accessible through the `self` keyword. Some additional global functions, namespaces objects, and constructors, not typically associated with the worker global scope, but available on it, are listed in the JavaScript Reference. See the complete list of functions available to workers. + + Documentation [SharedWorkerGlobalScope](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorkerGlobalScope) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorkerGlobalScope$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SharedWorkerGlobalScope") extern class SharedWorkerGlobalScope extends WorkerGlobalScope { + + /** + The name that the `SharedWorker` was (optionally) given when it was created. This is the name that the `SharedWorker.SharedWorker` constructor can pass to get a reference to the `SharedWorkerGlobalScope`. + **/ var name(default,null) : String; + + /** + Is an `EventHandler` representing the code to be called when the `connect` event is raised — that is, when a `MessagePort` connection is opened between the associated `SharedWorker` and the main thread. + **/ var onconnect : haxe.Constraints.Function; } \ No newline at end of file diff --git a/std/js/html/SimpleGestureEvent.hx b/std/js/html/SimpleGestureEvent.hx index 7f2b0d14..84ee6eb5 100644 --- a/std/js/html/SimpleGestureEvent.hx +++ b/std/js/html/SimpleGestureEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SimpleGestureEvent.webidl line 9:0. Do not edit! +// This file is generated from mozilla\SimpleGestureEvent.webidl. Do not edit! package js.html; @@ -39,6 +39,5 @@ extern class SimpleGestureEvent extends MouseEvent var delta(default,null) : Float; var clickCount(default,null) : Int; - /** @throws DOMError */ function initSimpleGestureEvent( typeArg : String, canBubbleArg : Bool, cancelableArg : Bool, viewArg : Window, detailArg : Int, screenXArg : Int, screenYArg : Int, clientXArg : Int, clientYArg : Int, ctrlKeyArg : Bool, altKeyArg : Bool, shiftKeyArg : Bool, metaKeyArg : Bool, buttonArg : Int, relatedTargetArg : EventTarget, allowedDirectionsArg : Int, directionArg : Int, deltaArg : Float, clickCount : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/SourceBuffer.hx b/std/js/html/SourceBuffer.hx index 33202068..5e0cafb4 100644 --- a/std/js/html/SourceBuffer.hx +++ b/std/js/html/SourceBuffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,25 +20,68 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SourceBuffer.webidl line 19:0. Do not edit! +// This file is generated from mozilla\SourceBuffer.webidl. Do not edit! package js.html; +/** + The `SourceBuffer` interface represents a chunk of media to be passed into an `HTMLMediaElement` and played, via a `MediaSource` object. This can be made up of one or several media segments. + + Documentation [SourceBuffer](https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SourceBuffer$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SourceBuffer") extern class SourceBuffer extends EventTarget { + + /** + Controls how the order of media segments in the `SourceBuffer` is handled, in terms of whether they can be appended in any order, or they have to be kept in a strict sequence. + **/ var mode : SourceBufferAppendMode; + + /** + Indicates whether the `SourceBuffer` is currently being updated — i.e. whether an `SourceBuffer.appendBuffer()`, `SourceBuffer.appendStream()`, or `SourceBuffer.remove()` operation is currently in progress. + **/ var updating(default,null) : Bool; + + /** + Returns the time ranges that are currently buffered in the `SourceBuffer`. + **/ var buffered(default,null) : TimeRanges; + + /** + Controls the offset applied to timestamps inside media segments that are subsequently appended to the `SourceBuffer`. + **/ var timestampOffset : Float; + + /** + Controls the timestamp for the start of the append window. This is a timestamp range that can be used to filter what media data is appended to the `SourceBuffer`. Coded media frames with timestamps wthin this range will be appended, whereas those outside the range will be filtered out. + **/ var appendWindowStart : Float; + + /** + Controls the timestamp for the end of the append window. + **/ var appendWindowEnd : Float; /** @throws DOMError */ @:overload( function( data : ArrayBuffer ) : Void {} ) + + /** + Appends media segment data from an `ArrayBuffer` or `ArrayBufferView` object to the `SourceBuffer`. + **/ function appendBuffer( data : ArrayBufferView ) : Void; /** @throws DOMError */ + + /** + Aborts the current segment and resets the segment parser. + **/ function abort() : Void; /** @throws DOMError */ + + /** + Removes media segments within a specific time range from the `SourceBuffer`. + **/ function remove( start : Float, end : Float ) : Void; } \ No newline at end of file diff --git a/std/js/html/SourceBufferAppendMode.hx b/std/js/html/SourceBufferAppendMode.hx index 484cea5a..b592a0d2 100644 --- a/std/js/html/SourceBufferAppendMode.hx +++ b/std/js/html/SourceBufferAppendMode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SourceBuffer.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SourceBuffer.webidl. Do not edit! package js.html; diff --git a/std/js/html/SourceBufferList.hx b/std/js/html/SourceBufferList.hx index cce04cbb..fe441b47 100644 --- a/std/js/html/SourceBufferList.hx +++ b/std/js/html/SourceBufferList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SourceBufferList.webidl line 14:0. Do not edit! +// This file is generated from mozilla\SourceBufferList.webidl. Do not edit! package js.html; +/** + The `SourceBufferList` interface represents a simple container list for multiple `SourceBuffer` objects. + + Documentation [SourceBufferList](https://developer.mozilla.org/en-US/docs/Web/API/SourceBufferList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SourceBufferList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SourceBufferList") extern class SourceBufferList extends EventTarget implements ArrayAccess { + + /** + Returns the number of `SourceBuffer` objects in the list. + **/ var length(default,null) : Int; } \ No newline at end of file diff --git a/std/js/html/SourceElement.hx b/std/js/html/SourceElement.hx index c659a916..3d34656d 100644 --- a/std/js/html/SourceElement.hx +++ b/std/js/html/SourceElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,17 +20,44 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLSourceElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLSourceElement.webidl. Do not edit! package js.html; +/** + The `HTMLSourceElement` interface provides special properties (beyond the regular `HTMLElement` object interface it also has available to it by inheritance) for manipulating `source` elements. + + Documentation [HTMLSourceElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSourceElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSourceElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLSourceElement") extern class SourceElement extends Element { + + /** + Is a `DOMString` reflecting the `src` HTML attribute, containing the URL for the media resource. The `HTMLSourceElement.src` property has a meaning only when the associated `source` element is nested in a media element that is a `video` or an `audio` element. It has no meaning and is ignored when it is nested in a `picture` element. + **/ var src : String; + + /** + Is a `DOMString` reflecting the `type` HTML attribute, containing the type of the media resource. + **/ var type : String; + + /** + Is a `DOMString` reflecting the `srcset` HTML attribute, containing a list of candidate images, separated by a comma (`',', U+002C COMMA`). A candidate image is a URL followed by a `'w'` with the width of the images, or an `'x'` followed by the pixel density. + **/ var srcset : String; + + /** + Is a `DOMString` representing image sizes between breakpoints + **/ var sizes : String; + + /** + Is a `DOMString` reflecting the `media` HTML attribute, containing the intended type of the media resource. + **/ var media : String; } \ No newline at end of file diff --git a/std/js/html/SpanElement.hx b/std/js/html/SpanElement.hx index d2b7e9f7..943039f2 100644 --- a/std/js/html/SpanElement.hx +++ b/std/js/html/SpanElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLSpanElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\HTMLSpanElement.webidl. Do not edit! package js.html; +/** + The `HTMLSpanElement` interface represents a `span` element and derives from the `HTMLElement` interface, but without implementing any additional properties or methods. + + Documentation [HTMLSpanElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSpanElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSpanElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLSpanElement") extern class SpanElement extends Element { diff --git a/std/js/html/SpeechGrammar.hx b/std/js/html/SpeechGrammar.hx index 034abc25..fe445aa0 100644 --- a/std/js/html/SpeechGrammar.hx +++ b/std/js/html/SpeechGrammar.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechGrammar.webidl line 15:0. Do not edit! +// This file is generated from mozilla\SpeechGrammar.webidl. Do not edit! package js.html; +/** + The `SpeechGrammar` interface of the Web Speech API represents a set of words or patterns of words that we want the recognition service to recognize. + + Documentation [SpeechGrammar](https://developer.mozilla.org/en-US/docs/Web/API/SpeechGrammar) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechGrammar$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SpeechGrammar") extern class SpeechGrammar { + + /** + Sets and returns a string containing the grammar from within in the `SpeechGrammar` object instance. + **/ var src : String; + + /** + Sets and returns the weight of the `SpeechGrammar` object. + **/ var weight : Float; /** @throws DOMError */ diff --git a/std/js/html/SpeechGrammarList.hx b/std/js/html/SpeechGrammarList.hx index e5a26bc6..11518754 100644 --- a/std/js/html/SpeechGrammarList.hx +++ b/std/js/html/SpeechGrammarList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,21 +20,44 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechGrammarList.webidl line 14:0. Do not edit! +// This file is generated from mozilla\SpeechGrammarList.webidl. Do not edit! package js.html; +/** + The `SpeechGrammarList` interface of the Web Speech API represents a list of `SpeechGrammar` objects containing words or patterns of words that we want the recognition service to recognize. + + Documentation [SpeechGrammarList](https://developer.mozilla.org/en-US/docs/Web/API/SpeechGrammarList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechGrammarList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SpeechGrammarList") extern class SpeechGrammarList implements ArrayAccess { + + /** + Returns the number of `SpeechGrammar` objects contained in the `SpeechGrammarList`. + **/ var length(default,null) : Int; /** @throws DOMError */ function new() : Void; /** @throws DOMError */ + + /** + Standard getter — allows individual `SpeechGrammar` objects to be retrieved from the `SpeechGrammarList` using array syntax. + **/ function item( index : Int ) : SpeechGrammar; /** @throws DOMError */ + + /** + Takes a grammar present at a specific URI and adds it to the `SpeechGrammarList` as a new `SpeechGrammar` object. + **/ function addFromURI( src : String, ?weight : Float ) : Void; /** @throws DOMError */ + + /** + Takes a grammar present in a specific `DOMString` within the code base (e.g. stored in a variable) and adds it to the `SpeechGrammarList` as a new `SpeechGrammar` object. + **/ function addFromString( string : String, ?weight : Float ) : Void; } \ No newline at end of file diff --git a/std/js/html/SpeechInputEvent.hx b/std/js/html/SpeechInputEvent.hx deleted file mode 100644 index a1a7a332..00000000 --- a/std/js/html/SpeechInputEvent.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html; - -/** @deprecated Use SpeechRecognitionEvent instead. */ -@:deprecated("SpeechInputEvent is deprecated, use SpeechRecognitionEvent instead") -typedef SpeechInputEvent = SpeechRecognitionEvent; diff --git a/std/js/html/SpeechInputResult.hx b/std/js/html/SpeechInputResult.hx deleted file mode 100644 index cf1628be..00000000 --- a/std/js/html/SpeechInputResult.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html; - -/** @deprecated Use SpeechRecognitionResult instead. */ -@:deprecated("SpeechInputResult is deprecated, use SpeechRecognitionResult instead") -typedef SpeechInputResult = SpeechRecognitionResult; diff --git a/std/js/html/SpeechInputResultList.hx b/std/js/html/SpeechInputResultList.hx deleted file mode 100644 index b245c3e1..00000000 --- a/std/js/html/SpeechInputResultList.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html; - -/** @deprecated Use SpeechRecognitionResultList instead. */ -@:deprecated("SpeechInputResultList is deprecated, use SpeechRecognitionResultList instead") -typedef SpeechInputResultList = SpeechRecognitionResultList; diff --git a/std/js/html/SpeechRecognition.hx b/std/js/html/SpeechRecognition.hx index 6b8e5aac..5c117b1d 100644 --- a/std/js/html/SpeechRecognition.hx +++ b/std/js/html/SpeechRecognition.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,35 +20,122 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechRecognition.webidl line 15:0. Do not edit! +// This file is generated from mozilla\SpeechRecognition.webidl. Do not edit! package js.html; +/** + The `SpeechRecognition` interface of the Web Speech API is the controller interface for the recognition service; this also handles the `SpeechRecognitionEvent` sent from the recognition service. + + Documentation [SpeechRecognition](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SpeechRecognition") extern class SpeechRecognition extends EventTarget { + + /** + Returns and sets a collection of `SpeechGrammar` objects that represent the grammars that will be understood by the current `SpeechRecognition`. + **/ var grammars : SpeechGrammarList; + + /** + Returns and sets the language of the current `SpeechRecognition`. If not specified, this defaults to the HTML `lang` attribute value, or the user agent's language setting if that isn't set either. + **/ var lang : String; + + /** + Controls whether continuous results are returned for each recognition, or only a single result. Defaults to single (`false`.) + **/ var continuous : Bool; + + /** + Controls whether interim results should be returned (`true`) or not (`false`.) Interim results are results that are not yet final (e.g. the `SpeechRecognitionResult.isFinal` property is `false`.) + **/ var interimResults : Bool; + + /** + Sets the maximum number of `SpeechRecognitionAlternative`s provided per result. The default value is 1. + **/ var maxAlternatives : Int; + + /** + Specifies the location of the speech recognition service used by the current `SpeechRecognition` to handle the actual recognition. The default is the user agent's default speech service. + **/ var serviceURI : String; + + /** + Fired when the user agent has started to capture audio. + **/ var onaudiostart : haxe.Constraints.Function; + + /** + Fired when any sound — recognisable speech or not — has been detected. + **/ var onsoundstart : haxe.Constraints.Function; + + /** + Fired when sound that is recognised by the speech recognition service as speech has been detected. + **/ var onspeechstart : haxe.Constraints.Function; + + /** + Fired when speech recognised by the speech recognition service has stopped being detected. + **/ var onspeechend : haxe.Constraints.Function; + + /** + Fired when any sound — recognisable speech or not — has stopped being detected. + **/ var onsoundend : haxe.Constraints.Function; + + /** + Fired when the user agent has finished capturing audio. + **/ var onaudioend : haxe.Constraints.Function; + + /** + Fired when the speech recognition service returns a result — a word or phrase has been positively recognized and this has been communicated back to the app. + **/ var onresult : haxe.Constraints.Function; + + /** + Fired when the speech recognition service returns a final result with no significant recognition. This may involve some degree of recognition, which doesn't meet or exceed the `SpeechRecognitionAlternative.confidence` threshold. + **/ var onnomatch : haxe.Constraints.Function; + + /** + Fired when a speech recognition error occurs. + **/ var onerror : haxe.Constraints.Function; + + /** + Fired when the speech recognition service has begun listening to incoming audio with intent to recognize grammars associated with the current `SpeechRecognition`. + **/ var onstart : haxe.Constraints.Function; + + /** + Fired when the speech recognition service has disconnected. + **/ var onend : haxe.Constraints.Function; /** @throws DOMError */ function new() : Void; /** @throws DOMError */ + + /** + Starts the speech recognition service listening to incoming audio with intent to recognize grammars associated with the current `SpeechRecognition`. + **/ function start( ?stream : MediaStream ) : Void; + + /** + Stops the speech recognition service from listening to incoming audio, and attempts to return a `SpeechRecognitionResult` using the audio captured so far. + **/ function stop() : Void; + + /** + Stops the speech recognition service from listening to incoming audio, and doesn't attempt to return a `SpeechRecognitionResult`. + **/ function abort() : Void; } \ No newline at end of file diff --git a/std/js/html/SpeechRecognitionAlternative.hx b/std/js/html/SpeechRecognitionAlternative.hx index 78b21cbc..9bb83f5b 100644 --- a/std/js/html/SpeechRecognitionAlternative.hx +++ b/std/js/html/SpeechRecognitionAlternative.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechRecognitionAlternative.webidl line 14:0. Do not edit! +// This file is generated from mozilla\SpeechRecognitionAlternative.webidl. Do not edit! package js.html; +/** + The `SpeechRecognitionAlternative` interface of the Web Speech API represents a single word that has been recognised by the speech recognition service. + + Documentation [SpeechRecognitionAlternative](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognitionAlternative) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognitionAlternative$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SpeechRecognitionAlternative") extern class SpeechRecognitionAlternative { + + /** + Returns a string containing the transcript of the recognised word. + **/ var transcript(default,null) : String; + + /** + Returns a numeric estimate of how confident the speech recognition system is that the recognition is correct. + **/ var confidence(default,null) : Float; } \ No newline at end of file diff --git a/std/js/html/SpeechRecognitionError.hx b/std/js/html/SpeechRecognitionError.hx index 2612f634..073dd517 100644 --- a/std/js/html/SpeechRecognitionError.hx +++ b/std/js/html/SpeechRecognitionError.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechRecognitionError.webidl line 20:0. Do not edit! +// This file is generated from mozilla\SpeechRecognitionError.webidl. Do not edit! package js.html; +/** + The `SpeechRecognitionError` interface of the Web Speech API represents error messages from the recognition service. + + Documentation [SpeechRecognitionError](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognitionError) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognitionError$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SpeechRecognitionError") extern class SpeechRecognitionError extends Event { + + /** + Returns the type of error raised. + **/ var error(default,null) : SpeechRecognitionErrorCode; + + /** + Returns a message describing the error in more detail. + **/ var message(default,null) : String; /** @throws DOMError */ diff --git a/std/js/html/SpeechRecognitionErrorCode.hx b/std/js/html/SpeechRecognitionErrorCode.hx index d8b6aecd..23a9ed8b 100644 --- a/std/js/html/SpeechRecognitionErrorCode.hx +++ b/std/js/html/SpeechRecognitionErrorCode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechRecognitionError.webidl line 7:0. Do not edit! +// This file is generated from mozilla\SpeechRecognitionError.webidl. Do not edit! package js.html; diff --git a/std/js/html/SpeechRecognitionErrorInit.hx b/std/js/html/SpeechRecognitionErrorInit.hx index 024ca12e..a4a7690e 100644 --- a/std/js/html/SpeechRecognitionErrorInit.hx +++ b/std/js/html/SpeechRecognitionErrorInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechRecognitionError.webidl line 26:0. Do not edit! +// This file is generated from mozilla\SpeechRecognitionError.webidl. Do not edit! package js.html; diff --git a/std/js/html/SpeechRecognitionEvent.hx b/std/js/html/SpeechRecognitionEvent.hx index 96caae50..7ccb126d 100644 --- a/std/js/html/SpeechRecognitionEvent.hx +++ b/std/js/html/SpeechRecognitionEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,39 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechRecognitionEvent.webidl line 10:0. Do not edit! +// This file is generated from mozilla\SpeechRecognitionEvent.webidl. Do not edit! package js.html; +/** + The `SpeechRecognitionEvent` interface of the Web Speech API represents the event object for the `result` and `nomatch` events, and contains all the data associated with an interim or final speech recognition result. + + Documentation [SpeechRecognitionEvent](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognitionEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognitionEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SpeechRecognitionEvent") extern class SpeechRecognitionEvent extends Event { + + /** + Returns the lowest index value result in the `SpeechRecognitionResultList` "array" that has actually changed. + **/ var resultIndex(default,null) : Int; - var results(default,null) : Dynamic/*MISSING nsISupports*/; - var interpretation(default,null) : String; + + /** + Returns a `SpeechRecognitionResultList` object representing all the speech recognition results for the current session. + **/ + var results(default,null) : SpeechRecognitionResultList; + + /** + Returns the semantic meaning of what the user said. + **/ + var interpretation(default,null) : Dynamic; + + /** + Returns an Extensible MultiModal Annotation markup language (EMMA) — XML — representation of the result. + **/ var emma(default,null) : HTMLDocument; /** @throws DOMError */ diff --git a/std/js/html/SpeechRecognitionEventInit.hx b/std/js/html/SpeechRecognitionEventInit.hx index 70c62550..687729fb 100644 --- a/std/js/html/SpeechRecognitionEventInit.hx +++ b/std/js/html/SpeechRecognitionEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechRecognitionEvent.webidl line 18:0. Do not edit! +// This file is generated from mozilla\SpeechRecognitionEvent.webidl. Do not edit! package js.html; @@ -28,7 +28,7 @@ typedef SpeechRecognitionEventInit = { > EventInit, @:optional var emma : HTMLDocument; - @:optional var interpretation : String; + @:optional var interpretation : Dynamic; @:optional var resultIndex : Int; - @:optional var results : Dynamic/*MISSING nsISupports*/; + @:optional var results : SpeechRecognitionResultList; } \ No newline at end of file diff --git a/std/js/html/SpeechRecognitionResult.hx b/std/js/html/SpeechRecognitionResult.hx index de671368..61420e4f 100644 --- a/std/js/html/SpeechRecognitionResult.hx +++ b/std/js/html/SpeechRecognitionResult.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,30 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechRecognitionResult.webidl line 14:0. Do not edit! +// This file is generated from mozilla\SpeechRecognitionResult.webidl. Do not edit! package js.html; +/** + The `SpeechRecognitionResult` interface of the Web Speech API represents a single recognition match, which may contain multiple `SpeechRecognitionAlternative` objects. + + Documentation [SpeechRecognitionResult](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognitionResult) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognitionResult$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SpeechRecognitionResult") extern class SpeechRecognitionResult implements ArrayAccess { + + /** + Returns the length of the "array" — the number of `SpeechRecognitionAlternative` objects contained in the result (also referred to as "n-best alternatives".) + **/ var length(default,null) : Int; - @:native("final") - var final_(default,null) : Bool; + + /** + A `Boolean` that states whether this result is final (true) or not (false) — if so, then this is the final time this result will be returned; if not, then this result is an interim result, and may be updated later on. + **/ + var isFinal(default,null) : Bool; function item( index : Int ) : SpeechRecognitionAlternative; } \ No newline at end of file diff --git a/std/js/html/SpeechRecognitionResultList.hx b/std/js/html/SpeechRecognitionResultList.hx index e2875e8c..99c8732e 100644 --- a/std/js/html/SpeechRecognitionResultList.hx +++ b/std/js/html/SpeechRecognitionResultList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechRecognitionResultList.webidl line 14:0. Do not edit! +// This file is generated from mozilla\SpeechRecognitionResultList.webidl. Do not edit! package js.html; +/** + The `SpeechRecognitionResultList` interface of the Web Speech API represents a list of `SpeechRecognitionResult` objects, or a single one if results are being captured in `continuous` mode. + + Documentation [SpeechRecognitionResultList](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognitionResultList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognitionResultList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SpeechRecognitionResultList") extern class SpeechRecognitionResultList implements ArrayAccess { + + /** + Returns the length of the "array" — the number of `SpeechRecognitionResult` objects in the list. + **/ var length(default,null) : Int; function item( index : Int ) : SpeechRecognitionResult; diff --git a/std/js/html/SpeechSynthesis.hx b/std/js/html/SpeechSynthesis.hx index 9f76c277..bed2b1cc 100644 --- a/std/js/html/SpeechSynthesis.hx +++ b/std/js/html/SpeechSynthesis.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,20 +20,59 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechSynthesis.webidl line 14:0. Do not edit! +// This file is generated from mozilla\SpeechSynthesis.webidl. Do not edit! package js.html; +/** + The `SpeechSynthesis` interface of the Web Speech API is the controller interface for the speech service; this can be used to retrieve information about the synthesis voices available on the device, start and pause speech, and other commands besides. + + Documentation [SpeechSynthesis](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SpeechSynthesis") extern class SpeechSynthesis { + + /** + A `Boolean` that returns `true` if the utterance queue contains as-yet-unspoken utterances. + **/ var pending(default,null) : Bool; + + /** + A `Boolean` that returns `true` if an utterance is currently in the process of being spoken — even if `SpeechSynthesis` is in a paused state. + **/ var speaking(default,null) : Bool; + + /** + A `Boolean` that returns `true` if the `SpeechSynthesis` object is in a paused state. + **/ var paused(default,null) : Bool; + + /** + Adds an `SpeechSynthesisUtterance` to the utterance queue; it will be spoken when any other utterances queued before it have been spoken. + **/ function speak( utterance : SpeechSynthesisUtterance ) : Void; + + /** + Removes all utterances from the utterance queue. + **/ function cancel() : Void; + + /** + Puts the `SpeechSynthesis` object into a paused state. + **/ function pause() : Void; + + /** + Puts the `SpeechSynthesis` object into a non-paused state: resumes it if it was already paused. + **/ function resume() : Void; + + /** + Returns a list of `SpeechSynthesisVoice` objects representing all the available voices on the current device. + **/ function getVoices() : Array; } \ No newline at end of file diff --git a/std/js/html/SpeechSynthesisErrorCode.hx b/std/js/html/SpeechSynthesisErrorCode.hx new file mode 100644 index 00000000..43f05004 --- /dev/null +++ b/std/js/html/SpeechSynthesisErrorCode.hx @@ -0,0 +1,40 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\SpeechSynthesisErrorEvent.webidl. Do not edit! + +package js.html; + +@:enum abstract SpeechSynthesisErrorCode(String) +{ + var CANCELED = "canceled"; + var INTERRUPTED = "interrupted"; + var AUDIO_BUSY = "audio-busy"; + var AUDIO_HARDWARE = "audio-hardware"; + var NETWORK = "network"; + var SYNTHESIS_UNAVAILABLE = "synthesis-unavailable"; + var SYNTHESIS_FAILED = "synthesis-failed"; + var LANGUAGE_UNAVAILABLE = "language-unavailable"; + var VOICE_UNAVAILABLE = "voice-unavailable"; + var TEXT_TOO_LONG = "text-too-long"; + var INVALID_ARGUMENT = "invalid-argument"; +} \ No newline at end of file diff --git a/std/js/html/SpeechSynthesisErrorEvent.hx b/std/js/html/SpeechSynthesisErrorEvent.hx new file mode 100644 index 00000000..61bb98a0 --- /dev/null +++ b/std/js/html/SpeechSynthesisErrorEvent.hx @@ -0,0 +1,45 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\SpeechSynthesisErrorEvent.webidl. Do not edit! + +package js.html; + +/** + The `SpeechSynthesisErrorEvent` interface of the Web Speech API contains information about any errors that occur while processing `SpeechSynthesisUtterance` objects in the speech service. + + Documentation [SpeechSynthesisErrorEvent](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisErrorEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisErrorEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("SpeechSynthesisErrorEvent") +extern class SpeechSynthesisErrorEvent extends SpeechSynthesisEvent +{ + + /** + Returns an error code indicating what has gone wrong with a speech synthesis attempt. + **/ + var error(default,null) : SpeechSynthesisErrorCode; + + /** @throws DOMError */ + function new( type : String, eventInitDict : SpeechSynthesisErrorEventInit ) : Void; +} \ No newline at end of file diff --git a/std/js/html/SpeechSynthesisErrorEventInit.hx b/std/js/html/SpeechSynthesisErrorEventInit.hx new file mode 100644 index 00000000..abd5eda3 --- /dev/null +++ b/std/js/html/SpeechSynthesisErrorEventInit.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\SpeechSynthesisErrorEvent.webidl. Do not edit! + +package js.html; + +typedef SpeechSynthesisErrorEventInit = +{ + > SpeechSynthesisEventInit, + var error : SpeechSynthesisErrorCode; +} \ No newline at end of file diff --git a/std/js/html/SpeechSynthesisEvent.hx b/std/js/html/SpeechSynthesisEvent.hx index 0e47880b..69fed953 100644 --- a/std/js/html/SpeechSynthesisEvent.hx +++ b/std/js/html/SpeechSynthesisEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,17 +20,41 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechSynthesisEvent.webidl line 15:0. Do not edit! +// This file is generated from mozilla\SpeechSynthesisEvent.webidl. Do not edit! package js.html; +/** + The `SpeechSynthesisEvent` interface of the Web Speech API contains information about the current state of `SpeechSynthesisUtterance` objects that have been processed in the speech service. + + Documentation [SpeechSynthesisEvent](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SpeechSynthesisEvent") extern class SpeechSynthesisEvent extends Event { + + /** + Returns the `SpeechSynthesisUtterance` instance that the event was triggered on. + **/ + var utterance(default,null) : SpeechSynthesisUtterance; + + /** + Returns the index position of the character in the `SpeechSynthesisUtterance.text` that was being spoken when the event was triggered. + **/ var charIndex(default,null) : Int; + + /** + Returns the elapsed time in milliseconds after the `SpeechSynthesisUtterance.text` started being spoken that the event was triggered at. + **/ var elapsedTime(default,null) : Float; + + /** + Returns the name associated with certain types of events occuring as the `SpeechSynthesisUtterance.text` is being spoken: the name of the SSML marker reached in the case of a `mark` event, or the type of boundary reached in the case of a `boundary` event. + **/ var name(default,null) : String; /** @throws DOMError */ - function new( type : String, ?eventInitDict : SpeechSynthesisEventInit ) : Void; + function new( type : String, eventInitDict : SpeechSynthesisEventInit ) : Void; } \ No newline at end of file diff --git a/std/js/html/SpeechSynthesisEventInit.hx b/std/js/html/SpeechSynthesisEventInit.hx index 4f99fb87..b816d7e9 100644 --- a/std/js/html/SpeechSynthesisEventInit.hx +++ b/std/js/html/SpeechSynthesisEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechSynthesisEvent.webidl line 22:0. Do not edit! +// This file is generated from mozilla\SpeechSynthesisEvent.webidl. Do not edit! package js.html; @@ -30,4 +30,5 @@ typedef SpeechSynthesisEventInit = @:optional var charIndex : Int; @:optional var elapsedTime : Float; @:optional var name : String; + var utterance : SpeechSynthesisUtterance; } \ No newline at end of file diff --git a/std/js/html/SpeechSynthesisUtterance.hx b/std/js/html/SpeechSynthesisUtterance.hx index cd8b5868..2b528448 100644 --- a/std/js/html/SpeechSynthesisUtterance.hx +++ b/std/js/html/SpeechSynthesisUtterance.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,25 +20,84 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechSynthesisUtterance.webidl line 16:0. Do not edit! +// This file is generated from mozilla\SpeechSynthesisUtterance.webidl. Do not edit! package js.html; +/** + The `SpeechSynthesisUtterance` interface of the Web Speech API represents a speech request. It contains the content the speech service should read and information about how to read it (e.g. language, pitch and volume.) + + Documentation [SpeechSynthesisUtterance](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisUtterance) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisUtterance$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SpeechSynthesisUtterance") extern class SpeechSynthesisUtterance extends EventTarget { + + /** + Gets and sets the text that will be synthesised when the utterance is spoken. + **/ var text : String; + + /** + Gets and sets the language of the utterance. + **/ var lang : String; + + /** + Gets and sets the voice that will be used to speak the utterance. + **/ var voice : SpeechSynthesisVoice; + + /** + Gets and sets the volume that the utterance will be spoken at. + **/ var volume : Float; + + /** + Gets and sets the speed at which the utterance will be spoken at. + **/ var rate : Float; + + /** + Gets and sets the pitch at which the utterance will be spoken at. + **/ var pitch : Float; + + /** + Fired when the utterance has begun to be spoken. + **/ var onstart : haxe.Constraints.Function; + + /** + Fired when the utterance has finished being spoken. + **/ var onend : haxe.Constraints.Function; + + /** + Fired when an error occurs that prevents the utterance from being succesfully spoken. + **/ var onerror : haxe.Constraints.Function; + + /** + Fired when the utterance is paused part way through. + **/ var onpause : haxe.Constraints.Function; + + /** + Fired when a paused utterance is resumed. + **/ var onresume : haxe.Constraints.Function; + + /** + Fired when the spoken utterance reaches a named SSML "mark" tag. + **/ var onmark : haxe.Constraints.Function; + + /** + Fired when the spoken utterance reaches a word or sentence boundary. + **/ var onboundary : haxe.Constraints.Function; /** @throws DOMError */ diff --git a/std/js/html/SpeechSynthesisVoice.hx b/std/js/html/SpeechSynthesisVoice.hx index 699df856..4ab3a938 100644 --- a/std/js/html/SpeechSynthesisVoice.hx +++ b/std/js/html/SpeechSynthesisVoice.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,39 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SpeechSynthesisVoice.webidl line 14:0. Do not edit! +// This file is generated from mozilla\SpeechSynthesisVoice.webidl. Do not edit! package js.html; +/** + The `SpeechSynthesisVoice` interface of the Web Speech API represents a voice that the system supports. Every `SpeechSynthesisVoice` has its own relative speech service including information about language, name and URI. + + Documentation [SpeechSynthesisVoice](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisVoice) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisVoice$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SpeechSynthesisVoice") extern class SpeechSynthesisVoice { + + /** + Returns the type of URI and location of the speech synthesis service for this voice. + **/ var voiceURI(default,null) : String; + + /** + Returns a human-readable name that represents the voice. + **/ var name(default,null) : String; + + /** + Returns a BCP 47 language tag indicating the language of the voice. + **/ var lang(default,null) : String; + + /** + A `Boolean` indicating whether the voice is supplied by a local speech synthesizer service (`true`), or a remote speech synthesizer service (`false`.) + **/ var localService(default,null) : Bool; @:native("default") var default_(default,null) : Bool; diff --git a/std/js/html/Storage.hx b/std/js/html/Storage.hx index e5ccf15d..2aae0384 100644 --- a/std/js/html/Storage.hx +++ b/std/js/html/Storage.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,23 +20,54 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Storage.webidl line 14:0. Do not edit! +// This file is generated from mozilla\Storage.webidl. Do not edit! package js.html; +/** + The `Storage` interface of the Web Storage API provides access to the session storage or local storage for a particular domain, allowing you to for example add, modify or delete stored data items. + + Documentation [Storage](https://developer.mozilla.org/en-US/docs/Web/API/Storage) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Storage$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Storage") extern class Storage { + + /** + Returns an integer representing the number of data items stored in the `Storage` object. + **/ var length(default,null) : Int; /** @throws DOMError */ + + /** + When passed a number n, this method will return the name of the nth key in the storage. + **/ function key( index : Int ) : String; /** @throws DOMError */ + + /** + When passed a key name, will return that key's value. + **/ function getItem( key : String ) : String; /** @throws DOMError */ + + /** + When passed a key name and value, will add that key to the storage, or update that key's value if it already exists. + **/ function setItem( key : String, value : String ) : Void; /** @throws DOMError */ + + /** + When passed a key name, will remove that key from the storage. + **/ function removeItem( key : String ) : Void; /** @throws DOMError */ + + /** + When invoked, will empty all keys out of the storage. + **/ function clear() : Void; } \ No newline at end of file diff --git a/std/js/html/StorageEvent.hx b/std/js/html/StorageEvent.hx index 50a07205..52eaa22a 100644 --- a/std/js/html/StorageEvent.hx +++ b/std/js/html/StorageEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/StorageEvent.webidl line 14:0. Do not edit! +// This file is generated from mozilla\StorageEvent.webidl. Do not edit! package js.html; +/** + A `StorageEvent` is sent to a window when a storage area changes. + + Documentation [StorageEvent](https://developer.mozilla.org/en-US/docs/Web/API/StorageEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/StorageEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("StorageEvent") extern class StorageEvent extends Event { @@ -35,6 +42,5 @@ extern class StorageEvent extends Event /** @throws DOMError */ function new( type : String, ?eventInitDict : StorageEventInit ) : Void; - /** @throws DOMError */ function initStorageEvent( type : String, canBubble : Bool, cancelable : Bool, key : String, oldValue : String, newValue : String, url : String, storageArea : Storage ) : Void; } \ No newline at end of file diff --git a/std/js/html/StorageEventInit.hx b/std/js/html/StorageEventInit.hx index 6c60ee69..286df44d 100644 --- a/std/js/html/StorageEventInit.hx +++ b/std/js/html/StorageEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/StorageEvent.webidl line 34:0. Do not edit! +// This file is generated from mozilla\StorageEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/StyleElement.hx b/std/js/html/StyleElement.hx index 5cf53b52..78e957e8 100644 --- a/std/js/html/StyleElement.hx +++ b/std/js/html/StyleElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,39 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLStyleElement.webidl line 11:0. Do not edit! +// This file is generated from mozilla\HTMLStyleElement.webidl. Do not edit! package js.html; +/** + The `HTMLStyleElement` interface represents a `style` element. It inherits properties and methods from its parent, `HTMLElement`, and from `LinkStyle`. + + Documentation [HTMLStyleElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLStyleElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLStyleElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLStyleElement") extern class StyleElement extends Element { + + /** + Is a `Boolean` value representing whether or not the stylesheet is disabled (true) or not (false). + **/ var disabled : Bool; + + /** + Is a `DOMString` representing the intended destination medium for style information. + **/ var media : String; + + /** + Is a `DOMString` representing the type of style being applied by this statement. + **/ var type : String; + + /** + Is a `Boolean` value indicating if the element applies to the whole document (`false`) or only to the parent's sub-tree (`true`). + **/ var scoped : Bool; var sheet(default,null) : StyleSheet; diff --git a/std/js/html/StyleSheet.hx b/std/js/html/StyleSheet.hx index 98a16870..3250327c 100644 --- a/std/js/html/StyleSheet.hx +++ b/std/js/html/StyleSheet.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,19 +20,54 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/StyleSheet.webidl line 12:0. Do not edit! +// This file is generated from mozilla\StyleSheet.webidl. Do not edit! package js.html; +/** + An object implementing the `StyleSheet` interface represents a single style sheet. CSS style sheets will further implement the more specialized `CSSStyleSheet` interface. + + Documentation [StyleSheet](https://developer.mozilla.org/en-US/docs/Web/API/StyleSheet) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/StyleSheet$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("StyleSheet") extern class StyleSheet { + + /** + Returns a `DOMString` representing the style sheet language for this style sheet. + **/ var type(default,null) : String; + + /** + Returns a `DOMString` representing the location of the stylesheet. + **/ var href(default,null) : String; + + /** + Returns a `Node` associating this style sheet with the current document. + **/ var ownerNode(default,null) : Node; + + /** + Returns a `StyleSheet` including this one, if any; returns `null` if there aren't any. + **/ var parentStyleSheet(default,null) : StyleSheet; + + /** + Returns a `DOMString` representing the advisory title of the current style sheet. + **/ var title(default,null) : String; + + /** + Returns a `MediaList` representing the intended destination medium for style information. + **/ var media(default,null) : MediaList; + + /** + Is a `Boolean` representing whether the current stylesheet has been applied or not. + **/ var disabled : Bool; } \ No newline at end of file diff --git a/std/js/html/StyleSheetList.hx b/std/js/html/StyleSheetList.hx index ecf4d37d..b6c8321c 100644 --- a/std/js/html/StyleSheetList.hx +++ b/std/js/html/StyleSheetList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/StyleSheetList.webidl line 5:0. Do not edit! +// This file is generated from mozilla\StyleSheetList.webidl. Do not edit! package js.html; +/** + The `StyleSheetList` interface represents a list of `StyleSheet`. + + Documentation [StyleSheetList](https://developer.mozilla.org/en-US/docs/Web/API/StyleSheetList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/StyleSheetList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("StyleSheetList") extern class StyleSheetList implements ArrayAccess { diff --git a/std/js/html/SubtleCrypto.hx b/std/js/html/SubtleCrypto.hx index 442cd9a9..a5e47995 100644 --- a/std/js/html/SubtleCrypto.hx +++ b/std/js/html/SubtleCrypto.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,35 +20,90 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SubtleCrypto.webidl line 159:0. Do not edit! +// This file is generated from mozilla\SubtleCrypto.webidl. Do not edit! package js.html; +/** + The `SubtleCrypto` interface represents a set of cryptographic primitives. It is available via the `Crypto.subtle` properties available in a window context (via `Window.crypto`). + + Documentation [SubtleCrypto](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SubtleCrypto") extern class SubtleCrypto { /** @throws DOMError */ + + /** + Returns a `Promise` of the encrypted data corresponding to the clear text, algorithm and key given as parameters. + **/ function encrypt( algorithm : haxe.extern.EitherType, key : CryptoKey, data : haxe.extern.EitherType ) : Promise; /** @throws DOMError */ + + /** + Returns a `Promise` of the clear data corresponding to the encrypted text, algorithm and key given as parameters. + **/ function decrypt( algorithm : haxe.extern.EitherType, key : CryptoKey, data : haxe.extern.EitherType ) : Promise; /** @throws DOMError */ + + /** + Returns a `Promise` of the signature corresponding to the text, algorithm and key given as parameters. + **/ function sign( algorithm : haxe.extern.EitherType, key : CryptoKey, data : haxe.extern.EitherType ) : Promise; /** @throws DOMError */ + + /** + Returns a `Promise` of a `Boolean` value indicating if the signature given as parameter matches the text, algorithm and key also given as parameters. + **/ function verify( algorithm : haxe.extern.EitherType, key : CryptoKey, signature : haxe.extern.EitherType, data : haxe.extern.EitherType ) : Promise; /** @throws DOMError */ + + /** + Returns a `Promise` of a digest generated from the algorithm and text given as parameters. + **/ function digest( algorithm : haxe.extern.EitherType, data : haxe.extern.EitherType ) : Promise; /** @throws DOMError */ + + /** + Returns a `Promise` of a newly generated `CryptoKey`, for symmetrical algorithms, or a `CryptoKeyPair`, containing two newly generated keys, for asymmetrical algorithm, that matches the algorithm, the usages and the extractability given as parameters. + **/ function generateKey( algorithm : haxe.extern.EitherType, extractable : Bool, keyUsages : Array ) : Promise; /** @throws DOMError */ + + /** + Returns a `Promise` of a newly generated `CryptoKey` derived from a master key and a specific algorithm given as parameters. + **/ function deriveKey( algorithm : haxe.extern.EitherType, baseKey : CryptoKey, derivedKeyType : haxe.extern.EitherType, extractable : Bool, keyUsages : Array ) : Promise; /** @throws DOMError */ + + /** + Returns a `Promise` of a newly generated buffer of pseudo-random bits derived from a master key and a specific algorithm given as parameters. + **/ function deriveBits( algorithm : haxe.extern.EitherType, baseKey : CryptoKey, length : Int ) : Promise; /** @throws DOMError */ + + /** + Returns a `Promise` of a `CryptoKey` corresponding to the format, the algorithm, the raw key data, the usages and the extractability given as parameters. + **/ function importKey( format : String, keyData : Dynamic, algorithm : haxe.extern.EitherType, extractable : Bool, keyUsages : Array ) : Promise; /** @throws DOMError */ + + /** + Returns a `Promise` of a buffer containing the key in the format requested. + **/ function exportKey( format : String, key : CryptoKey ) : Promise; /** @throws DOMError */ + + /** + Returns a `Promise` of a wrapped symmetric key for usage (transfer, storage) in insecure environments. The wrapped buffer returned is in the format given in parameters, and contains the key wrapped by the given wrapping key with the given algorithm. + **/ function wrapKey( format : String, key : CryptoKey, wrappingKey : CryptoKey, wrapAlgorithm : haxe.extern.EitherType ) : Promise; /** @throws DOMError */ + + /** + Returns a `Promise` of a `CryptoKey` corresponding to the wrapped key given in parameter. + **/ function unwrapKey( format : String, wrappedKey : haxe.extern.EitherType, unwrappingKey : CryptoKey, unwrapAlgorithm : haxe.extern.EitherType, unwrappedKeyAlgorithm : haxe.extern.EitherType, extractable : Bool, keyUsages : Array ) : Promise; } \ No newline at end of file diff --git a/std/js/html/SupportedType.hx b/std/js/html/SupportedType.hx index 530bb8c3..20289956 100644 --- a/std/js/html/SupportedType.hx +++ b/std/js/html/SupportedType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMParser.webidl line 13:0. Do not edit! +// This file is generated from mozilla\DOMParser.webidl. Do not edit! package js.html; diff --git a/std/js/html/TableCaptionElement.hx b/std/js/html/TableCaptionElement.hx index 8b139727..57d6d0e0 100644 --- a/std/js/html/TableCaptionElement.hx +++ b/std/js/html/TableCaptionElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLTableCaptionElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLTableCaptionElement.webidl. Do not edit! package js.html; +/** + The `HTMLTableCaptionElement` interface special properties (beyond the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating table caption elements. + + Documentation [HTMLTableCaptionElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCaptionElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCaptionElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLTableCaptionElement") extern class TableCaptionElement extends Element { + + /** + Is a `DOMString` which represents an enumerated attribute indicating alignment of the caption with respect to the table. + **/ var align : String; } \ No newline at end of file diff --git a/std/js/html/TableCellElement.hx b/std/js/html/TableCellElement.hx index 3d2c9070..06ab4a09 100644 --- a/std/js/html/TableCellElement.hx +++ b/std/js/html/TableCellElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,27 +20,86 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLTableCellElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLTableCellElement.webidl. Do not edit! package js.html; +/** + The `HTMLTableCellElement` interface provides special properties and methods (beyond the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating the layout and presentation of table cells, either header or data cells, in an HTML document. + + Documentation [HTMLTableCellElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLTableCellElement") extern class TableCellElement extends Element { + + /** + Is a `unsigned` `long` that represents the number of columns this cell must span. It reflects the `colspan` attribute. + **/ var colSpan : Int; + + /** + Is a `unsigned` `long` that represents the number of rows this cell must span. It reflects the `rowspan` attribute. + **/ var rowSpan : Int; + + /** + Is a `DOMSettableTokenList` describing a list of `id` of `th` elements that represents headers associated with the cell. It reflects the `headers` attribute. + **/ var headers : String; + + /** + Is a `long` representing the cell position in the cells collection of the `tr` it belongs to. If the cell doesn't belong to a `tr`, it returns `-1`. + **/ var cellIndex(default,null) : Int; var abbr : String; var scope : String; + + /** + Is a `DOMString` containing an enumerated value reflecting the `align` attribute. It indicates the alignment of the element's contents with respect to the surrounding context. The possible values are `"left"`, `"right"`, and `"center"`. + **/ var align : String; + + /** + Is a `DOMString` containing a name grouping cells in virtual. It reflects the obsolete `axis` attribute. + **/ var axis : String; + + /** + Is a `DOMString` containing a length of pixel of the hinted height of the cell. It reflects the obsolete `height` attribute. + **/ var height : String; + + /** + Is a `DOMString` containing a length of pixel of the hinted width of the cell. It reflects the obsolete `width` attribute. + **/ var width : String; + + /** + Is a `DOMString` containing one single chararcter. This character is the one to align all the cell of a column on. It reflects the `char` and default to the decimal points associated with the language, e.g. `'.'` for English, or `','` for French. This property was optional and was not very well supported. + **/ var ch : String; + + /** + Is a `DOMString` containing a integer indicating how many characters must be left at the right (for left-to-right scripts; or at the left for right-to-left scripts) of the character defined by `HTMLTableCellElement.ch`. This property was optional and was not very well supported. + **/ var chOff : String; + + /** + Is a `Boolean` value reflecting the `nowrap` attribute and indicating if cell content can be broken in several lines. + **/ var noWrap : Bool; + + /** + Is a `DOMString` representing an enumerated value indicating how the content of the cell must be vertically aligned. It reflects the `valign` attribute and can have one of the following values: `"top"`, `"middle"`, `"bottom"`, or `"baseline"`. + **/ var vAlign : String; + + /** + Is a `DOMString` containing the background color of the cells. It reflects the obsolete `bgColor` attribute. + **/ var bgColor : String; } \ No newline at end of file diff --git a/std/js/html/TableColElement.hx b/std/js/html/TableColElement.hx index 85feba74..54bc8c1a 100644 --- a/std/js/html/TableColElement.hx +++ b/std/js/html/TableColElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLTableColElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLTableColElement.webidl. Do not edit! package js.html; +/** + The `HTMLTableColElement` interface provides special properties (beyond the `HTMLElement` interface it also has available to it inheritance) for manipulating single or grouped table column elements. + + Documentation [HTMLTableColElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableColElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableColElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLTableColElement") extern class TableColElement extends Element { diff --git a/std/js/html/TableElement.hx b/std/js/html/TableElement.hx index 0382710e..3ecc5b80 100644 --- a/std/js/html/TableElement.hx +++ b/std/js/html/TableElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,37 +20,132 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLTableElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLTableElement.webidl. Do not edit! package js.html; +/** + The `HTMLTableElement` interface provides special properties and methods (beyond the regular `HTMLElement` object interface it also has available to it by inheritance) for manipulating the layout and presentation of tables in an HTML document. + + Documentation [HTMLTableElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLTableElement") extern class TableElement extends Element { + + /** + Is a `HTMLTableCaptionElement` representing the first `caption` that is a child of the element, or `null` if none is found. When set, if the object doesn't represent a `caption`, a `DOMException` with the `HierarchyRequestError` name is thrown. If a correct object is given, it is inserted in the tree as the first child of this element and the first `caption` that is a child of this element is removed from the tree, if any. + **/ var caption : TableCaptionElement; + + /** + Is a `HTMLTableSectionElement` representing the first `thead` that is a child of the element, or `null` if none is found. When set, if the object doesn't represent a `thead`, a `DOMException` with the `HierarchyRequestError` name is thrown. If a correct object is given, it is inserted in the tree immediately before the first element that is neither a `caption`, nor a `colgroup`, or as the last child if there is no such element, and the first `thead` that is a child of this element is removed from the tree, if any. + **/ var tHead : TableSectionElement; + + /** + Is a `HTMLTableSectionElement` representing the first `tfoot` that is a child of the element, or `null` if none is found. When set, if the object doesn't represent a `tfoot`, a `DOMException` with the `HierarchyRequestError` name is thrown. If a correct object is given, it is inserted in the tree immediately before the first element that is neither a `caption`, a `colgroup`, nor a `thead`, or as the last child if there is no such element, and the first `tfoot` that is a child of this element is removed from the tree, if any. + **/ var tFoot : TableSectionElement; + + /** + Returns a live `HTMLCollection` containing all the `tbody` of the element. The `HTMLCollection` is live and is automatically updated when the `HTMLTableElement` changes. + **/ var tBodies(default,null) : HTMLCollection; + + /** + Returns a live `HTMLCollection` containing all the rows of the element, that is all `tr` that are a child of the element, or a child or one of its `thead`, `tbody` and `tfoot` children. The rows members of a `thead` appear first, in tree order, and those members of a `tbody` last, also in tree order. The `HTMLCollection` is live and is automatically updated when the `HTMLTableElement` changes. + **/ var rows(default,null) : HTMLCollection; + + /** + Is a `DOMString` containing an enumerated value reflecting the `align` attribute. It indicates the alignment of the element's contents with respect to the surrounding context. The possible values are `"left"`, `"right"`, and `"center"`. + **/ var align : String; + + /** + Is a `DOMString` containing the width in pixels of the border of the table. It reflects the obsolete `border` attribute. + **/ var border : String; + + /** + Is a `DOMString` containing the type of the external borders of the table. It reflects the obsolete `frame` attribute and can take one of the following values: `"void"`, `"above"`, `"below"`, `"hsides"`, `"vsides"`, `"lhs"`, `"rhs"`, `"box"`, or `"border"`. + **/ var frame : String; + + /** + Is a `DOMString` containing the type of the internal borders of the table. It reflects the obsolete `rules` attribute and can take one of the following values: `"none"`, `"groups"`, `"rows"`, `"cols"`, or `"all"`. + **/ var rules : String; + + /** + Is a `DOMString` containing a description of the purpose or the structure of the table. It reflects the obsolete `summary` attribute. + **/ var summary : String; + + /** + Is a `DOMString` containing the length in pixels or in percentage of the desired width fo the entire table. It reflects the obsolete `width` attribute. + **/ var width : String; + + /** + Is a `DOMString` containing the background color of the cells. It reflects the obsolete `bgColor` attribute. + **/ var bgColor : String; + + /** + Is a `DOMString` containing the width in pixels of the horizontal and vertical sapce between cell content and cell borders. It reflects the obsolete `cellpadding` attribute. + **/ var cellPadding : String; + + /** + Is a `DOMString` containing the width in pixels of the horizontal and vertical separation between cells. It reflects the obsolete `cellspacing` attribute. + **/ var cellSpacing : String; + + /** + Returns an `HTMLElement` representing the first `caption` that is a child of the element. If none is found, a new one is created and inserted in the tree as the first child of the `table` element. + **/ function createCaption() : Element; + + /** + Removes the first `caption` that is a child of the element. + **/ function deleteCaption() : Void; + + /** + Returns an `HTMLElement` representing the first `thead` that is a child of the element. If none is found, a new one is created and inserted in the tree immediately before the first element that is neither a `caption`, nor a `colgroup`, or as the last child if there is no such element. + **/ function createTHead() : Element; + + /** + Removes the first `thead` that is a child of the element. + **/ function deleteTHead() : Void; + + /** + Returns an `HTMLElement` representing the first `tfoot` that is a child of the element. If none is found, a new one is created and inserted in the tree immediately before the first element that is neither a `caption`, a `colgroup`, nor a `thead`, or as the last child if there is no such element. + **/ function createTFoot() : Element; + + /** + Removes the first `tfoot` that is a child of the element. + **/ function deleteTFoot() : Void; function createTBody() : Element; /** @throws DOMError */ + + /** + Returns an `HTMLTableRowElement` representing a new row of the table. It inserts it in the rows collection immediately before the `tr` element at the given `index` position. If necessary a `tbody` is created. If the `index` is `-1`, the new row is appended to the collection. If the `index` is smaller than `-1` or greater than the number of rows in the collection, a `DOMException` with the value `IndexSizeError` is raised. + **/ function insertRow( ?index : Int = -1 ) : Element; /** @throws DOMError */ + + /** + Removes the row corresponding to the `index` given in parameter. If the `index` value is `-1` the last row is removed; if it smaller than `-1` or greater than the amount of rows in the collection, a `DOMException` with the value `IndexSizeError` is raised. + **/ function deleteRow( index : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/TableRowElement.hx b/std/js/html/TableRowElement.hx index bdbcfd55..512f1701 100644 --- a/std/js/html/TableRowElement.hx +++ b/std/js/html/TableRowElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,24 +20,71 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLTableRowElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLTableRowElement.webidl. Do not edit! package js.html; +/** + The `HTMLTableRowElement` interface provides special properties and methods (beyond the `HTMLElement` interface it also has available to it by inheritance) for manipulating the layout and presentation of rows in an HTML table. + + Documentation [HTMLTableRowElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableRowElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableRowElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLTableRowElement") extern class TableRowElement extends Element { + + /** + Returns a `long` value which gives the logical position of the row within the entire table. If the row is not part of a table, returns `-1`. + **/ var rowIndex(default,null) : Int; + + /** + Returns a `long` value which gives the logical position of the row within the table section it belongs to. If the row is not part of a section, returns `-1`. + **/ var sectionRowIndex(default,null) : Int; + + /** + Returns a live `HTMLCollection` containing the cells in the row. The `HTMLCollection` is live and is automatically updated when cells are added or removed. + **/ var cells(default,null) : HTMLCollection; + + /** + Is a `DOMString` containing an enumerated value reflecting the `align` attribute. It indicates the alignment of the element's contents with respect to the surrounding context. The possible values are `"left"`, `"right"`, and `"center"`. + **/ var align : String; + + /** + Is a `DOMString` containing one single character. This character is the one to align all the cell of a column on. It reflects the `char` and default to the decimal points associated with the language, e.g. `'.'` for English, or `','` for French. This property was optional and was not very well supported. + **/ var ch : String; + + /** + Is a `DOMString` containing a integer indicating how many characters must be left at the right (for left-to-right scripts; or at the left for right-to-left scripts) of the character defined by `HTMLTableRowElement.ch`. This property was optional and was not very well supported. + **/ var chOff : String; + + /** + Is a `DOMString` representing an enumerated value indicating how the content of the cell must be vertically aligned. It reflects the `valign` attribute and can have one of the following values: `"top"`, `"middle"`, `"bottom"`, or `"baseline"`. + **/ var vAlign : String; + + /** + Is a `DOMString` containing the background color of the cells. It reflects the obsolete `bgColor` attribute. + **/ var bgColor : String; /** @throws DOMError */ + + /** + Inserts a new cell just before the given position in the row. If the given position is not given or is `-1`, it appends the cell to the row. If the given position is greater (or equal as it starts at zero) than the amount of cells in the row, or is smaller than `-1`, it raises a `DOMException` with the `IndexSizeError` value. Returns a reference to a HTMLTableCellElement [en-US]. + **/ function insertCell( ?index : Int = -1 ) : Element; /** @throws DOMError */ + + /** + Removes the cell at the given position in the row. If the given position is greater (or equal as it starts at zero) than the amount of cells in the row, or is smaller than `0`, it raises a `DOMException` with the `IndexSizeError` value. + **/ function deleteCell( index : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/TableSectionElement.hx b/std/js/html/TableSectionElement.hx index 24454cc4..77b7a9d2 100644 --- a/std/js/html/TableSectionElement.hx +++ b/std/js/html/TableSectionElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,21 +20,56 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLTableSectionElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLTableSectionElement.webidl. Do not edit! package js.html; +/** + The `HTMLTableSectionElement` interface provides special properties and methods (beyond the `HTMLElement` interface it also has available to it by inheritance) for manipulating the layout and presentation of sections, that is headers, footers and bodies, in an HTML table. + + Documentation [HTMLTableSectionElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableSectionElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableSectionElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLTableSectionElement") extern class TableSectionElement extends Element { + + /** + Returns a live `HTMLCollection` containing the rows in the section. The `HTMLCollection` is live and is automatically updated when rows are added or removed. + **/ var rows(default,null) : HTMLCollection; + + /** + Is a `DOMString` containing an enumerated value reflecting the `align` attribute. It indicates the alignment of the element's contents with respect to the surrounding context. The possible values are `"left"`, `"right"`, and `"center"`. + **/ var align : String; + + /** + Is a `DOMString` containing one single chararcter. This character is the one to align all the cell of a column on. It reflects the `char` and default to the decimal points associated with the language, e.g. `'.'` for English, or `','` for French. This property was optional and was not very well supported. + **/ var ch : String; + + /** + Is a `DOMString` containing a integer indicating how many characters must be left at the right (for left-to-right scripts; or at the left for right-to-left scripts) of the character defined by `HTMLTableRowElement.ch`. This property was optional and was not very well supported. + **/ var chOff : String; + + /** + Is a `DOMString` representing an enumerated value indicating how the content of the cell must be vertically aligned. It reflects the `valign` attribute and can have one of the following values: `"top"`, `"middle"`, `"bottom"`, or `"baseline"`. + **/ var vAlign : String; /** @throws DOMError */ + + /** + Inserts a new row just before the given position in the section. If the given position is not given or is `-1`, it appends the row to the end of section. If the given position is greater (or equal as it starts at zero) than the amount of rows in the section, or is smaller than `-1`, it raises a `DOMException` with the `IndexSizeError` value. + **/ function insertRow( ?index : Int = -1 ) : Element; /** @throws DOMError */ + + /** + Removes the cell at the given position in the section. If the given position is greater (or equal as it starts at zero) than the amount of rows in the section, or is smaller than `0`, it raises a `DOMException` with the `IndexSizeError` value. + **/ function deleteRow( index : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/TemplateElement.hx b/std/js/html/TemplateElement.hx index ad009827..5f4a8de1 100644 --- a/std/js/html/TemplateElement.hx +++ b/std/js/html/TemplateElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLTemplateElement.webidl line 12:0. Do not edit! +// This file is generated from mozilla\HTMLTemplateElement.webidl. Do not edit! package js.html; diff --git a/std/js/html/Text.hx b/std/js/html/Text.hx index 21fa1dec..987e38db 100644 --- a/std/js/html/Text.hx +++ b/std/js/html/Text.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Text.webidl line 14:0. Do not edit! +// This file is generated from mozilla\Text.webidl. Do not edit! package js.html; +/** + The `Text` interface represents the textual content of `Element` or `Attr`.  If an element has no markup within its content, it has a single child implementing `Text` that contains the element's text.  However, if the element contains markup, it is parsed into information items and `Text` nodes that form its children. + + Documentation [Text](https://developer.mozilla.org/en-US/docs/Web/API/Text) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Text$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Text") extern class Text extends CharacterData { + + /** + Returns a `DOMString` containing the text of all `Text` nodes logically adjacent to this `Node`, concatenated in document order. + **/ var wholeText(default,null) : String; /** @throws DOMError */ diff --git a/std/js/html/TextAreaElement.hx b/std/js/html/TextAreaElement.hx index 53485b60..7e28ead2 100644 --- a/std/js/html/TextAreaElement.hx +++ b/std/js/html/TextAreaElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLTextAreaElement.webidl line 17:0. Do not edit! +// This file is generated from mozilla\HTMLTextAreaElement.webidl. Do not edit! package js.html; +/** + The `HTMLTextAreaElement` interface provides special properties and methods for manipulating the layout and presentation of `textarea` elements. + + Documentation [HTMLTextAreaElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLTextAreaElement") extern class TextAreaElement extends Element { diff --git a/std/js/html/TextDecodeOptions.hx b/std/js/html/TextDecodeOptions.hx index af68f02e..941d74b7 100644 --- a/std/js/html/TextDecodeOptions.hx +++ b/std/js/html/TextDecodeOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TextDecoder.webidl line 28:0. Do not edit! +// This file is generated from mozilla\TextDecoder.webidl. Do not edit! package js.html; diff --git a/std/js/html/TextDecoder.hx b/std/js/html/TextDecoder.hx index b9bae301..c51802ea 100644 --- a/std/js/html/TextDecoder.hx +++ b/std/js/html/TextDecoder.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,18 +20,37 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TextDecoder.webidl line 15:0. Do not edit! +// This file is generated from mozilla\TextDecoder.webidl. Do not edit! package js.html; +/** + The `TextDecoder` interface represents a decoder for a specific method, that is a specific character encoding, like `utf-8`, `iso-8859-2`, `koi8`, `cp1261`, `gbk`, ... A decoder takes a stream of bytes as input and emits a stream of code points. For a more scalable, non-native library, see `StringView` – a C-like representation of strings based on typed arrays. + + Documentation [TextDecoder](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("TextDecoder") extern class TextDecoder { + + /** + Is a `DOMString` containing the name of the decoder, that is a string describing the method the `TextDecoder` will use. + **/ var encoding(default,null) : String; + + /** + Is a `Boolean` indicating whether the error mode is fatal. + **/ var fatal(default,null) : Bool; /** @throws DOMError */ function new( ?label : String = "utf-8", ?options : TextDecoderOptions ) : Void; /** @throws DOMError */ + + /** + Returns a `DOMString` containing the text decoded with the method of the specific `TextDecoder` object. + **/ function decode( ?input : haxe.extern.EitherType, ?options : TextDecodeOptions ) : String; } \ No newline at end of file diff --git a/std/js/html/TextDecoderOptions.hx b/std/js/html/TextDecoderOptions.hx index ab7336c7..0a84709d 100644 --- a/std/js/html/TextDecoderOptions.hx +++ b/std/js/html/TextDecoderOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TextDecoder.webidl line 24:0. Do not edit! +// This file is generated from mozilla\TextDecoder.webidl. Do not edit! package js.html; diff --git a/std/js/html/TextEncoder.hx b/std/js/html/TextEncoder.hx index 12da259f..6d227ccf 100644 --- a/std/js/html/TextEncoder.hx +++ b/std/js/html/TextEncoder.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,31 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TextEncoder.webidl line 15:0. Do not edit! +// This file is generated from mozilla\TextEncoder.webidl. Do not edit! package js.html; +/** + TextEncoder takes a stream of code points as input and emits a stream of bytes. For a more scalable, non-native library, see `StringView` – a C-like representation of strings based on typed arrays. + + Documentation [TextEncoder](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("TextEncoder") extern class TextEncoder { + + /** + Is a `DOMString` containing the name of the encoder, that is a string describing the method the `TextEncoder` will use. + **/ var encoding(default,null) : String; /** @throws DOMError */ function new( ?utfLabel : String = "utf-8" ) : Void; + + /** + Returns a `Uint8Array` containing utf-8 encoded text. + **/ function encode( ?input : String = "" ) : Uint8Array; } \ No newline at end of file diff --git a/std/js/html/TextMetrics.hx b/std/js/html/TextMetrics.hx index 3820449b..423e1bf2 100644 --- a/std/js/html/TextMetrics.hx +++ b/std/js/html/TextMetrics.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/CanvasRenderingContext2D.webidl line 301:0. Do not edit! +// This file is generated from mozilla\CanvasRenderingContext2D.webidl. Do not edit! package js.html; +/** + The `TextMetrics` interface represents the dimension of a text in the canvas, as created by the `CanvasRenderingContext2D.measureText()` method. + + Documentation [TextMetrics](https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("TextMetrics") extern class TextMetrics { + + /** + Is a `double` giving the calculated width of a segment of inline text in CSS pixels. It takes into account the current font of the context. + **/ var width(default,null) : Float; } \ No newline at end of file diff --git a/std/js/html/TextTrack.hx b/std/js/html/TextTrack.hx index 7a411f74..3db8841e 100644 --- a/std/js/html/TextTrack.hx +++ b/std/js/html/TextTrack.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TextTrack.webidl line 25:0. Do not edit! +// This file is generated from mozilla\TextTrack.webidl. Do not edit! package js.html; @@ -35,6 +35,7 @@ extern class TextTrack extends EventTarget var mode : TextTrackMode; var cues(default,null) : TextTrackCueList; var activeCues(default,null) : TextTrackCueList; + var oncuechange : haxe.Constraints.Function; function addCue( cue : VTTCue ) : Void; /** @throws DOMError */ diff --git a/std/js/html/TextTrackCue.hx b/std/js/html/TextTrackCue.hx index 8e320332..2ab3f4a2 100644 --- a/std/js/html/TextTrackCue.hx +++ b/std/js/html/TextTrackCue.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,8 +20,19 @@ * DEALINGS IN THE SOFTWARE. */ +// This file is generated from mozilla\TextTrackCue.webidl. Do not edit! + package js.html; -/** @deprecated Use VTTCue instead. */ -@:deprecated("TextTrackCue is deprecated, use VTTCue instead") -typedef TextTrackCue = VTTCue; +@:native("TextTrackCue") +extern class TextTrackCue extends EventTarget +{ + var track(default,null) : TextTrack; + var id : String; + var startTime : Float; + var endTime : Float; + var pauseOnExit : Bool; + var onenter : haxe.Constraints.Function; + var onexit : haxe.Constraints.Function; + +} \ No newline at end of file diff --git a/std/js/html/TextTrackCueList.hx b/std/js/html/TextTrackCueList.hx index e26669f8..3004438c 100644 --- a/std/js/html/TextTrackCueList.hx +++ b/std/js/html/TextTrackCueList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TextTrackCueList.webidl line 11:0. Do not edit! +// This file is generated from mozilla\TextTrackCueList.webidl. Do not edit! package js.html; diff --git a/std/js/html/TextTrackKind.hx b/std/js/html/TextTrackKind.hx index 373c2cd7..d90d800c 100644 --- a/std/js/html/TextTrackKind.hx +++ b/std/js/html/TextTrackKind.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TextTrack.webidl line 10:0. Do not edit! +// This file is generated from mozilla\TextTrack.webidl. Do not edit! package js.html; diff --git a/std/js/html/TextTrackList.hx b/std/js/html/TextTrackList.hx index 641380ed..b6aad223 100644 --- a/std/js/html/TextTrackList.hx +++ b/std/js/html/TextTrackList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TextTrackList.webidl line 11:0. Do not edit! +// This file is generated from mozilla\TextTrackList.webidl. Do not edit! package js.html; diff --git a/std/js/html/TextTrackMode.hx b/std/js/html/TextTrackMode.hx index c3f19189..169d53a2 100644 --- a/std/js/html/TextTrackMode.hx +++ b/std/js/html/TextTrackMode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TextTrack.webidl line 18:0. Do not edit! +// This file is generated from mozilla\TextTrack.webidl. Do not edit! package js.html; diff --git a/std/js/html/TimeElement.hx b/std/js/html/TimeElement.hx index eedaeb4b..763df07e 100644 --- a/std/js/html/TimeElement.hx +++ b/std/js/html/TimeElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLTimeElement.webidl line 10:0. Do not edit! +// This file is generated from mozilla\HTMLTimeElement.webidl. Do not edit! package js.html; +/** + The `HTMLTimeElement` interface provides special properties (beyond the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating `time` elements. + + Documentation [HTMLTimeElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTimeElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTimeElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLTimeElement") extern class TimeElement extends Element { + + /** + Is a `DOMString` that reflects the `datetime` HTML attribute, containing a machine-readable form of the element's date and time value. + **/ var dateTime : String; } \ No newline at end of file diff --git a/std/js/html/TimeEvent.hx b/std/js/html/TimeEvent.hx index b3d4f218..81262789 100644 --- a/std/js/html/TimeEvent.hx +++ b/std/js/html/TimeEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TimeEvent.webidl line 13:0. Do not edit! +// This file is generated from mozilla\TimeEvent.webidl. Do not edit! package js.html; +/** + Extends Event. + + Documentation [TimeEvent](https://developer.mozilla.org/en-US/docs/Web/API/TimeEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/TimeEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("TimeEvent") extern class TimeEvent extends Event { diff --git a/std/js/html/TimeRanges.hx b/std/js/html/TimeRanges.hx index 48e7f967..50575a8a 100644 --- a/std/js/html/TimeRanges.hx +++ b/std/js/html/TimeRanges.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,17 +20,36 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TimeRanges.webidl line 14:0. Do not edit! +// This file is generated from mozilla\TimeRanges.webidl. Do not edit! package js.html; +/** + The `TimeRanges` interface is used to represent a set of time ranges, primarily for the purpose of tracking which portions of media have been buffered when loading it for use by the `audio` and `video` elements. + + Documentation [TimeRanges](https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("TimeRanges") extern class TimeRanges { + + /** + Returns an `unsigned long` representing the number of time ranges represented by the time range object. + **/ var length(default,null) : Int; /** @throws DOMError */ + + /** + Returns the time for the start of the range with the specified index. + **/ function start( index : Int ) : Float; /** @throws DOMError */ + + /** + Returns the time for the end of the specified range. + **/ function end( index : Int ) : Float; } \ No newline at end of file diff --git a/std/js/html/TitleElement.hx b/std/js/html/TitleElement.hx index 289163a4..731f6c79 100644 --- a/std/js/html/TitleElement.hx +++ b/std/js/html/TitleElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLTitleElement.webidl line 10:0. Do not edit! +// This file is generated from mozilla\HTMLTitleElement.webidl. Do not edit! package js.html; +/** + The `HTMLTitleElement` interface contains the title for a document. This element inherits all of the properties and methods of the `HTMLElement` interface. + + Documentation [HTMLTitleElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTitleElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTitleElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLTitleElement") extern class TitleElement extends Element { + + /** + Is a `DOMString` representing the text of the document's title. + **/ var text : String; } \ No newline at end of file diff --git a/std/js/html/Touch.hx b/std/js/html/Touch.hx index f9510f5f..04839b61 100644 --- a/std/js/html/Touch.hx +++ b/std/js/html/Touch.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Touch.webidl line 14:0. Do not edit! +// This file is generated from mozilla\Touch.webidl. Do not edit! package js.html; +/** + The `Touch` interface represents a single contact point on a touch-sensitive device. The contact point is commonly a finger or stylus and the device may be a touchscreen or trackpad. + + Documentation [Touch](https://developer.mozilla.org/en-US/docs/Web/API/Touch) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Touch$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Touch") extern class Touch { @@ -40,4 +47,6 @@ extern class Touch var rotationAngle(default,null) : Float; var force(default,null) : Float; + /** @throws DOMError */ + function new( touchInitDict : TouchInit ) : Void; } \ No newline at end of file diff --git a/std/js/html/TouchEvent.hx b/std/js/html/TouchEvent.hx index 36731af1..1b89a5e6 100644 --- a/std/js/html/TouchEvent.hx +++ b/std/js/html/TouchEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TouchEvent.webidl line 8:0. Do not edit! +// This file is generated from mozilla\TouchEvent.webidl. Do not edit! package js.html; +/** + The `TouchEvent` interface represents an event sent when the state of contacts with a touch-sensitive surface changes. This surface can be a touch screen or trackpad, for example. The event can describe one or more points of contact with the screen and includes support for detecting movement, addition and removal of contact points, and so forth. + + Documentation [TouchEvent](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("TouchEvent") extern class TouchEvent extends UIEvent { @@ -36,5 +43,6 @@ extern class TouchEvent extends UIEvent var shiftKey(default,null) : Bool; /** @throws DOMError */ + function new( type : String, ?eventInitDict : TouchEventInit ) : Void; function initTouchEvent( type : String, canBubble : Bool, cancelable : Bool, view : Window, detail : Int, ctrlKey : Bool, altKey : Bool, shiftKey : Bool, metaKey : Bool, touches : TouchList, targetTouches : TouchList, changedTouches : TouchList ) : Void; } \ No newline at end of file diff --git a/std/js/html/TouchEventInit.hx b/std/js/html/TouchEventInit.hx new file mode 100644 index 00000000..29da8bfd --- /dev/null +++ b/std/js/html/TouchEventInit.hx @@ -0,0 +1,33 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\TouchEvent.webidl. Do not edit! + +package js.html; + +typedef TouchEventInit = +{ + > EventModifierInit, + @:optional var changedTouches : Array; + @:optional var targetTouches : Array; + @:optional var touches : Array; +} \ No newline at end of file diff --git a/std/js/html/TouchInit.hx b/std/js/html/TouchInit.hx new file mode 100644 index 00000000..73bb7cf5 --- /dev/null +++ b/std/js/html/TouchInit.hx @@ -0,0 +1,41 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Touch.webidl. Do not edit! + +package js.html; + +typedef TouchInit = +{ + @:optional var clientX : Int; + @:optional var clientY : Int; + @:optional var force : Float; + var identifier : Int; + @:optional var pageX : Int; + @:optional var pageY : Int; + @:optional var radiusX : Float; + @:optional var radiusY : Float; + @:optional var rotationAngle : Float; + @:optional var screenX : Int; + @:optional var screenY : Int; + var target : EventTarget; +} \ No newline at end of file diff --git a/std/js/html/TouchList.hx b/std/js/html/TouchList.hx index b0882b4e..66a749b4 100644 --- a/std/js/html/TouchList.hx +++ b/std/js/html/TouchList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TouchList.webidl line 14:0. Do not edit! +// This file is generated from mozilla\TouchList.webidl. Do not edit! package js.html; +/** + The `TouchList` interface represents a list of contact points with a touch surface; for example, if the user has three fingers on the touch surface (such as a screen or trackpad), the corresponding `TouchList` object would have one `Touch` object for each finger, for a total of three entries. + + Documentation [TouchList](https://developer.mozilla.org/en-US/docs/Web/API/TouchList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/TouchList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("TouchList") extern class TouchList implements ArrayAccess { + + /** + The number of `Touch` objects in the `TouchList`. + **/ var length(default,null) : Int; + + /** + Returns the `Touch` object at the specified index in the list. + **/ function item( index : Int ) : Touch; + + /** + Returns the first `Touch` item in the list whose identifier matches a specified value. + **/ function identifiedTouch( identifier : Int ) : Touch; } \ No newline at end of file diff --git a/std/js/html/TrackElement.hx b/std/js/html/TrackElement.hx index c5d8d009..843b1739 100644 --- a/std/js/html/TrackElement.hx +++ b/std/js/html/TrackElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLTrackElement.webidl line 11:0. Do not edit! +// This file is generated from mozilla\HTMLTrackElement.webidl. Do not edit! package js.html; +/** + The HTMLTrackElement` interface provides access to the properties of `track` elements, as well as methods to manipulate them. + + Documentation [HTMLTrackElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTrackElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTrackElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLTrackElement") extern class TrackElement extends Element { @@ -32,13 +39,67 @@ extern class TrackElement extends Element static inline var LOADED : Int = 2; static inline var ERROR : Int = 3; + + /** + Is a `DOMString` that reflects the `kind` HTML attribute, indicating how the text track is meant to be used. Possible values are: subtitles, captions, descriptions, chapters, metadata. + **/ var kind : String; + + /** + Is a `DOMString` that reflects the `src` HTML attribute, indicating the address of the text track data. + **/ var src : String; + + /** + Is a `DOMString` that reflects the `srclang` HTML attribute, indicating the language of the text track data. + **/ var srclang : String; + + /** + Is a `DOMString` that reflects the `label` HTML attribute, indicating a user-readable title for the track. + **/ var label : String; @:native("default") var default_ : Bool; + + /** + Returns  an unsigned short that show the readiness state of the track: + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConstantValueDescription
NONE0Indicates that the text track's cues have not been obtained.
LOADING1Indicates that the text track is loading and there have been no fatal errors encountered so far. Further cues might still be added to the track by the parser.
LOADED2Indicates that the text track has been loaded with no fatal errors.
ERROR3Indicates that the text track was enabled, but when the user agent attempted to obtain it, this failed in some way. Some or all of the cues are likely missing and will not be obtained.
+ + **/ var readyState(default,null) : Int; + + /** + Returns `TextTrack` is the track element's text track data. + **/ var track(default,null) : TextTrack; } \ No newline at end of file diff --git a/std/js/html/TrackEvent.hx b/std/js/html/TrackEvent.hx index ad02ec70..03dfd6d2 100644 --- a/std/js/html/TrackEvent.hx +++ b/std/js/html/TrackEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TrackEvent.webidl line 11:0. Do not edit! +// This file is generated from mozilla\TrackEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/TrackEventInit.hx b/std/js/html/TrackEventInit.hx index 0df60c0c..c082224d 100644 --- a/std/js/html/TrackEventInit.hx +++ b/std/js/html/TrackEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TrackEvent.webidl line 16:0. Do not edit! +// This file is generated from mozilla\TrackEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/TransitionEvent.hx b/std/js/html/TransitionEvent.hx index a1db9455..e055d5e6 100644 --- a/std/js/html/TransitionEvent.hx +++ b/std/js/html/TransitionEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TransitionEvent.webidl line 15:0. Do not edit! +// This file is generated from mozilla\TransitionEvent.webidl. Do not edit! package js.html; +/** + The `Transition``Event` interface represents events providing information related to transitions. + + Documentation [TransitionEvent](https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("TransitionEvent") extern class TransitionEvent extends Event { + + /** + Is a `DOMString` containing the name CSS property associated with the transition. + **/ var propertyName(default,null) : String; + + /** + Is a `float` giving the amount of time the transtion has been running, in seconds, when this event fired. This value is not affected by the `transition-delay` property. + **/ var elapsedTime(default,null) : Float; + + /** + Is a `DOMString`, starting with `'::'`, containing the name of the pseudo-element the animation runs on. If the transition doesn't run on a pseudo-element but on the element, an empty string: `''``.` + **/ var pseudoElement(default,null) : String; /** @throws DOMError */ diff --git a/std/js/html/TransitionEventInit.hx b/std/js/html/TransitionEventInit.hx index 9eb0ea8f..9cc31ff3 100644 --- a/std/js/html/TransitionEventInit.hx +++ b/std/js/html/TransitionEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TransitionEvent.webidl line 21:0. Do not edit! +// This file is generated from mozilla\TransitionEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/TreeWalker.hx b/std/js/html/TreeWalker.hx index 3c777353..0f40f3f2 100644 --- a/std/js/html/TreeWalker.hx +++ b/std/js/html/TreeWalker.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,30 +20,156 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/TreeWalker.webidl line 13:0. Do not edit! +// This file is generated from mozilla\TreeWalker.webidl. Do not edit! package js.html; +/** + The `TreeWalker` object represents the nodes of a document subtree and a position within them. + + Documentation [TreeWalker](https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("TreeWalker") extern class TreeWalker { + + /** + Returns a `Node` representing the root node as specified when the `TreeWalker` was created. + **/ var root(default,null) : Node; + + /** + Returns an unsigned long being a bitmask made of constants describing the types of Node that must to be presented. Non-matching nodes are skipped, but their children may be included, if relevant. The possible values are: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConstantNumerical valueDescription
NodeFilter.SHOW_ALL-1 (that is the max value of unsigned long)Shows all nodes.
NodeFilter.SHOW_ATTRIBUTE {{deprecated_inline}}2Shows attribute Attr nodes. This is meaningful only when creating a TreeWalker with an Attr node as its root; in this case, it means that the attribute node will appear in the first position of the iteration or traversal. Since attributes are never children of other nodes, they do not appear when traversing over the document tree.
NodeFilter.SHOW_CDATA_SECTION {{deprecated_inline}}8Shows CDATASection nodes.
NodeFilter.SHOW_COMMENT128Shows Comment nodes.
NodeFilter.SHOW_DOCUMENT256Shows Document nodes.
NodeFilter.SHOW_DOCUMENT_FRAGMENT1024Shows DocumentFragment nodes.
NodeFilter.SHOW_DOCUMENT_TYPE512Shows DocumentType nodes.
NodeFilter.SHOW_ELEMENT1Shows Element nodes.
NodeFilter.SHOW_ENTITY {{deprecated_inline}}32Shows Entity nodes. This is meaningful only when creating a TreeWalker with an Entity node as its root; in this case, it means that the Entity node will appear in the first position of the traversal. Since entities are not part of the document tree, they do not appear when traversing over the document tree.
NodeFilter.SHOW_ENTITY_REFERENCE {{deprecated_inline}}16Shows EntityReference nodes.
NodeFilter.SHOW_NOTATION {{deprecated_inline}}2048Shows Notation nodes. This is meaningful only when creating a TreeWalker with a Notation node as its root; in this case, it means that the Notation node will appear in the first position of the traversal. Since entities are not part of the document tree, they do not appear when traversing over the document tree.
NodeFilter.SHOW_PROCESSING_INSTRUCTION64Shows ProcessingInstruction nodes.
NodeFilter.SHOW_TEXT4Shows Text nodes.
+ + **/ var whatToShow(default,null) : Int; + + /** + Returns a `NodeFilter` used to select the relevant nodes. + **/ var filter(default,null) : NodeFilter; + + /** + Is the `Node` on which the `TreeWalker` is currently pointing at. + **/ var currentNode : Node; /** @throws DOMError */ + + /** + Moves the current `Node` to the first visible ancestor node in the document order, and returns the found node. It also moves the current node to this one. If no such node exists, or if it is before that the root node defined at the object construction, returns `null` and the current node is not changed. + **/ function parentNode() : Node; /** @throws DOMError */ + + /** + Moves the current `Node` to the first visible child of the current node, and returns the found child. It also moves the current node to this child. If no such child exists, returns `null` and the current node is not changed. + **/ function firstChild() : Node; /** @throws DOMError */ + + /** + Moves the current `Node` to the last visible child of the current node, and returns the found child. It also moves the current node to this child. If no such child exists, returns `null` and the current node is not changed. + **/ function lastChild() : Node; /** @throws DOMError */ + + /** + Moves the current `Node` to its previous sibling, if any, and returns the found sibling. If there is no such node, return `null` and the current node is not changed. + **/ function previousSibling() : Node; /** @throws DOMError */ + + /** + Moves the current `Node` to its next sibling, if any, and returns the found sibling. If there is no such node, return `null` and the current node is not changed. + **/ function nextSibling() : Node; /** @throws DOMError */ + + /** + Moves the current `Node` to the previous visible node in the document order, and returns the found node. It also moves the current node to this one. If no such node exists,or if it is before that the root node defined at the object construction, returns `null` and the current node is not changed. + **/ function previousNode() : Node; /** @throws DOMError */ + + /** + Moves the current `Node` to the next visible node in the document order, and returns the found node. It also moves the current node to this one. If no such node exists, returns `null` and the current node is not changed. + **/ function nextNode() : Node; } \ No newline at end of file diff --git a/std/js/html/UIEvent.hx b/std/js/html/UIEvent.hx index 947c5632..314c938c 100644 --- a/std/js/html/UIEvent.hx +++ b/std/js/html/UIEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,29 +20,76 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/UIEvent.webidl line 14:0. Do not edit! +// This file is generated from mozilla\UIEvent.webidl. Do not edit! package js.html; +/** + The `UIEvent` interface represents simple user interface events. + + Documentation [UIEvent](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("UIEvent") extern class UIEvent extends Event { static inline var SCROLL_PAGE_UP : Int = -32768; static inline var SCROLL_PAGE_DOWN : Int = 32768; + + /** + Returns a `WindowProxy` that contains the view that generated the event. + **/ var view(default,null) : Window; + + /** + Returns a `long` with details about the event, depending on the event type. + **/ var detail(default,null) : Int; + + /** + Returns the horizontal coordinate of the event relative to the current layer. + **/ var layerX(default,null) : Int; + + /** + Returns the vertical coordinate of the event relative to the current layer. + **/ var layerY(default,null) : Int; + + /** + Returns the horizontal coordinate of the event relative to the whole document. + **/ var pageX(default,null) : Int; + + /** + Returns the vertical coordinate of the event relative to the whole document. + **/ var pageY(default,null) : Int; + + /** + Returns the numeric `keyCode` of the key pressed, or the character code (`charCode`) for an alphanumeric key pressed. + **/ var which(default,null) : Int; var rangeParent(default,null) : Node; var rangeOffset(default,null) : Int; + + /** + Is a `Boolean` indicating whether the bubbling of the event has been canceled or not. + **/ var cancelBubble : Bool; + + /** + Returns a `Boolean` indicating whether the event produced a key character or not. + **/ var isChar(default,null) : Bool; /** @throws DOMError */ function new( type : String, ?eventInitDict : UIEventInit ) : Void; + + /** + Initializes a `UIEvent` object. If the event has already being dispatched, this method does nothing. + **/ function initUIEvent( aType : String, aCanBubble : Bool, aCancelable : Bool, aView : Window, aDetail : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/UIEventInit.hx b/std/js/html/UIEventInit.hx index c0d1f875..ed92a27f 100644 --- a/std/js/html/UIEventInit.hx +++ b/std/js/html/UIEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/UIEvent.webidl line 41:0. Do not edit! +// This file is generated from mozilla\UIEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/UListElement.hx b/std/js/html/UListElement.hx index d8859f6e..4fde9929 100644 --- a/std/js/html/UListElement.hx +++ b/std/js/html/UListElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLUListElement.webidl line 16:0. Do not edit! +// This file is generated from mozilla\HTMLUListElement.webidl. Do not edit! package js.html; +/** + The `HTMLUListElement` interface provides special properties (beyond those defined on the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating unordered list elements. + + Documentation [HTMLUListElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLUListElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLUListElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLUListElement") extern class UListElement extends Element { + + /** + Is a `Boolean` indicating that spacing between list items should be reduced. This property reflects the `compact` attribute only, it doesn't consider the `line-height` CSS property used for that behavior in modern pages. + **/ var compact : Bool; + + /** + Is a `DOMString` value reflecting the `type` and defining the kind of marker to be used to display. The values are browser dependent and have never been standardized. + **/ var type : String; } \ No newline at end of file diff --git a/std/js/html/URL.hx b/std/js/html/URL.hx index e14a62d4..4e08be4a 100644 --- a/std/js/html/URL.hx +++ b/std/js/html/URL.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/URL.webidl line 19:0. Do not edit! +// This file is generated from mozilla\URL.webidl. Do not edit! package js.html; +/** + The `URL` interface represent an object providing static methods used for creating object URLs. + + Documentation [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/URL$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("URL") extern class URL { @@ -31,21 +38,70 @@ extern class URL @:overload( function( blob : Blob, ?options : ObjectURLOptions ) : String {} ) @:overload( function( stream : MediaStream, ?options : ObjectURLOptions ) : String {} ) static function createObjectURL( source : MediaSource, ?options : ObjectURLOptions ) : String; + /** @throws DOMError */ static function revokeObjectURL( url : String ) : Void; + + /** + Is a `DOMString` containing the whole URL. + **/ var href : String; + + /** + Returns a `DOMString` containing the origin of the URL, that is its scheme, its domain and its port. + **/ var origin(default,null) : String; + + /** + Is a `DOMString` containing the protocol scheme of the URL, including the final `':'`. + **/ var protocol : String; + + /** + Is a `DOMString` containing the username specified before the domain name. + **/ var username : String; + + /** + Is a `DOMString` containing the password specified before the domain name. + **/ var password : String; + + /** + Is a `DOMString` containing the host, that is the hostname, a `':'`, and the port of the URL. + **/ var host : String; + + /** + Is a `DOMString` containing the domain of the URL. + **/ var hostname : String; + + /** + Is a `DOMString` containing the port number of the URL. + **/ var port : String; + + /** + Is a `DOMString` containing an initial `'/'` followed by the path of the URL. + **/ var pathname : String; + + /** + Is a `DOMString` containing a `'?'` followed by the parameters of the URL. + **/ var search : String; + + /** + Returns a `URLSearchParams` object allowing to access the GET query arguments contained in the URL. + **/ + var searchParams(default,null) : URLSearchParams; + + /** + Is a `DOMString` containing a `'#'` followed by the fragment identifier of the URL. + **/ var hash : String; - var searchParams : URLSearchParams; /** @throws DOMError */ @:overload( function( url : String, base : URL ) : Void {} ) - function new( url : String, ?base : String = "about:blank" ) : Void; + function new( url : String, ?base : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/URLSearchParams.hx b/std/js/html/URLSearchParams.hx index e2fcca26..066fa2ab 100644 --- a/std/js/html/URLSearchParams.hx +++ b/std/js/html/URLSearchParams.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,21 +20,68 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/URLSearchParams.webidl line 19:0. Do not edit! +// This file is generated from mozilla\URLSearchParams.webidl. Do not edit! package js.html; +/** + The `URLSearchParams` interface defines utility methods to work with the query string of a URL. + + Documentation [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("URLSearchParams") extern class URLSearchParams { /** @throws DOMError */ @:overload( function( ?init : String = "" ) : Void {} ) function new( init : URLSearchParams ) : Void; + + /** + Appends a specified key/value pair as a new search parameter. + **/ function append( name : String, value : String ) : Void; @:native("delete") function delete_( name : String ) : Void; + + /** + Returns the first value associated to the given search parameter. + **/ function get( name : String ) : String; + + /** + Returns all the values association with a given search parameter. + **/ function getAll( name : String ) : Array; + + /** + Returns a `Boolean` indicating if such a search parameter exists. + **/ function has( name : String ) : Bool; + + /** + Sets the value associated to a given search parameter to the given value. If there were several values, delete the others. + **/ function set( name : String, value : String ) : Void; + /** @throws DOMError */ + + /** + Returns an `Iteration_protocols` allowing to go through all key/value pairs contained in this object. + **/ + function entries() : URLSearchParamsIterator; + /** @throws DOMError */ + + /** + Returns an `Iteration_protocols` allowing to go through all keys of the key/value pairs contained in this object. + **/ + function keys() : URLSearchParamsIterator; + /** @throws DOMError */ + + /** + Returns an `Iteration_protocols` allowing to go through all values of the key/value pairs contained in this object. + **/ + function values() : URLSearchParamsIterator; + /** @throws DOMError */ + function forEach( callback : Dynamic, ?thisArg : Dynamic ) : Void; } \ No newline at end of file diff --git a/std/js/html/DOMSettableTokenList.hx b/std/js/html/URLSearchParamsIterator.hx similarity index 81% rename from std/js/html/DOMSettableTokenList.hx rename to std/js/html/URLSearchParamsIterator.hx index 032b371a..c57d93f7 100644 --- a/std/js/html/DOMSettableTokenList.hx +++ b/std/js/html/URLSearchParamsIterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DOMSettableTokenList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\URLSearchParams.webidl. Do not edit! package js.html; -@:native("DOMSettableTokenList") -extern class DOMSettableTokenList extends DOMTokenList +@:native("URLSearchParamsIterator") +extern class URLSearchParamsIterator { - var value : String; - + /** @throws DOMError */ + function next() : Dynamic; } \ No newline at end of file diff --git a/std/js/html/Uint16Array.hx b/std/js/html/Uint16Array.hx index c06cb2a2..0530f77e 100644 --- a/std/js/html/Uint16Array.hx +++ b/std/js/html/Uint16Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl line 119:0. Do not edit! +// This file is generated from typedarray.webidl. Do not edit! package js.html; @@ -36,9 +36,7 @@ extern class Uint16Array extends ArrayBufferView implements ArrayAccess @:overload( function( array : Uint16Array ) : Void {} ) @:overload( function( array : Array ) : Void {} ) function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; - function get( index : Int ) : Int; - @:overload( function( index : Int, value : Int ) : Void {} ) @:overload( function( array : Uint16Array, ?offset : Int ) : Void {} ) function set( array : Array, ?offset : Int ) : Void; - function subarray( start : Int, end : Int ) : Uint16Array; + function subarray( start : Int, ?end : Int ) : Uint16Array; } \ No newline at end of file diff --git a/std/js/html/Uint32Array.hx b/std/js/html/Uint32Array.hx index 2ecb5273..4c32bf8d 100644 --- a/std/js/html/Uint32Array.hx +++ b/std/js/html/Uint32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl line 159:0. Do not edit! +// This file is generated from typedarray.webidl. Do not edit! package js.html; @@ -36,9 +36,7 @@ extern class Uint32Array extends ArrayBufferView implements ArrayAccess @:overload( function( array : Uint32Array ) : Void {} ) @:overload( function( array : Array ) : Void {} ) function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; - function get( index : Int ) : Int; - @:overload( function( index : Int, value : Int ) : Void {} ) @:overload( function( array : Uint32Array, ?offset : Int ) : Void {} ) function set( array : Array, ?offset : Int ) : Void; - function subarray( start : Int, end : Int ) : Uint32Array; + function subarray( start : Int, ?end : Int ) : Uint32Array; } \ No newline at end of file diff --git a/std/js/html/Uint8Array.hx b/std/js/html/Uint8Array.hx index 3ab051d1..9e572bfb 100644 --- a/std/js/html/Uint8Array.hx +++ b/std/js/html/Uint8Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl line 59:0. Do not edit! +// This file is generated from typedarray.webidl. Do not edit! package js.html; +// Explicitly include the compatibility class +import js.html.compat.Uint8Array; + @:native("Uint8Array") extern class Uint8Array extends ArrayBufferView implements ArrayAccess { @@ -36,9 +39,7 @@ extern class Uint8Array extends ArrayBufferView implements ArrayAccess @:overload( function( array : Uint8Array ) : Void {} ) @:overload( function( array : Array ) : Void {} ) function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; - function get( index : Int ) : Int; - @:overload( function( index : Int, value : Int ) : Void {} ) @:overload( function( array : Uint8Array, ?offset : Int ) : Void {} ) function set( array : Array, ?offset : Int ) : Void; - function subarray( start : Int, end : Int ) : Uint8Array; + function subarray( start : Int, ?end : Int ) : Uint8Array; } \ No newline at end of file diff --git a/std/js/html/Uint8ClampedArray.hx b/std/js/html/Uint8ClampedArray.hx index 33c43e2f..6c7d9813 100644 --- a/std/js/html/Uint8ClampedArray.hx +++ b/std/js/html/Uint8ClampedArray.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from typedarray.webidl line 79:0. Do not edit! +// This file is generated from typedarray.webidl. Do not edit! package js.html; @@ -36,9 +36,7 @@ extern class Uint8ClampedArray extends ArrayBufferView implements ArrayAccess ) : Void {} ) function new( buffer : ArrayBuffer, ?byteOffset : Int, ?length : Int ) : Void; - function get( index : Int ) : Int; - @:overload( function( index : Int, value : Int ) : Void {} ) @:overload( function( array : Uint8ClampedArray, ?offset : Int ) : Void {} ) function set( array : Array, ?offset : Int ) : Void; - function subarray( start : Int, end : Int ) : Uint8ClampedArray; + function subarray( start : Int, ?end : Int ) : Uint8ClampedArray; } \ No newline at end of file diff --git a/std/js/html/UncaughtRejectionObserver.hx b/std/js/html/UncaughtRejectionObserver.hx new file mode 100644 index 00000000..0279803b --- /dev/null +++ b/std/js/html/UncaughtRejectionObserver.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\PromiseDebugging.webidl. Do not edit! + +package js.html; + +@:native("UncaughtRejectionObserver") +extern class UncaughtRejectionObserver +{ + function onLeftUncaught( p : Promise ) : Void; + function onConsumed( p : Promise ) : Void; +} \ No newline at end of file diff --git a/std/js/html/UnknownElement.hx b/std/js/html/UnknownElement.hx index 4545930e..46e0e178 100644 --- a/std/js/html/UnknownElement.hx +++ b/std/js/html/UnknownElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLElement.webidl line 117:0. Do not edit! +// This file is generated from mozilla\HTMLElement.webidl. Do not edit! package js.html; +/** + The `HTMLUnknownElement` interface represents an invalid HTML element and derives from the `HTMLElement` interface, but without implementing any additional properties or methods. + + Documentation [HTMLUnknownElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLUnknownElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLUnknownElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLUnknownElement") extern class UnknownElement extends Element { diff --git a/std/js/html/VTTCue.hx b/std/js/html/VTTCue.hx index 59bae7fc..5c57b65f 100644 --- a/std/js/html/VTTCue.hx +++ b/std/js/html/VTTCue.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,18 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/VTTCue.webidl line 28:0. Do not edit! +// This file is generated from mozilla\VTTCue.webidl. Do not edit! package js.html; @:native("VTTCue") -extern class VTTCue extends EventTarget +extern class VTTCue extends TextTrackCue { - var track(default,null) : TextTrack; - var id : String; - var startTime : Float; - var endTime : Float; - var pauseOnExit : Bool; var region : VTTRegion; var vertical : DirectionSetting; var snapToLines : Bool; @@ -42,8 +37,6 @@ extern class VTTCue extends EventTarget var size : Int; var align : AlignSetting; var text : String; - var onenter : haxe.Constraints.Function; - var onexit : haxe.Constraints.Function; /** @throws DOMError */ function new( startTime : Float, endTime : Float, text : String ) : Void; diff --git a/std/js/html/VTTRegion.hx b/std/js/html/VTTRegion.hx index d604c5ed..36608832 100644 --- a/std/js/html/VTTRegion.hx +++ b/std/js/html/VTTRegion.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/VTTRegion.webidl line 11:0. Do not edit! +// This file is generated from mozilla\VTTRegion.webidl. Do not edit! package js.html; diff --git a/std/js/html/ValidityState.hx b/std/js/html/ValidityState.hx index 493fd231..96e6afb4 100644 --- a/std/js/html/ValidityState.hx +++ b/std/js/html/ValidityState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,22 +20,69 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ValidityState.webidl line 13:0. Do not edit! +// This file is generated from mozilla\ValidityState.webidl. Do not edit! package js.html; +/** + The `ValidityState` interface represents the validity states that an element can be in, with respect to constraint validation. Together, they help explain why an element's value fails to validate, if it's not valid. + + Documentation [ValidityState](https://developer.mozilla.org/en-US/docs/Web/API/ValidityState) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ValidityState$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("ValidityState") extern class ValidityState { + + /** + Is a `Boolean` indicating the element has a `required` attribute, but no value. + **/ var valueMissing(default,null) : Bool; + + /** + Is a `Boolean` indicating the value is not in the required syntax (when `type` is `email` or `url`). + **/ var typeMismatch(default,null) : Bool; + + /** + Is a `Boolean` indicating the value does not match the specified `pattern`. + **/ var patternMismatch(default,null) : Bool; + + /** + Is a `Boolean` indicating the value exceeds the specified `maxlength` for `HTMLInputElement` or `HTMLTextAreaElement` objects. Note: This will never be `true` in Gecko, because elements' values are prevented from being longer than `maxlength`. + **/ var tooLong(default,null) : Bool; + + /** + Is a `Boolean` indicating the value is less than the minimum specified by the `min` attribute. + **/ var rangeUnderflow(default,null) : Bool; + + /** + Is a `Boolean` indicating the value is greater than the maximum specified by the `max` attribute. + **/ var rangeOverflow(default,null) : Bool; + + /** + Is a `Boolean` indicating the value does not fit the rules determined by the `step` attribute (that is, it's not evenly divisible by the step value). + **/ var stepMismatch(default,null) : Bool; + + /** + Is a `Boolean` indicating the user has provided input that the browser is unable to convert. + **/ var badInput(default,null) : Bool; + + /** + Is a `Boolean` indicating the element's custom validity message has been set to a non-empty string by calling the element's `setCustomValidity()` method. + **/ var customError(default,null) : Bool; + + /** + Is a `Boolean` indicating the element meets all constraint validations, and is therefore considered to be valid. + **/ var valid(default,null) : Bool; } \ No newline at end of file diff --git a/std/js/html/VideoElement.hx b/std/js/html/VideoElement.hx index fad2479c..5e97108b 100644 --- a/std/js/html/VideoElement.hx +++ b/std/js/html/VideoElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,18 +20,49 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/HTMLVideoElement.webidl line 14:0. Do not edit! +// This file is generated from mozilla\HTMLVideoElement.webidl. Do not edit! package js.html; +/** + The `HTMLVideoElement` interface provides special properties and methods for manipulating video objects. It also inherits properties and methods of `HTMLMediaElement` and `HTMLElement`. + + Documentation [HTMLVideoElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("HTMLVideoElement") extern class VideoElement extends MediaElement { + + /** + Is a `DOMString` that reflects the `width` HTML attribute, which specifies the width of the display area, in CSS pixels. + **/ var width : Int; + + /** + Is a `DOMString` that reflects the `height` HTML attribute, which specifies the height of the display area, in CSS pixels. + **/ var height : Int; + + /** + Returns an `unsigned long` containing the intrinsic width of the resource in CSS pixels, taking into account the dimensions, aspect ratio, clean aperture, resolution, and so forth, as defined for the format used by the resource. If the element's ready state is `HAVE_NOTHING`, the value is `0`. + **/ var videoWidth(default,null) : Int; + + /** + Returns an `unsigned long` containing the intrinsic height of the resource in CSS pixels, taking into account the dimensions, aspect ratio, clean aperture, resolution, and so forth, as defined for the format used by the resource. If the element's ready state is `HAVE_NOTHING`, the value is `0`. + **/ var videoHeight(default,null) : Int; + + /** + Is a `DOMString` that reflects the `poster` HTML attribute, which specifies an image to show while no video data is available. + **/ var poster : String; + + /** + Returns a `VideoPlaybackQuality` objects that contains the current playback metrics. + **/ function getVideoPlaybackQuality() : VideoPlaybackQuality; } \ No newline at end of file diff --git a/std/js/html/VideoPlaybackQuality.hx b/std/js/html/VideoPlaybackQuality.hx index 6bcf19de..22cd2e2b 100644 --- a/std/js/html/VideoPlaybackQuality.hx +++ b/std/js/html/VideoPlaybackQuality.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,39 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/VideoPlaybackQuality.webidl line 14:0. Do not edit! +// This file is generated from mozilla\VideoPlaybackQuality.webidl. Do not edit! package js.html; +/** + The `VideoPlaybackQuality` interface represents the set of metrics describing the playback quality of a video. + + Documentation [VideoPlaybackQuality](https://developer.mozilla.org/en-US/docs/Web/API/VideoPlaybackQuality) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/VideoPlaybackQuality$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("VideoPlaybackQuality") extern class VideoPlaybackQuality { + + /** + A `DOMHighResTimeStamp` containing the time in miliseconds since the start of the navigation and the creation of the object. + **/ var creationTime(default,null) : Float; + + /** + An `unsigned long` giving the number of video frames created and dropped since the creation of the associated `HTMLVideoElement`. + **/ var totalVideoFrames(default,null) : Int; + + /** + An `unsigned long` giving the number of video frames dropped since the creation of the associated `HTMLVideoElement`. + **/ var droppedVideoFrames(default,null) : Int; + + /** + An `unsigned long` giving the number of video frames corrupted since the creation of the associated `HTMLVideoElement`. A corrupted frame may be created or dropped. + **/ var corruptedVideoFrames(default,null) : Int; } \ No newline at end of file diff --git a/std/js/html/VideoStreamTrack.hx b/std/js/html/VideoStreamTrack.hx index 7384de45..631f4998 100644 --- a/std/js/html/VideoStreamTrack.hx +++ b/std/js/html/VideoStreamTrack.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/VideoStreamTrack.webidl line 14:0. Do not edit! +// This file is generated from mozilla\VideoStreamTrack.webidl. Do not edit! package js.html; diff --git a/std/js/html/VideoTrack.hx b/std/js/html/VideoTrack.hx index 163fb8a7..d9da4fd1 100644 --- a/std/js/html/VideoTrack.hx +++ b/std/js/html/VideoTrack.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/VideoTrack.webidl line 11:0. Do not edit! +// This file is generated from mozilla\VideoTrack.webidl. Do not edit! package js.html; diff --git a/std/js/html/VideoTrackList.hx b/std/js/html/VideoTrackList.hx index 6f98780f..1a90c9b5 100644 --- a/std/js/html/VideoTrackList.hx +++ b/std/js/html/VideoTrackList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/VideoTrackList.webidl line 11:0. Do not edit! +// This file is generated from mozilla\VideoTrackList.webidl. Do not edit! package js.html; diff --git a/std/js/html/VisibilityState.hx b/std/js/html/VisibilityState.hx index 89e0314c..43a94c56 100644 --- a/std/js/html/VisibilityState.hx +++ b/std/js/html/VisibilityState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Document.webidl line 14:0. Do not edit! +// This file is generated from mozilla\Document.webidl. Do not edit! package js.html; diff --git a/std/js/html/WebSocket.hx b/std/js/html/WebSocket.hx index 2fa113ed..8385f278 100644 --- a/std/js/html/WebSocket.hx +++ b/std/js/html/WebSocket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebSocket.webidl line 20:0. Do not edit! +// This file is generated from mozilla\WebSocket.webidl. Do not edit! package js.html; +/** + The `WebSocket` object provides the API for creating and managing a WebSocket connection to a server, as well as for sending and receiving data on the connection. + + Documentation [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WebSocket") extern class WebSocket extends EventTarget { diff --git a/std/js/html/WheelEvent.hx b/std/js/html/WheelEvent.hx index 1c8e0b38..3fc512cb 100644 --- a/std/js/html/WheelEvent.hx +++ b/std/js/html/WheelEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WheelEvent.webidl line 14:0. Do not edit! +// This file is generated from mozilla\WheelEvent.webidl. Do not edit! package js.html; +/** + The `WheelEvent` interface represents events that occur due to the user moving a mouse wheel or similar input device. + + Documentation [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WheelEvent") extern class WheelEvent extends MouseEvent { @@ -31,9 +38,50 @@ extern class WheelEvent extends MouseEvent static inline var DOM_DELTA_LINE : Int = 1; static inline var DOM_DELTA_PAGE : Int = 2; + + /** + Returns a `double` representing the horizontal scroll amount. + **/ var deltaX(default,null) : Float; + + /** + Returns a `double` representing the vertical scroll amount. + **/ var deltaY(default,null) : Float; + + /** + Returns a `double` representing the scroll amount for the z-axis. + **/ var deltaZ(default,null) : Float; + + /** + Returns an unsigned long representing the unit of the delta values scroll amount. Permitted values are: + + + + + + + + + + + + + + + + + + + + + + + +
ConstantValueDescription
DOM_DELTA_PIXEL0x00The delta values are specified in pixels.
DOM_DELTA_LINE0x01The delta values are specified in lines.
DOM_DELTA_PAGE0x02The delta values are specified in pages.
+ + **/ var deltaMode(default,null) : Int; /** @throws DOMError */ diff --git a/std/js/html/WheelEventInit.hx b/std/js/html/WheelEventInit.hx index ba762136..222763df 100644 --- a/std/js/html/WheelEventInit.hx +++ b/std/js/html/WheelEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WheelEvent.webidl line 27:0. Do not edit! +// This file is generated from mozilla\WheelEvent.webidl. Do not edit! package js.html; diff --git a/std/js/html/Window.hx b/std/js/html/Window.hx index a3724d42..d6708192 100644 --- a/std/js/html/Window.hx +++ b/std/js/html/Window.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,62 +20,225 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Window.webidl line 28:11. Do not edit! +// This file is generated from mozilla\Window.webidl. Do not edit! package js.html; +/** + The `window` object represents a window containing a DOM document; the `document` property points to the DOM document loaded in that window. + + Documentation [Window](https://developer.mozilla.org/en-US/docs/Web/API/Window) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Window$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Window") extern class Window extends EventTarget { + + /** + Returns a reference to the current window. + **/ var window(default,null) : Window; + + /** + Returns an object reference to the window object itself. + **/ var self(default,null) : Window; + + /** + Returns a reference to the document that the window contains. + **/ var document(default,null) : HTMLDocument; + + /** + Gets/sets the name of the window. + **/ var name : String; + + /** + Gets/sets the location, or current URL, of the window object. + **/ var location(default,null) : Location; + + /** + Returns a reference to the history object. + **/ var history(default,null) : History; + + /** + Returns the locationbar object, whose visibility can be toggled in the window. + **/ var locationbar(default,null) : BarProp; + + /** + Returns the menubar object, whose visibility can be toggled in the window. + **/ var menubar(default,null) : BarProp; + + /** + Returns the personalbar object, whose visibility can be toggled in the window. + **/ var personalbar(default,null) : BarProp; + + /** + Returns the scrollbars object, whose visibility can be toggled in the window. + **/ var scrollbars(default,null) : BarProp; + + /** + Returns the statusbar object, whose visibility can be toggled in the window. + **/ var statusbar(default,null) : BarProp; + + /** + Returns the toolbar object, whose visibility can be toggled in the window. + **/ var toolbar(default,null) : BarProp; + + /** + Gets/sets the text in the statusbar at the bottom of the browser. + **/ var status : String; + + /** + This property indicates whether the current window is closed or not. + **/ var closed(default,null) : Bool; + + /** + Returns an array of the subframes in the current window. + **/ var frames(default,null) : Window; + + /** + Returns the number of frames in the window. See also `window.frames`. + **/ var length(default,null) : Int; + + /** + Returns a reference to the topmost window in the window hierarchy. This property is read only. + **/ var top(default,null) : Window; + + /** + Returns a reference to the window that opened this current window. + **/ var opener : Dynamic; + + /** + Returns a reference to the parent of the current window or subframe. + **/ var parent(default,null) : Window; + + /** + Returns the element in which the window is embedded, or null if the window is not embedded. + **/ var frameElement(default,null) : Element; + + /** + Returns a reference to the navigator object. + **/ var navigator(default,null) : Navigator; - var applicationCache(default,null) : ApplicationCache; + + /** + Returns the orientation in degrees (in 90 degree increments) of the viewport relative to the device's natural orientation. + **/ var orientation(default,null) : Int; var onorientationchange : haxe.Constraints.Function; + + /** + Returns a reference to the screen object associated with the window. + **/ var screen(default,null) : Screen; - var innerWidth : Int; - var innerHeight : Int; + + /** + Gets the width of the content area of the browser window including, if rendered, the vertical scrollbar. + **/ + var innerWidth : Dynamic; + + /** + Gets the height of the content area of the browser window including, if rendered, the horizontal scrollbar. + **/ + var innerHeight : Dynamic; + + /** + Returns the number of pixels that the document has already been scrolled horizontally. + **/ var scrollX(default,null) : Int; var pageXOffset(default,null) : Int; + + /** + Returns the number of pixels that the document has already been scrolled vertically. + **/ var scrollY(default,null) : Int; var pageYOffset(default,null) : Int; - var screenX : Int; - var screenY : Int; - var outerWidth : Int; - var outerHeight : Int; + + /** + Returns the horizontal distance of the left border of the user's browser from the left side of the screen. + **/ + var screenX : Dynamic; + + /** + Returns the vertical distance of the top border of the user's browser from the top side of the screen. + **/ + var screenY : Dynamic; + + /** + Gets the width of the outside of the browser window. + **/ + var outerWidth : Dynamic; + + /** + Gets the height of the outside of the browser window. + **/ + var outerHeight : Dynamic; + + /** + Provides a hosting area for performance related attributes. + **/ var performance(default,null) : Performance; - var crypto(default,null) : Dynamic/*MISSING nsIDOMCrypto*/; + + /** + Returns the ratio between physical pixels and device independent pixels in the current display. + **/ var devicePixelRatio(default,null) : Float; + + /** + The maximum offset that the window can be scrolled to horizontally, that is the document width minus the viewport width. + **/ var scrollMaxX(default,null) : Int; + + /** + The maximum offset that the window can be scrolled to vertically (i.e., the document height minus the viewport height). + **/ var scrollMaxY(default,null) : Int; + + /** + This property indicates whether the window is displayed in full screen or not. + **/ var fullScreen : Bool; var onwheel : haxe.Constraints.Function; var ondevicemotion : haxe.Constraints.Function; var ondeviceorientation : haxe.Constraints.Function; + var onabsolutedeviceorientation : haxe.Constraints.Function; var ondeviceproximity : haxe.Constraints.Function; var onuserproximity : haxe.Constraints.Function; var ondevicelight : haxe.Constraints.Function; + + /** + Returns a reference to the content element in the current window. The obsolete variant with underscore is no longer available from Web content. + **/ var content(default,null) : Dynamic; + + /** + Returns a reference to the console object which provides access to the browser's debugging console. + **/ var console(default,null) : Console; + + /** + Returns the browser crypto object. + **/ + var crypto(default,null) : Crypto; var onabort : haxe.Constraints.Function; var onblur : haxe.Constraints.Function; var onfocus : haxe.Constraints.Function; @@ -117,6 +280,7 @@ extern class Window extends EventTarget var onprogress : haxe.Constraints.Function; var onratechange : haxe.Constraints.Function; var onreset : haxe.Constraints.Function; + var onresize : haxe.Constraints.Function; var onscroll : haxe.Constraints.Function; var onseeked : haxe.Constraints.Function; var onseeking : haxe.Constraints.Function; @@ -138,10 +302,16 @@ extern class Window extends EventTarget var onpointerleave : haxe.Constraints.Function; var ongotpointercapture : haxe.Constraints.Function; var onlostpointercapture : haxe.Constraints.Function; + var onfullscreenchange : haxe.Constraints.Function; + var onfullscreenerror : haxe.Constraints.Function; var onpointerlockchange : haxe.Constraints.Function; var onpointerlockerror : haxe.Constraints.Function; var indexedDB(default,null) : js.html.idb.Factory; var onerror : haxe.extern.EitherType -> String -> Int -> Int -> Dynamic -> Bool; + + /** + Returns a `SpeechSynthesis` object, which is the entry point into using Web Speech API speech synthesis functionality. + **/ var speechSynthesis(default,null) : SpeechSynthesis; var ontouchstart : haxe.Constraints.Function; var ontouchend : haxe.Constraints.Function; @@ -158,81 +328,212 @@ extern class Window extends EventTarget var onpagehide : haxe.Constraints.Function; var onpageshow : haxe.Constraints.Function; var onpopstate : haxe.Constraints.Function; - var onresize : haxe.Constraints.Function; + var onstorage : haxe.Constraints.Function; var onunload : haxe.Constraints.Function; + + /** + Returns a reference to the local storage object used to store data that may only be accessed by the origin that created it. + **/ var localStorage(default,null) : Storage; + + /** + Returns a storage object for storing data within a single page session. + **/ var sessionStorage(default,null) : Storage; /** @throws DOMError */ + + /** + Closes the current window. + **/ function close() : Void; /** @throws DOMError */ + + /** + This method stops window loading. + **/ function stop() : Void; /** @throws DOMError */ + + /** + Sets focus on the current window. + **/ function focus() : Void; /** @throws DOMError */ + + /** + Sets focus away from the window. + **/ function blur() : Void; /** @throws DOMError */ + + /** + Opens a new window. + **/ function open( ?url : String = "", ?target : String = "", ?features : String = "" ) : Window; /** @throws DOMError */ @:overload( function() : Void {} ) + + /** + Displays an alert dialog. + **/ function alert( message : String ) : Void; /** @throws DOMError */ + + /** + Displays a dialog with a message that the user needs to respond to. + **/ function confirm( ?message : String = "" ) : Bool; /** @throws DOMError */ + + /** + Returns the text entered by the user in a prompt dialog. + **/ function prompt( ?message : String = "", ?default_ : String = "" ) : String; /** @throws DOMError */ + + /** + Opens the Print Dialog to print the current document. + **/ function print() : Void; /** @throws DOMError */ + + /** + Provides a secure means for one window to send a string of data to another window, which need not be within the same domain as the first. + **/ function postMessage( message : Dynamic, targetOrigin : String, ?transfer : Array ) : Void; + + /** + Registers the window to capture all events of the specified type. + **/ function captureEvents() : Void; + + /** + Releases the window from trapping events of a specific type. + **/ function releaseEvents() : Void; /** @throws DOMError */ + + /** + Returns the selection object representing the selected item(s). + **/ function getSelection() : Selection; /** @throws DOMError */ + + /** + Gets computed style for the specified element. Computed style indicates the computed values of all CSS properties of the element. + **/ function getComputedStyle( elt : Element, ?pseudoElt : String = "" ) : CSSStyleDeclaration; /** @throws DOMError */ + + /** + Returns a `MediaQueryList` object representing the specified media query string. + **/ function matchMedia( query : String ) : MediaQueryList; /** @throws DOMError */ + + /** + Moves the window to the specified coordinates. + **/ function moveTo( x : Int, y : Int ) : Void; /** @throws DOMError */ + + /** + Moves the current window by a specified amount. + **/ function moveBy( x : Int, y : Int ) : Void; /** @throws DOMError */ + + /** + Dynamically resizes window. + **/ function resizeTo( x : Int, y : Int ) : Void; /** @throws DOMError */ + + /** + Resizes the current window by a certain amount. + **/ function resizeBy( x : Int, y : Int ) : Void; @:overload( function( x : Float, y : Float ) : Void {} ) + + /** + Scrolls the window to a particular place in the document. + **/ function scroll( ?options : ScrollToOptions ) : Void; @:overload( function( x : Float, y : Float ) : Void {} ) + + /** + Scrolls to a particular set of coordinates in the document. + **/ function scrollTo( ?options : ScrollToOptions ) : Void; @:overload( function( x : Float, y : Float ) : Void {} ) + + /** + Scrolls the document in the window by the given amount. + **/ function scrollBy( ?options : ScrollToOptions ) : Void; /** @throws DOMError */ function requestAnimationFrame( callback : Float -> Void ) : Int; /** @throws DOMError */ function cancelAnimationFrame( handle : Int ) : Void; /** @throws DOMError */ + + /** + Gets default computed style for the specified element, ignoring author stylesheets. + **/ function getDefaultComputedStyle( elt : Element, ?pseudoElt : String = "" ) : CSSStyleDeclaration; + + /** + Scrolls the document by the given number of lines. + **/ function scrollByLines( numLines : Int, ?options : ScrollOptions ) : Void; + + /** + Scrolls the current document by the specified number of pages. + **/ function scrollByPages( numPages : Int, ?options : ScrollOptions ) : Void; /** @throws DOMError */ + + /** + Sizes the window according to its content. + **/ function sizeToContent() : Void; + + /** + Updates the state of commands of the current chrome window (UI). + **/ function updateCommands( action : String, ?sel : Selection, ?reason : Int = 0 ) : Void; /** @throws DOMError */ + + /** + Searches for a given string in a window. + **/ function find( ?str : String = "", ?caseSensitive : Bool = false, ?backwards : Bool = false, ?wrapAround : Bool = false, ?wholeWord : Bool = false, ?searchInFrames : Bool = false, ?showDialog : Bool = false ) : Bool; + + /** + Writes a message to the console. + **/ function dump( str : String ) : Void; + + /** + Toggles a user's ability to resize a window. + **/ function setResizable( resizable : Bool ) : Void; /** @throws DOMError */ + function fetch( input : haxe.extern.EitherType, ?init : RequestInit ) : Promise; + /** @throws DOMError */ + @:overload( function( aImage : haxe.extern.EitherType>>>>> ) : Promise {} ) + function createImageBitmap( aImage : haxe.extern.EitherType>>>>>, aSx : Int, aSy : Int, aSw : Int, aSh : Int ) : Promise; + /** @throws DOMError */ function btoa( btoa : String ) : String; /** @throws DOMError */ function atob( atob : String ) : String; /** @throws DOMError */ @:overload( function( handler : haxe.Constraints.Function, ?timeout : Int = 0, arguments : haxe.extern.Rest ) : Int {} ) function setTimeout( handler : String, ?timeout : Int = 0, unused : haxe.extern.Rest ) : Int; - /** @throws DOMError */ function clearTimeout( ?handle : Int = 0 ) : Void; /** @throws DOMError */ @:overload( function( handler : haxe.Constraints.Function, ?timeout : Int, arguments : haxe.extern.Rest ) : Int {} ) function setInterval( handler : String, ?timeout : Int, unused : haxe.extern.Rest ) : Int; - /** @throws DOMError */ function clearInterval( ?handle : Int = 0 ) : Void; } \ No newline at end of file diff --git a/std/js/html/WindowClient.hx b/std/js/html/WindowClient.hx new file mode 100644 index 00000000..f1921835 --- /dev/null +++ b/std/js/html/WindowClient.hx @@ -0,0 +1,54 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\Client.webidl. Do not edit! + +package js.html; + +/** + The `WindowClient` interface of the ServiceWorker API represents the scope of a service worker client that is a document in a browser context, controlled by an active worker. The service worker client independently selects and uses a service worker for its own loading and sub-resources. + + Documentation [WindowClient](https://developer.mozilla.org/en-US/docs/Web/API/WindowClient) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WindowClient$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WindowClient") +extern class WindowClient extends Client +{ + + /** + Indicates the visibility of the current client. This value can be one of `hidden`, `visible`, `prerender`, or `unloaded`. + **/ + var visibilityState(default,null) : VisibilityState; + + /** + A boolean that indicates whether the current client has focus. + **/ + var focused(default,null) : Bool; + + /** @throws DOMError */ + + /** + Gives user input focus to the current client.  + **/ + function focus() : Promise; +} \ No newline at end of file diff --git a/std/js/html/Worker.hx b/std/js/html/Worker.hx index 70d6b9f5..708e975a 100644 --- a/std/js/html/Worker.hx +++ b/std/js/html/Worker.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,19 +20,38 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/Worker.webidl line 18:0. Do not edit! +// This file is generated from mozilla\Worker.webidl. Do not edit! package js.html; +/** + The `Worker` interface of the Web Workers API represents a background task that can be easily created and can send messages back to its creator. Creating a worker is as simple as calling the `Worker()` constructor and specifying a script to be run in the worker thread. + + Documentation [Worker](https://developer.mozilla.org/en-US/docs/Web/API/Worker) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/Worker$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("Worker") extern class Worker extends EventTarget { + + /** + An `EventListener` called whenever a `MessageEvent` of type `message` bubbles through the worker — i.e. when a message is sent to the parent document from the worker via `DedicatedWorkerGlobalScope.postMessage`. The message is stored in the event's `MessageEvent.data` property. + **/ var onmessage : haxe.Constraints.Function; var onerror : haxe.Constraints.Function; /** @throws DOMError */ function new( scriptURL : String ) : Void; + + /** + Immediately terminates the worker. This does not offer the worker an opportunity to finish its operations; it is simply stopped at once. ServiceWorker instances do not support this method. + **/ function terminate() : Void; /** @throws DOMError */ + + /** + Sends a message — which can consist of `any` JavaScript object — to the worker's inner scope. + **/ function postMessage( message : Dynamic, ?transfer : Array ) : Void; } \ No newline at end of file diff --git a/std/js/html/MediaKeys.hx b/std/js/html/WorkerDebuggerGlobalScope.hx similarity index 58% rename from std/js/html/MediaKeys.hx rename to std/js/html/WorkerDebuggerGlobalScope.hx index 0fbb38fb..ed70dca1 100644 --- a/std/js/html/MediaKeys.hx +++ b/std/js/html/WorkerDebuggerGlobalScope.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,25 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaKeys.webidl line 17:0. Do not edit! +// This file is generated from mozilla\WorkerDebuggerGlobalScope.webidl. Do not edit! package js.html; -@:native("MediaKeys") -extern class MediaKeys +@:native("WorkerDebuggerGlobalScope") +extern class WorkerDebuggerGlobalScope extends EventTarget { - var keySystem(default,null) : String; + var global(default,null) : Dynamic; + var onmessage : haxe.Constraints.Function; + var console(default,null) : Console; + function createSandbox( name : String, prototype : Dynamic ) : Dynamic; /** @throws DOMError */ - function createSession( ?sessionType : SessionType = "temporary" ) : MediaKeySession; - function setServerCertificate( serverCertificate : haxe.extern.EitherType ) : Promise; + function loadSubScript( url : String, ?sandbox : Dynamic ) : Void; + function enterEventLoop() : Void; + function leaveEventLoop() : Void; + function postMessage( message : String ) : Void; + /** @throws DOMError */ + function setImmediate( handler : haxe.Constraints.Function ) : Void; + function reportError( message : String ) : Void; + function dump( ?string : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/WorkerGlobalScope.hx b/std/js/html/WorkerGlobalScope.hx index d6db799e..721fb6ea 100644 --- a/std/js/html/WorkerGlobalScope.hx +++ b/std/js/html/WorkerGlobalScope.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,39 +20,99 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WorkerGlobalScope.webidl line 16:0. Do not edit! +// This file is generated from mozilla\WorkerGlobalScope.webidl. Do not edit! package js.html; +/** + The `WorkerGlobalScope` interface of the Web Workers API is an interface representing the scope of any worker. Workers have no browsing context; this scope contains the information usually conveyed by `Window` objects — in this case event handlers, the console or the associated `WorkerNavigator` object. Each `WorkerGlobalScope` has its own event loop. + + Documentation [WorkerGlobalScope](https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WorkerGlobalScope") extern class WorkerGlobalScope extends EventTarget { + + /** + Returns a reference to the `WorkerGlobalScope` itself. Most of the time it is a specific scope like `DedicatedWorkerGlobalScope`,  `SharedWorkerGlobalScope` or `ServiceWorkerGlobalScope`. + **/ var self(default,null) : WorkerGlobalScope; + + /** + Returns the `Console` associated with the worker. + **/ var console(default,null) : Console; + + /** + Returns the `WorkerLocation` associated with the worker. It is a specific location object, mostly a subset of the `Location` for browsing scopes, but adapted to workers. + **/ var location(default,null) : WorkerLocation; + + /** + Is an `EventHandler` representing the code to be called when the `error` event is raised. + **/ var onerror : haxe.extern.EitherType -> String -> Int -> Int -> Dynamic -> Bool; + + /** + Is an `EventHandler` representing the code to be called when the `offline` event is raised. + **/ var onoffline : haxe.Constraints.Function; + + /** + Is an `EventHandler` representing the code to be called when the `online` event is raised. + **/ var ononline : haxe.Constraints.Function; + + /** + Returns the `WorkerNavigator` associated with the worker. It is a specific navigator object, mostly a subset of the `Navigator` for browsing scopes, but adapted to workers. + **/ var navigator(default,null) : WorkerNavigator; + + /** + Is an `EventHandler` representing the code to be called when the `close` event is raised. + **/ var onclose : haxe.Constraints.Function; + + /** + Returns the `Performance` associated with the worker. It is a regular performance object, except that only a subset of its property and methods are available to workers. + **/ var performance(default,null) : Performance; + var indexedDB(default,null) : js.html.idb.Factory; + + /** @throws DOMError */ + /** + Discards any tasks queued in the `WorkerGlobalScope`'s event loop, effectively closing this particular scope. + **/ function close() : Void; /** @throws DOMError */ + + /** + Imports one or more scripts into the worker's scope. You can specify as many as you'd like, separated by commas. For example:` importScripts('foo.js', 'bar.js');` + **/ function importScripts( urls : haxe.extern.Rest ) : Void; + + /** + Allows you to write a message to stdout — i.e. in your terminal. This is the same as Firefox's `window.dump`, but for workers. + **/ function dump( ?str : String ) : Void; /** @throws DOMError */ + function fetch( input : haxe.extern.EitherType, ?init : RequestInit ) : Promise; + /** @throws DOMError */ + @:overload( function( aImage : haxe.extern.EitherType>>>>> ) : Promise {} ) + function createImageBitmap( aImage : haxe.extern.EitherType>>>>>, aSx : Int, aSy : Int, aSw : Int, aSh : Int ) : Promise; + /** @throws DOMError */ function btoa( btoa : String ) : String; /** @throws DOMError */ function atob( atob : String ) : String; /** @throws DOMError */ @:overload( function( handler : haxe.Constraints.Function, ?timeout : Int = 0, arguments : haxe.extern.Rest ) : Int {} ) function setTimeout( handler : String, ?timeout : Int = 0, unused : haxe.extern.Rest ) : Int; - /** @throws DOMError */ function clearTimeout( ?handle : Int = 0 ) : Void; /** @throws DOMError */ @:overload( function( handler : haxe.Constraints.Function, ?timeout : Int, arguments : haxe.extern.Rest ) : Int {} ) function setInterval( handler : String, ?timeout : Int, unused : haxe.extern.Rest ) : Int; - /** @throws DOMError */ function clearInterval( ?handle : Int = 0 ) : Void; } \ No newline at end of file diff --git a/std/js/html/WorkerLocation.hx b/std/js/html/WorkerLocation.hx index 8971a53f..93713951 100644 --- a/std/js/html/WorkerLocation.hx +++ b/std/js/html/WorkerLocation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,22 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WorkerLocation.webidl line 16:0. Do not edit! +// This file is generated from mozilla\WorkerLocation.webidl. Do not edit! package js.html; +/** + The `WorkerLocation` interface defines the absolute location of the script executed by the `Worker`. Such an object is initialized for each worker and is available via the `WorkerGlobalScope.location` property obtained by calling `window.self.location`. + + Documentation [WorkerLocation](https://developer.mozilla.org/en-US/docs/Web/API/WorkerLocation) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WorkerLocation$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WorkerLocation") extern class WorkerLocation { var href(default,null) : String; + var origin(default,null) : String; var protocol(default,null) : String; var host(default,null) : String; var hostname(default,null) : String; @@ -35,6 +43,5 @@ extern class WorkerLocation var pathname(default,null) : String; var search(default,null) : String; var hash(default,null) : String; - var origin(default,null) : String; } \ No newline at end of file diff --git a/std/js/html/WorkerNavigator.hx b/std/js/html/WorkerNavigator.hx index 05127e4a..3e0e277b 100644 --- a/std/js/html/WorkerNavigator.hx +++ b/std/js/html/WorkerNavigator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,21 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WorkerNavigator.webidl line 7:0. Do not edit! +// This file is generated from mozilla\WorkerNavigator.webidl. Do not edit! package js.html; +/** + The `WorkerNavigator` interface represents a subset of the `Navigator` interface allowed to be accessed from a `Worker`. Such an object is initialized for each worker and is available via the `WorkerGlobalScope.navigator` property obtained by calling `window.self.navigator`. + + Documentation [WorkerNavigator](https://developer.mozilla.org/en-US/docs/Web/API/WorkerNavigator) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WorkerNavigator$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WorkerNavigator") extern class WorkerNavigator { + var hardwareConcurrency(default,null) : Int; var appCodeName(default,null) : String; var appName(default,null) : String; var appVersion(default,null) : String; diff --git a/std/js/html/XMLDocument.hx b/std/js/html/XMLDocument.hx index 54eebe80..0662cfc0 100644 --- a/std/js/html/XMLDocument.hx +++ b/std/js/html/XMLDocument.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,26 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/XMLDocument.webidl line 12:0. Do not edit! +// This file is generated from mozilla\XMLDocument.webidl. Do not edit! package js.html; +/** + The XMLDocument interface represent an XML document. It inherits from the generic `Document` and does not add any specific methods or properties to it: nevertheless, several algorithms behave differently with the two types of documents. + + Documentation [XMLDocument](https://developer.mozilla.org/en-US/docs/Web/API/XMLDocument) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/XMLDocument$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("XMLDocument") extern class XMLDocument extends Document { var async : Bool; /** @throws DOMError */ + + /** + Loads an XML document. + **/ function load( url : String ) : Bool; } \ No newline at end of file diff --git a/std/js/html/XMLHttpRequest.hx b/std/js/html/XMLHttpRequest.hx index 826b2d02..87d2870e 100644 --- a/std/js/html/XMLHttpRequest.hx +++ b/std/js/html/XMLHttpRequest.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/XMLHttpRequest.webidl line 58:0. Do not edit! +// This file is generated from mozilla\XMLHttpRequest.webidl. Do not edit! package js.html; +/** + `XMLHttpRequest` is an API that provides client functionality for transferring data between a client and a server. It provides an easy way to retrieve data from a URL without having to do a full page refresh. This enables a Web page to update just a part of the page without disrupting what the user is doing. + + Documentation [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("XMLHttpRequest") extern class XMLHttpRequest extends XMLHttpRequestEventTarget { @@ -42,6 +49,10 @@ extern class XMLHttpRequest extends XMLHttpRequestEventTarget var status(default,null) : Int; var statusText(default,null) : String; var responseType : XMLHttpRequestResponseType; + + /** + Returns an `ArrayBuffer`, `Blob`, `Document`, JavaScript object, or a `DOMString`, depending on the value of `XMLHttpRequest.responseType`. that contains the response entity body. + **/ var response(default,null) : Dynamic; var responseText(default,null) : String; var responseXML(default,null) : HTMLDocument; @@ -51,8 +62,16 @@ extern class XMLHttpRequest extends XMLHttpRequestEventTarget function new( ignored : String ) : Void; /** @throws DOMError */ @:overload( function( method : String, url : String ) : Void {} ) + + /** + Initializes a request. This method is to be used from JavaScript code; to initialize a request from native code, use `openRequest()` instead. + **/ function open( method : String, url : String, async : Bool, ?user : String, ?password : String ) : Void; /** @throws DOMError */ + + /** + Sets the value of an HTTP request header. You must call `setRequestHeader()`after `open()`, but before `send()`. + **/ function setRequestHeader( header : String, value : String ) : Void; /** @throws DOMError */ @:overload( function() : Void {} ) @@ -62,15 +81,33 @@ extern class XMLHttpRequest extends XMLHttpRequestEventTarget @:overload( function( data : HTMLDocument ) : Void {} ) @:overload( function( data : String ) : Void {} ) @:overload( function( data : FormData ) : Void {} ) + + /** + Sends the request. If the request is asynchronous (which is the default), this method returns as soon as the request is sent. + **/ function send( data : Dynamic/*MISSING InputStream*/ ) : Void; /** @throws DOMError */ + + /** + Aborts the request if it has already been sent. + **/ function abort() : Void; /** @throws DOMError */ + + /** + Returns the string containing the text of the specified header, or `null` if either the response has not yet been received or the header doesn't exist in the response. + **/ function getResponseHeader( header : String ) : String; /** @throws DOMError */ + + /** + Returns all the response headers, separated by CRLF, as a string, or `null` if no response has been received. + **/ function getAllResponseHeaders() : String; /** @throws DOMError */ + + /** + Overrides the MIME type returned by the server. + **/ function overrideMimeType( mime : String ) : Void; - /** @throws DOMError */ - function sendAsBinary( body : String ) : Void; } \ No newline at end of file diff --git a/std/js/html/XMLHttpRequestEventTarget.hx b/std/js/html/XMLHttpRequestEventTarget.hx index 7c731dea..ff007bdd 100644 --- a/std/js/html/XMLHttpRequestEventTarget.hx +++ b/std/js/html/XMLHttpRequestEventTarget.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/XMLHttpRequestEventTarget.webidl line 15:0. Do not edit! +// This file is generated from mozilla\XMLHttpRequestEventTarget.webidl. Do not edit! package js.html; +/** + `XMLHttpRequestEventTarget` is the interface that describes the event handlers you can implement in an object that will handle events for an `XMLHttpRequest`. + + Documentation [XMLHttpRequestEventTarget](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("XMLHttpRequestEventTarget") extern class XMLHttpRequestEventTarget extends EventTarget { diff --git a/std/js/html/XMLHttpRequestResponseType.hx b/std/js/html/XMLHttpRequestResponseType.hx index 9e44f05c..b677415a 100644 --- a/std/js/html/XMLHttpRequestResponseType.hx +++ b/std/js/html/XMLHttpRequestResponseType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/XMLHttpRequest.webidl line 17:0. Do not edit! +// This file is generated from mozilla\XMLHttpRequest.webidl. Do not edit! package js.html; diff --git a/std/js/html/XMLHttpRequestUpload.hx b/std/js/html/XMLHttpRequestUpload.hx index 311dbd89..ac31b5a5 100644 --- a/std/js/html/XMLHttpRequestUpload.hx +++ b/std/js/html/XMLHttpRequestUpload.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/XMLHttpRequestUpload.webidl line 14:0. Do not edit! +// This file is generated from mozilla\XMLHttpRequestUpload.webidl. Do not edit! package js.html; diff --git a/std/js/html/XMLSerializer.hx b/std/js/html/XMLSerializer.hx index 72011f19..1da7304c 100644 --- a/std/js/html/XMLSerializer.hx +++ b/std/js/html/XMLSerializer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/XMLSerializer.webidl line 12:0. Do not edit! +// This file is generated from mozilla\XMLSerializer.webidl. Do not edit! package js.html; diff --git a/std/js/html/XMLStylesheetProcessingInstruction.hx b/std/js/html/XMLStylesheetProcessingInstruction.hx index 44ff963f..26a465a9 100644 --- a/std/js/html/XMLStylesheetProcessingInstruction.hx +++ b/std/js/html/XMLStylesheetProcessingInstruction.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/XMLStylesheetProcessingInstruction.webidl line 7:0. Do not edit! +// This file is generated from mozilla\XMLStylesheetProcessingInstruction.webidl. Do not edit! package js.html; diff --git a/std/js/html/XPathEvaluator.hx b/std/js/html/XPathEvaluator.hx index e7228661..c1e6fed1 100644 --- a/std/js/html/XPathEvaluator.hx +++ b/std/js/html/XPathEvaluator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/XPathEvaluator.webidl line 8:0. Do not edit! +// This file is generated from mozilla\XPathEvaluator.webidl. Do not edit! package js.html; diff --git a/std/js/html/XPathExpression.hx b/std/js/html/XPathExpression.hx index ff41921d..604453ed 100644 --- a/std/js/html/XPathExpression.hx +++ b/std/js/html/XPathExpression.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/XPathExpression.webidl line 7:0. Do not edit! +// This file is generated from mozilla\XPathExpression.webidl. Do not edit! package js.html; +/** + An `XPathExpression` is a compiled XPath query returned from `document.createExpression()`. It has a method `evaluate()` which can be used to execute the compiled XPath. + + Documentation [XPathExpression](https://developer.mozilla.org/en-US/docs/Web/API/XPathExpression) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/XPathExpression$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("XPathExpression") extern class XPathExpression { diff --git a/std/js/html/XPathNSResolver.hx b/std/js/html/XPathNSResolver.hx index 043b68cb..f7cad4a9 100644 --- a/std/js/html/XPathNSResolver.hx +++ b/std/js/html/XPathNSResolver.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/XPathNSResolver.webidl line 7:9. Do not edit! +// This file is generated from mozilla\XPathNSResolver.webidl. Do not edit! package js.html; diff --git a/std/js/html/XPathResult.hx b/std/js/html/XPathResult.hx index d1af016e..a108a10f 100644 --- a/std/js/html/XPathResult.hx +++ b/std/js/html/XPathResult.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/XPathResult.webidl line 9:0. Do not edit! +// This file is generated from mozilla\XPathResult.webidl. Do not edit! package js.html; @@ -38,16 +38,52 @@ extern class XPathResult static inline var ANY_UNORDERED_NODE_TYPE : Int = 8; static inline var FIRST_ORDERED_NODE_TYPE : Int = 9; + + /** + readonly integer (short) + **/ var resultType(default,null) : Int; + + /** + readonly float + **/ var numberValue(default,null) : Float; + + /** + readonly String + **/ var stringValue(default,null) : String; + + /** + readonly boolean + **/ var booleanValue(default,null) : Bool; + + /** + readonly Node + **/ var singleNodeValue(default,null) : Node; + + /** + readonly boolean + **/ var invalidIteratorState(default,null) : Bool; + + /** + readonly Integer + **/ var snapshotLength(default,null) : Int; /** @throws DOMError */ + + /** + ... + **/ function iterateNext() : Node; /** @throws DOMError */ + + /** + ... + **/ function snapshotItem( index : Int ) : Node; } \ No newline at end of file diff --git a/std/js/html/XSLTProcessor.hx b/std/js/html/XSLTProcessor.hx index e4fc9c0c..7b8554fa 100644 --- a/std/js/html/XSLTProcessor.hx +++ b/std/js/html/XSLTProcessor.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/XSLTProcessor.webidl line 9:0. Do not edit! +// This file is generated from mozilla\XSLTProcessor.webidl. Do not edit! package js.html; +/** + An `XSLTProcessor` applies an XSLT stylesheet transformation to an XML document to produce a new XML document as output. It has methods to load the XSLT stylesheet, to manipulate `xsl:param` parameter values, and to apply the transformation to documents. + + Documentation [XSLTProcessor](https://developer.mozilla.org/en-US/docs/Web/API/XSLTProcessor) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/XSLTProcessor$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("XSLTProcessor") extern class XSLTProcessor { diff --git a/std/js/html/audio/AnalyserNode.hx b/std/js/html/audio/AnalyserNode.hx index 5b950fdb..9f0d5894 100644 --- a/std/js/html/audio/AnalyserNode.hx +++ b/std/js/html/audio/AnalyserNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,21 +20,64 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AnalyserNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\AnalyserNode.webidl. Do not edit! package js.html.audio; +/** + The `AnalyserNode` interface represents a node able to provide real-time frequency and time-domain analysis information. It is an `AudioNode` that passes the audio stream unchanged from the input to the output, but allows you to take the generated data, process it, and create audio visualizations. + + Documentation [AnalyserNode](https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AnalyserNode") extern class AnalyserNode extends AudioNode { + + /** + Is an unsigned long value representing the size of the FFT (Fast Fourier Transform) to be used to determine the frequency domain. + **/ var fftSize : Int; + + /** + Is an unsigned long value half that of the FFT size. This generally equates to the number of data values you will have to play with for the visualization. + **/ var frequencyBinCount(default,null) : Int; + + /** + Is a double value representing the minimum power value in the scaling range for the FFT analysis data, for conversion to unsigned byte values — basically, this specifies the minimum value for the range of results when using `getByteFrequencyData()`. + **/ var minDecibels : Float; + + /** + Is a double value representing the maximum power value in the scaling range for the FFT analysis data, for conversion to unsigned byte values — basically, this specifies the maximum value for the range of results when using `getByteFrequencyData()`. + **/ var maxDecibels : Float; + + /** + Is a double value representing the averaging constant with the last analysis frame — basically, it makes the transition between values over time smoother. + **/ var smoothingTimeConstant : Float; + + /** + Copies the current frequency data into a `Float32Array` array passed into it. + **/ function getFloatFrequencyData( array : js.html.Float32Array ) : Void; + + /** + Copies the current frequency data into a `Uint8Array` (unsigned byte array) passed into it. + **/ function getByteFrequencyData( array : js.html.Uint8Array ) : Void; + + /** + Copies the current waveform, or time-domain, data into a `Float32Array` array passed into it. + **/ function getFloatTimeDomainData( array : js.html.Float32Array ) : Void; + + /** + Copies the current waveform, or time-domain, data into a `Uint8Array` (unsigned byte array) passed into it. + **/ function getByteTimeDomainData( array : js.html.Uint8Array ) : Void; } \ No newline at end of file diff --git a/std/js/html/audio/AudioBuffer.hx b/std/js/html/audio/AudioBuffer.hx index 64d40641..20f1ca0a 100644 --- a/std/js/html/audio/AudioBuffer.hx +++ b/std/js/html/audio/AudioBuffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,22 +20,57 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioBuffer.webidl line 13:0. Do not edit! +// This file is generated from mozilla\AudioBuffer.webidl. Do not edit! package js.html.audio; +/** + Objects of these types are designed to hold small audio snippets, typically less than 45 s. For longer sounds, objects implementing the `MediaElementAudioSourceNode` are more suitable. The buffer contains data in the following format:  non-interleaved IEEE754 32-bit linear PCM with a nominal range between `-1` and `+1`, that is, 32bits floating point buffer, with each samples between -1.0 and 1.0. If the `AudioBuffer` has multiple channels, they are stored in separate buffer. + + Documentation [AudioBuffer](https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AudioBuffer") extern class AudioBuffer { + + /** + Returns a float representing the sample rate, in samples per second, of the PCM data stored in the buffer. + **/ var sampleRate(default,null) : Float; + + /** + Returns an integer representing the length, in sample-frames, of the PCM data stored in the buffer. + **/ var length(default,null) : Int; + + /** + Returns a double representing the duration, in seconds, of the PCM data stored in the buffer. + **/ var duration(default,null) : Float; + + /** + Returns an integer representing the number of discrete audio channels described by the PCM data stored in the buffer. + **/ var numberOfChannels(default,null) : Int; /** @throws DOMError */ + + /** + Returns a `Float32Array` containing the PCM data associated with the channel, defined by the `channel` parameter (with `0` representing the first channel). + **/ function getChannelData( channel : Int ) : js.html.Float32Array; /** @throws DOMError */ + + /** + Copies the samples from the specified channel of the `AudioBuffer` to the `destination` array. + **/ function copyFromChannel( destination : js.html.Float32Array, channelNumber : Int, ?startInChannel : Int = 0 ) : Void; /** @throws DOMError */ + + /** + Copies the samples to the specified channel of the `AudioBuffer`, from the `source` array. + **/ function copyToChannel( source : js.html.Float32Array, channelNumber : Int, ?startInChannel : Int = 0 ) : Void; } \ No newline at end of file diff --git a/std/js/html/audio/AudioBufferSourceNode.hx b/std/js/html/audio/AudioBufferSourceNode.hx index 8830cc5b..e036952f 100644 --- a/std/js/html/audio/AudioBufferSourceNode.hx +++ b/std/js/html/audio/AudioBufferSourceNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,22 +20,66 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioBufferSourceNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\AudioBufferSourceNode.webidl. Do not edit! package js.html.audio; +/** + The `AudioBufferSourceNode` interface represents an audio source consisting of in-memory audio data, stored in an `AudioBuffer`. It is an `AudioNode` that acts as an audio source`.` + + Documentation [AudioBufferSourceNode](https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AudioBufferSourceNode") extern class AudioBufferSourceNode extends AudioNode { + + /** + Is an `AudioBuffer` that defines the audio asset to be played, or when set to the value `null`, defines a single channel of silence.  + **/ var buffer : AudioBuffer; + + /** + Is an a-rate `AudioParam` that defines the speed factor at which the audio asset will be played. Since no pitch correction is applied on the output, this can be used to change the pitch of the sample. + **/ var playbackRate(default,null) : AudioParam; + + /** + Is a `AudioParam` representing detuning of oscillation in cents. Its default value is `0`. + **/ + var detune(default,null) : AudioParam; + + /** + Is a Boolean attribute indicating if the audio asset must be replayed when the end of the `AudioBuffer` is reached. Its default value is `false`. + **/ var loop : Bool; + + /** + Is a double value indicating, in seconds, where in the `AudioBuffer` the restart of the play must happen. Its default value is `0`. + **/ var loopStart : Float; + + /** + Is a double value indicating, in seconds, where in the `AudioBuffer` the replay of the play must stop (and eventually loop again). Its default value is `0`. + **/ var loopEnd : Float; + + /** + Is an `EventHandler` containing the callback associated with the `ended_(Web_Audio)` event. + **/ var onended : haxe.Constraints.Function; /** @throws DOMError */ + + /** + Schedules the start of the playback of the audio asset. + **/ function start( ?when : Float = 0.0, ?grainOffset : Float = 0.0, ?grainDuration : Float ) : Void; /** @throws DOMError */ + + /** + Schedules the end of the playback of an audio asset. + **/ function stop( ?when : Float = 0.0 ) : Void; } \ No newline at end of file diff --git a/std/js/html/audio/AudioContext.hx b/std/js/html/audio/AudioContext.hx index f1b713c6..f551d535 100644 --- a/std/js/html/audio/AudioContext.hx +++ b/std/js/html/audio/AudioContext.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,48 +20,190 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioContext.webidl line 18:0. Do not edit! +// This file is generated from mozilla\AudioContext.webidl. Do not edit! package js.html.audio; +/** + An `AudioContext` can be a target of events, therefore it implements the `EventTarget` interface. + + Documentation [AudioContext](https://developer.mozilla.org/en-US/docs/Web/API/AudioContext) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AudioContext$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AudioContext") extern class AudioContext extends js.html.EventTarget { + + /** + Returns an `AudioDestinationNode` representing the final destination of all audio in the context. It can be thought of as the audio-rendering device. + **/ var destination(default,null) : AudioDestinationNode; + + /** + Returns a float representing the sample rate (in samples per second) used by all nodes in this context. The sample-rate of an `AudioContext` cannot be changed. + **/ var sampleRate(default,null) : Float; + + /** + Returns a double representing an ever-increasing hardware time in seconds used for scheduling. It starts at `0`. + **/ var currentTime(default,null) : Float; + + /** + Returns the `AudioListener` object, used for 3D spatialization. + **/ var listener(default,null) : AudioListener; + /** + Returns the current state of the `AudioContext`. + **/ + var state(default,null) : js.html.AudioContextState; + + /** + An event handler that runs when an event of type `statechange` has fired. This occurs when the `AudioContext`'s state changes, due to the calling of one of the state change methods (`AudioContext.suspend`, `AudioContext.resume`, or `AudioContext.close`). + **/ + var onstatechange : haxe.Constraints.Function; + /** @throws DOMError */ @:overload( function() : Void {} ) function new( audioChannelType : js.html.AudioChannel ) : Void; /** @throws DOMError */ + + /** + Suspends the progression of time in the audio context, temporarily halting audio hardware access and reducing CPU/battery usage in the process. + **/ + function suspend() : Promise; + /** @throws DOMError */ + + /** + Resumes the progression of time in an audio context that has previously been suspended. + **/ + function resume() : Promise; + /** @throws DOMError */ + + /** + Closes the audio context, releasing any system audio resources that it uses. + **/ + function close() : Promise; + /** @throws DOMError */ + + /** + Creates a new, empty `AudioBuffer` object, which can then be populated by data and played via an `AudioBufferSourceNode`. + **/ function createBuffer( numberOfChannels : Int, length : Int, sampleRate : Float ) : AudioBuffer; + /** @throws DOMError */ + + /** + Asynchronously decodes audio file data contained in an `ArrayBuffer`. In this case, the ArrayBuffer is usually loaded from an `XMLHttpRequest`'s `response` attribute after setting the `responseType` to `arraybuffer`. This method only works on complete files, not fragments of audio files. + **/ function decodeAudioData( audioData : js.html.ArrayBuffer, ?successCallback : AudioBuffer -> Void, ?errorCallback : Void -> Void ) : Promise; + /** @throws DOMError */ + + /** + Creates an `AudioBufferSourceNode`, which can be used to play and manipulate audio data contained within an `AudioBuffer` object. `AudioBuffer`s are created using `AudioContext.createBuffer` or returned by `AudioContext.decodeAudioData` when it successfully decodes an audio track. + **/ function createBufferSource() : AudioBufferSourceNode; /** @throws DOMError */ + + /** + Creates a `MediaStreamAudioDestinationNode` associated with a `MediaStream` representing an audio stream which may be stored in a local file or sent to another computer. + **/ function createMediaStreamDestination() : MediaStreamAudioDestinationNode; /** @throws DOMError */ + + /** + Creates a `ScriptProcessorNode`, which can be used for direct audio processing via JavaScript. + **/ function createScriptProcessor( ?bufferSize : Int = 0, ?numberOfInputChannels : Int = 2, ?numberOfOutputChannels : Int = 2 ) : ScriptProcessorNode; + /** @throws DOMError */ + + /** + Creates a `StereoPannerNode`, which can be used to apply stereo panning to an audio source. + **/ function createStereoPanner() : StereoPannerNode; + /** @throws DOMError */ + + /** + Creates an `AnalyserNode`, which can be used to expose audio time and frequency data and for example to create data visualisations. + **/ function createAnalyser() : AnalyserNode; /** @throws DOMError */ + + /** + Creates a `MediaElementAudioSourceNode` associated with an `HTMLMediaElement`. This can be used to play and manipulate audio from `video` or `audio` elements. + **/ function createMediaElementSource( mediaElement : js.html.MediaElement ) : MediaElementAudioSourceNode; /** @throws DOMError */ + + /** + Creates a `MediaStreamAudioSourceNode` associated with a `MediaStream` representing an audio stream which may come from the local computer microphone or other sources. + **/ function createMediaStreamSource( mediaStream : js.html.MediaStream ) : MediaStreamAudioSourceNode; + /** @throws DOMError */ + + /** + Creates a `GainNode`, which can be used to control the overall volume of the audio graph. + **/ function createGain() : GainNode; /** @throws DOMError */ + + /** + Creates a `DelayNode`, which is used to delay the incoming audio signal by a certain amount. This node is also useful to create feedback loops in a Web Audio API graph. + **/ function createDelay( ?maxDelayTime : Float = 1.0 ) : DelayNode; + /** @throws DOMError */ + + /** + Creates a `BiquadFilterNode`, which represents a second order filter configurable as several different common filter types: high-pass, low-pass, band-pass, etc. + **/ function createBiquadFilter() : BiquadFilterNode; + /** @throws DOMError */ + + /** + Creates a `WaveShaperNode`, which is used to implement non-linear distortion effects. + **/ function createWaveShaper() : WaveShaperNode; + /** @throws DOMError */ + + /** + Creates a `PannerNode`, which is used to spatialise an incoming audio stream in 3D space. + **/ function createPanner() : PannerNode; + /** @throws DOMError */ + + /** + Creates a `ConvolverNode`, which can be used to apply convolution effects to your audio graph, for example a reverberation effect. + **/ function createConvolver() : ConvolverNode; /** @throws DOMError */ + + /** + Creates a `ChannelSplitterNode`, which is used to access the individual channels of an audio stream and process them separately. + **/ function createChannelSplitter( ?numberOfOutputs : Int = 6 ) : ChannelSplitterNode; /** @throws DOMError */ + + /** + Creates a `ChannelMergerNode`, which is used to combine channels from multiple audio streams into a single audio stream. + **/ function createChannelMerger( ?numberOfInputs : Int = 6 ) : ChannelMergerNode; + /** @throws DOMError */ + + /** + Creates a `DynamicsCompressorNode`, which can be used to apply acoustic compression to an audio signal. + **/ function createDynamicsCompressor() : DynamicsCompressorNode; + /** @throws DOMError */ + + /** + Creates an `OscillatorNode`, a source representing a periodic waveform. It basically generates a tone. + **/ function createOscillator() : OscillatorNode; /** @throws DOMError */ + + /** + Creates a `PeriodicWave`, used to define a periodic waveform that can be used to determine the output of an `OscillatorNode`. + **/ function createPeriodicWave( real : js.html.Float32Array, imag : js.html.Float32Array ) : PeriodicWave; } \ No newline at end of file diff --git a/std/js/html/audio/AudioDestinationNode.hx b/std/js/html/audio/AudioDestinationNode.hx index ce6c0141..81714de2 100644 --- a/std/js/html/audio/AudioDestinationNode.hx +++ b/std/js/html/audio/AudioDestinationNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioDestinationNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\AudioDestinationNode.webidl. Do not edit! package js.html.audio; +/** + `AudioDestinationNode` has no output (as it is the output, no more `AudioNode` can be linked after it in the audio graph) and one input. The amount of channels in the input must be between `0` and the `maxChannelCount` value or an exception is raised. + + Documentation [AudioDestinationNode](https://developer.mozilla.org/en-US/docs/Web/API/AudioDestinationNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AudioDestinationNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AudioDestinationNode") extern class AudioDestinationNode extends AudioNode { + + /** + Is an `unsigned long` defining the maximum amount of channels that the physical device can handle. + **/ var maxChannelCount(default,null) : Int; } \ No newline at end of file diff --git a/std/js/html/audio/AudioListener.hx b/std/js/html/audio/AudioListener.hx index af1a5231..3e8fd020 100644 --- a/std/js/html/audio/AudioListener.hx +++ b/std/js/html/audio/AudioListener.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,17 +20,32 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioListener.webidl line 13:0. Do not edit! +// This file is generated from mozilla\AudioListener.webidl. Do not edit! package js.html.audio; +/** + It is important to note that there is only one listener per context and that it isn't an `AudioNode`. + + Documentation [AudioListener](https://developer.mozilla.org/en-US/docs/Web/API/AudioListener) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AudioListener$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AudioListener") extern class AudioListener { var dopplerFactor : Float; var speedOfSound : Float; + + /** + Sets the position of the listener. See `Deprecated features` to learn why this method was removed. + **/ function setPosition( x : Float, y : Float, z : Float ) : Void; + + /** + Sets the orientation of the listener. + **/ function setOrientation( x : Float, y : Float, z : Float, xUp : Float, yUp : Float, zUp : Float ) : Void; function setVelocity( x : Float, y : Float, z : Float ) : Void; } \ No newline at end of file diff --git a/std/js/html/audio/AudioNode.hx b/std/js/html/audio/AudioNode.hx index 75d6161d..0368fe0b 100644 --- a/std/js/html/audio/AudioNode.hx +++ b/std/js/html/audio/AudioNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,23 +20,64 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioNode.webidl line 24:0. Do not edit! +// This file is generated from mozilla\AudioNode.webidl. Do not edit! package js.html.audio; +/** + The `AudioNode` interface is a generic interface for representing an audio processing module like an audio source (e.g. an HTML `audio` or `video` element, an `OscillatorNode`, etc.), the audio destination, intermediate processing module (e.g. a filter like `BiquadFilterNode` or `ConvolverNode`), or volume control (like `GainNode`). + + Documentation [AudioNode](https://developer.mozilla.org/en-US/docs/Web/API/AudioNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AudioNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AudioNode") extern class AudioNode extends js.html.EventTarget { + + /** + Returns the associated `AudioContext`, that is the object representing the processing graph the node is participating in. + **/ var context(default,null) : AudioContext; + + /** + Returns the number of inputs feeding the node. Source nodes are defined as nodes having a `numberOfInputs` property with a value of `0`. + **/ var numberOfInputs(default,null) : Int; + + /** + Returns the number of outputs coming out of the node. Destination nodes — like `AudioDestinationNode` — have a value of `0` for this attribute. + **/ var numberOfOutputs(default,null) : Int; + + /** + Represents an integer used to determine how many channels are used when up-mixing and down-mixing connections to any inputs to the node. Its usage and precise definition depend on the value of `AudioNode.channelCountMode`. + **/ var channelCount : Int; + + /** + Represents an enumerated value describing the way channels must be matched between the node's inputs and outputs. + **/ var channelCountMode : ChannelCountMode; + + /** + Represents an enumerated value describing the meaning of the channels. This interpretation will define how audio up-mixing and down-mixing will happen. + + The possible values are `"speakers"` or `"discrete"`. + **/ var channelInterpretation : ChannelInterpretation; /** @throws DOMError */ - @:overload( function( destination : AudioNode, ?output : Int = 0, ?input : Int = 0 ) : Void {} ) + @:overload( function( destination : AudioNode, ?output : Int = 0, ?input : Int = 0 ) : AudioNode {} ) + + /** + Allows us to connect one output of this node to one input of an audio parameter. + **/ function connect( destination : AudioParam, ?output : Int = 0 ) : Void; /** @throws DOMError */ + + /** + Allows us to disconnect the current node from another one it is already connected to. + **/ function disconnect( ?output : Int = 0 ) : Void; } \ No newline at end of file diff --git a/std/js/html/audio/AudioParam.hx b/std/js/html/audio/AudioParam.hx index 4ba4b6b0..b93947d8 100644 --- a/std/js/html/audio/AudioParam.hx +++ b/std/js/html/audio/AudioParam.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,26 +20,65 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioParam.webidl line 13:0. Do not edit! +// This file is generated from mozilla\AudioParam.webidl. Do not edit! package js.html.audio; +/** + There are two kinds of `AudioParam`, a-rate and k-rate parameters: + + Documentation [AudioParam](https://developer.mozilla.org/en-US/docs/Web/API/AudioParam) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AudioParam$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AudioParam") extern class AudioParam { + + /** + Represents the parameter's current volume as a floating point value; initially set to the value of `AudioParam.defaultValue`. Though it can be set, any modifications happening while there are automation events scheduled — that is events scheduled using the methods of the `AudioParam` — are ignored, without raising any exception. + **/ var value : Float; + + /** + Represents the initial volume of the attribute as defined by the specific `AudioNode` creating the `AudioParam`. + **/ var defaultValue(default,null) : Float; /** @throws DOMError */ + + /** + Schedules an instant change to the value of the `AudioParam` at a precise time, as measured against `AudioContext.currentTime`. The new value is given in the `value` parameter. + **/ function setValueAtTime( value : Float, startTime : Float ) : Void; /** @throws DOMError */ + + /** + Schedules a gradual linear change in the value of the `AudioParam`. The change starts at the time specified for the previous event, follows a linear ramp to the new value given in the `value` parameter, and reaches the new value at the time given in the `endTime` parameter. + **/ function linearRampToValueAtTime( value : Float, endTime : Float ) : Void; /** @throws DOMError */ + + /** + Schedules a gradual exponential change in the value of the `AudioParam`. The change starts at the time specified for the previous event, follows an exponential ramp to the new value given in the `value` parameter, and reaches the new value at the time given in the `endTime` parameter. + **/ function exponentialRampToValueAtTime( value : Float, endTime : Float ) : Void; /** @throws DOMError */ + + /** + Schedules the start of a change to the value of the `AudioParam`. The change starts at the time specified in `startTime` and exponentially moves towards the value given by the `target` parameter. The exponential decay rate is defined by the `timeConstant` parameter, which is a time measured in seconds. + **/ function setTargetAtTime( target : Float, startTime : Float, timeConstant : Float ) : Void; /** @throws DOMError */ + + /** + Schedules the values of the `AudioParam` to follow a set of values, defined by the `values` `Float32Array` scaled to fit into the given interval, starting at `startTime`, and having a specific `duration`. + **/ function setValueCurveAtTime( values : js.html.Float32Array, startTime : Float, duration : Float ) : Void; /** @throws DOMError */ + + /** + Cancels all scheduled future changes to the `AudioParam`. + **/ function cancelScheduledValues( startTime : Float ) : Void; } \ No newline at end of file diff --git a/std/js/html/audio/AudioProcessingEvent.hx b/std/js/html/audio/AudioProcessingEvent.hx index d56ad3bd..76811cda 100644 --- a/std/js/html/audio/AudioProcessingEvent.hx +++ b/std/js/html/audio/AudioProcessingEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioProcessingEvent.webidl line 13:0. Do not edit! +// This file is generated from mozilla\AudioProcessingEvent.webidl. Do not edit! package js.html.audio; +/** + The Web Audio API `AudioProcessingEvent` represents events that occur when a `ScriptProcessorNode` input buffer is ready to be processed. + + Documentation [AudioProcessingEvent](https://developer.mozilla.org/en-US/docs/Web/API/AudioProcessingEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/AudioProcessingEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("AudioProcessingEvent") extern class AudioProcessingEvent extends js.html.Event { diff --git a/std/js/html/audio/BiquadFilterNode.hx b/std/js/html/audio/BiquadFilterNode.hx index f1bc24f8..67dabe8e 100644 --- a/std/js/html/audio/BiquadFilterNode.hx +++ b/std/js/html/audio/BiquadFilterNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,18 +20,121 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/BiquadFilterNode.webidl line 24:0. Do not edit! +// This file is generated from mozilla\BiquadFilterNode.webidl. Do not edit! package js.html.audio; +/** + The `BiquadFilterNode` interface represents a simple low-order filter, and is created using the `AudioContext.createBiquadFilter()` method. It is an `AudioNode` that can represent different kinds of filters, tone control devices, and graphic equalizers. + + Documentation [BiquadFilterNode](https://developer.mozilla.org/en-US/docs/Web/API/BiquadFilterNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/BiquadFilterNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("BiquadFilterNode") extern class BiquadFilterNode extends AudioNode { + + /** + Is a string value defining the kind of filtering algorithm the node is implementing.
+   + + The meaning of the different parameters depending of the type of the filter (detune has the same meaning regardless, so isn't listed below) + + + type + Description + frequency + Q + gain + + + + + lowpass + + + + + + + highpass + + + + + + + bandpass + + + + + + + lowshelf + + + + + + + highshelf + + + + + + + peaking + + + + + + + notch + + + + + + + allpass + + + + + + +
Standard second-order resonant lowpass filter with 12dB/octave rolloff. Frequencies below the cutoff pass through; frequencies above it are attenuated.The cutoff frequency.Indicates how peaked the frequency is around the cutoff. The greater the value is, the greater is the peak.Not used
Standard second-order resonant highpass filter with 12dB/octave rolloff. Frequencies below the cutoff are attenuated; frequencies above it pass through.The cutoff frequency.Indicates how peaked the frequency is around the cutoff. The greater the value, the greater the peak.Not used
Standard second-order bandpass filter. Frequencies outside the given range of frequencies are attenuated; the frequencies inside it pass through.The center of the range of frequencies.Controls the width of the frequency band. The greater the Q value, the smaller the frequency band.Not used
Standard second-order lowshelf filer. Frequencies lower than the frequency get a boost, or an attenuation; frequencies over it are unchanged.The upper limit of the frequencies getting a boost or an attenuation.Not usedThe boost, in dB, to be applied; if negative, it will be an attenuation.
Standard second-order highshelf filer. Frequencies higher than the frequency get a boost or an attenuation; frequencies lower than it are unchanged.The lower limit of the frequencies getting a boost or an attenuation.Not usedThe boost, in dB, to be applied; if negative, it will be an attenuation.
Frequencies inside the range get a boost or an attenuation; frequencies outside it are unchanged.The middle of the frequency range getting a boost or an attenuation.Controls the width of the frequency band. The greater the Q value, the smaller the frequency band.The boost, in dB, to be applied; if negative, it will be an attenuation.
Standard notch filter, also called a band-stop or band-rejection filter. It is the opposite of a bandpass filter: frequencies outside the give range of frequencies pass through; frequencies inside it are attenuated.The center of the range of frequencies.Controls the width of the frequency band. The greater the Q value, the smaller the frequency band.Not used
Standard second-order allpass filter. It lets all frequencies through, but changes the phase-relationship between the various frequencies.The frequency with the maximal group delay, that is, the frequency where the center of the phase transition occurs.Controls how sharp the transition is at the medium frequency. The larger this parameter is, the sharper and larger the transition will be.Not used
+ + **/ var type : BiquadFilterType; + + /** + Is an a-rate `AudioParam`, a double representing a frequency in the current filtering algorithm measured in hertz (Hz). + **/ var frequency(default,null) : AudioParam; + + /** + Is an a-rate `AudioParam` representing detuning of the frequency in cents. + **/ var detune(default,null) : AudioParam; + + /** + Is an a-rate `AudioParam`, a double representing a Q factor, or quality factor. + **/ var Q(default,null) : AudioParam; + + /** + Is an a-rate `AudioParam`, a double representing the gain used in the current filtering algorithm. + **/ var gain(default,null) : AudioParam; + + /** + From the current filter parameter settings this method calculates the frequency response for frequencies specified in the provided array of frequencies. + **/ function getFrequencyResponse( frequencyHz : js.html.Float32Array, magResponse : js.html.Float32Array, phaseResponse : js.html.Float32Array ) : Void; } \ No newline at end of file diff --git a/std/js/html/audio/BiquadFilterType.hx b/std/js/html/audio/BiquadFilterType.hx index 638fa06a..4d92c38f 100644 --- a/std/js/html/audio/BiquadFilterType.hx +++ b/std/js/html/audio/BiquadFilterType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/BiquadFilterNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\BiquadFilterNode.webidl. Do not edit! package js.html.audio; diff --git a/std/js/html/audio/ChannelCountMode.hx b/std/js/html/audio/ChannelCountMode.hx index 233570dd..1a204c70 100644 --- a/std/js/html/audio/ChannelCountMode.hx +++ b/std/js/html/audio/ChannelCountMode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\AudioNode.webidl. Do not edit! package js.html.audio; diff --git a/std/js/html/audio/ChannelInterpretation.hx b/std/js/html/audio/ChannelInterpretation.hx index 6f522afc..2c5d6309 100644 --- a/std/js/html/audio/ChannelInterpretation.hx +++ b/std/js/html/audio/ChannelInterpretation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/AudioNode.webidl line 19:0. Do not edit! +// This file is generated from mozilla\AudioNode.webidl. Do not edit! package js.html.audio; diff --git a/std/js/html/audio/ChannelMergerNode.hx b/std/js/html/audio/ChannelMergerNode.hx index c5c0b2e2..52c01d00 100644 --- a/std/js/html/audio/ChannelMergerNode.hx +++ b/std/js/html/audio/ChannelMergerNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ChannelMergerNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\ChannelMergerNode.webidl. Do not edit! package js.html.audio; diff --git a/std/js/html/audio/ChannelSplitterNode.hx b/std/js/html/audio/ChannelSplitterNode.hx index 29f724f0..abde628f 100644 --- a/std/js/html/audio/ChannelSplitterNode.hx +++ b/std/js/html/audio/ChannelSplitterNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ChannelSplitterNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\ChannelSplitterNode.webidl. Do not edit! package js.html.audio; diff --git a/std/js/html/audio/ConvolverNode.hx b/std/js/html/audio/ConvolverNode.hx index 98d206ad..d6bc0b85 100644 --- a/std/js/html/audio/ConvolverNode.hx +++ b/std/js/html/audio/ConvolverNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ConvolverNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\ConvolverNode.webidl. Do not edit! package js.html.audio; +/** + The `ConvolverNode` interface is an `AudioNode` that performs a Linear Convolution on a given `AudioBuffer`, often used to achieve a reverb effect. A `ConvolverNode` always has exactly one input and one output. + + Documentation [ConvolverNode](https://developer.mozilla.org/en-US/docs/Web/API/ConvolverNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ConvolverNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("ConvolverNode") extern class ConvolverNode extends AudioNode { + + /** + A mono, stereo, or 4-channel `AudioBuffer` containing the (possibly multichannel) impulse response used by the `ConvolverNode` to create the reverb effect. + **/ var buffer : AudioBuffer; + + /** + A boolean that controls whether the impulse response from the buffer will be scaled by an equal-power normalization when the `buffer` attribute is set, or not. + **/ var normalize : Bool; } \ No newline at end of file diff --git a/std/js/html/audio/DelayNode.hx b/std/js/html/audio/DelayNode.hx index 48caa971..13e43083 100644 --- a/std/js/html/audio/DelayNode.hx +++ b/std/js/html/audio/DelayNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,22 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DelayNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\DelayNode.webidl. Do not edit! package js.html.audio; +/** + Documentation [DelayNode](https://developer.mozilla.org/en-US/docs/Web/API/DelayNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DelayNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DelayNode") extern class DelayNode extends AudioNode { + + /** + Is an a-rate `AudioParam` representing the amount of delay to apply. + **/ var delayTime(default,null) : AudioParam; } \ No newline at end of file diff --git a/std/js/html/audio/DistanceModelType.hx b/std/js/html/audio/DistanceModelType.hx index 3a9cd2c4..e4d74ed4 100644 --- a/std/js/html/audio/DistanceModelType.hx +++ b/std/js/html/audio/DistanceModelType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PannerNode.webidl line 18:0. Do not edit! +// This file is generated from mozilla\PannerNode.webidl. Do not edit! package js.html.audio; diff --git a/std/js/html/audio/DynamicsCompressorNode.hx b/std/js/html/audio/DynamicsCompressorNode.hx index e1e341ef..35c9434c 100644 --- a/std/js/html/audio/DynamicsCompressorNode.hx +++ b/std/js/html/audio/DynamicsCompressorNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,18 +20,49 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DynamicsCompressorNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\DynamicsCompressorNode.webidl. Do not edit! package js.html.audio; +/** + Inherits properties from its parent, `AudioNode`. + + Documentation [DynamicsCompressorNode](https://developer.mozilla.org/en-US/docs/Web/API/DynamicsCompressorNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/DynamicsCompressorNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("DynamicsCompressorNode") extern class DynamicsCompressorNode extends AudioNode { + + /** + Is a `AudioParam` representing the decibel value above which the compression will start taking effect. + **/ var threshold(default,null) : AudioParam; + + /** + Is a `AudioParam` containing a decibel value representing the range above the threshold where the curve smoothly transitions to the compressed portion. + **/ var knee(default,null) : AudioParam; + + /** + Is a `AudioParam` representing the amount of change, in dB, needed in the input for a 1 dB change in the output. + **/ var ratio(default,null) : AudioParam; - var reduction(default,null) : AudioParam; + + /** + Is a `float `representing the amount of gain reduction currently applied by the compressor to the signal. + **/ + var reduction(default,null) : Float; + + /** + Is a `AudioParam` representing the amount of time, in seconds, required to reduce the gain by 10 dB. + **/ var attack(default,null) : AudioParam; + + /** + Is a `AudioParam` representing the amount of time, in seconds, required to increase the gain by 10 dB. + **/ var release(default,null) : AudioParam; } \ No newline at end of file diff --git a/std/js/html/audio/GainNode.hx b/std/js/html/audio/GainNode.hx index a6aeac83..e40561f3 100644 --- a/std/js/html/audio/GainNode.hx +++ b/std/js/html/audio/GainNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/GainNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\GainNode.webidl. Do not edit! package js.html.audio; +/** + The gain is a unitless value, changing with time, that is multiplied to each corresponding sample of all input channels. If modified, the new gain is applied using a de-zippering algorithm in order to prevent unaesthetic 'clicks' from appearing in the resulting audio. + + Documentation [GainNode](https://developer.mozilla.org/en-US/docs/Web/API/GainNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/GainNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("GainNode") extern class GainNode extends AudioNode { + + /** + Is an a-rate `AudioParam` representing the amount of gain to apply. + **/ var gain(default,null) : AudioParam; } \ No newline at end of file diff --git a/std/js/html/audio/MediaElementAudioSourceNode.hx b/std/js/html/audio/MediaElementAudioSourceNode.hx index ff1d33c8..c82325e7 100644 --- a/std/js/html/audio/MediaElementAudioSourceNode.hx +++ b/std/js/html/audio/MediaElementAudioSourceNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaElementAudioSourceNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\MediaElementAudioSourceNode.webidl. Do not edit! package js.html.audio; +/** + A `MediaElementSourceNode` has no inputs and exactly one output, and is created using the `AudioContext.createMediaElementSource` method. The amount of channels in the output equals the number of channels of the audio referenced by the `HTMLMediaElement` used in the creation of the node, or is 1 if the `HTMLMediaElement` has no audio. + + Documentation [MediaElementAudioSourceNode](https://developer.mozilla.org/en-US/docs/Web/API/MediaElementAudioSourceNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MediaElementAudioSourceNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MediaElementAudioSourceNode") extern class MediaElementAudioSourceNode extends AudioNode { diff --git a/std/js/html/audio/MediaStreamAudioDestinationNode.hx b/std/js/html/audio/MediaStreamAudioDestinationNode.hx index c67f9343..5e77a997 100644 --- a/std/js/html/audio/MediaStreamAudioDestinationNode.hx +++ b/std/js/html/audio/MediaStreamAudioDestinationNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaStreamAudioDestinationNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\MediaStreamAudioDestinationNode.webidl. Do not edit! package js.html.audio; +/** + Inherits properties from its parent, `AudioNode`. + + Documentation [MediaStreamAudioDestinationNode](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamAudioDestinationNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamAudioDestinationNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MediaStreamAudioDestinationNode") extern class MediaStreamAudioDestinationNode extends AudioNode { + + /** + Is a `MediaStream` containing a single `AudioMediaStreamTrack` with the same number of channels as the node itself. You can use this property to get a stream out of the audio graph and feed it into another construct, such as a Media Recorder. + **/ var stream(default,null) : js.html.MediaStream; } \ No newline at end of file diff --git a/std/js/html/audio/MediaStreamAudioSourceNode.hx b/std/js/html/audio/MediaStreamAudioSourceNode.hx index 126e819b..93805421 100644 --- a/std/js/html/audio/MediaStreamAudioSourceNode.hx +++ b/std/js/html/audio/MediaStreamAudioSourceNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/MediaStreamAudioSourceNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\MediaStreamAudioSourceNode.webidl. Do not edit! package js.html.audio; +/** + A `MediaElementSourceNode` has no inputs and exactly one output, and is created using the `AudioContext.createMediaStreamSource` method. The amount of channels in the output equals the number of channels in `AudioMediaStreamTrack`. If there is no valid media stream, then the number of output channels will be one silent channel. + + Documentation [MediaStreamAudioSourceNode](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamAudioSourceNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamAudioSourceNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("MediaStreamAudioSourceNode") extern class MediaStreamAudioSourceNode extends AudioNode { diff --git a/std/js/html/audio/OfflineAudioCompletionEvent.hx b/std/js/html/audio/OfflineAudioCompletionEvent.hx index 9883553e..1d9e69a1 100644 --- a/std/js/html/audio/OfflineAudioCompletionEvent.hx +++ b/std/js/html/audio/OfflineAudioCompletionEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/OfflineAudioCompletionEvent.webidl line 13:0. Do not edit! +// This file is generated from mozilla\OfflineAudioCompletionEvent.webidl. Do not edit! package js.html.audio; +/** + The Web Audio API `OfflineAudioCompletionEvent` interface represents events that occur when the processing of an `OfflineAudioContext` is terminated. The `complete` event implements this interface. + + Documentation [OfflineAudioCompletionEvent](https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioCompletionEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioCompletionEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("OfflineAudioCompletionEvent") extern class OfflineAudioCompletionEvent extends js.html.Event { diff --git a/std/js/html/audio/OfflineAudioContext.hx b/std/js/html/audio/OfflineAudioContext.hx index 85e600ba..fd31663c 100644 --- a/std/js/html/audio/OfflineAudioContext.hx +++ b/std/js/html/audio/OfflineAudioContext.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,17 +20,32 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/OfflineAudioContext.webidl line 16:0. Do not edit! +// This file is generated from mozilla\OfflineAudioContext.webidl. Do not edit! package js.html.audio; +/** + The `OfflineAudioContext` interface is an `AudioContext` interface representing an audio-processing graph built from linked together `AudioNode`s. In contrast with a standard `AudioContext`, an `OfflineAudioContext` doesn't render the audio to the device hardware; instead, it generates it, as fast as it can, and outputs the result to an `AudioBuffer`. + + Documentation [OfflineAudioContext](https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("OfflineAudioContext") extern class OfflineAudioContext extends AudioContext { + + /** + Is an `EventHandler` called when processing is terminated, that is when the `complete` event (of type `OfflineAudioCompletionEvent`) is raised, after the event-based version of `OfflineAudioContext.startRendering()` is used. + **/ var oncomplete : haxe.Constraints.Function; /** @throws DOMError */ function new( numberOfChannels : Int, length : Int, sampleRate : Float ) : Void; /** @throws DOMError */ + + /** + Starts rendering the audio, taking into account the current connections and the current scheduled changes. This page covers both the event-based version and the promise-based version. + **/ function startRendering() : Promise; } \ No newline at end of file diff --git a/std/js/html/audio/OscillatorNode.hx b/std/js/html/audio/OscillatorNode.hx index a26f46a5..4b12ee46 100644 --- a/std/js/html/audio/OscillatorNode.hx +++ b/std/js/html/audio/OscillatorNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,21 +20,52 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/OscillatorNode.webidl line 21:0. Do not edit! +// This file is generated from mozilla\OscillatorNode.webidl. Do not edit! package js.html.audio; +/** + The `OscillatorNode` interface represents a periodic waveform, like a sine wave. It is an `AudioNode` audio-processing module that causes a given frequency of sine wave to be created — in effect, a constant tone. + + Documentation [OscillatorNode](https://developer.mozilla.org/en-US/docs/Web/API/OscillatorNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/OscillatorNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("OscillatorNode") extern class OscillatorNode extends AudioNode { + + /** + Represents the shape of the oscillator wave generated. Different waves will produce different tones. + **/ var type : OscillatorType; + + /** + An a-rate `AudioParam` representing the frequency of oscillation in hertz (though the AudioParam` returned is read-only, the value it represents is not.) + **/ var frequency(default,null) : AudioParam; + + /** + An a-rate `AudioParam` representing detuning of oscillation in cents (though the AudioParam` returned is read-only, the value it represents is not.) + **/ var detune(default,null) : AudioParam; var onended : haxe.Constraints.Function; /** @throws DOMError */ + + /** + This method specifies the exact time to start playing the tone. + **/ function start( ?when : Float = 0.0 ) : Void; /** @throws DOMError */ + + /** + This method specifies the exact time to stop playing the tone. + **/ function stop( ?when : Float = 0.0 ) : Void; + + /** + Used to point to a `PeriodicWave` defining a periodic waveform that can be used to shape the oscillator's output, when `type = "custom"` is used. This replaces the now-obsolete `OscillatorNode.setWaveTable`. + **/ function setPeriodicWave( periodicWave : PeriodicWave ) : Void; } \ No newline at end of file diff --git a/std/js/html/audio/OscillatorType.hx b/std/js/html/audio/OscillatorType.hx index 5ca43481..c6aae962 100644 --- a/std/js/html/audio/OscillatorType.hx +++ b/std/js/html/audio/OscillatorType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/OscillatorNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\OscillatorNode.webidl. Do not edit! package js.html.audio; diff --git a/std/js/html/audio/OverSampleType.hx b/std/js/html/audio/OverSampleType.hx index 7b9d4cbd..3abd7dc0 100644 --- a/std/js/html/audio/OverSampleType.hx +++ b/std/js/html/audio/OverSampleType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WaveShaperNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\WaveShaperNode.webidl. Do not edit! package js.html.audio; diff --git a/std/js/html/audio/PannerNode.hx b/std/js/html/audio/PannerNode.hx index 8a382178..2e228b57 100644 --- a/std/js/html/audio/PannerNode.hx +++ b/std/js/html/audio/PannerNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,23 +20,74 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PannerNode.webidl line 24:0. Do not edit! +// This file is generated from mozilla\PannerNode.webidl. Do not edit! package js.html.audio; +/** + A `PannerNode` always has exactly one input and one output: the input can be mono or stereo but the output is always stereo (2 channels); you can't have panning effects without at least two audio channels! + + Documentation [PannerNode](https://developer.mozilla.org/en-US/docs/Web/API/PannerNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PannerNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("PannerNode") extern class PannerNode extends AudioNode { + + /** + An enumerated value determining which spatialisation algorithm to use to position the audio in 3D space. + **/ var panningModel : PanningModelType; + + /** + An enumerated value determining which algorithm to use to reduce the volume of the audio source as it moves away from the listener. + **/ var distanceModel : DistanceModelType; + + /** + A double value representing the reference distance for reducing volume as the audio source moves further from the listener. + **/ var refDistance : Float; + + /** + A double value representing the maximum distance between the audio source and the listener, after which the volume is not reduced any further. + **/ var maxDistance : Float; + + /** + A double value describing how quickly the volume is reduced as the source moves away from the listener. This value is used by all distance models. + **/ var rolloffFactor : Float; + + /** + Is a double value describing the angle, in degrees, of a cone inside of which there will be no volume reduction. + **/ var coneInnerAngle : Float; + + /** + A double value describing the angle, in degrees, of a cone outside of which the volume will be reduced by a constant value, defined by the `coneOuterGain` attribute. + **/ var coneOuterAngle : Float; + + /** + A double value describing the amount of volume reduction outside the cone defined by the `coneOuterAngle` attribute. Its default value is `0`, meaning that no sound can be heard. + **/ var coneOuterGain : Float; + + /** + Defines the position of the audio source relative to the listener (represented by an `AudioListener` object stored in the `AudioContext.listener` attribute.) + **/ function setPosition( x : Float, y : Float, z : Float ) : Void; + + /** + Defines the direction the audio source is playing in. + **/ function setOrientation( x : Float, y : Float, z : Float ) : Void; + + /** + Defines the velocity vector of the audio source — how fast it is moving and in what direction. In a previous version of the specification, the `PannerNode` had a velocity that could pitch up or down `AudioBufferSourceNode`s connected downstream. This feature was not clearly specified and had a number of issues, so it was removed from the specification. + **/ function setVelocity( x : Float, y : Float, z : Float ) : Void; } \ No newline at end of file diff --git a/std/js/html/audio/PanningModelType.hx b/std/js/html/audio/PanningModelType.hx index e1b04117..790ef038 100644 --- a/std/js/html/audio/PanningModelType.hx +++ b/std/js/html/audio/PanningModelType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PannerNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\PannerNode.webidl. Do not edit! package js.html.audio; diff --git a/std/js/html/audio/PeriodicWave.hx b/std/js/html/audio/PeriodicWave.hx index a166b631..e3f8421e 100644 --- a/std/js/html/audio/PeriodicWave.hx +++ b/std/js/html/audio/PeriodicWave.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/PeriodicWave.webidl line 13:0. Do not edit! +// This file is generated from mozilla\PeriodicWave.webidl. Do not edit! package js.html.audio; +/** + `PeriodicWave` has no inputs or outputs; it is used to create custom oscillators via `OscillatorNode.setPeriodicWave`. The `PeriodicWave` itself is created/returned by `AudioContext.createPeriodicWave`. + + Documentation [PeriodicWave](https://developer.mozilla.org/en-US/docs/Web/API/PeriodicWave) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/PeriodicWave$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("PeriodicWave") extern class PeriodicWave { diff --git a/std/js/html/audio/ScriptProcessorNode.hx b/std/js/html/audio/ScriptProcessorNode.hx index 5b36f49e..1141f09e 100644 --- a/std/js/html/audio/ScriptProcessorNode.hx +++ b/std/js/html/audio/ScriptProcessorNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,27 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/ScriptProcessorNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\ScriptProcessorNode.webidl. Do not edit! package js.html.audio; +/** + Documentation [ScriptProcessorNode](https://developer.mozilla.org/en-US/docs/Web/API/ScriptProcessorNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ScriptProcessorNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("ScriptProcessorNode") extern class ScriptProcessorNode extends AudioNode { + + /** + Represents the `EventHandler` to be called. + **/ var onaudioprocess : haxe.Constraints.Function; + + /** + Returns an integer representing both the input and output buffer size. Its value can be a power of 2 value in the range `256`–`16384`. + **/ var bufferSize(default,null) : Int; } \ No newline at end of file diff --git a/std/js/html/audio/StereoPannerNode.hx b/std/js/html/audio/StereoPannerNode.hx index ff7df9b2..09b97558 100644 --- a/std/js/html/audio/StereoPannerNode.hx +++ b/std/js/html/audio/StereoPannerNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/StereoPannerNode.webidl line 13:0. Do not edit! +// This file is generated from mozilla\StereoPannerNode.webidl. Do not edit! package js.html.audio; +/** + The `pan` property takes a unitless value between `-1` (full left pan) and `1` (full right pan). This interface was introduced as a much simpler way to apply a simple panning effect than having to use a full `PannerNode`. + + Documentation [StereoPannerNode](https://developer.mozilla.org/en-US/docs/Web/API/StereoPannerNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/StereoPannerNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("StereoPannerNode") extern class StereoPannerNode extends AudioNode { + + /** + Is an a-rate `AudioParam` representing the amount of panning to apply. + **/ var pan(default,null) : AudioParam; } \ No newline at end of file diff --git a/std/js/html/audio/WaveShaperNode.hx b/std/js/html/audio/WaveShaperNode.hx index ab270173..87d41e50 100644 --- a/std/js/html/audio/WaveShaperNode.hx +++ b/std/js/html/audio/WaveShaperNode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WaveShaperNode.webidl line 19:0. Do not edit! +// This file is generated from mozilla\WaveShaperNode.webidl. Do not edit! package js.html.audio; +/** + A `WaveShaperNode` always has exactly one input and one output. + + Documentation [WaveShaperNode](https://developer.mozilla.org/en-US/docs/Web/API/WaveShaperNode) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WaveShaperNode$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WaveShaperNode") extern class WaveShaperNode extends AudioNode { + + /** + Is a `Float32Array` of numbers describing the distortion to apply. + **/ var curve : js.html.Float32Array; + + /** + Is an enumerated value indicating if oversampling must be used. Oversampling is a technique for creating more samples (up-sampling) before applying the distortion effect to the audio signal. + **/ var oversample : OverSampleType; } \ No newline at end of file diff --git a/std/js/html/compat/ArrayBuffer.hx b/std/js/html/compat/ArrayBuffer.hx index e31f754d..1a152faf 100644 --- a/std/js/html/compat/ArrayBuffer.hx +++ b/std/js/html/compat/ArrayBuffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,12 +21,13 @@ */ package js.html.compat; -@:keep +#if !nodejs +@:ifFeature("js.html.ArrayBuffer.*") class ArrayBuffer { public var byteLength : Int; var a : Array; - + public function new( ?a : Dynamic ) { if( Std.is(a,Array) ) { this.a = a; @@ -39,21 +40,22 @@ class ArrayBuffer { byteLength = len; } } - + public function slice(begin,?end) { return new ArrayBuffer(a.slice(begin,end)); } - + static function sliceImpl(begin,?end) { - var u = new js.html.Uint8Array(untyped __js__('this'), begin, end == null ? null : end - begin); - var result = new js.html.ArrayBuffer(u.byteLength); - var resultArray = new js.html.Uint8Array(result); + var u = new js.html.Uint8Array(js.Lib.nativeThis, begin, end == null ? null : end - begin); + var result = new js.html.ArrayBuffer(u.byteLength); + var resultArray = new js.html.Uint8Array(result); resultArray.set(u); - return result; + return result; } static function __init__() untyped { var ArrayBuffer = js.Lib.global.ArrayBuffer || js.html.compat.ArrayBuffer; if( ArrayBuffer.prototype.slice == null ) ArrayBuffer.prototype.slice = sliceImpl; // IE10 } -} \ No newline at end of file +} +#end \ No newline at end of file diff --git a/std/js/html/compat/DataView.hx b/std/js/html/compat/DataView.hx index 474fc672..df108933 100644 --- a/std/js/html/compat/DataView.hx +++ b/std/js/html/compat/DataView.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,9 +20,11 @@ * DEALINGS IN THE SOFTWARE. */ package js.html.compat; + +#if !nodejs import haxe.io.Error; -@:keep +@:ifFeature("js.html.DataView.*") @:access(js.html.compat.ArrayBuffer) class DataView { @@ -30,12 +32,19 @@ class DataView { var offset : Int; var length : Int; + public var byteLength(default,null):Int; + public var byteOffset(default,null):Int; + public var buffer(default,null):ArrayBuffer; + public function new( buffer : ArrayBuffer, ?byteOffset : Int, ?byteLength : Int ) : Void { this.buf = buffer; this.offset = byteOffset == null ? 0 : byteOffset; this.length = byteLength == null ? buffer.byteLength - this.offset : byteLength; if( offset < 0 || length < 0 || offset+length > buffer.byteLength ) throw OutsideBounds; + this.byteLength = length; + this.byteOffset = offset; + this.buffer = buf; } public function getInt8( byteOffset : Int ) : Int { @@ -141,4 +150,5 @@ class DataView { var DataView = untyped js.Lib.global.DataView || js.html.compat.DataView; } -} \ No newline at end of file +} +#end \ No newline at end of file diff --git a/std/js/html/compat/Float32Array.hx b/std/js/html/compat/Float32Array.hx index 4e4de9a9..913ec49b 100644 --- a/std/js/html/compat/Float32Array.hx +++ b/std/js/html/compat/Float32Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,7 +21,10 @@ */ package js.html.compat; -@:keep +#if !nodejs +import js.Lib.nativeThis; + +@:ifFeature("js.html.Float32Array.*") class Float32Array { static var BYTES_PER_ELEMENT = 4; @@ -44,7 +47,7 @@ class Float32Array { arr = []; // decode buffer for( i in 0...length ) { - var val = untyped buffer.a[offset++] | (buffer.a[offset++] << 8) | (buffer.a[offset++] << 16) | (buffer.a[offset++] << 24); + var val = untyped buffer.a[offset++] | (buffer.a[offset++] << 8) | (buffer.a[offset++] << 16) | (buffer.a[offset++] << 24); arr.push(haxe.io.FPHelper.i32ToFloat(val)); } untyped { @@ -78,26 +81,24 @@ class Float32Array { } static function _set( ?arg : Dynamic, ?offset : Int ) { - var t : Dynamic = untyped __js__("this"); if( Std.is(arg.buffer,ArrayBuffer) ) { var a : Array = arg; - if( arg.byteLength + offset > t.byteLength ) + if( arg.byteLength + offset > nativeThis.byteLength ) throw "set() outside of range"; for( i in 0...arg.byteLength ) - t[i + offset] = a[i]; + nativeThis[i + offset] = a[i]; } else if( Std.is(arg,Array) ) { var a : Array = arg; - if( a.length + offset > t.byteLength ) + if( a.length + offset > nativeThis.byteLength ) throw "set() outside of range"; for( i in 0...a.length ) - t[i + offset] = a[i]; + nativeThis[i + offset] = a[i]; } else throw "TODO"; } static function _subarray( start : Int, ?end : Int ) { - var t : Dynamic = untyped __js__("this"); - var a = _new(t.slice(start,end)); + var a = _new(nativeThis.slice(start,end)); a.byteOffset = start * 4; return a; } @@ -106,4 +107,5 @@ class Float32Array { var Float32Array = untyped js.Lib.global.Float32Array || _new; } -} \ No newline at end of file +} +#end \ No newline at end of file diff --git a/std/js/html/compat/Float64Array.hx b/std/js/html/compat/Float64Array.hx index 6d039935..2873f8d6 100644 --- a/std/js/html/compat/Float64Array.hx +++ b/std/js/html/compat/Float64Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,7 +21,10 @@ */ package js.html.compat; -@:keep +#if !nodejs +import js.Lib.nativeThis; + +@:ifFeature("js.html.Float64Array.*") class Float64Array { static var BYTES_PER_ELEMENT = 8; @@ -85,26 +88,24 @@ class Float64Array { } static function _set( ?arg : Dynamic, ?offset : Int ) { - var t : Dynamic = untyped __js__("this"); if( Std.is(arg.buffer,ArrayBuffer) ) { var a : Array = arg; - if( arg.byteLength + offset > t.byteLength ) + if( arg.byteLength + offset > nativeThis.byteLength ) throw "set() outside of range"; for( i in 0...arg.byteLength ) - t[i + offset] = a[i]; + nativeThis[i + offset] = a[i]; } else if( Std.is(arg,Array) ) { var a : Array = arg; - if( a.length + offset > t.byteLength ) + if( a.length + offset > nativeThis.byteLength ) throw "set() outside of range"; for( i in 0...a.length ) - t[i + offset] = a[i]; + nativeThis[i + offset] = a[i]; } else throw "TODO"; } static function _subarray( start : Int, ?end : Int ) { - var t : Dynamic = untyped __js__("this"); - var a = _new(t.slice(start,end)); + var a = _new(nativeThis.slice(start,end)); a.byteOffset = start * 8; return a; } @@ -113,4 +114,5 @@ class Float64Array { var Float64Array = untyped js.Lib.global.Float64Array || (js.Lib.global.Float32Array ? 'notsupported' : null) || _new; } -} \ No newline at end of file +} +#end diff --git a/std/js/html/compat/Uint8Array.hx b/std/js/html/compat/Uint8Array.hx index 8af5cf7b..210434ae 100644 --- a/std/js/html/compat/Uint8Array.hx +++ b/std/js/html/compat/Uint8Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,7 +21,10 @@ */ package js.html.compat; -@:keep +#if !nodejs +import js.Lib.nativeThis; + +@:ifFeature("js.html.Uint8Array.*") class Uint8Array { static var BYTES_PER_ELEMENT = 1; @@ -69,26 +72,24 @@ class Uint8Array { } static function _set( ?arg : Dynamic, ?offset : Int ) { - var t : Dynamic = untyped __js__("this"); if( Std.is(arg.buffer,ArrayBuffer) ) { var a : Array = arg; - if( arg.byteLength + offset > t.byteLength ) + if( arg.byteLength + offset > nativeThis.byteLength ) throw "set() outside of range"; for( i in 0...arg.byteLength ) - t[i + offset] = a[i]; + nativeThis[i + offset] = a[i]; } else if( Std.is(arg,Array) ) { var a : Array = arg; - if( a.length + offset > t.byteLength ) + if( a.length + offset > nativeThis.byteLength ) throw "set() outside of range"; for( i in 0...a.length ) - t[i + offset] = a[i]; + nativeThis[i + offset] = a[i]; } else throw "TODO"; } static function _subarray( start : Int, ?end : Int ) { - var t : Dynamic = untyped __js__("this"); - var a = _new(t.slice(start,end)); + var a = _new(nativeThis.slice(start,end)); a.byteOffset = start; return a; } @@ -97,4 +98,5 @@ class Uint8Array { var Uint8Array = untyped js.Lib.global.Uint8Array || _new; } -} \ No newline at end of file +} +#end \ No newline at end of file diff --git a/std/js/html/idb/Cursor.hx b/std/js/html/idb/Cursor.hx index f748f494..5736f89b 100644 --- a/std/js/html/idb/Cursor.hx +++ b/std/js/html/idb/Cursor.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,21 +20,52 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBCursor.webidl line 17:0. Do not edit! +// This file is generated from mozilla\IDBCursor.webidl. Do not edit! package js.html.idb; +/** + The `IDBCursor` interface of the IndexedDB API represents a cursor for traversing or iterating over multiple records in a database. + + Documentation [IDBCursor](https://developer.mozilla.org/en-US/docs/Web/API/IDBCursor) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/IDBCursor$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("IDBCursor") extern class Cursor { + + /** + Returns the `IDBObjectStore` or `IDBIndex` that the cursor is iterating. This function never returns null or throws an exception, even if the cursor is currently being iterated, has iterated past its end, or its transaction is not active. + **/ var source(default,null) : haxe.extern.EitherType; + + /** + Returns the direction of traversal of the cursor. See Constants for possible values. + **/ var direction(default,null) : CursorDirection; + + /** + Returns the key for the record at the cursor's position. If the cursor is outside its range, this is set to `undefined`. The cursor's key can be any data type. + **/ var key(default,null) : Dynamic; + + /** + Returns the cursor's current effective primary key. If the cursor is currently being iterated or has iterated outside its range, this is set to `undefined`. The cursor's primary key can be any data type. + **/ var primaryKey(default,null) : Dynamic; /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, and, in a separate thread, updates the value at the current position of the cursor in the object store. This can be used to update specific records. + **/ function update( value : Dynamic ) : Request; /** @throws DOMError */ + + /** + Sets the number times a cursor should move its position forward. + **/ function advance( count : Int ) : Void; /** @throws DOMError */ @:native("continue") diff --git a/std/js/html/idb/CursorDirection.hx b/std/js/html/idb/CursorDirection.hx index 6f90f9e8..84bfdf89 100644 --- a/std/js/html/idb/CursorDirection.hx +++ b/std/js/html/idb/CursorDirection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBCursor.webidl line 10:0. Do not edit! +// This file is generated from mozilla\IDBCursor.webidl. Do not edit! package js.html.idb; diff --git a/std/js/html/idb/CursorWithValue.hx b/std/js/html/idb/CursorWithValue.hx index 53dca7c0..e0aa2a49 100644 --- a/std/js/html/idb/CursorWithValue.hx +++ b/std/js/html/idb/CursorWithValue.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,22 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBCursor.webidl line 41:0. Do not edit! +// This file is generated from mozilla\IDBCursor.webidl. Do not edit! package js.html.idb; +/** + Documentation [IDBCursorWithValue](https://developer.mozilla.org/en-US/docs/Web/API/IDBCursorWithValue) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/IDBCursorWithValue$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("IDBCursorWithValue") extern class CursorWithValue extends Cursor { + + /** + Returns the value of the current cursor. + **/ var value(default,null) : Dynamic; } \ No newline at end of file diff --git a/std/js/html/idb/Database.hx b/std/js/html/idb/Database.hx index 89aba510..a08091f4 100644 --- a/std/js/html/idb/Database.hx +++ b/std/js/html/idb/Database.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,27 +20,75 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBDatabase.webidl line 13:0. Do not edit! +// This file is generated from mozilla\IDBDatabase.webidl. Do not edit! package js.html.idb; +/** + Inherits from: EventTarget + + Documentation [IDBDatabase](https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("IDBDatabase") extern class Database extends js.html.EventTarget { + + /** + A `DOMString` that contains the name of the connected database. + **/ var name(default,null) : String; + + /** + A 64-bit integer that contains the version of the connected database. When a database is first created, this attribute is an empty string. + **/ var version(default,null) : Int; + + /** + A `DOMStringList` that contains a list of the names of the object stores currently in the connected database. + **/ var objectStoreNames(default,null) : js.html.DOMStringList; + + /** + Fires when access of the database is aborted. + **/ var onabort : haxe.Constraints.Function; + + /** + Fires when access to the database fails. + **/ var onerror : haxe.Constraints.Function; + + /** + + Fires when a database structure change (`IDBOpenDBRequest.onupgradeneeded` event or` ``IDBFactory.deleteDatabase()` was requested elsewhere (most probably in another window/tab on the same computer). This is different from the version change transaction (see `IDBVersionChangeEvent`), but it is related. + + **/ var onversionchange : haxe.Constraints.Function; /** @throws DOMError */ + + /** + Creates and returns a new object store or index. + **/ function createObjectStore( name : String, ?optionalParameters : ObjectStoreParameters ) : ObjectStore; /** @throws DOMError */ + + /** + Destroys the object store with the given name in the connected database, along with any indexes that reference it. + **/ function deleteObjectStore( name : String ) : Void; /** @throws DOMError */ - @:overload( function( storeName : String, ?mode : TransactionMode = "readonly" ) : Transaction {} ) - function transaction( storeNames : Array, ?mode : TransactionMode = "readonly" ) : Transaction; + + /** + Immediately returns a transaction object (`IDBTransaction`) containing the `IDBTransaction.objectStore` method, which you can use to access your object store. Runs in a separate thread. + **/ + function transaction( storeNames : haxe.extern.EitherType>, ?mode : TransactionMode = "readonly" ) : Transaction; + + /** + Returns immediately and closes the connection to a database in a separate thread. + **/ function close() : Void; /** @throws DOMError */ function createMutableFile( name : String, ?type : String ) : Request; diff --git a/std/js/html/idb/Factory.hx b/std/js/html/idb/Factory.hx index 3fa168f8..df459eba 100644 --- a/std/js/html/idb/Factory.hx +++ b/std/js/html/idb/Factory.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBFactory.webidl line 26:0. Do not edit! +// This file is generated from mozilla\IDBFactory.webidl. Do not edit! package js.html.idb; +/** + In the following code snippet, we make a request to open a database, and include handlers for the success and error cases. For a full working example, see our To-do Notifications app (view example live.) + + Documentation [IDBFactory](https://developer.mozilla.org/en-US/docs/Web/API/IDBFactory) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/IDBFactory$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("IDBFactory") extern class Factory { diff --git a/std/js/html/idb/FileHandle.hx b/std/js/html/idb/FileHandle.hx index ad9736ac..a5674814 100644 --- a/std/js/html/idb/FileHandle.hx +++ b/std/js/html/idb/FileHandle.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBFileHandle.webidl line 11:0. Do not edit! +// This file is generated from mozilla\IDBFileHandle.webidl. Do not edit! package js.html.idb; @@ -43,13 +43,9 @@ extern class FileHandle extends js.html.EventTarget /** @throws DOMError */ function readAsText( size : Int, ?encoding : String ) : FileRequest; /** @throws DOMError */ - @:overload( function( value : js.html.ArrayBuffer ) : FileRequest {} ) - @:overload( function( value : js.html.Blob ) : FileRequest {} ) - function write( value : String ) : FileRequest; + function write( value : haxe.extern.EitherType>> ) : FileRequest; /** @throws DOMError */ - @:overload( function( value : js.html.ArrayBuffer ) : FileRequest {} ) - @:overload( function( value : js.html.Blob ) : FileRequest {} ) - function append( value : String ) : FileRequest; + function append( value : haxe.extern.EitherType>> ) : FileRequest; /** @throws DOMError */ function truncate( ?size : Int ) : FileRequest; /** @throws DOMError */ diff --git a/std/js/html/idb/FileMetadataParameters.hx b/std/js/html/idb/FileMetadataParameters.hx index 6d680e9b..c5c787b9 100644 --- a/std/js/html/idb/FileMetadataParameters.hx +++ b/std/js/html/idb/FileMetadataParameters.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBFileHandle.webidl line 5:0. Do not edit! +// This file is generated from mozilla\IDBFileHandle.webidl. Do not edit! package js.html.idb; diff --git a/std/js/html/idb/FileRequest.hx b/std/js/html/idb/FileRequest.hx index 04f0eddb..a4216bfd 100644 --- a/std/js/html/idb/FileRequest.hx +++ b/std/js/html/idb/FileRequest.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBFileRequest.webidl line 7:0. Do not edit! +// This file is generated from mozilla\IDBFileRequest.webidl. Do not edit! package js.html.idb; diff --git a/std/js/html/idb/Index.hx b/std/js/html/idb/Index.hx index 0354df1a..9f34b9c3 100644 --- a/std/js/html/idb/Index.hx +++ b/std/js/html/idb/Index.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,27 +20,86 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBIndex.webidl line 15:0. Do not edit! +// This file is generated from mozilla\IDBIndex.webidl. Do not edit! package js.html.idb; +/** + `IDBIndex` interface of the IndexedDB API provides asynchronous access to an index in a database. An index is a kind of object store for looking up records in another object store, called the referenced object store. You use this interface to retrieve data. + + Documentation [IDBIndex](https://developer.mozilla.org/en-US/docs/Web/API/IDBIndex) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/IDBIndex$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("IDBIndex") extern class Index { + + /** + The name of this index. + **/ var name(default,null) : String; + + /** + The name of the object store referenced by this index. + **/ var objectStore(default,null) : ObjectStore; + + /** + The key path of this index. If null, this index is not auto-populated. + **/ var keyPath(default,null) : Dynamic; + + /** + Affects how the index behaves when the result of evaluating the index's key path yields an array. If `true`, there is one record in the index for each item in an array of keys. If `false`, then there is one record for each key that is an array. + **/ var multiEntry(default,null) : Bool; + + /** + If `true`, this index does not allow duplicate values for a key. + **/ var unique(default,null) : Bool; /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, and, in a separate thread, creates a cursor over the specified key range. + **/ function openCursor( ?range : Dynamic, ?direction : CursorDirection = "next" ) : Request; /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, and, in a separate thread, creates a cursor over the specified key range, as arranged by this index. + **/ function openKeyCursor( ?range : Dynamic, ?direction : CursorDirection = "next" ) : Request; /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, and, in a separate thread, finds either the value in the referenced object store that corresponds to the given key or the first corresponding value, if `key` is an `IDBKeyRange`. + **/ function get( key : Dynamic ) : Request; /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, and, in a separate thread, finds either the given key or the primary key, if `key` is an `IDBKeyRange`. + **/ function getKey( key : Dynamic ) : Request; /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, and in a separate thread, returns the number of records within a key range. + **/ function count( ?key : Dynamic ) : Request; + /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, in a separate thread, finds all matching values in the referenced object store that correspond to the given key or are in range, if `key` is an `IDBKeyRange`. + **/ + function getAll( ?key : Dynamic, ?limit : Int ) : Request; + /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, in a separate thread, finds all matching keys in the referenced object store that correspond to the given key or are in range, if `key` is an `IDBKeyRange`. + **/ + function getAllKeys( ?key : Dynamic, ?limit : Int ) : Request; } \ No newline at end of file diff --git a/std/js/html/idb/IndexParameters.hx b/std/js/html/idb/IndexParameters.hx index 3d14c444..42726a69 100644 --- a/std/js/html/idb/IndexParameters.hx +++ b/std/js/html/idb/IndexParameters.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,12 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBIndex.webidl line 10:0. Do not edit! +// This file is generated from mozilla\IDBIndex.webidl. Do not edit! package js.html.idb; typedef IndexParameters = { + @:optional var locale : String; @:optional var multiEntry : Bool; @:optional var unique : Bool; } \ No newline at end of file diff --git a/std/js/html/idb/KeyRange.hx b/std/js/html/idb/KeyRange.hx index 70148fbe..d248aa70 100644 --- a/std/js/html/idb/KeyRange.hx +++ b/std/js/html/idb/KeyRange.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,24 +20,69 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBKeyRange.webidl line 12:0. Do not edit! +// This file is generated from mozilla\IDBKeyRange.webidl. Do not edit! package js.html.idb; +/** + A key range can be a single value or a range with upper and lower bounds or endpoints. If the key range has both upper and lower bounds, then it is bounded; if it has no bounds, it is unbounded. A bounded key range can either be open (the endpoints are excluded) or closed (the endpoints are included). To retrieve all keys within a certain range, you can use the following code constructs: + + Documentation [IDBKeyRange](https://developer.mozilla.org/en-US/docs/Web/API/IDBKeyRange) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/IDBKeyRange$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("IDBKeyRange") extern class KeyRange { /** @throws DOMError */ - static function only( value : Dynamic ) : KeyRange; + static + /** + Creates a new key range containing a single value. + **/ + function only( value : Dynamic ) : KeyRange; /** @throws DOMError */ - static function lowerBound( lower : Dynamic, ?open : Bool = false ) : KeyRange; + static + /** + Creates a new key range with only a lower bound. + **/ + function lowerBound( lower : Dynamic, ?open : Bool = false ) : KeyRange; /** @throws DOMError */ - static function upperBound( upper : Dynamic, ?open : Bool = false ) : KeyRange; + static + /** + Creates a new upper-bound key range. + **/ + function upperBound( upper : Dynamic, ?open : Bool = false ) : KeyRange; /** @throws DOMError */ - static function bound( lower : Dynamic, upper : Dynamic, ?lowerOpen : Bool = false, ?upperOpen : Bool = false ) : KeyRange; + static + /** + Creates a new key range with upper and lower bounds. + **/ + function bound( lower : Dynamic, upper : Dynamic, ?lowerOpen : Bool = false, ?upperOpen : Bool = false ) : KeyRange; + + /** + Lower bound of the key range. + **/ var lower(default,null) : Dynamic; + + /** + Upper bound of the key range. + **/ var upper(default,null) : Dynamic; + + /** + Returns false if the lower-bound value is included in the key range. + **/ var lowerOpen(default,null) : Bool; + + /** + Returns false if the upper-bound value is included in the key range. + **/ var upperOpen(default,null) : Bool; + /** @throws DOMError */ + + /** + Returns a boolean indicating whether a specified key is inside the key range. + **/ + function includes( key : Dynamic ) : Bool; } \ No newline at end of file diff --git a/std/js/html/idb/MutableFile.hx b/std/js/html/idb/MutableFile.hx index d506caf0..83045c81 100644 --- a/std/js/html/idb/MutableFile.hx +++ b/std/js/html/idb/MutableFile.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBMutableFile.webidl line 6:0. Do not edit! +// This file is generated from mozilla\IDBMutableFile.webidl. Do not edit! package js.html.idb; +/** + The `IDBMutableFile` interface provides access in read or write mode to a file, dealing with all the necessary locks. + + Documentation [IDBMutableFile](https://developer.mozilla.org/en-US/docs/Web/API/IDBMutableFile) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/IDBMutableFile$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("IDBMutableFile") extern class MutableFile extends js.html.EventTarget { diff --git a/std/js/html/idb/ObjectStore.hx b/std/js/html/idb/ObjectStore.hx index 67cfe9e1..80efefbf 100644 --- a/std/js/html/idb/ObjectStore.hx +++ b/std/js/html/idb/ObjectStore.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,39 +20,120 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBObjectStore.webidl line 15:0. Do not edit! +// This file is generated from mozilla\IDBObjectStore.webidl. Do not edit! package js.html.idb; +/** + This example shows a variety of different uses of object stores, from updating the data structure with `IDBObjectStore.createIndex` inside an `onupgradeneeded` function, to adding a new item to our object store with `IDBObjectStore.add`. For a full working example, see our To-do Notifications app (view example live.) + + Documentation [IDBObjectStore](https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("IDBObjectStore") extern class ObjectStore { + + /** + The name of this object store. + **/ var name(default,null) : String; + + /** + The key path of this object store. If this attribute is `null`, the application must provide a key for each modification operation. + **/ var keyPath(default,null) : Dynamic; + + /** + A list of the names of indexes on objects in this object store. + **/ var indexNames(default,null) : js.html.DOMStringList; + + /** + The `IDBTransaction` object to which this object store belongs. + **/ var transaction(default,null) : Transaction; + + /** + The value of the auto increment flag for this object store. + **/ var autoIncrement(default,null) : Bool; /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, and, in a separate thread, creates a structured clone of the `value`, and stores the cloned value in the object store. This is for updating existing records in an object store when the transaction's mode is `readwrite`. + **/ function put( value : Dynamic, ?key : Dynamic ) : Request; /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, and, in a separate thread, creates a structured clone of the `value`, and stores the cloned value in the object store. This is for adding new records to an object store. + **/ function add( value : Dynamic, ?key : Dynamic ) : Request; /** @throws DOMError */ @:native("delete") function delete_( key : Dynamic ) : Request; /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, and, in a separate thread, returns the store object store selected by the specified key. This is for retrieving specific records from an object store. + **/ function get( key : Dynamic ) : Request; /** @throws DOMError */ + + /** + Creates and immediately returns an `IDBRequest` object, and clears this object store in a separate thread. This is for deleting all current records out of an object store. + **/ function clear() : Request; /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, and, in a separate thread, returns a new `IDBCursorWithValue` object. Used for iterating through an object store by primary key with a cursor. + **/ function openCursor( ?range : Dynamic, ?direction : CursorDirection = "next" ) : Request; /** @throws DOMError */ @:overload( function( name : String, keyPath : String, ?optionalParameters : IndexParameters ) : Index {} ) + + /** + Creates a new index during a version upgrade, returning a new `IDBIndex` object in the connected database. + **/ function createIndex( name : String, keyPath : Array, ?optionalParameters : IndexParameters ) : Index; /** @throws DOMError */ + + /** + Opens an index from this object store after which it can, for example, be used to return a sequence of records sorted by that index using a cursor. + **/ function index( name : String ) : Index; /** @throws DOMError */ + + /** + Destroys the specified index in the connected database, used during a version upgrade. + **/ function deleteIndex( indexName : String ) : Void; /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, and, in a separate thread, returns the total number of records that match the provided key or `IDBKeyRange`. If no arguments are provided, it returns the total number of records in the store. + **/ function count( ?key : Dynamic ) : Request; + /** @throws DOMError */ + + /** + Returns an `IDBRequest` object retrieves all objects in the object store matching the specified parameter or all objects in the store if no parameters are given. + **/ + function getAll( ?key : Dynamic, ?limit : Int ) : Request; + /** @throws DOMError */ + + /** + Returns an `IDBRequest` object retrieves record keys for all objects in the object store matching the specified parameter or all objects in the store if no parameters are given. + **/ + function getAllKeys( ?key : Dynamic, ?limit : Int ) : Request; + /** @throws DOMError */ + + /** + Returns an `IDBRequest` object, and, in a separate thread, returns a new `IDBCursorWithValue`. Used for iterating through an object store with a key. + **/ + function openKeyCursor( ?range : Dynamic, ?direction : CursorDirection = "next" ) : Request; } \ No newline at end of file diff --git a/std/js/html/idb/ObjectStoreParameters.hx b/std/js/html/idb/ObjectStoreParameters.hx index a299bc42..c475bdbb 100644 --- a/std/js/html/idb/ObjectStoreParameters.hx +++ b/std/js/html/idb/ObjectStoreParameters.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBObjectStore.webidl line 10:0. Do not edit! +// This file is generated from mozilla\IDBObjectStore.webidl. Do not edit! package js.html.idb; diff --git a/std/js/html/idb/OpenDBOptions.hx b/std/js/html/idb/OpenDBOptions.hx index fec302f2..9024cd7b 100644 --- a/std/js/html/idb/OpenDBOptions.hx +++ b/std/js/html/idb/OpenDBOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBFactory.webidl line 15:0. Do not edit! +// This file is generated from mozilla\IDBFactory.webidl. Do not edit! package js.html.idb; diff --git a/std/js/html/idb/OpenDBRequest.hx b/std/js/html/idb/OpenDBRequest.hx index ab224796..60216893 100644 --- a/std/js/html/idb/OpenDBRequest.hx +++ b/std/js/html/idb/OpenDBRequest.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBOpenDBRequest.webidl line 10:0. Do not edit! +// This file is generated from mozilla\IDBOpenDBRequest.webidl. Do not edit! package js.html.idb; +/** + No methods, but inherits methods from its parents `IDBRequest` and `EventTarget`. + + Documentation [IDBOpenDBRequest](https://developer.mozilla.org/en-US/docs/Web/API/IDBOpenDBRequest) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/IDBOpenDBRequest$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("IDBOpenDBRequest") extern class OpenDBRequest extends Request { + + /** + The event handler for the blocked event. This event is triggered when the `upgradeneeded` event should be triggered because of a version change but the database is still in use (i.e. not closed) somewhere, even after the `versionchange` event was sent. + **/ var onblocked : haxe.Constraints.Function; + + /** + The event handler for the `upgradeneeded` event, fired when a database of a bigger version number than the existing stored database is loaded. + **/ var onupgradeneeded : haxe.Constraints.Function; } \ No newline at end of file diff --git a/std/js/html/idb/Request.hx b/std/js/html/idb/Request.hx index 2ad5f897..c2a8e9c4 100644 --- a/std/js/html/idb/Request.hx +++ b/std/js/html/idb/Request.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,19 +20,56 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBRequest.webidl line 16:0. Do not edit! +// This file is generated from mozilla\IDBRequest.webidl. Do not edit! package js.html.idb; +/** + The request object does not initially contain any information about the result of the operation, but once information becomes available, an event is fired on the request, and the information becomes available through the properties of the `IDBRequest` instance. + + Documentation [IDBRequest](https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("IDBRequest") extern class Request extends js.html.EventTarget { + + /** + + Returns the result of the request. If the the request failed and the result is not available, an InvalidStateError exception is thrown. + + **/ var result(default,null) : Dynamic; + + /** + Returns an error in the event of an unsuccessful request, indicating what went wrong. + **/ var error(default,null) : js.html.DOMError; + + /** + The source of the request, such as an `IDBIndex` or an `IDBObjectStore`. If no source exists (such as when calling `IDBFactory.open`), it returns null. + **/ var source(default,null) : haxe.extern.EitherType>; + + /** + The transaction for the request. This property can be null for certain requests, for example those returned from `IDBFactory.open` unless an upgrade is needed. (You're just connecting to a database, so there is no transaction to return). + **/ var transaction(default,null) : Transaction; + + /** + The state of the request. Every request starts in the `pending` state. The state changes to `done` when the request completes successfully or when an error occurs. + **/ var readyState(default,null) : RequestReadyState; + + /** + The event handler for the success event. + **/ var onsuccess : haxe.Constraints.Function; + + /** + The event handler for the error event. + **/ var onerror : haxe.Constraints.Function; } \ No newline at end of file diff --git a/std/js/html/idb/RequestReadyState.hx b/std/js/html/idb/RequestReadyState.hx index c90557a3..94a23a93 100644 --- a/std/js/html/idb/RequestReadyState.hx +++ b/std/js/html/idb/RequestReadyState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBRequest.webidl line 11:0. Do not edit! +// This file is generated from mozilla\IDBRequest.webidl. Do not edit! package js.html.idb; diff --git a/std/js/html/idb/Transaction.hx b/std/js/html/idb/Transaction.hx index a365f363..9a06b524 100644 --- a/std/js/html/idb/Transaction.hx +++ b/std/js/html/idb/Transaction.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,19 +20,54 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBTransaction.webidl line 17:0. Do not edit! +// This file is generated from mozilla\IDBTransaction.webidl. Do not edit! package js.html.idb; +/** + Note that as of Firefox 40, IndexedDB transactions have relaxed durability guarantees to increase performance (see bug 1112702.) Previously in a `readwrite` transaction `IDBTransaction.oncomplete` was fired only when all data was guaranteed to have been flushed to disk. In Firefox 40+ the `complete` event is fired after the OS has been told to write the data but potentially before that data has actually been flushed to disk. The `complete` event may thus be delivered quicker than before, however, there exists a small chance that the entire transaction will be lost if the OS crashes or there is a loss of system power before the data is flushed to disk. Since such catastrophic events are rare most consumers should not need to concern themselves further. + + Documentation [IDBTransaction](https://developer.mozilla.org/en-US/docs/Web/API/IDBTransaction) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/IDBTransaction$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("IDBTransaction") extern class Transaction extends js.html.EventTarget { + + /** + The mode for isolating access to data in the object stores that are in the scope of the transaction. For possible values, see the Constants section below. The default value is `readonly`. + **/ var mode(default,null) : TransactionMode; + + /** + The database connection with which this transaction is associated. + **/ var db(default,null) : Database; + + /** + Returns one of several types of error when there is an unsuccessful transaction. This property is `null` if the transaction is not finished, is finished and successfully committed, or was aborted with `IDBTransaction.abort` function. + **/ var error(default,null) : js.html.DOMError; + + /** + The event handler for the `abort` event, fired when the transaction is aborted. + **/ var onabort : haxe.Constraints.Function; + + /** + The event handler for the `complete` event, thrown when the transaction completes successfully. + **/ var oncomplete : haxe.Constraints.Function; + + /** + The event handler for the `error` event, thrown when the transaction fails to complete. + **/ var onerror : haxe.Constraints.Function; + + /** + Returns a `DOMStringList` of the names of `IDBObjectStore` objects. + **/ var objectStoreNames(default,null) : js.html.DOMStringList; /** @throws DOMError */ diff --git a/std/js/html/idb/TransactionMode.hx b/std/js/html/idb/TransactionMode.hx index 86909828..dd9cc449 100644 --- a/std/js/html/idb/TransactionMode.hx +++ b/std/js/html/idb/TransactionMode.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBTransaction.webidl line 11:0. Do not edit! +// This file is generated from mozilla\IDBTransaction.webidl. Do not edit! package js.html.idb; @@ -28,5 +28,7 @@ package js.html.idb; { var READONLY = "readonly"; var READWRITE = "readwrite"; + var READWRITEFLUSH = "readwriteflush"; + var CLEANUP = "cleanup"; var VERSIONCHANGE = "versionchange"; } \ No newline at end of file diff --git a/std/js/html/idb/VersionChangeEvent.hx b/std/js/html/idb/VersionChangeEvent.hx index 36e06f4a..58ed0171 100644 --- a/std/js/html/idb/VersionChangeEvent.hx +++ b/std/js/html/idb/VersionChangeEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBVersionChangeEvent.webidl line 19:0. Do not edit! +// This file is generated from mozilla\IDBVersionChangeEvent.webidl. Do not edit! package js.html.idb; +/** + The `IDBVersionChangeEvent` interface of the IndexedDB API indicates that the version of the database has changed, as the result of an `IDBOpenDBRequest.onupgradeneeded` event handler function. + + Documentation [IDBVersionChangeEvent](https://developer.mozilla.org/en-US/docs/Web/API/IDBVersionChangeEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/IDBVersionChangeEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("IDBVersionChangeEvent") extern class VersionChangeEvent extends js.html.Event { diff --git a/std/js/html/idb/VersionChangeEventInit.hx b/std/js/html/idb/VersionChangeEventInit.hx index c3b8d676..a4118a4c 100644 --- a/std/js/html/idb/VersionChangeEventInit.hx +++ b/std/js/html/idb/VersionChangeEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/IDBVersionChangeEvent.webidl line 13:0. Do not edit! +// This file is generated from mozilla\IDBVersionChangeEvent.webidl. Do not edit! package js.html.idb; diff --git a/std/js/html/ClientRect.hx b/std/js/html/rtc/AnswerOptions.hx similarity index 84% rename from std/js/html/ClientRect.hx rename to std/js/html/rtc/AnswerOptions.hx index 0e6d432b..1b617c32 100644 --- a/std/js/html/ClientRect.hx +++ b/std/js/html/rtc/AnswerOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,8 +20,11 @@ * DEALINGS IN THE SOFTWARE. */ -package js.html; +// This file is generated from mozilla\RTCPeerConnection.webidl. Do not edit! -/** @deprecated Use DOMRect instead. */ -@:deprecated("ClientRect is deprecated, use DOMRect instead") -typedef ClientRect = DOMRect; +package js.html.rtc; + +typedef AnswerOptions = +{ + > OfferAnswerOptions, +} \ No newline at end of file diff --git a/std/js/html/rtc/Certificate.hx b/std/js/html/rtc/Certificate.hx new file mode 100644 index 00000000..d9f3e549 --- /dev/null +++ b/std/js/html/rtc/Certificate.hx @@ -0,0 +1,43 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\RTCCertificate.webidl. Do not edit! + +package js.html.rtc; + +/** + The interface of the the WebRTC API provides an object represents a certificate that an `RTCPeerConnection` uses to authenticate. + + Documentation [RTCCertificate](https://developer.mozilla.org/en-US/docs/Web/API/RTCCertificate) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/RTCCertificate$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("RTCCertificate") +extern class Certificate +{ + + /** + Returns the expiration date of the certificate. + **/ + var expires(default,null) : Int; + +} \ No newline at end of file diff --git a/std/js/html/rtc/Configuration.hx b/std/js/html/rtc/Configuration.hx index 58ffe2a8..45469db2 100644 --- a/std/js/html/rtc/Configuration.hx +++ b/std/js/html/rtc/Configuration.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,12 +20,15 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCConfiguration.webidl line 16:0. Do not edit! +// This file is generated from mozilla\RTCConfiguration.webidl. Do not edit! package js.html.rtc; typedef Configuration = { + @:optional var bundlePolicy : Dynamic/*MISSING RTCBundlePolicy*/; + @:optional var certificates : Array; @:optional var iceServers : Array; + @:optional var iceTransportPolicy : Dynamic/*MISSING RTCIceTransportPolicy*/; @:optional var peerIdentity : String; } \ No newline at end of file diff --git a/std/js/html/rtc/DataChannel.hx b/std/js/html/rtc/DataChannel.hx index 3b001463..8a9efae5 100644 --- a/std/js/html/rtc/DataChannel.hx +++ b/std/js/html/rtc/DataChannel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DataChannel.webidl line 18:0. Do not edit! +// This file is generated from mozilla\DataChannel.webidl. Do not edit! package js.html.rtc; @@ -31,10 +31,12 @@ extern class DataChannel extends js.html.EventTarget var reliable(default,null) : Bool; var readyState(default,null) : DataChannelState; var bufferedAmount(default,null) : Int; + var bufferedAmountLowThreshold : Int; var onopen : haxe.Constraints.Function; var onerror : haxe.Constraints.Function; var onclose : haxe.Constraints.Function; var onmessage : haxe.Constraints.Function; + var onbufferedamountlow : haxe.Constraints.Function; var binaryType : DataChannelType; var protocol(default,null) : String; var ordered(default,null) : Bool; diff --git a/std/js/html/rtc/DataChannelInit.hx b/std/js/html/rtc/DataChannelInit.hx index 8927a71f..0acae8c3 100644 --- a/std/js/html/rtc/DataChannelInit.hx +++ b/std/js/html/rtc/DataChannelInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCPeerConnection.webidl line 40:0. Do not edit! +// This file is generated from mozilla\RTCPeerConnection.webidl. Do not edit! package js.html.rtc; diff --git a/std/js/html/rtc/DataChannelState.hx b/std/js/html/rtc/DataChannelState.hx index 3850e379..6599b6a4 100644 --- a/std/js/html/rtc/DataChannelState.hx +++ b/std/js/html/rtc/DataChannelState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DataChannel.webidl line 5:0. Do not edit! +// This file is generated from mozilla\DataChannel.webidl. Do not edit! package js.html.rtc; diff --git a/std/js/html/rtc/DataChannelType.hx b/std/js/html/rtc/DataChannelType.hx index 165e854d..44d7c37a 100644 --- a/std/js/html/rtc/DataChannelType.hx +++ b/std/js/html/rtc/DataChannelType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/DataChannel.webidl line 12:0. Do not edit! +// This file is generated from mozilla\DataChannel.webidl. Do not edit! package js.html.rtc; diff --git a/std/js/html/rtc/IceCandidate.hx b/std/js/html/rtc/IceCandidate.hx index 9c9bc088..4a2a668a 100644 --- a/std/js/html/rtc/IceCandidate.hx +++ b/std/js/html/rtc/IceCandidate.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCIceCandidate.webidl line 19:0. Do not edit! +// This file is generated from mozilla\RTCIceCandidate.webidl. Do not edit! package js.html.rtc; +/** + The `RTCIceCandidate` interface of the the WebRTC API represents a candidate internet connectivity establishment (ICE) server for establishing an `RTCPeerConnection`. + + Documentation [RTCIceCandidate](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidate) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidate$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("RTCIceCandidate") extern class IceCandidate { + + /** + Returns a transport address for the candidate that can be used for connectivity checks. The format of this address is a `candidate-attribute` as defined in RTC 5245. + **/ var candidate : String; + + /** + If not `null`, this contains the identifier of the "media stream identification" (as defined in RFC 5888) for the media component this candidate is associated with. + **/ var sdpMid : String; + + /** + If not `null`, this indicates the index (starting at zero) of the media description (as defined in RFC 4566) in the SDP this candidate is associated with. + **/ var sdpMLineIndex : Int; /** @throws DOMError */ diff --git a/std/js/html/rtc/IceCandidateInit.hx b/std/js/html/rtc/IceCandidateInit.hx index b0c0b301..51ade567 100644 --- a/std/js/html/rtc/IceCandidateInit.hx +++ b/std/js/html/rtc/IceCandidateInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCIceCandidate.webidl line 10:0. Do not edit! +// This file is generated from mozilla\RTCIceCandidate.webidl. Do not edit! package js.html.rtc; diff --git a/std/js/html/rtc/IceConnectionState.hx b/std/js/html/rtc/IceConnectionState.hx index a1f283c8..41262506 100644 --- a/std/js/html/rtc/IceConnectionState.hx +++ b/std/js/html/rtc/IceConnectionState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCPeerConnection.webidl line 30:0. Do not edit! +// This file is generated from mozilla\RTCPeerConnection.webidl. Do not edit! package js.html.rtc; diff --git a/std/js/html/rtc/IceGatheringState.hx b/std/js/html/rtc/IceGatheringState.hx index d05864e6..6242db81 100644 --- a/std/js/html/rtc/IceGatheringState.hx +++ b/std/js/html/rtc/IceGatheringState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCPeerConnection.webidl line 24:0. Do not edit! +// This file is generated from mozilla\RTCPeerConnection.webidl. Do not edit! package js.html.rtc; diff --git a/std/js/html/rtc/IdentityAssertion.hx b/std/js/html/rtc/IdentityAssertion.hx index 4cca84e3..f834712b 100644 --- a/std/js/html/rtc/IdentityAssertion.hx +++ b/std/js/html/rtc/IdentityAssertion.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,12 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCIdentityAssertion.webidl line 13:0. Do not edit! +// This file is generated from mozilla\RTCIdentityAssertion.webidl. Do not edit! package js.html.rtc; -@:native("RTCIdentityAssertion") -extern class IdentityAssertion +typedef IdentityAssertion = { - var idp : String; - var name : String; - - /** @throws DOMError */ - function new( idp : String, name : String ) : Void; + @:optional var idp : String; + @:optional var name : String; } \ No newline at end of file diff --git a/std/js/html/rtc/IdentityAssertionResult.hx b/std/js/html/rtc/IdentityAssertionResult.hx new file mode 100644 index 00000000..780d0b87 --- /dev/null +++ b/std/js/html/rtc/IdentityAssertionResult.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\RTCIdentityProvider.webidl. Do not edit! + +package js.html.rtc; + +typedef IdentityAssertionResult = +{ + var assertion : String; + var idp : Dynamic/*MISSING RTCIdentityProviderDetails*/; +} \ No newline at end of file diff --git a/std/js/html/rtc/IdentityProvider.hx b/std/js/html/rtc/IdentityProvider.hx new file mode 100644 index 00000000..db38ecc7 --- /dev/null +++ b/std/js/html/rtc/IdentityProvider.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\RTCIdentityProvider.webidl. Do not edit! + +package js.html.rtc; + +@:native("RTCIdentityProvider") +extern class IdentityProvider +{ + function generateAssertion( contents : String, origin : String, ?usernameHint : String ) : Promise; + function validateAssertion( assertion : String, origin : String ) : Promise; +} \ No newline at end of file diff --git a/std/js/html/rtc/IdentityProviderRegistrar.hx b/std/js/html/rtc/IdentityProviderRegistrar.hx new file mode 100644 index 00000000..459adf2b --- /dev/null +++ b/std/js/html/rtc/IdentityProviderRegistrar.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\RTCIdentityProvider.webidl. Do not edit! + +package js.html.rtc; + +@:native("RTCIdentityProviderRegistrar") +extern class IdentityProviderRegistrar +{ + function register( idp : IdentityProvider ) : Void; +} \ No newline at end of file diff --git a/std/js/html/webgl/VertexArray.hx b/std/js/html/rtc/IdentityValidationResult.hx similarity index 82% rename from std/js/html/webgl/VertexArray.hx rename to std/js/html/rtc/IdentityValidationResult.hx index 9a91f1a0..d7e37494 100644 --- a/std/js/html/webgl/VertexArray.hx +++ b/std/js/html/rtc/IdentityValidationResult.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,12 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 67:0. Do not edit! +// This file is generated from mozilla\RTCIdentityProvider.webidl. Do not edit! -package js.html.webgl; +package js.html.rtc; -@:native("WebGLVertexArray") -extern class VertexArray +typedef IdentityValidationResult = { + var contents : String; + var identity : String; } \ No newline at end of file diff --git a/std/js/html/rtc/OfferAnswerOptions.hx b/std/js/html/rtc/OfferAnswerOptions.hx new file mode 100644 index 00000000..11ee52e7 --- /dev/null +++ b/std/js/html/rtc/OfferAnswerOptions.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\RTCPeerConnection.webidl. Do not edit! + +package js.html.rtc; + +typedef OfferAnswerOptions = +{ +} \ No newline at end of file diff --git a/std/js/html/rtc/OfferOptions.hx b/std/js/html/rtc/OfferOptions.hx index 2440fb05..0e1ea95a 100644 --- a/std/js/html/rtc/OfferOptions.hx +++ b/std/js/html/rtc/OfferOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,12 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCPeerConnection.webidl line 55:0. Do not edit! +// This file is generated from mozilla\RTCPeerConnection.webidl. Do not edit! package js.html.rtc; typedef OfferOptions = { + > OfferAnswerOptions, @:optional var mandatory : Dynamic/*MISSING DeprecatedRTCOfferOptionsSet*/; @:optional var offerToReceiveAudio : Int; @:optional var offerToReceiveVideo : Int; diff --git a/std/js/html/rtc/PeerConnection.hx b/std/js/html/rtc/PeerConnection.hx index f8569681..e51ddd8c 100644 --- a/std/js/html/rtc/PeerConnection.hx +++ b/std/js/html/rtc/PeerConnection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,45 +20,52 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCPeerConnection.webidl line 80:0. Do not edit! +// This file is generated from mozilla\RTCPeerConnection.webidl. Do not edit! package js.html.rtc; +/** + The `RTCPeerConnection` interface represents a WebRTC connection between the local computer and a remote peer. It provides methods to connect to a remote peer, maintain and monitor the connection, and close the connection once it's no longer needed. + + Documentation [RTCPeerConnection](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("RTCPeerConnection") extern class PeerConnection extends js.html.EventTarget { + /** @throws DOMError */ + static function generateCertificate( keygenAlgorithm : haxe.extern.EitherType ) : Promise; var localDescription(default,null) : SessionDescription; var remoteDescription(default,null) : SessionDescription; var signalingState(default,null) : SignalingState; + var canTrickleIceCandidates(default,null) : Bool; var iceGatheringState(default,null) : IceGatheringState; var iceConnectionState(default,null) : IceConnectionState; - var peerIdentity(default,null) : IdentityAssertion; + var peerIdentity(default,null) : Promise; + var idpLoginUrl(default,null) : String; var onnegotiationneeded : haxe.Constraints.Function; var onicecandidate : haxe.Constraints.Function; var onsignalingstatechange : haxe.Constraints.Function; var onaddstream : haxe.Constraints.Function; var onaddtrack : haxe.Constraints.Function; + var ontrack : haxe.Constraints.Function; var onremovestream : haxe.Constraints.Function; var oniceconnectionstatechange : haxe.Constraints.Function; var ondatachannel : haxe.Constraints.Function; - var onidentityresult : haxe.Constraints.Function; - var onpeeridentity : haxe.Constraints.Function; - var onidpassertionerror : haxe.Constraints.Function; - var onidpvalidationerror : haxe.Constraints.Function; /** @throws DOMError */ function new( ?configuration : Configuration, ?constraints : Dynamic ) : Void; function setIdentityProvider( provider : String, ?protocol : String, ?username : String ) : Void; - function getIdentityAssertion() : Void; + function getIdentityAssertion() : Promise; @:overload( function( ?options : OfferOptions ) : Promise {} ) function createOffer( successCallback : SessionDescription -> Void, failureCallback : js.html.DOMError -> Void, ?options : OfferOptions ) : Promise; - @:overload( function() : Promise {} ) + @:overload( function( ?options : AnswerOptions ) : Promise {} ) function createAnswer( successCallback : SessionDescription -> Void, failureCallback : js.html.DOMError -> Void ) : Promise; @:overload( function( description : SessionDescription ) : Promise {} ) function setLocalDescription( description : SessionDescription, successCallback : Void -> Void, failureCallback : js.html.DOMError -> Void ) : Promise; @:overload( function( description : SessionDescription ) : Promise {} ) function setRemoteDescription( description : SessionDescription, successCallback : Void -> Void, failureCallback : js.html.DOMError -> Void ) : Promise; - function updateIce( ?configuration : Configuration ) : Void; @:overload( function( candidate : IceCandidate ) : Promise {} ) function addIceCandidate( candidate : IceCandidate, successCallback : Void -> Void, failureCallback : js.html.DOMError -> Void ) : Promise; function getConfiguration() : Configuration; @@ -72,7 +79,7 @@ extern class PeerConnection extends js.html.EventTarget function getSenders() : Array; function getReceivers() : Array; function close() : Void; - @:overload( function( selector : js.html.MediaStreamTrack ) : Promise {} ) + @:overload( function( ?selector : js.html.MediaStreamTrack ) : Promise {} ) function getStats( selector : js.html.MediaStreamTrack, successCallback : StatsReport -> Void, failureCallback : js.html.DOMError -> Void ) : Promise; function createDataChannel( label : String, ?dataChannelDict : DataChannelInit ) : Dynamic/*MISSING RTCDataChannel*/; } \ No newline at end of file diff --git a/std/js/html/rtc/RtpParameters.hx b/std/js/html/rtc/RtpParameters.hx new file mode 100644 index 00000000..56577816 --- /dev/null +++ b/std/js/html/rtc/RtpParameters.hx @@ -0,0 +1,33 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\RTCRtpSender.webidl. Do not edit! + +package js.html.rtc; + +typedef RtpParameters = +{ + @:optional var codecs : Array; + @:optional var encodings : Array; + @:optional var headerExtensions : Array; + @:optional var rtcp : Dynamic/*MISSING RTCRtcpParameters*/; +} \ No newline at end of file diff --git a/std/js/html/rtc/RtpReceiver.hx b/std/js/html/rtc/RtpReceiver.hx index 73dcabf1..ee1e3ef1 100644 --- a/std/js/html/rtc/RtpReceiver.hx +++ b/std/js/html/rtc/RtpReceiver.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCRtpReceiver.webidl line 12:0. Do not edit! +// This file is generated from mozilla\RTCRtpReceiver.webidl. Do not edit! package js.html.rtc; diff --git a/std/js/html/rtc/RtpSender.hx b/std/js/html/rtc/RtpSender.hx index daab7b1a..d3fee948 100644 --- a/std/js/html/rtc/RtpSender.hx +++ b/std/js/html/rtc/RtpSender.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCRtpSender.webidl line 12:0. Do not edit! +// This file is generated from mozilla\RTCRtpSender.webidl. Do not edit! package js.html.rtc; @@ -29,5 +29,7 @@ extern class RtpSender { var track(default,null) : js.html.MediaStreamTrack; + function setParameters( ?parameters : RtpParameters ) : Promise; + function getParameters() : RtpParameters; function replaceTrack( track : js.html.MediaStreamTrack ) : Promise; } \ No newline at end of file diff --git a/std/js/html/rtc/SdpType.hx b/std/js/html/rtc/SdpType.hx index e13b2e23..8064dd71 100644 --- a/std/js/html/rtc/SdpType.hx +++ b/std/js/html/rtc/SdpType.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCSessionDescription.webidl line 10:0. Do not edit! +// This file is generated from mozilla\RTCSessionDescription.webidl. Do not edit! package js.html.rtc; @@ -29,4 +29,5 @@ package js.html.rtc; var OFFER = "offer"; var PRANSWER = "pranswer"; var ANSWER = "answer"; + var ROLLBACK = "rollback"; } \ No newline at end of file diff --git a/std/js/html/rtc/SessionDescription.hx b/std/js/html/rtc/SessionDescription.hx index e84dc1c6..78979200 100644 --- a/std/js/html/rtc/SessionDescription.hx +++ b/std/js/html/rtc/SessionDescription.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCSessionDescription.webidl line 24:0. Do not edit! +// This file is generated from mozilla\RTCSessionDescription.webidl. Do not edit! package js.html.rtc; +/** + The `RTCSessionDescription` interface represents the parameters of a session. Each `RTCSessionDescription` consists of a description `type` indicating which part of the offer/answer negotiation process it describes and of the SDP descriptor of the session. + + Documentation [RTCSessionDescription](https://developer.mozilla.org/en-US/docs/Web/API/RTCSessionDescription) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/RTCSessionDescription$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("RTCSessionDescription") extern class SessionDescription { + + /** + An enum of type ``RTCSdpType`` describing the session description's type. + **/ var type : SdpType; + + /** + A `DOMString` containing the `SDP` describing the session. + **/ var sdp : String; /** @throws DOMError */ diff --git a/std/js/html/rtc/SessionDescriptionInit.hx b/std/js/html/rtc/SessionDescriptionInit.hx index 1ad58112..51ff8935 100644 --- a/std/js/html/rtc/SessionDescriptionInit.hx +++ b/std/js/html/rtc/SessionDescriptionInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCSessionDescription.webidl line 16:0. Do not edit! +// This file is generated from mozilla\RTCSessionDescription.webidl. Do not edit! package js.html.rtc; diff --git a/std/js/html/rtc/SignalingState.hx b/std/js/html/rtc/SignalingState.hx index 20d66ecb..0590ac45 100644 --- a/std/js/html/rtc/SignalingState.hx +++ b/std/js/html/rtc/SignalingState.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCPeerConnection.webidl line 15:0. Do not edit! +// This file is generated from mozilla\RTCPeerConnection.webidl. Do not edit! package js.html.rtc; diff --git a/std/js/html/rtc/StatsReport.hx b/std/js/html/rtc/StatsReport.hx index 69abd026..aeaafeb0 100644 --- a/std/js/html/rtc/StatsReport.hx +++ b/std/js/html/rtc/StatsReport.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/RTCStatsReport.webidl line 175:0. Do not edit! +// This file is generated from mozilla\RTCStatsReport.webidl. Do not edit! package js.html.rtc; +/** + WebRTC provides a method—`RTCPeerConnection.getStats()`—which returns a set of statistics about the state of the connection and the data transfers which have taken place. This status report is an object of type `RTCStatsReport`, and consists of a mapping of strings identifying objects which have had statistics recorded and a dictionary containing all of the corresponding data. + + Documentation [RTCStatsReport](https://developer.mozilla.org/en-US/docs/Web/API/RTCStatsReport) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/RTCStatsReport$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("RTCStatsReport") extern class StatsReport { diff --git a/std/js/html/svg/AElement.hx b/std/js/html/svg/AElement.hx index d221992d..dc5242b4 100644 --- a/std/js/html/svg/AElement.hx +++ b/std/js/html/svg/AElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGAElement` interface provides access to the properties of `a` element, as well as methods to manipulate them. + + Documentation [SVGAElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGAElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAElement") extern class AElement extends GraphicsElement { + + /** + It corresponds to attribute  `target` on the given `a` element. + **/ var target(default,null) : AnimatedString; var download : String; var href(default,null) : AnimatedString; diff --git a/std/js/html/svg/AltGlyphElement.hx b/std/js/html/svg/AltGlyphElement.hx index af86309c..443b5716 100644 --- a/std/js/html/svg/AltGlyphElement.hx +++ b/std/js/html/svg/AltGlyphElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAltGlyphElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAltGlyphElement.webidl. Do not edit! package js.html.svg; +/** +   + + Documentation [SVGAltGlyphElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGAltGlyphElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAltGlyphElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAltGlyphElement") extern class AltGlyphElement extends TextPositioningElement { + + /** + It corresponds to the attribute `glyphRef` on the given element. It's data type is 'String'. It defines the glyph identifier, whose format is dependent on the ‘format’ of the given font. + **/ var glyphRef : String; + + /** + It corresponds to the attribute  `format` on the given element. It's data type is 'String'. This property specifies the format of the given font. + **/ var format : String; var href(default,null) : AnimatedString; diff --git a/std/js/html/svg/Angle.hx b/std/js/html/svg/Angle.hx index 20d84adb..0533a1d0 100644 --- a/std/js/html/svg/Angle.hx +++ b/std/js/html/svg/Angle.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAngle.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAngle.webidl. Do not edit! package js.html.svg; +/** + The `SVGAngle` interface is used to represent a value that can be an `angle` or `number` value. An `SVGAngle` reflected through the `animVal` attribute is always read only. + + Documentation [SVGAngle](https://developer.mozilla.org/en-US/docs/Web/API/SVGAngle) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAngle$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAngle") extern class Angle { @@ -33,9 +40,37 @@ extern class Angle static inline var SVG_ANGLETYPE_RAD : Int = 3; static inline var SVG_ANGLETYPE_GRAD : Int = 4; + + /** + The type of the value as specified by one of the `SVG_ANGLETYPE_*` constants defined on this interface. + **/ var unitType(default,null) : Int; + + /** + + The value as a floating point value, in user units. Setting this attribute will cause `valueInSpecifiedUnits` and `valueAsString` to be updated automatically to reflect this setting. + + Exceptions on setting: a `DOMException` with code `NO_MODIFICATION_ALLOWED_ERR` is raised when the length corresponds to a read only attribute or when the object itself is read only. + + **/ var value : Float; + + /** + + The value as a floating point value, in the units expressed by `unitType`. Setting this attribute will cause `value` and `valueAsString` to be updated automatically to reflect this setting. + + Exceptions on setting: a `DOMException` with code `NO_MODIFICATION_ALLOWED_ERR` is raised when the length corresponds to a read only attribute or when the object itself is read only. + + **/ var valueInSpecifiedUnits : Float; + + /** + + The value as a `DOMString` value, in the units expressed by `unitType`. Setting this attribute will cause `value`, `valueInSpecifiedUnits` and `unitType` to be updated automatically to reflect this setting. + + Exceptions on setting: + a `DOMException` with code `SYNTAX_ERR` is raised if the assigned string cannot be parsed as a valid `angle`. a `DOMException` with code `NO_MODIFICATION_ALLOWED_ERR` is raised when the length corresponds to a read only attribute or when the object itself is read only. + **/ var valueAsString : String; /** @throws DOMError */ diff --git a/std/js/html/svg/AnimateElement.hx b/std/js/html/svg/AnimateElement.hx index beccddbb..7817e675 100644 --- a/std/js/html/svg/AnimateElement.hx +++ b/std/js/html/svg/AnimateElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimateElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimateElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimateElement` interface corresponds to the `animate` element. + + Documentation [SVGAnimateElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimateElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimateElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimateElement") extern class AnimateElement extends AnimationElement { diff --git a/std/js/html/svg/AnimateMotionElement.hx b/std/js/html/svg/AnimateMotionElement.hx index bd9e3bde..2d4c70f5 100644 --- a/std/js/html/svg/AnimateMotionElement.hx +++ b/std/js/html/svg/AnimateMotionElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimateMotionElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimateMotionElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimateMotionElement` interface corresponds to the `animateMotion` element. + + Documentation [SVGAnimateMotionElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimateMotionElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimateMotionElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimateMotionElement") extern class AnimateMotionElement extends AnimationElement { diff --git a/std/js/html/svg/AnimateTransformElement.hx b/std/js/html/svg/AnimateTransformElement.hx index ea83b079..7bf52611 100644 --- a/std/js/html/svg/AnimateTransformElement.hx +++ b/std/js/html/svg/AnimateTransformElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimateTransformElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimateTransformElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimateTransformElement` interface corresponds to the `animateTransform` element. + + Documentation [SVGAnimateTransformElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimateTransformElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimateTransformElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimateTransformElement") extern class AnimateTransformElement extends AnimationElement { diff --git a/std/js/html/svg/AnimatedAngle.hx b/std/js/html/svg/AnimatedAngle.hx index 7b357330..4dabf062 100644 --- a/std/js/html/svg/AnimatedAngle.hx +++ b/std/js/html/svg/AnimatedAngle.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimatedAngle.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimatedAngle.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimatedAngle` interface is used for attributes of basic type angle which can be animated. + + Documentation [SVGAnimatedAngle](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedAngle) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedAngle$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimatedAngle") extern class AnimatedAngle { diff --git a/std/js/html/svg/AnimatedBoolean.hx b/std/js/html/svg/AnimatedBoolean.hx index 6b1e3e51..bf5efb2e 100644 --- a/std/js/html/svg/AnimatedBoolean.hx +++ b/std/js/html/svg/AnimatedBoolean.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimatedBoolean.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimatedBoolean.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimatedBoolean` interface is used for attributes of type boolean which can be animated. + + Documentation [SVGAnimatedBoolean](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedBoolean) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedBoolean$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimatedBoolean") extern class AnimatedBoolean { diff --git a/std/js/html/svg/AnimatedEnumeration.hx b/std/js/html/svg/AnimatedEnumeration.hx index fc15e4bc..06e3dfaf 100644 --- a/std/js/html/svg/AnimatedEnumeration.hx +++ b/std/js/html/svg/AnimatedEnumeration.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimatedEnumeration.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimatedEnumeration.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimatedEnumeration` interface is used for attributes whose value must be a constant from a particular enumeration and which can be animated. + + Documentation [SVGAnimatedEnumeration](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedEnumeration) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedEnumeration$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimatedEnumeration") extern class AnimatedEnumeration { diff --git a/std/js/html/svg/AnimatedInteger.hx b/std/js/html/svg/AnimatedInteger.hx index 563aca86..190803c4 100644 --- a/std/js/html/svg/AnimatedInteger.hx +++ b/std/js/html/svg/AnimatedInteger.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimatedInteger.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimatedInteger.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimatedInteger` interface is used for attributes of basic type integer which can be animated. + + Documentation [SVGAnimatedInteger](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedInteger) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedInteger$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimatedInteger") extern class AnimatedInteger { diff --git a/std/js/html/svg/AnimatedLength.hx b/std/js/html/svg/AnimatedLength.hx index ffa72db5..16f5fe14 100644 --- a/std/js/html/svg/AnimatedLength.hx +++ b/std/js/html/svg/AnimatedLength.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimatedLength.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimatedLength.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimatedLength` interface is used for attributes of basic type length which can be animated. + + Documentation [SVGAnimatedLength](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedLength) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedLength$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimatedLength") extern class AnimatedLength { diff --git a/std/js/html/svg/AnimatedLengthList.hx b/std/js/html/svg/AnimatedLengthList.hx index de6d2240..fb9b7fe9 100644 --- a/std/js/html/svg/AnimatedLengthList.hx +++ b/std/js/html/svg/AnimatedLengthList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimatedLengthList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimatedLengthList.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimatedLengthList` interface is used for attributes of type `SVGLengthList` which can be animated. + + Documentation [SVGAnimatedLengthList](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedLengthList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedLengthList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimatedLengthList") extern class AnimatedLengthList { diff --git a/std/js/html/svg/AnimatedNumber.hx b/std/js/html/svg/AnimatedNumber.hx index 1504dde3..f5b89bfa 100644 --- a/std/js/html/svg/AnimatedNumber.hx +++ b/std/js/html/svg/AnimatedNumber.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimatedNumber.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimatedNumber.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimatedNumber` interface is used for attributes of basic type Number which can be animated. + + Documentation [SVGAnimatedNumber](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedNumber) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedNumber$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimatedNumber") extern class AnimatedNumber { diff --git a/std/js/html/svg/AnimatedNumberList.hx b/std/js/html/svg/AnimatedNumberList.hx index 685bff42..09160a8c 100644 --- a/std/js/html/svg/AnimatedNumberList.hx +++ b/std/js/html/svg/AnimatedNumberList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimatedNumberList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimatedNumberList.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimatedNumber` interface is used for attributes which take a list of numbers and which can be animated. + + Documentation [SVGAnimatedNumberList](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedNumberList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedNumberList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimatedNumberList") extern class AnimatedNumberList { diff --git a/std/js/html/svg/AnimatedPreserveAspectRatio.hx b/std/js/html/svg/AnimatedPreserveAspectRatio.hx index c62089d6..40eccf49 100644 --- a/std/js/html/svg/AnimatedPreserveAspectRatio.hx +++ b/std/js/html/svg/AnimatedPreserveAspectRatio.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimatedPreserveAspectRatio.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimatedPreserveAspectRatio.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimatedPreserveAspectRatio` interface is used for attributes of type `SVGPreserveAspectRatio` which can be animated. + + Documentation [SVGAnimatedPreserveAspectRatio](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedPreserveAspectRatio) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedPreserveAspectRatio$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimatedPreserveAspectRatio") extern class AnimatedPreserveAspectRatio { diff --git a/std/js/html/svg/AnimatedRect.hx b/std/js/html/svg/AnimatedRect.hx index dc7f01c8..fbcf2032 100644 --- a/std/js/html/svg/AnimatedRect.hx +++ b/std/js/html/svg/AnimatedRect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimatedRect.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimatedRect.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimatedRect` interface is used for attributes of basic `SVGRect` which can be animated. + + Documentation [SVGAnimatedRect](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedRect) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedRect$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimatedRect") extern class AnimatedRect { diff --git a/std/js/html/svg/AnimatedString.hx b/std/js/html/svg/AnimatedString.hx index 22425ba5..e2e3bc58 100644 --- a/std/js/html/svg/AnimatedString.hx +++ b/std/js/html/svg/AnimatedString.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,14 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimatedString.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimatedString.webidl. Do not edit! package js.html.svg; +/** + The` SVGAnimatedString `interface represent string attributes which can be animated from each SVG declaration. You need to create SVG attribute before doing anything else, everything should be declared inside this. + + Documentation [SVGAnimatedString](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedString) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedString$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimatedString") extern class AnimatedString { + + /** + This is a `DOMString` representing the base value. The base value of the given attribute before applying any animations. Setter throws DOMException. + **/ var baseVal : String; + + /** + This is a `DOMString` representing the animation value. If the given attribute or property is being animated it contains the current animated value of the attribute or property. If the given attribute or property is not currently being animated, it contains the same value as baseVal. + **/ var animVal(default,null) : String; } \ No newline at end of file diff --git a/std/js/html/svg/AnimatedTransformList.hx b/std/js/html/svg/AnimatedTransformList.hx index ee301bb2..c12c62b0 100644 --- a/std/js/html/svg/AnimatedTransformList.hx +++ b/std/js/html/svg/AnimatedTransformList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimatedTransformList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimatedTransformList.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimatedTransformList` interface is used for attributes which take a list of numbers and which can be animated. + + Documentation [SVGAnimatedTransformList](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedTransformList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimatedTransformList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimatedTransformList") extern class AnimatedTransformList { diff --git a/std/js/html/svg/AnimationElement.hx b/std/js/html/svg/AnimationElement.hx index 91f77f73..743d2994 100644 --- a/std/js/html/svg/AnimationElement.hx +++ b/std/js/html/svg/AnimationElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGAnimationElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGAnimationElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGAnimationElement` interface is the base interface for all of the animation element interfaces: `SVGAnimateElement`, `SVGSetElement`, `SVGAnimateColorElement`, `SVGAnimateMotionElement` and `SVGAnimateTransformElement`. + + Documentation [SVGAnimationElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimationElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGAnimationElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGAnimationElement") extern class AnimationElement extends Element { diff --git a/std/js/html/svg/BoundingBoxOptions.hx b/std/js/html/svg/BoundingBoxOptions.hx index 96f6dc0a..fa88458a 100644 --- a/std/js/html/svg/BoundingBoxOptions.hx +++ b/std/js/html/svg/BoundingBoxOptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGGraphicsElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGGraphicsElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/CircleElement.hx b/std/js/html/svg/CircleElement.hx index a8da2349..d2e0c3ac 100644 --- a/std/js/html/svg/CircleElement.hx +++ b/std/js/html/svg/CircleElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGCircleElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGCircleElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGCircleElement` interface is an interface for the `circle` element. The circle element is defined by the cx and cy attributes, that denote the coordinates of the centre of the circle. It also has a radius attribute r that denotes the radius of the circle. The radius value must be positive to allow the successful rendering of the element. + + Documentation [SVGCircleElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGCircleElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGCircleElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGCircleElement") extern class CircleElement extends GraphicsElement { diff --git a/std/js/html/svg/ClipPathElement.hx b/std/js/html/svg/ClipPathElement.hx index 74dd6fb8..c8213abf 100644 --- a/std/js/html/svg/ClipPathElement.hx +++ b/std/js/html/svg/ClipPathElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGClipPathElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGClipPathElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGClipPathElement` interface provides access to the properties of `clipPath` elements, as well as methods to manipulate them. + + Documentation [SVGClipPathElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGClipPathElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGClipPathElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGClipPathElement") extern class ClipPathElement extends Element { diff --git a/std/js/html/svg/ComponentTransferFunctionElement.hx b/std/js/html/svg/ComponentTransferFunctionElement.hx index 1cb71480..fa9251bf 100644 --- a/std/js/html/svg/ComponentTransferFunctionElement.hx +++ b/std/js/html/svg/ComponentTransferFunctionElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGComponentTransferFunctionElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGComponentTransferFunctionElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/DefsElement.hx b/std/js/html/svg/DefsElement.hx index 8c441cb8..cb2dd9de 100644 --- a/std/js/html/svg/DefsElement.hx +++ b/std/js/html/svg/DefsElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGDefsElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGDefsElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGDefsElement` interface corresponds to the `defs` element. + + Documentation [SVGDefsElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGDefsElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGDefsElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGDefsElement") extern class DefsElement extends GraphicsElement { diff --git a/std/js/html/svg/DescElement.hx b/std/js/html/svg/DescElement.hx index 6d69ec83..49a69bbe 100644 --- a/std/js/html/svg/DescElement.hx +++ b/std/js/html/svg/DescElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGDescElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGDescElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGDescElement` interface corresponds to the `desc` element. + + Documentation [SVGDescElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGDescElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGDescElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGDescElement") extern class DescElement extends Element { diff --git a/std/js/html/svg/Document.hx b/std/js/html/svg/Document.hx index 897dcc92..2a6173d3 100644 --- a/std/js/html/svg/Document.hx +++ b/std/js/html/svg/Document.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGDocument.webidl line 10:0. Do not edit! +// This file is generated from mozilla\SVGDocument.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/Element.hx b/std/js/html/svg/Element.hx index 942b735c..e6e2d1ea 100644 --- a/std/js/html/svg/Element.hx +++ b/std/js/html/svg/Element.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGElement.webidl. Do not edit! package js.html.svg; +/** + All of the SVG DOM interfaces that correspond directly to elements in the SVG language derive from the `SVGElement` interface. + + Documentation [SVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGElement") extern class Element extends js.html.DOMElement { diff --git a/std/js/html/svg/EllipseElement.hx b/std/js/html/svg/EllipseElement.hx index 05e5b5f7..3265b239 100644 --- a/std/js/html/svg/EllipseElement.hx +++ b/std/js/html/svg/EllipseElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGEllipseElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGEllipseElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGEllipseElement` interface provides access to the properties of `ellipse` elements. + + Documentation [SVGEllipseElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGEllipseElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGEllipseElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGEllipseElement") extern class EllipseElement extends GraphicsElement { diff --git a/std/js/html/svg/FEBlendElement.hx b/std/js/html/svg/FEBlendElement.hx index 491a4f98..07ae5f5f 100644 --- a/std/js/html/svg/FEBlendElement.hx +++ b/std/js/html/svg/FEBlendElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEBlendElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEBlendElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEColorMatrixElement.hx b/std/js/html/svg/FEColorMatrixElement.hx index 5e87fc8a..bcf95880 100644 --- a/std/js/html/svg/FEColorMatrixElement.hx +++ b/std/js/html/svg/FEColorMatrixElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEColorMatrixElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEColorMatrixElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEComponentTransferElement.hx b/std/js/html/svg/FEComponentTransferElement.hx index 02d1e109..8a5d7f7e 100644 --- a/std/js/html/svg/FEComponentTransferElement.hx +++ b/std/js/html/svg/FEComponentTransferElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEComponentTransferElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEComponentTransferElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FECompositeElement.hx b/std/js/html/svg/FECompositeElement.hx index 46c2611f..433f23c2 100644 --- a/std/js/html/svg/FECompositeElement.hx +++ b/std/js/html/svg/FECompositeElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFECompositeElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFECompositeElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEConvolveMatrixElement.hx b/std/js/html/svg/FEConvolveMatrixElement.hx index dcba7f8f..6adf7da5 100644 --- a/std/js/html/svg/FEConvolveMatrixElement.hx +++ b/std/js/html/svg/FEConvolveMatrixElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEConvolveMatrixElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEConvolveMatrixElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEDiffuseLightingElement.hx b/std/js/html/svg/FEDiffuseLightingElement.hx index 3e09f7d1..17181444 100644 --- a/std/js/html/svg/FEDiffuseLightingElement.hx +++ b/std/js/html/svg/FEDiffuseLightingElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEDiffuseLightingElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEDiffuseLightingElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEDisplacementMapElement.hx b/std/js/html/svg/FEDisplacementMapElement.hx index 9e4094f6..34ce601d 100644 --- a/std/js/html/svg/FEDisplacementMapElement.hx +++ b/std/js/html/svg/FEDisplacementMapElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEDisplacementMapElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEDisplacementMapElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEDistantLightElement.hx b/std/js/html/svg/FEDistantLightElement.hx index 55cda0de..4be46116 100644 --- a/std/js/html/svg/FEDistantLightElement.hx +++ b/std/js/html/svg/FEDistantLightElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEDistantLightElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEDistantLightElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEDropShadowElement.hx b/std/js/html/svg/FEDropShadowElement.hx index 0670d45e..b57b6bdb 100644 --- a/std/js/html/svg/FEDropShadowElement.hx +++ b/std/js/html/svg/FEDropShadowElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEDropShadowElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEDropShadowElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEFloodElement.hx b/std/js/html/svg/FEFloodElement.hx index aad0ad55..5694ff7c 100644 --- a/std/js/html/svg/FEFloodElement.hx +++ b/std/js/html/svg/FEFloodElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEFloodElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEFloodElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEFuncAElement.hx b/std/js/html/svg/FEFuncAElement.hx index 94609d0f..0176d50c 100644 --- a/std/js/html/svg/FEFuncAElement.hx +++ b/std/js/html/svg/FEFuncAElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEFuncAElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEFuncAElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEFuncBElement.hx b/std/js/html/svg/FEFuncBElement.hx index b41a0c5c..b198ac2b 100644 --- a/std/js/html/svg/FEFuncBElement.hx +++ b/std/js/html/svg/FEFuncBElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEFuncBElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEFuncBElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEFuncGElement.hx b/std/js/html/svg/FEFuncGElement.hx index ce99a929..e276e7bb 100644 --- a/std/js/html/svg/FEFuncGElement.hx +++ b/std/js/html/svg/FEFuncGElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEFuncGElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEFuncGElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEFuncRElement.hx b/std/js/html/svg/FEFuncRElement.hx index 27f734cf..2ef0e774 100644 --- a/std/js/html/svg/FEFuncRElement.hx +++ b/std/js/html/svg/FEFuncRElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEFuncRElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEFuncRElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEGaussianBlurElement.hx b/std/js/html/svg/FEGaussianBlurElement.hx index 8be3c750..51cd526e 100644 --- a/std/js/html/svg/FEGaussianBlurElement.hx +++ b/std/js/html/svg/FEGaussianBlurElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEGaussianBlurElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEGaussianBlurElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEImageElement.hx b/std/js/html/svg/FEImageElement.hx index 8ac636fd..57201dc2 100644 --- a/std/js/html/svg/FEImageElement.hx +++ b/std/js/html/svg/FEImageElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEImageElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEImageElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEMergeElement.hx b/std/js/html/svg/FEMergeElement.hx index afa341c4..e48247ea 100644 --- a/std/js/html/svg/FEMergeElement.hx +++ b/std/js/html/svg/FEMergeElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEMergeElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEMergeElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEMergeNodeElement.hx b/std/js/html/svg/FEMergeNodeElement.hx index d65db29c..e764f3a6 100644 --- a/std/js/html/svg/FEMergeNodeElement.hx +++ b/std/js/html/svg/FEMergeNodeElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEMergeNodeElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEMergeNodeElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEMorphologyElement.hx b/std/js/html/svg/FEMorphologyElement.hx index ca7e5cd2..0827a70b 100644 --- a/std/js/html/svg/FEMorphologyElement.hx +++ b/std/js/html/svg/FEMorphologyElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEMorphologyElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEMorphologyElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEOffsetElement.hx b/std/js/html/svg/FEOffsetElement.hx index 658c620e..a88ae1b0 100644 --- a/std/js/html/svg/FEOffsetElement.hx +++ b/std/js/html/svg/FEOffsetElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEOffsetElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEOffsetElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FEPointLightElement.hx b/std/js/html/svg/FEPointLightElement.hx index a1cdf5cb..aa544413 100644 --- a/std/js/html/svg/FEPointLightElement.hx +++ b/std/js/html/svg/FEPointLightElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFEPointLightElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFEPointLightElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FESpecularLightingElement.hx b/std/js/html/svg/FESpecularLightingElement.hx index 78168e4a..4f102be3 100644 --- a/std/js/html/svg/FESpecularLightingElement.hx +++ b/std/js/html/svg/FESpecularLightingElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFESpecularLightingElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFESpecularLightingElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FESpotLightElement.hx b/std/js/html/svg/FESpotLightElement.hx index 1c78d925..70abc4fd 100644 --- a/std/js/html/svg/FESpotLightElement.hx +++ b/std/js/html/svg/FESpotLightElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFESpotLightElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFESpotLightElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FETileElement.hx b/std/js/html/svg/FETileElement.hx index 4eba2bc8..b8c9071c 100644 --- a/std/js/html/svg/FETileElement.hx +++ b/std/js/html/svg/FETileElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFETileElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFETileElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FETurbulenceElement.hx b/std/js/html/svg/FETurbulenceElement.hx index 445b1eec..c90a97ea 100644 --- a/std/js/html/svg/FETurbulenceElement.hx +++ b/std/js/html/svg/FETurbulenceElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFETurbulenceElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFETurbulenceElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/FilterElement.hx b/std/js/html/svg/FilterElement.hx index f358ad66..b731bca8 100644 --- a/std/js/html/svg/FilterElement.hx +++ b/std/js/html/svg/FilterElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGFilterElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGFilterElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGFilterElement` interface provides access to the properties of `filter` elements, as well as methods to manipulate them. + + Documentation [SVGFilterElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGFilterElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGFilterElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGFilterElement") extern class FilterElement extends Element { diff --git a/std/js/html/svg/ForeignObjectElement.hx b/std/js/html/svg/ForeignObjectElement.hx index 4aa2f4fe..19bbfb89 100644 --- a/std/js/html/svg/ForeignObjectElement.hx +++ b/std/js/html/svg/ForeignObjectElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGForeignObjectElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGForeignObjectElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGForeignObjectElement` interface provides access to the properties of `foreignObject` elements, as well as methods to manipulate them. + + Documentation [SVGForeignObjectElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGForeignObjectElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGForeignObjectElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGForeignObjectElement") extern class ForeignObjectElement extends GraphicsElement { diff --git a/std/js/html/svg/GElement.hx b/std/js/html/svg/GElement.hx index fc084514..053a168e 100644 --- a/std/js/html/svg/GElement.hx +++ b/std/js/html/svg/GElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGGElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGGElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGGElement` interface corresponds to the `g` element. + + Documentation [SVGGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGGElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGGElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGGElement") extern class GElement extends GraphicsElement { diff --git a/std/js/html/svg/GradientElement.hx b/std/js/html/svg/GradientElement.hx index 3f2fdf90..0e5de17d 100644 --- a/std/js/html/svg/GradientElement.hx +++ b/std/js/html/svg/GradientElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGGradientElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGGradientElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGGradient` interface is a base interface used by `SVGLinearGradientElement` and `SVGRadialGradientElement`. + + Documentation [SVGGradientElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGGradientElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGGradientElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGGradientElement") extern class GradientElement extends Element { diff --git a/std/js/html/svg/GraphicsElement.hx b/std/js/html/svg/GraphicsElement.hx index 70e3d544..96fd06ed 100644 --- a/std/js/html/svg/GraphicsElement.hx +++ b/std/js/html/svg/GraphicsElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGGraphicsElement.webidl line 20:0. Do not edit! +// This file is generated from mozilla\SVGGraphicsElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/IFrameElement.hx b/std/js/html/svg/IFrameElement.hx deleted file mode 100644 index fb72ee6b..00000000 --- a/std/js/html/svg/IFrameElement.hx +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C)2005-2015 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. - */ - -// This file is generated from mozilla/SVGIFrameElement.webidl line 18:0. Do not edit! - -package js.html.svg; - -@:native("SVGIFrameElement") -extern class IFrameElement extends GraphicsElement -{ - var x(default,null) : AnimatedLength; - var y(default,null) : AnimatedLength; - var width(default,null) : AnimatedLength; - var height(default,null) : AnimatedLength; - var preserveAspectRatio(default,null) : AnimatedPreserveAspectRatio; - var name(default,null) : String; - var src(default,null) : String; - var srcdoc(default,null) : String; - var sandbox(default,null) : js.html.DOMSettableTokenList; - var contentDocument(default,null) : js.html.HTMLDocument; - var contentWindow(default,null) : Window; - -} \ No newline at end of file diff --git a/std/js/html/svg/ImageElement.hx b/std/js/html/svg/ImageElement.hx index a3a1ee90..398116f2 100644 --- a/std/js/html/svg/ImageElement.hx +++ b/std/js/html/svg/ImageElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGImageElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGImageElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGImageElement` interface corresponds to the `image` element. + + Documentation [SVGImageElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGImageElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGImageElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGImageElement") extern class ImageElement extends GraphicsElement { diff --git a/std/js/html/svg/Length.hx b/std/js/html/svg/Length.hx index 65ef89f4..82ea1989 100644 --- a/std/js/html/svg/Length.hx +++ b/std/js/html/svg/Length.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGLength.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGLength.webidl. Do not edit! package js.html.svg; +/** + The `SVGLength` interface correspond to the length basic data type. + + Documentation [SVGLength](https://developer.mozilla.org/en-US/docs/Web/API/SVGLength) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGLength$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGLength") extern class Length { diff --git a/std/js/html/svg/LengthList.hx b/std/js/html/svg/LengthList.hx index 72edf8a0..4b9ae36f 100644 --- a/std/js/html/svg/LengthList.hx +++ b/std/js/html/svg/LengthList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGLengthList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGLengthList.webidl. Do not edit! package js.html.svg; +/** + The `SVGLengthList` defines a list of `SVGLength` objects. + + Documentation [SVGLengthList](https://developer.mozilla.org/en-US/docs/Web/API/SVGLengthList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGLengthList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGLengthList") extern class LengthList implements ArrayAccess { diff --git a/std/js/html/svg/LineElement.hx b/std/js/html/svg/LineElement.hx index 37251012..d1b4a02a 100644 --- a/std/js/html/svg/LineElement.hx +++ b/std/js/html/svg/LineElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGLineElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGLineElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGLineElement` interface provides access to the properties of `line` elements, as well as methods to manipulate them. + + Documentation [SVGLineElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGLineElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGLineElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGLineElement") extern class LineElement extends GraphicsElement { diff --git a/std/js/html/svg/LinearGradientElement.hx b/std/js/html/svg/LinearGradientElement.hx index b2ccfc20..ab3f4296 100644 --- a/std/js/html/svg/LinearGradientElement.hx +++ b/std/js/html/svg/LinearGradientElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGLinearGradientElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGLinearGradientElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGLinearGradientElement` interface corresponds to the `linearGradient` element. + + Documentation [SVGLinearGradientElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGLinearGradientElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGLinearGradientElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGLinearGradientElement") extern class LinearGradientElement extends GradientElement { diff --git a/std/js/html/svg/MPathElement.hx b/std/js/html/svg/MPathElement.hx index 511e68a0..f3f98e87 100644 --- a/std/js/html/svg/MPathElement.hx +++ b/std/js/html/svg/MPathElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGMPathElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGMPathElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGMPathElement` interface corresponds to the `mpath` element. + + Documentation [SVGMPathElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGMPathElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGMPathElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGMPathElement") extern class MPathElement extends Element { diff --git a/std/js/html/svg/MarkerElement.hx b/std/js/html/svg/MarkerElement.hx index c8aac581..078df77a 100644 --- a/std/js/html/svg/MarkerElement.hx +++ b/std/js/html/svg/MarkerElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGMarkerElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGMarkerElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/MaskElement.hx b/std/js/html/svg/MaskElement.hx index 43c4c858..ab6fde09 100644 --- a/std/js/html/svg/MaskElement.hx +++ b/std/js/html/svg/MaskElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGMaskElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGMaskElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGMaskElement` interface provides access to the properties of `mask` elements, as well as methods to manipulate them. + + Documentation [SVGMaskElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGMaskElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGMaskElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGMaskElement") extern class MaskElement extends Element { diff --git a/std/js/html/svg/Matrix.hx b/std/js/html/svg/Matrix.hx index 534748d1..dbe1031d 100644 --- a/std/js/html/svg/Matrix.hx +++ b/std/js/html/svg/Matrix.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGMatrix.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGMatrix.webidl. Do not edit! package js.html.svg; +/** + Many of SVG's graphics operations utilize 2x3 matrices of the form: + + Documentation [SVGMatrix](https://developer.mozilla.org/en-US/docs/Web/API/SVGMatrix) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGMatrix$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGMatrix") extern class Matrix { diff --git a/std/js/html/svg/MetadataElement.hx b/std/js/html/svg/MetadataElement.hx index 505a739b..210f1ff1 100644 --- a/std/js/html/svg/MetadataElement.hx +++ b/std/js/html/svg/MetadataElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGMetadataElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGMetadataElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/Number.hx b/std/js/html/svg/Number.hx index 6036bea7..ac4a10fa 100644 --- a/std/js/html/svg/Number.hx +++ b/std/js/html/svg/Number.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGNumber.webidl line 15:0. Do not edit! +// This file is generated from mozilla\SVGNumber.webidl. Do not edit! package js.html.svg; +/** + The `SVGNumber` interface correspond to the number basic data type. + + Documentation [SVGNumber](https://developer.mozilla.org/en-US/docs/Web/API/SVGNumber) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGNumber$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGNumber") extern class Number { diff --git a/std/js/html/svg/NumberList.hx b/std/js/html/svg/NumberList.hx index 6c0c94a3..6136c0c1 100644 --- a/std/js/html/svg/NumberList.hx +++ b/std/js/html/svg/NumberList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGNumberList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGNumberList.webidl. Do not edit! package js.html.svg; +/** + The `SVGNumberList` defines a list of `SVGNumber` objects. + + Documentation [SVGNumberList](https://developer.mozilla.org/en-US/docs/Web/API/SVGNumberList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGNumberList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGNumberList") extern class NumberList implements ArrayAccess { diff --git a/std/js/html/svg/PathElement.hx b/std/js/html/svg/PathElement.hx index 3ceb434c..58ff35f6 100644 --- a/std/js/html/svg/PathElement.hx +++ b/std/js/html/svg/PathElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathElement.webidl line 12:0. Do not edit! +// This file is generated from mozilla\SVGPathElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGPathElement` interface corresponds to the `path` element. + + Documentation [SVGPathElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGPathElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGPathElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGPathElement") extern class PathElement extends GraphicsElement { diff --git a/std/js/html/svg/PathSeg.hx b/std/js/html/svg/PathSeg.hx index c0b66b61..1b515433 100644 --- a/std/js/html/svg/PathSeg.hx +++ b/std/js/html/svg/PathSeg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegArcAbs.hx b/std/js/html/svg/PathSegArcAbs.hx index b9106c19..cdced3f8 100644 --- a/std/js/html/svg/PathSegArcAbs.hx +++ b/std/js/html/svg/PathSegArcAbs.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 124:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegArcRel.hx b/std/js/html/svg/PathSegArcRel.hx index 1693842f..133e546b 100644 --- a/std/js/html/svg/PathSegArcRel.hx +++ b/std/js/html/svg/PathSegArcRel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 141:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegClosePath.hx b/std/js/html/svg/PathSegClosePath.hx index ac06ce9c..32c34211 100644 --- a/std/js/html/svg/PathSegClosePath.hx +++ b/std/js/html/svg/PathSegClosePath.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 41:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegCurvetoCubicAbs.hx b/std/js/html/svg/PathSegCurvetoCubicAbs.hx index 3f183768..ad5eb852 100644 --- a/std/js/html/svg/PathSegCurvetoCubicAbs.hx +++ b/std/js/html/svg/PathSegCurvetoCubicAbs.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 72:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegCurvetoCubicRel.hx b/std/js/html/svg/PathSegCurvetoCubicRel.hx index d857304a..69b3506a 100644 --- a/std/js/html/svg/PathSegCurvetoCubicRel.hx +++ b/std/js/html/svg/PathSegCurvetoCubicRel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 87:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegCurvetoCubicSmoothAbs.hx b/std/js/html/svg/PathSegCurvetoCubicSmoothAbs.hx index 88b297c9..c59ccc68 100644 --- a/std/js/html/svg/PathSegCurvetoCubicSmoothAbs.hx +++ b/std/js/html/svg/PathSegCurvetoCubicSmoothAbs.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 178:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegCurvetoCubicSmoothRel.hx b/std/js/html/svg/PathSegCurvetoCubicSmoothRel.hx index 49f3bf25..377d62e6 100644 --- a/std/js/html/svg/PathSegCurvetoCubicSmoothRel.hx +++ b/std/js/html/svg/PathSegCurvetoCubicSmoothRel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 189:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegCurvetoQuadraticAbs.hx b/std/js/html/svg/PathSegCurvetoQuadraticAbs.hx index 20ca149f..e8346214 100644 --- a/std/js/html/svg/PathSegCurvetoQuadraticAbs.hx +++ b/std/js/html/svg/PathSegCurvetoQuadraticAbs.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 102:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegCurvetoQuadraticRel.hx b/std/js/html/svg/PathSegCurvetoQuadraticRel.hx index fb019c99..25c9bc4e 100644 --- a/std/js/html/svg/PathSegCurvetoQuadraticRel.hx +++ b/std/js/html/svg/PathSegCurvetoQuadraticRel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 113:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegCurvetoQuadraticSmoothAbs.hx b/std/js/html/svg/PathSegCurvetoQuadraticSmoothAbs.hx index 100503d8..88cb91e8 100644 --- a/std/js/html/svg/PathSegCurvetoQuadraticSmoothAbs.hx +++ b/std/js/html/svg/PathSegCurvetoQuadraticSmoothAbs.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 200:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegCurvetoQuadraticSmoothRel.hx b/std/js/html/svg/PathSegCurvetoQuadraticSmoothRel.hx index eb8bc9fb..b9ba6b37 100644 --- a/std/js/html/svg/PathSegCurvetoQuadraticSmoothRel.hx +++ b/std/js/html/svg/PathSegCurvetoQuadraticSmoothRel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 207:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegLinetoAbs.hx b/std/js/html/svg/PathSegLinetoAbs.hx index 9b69d76f..9d586047 100644 --- a/std/js/html/svg/PathSegLinetoAbs.hx +++ b/std/js/html/svg/PathSegLinetoAbs.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 58:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegLinetoHorizontalAbs.hx b/std/js/html/svg/PathSegLinetoHorizontalAbs.hx index c8256a8e..6f7f7eba 100644 --- a/std/js/html/svg/PathSegLinetoHorizontalAbs.hx +++ b/std/js/html/svg/PathSegLinetoHorizontalAbs.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 158:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegLinetoHorizontalRel.hx b/std/js/html/svg/PathSegLinetoHorizontalRel.hx index 40686e83..c8312a3b 100644 --- a/std/js/html/svg/PathSegLinetoHorizontalRel.hx +++ b/std/js/html/svg/PathSegLinetoHorizontalRel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 163:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegLinetoRel.hx b/std/js/html/svg/PathSegLinetoRel.hx index 8eb4fbac..894049f7 100644 --- a/std/js/html/svg/PathSegLinetoRel.hx +++ b/std/js/html/svg/PathSegLinetoRel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 65:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegLinetoVerticalAbs.hx b/std/js/html/svg/PathSegLinetoVerticalAbs.hx index c1f2c5cf..0157e2ef 100644 --- a/std/js/html/svg/PathSegLinetoVerticalAbs.hx +++ b/std/js/html/svg/PathSegLinetoVerticalAbs.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 168:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegLinetoVerticalRel.hx b/std/js/html/svg/PathSegLinetoVerticalRel.hx index ab03d4e7..615f7308 100644 --- a/std/js/html/svg/PathSegLinetoVerticalRel.hx +++ b/std/js/html/svg/PathSegLinetoVerticalRel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 173:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegList.hx b/std/js/html/svg/PathSegList.hx index c37a4ffb..af79d5dc 100644 --- a/std/js/html/svg/PathSegList.hx +++ b/std/js/html/svg/PathSegList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSegList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGPathSegList.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegMovetoAbs.hx b/std/js/html/svg/PathSegMovetoAbs.hx index feaba892..e5d9edc6 100644 --- a/std/js/html/svg/PathSegMovetoAbs.hx +++ b/std/js/html/svg/PathSegMovetoAbs.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 44:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PathSegMovetoRel.hx b/std/js/html/svg/PathSegMovetoRel.hx index 09fc31b3..90fa2b29 100644 --- a/std/js/html/svg/PathSegMovetoRel.hx +++ b/std/js/html/svg/PathSegMovetoRel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPathSeg.webidl line 51:0. Do not edit! +// This file is generated from mozilla\SVGPathSeg.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PatternElement.hx b/std/js/html/svg/PatternElement.hx index af0b9622..665847bf 100644 --- a/std/js/html/svg/PatternElement.hx +++ b/std/js/html/svg/PatternElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPatternElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGPatternElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGPatternElement` interface corresponds to the `pattern` element. + + Documentation [SVGPatternElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGPatternElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGPatternElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGPatternElement") extern class PatternElement extends Element { diff --git a/std/js/html/svg/Point.hx b/std/js/html/svg/Point.hx index d693756a..fe2473da 100644 --- a/std/js/html/svg/Point.hx +++ b/std/js/html/svg/Point.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPoint.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGPoint.webidl. Do not edit! package js.html.svg; +/** + An `SVGPoint` represents a 2D or 3D point in the SVG coordinate system. + + Documentation [SVGPoint](https://developer.mozilla.org/en-US/docs/Web/API/SVGPoint) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGPoint$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGPoint") extern class Point { diff --git a/std/js/html/svg/PointList.hx b/std/js/html/svg/PointList.hx index d21c79b6..65808c09 100644 --- a/std/js/html/svg/PointList.hx +++ b/std/js/html/svg/PointList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPointList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGPointList.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/PolygonElement.hx b/std/js/html/svg/PolygonElement.hx index 7211bb58..c0537f20 100644 --- a/std/js/html/svg/PolygonElement.hx +++ b/std/js/html/svg/PolygonElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPolygonElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGPolygonElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGPolygonElement` interface provides access to the properties of `polygon` elements, as well as methods to manipulate them. + + Documentation [SVGPolygonElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGPolygonElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGPolygonElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGPolygonElement") extern class PolygonElement extends GraphicsElement { diff --git a/std/js/html/svg/PolylineElement.hx b/std/js/html/svg/PolylineElement.hx index ed8b8fe7..55482662 100644 --- a/std/js/html/svg/PolylineElement.hx +++ b/std/js/html/svg/PolylineElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPolylineElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGPolylineElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGPolylineElement` interface provides access to the properties of `polyline` elements, as well as methods to manipulate them. + + Documentation [SVGPolylineElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGPolylineElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGPolylineElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGPolylineElement") extern class PolylineElement extends GraphicsElement { diff --git a/std/js/html/svg/PreserveAspectRatio.hx b/std/js/html/svg/PreserveAspectRatio.hx index 741e3788..84e0c295 100644 --- a/std/js/html/svg/PreserveAspectRatio.hx +++ b/std/js/html/svg/PreserveAspectRatio.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGPreserveAspectRatio.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGPreserveAspectRatio.webidl. Do not edit! package js.html.svg; +/** + The `SVGPreserveAspectRatio` interface corresponds to the `preserveAspectRatio` attribute, which is available for some of SVG's elements. + + Documentation [SVGPreserveAspectRatio](https://developer.mozilla.org/en-US/docs/Web/API/SVGPreserveAspectRatio) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGPreserveAspectRatio$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGPreserveAspectRatio") extern class PreserveAspectRatio { diff --git a/std/js/html/svg/RadialGradientElement.hx b/std/js/html/svg/RadialGradientElement.hx index bc316af1..de6a7990 100644 --- a/std/js/html/svg/RadialGradientElement.hx +++ b/std/js/html/svg/RadialGradientElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGRadialGradientElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGRadialGradientElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGRadialGradientElement` interface corresponds to the `radialGradient` element. + + Documentation [SVGRadialGradientElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGRadialGradientElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGRadialGradientElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGRadialGradientElement") extern class RadialGradientElement extends GradientElement { diff --git a/std/js/html/svg/Rect.hx b/std/js/html/svg/Rect.hx index 9daf3270..352e7b2b 100644 --- a/std/js/html/svg/Rect.hx +++ b/std/js/html/svg/Rect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGRect.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGRect.webidl. Do not edit! package js.html.svg; +/** + The `SVGRect` represents a rectangle. Rectangles consist of codex/code and codey/code coordinate pair identifying a minimum X value, a minimum Y value, and a width and height, which are constrained to be non-negative. + + Documentation [SVGRect](https://developer.mozilla.org/en-US/docs/Web/API/SVGRect) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGRect$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGRect") extern class Rect { diff --git a/std/js/html/svg/RectElement.hx b/std/js/html/svg/RectElement.hx index 371010ce..47248dfe 100644 --- a/std/js/html/svg/RectElement.hx +++ b/std/js/html/svg/RectElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGRectElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGRectElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGRectElement` interface provides access to the properties of `rect` elements, as well as methods to manipulate them. + + Documentation [SVGRectElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGRectElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGRectElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGRectElement") extern class RectElement extends GraphicsElement { diff --git a/std/js/html/svg/SVGElement.hx b/std/js/html/svg/SVGElement.hx index a9e9a21c..05621b11 100644 --- a/std/js/html/svg/SVGElement.hx +++ b/std/js/html/svg/SVGElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGSVGElement.webidl line 15:0. Do not edit! +// This file is generated from mozilla\SVGSVGElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGSVGElement` interface provides access to the properties of `svg` elements, as well as methods to manipulate them. This interface contains also various miscellaneous commonly-used utility methods, such as matrix operations and the ability to control the time of redraw on visual rendering devices. + + Documentation [SVGSVGElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGSVGElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGSVGElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGSVGElement") extern class SVGElement extends GraphicsElement { @@ -49,7 +56,6 @@ extern class SVGElement extends GraphicsElement function suspendRedraw( maxWaitMilliseconds : Int ) : Int; function unsuspendRedraw( suspendHandleID : Int ) : Void; function unsuspendRedrawAll() : Void; - /** @throws DOMError */ function forceRedraw() : Void; function pauseAnimations() : Void; function unpauseAnimations() : Void; diff --git a/std/js/html/svg/ScriptElement.hx b/std/js/html/svg/ScriptElement.hx index ff95725e..cf1eabc1 100644 --- a/std/js/html/svg/ScriptElement.hx +++ b/std/js/html/svg/ScriptElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGScriptElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGScriptElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGScriptElement` interface corresponds to the SVG `script` element. + + Documentation [SVGScriptElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGScriptElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGScriptElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGScriptElement") extern class ScriptElement extends Element { diff --git a/std/js/html/svg/SetElement.hx b/std/js/html/svg/SetElement.hx index 25273cf0..f37b0ec8 100644 --- a/std/js/html/svg/SetElement.hx +++ b/std/js/html/svg/SetElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGSetElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGSetElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGSetElement` interface corresponds to the `set` element. + + Documentation [SVGSetElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGSetElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGSetElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGSetElement") extern class SetElement extends AnimationElement { diff --git a/std/js/html/svg/StopElement.hx b/std/js/html/svg/StopElement.hx index 498cee3d..48e3b953 100644 --- a/std/js/html/svg/StopElement.hx +++ b/std/js/html/svg/StopElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGStopElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGStopElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGStopElement` interface corresponds to the `stop` element. + + Documentation [SVGStopElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGStopElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGStopElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGStopElement") extern class StopElement extends Element { diff --git a/std/js/html/svg/StringList.hx b/std/js/html/svg/StringList.hx index 43ce3b09..11df3dcd 100644 --- a/std/js/html/svg/StringList.hx +++ b/std/js/html/svg/StringList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGStringList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGStringList.webidl. Do not edit! package js.html.svg; +/** + The `SVGStringList` defines a list of `DOMString` objects. + + Documentation [SVGStringList](https://developer.mozilla.org/en-US/docs/Web/API/SVGStringList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGStringList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGStringList") extern class StringList implements ArrayAccess { diff --git a/std/js/html/svg/StyleElement.hx b/std/js/html/svg/StyleElement.hx index 4778d1fc..aa3cc7af 100644 --- a/std/js/html/svg/StyleElement.hx +++ b/std/js/html/svg/StyleElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGStyleElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGStyleElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGStyleElement` interface corresponds to the SVG `style` element. + + Documentation [SVGStyleElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGStyleElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGStyleElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGStyleElement") extern class StyleElement extends Element { @@ -31,5 +38,6 @@ extern class StyleElement extends Element var type : String; var media : String; var scoped : Bool; + var sheet(default,null) : js.html.StyleSheet; } \ No newline at end of file diff --git a/std/js/html/svg/SwitchElement.hx b/std/js/html/svg/SwitchElement.hx index 70404212..5684b7f6 100644 --- a/std/js/html/svg/SwitchElement.hx +++ b/std/js/html/svg/SwitchElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGSwitchElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGSwitchElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGSwitchElement` interface corresponds to the `switch` element. + + Documentation [SVGSwitchElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGSwitchElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGSwitchElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGSwitchElement") extern class SwitchElement extends GraphicsElement { diff --git a/std/js/html/svg/SymbolElement.hx b/std/js/html/svg/SymbolElement.hx index 28885cd6..e0083d57 100644 --- a/std/js/html/svg/SymbolElement.hx +++ b/std/js/html/svg/SymbolElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGSymbolElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGSymbolElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGSymbolElement` interface corresponds to the `symbol` element. + + Documentation [SVGSymbolElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGSymbolElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGSymbolElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGSymbolElement") extern class SymbolElement extends Element { diff --git a/std/js/html/svg/TSpanElement.hx b/std/js/html/svg/TSpanElement.hx index 476e45b6..e0257255 100644 --- a/std/js/html/svg/TSpanElement.hx +++ b/std/js/html/svg/TSpanElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGTSpanElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGTSpanElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGTSpanElement` interface provides access to the properties of `tspan` elements, as well as methods to manipulate them. + + Documentation [SVGTSpanElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGTSpanElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGTSpanElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGTSpanElement") extern class TSpanElement extends TextPositioningElement { diff --git a/std/js/html/svg/TextContentElement.hx b/std/js/html/svg/TextContentElement.hx index 70c3df31..86d9fc8b 100644 --- a/std/js/html/svg/TextContentElement.hx +++ b/std/js/html/svg/TextContentElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGTextContentElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGTextContentElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/TextElement.hx b/std/js/html/svg/TextElement.hx index 9fc2d1e8..54bf487b 100644 --- a/std/js/html/svg/TextElement.hx +++ b/std/js/html/svg/TextElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGTextElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGTextElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGTextElement` interface corresponds to the `text` elements. + + Documentation [SVGTextElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGTextElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGTextElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGTextElement") extern class TextElement extends TextPositioningElement { diff --git a/std/js/html/svg/TextPathElement.hx b/std/js/html/svg/TextPathElement.hx index b79e8423..3f889727 100644 --- a/std/js/html/svg/TextPathElement.hx +++ b/std/js/html/svg/TextPathElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGTextPathElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGTextPathElement.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/TextPositioningElement.hx b/std/js/html/svg/TextPositioningElement.hx index dde3e83a..cf34678b 100644 --- a/std/js/html/svg/TextPositioningElement.hx +++ b/std/js/html/svg/TextPositioningElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGTextPositioningElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGTextPositioningElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGTextPositioningElement` interface is inherited by text-related interfaces: `SVGTextElement`, `SVGTSpanElement`, `SVGTRefElement` and `SVGAltGlyphElement`. + + Documentation [SVGTextPositioningElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGTextPositioningElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGTextPositioningElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGTextPositioningElement") extern class TextPositioningElement extends TextContentElement { diff --git a/std/js/html/svg/TitleElement.hx b/std/js/html/svg/TitleElement.hx index f009c543..c85fbe39 100644 --- a/std/js/html/svg/TitleElement.hx +++ b/std/js/html/svg/TitleElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGTitleElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGTitleElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGTitleElement` interface corresponds to the `title` element. + + Documentation [SVGTitleElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGTitleElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGTitleElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGTitleElement") extern class TitleElement extends Element { diff --git a/std/js/html/svg/Transform.hx b/std/js/html/svg/Transform.hx index 811b0511..a31da433 100644 --- a/std/js/html/svg/Transform.hx +++ b/std/js/html/svg/Transform.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGTransform.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGTransform.webidl. Do not edit! package js.html.svg; +/** + `SVGTransform` is the interface for one of the component transformations within an `SVGTransformList`; thus, an `SVGTransform` object corresponds to a single component (e.g., `scale(…)` or `matrix(…)`) within a `transform` attribute. + + Documentation [SVGTransform](https://developer.mozilla.org/en-US/docs/Web/API/SVGTransform) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGTransform$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGTransform") extern class Transform { diff --git a/std/js/html/svg/TransformList.hx b/std/js/html/svg/TransformList.hx index a73f3355..97b65ee7 100644 --- a/std/js/html/svg/TransformList.hx +++ b/std/js/html/svg/TransformList.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGTransformList.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGTransformList.webidl. Do not edit! package js.html.svg; +/** + The `SVGTransformList` defines a list of `SVGTransform` objects. + + Documentation [SVGTransformList](https://developer.mozilla.org/en-US/docs/Web/API/SVGTransformList) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGTransformList$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGTransformList") extern class TransformList implements ArrayAccess { diff --git a/std/js/html/svg/UnitTypes.hx b/std/js/html/svg/UnitTypes.hx index b11a54f6..120b7777 100644 --- a/std/js/html/svg/UnitTypes.hx +++ b/std/js/html/svg/UnitTypes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGUnitTypes.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGUnitTypes.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/UseElement.hx b/std/js/html/svg/UseElement.hx index 5c1120a7..1f129736 100644 --- a/std/js/html/svg/UseElement.hx +++ b/std/js/html/svg/UseElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGUseElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGUseElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGUseElement` interface provides access to the properties of `use` elements, as well as methods to manipulate them. + + Documentation [SVGUseElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGUseElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGUseElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGUseElement") extern class UseElement extends GraphicsElement { diff --git a/std/js/html/svg/ViewElement.hx b/std/js/html/svg/ViewElement.hx index 45c0723f..3ecaa2be 100644 --- a/std/js/html/svg/ViewElement.hx +++ b/std/js/html/svg/ViewElement.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGViewElement.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGViewElement.webidl. Do not edit! package js.html.svg; +/** + The `SVGViewElement` interface provides access to the properties of `view` elements, as well as methods to manipulate them. + + Documentation [SVGViewElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGViewElement) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/SVGViewElement$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("SVGViewElement") extern class ViewElement extends Element { diff --git a/std/js/html/svg/ZoomAndPan.hx b/std/js/html/svg/ZoomAndPan.hx index aa80ca40..27e855fa 100644 --- a/std/js/html/svg/ZoomAndPan.hx +++ b/std/js/html/svg/ZoomAndPan.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGZoomAndPan.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGZoomAndPan.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/svg/ZoomEvent.hx b/std/js/html/svg/ZoomEvent.hx index 14fbe31e..17ae65ea 100644 --- a/std/js/html/svg/ZoomEvent.hx +++ b/std/js/html/svg/ZoomEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/SVGZoomEvent.webidl line 13:0. Do not edit! +// This file is generated from mozilla\SVGZoomEvent.webidl. Do not edit! package js.html.svg; diff --git a/std/js/html/webgl/ActiveInfo.hx b/std/js/html/webgl/ActiveInfo.hx index 7d2e501e..ceafcf65 100644 --- a/std/js/html/webgl/ActiveInfo.hx +++ b/std/js/html/webgl/ActiveInfo.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 70:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; +/** + The WebGLActiveInfo interface is part of the WebGL API and represents the information returned by calling the `WebGLRenderingContext.getActiveAttrib()` and `WebGLRenderingContext.getActiveUniform()` methods. + + Documentation [WebGLActiveInfo](https://developer.mozilla.org/en-US/docs/Web/API/WebGLActiveInfo) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLActiveInfo$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WebGLActiveInfo") extern class ActiveInfo { + + /** + The read-only size of the requested variable. + **/ var size(default,null) : Int; + + /** + The read-only type of the requested variable. + **/ var type(default,null) : Int; + + /** + The read-only name of the requested variable. + **/ var name(default,null) : String; } \ No newline at end of file diff --git a/std/js/html/webgl/Buffer.hx b/std/js/html/webgl/Buffer.hx index 619fe293..551fb720 100644 --- a/std/js/html/webgl/Buffer.hx +++ b/std/js/html/webgl/Buffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 46:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; +/** + The WebGLBuffer interface is part of the WebGL API and represents an opaque buffer object storing data such as vertices or colors. + + Documentation [WebGLBuffer](https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WebGLBuffer") extern class Buffer { diff --git a/std/js/html/webgl/ContextAttributes.hx b/std/js/html/webgl/ContextAttributes.hx index ea0dd7bd..e9fba19f 100644 --- a/std/js/html/webgl/ContextAttributes.hx +++ b/std/js/html/webgl/ContextAttributes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 34:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; @@ -29,6 +29,7 @@ typedef ContextAttributes = @:optional var alpha : Bool; @:optional var antialias : Bool; @:optional var depth : Bool; + @:optional var failIfMajorPerformanceCaveat : Bool; @:optional var premultipliedAlpha : Bool; @:optional var preserveDrawingBuffer : Bool; @:optional var stencil : Bool; diff --git a/std/js/html/webgl/ContextEvent.hx b/std/js/html/webgl/ContextEvent.hx index 6c04ce7b..59f9d67d 100644 --- a/std/js/html/webgl/ContextEvent.hx +++ b/std/js/html/webgl/ContextEvent.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,24 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from webgl.webidl line 4:0. Do not edit! +// This file is generated from webgl.webidl. Do not edit! package js.html.webgl; +/** + The WebContextEvent interface is part of the WebGL API and is an interface for an event that is generated in response to a status change to the WebGL rendering context. + + Documentation [WebGLContextEvent](https://developer.mozilla.org/en-US/docs/Web/API/WebGLContextEvent) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLContextEvent$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WebGLContextEvent") extern class ContextEvent extends js.html.Event { + + /** + A read-only property containing additional information about the event. + **/ var statusMessage(default,null) : String; /** @throws DOMError */ diff --git a/std/js/html/webgl/ContextEventInit.hx b/std/js/html/webgl/ContextEventInit.hx index 06c79665..bf6eb529 100644 --- a/std/js/html/webgl/ContextEventInit.hx +++ b/std/js/html/webgl/ContextEventInit.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from webgl.webidl line 9:0. Do not edit! +// This file is generated from webgl.webidl. Do not edit! package js.html.webgl; diff --git a/std/js/html/webgl/DebugRendererInfo.hx b/std/js/html/webgl/DebugRendererInfo.hx deleted file mode 100644 index aeb7ab76..00000000 --- a/std/js/html/webgl/DebugRendererInfo.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html.webgl; - -/** @deprecated Use ExtensionDebugRendererInfo instead. */ -@:deprecated("DebugRendererInfo is deprecated, use ExtensionDebugRendererInfo instead") -typedef DebugRendererInfo = ExtensionDebugRendererInfo; diff --git a/std/js/html/webgl/DebugShaders.hx b/std/js/html/webgl/DebugShaders.hx deleted file mode 100644 index 4f7445db..00000000 --- a/std/js/html/webgl/DebugShaders.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html.webgl; - -/** @deprecated Use ExtensionDebugShaders instead. */ -@:deprecated("DebugShaders is deprecated, use ExtensionDebugShaders instead") -typedef DebugShaders = ExtensionDebugShaders; diff --git a/std/js/html/webgl/DepthTexture.hx b/std/js/html/webgl/DepthTexture.hx deleted file mode 100644 index 00200593..00000000 --- a/std/js/html/webgl/DepthTexture.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html.webgl; - -/** @deprecated Use ExtensionDepthTexture instead. */ -@:deprecated("DepthTexture is deprecated, use ExtensionDepthTexture instead") -typedef DepthTexture = ExtensionDepthTexture; diff --git a/std/js/html/webgl/EXTTextureFilterAnisotropic.hx b/std/js/html/webgl/EXTTextureFilterAnisotropic.hx deleted file mode 100644 index 7184461b..00000000 --- a/std/js/html/webgl/EXTTextureFilterAnisotropic.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html.webgl; - -/** @deprecated Use ExtensionTextureFilterAnisotropic instead. */ -@:deprecated("EXTTextureFilterAnisotropic is deprecated, use ExtensionTextureFilterAnisotropic instead") -typedef EXTTextureFilterAnisotropic = ExtensionTextureFilterAnisotropic; diff --git a/std/js/html/webgl/ExtensionBlendMinMax.hx b/std/js/html/webgl/ExtensionBlendMinMax.hx index 375e909a..42b6e2ee 100644 --- a/std/js/html/webgl/ExtensionBlendMinMax.hx +++ b/std/js/html/webgl/ExtensionBlendMinMax.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 973:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionBlendMinMax") +/** + The `EXT_blend_minmax` extension is part of the WebGL API and extends blending capabilities by adding two new blend equations: the minimum or maximum color components of the source and destination colors. + + Documentation [EXT_blend_minmax](https://developer.mozilla.org/en-US/docs/Web/API/EXT_blend_minmax) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EXT_blend_minmax$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("EXT_blend_minmax") extern class ExtensionBlendMinMax { static inline var MIN_EXT : Int = 32775; diff --git a/std/js/html/webgl/ExtensionColorBufferFloat.hx b/std/js/html/webgl/ExtensionColorBufferFloat.hx index 19dfb564..3ca743a8 100644 --- a/std/js/html/webgl/ExtensionColorBufferFloat.hx +++ b/std/js/html/webgl/ExtensionColorBufferFloat.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 936:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionColorBufferFloat") +/** + The `WEBGL_color_buffer_float` extension is part of the WebGL API and adds the ability to render to 32-bit floating-point color buffers. + + Documentation [WEBGL_color_buffer_float](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_color_buffer_float) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_color_buffer_float$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WEBGL_color_buffer_float") extern class ExtensionColorBufferFloat { static inline var RGBA32F_EXT : Int = 34836; diff --git a/std/js/html/webgl/ExtensionColorBufferHalfFloat.hx b/std/js/html/webgl/ExtensionColorBufferHalfFloat.hx index e0db8e2c..90163146 100644 --- a/std/js/html/webgl/ExtensionColorBufferHalfFloat.hx +++ b/std/js/html/webgl/ExtensionColorBufferHalfFloat.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 945:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionColorBufferHalfFloat") +/** + The `EXT_color_buffer_half_float` extension is part of the WebGL API and adds the ability to render to 16-bit floating-point color buffers. + + Documentation [EXT_color_buffer_half_float](https://developer.mozilla.org/en-US/docs/Web/API/EXT_color_buffer_half_float) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EXT_color_buffer_half_float$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("EXT_color_buffer_half_float") extern class ExtensionColorBufferHalfFloat { static inline var RGBA16F_EXT : Int = 34842; diff --git a/std/js/html/webgl/ExtensionCompressedTextureATC.hx b/std/js/html/webgl/ExtensionCompressedTextureATC.hx index e6055ef6..80a9151c 100644 --- a/std/js/html/webgl/ExtensionCompressedTextureATC.hx +++ b/std/js/html/webgl/ExtensionCompressedTextureATC.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 789:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionCompressedTextureATC") +/** + The `WEBGL_compressed_texture_atc` extension is part of the WebGL API and exposes 3 ATC compressed texture formats. ATC is a proprietary compression algorithm for compressing textures on handheld devices. + + Documentation [WEBGL_compressed_texture_atc](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_compressed_texture_atc) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_compressed_texture_atc$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WEBGL_compressed_texture_atc") extern class ExtensionCompressedTextureATC { static inline var COMPRESSED_RGB_ATC_WEBGL : Int = 35986; diff --git a/std/js/html/webgl/ExtensionCompressedTextureES3.hx b/std/js/html/webgl/ExtensionCompressedTextureES3.hx new file mode 100644 index 00000000..43ef12ad --- /dev/null +++ b/std/js/html/webgl/ExtensionCompressedTextureES3.hx @@ -0,0 +1,48 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! + +package js.html.webgl; + +/** + The `WEBGL_compressed_texture_es3` extension is part of the WebGL API and exposes 10 ETC/EAC compressed texture formats. + + Documentation [WEBGL_compressed_texture_es3](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_compressed_texture_es3) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_compressed_texture_es3$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WEBGL_compressed_texture_es3") +extern class ExtensionCompressedTextureES3 +{ + static inline var COMPRESSED_R11_EAC : Int = 37488; + static inline var COMPRESSED_SIGNED_R11_EAC : Int = 37489; + static inline var COMPRESSED_RG11_EAC : Int = 37490; + static inline var COMPRESSED_SIGNED_RG11_EAC : Int = 37491; + static inline var COMPRESSED_RGB8_ETC2 : Int = 37492; + static inline var COMPRESSED_SRGB8_ETC2 : Int = 37493; + static inline var COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 : Int = 37494; + static inline var COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 : Int = 37495; + static inline var COMPRESSED_RGBA8_ETC2_EAC : Int = 37496; + static inline var COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : Int = 37497; + +} \ No newline at end of file diff --git a/std/js/html/webgl/ExtensionCompressedTextureETC1.hx b/std/js/html/webgl/ExtensionCompressedTextureETC1.hx index 309a063f..387a96be 100644 --- a/std/js/html/webgl/ExtensionCompressedTextureETC1.hx +++ b/std/js/html/webgl/ExtensionCompressedTextureETC1.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 797:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionCompressedTextureETC1") +/** + The `WEBGL_compressed_texture_etc1` extension is part of the WebGL API and exposes the ETC1 compressed texture format. + + Documentation [WEBGL_compressed_texture_etc1](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_compressed_texture_etc1) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_compressed_texture_etc1$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WEBGL_compressed_texture_etc1") extern class ExtensionCompressedTextureETC1 { static inline var COMPRESSED_RGB_ETC1_WEBGL : Int = 36196; diff --git a/std/js/html/webgl/ExtensionCompressedTexturePVRTC.hx b/std/js/html/webgl/ExtensionCompressedTexturePVRTC.hx index 2f57b911..54df7e0c 100644 --- a/std/js/html/webgl/ExtensionCompressedTexturePVRTC.hx +++ b/std/js/html/webgl/ExtensionCompressedTexturePVRTC.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 803:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionCompressedTexturePVRTC") +/** + The `WEBGL_compressed_texture_pvrtc` extension is part of the WebGL API and exposes four PVRTC compressed texture formats. + + Documentation [WEBGL_compressed_texture_pvrtc](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_compressed_texture_pvrtc) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_compressed_texture_pvrtc$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WEBGL_compressed_texture_pvrtc") extern class ExtensionCompressedTexturePVRTC { static inline var COMPRESSED_RGB_PVRTC_4BPPV1_IMG : Int = 35840; diff --git a/std/js/html/webgl/ExtensionCompressedTextureS3TC.hx b/std/js/html/webgl/ExtensionCompressedTextureS3TC.hx index dd9eb109..20240516 100644 --- a/std/js/html/webgl/ExtensionCompressedTextureS3TC.hx +++ b/std/js/html/webgl/ExtensionCompressedTextureS3TC.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 780:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionCompressedTextureS3TC") +/** + The `WEBGL_compressed_texture_s3tc` extension is part of the WebGL API and exposes four S3TC compressed texture formats. + + Documentation [WEBGL_compressed_texture_s3tc](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_compressed_texture_s3tc) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_compressed_texture_s3tc$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WEBGL_compressed_texture_s3tc") extern class ExtensionCompressedTextureS3TC { static inline var COMPRESSED_RGB_S3TC_DXT1_EXT : Int = 33776; diff --git a/std/js/html/webgl/ExtensionDebugRendererInfo.hx b/std/js/html/webgl/ExtensionDebugRendererInfo.hx index 2f92ac01..dd6c0e1b 100644 --- a/std/js/html/webgl/ExtensionDebugRendererInfo.hx +++ b/std/js/html/webgl/ExtensionDebugRendererInfo.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 812:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionDebugRendererInfo") +/** + The `WEBGL_debug_renderer_info` extension is part of the WebGL API and exposes two constants with information about the graphics driver for debugging purposes. + + Documentation [WEBGL_debug_renderer_info](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_debug_renderer_info) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_debug_renderer_info$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WEBGL_debug_renderer_info") extern class ExtensionDebugRendererInfo { static inline var UNMASKED_VENDOR_WEBGL : Int = 37445; diff --git a/std/js/html/webgl/ExtensionDebugShaders.hx b/std/js/html/webgl/ExtensionDebugShaders.hx index 116fd790..35ff37fc 100644 --- a/std/js/html/webgl/ExtensionDebugShaders.hx +++ b/std/js/html/webgl/ExtensionDebugShaders.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,12 +20,23 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 819:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionDebugShaders") +/** + The `WEBGL_debug_shaders` extension is part of the WebGL API and exposes a method to debug shaders from privileged contexts. + + Documentation [WEBGL_debug_shaders](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_debug_shaders) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_debug_shaders$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WEBGL_debug_shaders") extern class ExtensionDebugShaders { + + /** + Returns the translated shader source. + **/ function getTranslatedShaderSource( shader : Shader ) : String; } \ No newline at end of file diff --git a/std/js/html/webgl/ExtensionDepthTexture.hx b/std/js/html/webgl/ExtensionDepthTexture.hx index ed87f080..a11579fe 100644 --- a/std/js/html/webgl/ExtensionDepthTexture.hx +++ b/std/js/html/webgl/ExtensionDepthTexture.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 825:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionDepthTexture") +/** + The `WEBGL_depth_texture` extension is part of the WebGL API and defines 2D depth and depth-stencil textures. + + Documentation [WEBGL_depth_texture](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_depth_texture) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_depth_texture$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WEBGL_depth_texture") extern class ExtensionDepthTexture { static inline var UNSIGNED_INT_24_8_WEBGL : Int = 34042; diff --git a/std/js/html/webgl/ExtensionDisjointTimerQuery.hx b/std/js/html/webgl/ExtensionDisjointTimerQuery.hx new file mode 100644 index 00000000..26e3b759 --- /dev/null +++ b/std/js/html/webgl/ExtensionDisjointTimerQuery.hx @@ -0,0 +1,93 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! + +package js.html.webgl; + +/** + The EXT_disjoint_timer_query extension is part of the WebGL API and provides a way to measure the duration of a set of GL commands, without stalling the rendering pipeline. + + Documentation [EXT_disjoint_timer_query](https://developer.mozilla.org/en-US/docs/Web/API/EXT_disjoint_timer_query) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EXT_disjoint_timer_query$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("EXT_disjoint_timer_query") +extern class ExtensionDisjointTimerQuery +{ + static inline var QUERY_COUNTER_BITS_EXT : Int = 34916; + static inline var CURRENT_QUERY_EXT : Int = 34917; + static inline var QUERY_RESULT_EXT : Int = 34918; + static inline var QUERY_RESULT_AVAILABLE_EXT : Int = 34919; + static inline var TIME_ELAPSED_EXT : Int = 35007; + static inline var TIMESTAMP_EXT : Int = 36392; + static inline var GPU_DISJOINT_EXT : Int = 36795; + + + /** + + Creates a new `WebGLTimerQueryEXT`. + + **/ + function createQueryEXT() : TimerQueryEXT; + + /** + + Deletes a given `WebGLTimerQueryEXT`. + + **/ + function deleteQueryEXT( query : TimerQueryEXT ) : Void; + + /** + + Returns `true` if a given object is a `WebGLTimerQueryEXT`. + + **/ + function isQueryEXT( query : TimerQueryEXT ) : Bool; + + /** + The timer starts when all commands prior to `beginQueryEXT` have been fully executed. + **/ + function beginQueryEXT( target : Int, query : TimerQueryEXT ) : Void; + + /** + The timer stops when all commands prior to `endQueryEXT` have been fully executed. + **/ + function endQueryEXT( target : Int ) : Void; + + /** + + Records the current time into the corresponding query object. + + **/ + function queryCounterEXT( query : TimerQueryEXT, target : Int ) : Void; + + /** + Returns information about a query target. + **/ + function getQueryEXT( target : Int, pname : Int ) : Dynamic; + + /** + Return the state of a query object. + **/ + function getQueryObjectEXT( query : TimerQueryEXT, pname : Int ) : Dynamic; +} \ No newline at end of file diff --git a/std/js/html/webgl/ExtensionDrawBuffers.hx b/std/js/html/webgl/ExtensionDrawBuffers.hx index 565a6f73..2d160e27 100644 --- a/std/js/html/webgl/ExtensionDrawBuffers.hx +++ b/std/js/html/webgl/ExtensionDrawBuffers.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 873:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionDrawBuffers") +/** + The `WEBGL_draw_buffers` extension is part of the WebGL API and enables a fragment shader to write to several textures, which is useful for deferred shading, for example. + + Documentation [WEBGL_draw_buffers](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_draw_buffers) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_draw_buffers$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WEBGL_draw_buffers") extern class ExtensionDrawBuffers { static inline var COLOR_ATTACHMENT0_WEBGL : Int = 36064; @@ -62,5 +69,11 @@ extern class ExtensionDrawBuffers static inline var MAX_COLOR_ATTACHMENTS_WEBGL : Int = 36063; static inline var MAX_DRAW_BUFFERS_WEBGL : Int = 34852; + + /** + + Defines the draw buffers to which all fragment colors are written. (When using `WebGL2RenderingContext`, this method is available as `WebGL2RenderingContext.drawBuffers()` by default). + + **/ function drawBuffersWEBGL( buffers : Array ) : Void; } \ No newline at end of file diff --git a/std/js/html/webgl/ExtensionElementIndexUint.hx b/std/js/html/webgl/ExtensionElementIndexUint.hx index dc2c9e40..ee6edcd8 100644 --- a/std/js/html/webgl/ExtensionElementIndexUint.hx +++ b/std/js/html/webgl/ExtensionElementIndexUint.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 831:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionElementIndexUint") +/** + The `OES_element_index_uint` extension is part of the WebGL API and adds support for `gl.UNSIGNED_INT` types to `WebGLRenderingContext.drawElements()`. + + Documentation [OES_element_index_uint](https://developer.mozilla.org/en-US/docs/Web/API/OES_element_index_uint) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/OES_element_index_uint$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("OES_element_index_uint") extern class ExtensionElementIndexUint { } \ No newline at end of file diff --git a/std/js/html/webgl/ExtensionFragDepth.hx b/std/js/html/webgl/ExtensionFragDepth.hx index 8ecaf420..da80d2bd 100644 --- a/std/js/html/webgl/ExtensionFragDepth.hx +++ b/std/js/html/webgl/ExtensionFragDepth.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 836:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionFragDepth") +/** + The `EXT_frag_depth` extension is part of the WebGL API and enables to set a depth value of a fragment from within the fragment shader. + + Documentation [EXT_frag_depth](https://developer.mozilla.org/en-US/docs/Web/API/EXT_frag_depth) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EXT_frag_depth$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("EXT_frag_depth") extern class ExtensionFragDepth { } \ No newline at end of file diff --git a/std/js/html/webgl/ExtensionInstancedArrays.hx b/std/js/html/webgl/ExtensionInstancedArrays.hx index f737ee08..157030d8 100644 --- a/std/js/html/webgl/ExtensionInstancedArrays.hx +++ b/std/js/html/webgl/ExtensionInstancedArrays.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,16 +20,41 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 964:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionInstancedArrays") +/** + The `ANGLE_instanced_arrays` extension is part of the WebGL API and allows to draw the same object, or groups of similar objects multiple times, if they share the same vertex data, primitive count and type. + + Documentation [ANGLE_instanced_arrays](https://developer.mozilla.org/en-US/docs/Web/API/ANGLE_instanced_arrays) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/ANGLE_instanced_arrays$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("ANGLE_instanced_arrays") extern class ExtensionInstancedArrays { static inline var VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE : Int = 35070; + + /** + + Behaves identically to `WebGLRenderingContext.drawArrays()` except that multiple instances of the range of elements are executed, and the instance advances for each iteration. + + **/ function drawArraysInstancedANGLE( mode : Int, first : Int, count : Int, primcount : Int ) : Void; + + /** + + Behaves identically to `WebGLRenderingContext.drawElements()` except that multiple instances of the set of elements are executed and the instance advances between each set. + + **/ function drawElementsInstancedANGLE( mode : Int, count : Int, type : Int, offset : Int, primcount : Int ) : Void; + + /** + + Modifies the rate at which generic vertex attributes advance when rendering multiple instances of primitives with `ANGLE_instanced_arrays.drawArraysInstancedANGLE()` and `ANGLE_instanced_arrays.drawElementsInstancedANGLE()`. + + **/ function vertexAttribDivisorANGLE( index : Int, divisor : Int ) : Void; } \ No newline at end of file diff --git a/std/js/html/webgl/ExtensionLoseContext.hx b/std/js/html/webgl/ExtensionLoseContext.hx index b057ca1d..73b94763 100644 --- a/std/js/html/webgl/ExtensionLoseContext.hx +++ b/std/js/html/webgl/ExtensionLoseContext.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,13 +20,28 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 841:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionLoseContext") +/** + The WEBGL_lose_context extension is part of the WebGL API and exposes functions to simulate losing and restoring a `WebGLRenderingContext`. + + Documentation [WEBGL_lose_context](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WEBGL_lose_context") extern class ExtensionLoseContext { + + /** + Simulates losing the context. + **/ function loseContext() : Void; + + /** + Simulates restoring the context. + **/ function restoreContext() : Void; } \ No newline at end of file diff --git a/std/js/html/webgl/ExtensionSRGB.hx b/std/js/html/webgl/ExtensionSRGB.hx index c408dd4b..644c3f1e 100644 --- a/std/js/html/webgl/ExtensionSRGB.hx +++ b/std/js/html/webgl/ExtensionSRGB.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 854:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionSRGB") +/** + The `EXT_sRGB` extension is part of the WebGL API and adds sRGB support to textures and framebuffer objects. + + Documentation [EXT_sRGB](https://developer.mozilla.org/en-US/docs/Web/API/EXT_sRGB) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EXT_sRGB$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("EXT_sRGB") extern class ExtensionSRGB { static inline var SRGB_EXT : Int = 35904; diff --git a/std/js/html/webgl/ExtensionShaderTextureLod.hx b/std/js/html/webgl/ExtensionShaderTextureLod.hx index c08596f7..013bc0d7 100644 --- a/std/js/html/webgl/ExtensionShaderTextureLod.hx +++ b/std/js/html/webgl/ExtensionShaderTextureLod.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 920:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionShaderTextureLod") +/** + The `EXT_shader_texture_lod` extension is part of the WebGL API and adds additional texture functions to the OpenGL ES Shading Language which provide the shader writer with explicit control of LOD (Level of detail). + + Documentation [EXT_shader_texture_lod](https://developer.mozilla.org/en-US/docs/Web/API/EXT_shader_texture_lod) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EXT_shader_texture_lod$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("EXT_shader_texture_lod") extern class ExtensionShaderTextureLod { } \ No newline at end of file diff --git a/std/js/html/webgl/ExtensionStandardDerivatives.hx b/std/js/html/webgl/ExtensionStandardDerivatives.hx index 34e15e95..1d3edb6a 100644 --- a/std/js/html/webgl/ExtensionStandardDerivatives.hx +++ b/std/js/html/webgl/ExtensionStandardDerivatives.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 863:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionStandardDerivatives") +/** + The `OES_standard_derivatives` extension is part of the WebGL API and adds the GLSL derivative functions `dFdx`, `dFdy`, and `fwidth`. + + Documentation [OES_standard_derivatives](https://developer.mozilla.org/en-US/docs/Web/API/OES_standard_derivatives) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/OES_standard_derivatives$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("OES_standard_derivatives") extern class ExtensionStandardDerivatives { static inline var FRAGMENT_SHADER_DERIVATIVE_HINT_OES : Int = 35723; diff --git a/std/js/html/webgl/ExtensionTextureFilterAnisotropic.hx b/std/js/html/webgl/ExtensionTextureFilterAnisotropic.hx index 8c8762c9..20125b75 100644 --- a/std/js/html/webgl/ExtensionTextureFilterAnisotropic.hx +++ b/std/js/html/webgl/ExtensionTextureFilterAnisotropic.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 847:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionTextureFilterAnisotropic") +/** + The `EXT_texture_filter_anisotropic` extension is part of the WebGL API and exposes two constants for anisotropic filtering (AF). + + Documentation [EXT_texture_filter_anisotropic](https://developer.mozilla.org/en-US/docs/Web/API/EXT_texture_filter_anisotropic) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/EXT_texture_filter_anisotropic$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("EXT_texture_filter_anisotropic") extern class ExtensionTextureFilterAnisotropic { static inline var TEXTURE_MAX_ANISOTROPY_EXT : Int = 34046; diff --git a/std/js/html/webgl/ExtensionTextureFloat.hx b/std/js/html/webgl/ExtensionTextureFloat.hx index f9fa019e..4993a68e 100644 --- a/std/js/html/webgl/ExtensionTextureFloat.hx +++ b/std/js/html/webgl/ExtensionTextureFloat.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 868:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionTextureFloat") +/** + The `OES_texture_float` extension is part of the WebGL API and exposes floating-point pixel types for textures. + + Documentation [OES_texture_float](https://developer.mozilla.org/en-US/docs/Web/API/OES_texture_float) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/OES_texture_float$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("OES_texture_float") extern class ExtensionTextureFloat { } \ No newline at end of file diff --git a/std/js/html/webgl/ExtensionTextureFloatLinear.hx b/std/js/html/webgl/ExtensionTextureFloatLinear.hx index 17bfa8f0..ac4ddf3c 100644 --- a/std/js/html/webgl/ExtensionTextureFloatLinear.hx +++ b/std/js/html/webgl/ExtensionTextureFloatLinear.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 915:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionTextureFloatLinear") +/** + The `OES_texture_float_linear` extension is part of the WebGL API and allows linear filtering with floating-point pixel types for textures. + + Documentation [OES_texture_float_linear](https://developer.mozilla.org/en-US/docs/Web/API/OES_texture_float_linear) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/OES_texture_float_linear$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("OES_texture_float_linear") extern class ExtensionTextureFloatLinear { } \ No newline at end of file diff --git a/std/js/html/webgl/ExtensionTextureHalfFloat.hx b/std/js/html/webgl/ExtensionTextureHalfFloat.hx index 167476a0..50e3abea 100644 --- a/std/js/html/webgl/ExtensionTextureHalfFloat.hx +++ b/std/js/html/webgl/ExtensionTextureHalfFloat.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 925:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionTextureHalfFloat") +/** + The `OES_texture_half_float` extension is part of the WebGL API and adds texture formats with 16- (aka half float) and 32-bit floating-point components. + + Documentation [OES_texture_half_float](https://developer.mozilla.org/en-US/docs/Web/API/OES_texture_half_float) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/OES_texture_half_float$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("OES_texture_half_float") extern class ExtensionTextureHalfFloat { static inline var HALF_FLOAT_OES : Int = 36193; diff --git a/std/js/html/webgl/ExtensionTextureHalfFloatLinear.hx b/std/js/html/webgl/ExtensionTextureHalfFloatLinear.hx index 677c0f27..2a1f9806 100644 --- a/std/js/html/webgl/ExtensionTextureHalfFloatLinear.hx +++ b/std/js/html/webgl/ExtensionTextureHalfFloatLinear.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,11 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 931:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionTextureHalfFloatLinear") +/** + The `OES_texture_half_float_linear` extension is part of the WebGL API and allows linear filtering with half floating-point pixel types for textures. + + Documentation [OES_texture_half_float_linear](https://developer.mozilla.org/en-US/docs/Web/API/OES_texture_half_float_linear) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/OES_texture_half_float_linear$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("OES_texture_half_float_linear") extern class ExtensionTextureHalfFloatLinear { } \ No newline at end of file diff --git a/std/js/html/webgl/ExtensionVertexArrayObject.hx b/std/js/html/webgl/ExtensionVertexArrayObject.hx new file mode 100644 index 00000000..f5742af5 --- /dev/null +++ b/std/js/html/webgl/ExtensionVertexArrayObject.hx @@ -0,0 +1,67 @@ +/* + * Copyright (C)2005-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. + */ + +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! + +package js.html.webgl; + +/** + The OES_vertex_array_object extension is part of the WebGL API and provides vertex array objects (VAOs) which encapsulate vertex array states. These objects keep pointers to vertex data and provide names for different sets of vertex data. + + Documentation [OES_vertex_array_object](https://developer.mozilla.org/en-US/docs/Web/API/OES_vertex_array_object) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/OES_vertex_array_object$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("OES_vertex_array_object") +extern class ExtensionVertexArrayObject +{ + static inline var VERTEX_ARRAY_BINDING_OES : Int = 34229; + + + /** + + Creates a new `WebGLVertexArrayObjectOES`. + + **/ + function createVertexArrayOES() : VertexArrayObjectOES; + + /** + + Deletes a given `WebGLVertexArrayObjectOES`. + + **/ + function deleteVertexArrayOES( arrayObject : VertexArrayObjectOES ) : Void; + + /** + + Returns `true` if a given object is a `WebGLVertexArrayObjectOES`. + + **/ + function isVertexArrayOES( arrayObject : VertexArrayObjectOES ) : Bool; + + /** + + Binds a given `WebGLVertexArrayObjectOES` to the buffer. + + **/ + function bindVertexArrayOES( arrayObject : VertexArrayObjectOES ) : Void; +} \ No newline at end of file diff --git a/std/js/html/webgl/Framebuffer.hx b/std/js/html/webgl/Framebuffer.hx index 57f22196..c3f5def9 100644 --- a/std/js/html/webgl/Framebuffer.hx +++ b/std/js/html/webgl/Framebuffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 49:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; +/** + The WebGLFramebuffer interface is part of the WebGL API and represents a collection of buffers that serve as a rendering destination. + + Documentation [WebGLFramebuffer](https://developer.mozilla.org/en-US/docs/Web/API/WebGLFramebuffer) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLFramebuffer$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WebGLFramebuffer") extern class Framebuffer { diff --git a/std/js/html/webgl/GL.hx b/std/js/html/webgl/GL.hx index fe048728..477f1226 100644 --- a/std/js/html/webgl/GL.hx +++ b/std/js/html/webgl/GL.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/js/html/webgl/LoseContext.hx b/std/js/html/webgl/LoseContext.hx deleted file mode 100644 index e1a20ef2..00000000 --- a/std/js/html/webgl/LoseContext.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html.webgl; - -/** @deprecated Use ExtensionLoseContext instead. */ -@:deprecated("LoseContext is deprecated, use ExtensionLoseContext instead") -typedef LoseContext = ExtensionLoseContext; diff --git a/std/js/html/webgl/OESStandardDerivatives.hx b/std/js/html/webgl/OESStandardDerivatives.hx deleted file mode 100644 index c0348f34..00000000 --- a/std/js/html/webgl/OESStandardDerivatives.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html.webgl; - -/** @deprecated Use ExtensionStandardDerivatives instead. */ -@:deprecated("OESStandardDerivatives is deprecated, use ExtensionStandardDerivatives instead") -typedef OESStandardDerivatives = ExtensionStandardDerivatives; diff --git a/std/js/html/webgl/OESTextureFloat.hx b/std/js/html/webgl/OESTextureFloat.hx deleted file mode 100644 index bac7b970..00000000 --- a/std/js/html/webgl/OESTextureFloat.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html.webgl; - -/** @deprecated Use ExtensionTextureFloat instead. */ -@:deprecated("OESTextureFloat is deprecated, use ExtensionTextureFloat instead") -typedef OESTextureFloat = ExtensionTextureFloat; diff --git a/std/js/html/webgl/OESVertexArrayObject.hx b/std/js/html/webgl/OESVertexArrayObject.hx deleted file mode 100644 index 820f8cfb..00000000 --- a/std/js/html/webgl/OESVertexArrayObject.hx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C)2005-2015 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 js.html.webgl; - -/** @deprecated Use ExtensionVertexArray instead. */ -@:deprecated("OESVertexArrayObject is deprecated, use ExtensionVertexArray instead") -typedef OESVertexArrayObject = ExtensionVertexArray; diff --git a/std/js/html/webgl/Program.hx b/std/js/html/webgl/Program.hx index 8dd26413..072cd2e8 100644 --- a/std/js/html/webgl/Program.hx +++ b/std/js/html/webgl/Program.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 52:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; +/** + The WebGLProgram is part of the WebGL API and is a combination of two compiled `WebGLShader`s consisting of a vertex shader and a fragment shader (both written in GLSL). These are then linked into a usable program. + + Documentation [WebGLProgram](https://developer.mozilla.org/en-US/docs/Web/API/WebGLProgram) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLProgram$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WebGLProgram") extern class Program { diff --git a/std/js/html/webgl/Renderbuffer.hx b/std/js/html/webgl/Renderbuffer.hx index 1ba4fbee..9135ae7b 100644 --- a/std/js/html/webgl/Renderbuffer.hx +++ b/std/js/html/webgl/Renderbuffer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 55:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; +/** + The WebGLRenderbuffer interface is part of the WebGL API and represents a buffer that can contain an image, or can be source or target of an rendering operation. + + Documentation [WebGLRenderbuffer](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderbuffer) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderbuffer$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WebGLRenderbuffer") extern class Renderbuffer { diff --git a/std/js/html/webgl/RenderingContext.hx b/std/js/html/webgl/RenderingContext.hx index 13f2fde8..07783ac6 100644 --- a/std/js/html/webgl/RenderingContext.hx +++ b/std/js/html/webgl/RenderingContext.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 82:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; +/** + The WebGLRenderingContext interface provides the OpenGL ES 2.0 rendering context for the drawing surface of an HTML `canvas` element. + + Documentation [WebGLRenderingContext](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WebGLRenderingContext") extern class RenderingContext { @@ -348,9 +355,11 @@ extern class RenderingContext function blendFuncSeparate( srcRGB : Int, dstRGB : Int, srcAlpha : Int, dstAlpha : Int ) : Void; @:overload( function( target : Int, size : Int, usage : Int ) : Void {} ) @:overload( function( target : Int, data : js.html.ArrayBufferView, usage : Int ) : Void {} ) - function bufferData( target : Int, data : js.html.ArrayBuffer, usage : Int ) : Void; + @:overload( function( target : Int, data : js.html.ArrayBuffer, usage : Int ) : Void {} ) + function bufferData( target : Int, data : Dynamic/*MISSING SharedArrayBuffer*/, usage : Int ) : Void; @:overload( function( target : Int, offset : Int, data : js.html.ArrayBufferView ) : Void {} ) - function bufferSubData( target : Int, offset : Int, data : js.html.ArrayBuffer ) : Void; + @:overload( function( target : Int, offset : Int, data : js.html.ArrayBuffer ) : Void {} ) + function bufferSubData( target : Int, offset : Int, data : Dynamic/*MISSING SharedArrayBuffer*/ ) : Void; function checkFramebufferStatus( target : Int ) : Int; function clear( mask : Int ) : Void; function clearColor( red : Float, green : Float, blue : Float, alpha : Float ) : Void; diff --git a/std/js/html/webgl/Shader.hx b/std/js/html/webgl/Shader.hx index 3efdf965..9d5ae2a6 100644 --- a/std/js/html/webgl/Shader.hx +++ b/std/js/html/webgl/Shader.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 58:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; +/** + The WebGLShader is part of the WebGL API and can either be a vertex or a fragment shader. A `WebGLProgram` requires both types of shaders. + + Documentation [WebGLShader](https://developer.mozilla.org/en-US/docs/Web/API/WebGLShader) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLShader$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WebGLShader") extern class Shader { diff --git a/std/js/html/webgl/ShaderPrecisionFormat.hx b/std/js/html/webgl/ShaderPrecisionFormat.hx index f2310cd7..1e1d5932 100644 --- a/std/js/html/webgl/ShaderPrecisionFormat.hx +++ b/std/js/html/webgl/ShaderPrecisionFormat.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,15 +20,34 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 76:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; +/** + The WebGLShaderPrecisionFormat interface is part of the WebGL API and represents the information returned by calling the `WebGLRenderingContext.getShaderPrecisionFormat()` method. + + Documentation [WebGLShaderPrecisionFormat](https://developer.mozilla.org/en-US/docs/Web/API/WebGLShaderPrecisionFormat) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLShaderPrecisionFormat$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WebGLShaderPrecisionFormat") extern class ShaderPrecisionFormat { + + /** + The base 2 log of the absolute value of the minimum value that can be represented. + **/ var rangeMin(default,null) : Int; + + /** + The base 2 log of the absolute value of the maximum value that can be represented. + **/ var rangeMax(default,null) : Int; + + /** + The number of bits of precision that can be represented. For integer formats this value is always 0. + **/ var precision(default,null) : Int; } \ No newline at end of file diff --git a/std/js/html/webgl/Texture.hx b/std/js/html/webgl/Texture.hx index cf82d39f..7a1057e3 100644 --- a/std/js/html/webgl/Texture.hx +++ b/std/js/html/webgl/Texture.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 61:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; +/** + The WebGLTexture interface is part of the WebGL API and represents an opaque texture object providing storage and state for texturing operations. + + Documentation [WebGLTexture](https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WebGLTexture") extern class Texture { diff --git a/std/js/html/webgl/ExtensionVertexArray.hx b/std/js/html/webgl/TimerQueryEXT.hx similarity index 61% rename from std/js/html/webgl/ExtensionVertexArray.hx rename to std/js/html/webgl/TimerQueryEXT.hx index e85cd247..c94bc795 100644 --- a/std/js/html/webgl/ExtensionVertexArray.hx +++ b/std/js/html/webgl/TimerQueryEXT.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,17 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 954:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; -@:native("WebGLExtensionVertexArray") -extern class ExtensionVertexArray +/** + The `WebGLTimerQueryEXT` interface is part of the WebGL `EXT_disjoint_timer_query` extension and exposes a timer query object. + + Documentation [WebGLTimerQueryEXT](https://developer.mozilla.org/en-US/docs/Web/API/WebGLTimerQueryEXT) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLTimerQueryEXT$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WebGLTimerQueryEXT") +extern class TimerQueryEXT { - static inline var VERTEX_ARRAY_BINDING_OES : Int = 34229; - - function createVertexArrayOES() : VertexArray; - function deleteVertexArrayOES( arrayObject : VertexArray ) : Void; - function isVertexArrayOES( arrayObject : VertexArray ) : Bool; - function bindVertexArrayOES( arrayObject : VertexArray ) : Void; } \ No newline at end of file diff --git a/std/js/html/webgl/UniformLocation.hx b/std/js/html/webgl/UniformLocation.hx index 70ab669f..64ba9809 100644 --- a/std/js/html/webgl/UniformLocation.hx +++ b/std/js/html/webgl/UniformLocation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,10 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -// This file is generated from mozilla/WebGLRenderingContext.webidl line 64:0. Do not edit! +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! package js.html.webgl; +/** + The WebGLUniformLocation interface is part of the WebGL API and represents the location of a uniform variable in a shader program. + + Documentation [WebGLUniformLocation](https://developer.mozilla.org/en-US/docs/Web/API/WebGLUniformLocation) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLUniformLocation$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ @:native("WebGLUniformLocation") extern class UniformLocation { diff --git a/std/js/html/webgl/VertexArrayObjectOES.hx b/std/js/html/webgl/VertexArrayObjectOES.hx index cda4c1e0..78c3252b 100644 --- a/std/js/html/webgl/VertexArrayObjectOES.hx +++ b/std/js/html/webgl/VertexArrayObjectOES.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,8 +20,18 @@ * DEALINGS IN THE SOFTWARE. */ +// This file is generated from mozilla\WebGLRenderingContext.webidl. Do not edit! + package js.html.webgl; -/** @deprecated Use VertexArray instead. */ -@:deprecated("VertexArrayObjectOES is deprecated, use VertexArray instead") -typedef VertexArrayObjectOES = VertexArray; +/** + The `WebGLVertexArrayObjectOES` interface is part of the WebGL `OES_vertex_array_object` extension, represents vertex array objects (VAOs) pointing to vertex array data and provides names for different sets of vertex data. + + Documentation [WebGLVertexArrayObjectOES](https://developer.mozilla.org/en-US/docs/Web/API/WebGLVertexArrayObjectOES) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WebGLVertexArrayObjectOES$history), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/). + + @see +**/ +@:native("WebGLVertexArrayObjectOES") +extern class VertexArrayObjectOES +{ +} \ No newline at end of file diff --git a/std/js/jquery/Callbacks.hx b/std/js/jquery/Callbacks.hx new file mode 100644 index 00000000..a6262ebe --- /dev/null +++ b/std/js/jquery/Callbacks.hx @@ -0,0 +1,53 @@ +/* This file is generated, do not edit! Visit http://api.jquery.com/ for API documentation. */ +package js.jquery; +@:native("$.Callbacks") extern class Callbacks { + /** + Add a callback or a collection of callbacks to a callback list. + **/ + public function add(callbacks:haxe.extern.EitherType>):js.jquery.Callbacks; + /** + Disable a callback list from doing anything more. + **/ + public function disable():js.jquery.Callbacks; + /** + Determine if the callbacks list has been disabled. + **/ + public function disabled():Bool; + /** + Remove all of the callbacks from a list. + **/ + public function empty():js.jquery.Callbacks; + /** + Call all of the callbacks with the given arguments. + **/ + public function fire(arguments:Dynamic):js.jquery.Callbacks; + /** + Call all callbacks in a list with the given context and arguments. + **/ + public function fireWith(?context:Dynamic, ?args:Dynamic):js.jquery.Callbacks; + /** + Determine if the callbacks have already been called at least once. + **/ + public function fired():Bool; + /** + Determine whether or not the list has any callbacks attached. If a callback is provided as an argument, determine whether it is in a list. + **/ + public function has(?callback:haxe.Constraints.Function):Bool; + /** + Lock a callback list in its current state. + **/ + public function lock():js.jquery.Callbacks; + /** + Determine if the callbacks list has been locked. + **/ + public function locked():Bool; + /** + A multi-purpose callbacks list object that provides a powerful way to manage callback lists. + **/ + @:selfCall + public function new(flags:String):Void; + /** + Remove a callback or a collection of callbacks from a callback list. + **/ + public function remove(callbacks:haxe.extern.EitherType>):js.jquery.Callbacks; +} \ No newline at end of file diff --git a/std/js/jquery/Deferred.hx b/std/js/jquery/Deferred.hx new file mode 100644 index 00000000..a8dad698 --- /dev/null +++ b/std/js/jquery/Deferred.hx @@ -0,0 +1,79 @@ +/* This file is generated, do not edit! Visit http://api.jquery.com/ for API documentation. */ +package js.jquery; +@:native("$.Deferred") extern class Deferred { + /** + Add handlers to be called when the Deferred object is either resolved or rejected. + **/ + public function always(alwaysCallbacks:haxe.extern.EitherType>, ?alwaysCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; + /** + Add handlers to be called when the Deferred object is resolved. + **/ + public function done(doneCallbacks:haxe.extern.EitherType>, ?doneCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; + /** + Add handlers to be called when the Deferred object is rejected. + **/ + public function fail(failCallbacks:haxe.extern.EitherType>, ?failCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; + /** + Determine whether a Deferred object has been rejected. + **/ + @:deprecated("Deprecated since jQuery 1.7") + public function isRejected():Bool; + /** + Determine whether a Deferred object has been resolved. + **/ + @:deprecated("Deprecated since jQuery 1.7") + public function isResolved():Bool; + /** + A factory function that returns a chainable utility object with methods to register multiple callbacks into callback queues, invoke callback queues, and relay the success or failure state of any synchronous or asynchronous function. + **/ + @:selfCall + public function new(?beforeStart:js.jquery.Deferred -> Void):Void; + /** + Call the progressCallbacks on a Deferred object with the given args. + **/ + public function notify(args:Dynamic):js.jquery.Deferred; + /** + Call the progressCallbacks on a Deferred object with the given context and args. + **/ + public function notifyWith(context:Dynamic, ?args:Array):js.jquery.Deferred; + /** + Utility method to filter and/or chain Deferreds. + **/ + @:deprecated("Deprecated since jQuery 1.8") + @:overload(function(?doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function, ?progressFilter:haxe.Constraints.Function):js.jquery.Promise { }) + public function pipe(?doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function):js.jquery.Promise; + /** + Add handlers to be called when the Deferred object generates progress notifications. + **/ + public function progress(progressCallbacks:haxe.extern.EitherType, Array>>, ?progressCallbacks:haxe.extern.EitherType, Array>>):js.jquery.Deferred; + /** + Return a Deferred's Promise object. + **/ + public function promise(?target:Dynamic):js.jquery.Promise; + /** + Reject a Deferred object and call any failCallbacks with the given args. + **/ + public function reject(?args:Dynamic):js.jquery.Deferred; + /** + Reject a Deferred object and call any failCallbacks with the given context and args. + **/ + public function rejectWith(context:Dynamic, ?args:Array):js.jquery.Deferred; + /** + Resolve a Deferred object and call any doneCallbacks with the given args. + **/ + public function resolve(?args:Dynamic):js.jquery.Deferred; + /** + Resolve a Deferred object and call any doneCallbacks with the given context and args. + **/ + public function resolveWith(context:Dynamic, ?args:Array):js.jquery.Deferred; + /** + Determine the current state of a Deferred object. + **/ + public function state():String; + /** + Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. + **/ + @:overload(function(doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function, ?progressFilter:haxe.Constraints.Function):js.jquery.Promise { }) + @:overload(function(doneCallbacks:haxe.extern.EitherType>, failCallbacks:haxe.extern.EitherType>, ?progressCallbacks:haxe.extern.EitherType>):js.jquery.Promise { }) + public function then(doneCallbacks:haxe.extern.EitherType>, failCallbacks:haxe.extern.EitherType>):js.jquery.Promise; +} \ No newline at end of file diff --git a/std/js/jquery/Event.hx b/std/js/jquery/Event.hx new file mode 100644 index 00000000..90f2754c --- /dev/null +++ b/std/js/jquery/Event.hx @@ -0,0 +1,70 @@ +/* This file is generated, do not edit! Visit http://api.jquery.com/ for API documentation. */ +package js.jquery; +@:native("$.Event") extern class Event extends js.html.Event { + /** + An optional object of data passed to an event method when the current executing handler is bound. + **/ + public var data : Dynamic; + /** + The element where the currently-called jQuery event handler was attached. + **/ + public var delegateTarget : js.html.Element; + /** + Returns whether event.preventDefault() was ever called on this event object. + **/ + public function isDefaultPrevented():Bool; + /** + Returns whether event.stopImmediatePropagation() was ever called on this event object. + **/ + public function isImmediatePropagationStopped():Bool; + /** + Returns whether event.stopPropagation() was ever called on this event object. + **/ + public function isPropagationStopped():Bool; + /** + Indicates whether the META key was pressed when the event fired. + **/ + public var metaKey : Bool; + /** + The namespace specified when the event was triggered. + **/ + public var namespace : String; + /** + The mouse position relative to the left edge of the document. + **/ + public var pageX : Float; + /** + The mouse position relative to the top edge of the document. + **/ + public var pageY : Float; + /** + The other DOM element involved in the event, if any. + **/ + public var relatedTarget : js.html.Element; + /** + The last value returned by an event handler that was triggered by this event, unless the value was undefined. + **/ + public var result : Dynamic; + /** + For key or mouse events, this property indicates the specific key or button that was pressed. + **/ + public var which : Float; + public var altKey : Bool; + public var button : Int; + public var buttons : Int; + public var char : Int; + public var charCode : Int; + public var clientX : Int; + public var clientY : Int; + public var ctrlKey : Bool; + public var detail : Int; + public var key : String; + public var keyCode : Int; + public var offsetX : Int; + public var offsetY : Int; + public var screenX : Int; + public var screenY : Int; + public var shiftKey : Bool; + public var toElement : js.html.Element; + public var view : js.html.Window; +} \ No newline at end of file diff --git a/std/js/jquery/Helper.hx b/std/js/jquery/Helper.hx new file mode 100644 index 00000000..4e0c6041 --- /dev/null +++ b/std/js/jquery/Helper.hx @@ -0,0 +1,16 @@ +package js.jquery; + +@:noPackageRestrict +#if js extern #end class Helper { + macro public static function J(exprs:Array) { + return macro new js.jquery.JQuery($a{exprs}); + } + + #if !macro + public static var JTHIS(get, null) : js.jquery.JQuery; + + static inline function get_JTHIS() : js.jquery.JQuery { + return new js.jquery.JQuery(js.Lib.nativeThis); + } + #end +} \ No newline at end of file diff --git a/std/js/jquery/JQuery.hx b/std/js/jquery/JQuery.hx new file mode 100644 index 00000000..fdb961ce --- /dev/null +++ b/std/js/jquery/JQuery.hx @@ -0,0 +1,1097 @@ +/* This file is generated, do not edit! Visit http://api.jquery.com/ for API documentation. */ +package js.jquery; +@:native("$") extern class JQuery implements ArrayAccess { + /** + A multi-purpose callbacks list object that provides a powerful way to manage callback lists. + **/ + static public function Callbacks(flags:String):js.jquery.Callbacks; + /** + A factory function that returns a chainable utility object with methods to register multiple callbacks into callback queues, invoke callback queues, and relay the success or failure state of any synchronous or asynchronous function. + **/ + static public function Deferred(?beforeStart:js.jquery.Deferred -> Void):js.jquery.Deferred; + /** + Perform an asynchronous HTTP (Ajax) request. + **/ + @:overload(function(url:String, ?settings:Dynamic):js.jquery.JqXHR { }) + static public function ajax(?settings:Dynamic):js.jquery.JqXHR; + /** + Handle custom Ajax options or modify existing options before each request is sent and before they are processed by $.ajax(). + **/ + static public function ajaxPrefilter(?dataTypes:String, handler:Dynamic -> Dynamic -> js.jquery.JqXHR -> Void):Void; + /** + Set default values for future Ajax requests. Its use is not recommended. + **/ + static public function ajaxSetup(options:Dynamic):Void; + /** + Creates an object that handles the actual transmission of Ajax data. + **/ + static public function ajaxTransport(dataType:String, handler:Dynamic -> Dynamic -> js.jquery.JqXHR -> Void):Void; + /** + States if the current page, in the user's browser, is being rendered using the W3C CSS Box Model. This property was removed in jQuery 1.8. Please try to use feature detection instead. + **/ + @:deprecated("Deprecated since jQuery 1.3") + static public var boxModel : Bool; + /** + Contains flags for the useragent, read from navigator.userAgent. This property was removed in jQuery 1.9 and is available only through the jQuery.migrate plugin. Please try to use feature detection instead. + **/ + @:deprecated("Deprecated since jQuery 1.3") + static public var browser : Dynamic; + /** + Check to see if a DOM element is a descendant of another DOM element. + **/ + static public function contains(container:js.html.Element, contained:js.html.Element):Bool; + /** + Hook directly into jQuery to override how particular CSS properties are retrieved or set, normalize CSS property naming, or create custom properties. + **/ + static public var cssHooks : Dynamic; + /** + An object containing all CSS properties that may be used without a unit. The .css() method uses this object to see if it may append px to unitless values. + **/ + static public var cssNumber : Dynamic; + /** + Returns value at named data store for the element, as set by jQuery.data(element, name, value), or the full data store for the element. + OR + Store arbitrary data associated with the specified element. Returns the value that was set. + **/ + @:overload(function(element:js.html.Element, key:String):Dynamic { }) + @:overload(function(element:js.html.Element, key:String, value:Dynamic):Dynamic { }) + static public function data(element:js.html.Element):Dynamic; + /** + Execute the next function on the queue for the matched element. + **/ + static public function dequeue(element:js.html.Element, ?queueName:String):Void; + /** + A generic iterator function, which can be used to seamlessly iterate over both objects and arrays. Arrays and array-like objects with a length property (such as a function's arguments object) are iterated by numeric index, from 0 to length-1. Other objects are iterated via their named properties. + **/ + @:overload(function(object:Dynamic, callback:String -> Dynamic -> Void):Dynamic { }) + static public function each(array:Array, callback:Int -> Dynamic -> Void):Dynamic; + /** + Takes a string and throws an exception containing it. + **/ + static public function error(message:String):Void; + /** + Escapes any character that has a special meaning in a CSS selector. + **/ + static public function escapeSelector(selector:String):String; + /** + Merge the contents of two or more objects together into the first object. + **/ + @:overload(function(?deep:Bool, target:Dynamic, object1:Dynamic, ?objectN:Dynamic):Dynamic { }) + static public function extend(target:Dynamic, ?object1:Dynamic, ?objectN:Dynamic):Dynamic; + /** + An alias to `jQuery.prototype`. + **/ + static public var fn : Dynamic; + static public var fx : { /** + The rate (in milliseconds) at which animations fire. + **/ + var interval : Float; /** + Globally disable all animations. + **/ + var off : Bool; }; + /** + Load data from the server using a HTTP GET request. + **/ + @:overload(function(url:String, ?data:Dynamic, ?success:Dynamic -> String -> js.jquery.JqXHR -> Void, ?dataType:String):js.jquery.JqXHR { }) + static public function get(settings:Dynamic):js.jquery.JqXHR; + /** + Load JSON-encoded data from the server using a GET HTTP request. + **/ + static public function getJSON(url:String, ?data:Dynamic, ?success:Dynamic -> String -> js.jquery.JqXHR -> Void):js.jquery.JqXHR; + /** + Load a JavaScript file from the server using a GET HTTP request, then execute it. + **/ + static public function getScript(url:String, ?success:String -> String -> js.jquery.JqXHR -> Void):js.jquery.JqXHR; + /** + Execute some JavaScript code globally. + **/ + static public function globalEval(code:String):Void; + /** + Finds the elements of an array which satisfy a filter function. The original array is not affected. + **/ + static public function grep(array:haxe.extern.EitherType, js.html.NodeList>, _function:Dynamic -> Int -> Bool, ?invert:Bool):Array; + /** + Determine whether an element has any jQuery data associated with it. + **/ + static public function hasData(element:js.html.Element):Bool; + /** + Holds or releases the execution of jQuery's ready event. + **/ + static public function holdReady(hold:Bool):Void; + /** + Modify and filter HTML strings passed through jQuery manipulation methods. + **/ + static public function htmlPrefilter(html:String):String; + /** + Search for a specified value within an array and return its index (or -1 if not found). + **/ + static public function inArray(value:Dynamic, array:Array, ?fromIndex:Float):Float; + /** + Determine whether the argument is an array. + **/ + static public function isArray(obj:Dynamic):Bool; + /** + Check to see if an object is empty (contains no enumerable properties). + **/ + static public function isEmptyObject(object:Dynamic):Bool; + /** + Determine if the argument passed is a JavaScript function object. + **/ + static public function isFunction(obj:Dynamic):Bool; + /** + Determines whether its argument represents a JavaScript number. + **/ + static public function isNumeric(value:Dynamic):Bool; + /** + Check to see if an object is a plain object (created using "{}" or "new Object"). + **/ + static public function isPlainObject(object:Dynamic):Bool; + /** + Determine whether the argument is a window. + **/ + static public function isWindow(obj:Dynamic):Bool; + /** + Check to see if a DOM node is within an XML document (or is an XML document). + **/ + static public function isXMLDoc(node:js.html.Element):Bool; + /** + Convert an array-like object into a true JavaScript array. + **/ + static public function makeArray(obj:Dynamic):Array; + /** + Translate all items in an array or object to new array of items. + **/ + @:overload(function(object:Dynamic, callback:Dynamic -> String -> Dynamic):Array { }) + static public function map(array:Array, callback:Dynamic -> Int -> Dynamic):Array; + /** + Merge the contents of two arrays together into the first array. + **/ + static public function merge(first:haxe.extern.EitherType, js.html.NodeList>, second:haxe.extern.EitherType, js.html.NodeList>):Array; + /** + Relinquish jQuery's control of the $ variable. + **/ + static public function noConflict(?removeAll:Bool):Dynamic; + /** + An empty function. + **/ + static public function noop():Void; + /** + Return a number representing the current time. + **/ + static public function now():Float; + /** + Create a serialized representation of an array, a plain object, or a jQuery object suitable for use in a URL query string or Ajax request. In case a jQuery object is passed, it should contain input elements with name/value properties. + **/ + @:overload(function(obj:Dynamic, traditional:Bool):String { }) + static public function param(obj:Dynamic):String; + /** + Parses a string into an array of DOM nodes. + **/ + static public function parseHTML(data:String, ?context:js.html.Element, ?keepScripts:Bool):Array; + /** + Takes a well-formed JSON string and returns the resulting JavaScript value. + **/ + @:deprecated("Deprecated since jQuery 3.0") + static public function parseJSON(json:String):Dynamic; + /** + Parses a string into an XML document. + **/ + static public function parseXML(data:String):js.html.Document; + /** + Load data from the server using a HTTP POST request. + **/ + @:overload(function(url:String, ?data:Dynamic, ?success:Dynamic -> String -> js.jquery.JqXHR -> Void, ?dataType:String):js.jquery.JqXHR { }) + static public function post(settings:Dynamic):js.jquery.JqXHR; + /** + Takes a function and returns a new one that will always have a particular context. + **/ + @:overload(function(context:Dynamic, name:String):haxe.Constraints.Function { }) + @:overload(function(_function:haxe.Constraints.Function, context:Dynamic, ?additionalArguments:Dynamic):haxe.Constraints.Function { }) + @:overload(function(context:Dynamic, name:String, ?additionalArguments:Dynamic):haxe.Constraints.Function { }) + static public function proxy(_function:haxe.Constraints.Function, context:Dynamic):haxe.Constraints.Function; + /** + Show the queue of functions to be executed on the matched element. + OR + Manipulate the queue of functions to be executed on the matched element. + **/ + @:overload(function(element:js.html.Element, queueName:String, newQueue:Array Void>):js.jquery.JQuery { }) + @:overload(function(element:js.html.Element, queueName:String, callback:haxe.Constraints.Function):js.jquery.JQuery { }) + static public function queue(element:js.html.Element, ?queueName:String):Array Void>; + /** + Handles errors thrown synchronously in functions wrapped in jQuery(). + **/ + static public dynamic function readyException(error:js.Error):String; + /** + Remove a previously-stored piece of data. + **/ + static public function removeData(element:js.html.Element, ?name:String):js.jquery.JQuery; + /** + Creates an object containing a set of properties ready to be used in the definition of custom animations. + **/ + @:overload(function(?duration:haxe.extern.EitherType, ?settings:Dynamic):Dynamic { }) + @:overload(function(?duration:haxe.extern.EitherType, ?easing:String, ?complete:haxe.Constraints.Function):Dynamic { }) + static public function speed(settings:Dynamic):Dynamic; + /** + Creates a new copy of jQuery whose properties and methods can be modified without affecting the original jQuery object. + **/ + @:deprecated("Deprecated since jQuery 1.7") + static public function sub():js.jquery.JQuery; + /** + A collection of properties that represent the presence of different browser features or bugs. Intended for jQuery's internal use; specific properties may be removed when they are no longer needed internally to improve page startup performance. For your own project's feature-detection needs, we strongly recommend the use of an external library such as Modernizr instead of dependency on properties in jQuery.support. + **/ + @:deprecated("Deprecated since jQuery 1.9") + static public var support : Dynamic; + /** + Remove the whitespace from the beginning and end of a string. + **/ + static public function trim(str:String):String; + /** + Determine the internal JavaScript [[Class]] of an object. + **/ + static public function type(obj:Dynamic):String; + /** + Sorts an array of DOM elements, in place, with the duplicates removed. Note that this only works on arrays of DOM elements, not strings or numbers. + **/ + @:deprecated("Deprecated since jQuery 3.0") + static public function unique(array:Array):Array; + /** + Sorts an array of DOM elements, in place, with the duplicates removed. Note that this only works on arrays of DOM elements, not strings or numbers. + **/ + static public function uniqueSort(array:Array):Array; + /** + Provides a way to execute callback functions based on zero or more objects, usually Deferred objects that represent asynchronous events. + **/ + static public function when(deferreds:haxe.extern.Rest):js.jquery.Promise; + /** + Create a new jQuery object with elements added to the set of matched elements. + **/ + @:overload(function(elements:js.html.Element):js.jquery.JQuery { }) + @:overload(function(html:String):js.jquery.JQuery { }) + @:overload(function(selection:js.jquery.JQuery):js.jquery.JQuery { }) + @:overload(function(selector:String, context:js.html.Element):js.jquery.JQuery { }) + public function add(selector:String):js.jquery.JQuery; + /** + Add the previous set of elements on the stack to the current set, optionally filtered by a selector. + **/ + public function addBack(?selector:String):js.jquery.JQuery; + /** + Adds the specified class(es) to each element in the set of matched elements. + **/ + @:overload(function(_function:Int -> String -> String):js.jquery.JQuery { }) + public function addClass(className:String):js.jquery.JQuery; + /** + Insert content, specified by the parameter, after each element in the set of matched elements. + **/ + @:overload(function(_function:Int -> String -> haxe.extern.EitherType>):js.jquery.JQuery { }) + @:overload(function(content:haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType>>>>>, ?content:haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType>>>>>):js.jquery.JQuery { }) + public function after(_function:Int -> haxe.extern.EitherType>):js.jquery.JQuery; + /** + Register a handler to be called when Ajax requests complete. This is an AjaxEvent. + **/ + public function ajaxComplete(handler:js.jquery.Event -> js.jquery.JqXHR -> Dynamic -> Void):js.jquery.JQuery; + /** + Register a handler to be called when Ajax requests complete with an error. This is an Ajax Event. + **/ + public function ajaxError(handler:js.jquery.Event -> js.jquery.JqXHR -> Dynamic -> String -> Void):js.jquery.JQuery; + /** + Attach a function to be executed before an Ajax request is sent. This is an Ajax Event. + **/ + public function ajaxSend(handler:js.jquery.Event -> js.jquery.JqXHR -> Dynamic -> Void):js.jquery.JQuery; + /** + Register a handler to be called when the first Ajax request begins. This is an Ajax Event. + **/ + public function ajaxStart(handler:haxe.Constraints.Function):js.jquery.JQuery; + /** + Register a handler to be called when all Ajax requests have completed. This is an Ajax Event. + **/ + public function ajaxStop(handler:haxe.Constraints.Function):js.jquery.JQuery; + /** + Attach a function to be executed whenever an Ajax request completes successfully. This is an Ajax Event. + **/ + public function ajaxSuccess(handler:js.jquery.Event -> js.jquery.JqXHR -> Dynamic -> Dynamic -> Void):js.jquery.JQuery; + /** + Add the previous set of elements on the stack to the current set. + **/ + @:deprecated("Deprecated since jQuery 1.8") + public function andSelf():js.jquery.JQuery; + /** + Perform a custom animation of a set of CSS properties. + **/ + @:overload(function(properties:Dynamic, ?duration:haxe.extern.EitherType, ?easing:String, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + public function animate(properties:Dynamic, options:Dynamic):js.jquery.JQuery; + /** + Insert content, specified by the parameter, to the end of each element in the set of matched elements. + **/ + @:overload(function(content:haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType>>>>>, ?content:haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType>>>>>):js.jquery.JQuery { }) + public function append(_function:Int -> String -> haxe.extern.EitherType>):js.jquery.JQuery; + /** + Insert every element in the set of matched elements to the end of the target. + **/ + public function appendTo(target:haxe.extern.EitherType, haxe.extern.EitherType>>):js.jquery.JQuery; + /** + Set one or more attributes for the set of matched elements. + OR + Get the value of an attribute for the first element in the set of matched elements. + **/ + @:overload(function(attributes:Dynamic):js.jquery.JQuery { }) + @:overload(function(attributeName:String, value:haxe.extern.EitherType):js.jquery.JQuery { }) + @:overload(function(attributeName:String, _function:Int -> String -> haxe.extern.EitherType):js.jquery.JQuery { }) + public function attr(attributeName:String):String; + /** + Insert content, specified by the parameter, before each element in the set of matched elements. + **/ + @:overload(function(_function:Int -> String -> haxe.extern.EitherType>):js.jquery.JQuery { }) + @:overload(function(content:haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType>>>>>, ?content:haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType>>>>>):js.jquery.JQuery { }) + public function before(_function:Int -> haxe.extern.EitherType>):js.jquery.JQuery; + /** + Attach a handler to an event for the elements. + **/ + @:overload(function(eventType:String, ?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(eventType:String, ?eventData:Dynamic, ?preventBubble:Bool):js.jquery.JQuery { }) + public function bind(events:Dynamic):js.jquery.JQuery; + /** + Bind an event handler to the "blur" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function blur():js.jquery.JQuery; + /** + Bind an event handler to the "change" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function change():js.jquery.JQuery; + /** + Get the children of each element in the set of matched elements, optionally filtered by a selector. + **/ + public function children(?selector:String):js.jquery.JQuery; + /** + Remove from the queue all items that have not yet been run. + **/ + public function clearQueue(?queueName:String):js.jquery.JQuery; + /** + Bind an event handler to the "click" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function click():js.jquery.JQuery; + /** + Create a deep copy of the set of matched elements. + **/ + @:overload(function(?withDataAndEvents:Bool, ?deepWithDataAndEvents:Bool):js.jquery.JQuery { }) + public function clone(?withDataAndEvents:Bool):js.jquery.JQuery; + /** + For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. + OR + Get an array of all the elements and selectors matched against the current element up through the DOM tree. + **/ + @:overload(function(selection:js.jquery.JQuery):js.jquery.JQuery { }) + @:overload(function(element:js.html.Element):js.jquery.JQuery { }) + @:overload(function(selector:String, ?context:js.html.Element):js.jquery.JQuery { }) + @:overload(function(selectors:haxe.extern.EitherType, haxe.extern.EitherType>, ?context:js.html.Element):Array { }) + public function closest(selector:String):js.jquery.JQuery; + /** + Get the children of each element in the set of matched elements, including text and comment nodes. + **/ + public function contents():js.jquery.JQuery; + /** + The DOM node context originally passed to jQuery(); if none was passed then context will likely be the document. + **/ + @:deprecated("Deprecated since jQuery 1.10") + public var context : js.html.Element; + /** + Bind an event handler to the "contextmenu" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function contextmenu():js.jquery.JQuery; + /** + Set one or more CSS properties for the set of matched elements. + OR + Get the computed style properties for the first element in the set of matched elements. + **/ + @:overload(function(propertyNames:Array):String { }) + @:overload(function(properties:Dynamic):js.jquery.JQuery { }) + @:overload(function(propertyName:String, value:haxe.extern.EitherType):js.jquery.JQuery { }) + @:overload(function(propertyName:String, _function:Int -> String -> haxe.extern.EitherType):js.jquery.JQuery { }) + public function css(propertyName:String):String; + /** + Return the value at the named data store for the first element in the jQuery collection, as set by data(name, value) or by an HTML5 data-* attribute. + OR + Store arbitrary data associated with the matched elements. + **/ + @:overload(function(key:String):Dynamic { }) + @:overload(function(obj:Dynamic):js.jquery.JQuery { }) + @:overload(function(key:String, value:Dynamic):js.jquery.JQuery { }) + public function data():Dynamic; + /** + Bind an event handler to the "dblclick" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function dblclick():js.jquery.JQuery; + /** + Set a timer to delay execution of subsequent items in the queue. + **/ + public function delay(duration:Int, ?queueName:String):js.jquery.JQuery; + /** + Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements. + **/ + @:overload(function(selector:String, eventType:String, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(selector:String, eventType:String, eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function delegate(selector:String, events:Dynamic):js.jquery.JQuery; + /** + Execute the next function on the queue for the matched elements. + **/ + public function dequeue(?queueName:String):js.jquery.JQuery; + /** + Remove the set of matched elements from the DOM. + **/ + public function detach(?selector:String):js.jquery.JQuery; + /** + Remove event handlers previously attached using .live() from the elements. + **/ + @:deprecated("Deprecated since jQuery 1.7") + @:overload(function(events:Dynamic):js.jquery.JQuery { }) + @:overload(function(eventType:String, ?handler:String):js.jquery.JQuery { }) + public function die():js.jquery.JQuery; + /** + Iterate over a jQuery object, executing a function for each matched element. + **/ + public function each(_function:Int -> js.html.Element -> Void):js.jquery.JQuery; + /** + Remove all child nodes of the set of matched elements from the DOM. + **/ + public function empty():js.jquery.JQuery; + /** + End the most recent filtering operation in the current chain and return the set of matched elements to its previous state. + **/ + public function end():js.jquery.JQuery; + /** + Reduce the set of matched elements to the one at the specified index. + **/ + @:overload(function(indexFromEnd:Int):js.jquery.JQuery { }) + public function eq(index:Int):js.jquery.JQuery; + /** + Bind an event handler to the "error" JavaScript event. + **/ + @:deprecated("Deprecated since jQuery 1.8") + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function error(handler:js.jquery.Event -> Void):js.jquery.JQuery; + /** + Display the matched elements by fading them to opaque. + **/ + @:overload(function(?duration:haxe.extern.EitherType, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + @:overload(function(?duration:haxe.extern.EitherType, ?easing:String, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + public function fadeIn(options:Dynamic):js.jquery.JQuery; + /** + Hide the matched elements by fading them to transparent. + **/ + @:overload(function(?duration:haxe.extern.EitherType, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + @:overload(function(?duration:haxe.extern.EitherType, ?easing:String, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + public function fadeOut(options:Dynamic):js.jquery.JQuery; + /** + Adjust the opacity of the matched elements. + **/ + @:overload(function(duration:haxe.extern.EitherType, opacity:Float, ?easing:String, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + public function fadeTo(duration:haxe.extern.EitherType, opacity:Float, ?complete:haxe.Constraints.Function):js.jquery.JQuery; + /** + Display or hide the matched elements by animating their opacity. + **/ + @:overload(function(?duration:haxe.extern.EitherType, ?easing:String, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + public function fadeToggle(options:Dynamic):js.jquery.JQuery; + /** + Reduce the set of matched elements to those that match the selector or pass the function's test. + **/ + @:overload(function(elements:js.html.Element):js.jquery.JQuery { }) + @:overload(function(selection:js.jquery.JQuery):js.jquery.JQuery { }) + @:overload(function(_function:Int -> js.html.Element -> Bool):js.jquery.JQuery { }) + public function filter(selector:String):js.jquery.JQuery; + /** + Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element. + **/ + @:overload(function(element:haxe.extern.EitherType):js.jquery.JQuery { }) + public function find(selector:String):js.jquery.JQuery; + /** + Stop the currently-running animation, remove all queued animations, and complete all animations for the matched elements. + **/ + public function finish(?queue:String):js.jquery.JQuery; + /** + Reduce the set of matched elements to the first in the set. + **/ + public function first():js.jquery.JQuery; + /** + Bind an event handler to the "focus" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function focus():js.jquery.JQuery; + /** + Bind an event handler to the "focusin" event. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function focusin():js.jquery.JQuery; + /** + Bind an event handler to the "focusout" JavaScript event. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function focusout():js.jquery.JQuery; + /** + Retrieve one of the elements matched by the jQuery object. + OR + Retrieve the elements matched by the jQuery object. + **/ + @:overload(function(index:Int):js.html.Element { }) + public function get():Array; + /** + Reduce the set of matched elements to those that have a descendant that matches the selector or DOM element. + **/ + @:overload(function(contained:js.html.Element):js.jquery.JQuery { }) + public function has(selector:String):js.jquery.JQuery; + /** + Determine whether any of the matched elements are assigned the given class. + **/ + public function hasClass(className:String):Bool; + /** + Set the CSS height of every matched element. + OR + Get the current computed height for the first element in the set of matched elements. + **/ + @:overload(function(value:haxe.extern.EitherType):js.jquery.JQuery { }) + @:overload(function(_function:Int -> Int -> haxe.extern.EitherType):js.jquery.JQuery { }) + public function height():Float; + /** + Hide the matched elements. + **/ + @:overload(function(options:Dynamic):js.jquery.JQuery { }) + @:overload(function(?duration:haxe.extern.EitherType, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + @:overload(function(duration:haxe.extern.EitherType, ?easing:String, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + public function hide():js.jquery.JQuery; + /** + Bind two handlers to the matched elements, to be executed when the mouse pointer enters and leaves the elements. + OR + Bind a single handler to the matched elements, to be executed when the mouse pointer enters or leaves the elements. + **/ + @:overload(function(handlerIn:js.jquery.Event -> Void, handlerOut:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function hover(handlerInOut:js.jquery.Event -> Void):js.jquery.JQuery; + /** + Get the HTML contents of the first element in the set of matched elements. + OR + Set the HTML contents of each element in the set of matched elements. + **/ + @:overload(function(htmlString:String):js.jquery.JQuery { }) + @:overload(function(_function:Int -> String -> String):js.jquery.JQuery { }) + public function html():String; + /** + Search for a given element from among the matched elements. + **/ + @:overload(function(selector:String):Int { }) + @:overload(function(element:haxe.extern.EitherType):Int { }) + public function index():Int; + /** + Set the CSS inner height of each element in the set of matched elements. + OR + Get the current computed height for the first element in the set of matched elements, including padding but not border. + **/ + @:overload(function(value:haxe.extern.EitherType):js.jquery.JQuery { }) + @:overload(function(_function:Int -> Float -> haxe.extern.EitherType):js.jquery.JQuery { }) + public function innerHeight():Float; + /** + Get the current computed inner width for the first element in the set of matched elements, including padding but not border. + OR + Set the CSS inner width of each element in the set of matched elements. + **/ + @:overload(function(value:haxe.extern.EitherType):js.jquery.JQuery { }) + @:overload(function(_function:Int -> Float -> haxe.extern.EitherType):js.jquery.JQuery { }) + public function innerWidth():Float; + /** + Insert every element in the set of matched elements after the target. + **/ + public function insertAfter(target:haxe.extern.EitherType, haxe.extern.EitherType>>):js.jquery.JQuery; + /** + Insert every element in the set of matched elements before the target. + **/ + public function insertBefore(target:haxe.extern.EitherType, haxe.extern.EitherType>>):js.jquery.JQuery; + /** + Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments. + **/ + @:overload(function(selection:js.jquery.JQuery):Bool { }) + @:overload(function(elements:js.html.Element):Bool { }) + @:overload(function(_function:Int -> js.html.Element -> Bool):Bool { }) + public function is(selector:String):Bool; + /** + A string containing the jQuery version number. + **/ + public var jquery : String; + /** + Bind an event handler to the "keydown" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function keydown():js.jquery.JQuery; + /** + Bind an event handler to the "keypress" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function keypress():js.jquery.JQuery; + /** + Bind an event handler to the "keyup" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function keyup():js.jquery.JQuery; + /** + Reduce the set of matched elements to the final one in the set. + **/ + public function last():js.jquery.JQuery; + /** + The number of elements in the jQuery object. + **/ + public var length(default, null) : Int; + /** + Attach an event handler for all elements which match the current selector, now and in the future. + **/ + @:deprecated("Deprecated since jQuery 1.7") + @:overload(function(events:String, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(events:String, ?data:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function live(events:Dynamic):js.jquery.JQuery; + /** + Bind an event handler to the "load" JavaScript event. + OR + Load data from the server and place the returned HTML into the matched element. + **/ + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(url:String, ?data:Dynamic, ?complete:String -> String -> js.jquery.JqXHR -> Void):js.jquery.JQuery { }) + public function load(handler:js.jquery.Event -> Void):js.jquery.JQuery; + /** + Pass each element in the current matched set through a function, producing a new jQuery object containing the return values. + **/ + public function map(callback:Int -> js.html.Element -> Dynamic):js.jquery.JQuery; + /** + Bind an event handler to the "mousedown" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function mousedown():js.jquery.JQuery; + /** + Bind an event handler to be fired when the mouse enters an element, or trigger that handler on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function mouseenter():js.jquery.JQuery; + /** + Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function mouseleave():js.jquery.JQuery; + /** + Bind an event handler to the "mousemove" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function mousemove():js.jquery.JQuery; + /** + Bind an event handler to the "mouseout" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function mouseout():js.jquery.JQuery; + /** + Bind an event handler to the "mouseover" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function mouseover():js.jquery.JQuery; + /** + Bind an event handler to the "mouseup" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function mouseup():js.jquery.JQuery; + /** + Creates DOM elements on the fly from the provided string of raw HTML. + OR + Accepts a string containing a CSS selector which is then used to match a set of elements. + OR + Binds a function to be executed when the DOM has finished loading. + **/ + @:selfCall + @:overload(function(element:js.html.Element):Void { }) + @:overload(function(elementArray:haxe.extern.EitherType>):Void { }) + @:overload(function(selection:js.jquery.JQuery):Void { }) + @:overload(function(callback:haxe.Constraints.Function):Void { }) + @:overload(function(object:Dynamic):Void { }) + @:overload(function(html:String, attributes:Dynamic):Void { }) + @:overload(function(selector:String, ?context:haxe.extern.EitherType):Void { }) + @:overload(function(html:String, ?ownerDocument:js.html.Document):Void { }) + public function new():Void; + /** + Get the immediately following sibling of each element in the set of matched elements. If a selector is provided, it retrieves the next sibling only if it matches that selector. + **/ + public function next(?selector:String):js.jquery.JQuery; + /** + Get all following siblings of each element in the set of matched elements, optionally filtered by a selector. + **/ + public function nextAll(?selector:String):js.jquery.JQuery; + /** + Get all following siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object passed. + **/ + @:overload(function(?element:haxe.extern.EitherType, ?filter:String):js.jquery.JQuery { }) + public function nextUntil(?selector:String, ?filter:String):js.jquery.JQuery; + /** + Remove elements from the set of matched elements. + **/ + @:overload(function(selection:js.jquery.JQuery):js.jquery.JQuery { }) + @:overload(function(_function:Int -> js.html.Element -> Bool):js.jquery.JQuery { }) + public function not(selector:haxe.extern.EitherType, String>>):js.jquery.JQuery; + /** + Remove an event handler. + **/ + @:overload(function(event:js.jquery.Event):js.jquery.JQuery { }) + @:overload(function(events:Dynamic, ?selector:String):js.jquery.JQuery { }) + @:overload(function(events:String, ?selector:String, ?handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function off():js.jquery.JQuery; + /** + Get the current coordinates of the first element in the set of matched elements, relative to the document. + OR + Set the current coordinates of every element in the set of matched elements, relative to the document. + **/ + @:overload(function(coordinates:{ var top : Float; var left : Float; }):js.jquery.JQuery { }) + @:overload(function(_function:Int -> { var top : Float; var left : Float; } -> Dynamic):js.jquery.JQuery { }) + public function offset():{ var top : Float; var left : Float; }; + /** + Get the closest ancestor element that is positioned. + **/ + public function offsetParent():js.jquery.JQuery; + /** + Attach an event handler function for one or more events to the selected elements. + **/ + @:overload(function(events:String, ?selector:String, ?data:Dynamic, handler:js.jquery.Event -> haxe.extern.Rest -> Void):js.jquery.JQuery { }) + public function on(events:Dynamic, ?selector:String, ?data:Dynamic):js.jquery.JQuery; + /** + Attach a handler to an event for the elements. The handler is executed at most once per element per event type. + **/ + @:overload(function(events:Dynamic, ?selector:String, ?data:Dynamic):js.jquery.JQuery { }) + @:overload(function(events:String, ?selector:String, ?data:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function one(events:String, ?data:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery; + /** + Get the current computed height for the first element in the set of matched elements, including padding, border, and optionally margin. Returns a number (without "px") representation of the value or null if called on an empty set of elements. + OR + Set the CSS outer Height of each element in the set of matched elements. + **/ + @:overload(function(_function:haxe.Constraints.Function):js.jquery.JQuery { }) + @:overload(function(?includeMargin:Bool):Float { }) + public function outerHeight(value:haxe.extern.EitherType):js.jquery.JQuery; + /** + Get the current computed width for the first element in the set of matched elements, including padding and border. + OR + Set the CSS outer width of each element in the set of matched elements. + **/ + @:overload(function(_function:haxe.Constraints.Function):js.jquery.JQuery { }) + @:overload(function(?includeMargin:Bool):Float { }) + public function outerWidth(value:haxe.extern.EitherType):js.jquery.JQuery; + /** + Get the parent of each element in the current set of matched elements, optionally filtered by a selector. + **/ + public function parent(?selector:String):js.jquery.JQuery; + /** + Get the ancestors of each element in the current set of matched elements, optionally filtered by a selector. + **/ + public function parents(?selector:String):js.jquery.JQuery; + /** + Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector, DOM node, or jQuery object. + **/ + @:overload(function(?element:haxe.extern.EitherType, ?filter:String):js.jquery.JQuery { }) + public function parentsUntil(?selector:String, ?filter:String):js.jquery.JQuery; + /** + Get the current coordinates of the first element in the set of matched elements, relative to the offset parent. + **/ + public function position():{ var top : Float; var left : Float; }; + /** + Insert content, specified by the parameter, to the beginning of each element in the set of matched elements. + **/ + @:overload(function(content:haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType>>>>>, ?content:haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType, haxe.extern.EitherType>>>>>):js.jquery.JQuery { }) + public function prepend(_function:Int -> String -> haxe.extern.EitherType>):js.jquery.JQuery; + /** + Insert every element in the set of matched elements to the beginning of the target. + **/ + public function prependTo(target:haxe.extern.EitherType, haxe.extern.EitherType>>):js.jquery.JQuery; + /** + Get the immediately preceding sibling of each element in the set of matched elements. If a selector is provided, it retrieves the previous sibling only if it matches that selector. + **/ + public function prev(?selector:String):js.jquery.JQuery; + /** + Get all preceding siblings of each element in the set of matched elements, optionally filtered by a selector. + **/ + public function prevAll(?selector:String):js.jquery.JQuery; + /** + Get all preceding siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object. + **/ + @:overload(function(?element:haxe.extern.EitherType, ?filter:String):js.jquery.JQuery { }) + public function prevUntil(?selector:String, ?filter:String):js.jquery.JQuery; + /** + Return a Promise object to observe when all actions of a certain type bound to the collection, queued or not, have finished. + **/ + public function promise(?type:String, ?target:Dynamic):js.jquery.Promise; + /** + Set one or more properties for the set of matched elements. + OR + Get the value of a property for the first element in the set of matched elements. + **/ + @:overload(function(properties:Dynamic):js.jquery.JQuery { }) + @:overload(function(propertyName:String, _function:Int -> Dynamic -> Dynamic):js.jquery.JQuery { }) + @:overload(function(propertyName:String, value:Dynamic):js.jquery.JQuery { }) + public function prop(propertyName:String):Dynamic; + /** + Add a collection of DOM elements onto the jQuery stack. + **/ + @:overload(function(elements:haxe.extern.EitherType, js.html.NodeList>, name:String, arguments:Array):js.jquery.JQuery { }) + public function pushStack(elements:haxe.extern.EitherType, js.html.NodeList>):js.jquery.JQuery; + /** + Show the queue of functions to be executed on the matched elements. + OR + Manipulate the queue of functions to be executed, once for each matched element. + **/ + @:overload(function(?queueName:String, newQueue:Array Void>):js.jquery.JQuery { }) + @:overload(function(?queueName:String, callback:haxe.Constraints.Function -> Void):js.jquery.JQuery { }) + public function queue(?queueName:String):Array Void>; + /** + Specify a function to execute when the DOM is fully loaded. + **/ + public function ready(handler:haxe.Constraints.Function):js.jquery.JQuery; + /** + Remove the set of matched elements from the DOM. + **/ + public function remove(?selector:String):js.jquery.JQuery; + /** + Remove an attribute from each element in the set of matched elements. + **/ + public function removeAttr(attributeName:String):js.jquery.JQuery; + /** + Remove a single class, multiple classes, or all classes from each element in the set of matched elements. + **/ + @:overload(function(?className:String):js.jquery.JQuery { }) + public function removeClass(_function:Int -> String -> String):js.jquery.JQuery; + /** + Remove a previously-stored piece of data. + **/ + @:overload(function(?list:haxe.extern.EitherType, String>):js.jquery.JQuery { }) + public function removeData(?name:String):js.jquery.JQuery; + /** + Remove a property for the set of matched elements. + **/ + public function removeProp(propertyName:String):js.jquery.JQuery; + /** + Replace each target element with the set of matched elements. + **/ + public function replaceAll(target:haxe.extern.EitherType, haxe.extern.EitherType>>):js.jquery.JQuery; + /** + Replace each element in the set of matched elements with the provided new content and return the set of elements that was removed. + **/ + @:overload(function(_function:haxe.Constraints.Function):js.jquery.JQuery { }) + public function replaceWith(newContent:haxe.extern.EitherType, haxe.extern.EitherType>>):js.jquery.JQuery; + /** + Bind an event handler to the "resize" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function resize():js.jquery.JQuery; + /** + Bind an event handler to the "scroll" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function scroll():js.jquery.JQuery; + /** + Get the current horizontal position of the scroll bar for the first element in the set of matched elements. + OR + Set the current horizontal position of the scroll bar for each of the set of matched elements. + **/ + @:overload(function(value:Float):js.jquery.JQuery { }) + public function scrollLeft():Int; + /** + Set the current vertical position of the scroll bar for each of the set of matched elements. + OR + Get the current vertical position of the scroll bar for the first element in the set of matched elements or set the vertical position of the scroll bar for every matched element. + **/ + @:overload(function(value:Float):js.jquery.JQuery { }) + public function scrollTop():Float; + /** + Bind an event handler to the "select" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function select():js.jquery.JQuery; + /** + A selector representing selector passed to jQuery(), if any, when creating the original set. + **/ + @:deprecated("Deprecated since jQuery 1.7") + public var selector : String; + /** + Encode a set of form elements as a string for submission. + **/ + public function serialize():String; + /** + Encode a set of form elements as an array of names and values. + **/ + public function serializeArray():Array; + /** + Display the matched elements. + **/ + @:overload(function(options:Dynamic):js.jquery.JQuery { }) + @:overload(function(?duration:haxe.extern.EitherType, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + @:overload(function(duration:haxe.extern.EitherType, ?easing:String, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + public function show():js.jquery.JQuery; + /** + Get the siblings of each element in the set of matched elements, optionally filtered by a selector. + **/ + public function siblings(?selector:String):js.jquery.JQuery; + /** + Return the number of elements in the jQuery object. + **/ + @:deprecated("Deprecated since jQuery 1.8") + public function size():Int; + /** + Reduce the set of matched elements to a subset specified by a range of indices. + **/ + public function slice(start:Int, ?end:Int):js.jquery.JQuery; + /** + Display the matched elements with a sliding motion. + **/ + @:overload(function(?duration:haxe.extern.EitherType, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + @:overload(function(?duration:haxe.extern.EitherType, ?easing:String, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + public function slideDown(options:Dynamic):js.jquery.JQuery; + /** + Display or hide the matched elements with a sliding motion. + **/ + @:overload(function(?duration:haxe.extern.EitherType, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + @:overload(function(?duration:haxe.extern.EitherType, ?easing:String, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + public function slideToggle(options:Dynamic):js.jquery.JQuery; + /** + Hide the matched elements with a sliding motion. + **/ + @:overload(function(?duration:haxe.extern.EitherType, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + @:overload(function(?duration:haxe.extern.EitherType, ?easing:String, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + public function slideUp(options:Dynamic):js.jquery.JQuery; + /** + Stop the currently-running animation on the matched elements. + **/ + @:overload(function(?queue:String, ?clearQueue:Bool, ?jumpToEnd:Bool):js.jquery.JQuery { }) + public function stop(?clearQueue:Bool, ?jumpToEnd:Bool):js.jquery.JQuery; + /** + Bind an event handler to the "submit" JavaScript event, or trigger that event on an element. + **/ + @:overload(function(handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function submit():js.jquery.JQuery; + /** + Set the content of each element in the set of matched elements to the specified text. + OR + Get the combined text contents of each element in the set of matched elements, including their descendants. + **/ + @:overload(function(text:haxe.extern.EitherType>):js.jquery.JQuery { }) + @:overload(function(_function:Int -> String -> String):js.jquery.JQuery { }) + public function text():String; + /** + Retrieve all the elements contained in the jQuery set, as an array. + **/ + public function toArray():Array; + /** + Bind two or more handlers to the matched elements, to be executed on alternate clicks. + OR + Display or hide the matched elements. + **/ + @:overload(function(options:Dynamic):js.jquery.JQuery { }) + @:overload(function(?duration:haxe.extern.EitherType, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + @:overload(function(duration:haxe.extern.EitherType, ?easing:String, ?complete:haxe.Constraints.Function):js.jquery.JQuery { }) + @:overload(function(handler:js.jquery.Event -> Void, handler:js.jquery.Event -> Void, ?handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function toggle(display:Bool):js.jquery.JQuery; + /** + Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the state argument. + **/ + @:overload(function(?state:Bool):js.jquery.JQuery { }) + @:overload(function(className:String, state:Bool):js.jquery.JQuery { }) + @:overload(function(_function:Int -> String -> Bool -> String, ?state:Bool):js.jquery.JQuery { }) + public function toggleClass(className:String):js.jquery.JQuery; + /** + Execute all handlers and behaviors attached to the matched elements for the given event type. + **/ + @:overload(function(event:js.jquery.Event, ?extraParameters:Dynamic):js.jquery.JQuery { }) + public function trigger(eventType:String, ?extraParameters:Dynamic):js.jquery.JQuery; + /** + Execute all handlers attached to an element for an event. + **/ + @:overload(function(event:js.jquery.Event, ?extraParameters:Dynamic):Dynamic { }) + public function triggerHandler(eventType:String, ?extraParameters:Dynamic):Dynamic; + /** + Remove a previously-attached event handler from the elements. + **/ + @:overload(function(event:js.jquery.Event):js.jquery.JQuery { }) + @:overload(function(eventType:String, _false:Bool):js.jquery.JQuery { }) + @:overload(function(eventType:String, ?handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function unbind():js.jquery.JQuery; + /** + Remove a handler from the event for all elements which match the current selector, based upon a specific set of root elements. + **/ + @:overload(function(namespace:String):js.jquery.JQuery { }) + @:overload(function(selector:String, eventType:String):js.jquery.JQuery { }) + @:overload(function(selector:String, events:Dynamic):js.jquery.JQuery { }) + @:overload(function(selector:String, eventType:String, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function undelegate():js.jquery.JQuery; + /** + Bind an event handler to the "unload" JavaScript event. + **/ + @:deprecated("Deprecated since jQuery 1.8") + @:overload(function(?eventData:Dynamic, handler:js.jquery.Event -> Void):js.jquery.JQuery { }) + public function unload(handler:js.jquery.Event -> Void):js.jquery.JQuery; + /** + Remove the parents of the set of matched elements from the DOM, leaving the matched elements in their place. + **/ + @:overload(function(?selector:String):js.jquery.JQuery { }) + public function unwrap():js.jquery.JQuery; + /** + Set the value of each element in the set of matched elements. + OR + Get the current value of the first element in the set of matched elements. + **/ + @:overload(function(value:haxe.extern.EitherType, String>>):js.jquery.JQuery { }) + @:overload(function(_function:Int -> String -> String):js.jquery.JQuery { }) + public function val():Dynamic; + /** + Set the CSS width of each element in the set of matched elements. + OR + Get the current computed width for the first element in the set of matched elements. + **/ + @:overload(function(value:haxe.extern.EitherType):js.jquery.JQuery { }) + @:overload(function(_function:Int -> Int -> haxe.extern.EitherType):js.jquery.JQuery { }) + public function width():Float; + /** + Wrap an HTML structure around each element in the set of matched elements. + **/ + @:overload(function(_function:Int -> haxe.extern.EitherType):js.jquery.JQuery { }) + public function wrap(wrappingElement:haxe.extern.EitherType>):js.jquery.JQuery; + /** + Wrap an HTML structure around all elements in the set of matched elements. + **/ + @:overload(function(_function:Void -> haxe.extern.EitherType):js.jquery.JQuery { }) + public function wrapAll(wrappingElement:haxe.extern.EitherType>):js.jquery.JQuery; + /** + Wrap an HTML structure around the content of each element in the set of matched elements. + **/ + @:overload(function(_function:Int -> String):js.jquery.JQuery { }) + public function wrapInner(wrappingElement:haxe.extern.EitherType>):js.jquery.JQuery; + /** + Haxe iterator. + **/ + @:runtime + inline public function iterator():js.jquery.JqIterator return new js.jquery.JqIterator(this); + /** + Haxe iterator. + **/ + @:runtime + inline public function elements():js.jquery.JqEltsIterator return new js.jquery.JqEltsIterator(this); +} \ No newline at end of file diff --git a/std/js/jquery/JqEltsIterator.hx b/std/js/jquery/JqEltsIterator.hx new file mode 100644 index 00000000..e2c9e36b --- /dev/null +++ b/std/js/jquery/JqEltsIterator.hx @@ -0,0 +1,21 @@ +package js.jquery; + +class JqEltsIterator { + var j:JQuery; + var i:Int; + inline public function new(j:JQuery):Void { + this.i = 0; + this.j = j; + } + inline public function hasNext():Bool { + return i < j.length; + } + inline public function next():JQuery { + return new JQuery(this.j[i++]); + } + + static function __init__() { + if (untyped __typeof__(JQuery) != "undefined" && JQuery.fn != null) + JQuery.fn.elements = function() return new JqEltsIterator(js.Lib.nativeThis); + } +} \ No newline at end of file diff --git a/std/js/jquery/JqIterator.hx b/std/js/jquery/JqIterator.hx new file mode 100644 index 00000000..725bd92d --- /dev/null +++ b/std/js/jquery/JqIterator.hx @@ -0,0 +1,21 @@ +package js.jquery; + +class JqIterator { + var j:JQuery; + var i:Int; + inline public function new(j:JQuery):Void { + this.i = 0; + this.j = j; + } + inline public function hasNext():Bool { + return i < j.length; + } + inline public function next():js.html.Element { + return this.j[i++]; + } + + static function __init__() { + if (untyped __typeof__(JQuery) != "undefined" && JQuery.fn != null) + JQuery.fn.iterator = function() return new JqIterator(js.Lib.nativeThis); + } +} \ No newline at end of file diff --git a/std/js/jquery/JqXHR.hx b/std/js/jquery/JqXHR.hx new file mode 100644 index 00000000..aec53c07 --- /dev/null +++ b/std/js/jquery/JqXHR.hx @@ -0,0 +1,46 @@ +/* This file is generated, do not edit! Visit http://api.jquery.com/ for API documentation. */ +package js.jquery; +@:native("$.JqXHR") extern class JqXHR extends js.html.XMLHttpRequest { + /** + Add handlers to be called when the Deferred object is either resolved or rejected. + **/ + public function always(alwaysCallbacks:haxe.extern.EitherType>, ?alwaysCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; + /** + Add handlers to be called when the Deferred object is resolved. + **/ + public function done(doneCallbacks:haxe.extern.EitherType>, ?doneCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; + /** + Add handlers to be called when the Deferred object is rejected. + **/ + public function fail(failCallbacks:haxe.extern.EitherType>, ?failCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; + /** + Determine whether a Deferred object has been rejected. + **/ + @:deprecated("Deprecated since jQuery 1.7") + public function isRejected():Bool; + /** + Determine whether a Deferred object has been resolved. + **/ + @:deprecated("Deprecated since jQuery 1.7") + public function isResolved():Bool; + /** + Utility method to filter and/or chain Deferreds. + **/ + @:deprecated("Deprecated since jQuery 1.8") + @:overload(function(?doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function, ?progressFilter:haxe.Constraints.Function):js.jquery.Promise { }) + public function pipe(?doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function):js.jquery.Promise; + /** + Add handlers to be called when the Deferred object generates progress notifications. + **/ + public function progress(progressCallbacks:haxe.extern.EitherType, Array>>, ?progressCallbacks:haxe.extern.EitherType, Array>>):js.jquery.Deferred; + /** + Determine the current state of a Deferred object. + **/ + public function state():String; + /** + Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. + **/ + @:overload(function(doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function, ?progressFilter:haxe.Constraints.Function):js.jquery.Promise { }) + @:overload(function(doneCallbacks:haxe.extern.EitherType>, failCallbacks:haxe.extern.EitherType>, ?progressCallbacks:haxe.extern.EitherType>):js.jquery.Promise { }) + public function then(doneCallbacks:haxe.extern.EitherType>, failCallbacks:haxe.extern.EitherType>):js.jquery.Promise; +} \ No newline at end of file diff --git a/std/js/jquery/Promise.hx b/std/js/jquery/Promise.hx new file mode 100644 index 00000000..a1b2f2dc --- /dev/null +++ b/std/js/jquery/Promise.hx @@ -0,0 +1,46 @@ +/* This file is generated, do not edit! Visit http://api.jquery.com/ for API documentation. */ +package js.jquery; +@:native("$.Promise") typedef Promise = { + /** + Add handlers to be called when the Deferred object is either resolved or rejected. + **/ + public function always(alwaysCallbacks:haxe.extern.EitherType>, ?alwaysCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; + /** + Add handlers to be called when the Deferred object is resolved. + **/ + public function done(doneCallbacks:haxe.extern.EitherType>, ?doneCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; + /** + Add handlers to be called when the Deferred object is rejected. + **/ + public function fail(failCallbacks:haxe.extern.EitherType>, ?failCallbacks:haxe.extern.EitherType>):js.jquery.Deferred; + /** + Determine whether a Deferred object has been rejected. + **/ + @:deprecated("Deprecated since jQuery 1.7") + public function isRejected():Bool; + /** + Determine whether a Deferred object has been resolved. + **/ + @:deprecated("Deprecated since jQuery 1.7") + public function isResolved():Bool; + /** + Utility method to filter and/or chain Deferreds. + **/ + @:deprecated("Deprecated since jQuery 1.8") + @:overload(function(?doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function, ?progressFilter:haxe.Constraints.Function):js.jquery.Promise { }) + public function pipe(?doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function):js.jquery.Promise; + /** + Add handlers to be called when the Deferred object generates progress notifications. + **/ + public function progress(progressCallbacks:haxe.extern.EitherType, Array>>, ?progressCallbacks:haxe.extern.EitherType, Array>>):js.jquery.Deferred; + /** + Determine the current state of a Deferred object. + **/ + public function state():String; + /** + Add handlers to be called when the Deferred object is resolved, rejected, or still in progress. + **/ + @:overload(function(doneFilter:haxe.Constraints.Function, ?failFilter:haxe.Constraints.Function, ?progressFilter:haxe.Constraints.Function):js.jquery.Promise { }) + @:overload(function(doneCallbacks:haxe.extern.EitherType>, failCallbacks:haxe.extern.EitherType>, ?progressCallbacks:haxe.extern.EitherType>):js.jquery.Promise { }) + public function then(doneCallbacks:haxe.extern.EitherType>, failCallbacks:haxe.extern.EitherType>):js.jquery.Promise; +} \ No newline at end of file diff --git a/std/js/swfobject/SWFObject.hx b/std/js/swfobject/SWFObject.hx new file mode 100644 index 00000000..0b350824 --- /dev/null +++ b/std/js/swfobject/SWFObject.hx @@ -0,0 +1,128 @@ +/* + * Copyright (C)2005-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 js.swfobject; + +import js.html.*; +import haxe.extern.*; + +typedef SWFObjectEvent = { + /** + Boolean to indicate whether the creation of a Flash plugin-in DOM was successful or not + */ + var success:Bool; + /** + String indicating the ID used in swfobject.registerObject + */ + var id:String; + /** + HTML object element reference (null when success==false) + */ + @:optional var ref:Element; +} + +/** + For detecting the Adobe Flash Player plugin and embedding Flash (swf) files. +*/ +@:native("swfobject") +extern class SWFObject { + /** + Embed Flash content and alternative content using standards compliant markup (the nested-objects method with proprietary Internet Explorer conditional comments), and use JavaScript to resolve the issues that markup alone cannot solve (also called static publishing). + */ + static function registerObject(objectIdStr:String, swfVersionStr:String, xiSwfUrlStr:String, callbackFn:SWFObjectEvent->Void):Void; + /** + NOTE: For static publishing only (or: when using swfobject.registerObject() only) + + Returns the active object element. One of the side-effects of the nested-objects approach is that per SWF there are two object elements available in the HTML code, however you can only use one id or name attribute, because these have to be unique within a web page. + */ + static function getObjectById(objectIdStr:String):Element; + /** + Insert alternative content using standards compliant markup and embed Flash content with unobtrusive JavaScript (also called dynamic publishing). + */ + static function embedSWF(swfUrlStr:String, replaceElemIdStr:String, widthStr:String, heightStr:String, swfVersionStr:String, xiSwfUrlStr:String, flashvarsObj:Dynamic, parObj:Dynamic, attObj:Dynamic, callbackFn:SWFObjectEvent->Void):Void; + /** + Disable SWFObject's default show/hide behavior + */ + static function switchOffAutoHideShow():Void; + static function enableUriEncoding(bool:Bool):Void; + static var ua:{ + /** + a Boolean whether or not W3C DOM methods are supported + */ + var w3:Bool; + /** + an Array that contains the major, minor and release version number of the Flash Player + */ + var pv:Array; + /** + the Webkit version or false if not Webkit + */ + var wk:EitherType; + /** + a Boolean to indicate whether a visitor uses Internet Explorer on Windows or not + */ + var ie:Bool; + /** + a Boolean to indicate whether a visitor uses Mac OS or not + */ + var mac:Bool; + }; + /** + Returns a JavaScript object containing the major version (major:Number), minor version (minor:Number) and release version (release:Number) of an installed Flash player. Please note that while Flash version numbers normally consist of major.minor.release.build, SWFObject only looks at the first 3 numbers, so both "WIN 9,0,18,0" (IE) or "Shockwave Flash 9 r18" (all other browsers) will translate to "9.0.18". + */ + static function getFlashPlayerVersion():{ major:Int, minor:Int, release:Int }; + /** + Returns a Boolean to indicate whether or not a specific minimum version of the Flash plugin is installed. Please note that while Flash version numbers normally consist of major.minor.release.build, SWFObject only looks at the first 3 numbers, so both "WIN 9,0,18,0" (IE) or "Shockwave Flash 9 r18" (all other browsers) will translate to "9.0.18". + */ + static function hasFlashPlayerVersion(versionStr:String):Bool; + /** + Exposes SWFObject's internal cross-browser method to create a SWF. + */ + static function createSWF(attObj:Dynamic, parObj:Dynamic, replaceElemIdStr:String):Element; + /** + Enables developers to reuse SWFObject's internal methods to create their custom Express Install and activate it via the API + */ + static function showExpressInstall(att:Dynamic, par:Dynamic, replaceElemIdStr:String, callbackFn:SWFObjectEvent->Void):Bool; + /** + Removes a SWF from your web page. Is especially built to safely (only remove a SWF after it has been loaded, to avoid broken references) and completely (nullify references to avoid memory leaks) remove a SWF in Internet Explorer. + */ + static function removeSWF(objElemIdStr:String):Void; + /** + Exposes SWFObject's internal cross-browser method to create a dynamic stylesheet. It's most important feature is that it can be called before the DOM of a page is loaded. + */ + static function createCSS(selStr:String, declStr:String, ?mediaStr:String, ?newStyleBoolean:Bool):Void; + /** + A cross-browser method to execute a function as soon as the DOM of a web page is available. This method is supported by Gecko based browsers - like Firefox -, IE, Opera9+, and, Safari. For all other browsers the method will fall back to the addLoadEvent method. + */ + static function addDomLoadEvent(fn:Void->Void):Void; + /** + A safe (it doesn't overwrite existing onload events) cross-browser method to execute a function on the window onload event (which will fire as soon as a web page including all of its assets are loaded). + */ + static function addLoadEvent(fn:Void->Void):Void; + /** + Utility function that returns the value of the paramStr parameter in the URL query string or hash string. Similar functionality was already available in SWFObject 1.5 and lower. + */ + static function getQueryParamValue(param:String):String; + /** + swfobject version + */ + static var version:String; +} \ No newline at end of file diff --git a/std/lua/Bit.hx b/std/lua/Bit.hx new file mode 100644 index 00000000..68c8a2a3 --- /dev/null +++ b/std/lua/Bit.hx @@ -0,0 +1,41 @@ +/* + * Copyright (C)2005-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 lua; + +/** + Externs for the "bit" class that is required for Haxe lua +**/ +@:native("_hx_bit") +extern class Bit { + public static function bnot(x:Float) : Int; + public static function band(a:Float, b:Float) : Int; + public static function bor(a:Float, b:Float) : Int; + public static function bxor(a:Float, b:Float) : Int; + public static function lshift(x:Float, places:Int) : Int; + public static function rshift(x:Float, places:Int) : Int; + public static function arshift(x:Float, places:Int) : Int; + public static function mod(numerator:Float, denominator:Float) : Int; + public static function __init__() : Void { + untyped _hx_bit = __define_feature__("use._bitop",_hx_bit); + } +} diff --git a/std/lua/Boot.hx b/std/lua/Boot.hx new file mode 100644 index 00000000..50d5514c --- /dev/null +++ b/std/lua/Boot.hx @@ -0,0 +1,393 @@ +/* + * Copyright (C)2005-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 lua; + +import haxe.Constraints.Function; + + +@:dox(hide) +class Boot { + + // Used temporarily for bind() + static var _; + static var _fid = 0; + + public static var platformBigEndian = NativeStringTools.byte(NativeStringTools.dump(function(){}),7) > 0; + + static var hiddenFields : Table = untyped __lua__("{__id__=true, hx__closures=true, super=true, prototype=true, __fields__=true, __ifields__=true, __class__=true, __properties__=true}"); + + + + static function __unhtml(s : String) + return s.split("&").join("&").split("<").join("<").split(">").join(">"); + + /* + Indicates if the given object is a class. + */ + static inline public function isClass(o:Dynamic) : Bool { + if (Lua.type(o) != "table") return false; + else return untyped __define_feature__("lua.Boot.isClass", o.__name__); + } + + /* + Indicates if the given object is a enum. + */ + static inline public function isEnum(e:Dynamic) : Bool { + if (Lua.type(e) != "table") return false; + else return untyped __define_feature__("lua.Boot.isEnum", e.__ename__); + } + + /* + Returns the class of a given object, and defines the getClass feature + for the given class. + */ + static inline public function getClass(o:Dynamic) : Class { + if (Std.is(o, Array)) return Array; + else { + var cl = untyped __define_feature__("lua.Boot.getClass", o.__class__); + if (cl != null) return cl; + else return null; + } + } + + /* + Indicates if the given object is an instance of the given Type + */ + @:ifFeature("typed_catch") + private static function __instanceof(o : Dynamic, cl : Dynamic) { + if( cl == null ) return false; + + switch( cl ) { + case Int: + return (Lua.type(o) == "number" && clamp(o) == o); + case Float: + return Lua.type(o) == "number"; + case Bool: + return Lua.type(o) == "boolean"; + case String: + return Lua.type(o) == "string"; + case Thread: + return Lua.type(o) == "thread"; + case UserData: + return Lua.type(o) == "userdata"; + case Array: + return isArray(o); + case Table: + return Lua.type(o) == "table"; + case Dynamic: + return true; + default: { + if ( o!= null && Lua.type(o) == "table" && Lua.type(cl) == "table"){ + if (extendsOrImplements(getClass(o), cl)) return true; + // We've exhausted standard inheritance checks. Check for simple Class/Enum eqauality + // Also, do not use isClass/isEnum here, perform raw checks + untyped __feature__("Class.*",if( cl == Class && o.__name__ != null ) return true); + untyped __feature__("Enum.*",if( cl == Enum && o.__ename__ != null ) return true); + // last chance, is it an enum instance? + return o.__enum__ == cl; + } else { + return false; + } + } + } + } + static function isArray(o:Dynamic) : Bool { + return Lua.type(o) == "table" + && untyped o.__enum__ == null + && Lua.getmetatable(o) != null + && Lua.getmetatable(o).__index == untyped Array.prototype; + } + + /* + Indicates if the given object inherits from the given class + */ + static function inheritsFrom(o:Dynamic, cl:Class) : Bool { + while (Lua.getmetatable(o) != null && Lua.getmetatable(o).__index != null){ + if (Lua.getmetatable(o).__index == untyped cl.prototype) return true; + o = Lua.getmetatable(o).__index; + } + return false; + } + + @:ifFeature("typed_cast") + private static function __cast(o : Dynamic, t : Dynamic) { + if (__instanceof(o, t)) return o; + else throw "Cannot cast " +Std.string(o) + " to " +Std.string(t); + } + + /* + Helper method to generate a string representation of an enum + */ + static function printEnum(o:Array, s : String){ + if (o.length == 2){ + return o[0]; + } else { + // parameterized enums are arrays + var str = o[0] + "("; + s += "\t"; + for (i in 2...o.length){ + if( i != 2 ) + str += "," + __string_rec(o[i],s); + else + str += __string_rec(o[i],s); + } + return str + ")"; + } + } + + /* + Helper method to generate a string representation of a class + */ + static inline function printClass(c:Table, s : String) : String { + return '{${printClassRec(c,'',s)}}'; + } + + /* + Helper method to generate a string representation of a class + */ + static function printClassRec(c:Table, result='', s : String) : String { + var f = Boot.__string_rec; + untyped __lua__("for k,v in pairs(c) do if result ~= '' then result = result .. ', ' end result = result .. k .. ':' .. f(v, s.. '\t') end"); + return result; + } + + /* + Generate a string representation for arbitrary object. + */ + @:ifFeature("has_enum") + static function __string_rec(o : Dynamic, s:String = "") { + return switch(untyped __type__(o)){ + case "nil": "null"; + case "number" : { + if (o == std.Math.POSITIVE_INFINITY) "Infinity"; + else if (o == std.Math.NEGATIVE_INFINITY) "-Infinity"; + else if (o != o) "NaN"; + else untyped tostring(o); + } + case "boolean" : untyped tostring(o); + case "string" : o; + case "userdata": ""; + case "function": ""; + case "thread" : ""; + case "table": { + if (o.__enum__ != null) printEnum(o,s); + else if (o.toString != null && !isArray(o)) o.toString(); + else if (isArray(o)) { + var o2 : Array = untyped o; + if (s.length > 5) "[...]" + else '[${[for (i in o2) __string_rec(i,s+1)].join(",")}]'; + } + else if (o.__class__ != null) printClass(o,s+"\t"); + else { + var fields = fieldIterator(o); + var buffer:Table = Table.create(); + var first = true; + Table.insert(buffer,"{ "); + for (f in fields){ + if (first) first = false; + else Table.insert(buffer,", "); + Table.insert(buffer,'${Std.string(f)} : ${untyped Std.string(o[f])}'); + } + Table.insert(buffer, " }"); + Table.concat(buffer, ""); + } + }; + default : { + throw "Unknown Lua type"; + null; + } + } + + } + + /* + Define an array from the given table + */ + public inline static function defArray(tab: Table, ?length : Int) : Array { + if (length == null) length = TableTools.maxn(tab) + 1; // maxn doesn't count 0 index + return untyped _hx_tab_array(tab, length); + } + + /* + Create a Haxe object from the given table structure + */ + public inline static function tableToObject(t:Table) : Dynamic { + return untyped _hx_o(t); + } + + /* + Get Date object as string representation + */ + public static function dateStr( date : std.Date ) : String { + var m = date.getMonth() + 1; + var d = date.getDate(); + var h = date.getHours(); + var mi = date.getMinutes(); + var s = date.getSeconds(); + return date.getFullYear() + +"-"+(if( m < 10 ) "0"+m else ""+m) + +"-"+(if( d < 10 ) "0"+d else ""+d) + +" "+(if( h < 10 ) "0"+h else ""+h) + +":"+(if( mi < 10 ) "0"+mi else ""+mi) + +":"+(if( s < 10 ) "0"+s else ""+s); + } + + /* + A 32 bit clamp function for numbers + */ + public inline static function clamp(x:Float){ + return untyped __define_feature__("lua.Boot.clamp", _hx_bit_clamp(x)); + } + + /* + Create a standard date object from a lua string representation + */ + public static function strDate( s : String ) : std.Date { + switch( s.length ) { + case 8: // hh:mm:ss + var k = s.split(":"); + var t = lua.Os.time({ + year : 0, + month : 1, + day : 1, + hour : Lua.tonumber(k[0]), + min : Lua.tonumber(k[1]), + sec : Lua.tonumber(k[2]) + }); + return std.Date.fromTime(t); + case 10: // YYYY-MM-DD + var k = s.split("-"); + return new std.Date(Lua.tonumber(k[0]), Lua.tonumber(k[1]) - 1, Lua.tonumber(k[2]),0,0,0); + case 19: // YYYY-MM-DD hh:mm:ss + var k = s.split(" "); + var y = k[0].split("-"); + var t = k[1].split(":"); + return new std.Date(cast y[0],Lua.tonumber(y[1]) - 1, Lua.tonumber(y[2]),Lua.tonumber(t[0]),Lua.tonumber(t[1]),Lua.tonumber(t[2])); + default: + throw "Invalid date format : " + s; + } + } + + /* + Helper method to determine if class cl1 extends, implements, or otherwise equals cl2 + */ + public static function extendsOrImplements(cl1 : Class, cl2 : Class) : Bool { + if (cl1 == null || cl2 == null) return false; + else if (cl1 == cl2) return true; + else if (untyped cl1.__interfaces__ != null) { + var intf = untyped cl1.__interfaces__; + for (i in 1...( TableTools.maxn(intf) + 1)){ + // check each interface, including extended interfaces + if (extendsOrImplements(intf[i], cl2)) return true; + } + } + // check standard inheritance + return extendsOrImplements(untyped cl1.__super__, cl2); + } + + + /* + Returns a shell escaped version of "cmd" along with any args + */ + public static function shellEscapeCmd(cmd : String, ?args : Array){ + if (args != null) { + switch (Sys.systemName()) { + case "Windows": + cmd = [ + for (a in [StringTools.replace(cmd, "/", "\\")].concat(args)) + StringTools.quoteWinArg(a, true) + ].join(" "); + case _: + cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" "); + } + } + return cmd; + } + + /* + Returns a temp file path that can be used for reading and writing + */ + public static function tempFile() : String { + switch (Sys.systemName()){ + case "Windows" : return haxe.io.Path.join([Os.getenv("TMP"), Os.tmpname()]); + default : return Os.tmpname(); + } + } + + public static function fieldIterator( o : Table) : Iterator { + var tbl : Table = cast (untyped o.__fields__ != null) ? o.__fields__ : o; + var cur = Lua.pairs(tbl).next; + var next_valid = function(tbl, val){ + while (hiddenFields[untyped val] != null){ + val = cur(tbl, val).index; + } + return val; + } + var cur_val = next_valid(tbl, cur(tbl, null).index); + return { + next : function(){ + var ret = cur_val; + cur_val = next_valid(tbl, cur(tbl, cur_val).index); + return ret; + }, + hasNext : function() return cur_val != null + } + } + + static var os_patterns = [ + 'Windows' => ['windows','^mingw','^cygwin'], + 'Linux' => ['linux'], + 'Mac' => ['mac','darwin'], + 'BSD' => ['bsd$'], + 'Solaris' => ['SunOS'] + ]; + + public static function systemName() : String { + var os : String = null; + if (untyped jit != null && untyped jit.os != null ){ + os = untyped jit.os; + os = os.toLowerCase(); + } else { + var popen_status : Bool = false; + var popen_result : lua.FileHandle = null; + untyped __lua__("popen_status, popen_result = pcall(_G.io.popen, '')"); + if (popen_status) { + popen_result.close; + os = lua.Io.popen('uname -s','r').read('*l').toLowerCase(); + } else { + os = lua.Os.getenv('OS').toLowerCase(); + } + + } + + for (k in os_patterns.keys()){ + for (p in os_patterns.get(k)) { + if (lua.NativeStringTools.match(os,p) != null){ + return k; + } + } + } + + return null; + } +} diff --git a/std/lua/Coroutine.hx b/std/lua/Coroutine.hx new file mode 100644 index 00000000..989674f9 --- /dev/null +++ b/std/lua/Coroutine.hx @@ -0,0 +1,120 @@ +/* + * Copyright (C)2005-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 lua; + +import haxe.extern.Rest; +import haxe.Constraints.Function; + +/** + Externs for native Lua coroutines. +**/ +@:native("_G.coroutine") +extern class Coroutine extends Thread { + /** + Creates a new coroutine, with body `f`. `f` must be a Lua function. + **/ + public static function create(f : T) : Coroutine; + + /** + Returns the running coroutine plus a boolean, true when the running coroutine is the main one. + **/ + public static function running() : CoroutineRunning; + + /** + Returns the status of coroutine. + **/ + public static function status(c : Coroutine) : CoroutineState; + + /** + Starts or continues the execution of coroutine. + The first time you resume a coroutine, it starts running its body. + The values `args` are passed as the arguments to the body function. + If the coroutine has yielded, `resume` restarts it; + the values `args` are passed as the results from the yield. + + If the coroutine runs without any errors, `resume` returns `true` plus any + values passed to `yield` (if the coroutine yields) or any values returned + by the body function (if the coroutine terminates). If there is any error, + `resume` returns `false` plus the error message. + **/ + public static function resume(c : Coroutine, args : Rest) : CoroutineResume; + + /** + Suspends the execution of the calling coroutine. + The coroutine cannot be running a C function, a metamethod, or an iterator. + Any arguments to `yield` are passed as extra results to `resume`. + **/ + public static function yield(args : Rest) : Dynamic; + + /** + Creates a new coroutine, with body `f`. + Returns a function that resumes the coroutine each time it is called. + Any arguments passed to the function behave as the extra arguments to `resume`. + Returns the same values returned by `resume`, except the first boolean. + In case of error, propagates the error. + **/ + public static function wrap(f : T) : Coroutine; +} + +/** + A enumerator that describes the output of `Coroutine.status()`. +**/ +@:enum +abstract CoroutineState(String) { + /** + If the coroutine is suspended in a call to yield, or if it has not started + running yet. + **/ + var Suspended = "suspended"; + + /** + If the coroutine is running. + **/ + var Running = "running"; + + /** + If the coroutine is active but not running. That is, it has resumed another + coroutine. + **/ + var Normal = "normal"; + + /** + If the coroutine has finished its body function or if it has stopped with + an error. + **/ + var Dead = "dead"; +} + +@:multiReturn +extern class CoroutineResume { + var success : Bool; + var result : Dynamic; +} + + +@:multiReturn +extern class CoroutineRunning { + var coroutine : Coroutine; + var status : Bool; +} + diff --git a/std/lua/Debug.hx b/std/lua/Debug.hx new file mode 100644 index 00000000..b6f0c497 --- /dev/null +++ b/std/lua/Debug.hx @@ -0,0 +1,156 @@ +/* + * Copyright (C)2005-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 lua; +/** + Externs for the "debug" class for Haxe lua +**/ +import haxe.Constraints.Function; + +import lua.Table.AnyTable; + +@:native("debug") +extern class Debug { + /** + This function returns the name and the value of the local variable with + index local of the function at level level of the stack. + **/ + public static function getlocal(stackLevel : Int, idx : Int) : Dynamic; + + /** + This function assigns the value value to the local variable with index + local of the function at level level of the stack. + Call `getinfo` to check whether the level is valid. + **/ + public static function setlocal(stackLevel : Int, varName: String, value: Dynamic) : Void; + + /** + Returns a table with information about a function. + **/ + public static function getinfo(stackLevel : Int) : DebugInfo; + + /** + Sets the given function as a hook. + When called without arguments, `Debug.sethook` turns off the hook. + **/ + public static function sethook(?fun : Function, ?monitor : String) : Void; + + /** + Enters an interactive mode with the user, running each string that the user enters. + Using simple commands and other debug facilities, the user can inspect + global and local variables, change their values, evaluate expressions, + and so on. A line containing only the word `cont` finishes this function, + so that the caller continues its execution. + + Note that commands for `Debug.debug` are not lexically nested within any + function, and so have no direct access to local variables. + **/ + public static function debug() : Void; + + /** + Returns the current hook settings of the thread, as three values: + the current hook function, the current hook mask, and the current hook count + (as set by the `Debug.sethook` function). + **/ + public static function gethook(thread : Thread) : Function; + + /** + Returns the registry table. + **/ + public static function getregistry() : AnyTable; + + /** + Returns the metatable of the given `value` or `null` if it does not have a metatable. + **/ + public static function getmetatable(value : AnyTable) : AnyTable; + + /** + Sets the metatable for the given `value` to the given `table` (can be `null`). + **/ + public static function setmetatable(value : AnyTable, table : AnyTable) : Void; + + /** + This function returns the name and the value of the upvalue with index `up` + of the function `f`. The function returns `null` if there is no upvalue with + the given index. + **/ + public static function getupvalue(f : Function, up : Int) : Dynamic; + + /** + This function assigns the value value to the upvalue with index up of + the function `f`. The function returns `null` if there is no upvalue with + the given index. Otherwise, it returns the name of the upvalue. + **/ + public static function setupvalue(f : Function, up : Int, val : Dynamic) : Void; + + /** + Returns the Lua value associated to `val`. + If `val` is not a `UserData`, returns `null`. + **/ + public static function getuservalue(val : Dynamic) : Dynamic; + + /** + Sets the given value as the Lua value associated to the given udata. + `udata` must be a full `UserData`. + **/ + public static function setuservalue(udata : Dynamic, val : Dynamic) : Void; + + /** + Returns a string with a traceback of the call stack. + @param message (optional) is appended at the beginning of the traceback. + @param level (optional) tells at which level to start the traceback. + default is `1`, the function calling traceback. + **/ + public static function traceback(?thread : Thread, ?message : String, ?level : Int) : String; + + /** + Returns a unique identifier (as a light userdata) for the upvalue numbered + `n` from the given function `f`. + **/ + public static function upvalueid(f : Function, n : Int) : Dynamic; + + /** + Make the `n1`-th upvalue of the Lua closure `f1` refer to the `n2`-th + upvalue of the Lua closure `f2`. + **/ + public static function upvaluejoin(f1 : Function, n1 : Int, f2 : Function, n2 : Int) : Void; +} + +/** + A enumerator that describes the output of `Debug.getinfo()`. +**/ +typedef DebugInfo = { + currentline : Int, + func : Function, + istailcall : Bool, + isvararg : Bool, + lastlinedefined : Int, + linedefined : Int, + name : String, + namewhat : String, + nparams : Int, + nups : Int, + short_src : String, + source : String, + what : String +} + diff --git a/std/lua/Ffi.hx b/std/lua/Ffi.hx new file mode 100644 index 00000000..8728d7d6 --- /dev/null +++ b/std/lua/Ffi.hx @@ -0,0 +1,61 @@ +/* + * Copyright (C)2005-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 lua; + +#if lua_jit +@:native("_G.ffi") +extern class Ffi { + + // Declaring and accessing external symbols + public static var C : Dynamic; + public static function gc(cdata : Dynamic, finalizer : Function) : Void; + public static function load : (name : String, ?global : Bool) : Dynamic; + public static function metatype(ct : Ctype, metatable : Table) : Ctype; + public static function typeof(str:String) : Ctype; + + // C Type functionality + public static function alignof(ct : Ctype) : Int; + public static function istype(ct : Ctype, obj:Dynamic) : Bool; + public static function offsetof(ct : Ctype, field:String) : Int; + public static function sizeof(ct : Ctype, ?nelem : Int) : Int; + + + // Utility functionality + public static function errno(?newerr : Int) : Int; + public static function fill(dst : Dynamic, len : Int, c:Int) : Void; + public static function string(ptr : Dynamic, ?len : Int) : String; + + @:overload( function (dst : Dynamic, str : String) : Dynamic {}) + public static function copy(dst : Dynamic, src : Dynamic, len : Int) : String; + + // Target specific functionality + public static var os : String; + public static var arch : String; + public static function abi(param : String) : Bool; +} + +extern class Ctype {} + +// TODO FFI callback type (gc methods) +#end + diff --git a/std/lua/FileHandle.hx b/std/lua/FileHandle.hx new file mode 100644 index 00000000..aa2e2b0f --- /dev/null +++ b/std/lua/FileHandle.hx @@ -0,0 +1,38 @@ +/* + * Copyright (C)2005-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 lua; +import haxe.extern.EitherType; +import haxe.extern.Rest; +import sys.io.FileInput; + +extern class FileHandle extends UserData { + public function flush() : Void; + public function read(arg : Rest>) : String; + public function close() : Void; + + public function write(str : String) : Void; + + @:overload(function () : Int {}) + @:overload(function (arg : String) : Int {}) + public function seek(arg : String, pos : Int) : Void; +} + diff --git a/std/lua/HaxeIterator.hx b/std/lua/HaxeIterator.hx new file mode 100644 index 00000000..2d18aac1 --- /dev/null +++ b/std/lua/HaxeIterator.hx @@ -0,0 +1,42 @@ +/* + * Copyright (C)2005-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 lua; + +/** + An implementation of the Haxe iterator datastructure needed for identical + lua iterator behavior. + **/ +class HaxeIterator { + var state : T; + var f : Void->T; + public function new(f:Void->T){ + this.f = f; + this.state = f(); + } + public function next(){ + var ret = this.state; + this.state = this.f(); + return ret; + } + public function hasNext() return this.state != null; +} diff --git a/std/lua/Io.hx b/std/lua/Io.hx new file mode 100644 index 00000000..d16c7328 --- /dev/null +++ b/std/lua/Io.hx @@ -0,0 +1,127 @@ +/* + * Copyright (C)2005-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 lua; +import haxe.extern.Rest; + +/** + Input and Output Facilities +**/ +@:native("_G.io") +extern class Io { + public static var stdin : FileHandle; + public static var stderr : FileHandle; + public static var stdout : FileHandle; + + /** + Function to close regular files. + **/ + public static function close(?file : FileHandle) : Void; + + /** + Saves any written data to file. + **/ + public static function flush() : Void; + + /** + When called with a file name, it opens the named file (in text mode), + and sets its handle as the default input file. When called with a file handle, + it simply sets this file handle as the default input file. + When called without parameters, it returns the current default input file. + + In case of errors this function raises the error, instead of returning an + error code. + **/ + @:overload( function (file : String) : Void {}) + public static function input(file : FileHandle) : Void; + + /** + Opens the given file name in read mode and returns an iterator function that, + each time it is called, returns a new line from the file. + **/ + public static function lines(?file : String) : NativeIterator; + + /** + This function opens a file, in the mode specified in the string mode. + It returns a new file handle, or, in case of errors, `null` plus an error message. + + The mode string can be any of the following: + + * `"r"`: read mode (the default) + * `"w"`: write mode + * `"a"`: append mode + * `"r+"`: update mode, all previous data is preserved + * `"w+"`: update mode, all previous data is erased + * `"a+"`: append update mode, previous data is preserved, writing is only + allowed at the end of file + + The mode string can also have a `b` at the end, which is needed in some systems + to open the file in binary mode. This string is exactly what is used in the + standard C function fopen. + **/ + public static function open (filename : String, ?mode : String) : FileHandle; + + /** + Starts program `command` in a separated process and returns a file handle that + you can use to read data from this program (if mode is `"r"`, the default) + or to write data to this program (if mode is `"w"`). + + This function is system dependent and is not available on all platforms. + **/ + public static function popen(command : String, ?mode : String) : FileHandle; + + @:overload( function (?count : Int) : String {}) + public static function read(?filename : String) : String; + + /** + Writes the value of each of its arguments to the file. The arguments must + be strings or numbers. + To write other values, use `Lua.tostring` or `NativeStringTools.format` + before write. + **/ + public static function write(v : Rest) : Void; + + public static function output(?file : String) : FileHandle; + + /** + Returns a handle for a temporary file. This file is opened in update mode + and it is automatically removed when the program ends. + **/ + public static function tmpfile() : FileHandle; + + /** + Checks whether `obj` is a valid file handle. + **/ + public static function type(obj : FileHandle) : IoType; +} + +/** + A enumerator that describes the output of `Io.type()`. +**/ +@:enum +abstract IoType(String) { + var File = "file"; + var ClosedFile = "closed file"; + var NotAFile = null; + @:to public function toString(){ + return this; + } +} diff --git a/std/lua/Jit.hx b/std/lua/Jit.hx new file mode 100644 index 00000000..b832e4f7 --- /dev/null +++ b/std/lua/Jit.hx @@ -0,0 +1,21 @@ +package lua; + +import haxe.Constraints.Function; + +#if lua_jit +@:native("_G.jit") +extern class Jit { + public static function on(?f:Function, ?recursive:Bool) : Void; + public static function off(?f:Function, ?recursive:Bool) : Void; + public static function flush(?f:Function, ?recursive:Bool) : Void; + public static function status() : Bool; + public static var version : String; + public static var version_num : Int; + public static var os : String; + public static var arch : String; + public static var opt : { start : Function }; + public static var util : Dynamic; +} +#end + + diff --git a/std/lua/Lib.hx b/std/lua/Lib.hx new file mode 100644 index 00000000..e84fffff --- /dev/null +++ b/std/lua/Lib.hx @@ -0,0 +1,81 @@ +/* + * Copyright (C)2005-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 lua; +import lua.Lua; +import lua.Io; +import lua.NativeStringTools; + +/** + Platform-specific Lua Library. Provides some platform-specific functions + for the Lua target, such as conversion from Haxe types to native types + and vice-versa. +**/ +class Lib { + /** + Print the specified value on the default output followed by a newline character. + **/ + public static inline function println( v : Dynamic ) : Void { + Lua.print(Std.string(v)); + } + + /** + Print the specified value on the default output. + **/ + public static inline function print(v:Dynamic) : Void { + Io.write(Std.string(v)); + Io.flush(); + } + + public inline static function tableToArray(t:Table, ?length:Int) : Array { + return Boot.defArray(t, length); + } + + public inline static function tableToObject(t:Table) : Dynamic { + return Boot.tableToObject(t); + } + + public inline static function patternQuote(str:String) : String { + return NativeStringTools.gsub(str, "[%(%)%.%%%+%-%*%?%[%]%^%$]", function(c:String){ return "%" + c; }); + } + + public inline static function defArray(tab: Table, length : Int) : Array { + return Boot.defArray(tab, length); + } + + public static function fillArray(itr:Void->T) : Array { + var i: T = null; + var ret : Array = []; + while({i = itr(); i != null;}){ + ret.push(i); + } + return ret; + } + + public static function isShellAvailable() : Bool { + var ret : Dynamic = Os.execute(); + if (Lua.type(ret) == "bool"){ + return ret; + } else { + return ret != 0; + } + } +} diff --git a/std/lua/LocaleCategory.hx b/std/lua/LocaleCategory.hx new file mode 100644 index 00000000..cc966c1e --- /dev/null +++ b/std/lua/LocaleCategory.hx @@ -0,0 +1,10 @@ +package lua; +@:enum +abstract LocaleCategory(String){ + var All = "all"; + var Collate = "collate"; + var Ctype = "ctype"; + var Monetary = "monetary"; + var Numeric = "numeric"; + var Time = "time"; +} diff --git a/std/lua/Lua.hx b/std/lua/Lua.hx new file mode 100644 index 00000000..607f7258 --- /dev/null +++ b/std/lua/Lua.hx @@ -0,0 +1,215 @@ +package lua; +import haxe.extern.Rest; +import haxe.Constraints.Function; +import haxe.extern.Rest; + +/** + These are all global static methods within Lua. + **/ + +@:native("_G") +extern class Lua { + /** + A global variable that holds a string containing the current interpreter + version. + **/ + public static var _VERSION : String; + + public static var arg : Table; + + /** + Pushes onto the stack the metatable in the registry. + **/ + public static function getmetatable(tbl:Table): Table; + + /** + Pops a table from the stack and sets it as the new metatable for the value + at the given acceptable index. + **/ + public static function setmetatable(tbl:Table, mtbl: Table): Void; + + /** + Pops a table from the stack and sets it as the new environment for the value + at the given index. If the value at the given index is neither a function nor + a thread nor a userdata, lua_setfenv returns `0`. + Otherwise it returns `1`. + **/ + public static function setfenv(i:Int , tbl:Table): Void; + + /** + Allows a program to traverse all fields of a table. + Its first argument is a table and its second argument is an index in this + table. `next` returns the next index of the table and its associated value. + When `i` is `null`, `next` returns an initial index and its associated value. + When called with the last index, or with `null` in an empty table, `next` + returns `null`. In particular, you can use `next(t)` to check whether a + table is empty. + + The order in which the indices are enumerated is not specified, even for + numeric indices. (To traverse a table in numeric order, use a numerical for + or the `ipairs` function). + + The behavior of next is undefined if, during the traversal, any value + to a non-existent field in the table is assigned. Existing fields may + however be modified. In particular, existing fields may be cleared. + **/ + public static function next(k:Table, ?i : V): NextResult; + + /** + Receives an argument of any type and converts it to a string in a reasonable + format. + + For complete control of how numbers are converted, use`NativeStringTools.format`. + **/ + public static function tostring(v:Dynamic): String; + + public static function ipairs(t:Table): PairsResult; + + public static function pairs(t:Table): PairsResult ; + + public static function require(module:String) : Dynamic; + + /** + Converts the Lua value at the given acceptable base to `Int`. + The Lua value must be a number or a string convertible to a number, + otherwise `tonumber` returns `0`. + **/ + public static function tonumber(str:String, ?base:Int): Int; + + /** + Returns the Lua type of its only argument as a string. + The possible results of this function are: + + * `"nil"` (a string, not the Lua value nil), + * `"number"` + * `"string"` + * `"boolean"` + * `"table"` + * `"function"` + * `"thread"` + * `"userdata"` + **/ + public static function type(v:Dynamic) : String; + + /** + Receives any number of arguments, and prints their values to stdout, + using the tostring function to convert them to strings. + `print` is not intended for formatted output, but only as a quick way to show + a value, typically for debugging. + + For complete control of how numbers are converted, use `NativeStringTools.format`. + **/ + public static function print(v:haxe.extern.Rest) : Void; + + /** + If `n` is a number, returns all arguments after argument number `n`. + Otherwise, `n` must be the string `"#"`, and select returns the total + number of extra arguments it received. + **/ + public static function select(n:Dynamic, rest:Rest) : Dynamic; + + /** + Gets the real value of `table[index]`, without invoking any metamethod. + **/ + public static function rawget(t:Table, k:K) : V; + + /** + Sets the real value of `table[index]` to value, without invoking any metamethod. + **/ + public static function rawset(t:Table, k:K, v:V) : Void; + + /** + This function is a generic interface to the garbage collector. + It performs different functions according to its first argument. + **/ + public static function collectgarbage(opt:CollectGarbageOption, ?arg:Int) : Int; + + /** + Issues an error when the value of its argument `v` is `false` (i.e., `null` + or `false`) otherwise, returns all its arguments. message is an error message. + when absent, it defaults to "assertion failed!" + **/ + public static function assert(v:T, ?message:String) : T; + + /** + Loads and runs the given file. + **/ + public static function dofile(filename:String) : Void; + + /** + Generates a Lua error. The error message (which can actually be a Lua value + of any type) must be on the stack top. This function does a long jump, + and therefore never returns. + **/ + public static function error(message:String, ?level:Int) : Void; + + /** + Calls a function in protected mode. + **/ + public static function pcall(f:Function, rest:Rest) : PCallResult; + + /** + Returns `true` if the two values in acceptable indices `v1` and `v2` are + primitively equal (that is, without calling metamethods). + Otherwise returns `false`. + Also returns `false` if any of the indices are non valid. + **/ + public static function rawequal(v1:Dynamic, v2:Dynamic) : Bool; + + /** + This function is similar to pcall, except that you can set a new error + handler. + **/ + public static function xpcall(f:Function, msgh:Function, rest:Rest ) : PCallResult; + + /** + Loads the chunk from file filename or from the standard input if no filename + is given. + **/ + public static function loadfile(filename:String) : LoadResult; + + /** + Loads the chunk from given string. + **/ + public static function load(code:haxe.extern.EitherTypeString>) : LoadResult; + +} + +/** + Enum for describing garbage collection options +**/ +@:enum +abstract CollectGarbageOption(String) { + var Stop = "stop"; + var Restart = "restart"; + var Collect = "collect"; + var Count = "count"; + var Step = "step"; + var SetPause = "setpause"; + var SetStepMul = "setstepmul"; +} + +@:multiReturn +extern class PCallResult { + var status : Bool; + var value : Dynamic; +} + +@:multiReturn +extern class NextResult { + var index : K; + var value : V; +} + +@:multiReturn +extern class PairsResult { + var next : Table->K->NextResult; + var table : Table; + var index : V; +} + +@:multiReturn +extern class LoadResult { + var func : Function; + var message : String; +} diff --git a/std/lua/Map.hx b/std/lua/Map.hx new file mode 100644 index 00000000..fb962328 --- /dev/null +++ b/std/lua/Map.hx @@ -0,0 +1,89 @@ +/* + * Copyright (C)2005-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 lua; +class Map implements haxe.Constraints.IMap { + + private var h : Dynamic; + private var k : Dynamic; + + public inline function new() : Void { + h = {}; + k = {}; + } + + public inline function set( key : A, value : B ) : Void untyped { + h[key] = value; + k[key] = true; + } + + public inline function get( key : A ) : Null untyped { + return h[key]; + } + + public inline function exists( key : A ) : Bool untyped { + return k[key] != null; + } + + public function remove( key : A ) : Bool untyped { + if ( k[key] == null) return false; + k[key] = null; + h[key] = null; + return true; + } + + public function keys() : Iterator untyped { + var cur = next(k,null); + return { + next : function() { + var ret = cur; + cur = untyped next(k, cur); + return ret; + }, + hasNext : function() return cur != null + } + } + + public function iterator() : Iterator { + var itr = keys(); + return untyped { + hasNext : itr.hasNext, + next : function() return h[itr.next()] + }; + } + + public function toString() : String { + var s = new StringBuf(); + s.add("{"); + var it = keys(); + for( i in it ) { + s.add(i); + s.add(" => "); + s.add(Std.string(get(i))); + if( it.hasNext() ) + s.add(", "); + } + s.add("}"); + return s.toString(); + } + +} + diff --git a/std/lua/Math.hx b/std/lua/Math.hx new file mode 100644 index 00000000..a989d446 --- /dev/null +++ b/std/lua/Math.hx @@ -0,0 +1,43 @@ +package lua; + +@:native("_G.math") +extern class Math { + public static var pi : Float; + public static var huge : Float; + public static var NaN : Float; + + public static function abs (i : Float) : Float; + public static function ceil (i : Float) : Int; + public static function floor(i : Float) : Int; + + public static function acos (i : Float) : Float; + public static function asin (i : Float) : Float; + public static function atan (i : Float) : Float; + public static function atan2(i : Float, j : Float) : Float; + public static function cos (i : Float) : Float; + public static function cosh (i : Float) : Float; + public static function sin (i : Float) : Float; + public static function sinh (i : Float) : Float; + public static function tan (i : Float) : Float; + public static function tanh (i : Float) : Float; + public static function rad (i : Float) : Float; + + public static function modf (i : Float) : Float; + public static function fmod (i : Float) : Float; + + public static function pow (i : Float, j : Float) : Float; + public static function sqrt (i : Float) : Float; + public static function exp (i : Float) : Float; + public static function frexp(i : Float) : Float; + public static function ldexp(i : Float) : Float; + + public static function log (i : Float) : Float; + public static function log10(i : Float) : Float; + + public static function max (i : Float, j :Float) : Float; + public static function min (i : Float, j :Float) : Float; + + public static function random() : Float; + public static function randomseed(i : Float) : Float; +} + diff --git a/std/lua/NativeIterator.hx b/std/lua/NativeIterator.hx new file mode 100644 index 00000000..5d9866a7 --- /dev/null +++ b/std/lua/NativeIterator.hx @@ -0,0 +1,47 @@ +/* + * Copyright (C)2005-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 lua; + +/** + This abstract enables easy conversion from basic lua iterators + (i.e., a function that is called until it returns null), and + Haxe iterators, which provide a next/hasNext interface. +**/ + +@:callable +abstract NativeIterator(Void->T) { + public function new(f : Void->T) { + this = f; + } + + @:from + public static function fromF(f : Void->T){ + return new NativeIterator(f); + } + + @:to + public function toIterator() : Iterator { + return new HaxeIterator(this); + } +} + diff --git a/std/lua/NativeStringTools.hx b/std/lua/NativeStringTools.hx new file mode 100644 index 00000000..6d4e7c6f --- /dev/null +++ b/std/lua/NativeStringTools.hx @@ -0,0 +1,140 @@ +package lua; +/** + These are all externs for the base Lua "string" class, which functions + as an additional set of string tools. + + Note that all relevant indexes are "1" based. +**/ +@:native("_G.string") +extern class NativeStringTools { + /** + Receives a string and returns its length. The empty string `""` has + length `0`. Embedded zeros are counted, so `"a\000bc\000"` has length `5`. + **/ + public static function len(str : String): Int; + + /** + Receives zero or more integers. Returns a string with length equal to the + number of arguments, in which each character has the internal numerical + code equal to its corresponding argument. + Note that numerical codes are not necessarily portable across platforms. + **/ + public static function char(codes: haxe.extern.Rest): String; + + + // TODO: make a note about handling matched groups with multireturn + /** + Returns the substring of `str` that starts at `start` and continues until `end`; + `start` and `end` can be negative. If `end` is absent, then it is assumed to be + equal to `-1` (which is the same as the string length). + In particular, the call `sub(str,1,end)` returns a prefix of `str` + with length `end`, and `sub(str, -end)` returns a suffix of `str` with + length `start`. + **/ + public static function sub(str : String, start : Int, ?end : Int): StringSub; + + /** + Returns the character code at position `index` of `str`. + **/ + public static function charCodeAt(str : String, index : Int): Int; + + /** + Looks for the first match of pattern in the string `str`. + If it finds a match, then `find` returns the indices of `str` where this + occurrence starts and ends. + + @param target If the target has captures, then in a successful match the + captured values are also returned, after the two indices. + @param start specifies where to start the search; its default value is `1` + and can be negative. + @param plain turns off the pattern matching facilities, so the function does + a plain "find substring" operation, with no characters in pattern + being considered "magic". Note that if plain is given, then `start` must be given as well. + **/ + public static function find(str : String, target : String, ?start : Int, ?plain : Bool): StringFind; + + /** + Returns the internal numerical codes of the characters `str[index]`. + Note that numerical codes are not necessarily portable across platforms. + **/ + public static function byte(str : String, ?index : Int) : Int; + + /** + Returns a formatted version of its variable number of arguments following + the description given in its first argument (which must be a string). + The format string follows the same rules as the printf family of standard C + functions. The only differences are that the options/modifiers + `*`, `l`, `L`, `n`, `p`, and `h` are not supported and that there is an + extra option, `q`. The `q` option formats a string in a form suitable to be + safely read back by the Lua interpreter: the string is written between + double quotes, and all double quotes, newlines, embedded zeros, + and backslashes in the string are correctly escaped when written. + For instance, the call + `string.format('%q', 'a string with "quotes" and \n new line')` + will produce the string: + `"a string with \"quotes\" and \ + new line"` + + The options `c`, `d` `E`, `e`, `f`, `g`, `G`, `i`, `o`, `u, `X-, and `x` all + expect a number as argument, whereas `q` and `s` expect a string. + + This function does not accept string values containing embedded zeros, + except as arguments to the `q` option. + **/ + public static function format(str : String, ?e1 : Dynamic, ?e2 : Dynamic, ?e3 : Dynamic, ?e4 : Dynamic): String; + + /** + + **/ + @:overload( function (str : String, pattern : String, replace : String->Void, ?n : Int): String {}) + @:overload( function (str : String, pattern : String, replace : String->String, ?n : Int): String {}) + public static function gsub(str : String, pattern : String, replace : String, ?n : Int): String; + + /** + Returns an iterator function that, each time it is called, returns the next + captures from pattern over string `str`. If `pattern` specifies no captures, + then the whole match is produced in each call. + **/ + @:overload( function (str : String, pattern : String, match : Void->String, ?n : Int): String->Void {}) + public static function gmatch(str : String, pattern : String): Void->String; + + /** + Looks for the first match of pattern in the string s. If it finds one, + then match returns the captures from the pattern; otherwise it returns `null`. + If pattern specifies no captures, then the whole match is returned. + The optional argument `n` specifies where to start the search; + its default value is `1` and can be negative. + **/ + public static function match(str : String, pattern : String, ?n : Int): String; + + /** + Receives a string and returns a copy of this string with all lowercase + letters changed to uppercase. All other characters are left unchanged. + The definition of what a lowercase letter is depends on the current locale. + **/ + public static function upper(str:String) : String; + + /** + Receives a string and returns a copy of this string with all uppercase + letters changed to lowercase. All other characters are left unchanged. + The definition of what an uppercase letter is depends on the current locale. + **/ + public static function lower(str:String) : String; + + /** + Returns a string containing a binary representation of the given function, + so that a later loadstring on this string returns a copy of the function. + function must be a Lua function without upvalues. + **/ + public static function dump(d:Dynamic) : Dynamic; +} + +@:multiReturn extern class StringFind { + var begin : Int; + var end : Int; +} + +@:multiReturn extern class StringSub { + var match : String; + var count : Int; +} diff --git a/std/lua/Os.hx b/std/lua/Os.hx new file mode 100644 index 00000000..f5af7948 --- /dev/null +++ b/std/lua/Os.hx @@ -0,0 +1,127 @@ +package lua; + +/** + Operating System Facilities. +**/ +@:native("_G.os") +extern class Os { + /** + Returns an approximation of the amount in seconds of CPU time used by the + program. + **/ + public static function clock() : Float; + + @:overload( function (format : String, time : Time) : DateType {}) + @:overload( function (format : String) : DateType {}) + public static function date() : DateType; + + /** + Returns the number of seconds from time `t1` to time `t2`. + In POSIX, Windows, and some other systems, this value is exactly `t2-t1`. + **/ + public static function difftime(t2: Time, t1: Time) : Float; + + // TODO: multi-return + /** + This function is equivalent to the C function system. It passes command to + be executed by an operating system shell. It returns a status code, + which is system-dependent. If command is absent, then it returns + nonzero if a shell is available and zero otherwise. + **/ +#if (lua_ver < 5.2) + public static function execute(?command:String) : Int; +#elseif (lua_ver >= 5.2) + public static function execute(?command:String) : OsExecute; +#else + public static function execute(?command:String) : Dynamic; +#end + + /** + Calls the C function exit, with an optional code, to terminate the host program. + The default value for code is the success code. + **/ + public static function exit(code: Int) : Int; + + /** + Returns the value of the process environment variable `varname`, or `null` + if the variable is not defined. + **/ + public static function getenv(varname : String) : String; + + /** + Deletes the file or directory with the given name. + Directories must be empty to be removed. + **/ + public static function remove(filename : String) : OsSuccess; + + /** + Renames file or directory named `oldname` to `newname`. + **/ + public static function rename(oldname : String, newname : String) : OsSuccess; + + /** + Sets the current locale of the program. + **/ + public static function setlocale(locale : String, ?category : LocaleCategory ) : String; + + /** + Returns the current time when called without arguments, or a time + representing the date and time specified by the given table. + + The returned value is a number, whose meaning depends on your system. + In POSIX, Windows, and some other systems, this number counts the number + of seconds since some given start time (the "epoch"). + In other systems, the meaning is not specified, and the number returned + by time can be used only as an argument to date and difftime. + **/ + public static function time(?arg : TimeParam) : Time; + + /** + Returns a string with a file name that can be used for a temporary file. + The file must be explicitly opened before its use and explicitly removed + when no longer needed. + + When possible, you may prefer to use `Io.tmpfile`, which automatically + removes the file when the program ends. + **/ + public static function tmpname() : String; +} + +/** + A typedef that matches the date parameter `Os.time()` will accept. +**/ +typedef TimeParam = { + year : Float, + month : Float, + day : Float, + ?hour : Int, + ?min : Int, + ?sec : Int, + ?isdst : Bool +} + +/** + A typedef that describes the output of `Os.date()`. +**/ +typedef DateType = { + hour : Int, + min : Int, + sec : Int, + isdst : Bool, + year : Int, + month : Int, + wday : Int, + yday : Int, + day : Int, +} + +@:multiReturn extern class OsExecute { + var success : Bool; + var output : String; + var status : Int; +} + +@:multiReturn extern class OsSuccess { + var success : Bool; + var message : String; +} diff --git a/std/lua/Package.hx b/std/lua/Package.hx new file mode 100644 index 00000000..c1867eeb --- /dev/null +++ b/std/lua/Package.hx @@ -0,0 +1,70 @@ +/* + * Copyright (C)2005-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 lua; + +/** + Externs for lua package handling + **/ +@:native("_G.package") +extern class Package { + /** + A string describing some compile-time configurations for packages. + **/ + public static var config : String; + + /** + The path used by require to search for a Lua loader. + **/ + public static var path : String; + + /** + The path used by require to search for a C loader. + **/ + public static var cpath : String; + + /** + A table used by require to control which modules are already loaded. + **/ + public static var loaded : Table; + + /** + A table to store loaders for specific modules. + **/ + public static var preload : Table; + + /** + A table used by require to control how to load modules. + Each entry in this table is a searcher function. + **/ + public static var searchers :TableNull>; + + /** + Searches for the given `libname` in the given path `funcname`. + A path is a string containing a sequence of templates separated by semicolons. + **/ + public static function searchpath(name : String, path : String, ?sep : String, ?rep : String) : Null; + + /** + Dynamically links the host program with the C library `libname`. + **/ + public static function loadlib(libname : String, funcname : String) : Void; +} diff --git a/std/lua/PairTools.hx b/std/lua/PairTools.hx new file mode 100644 index 00000000..e0121242 --- /dev/null +++ b/std/lua/PairTools.hx @@ -0,0 +1,59 @@ +package lua; +/** + A set of utility methods for working with the Lua table extern. + **/ +class PairTools { + public static function ipairsEach(table:Table, func : Int->T->Void) : Void { + untyped __lua__("for i,v in _G.ipairs(table) do func(i,v) end"); + } + public static function pairsEach(table:Table, func : A->B->Void) : Void { + untyped __lua__("for k,v in _G.pairs(table) do func(k,v) end"); + } + public static function ipairsMap(table:Table, func : Int->A->B) : Table { + var ret : Table = Table.create(); + untyped __lua__( "for i,v in _G.ipairs(table) do ret[i] = func(i,v) end;"); + return ret; + } + public static function pairsMap(table:Table, func : A->B->C->C) : Table { + var ret : Table = Table.create(); + untyped __lua__( "for k,v in _G.pairs(table) do ret[k] = func(k,v) end;"); + return ret; + } + public static function ipairsFold(table:Table, func : Int->A->B->B, seed: B) : B { + untyped __lua__("for i,v in _G.ipairs(table) do seed = func(i,v,seed) end"); + return untyped __lua__("seed"); + } + public static function pairsFold(table:Table, func : A->B->C->C, seed: C) : C { + untyped __lua__("for k,v in _G.pairs(table) do seed = func(k,v,seed) end"); + return untyped __lua__("seed"); + } + + + public static function ipairsConcat(table1:Table, table2:Table){ + var ret:Table = Table.create(); + ipairsFold(table1, function(a,b,c:Table){ c[a] = b; return c;}, ret); + var size = lua.TableTools.maxn(ret); + ipairsFold(table2, function(a,b,c:Table){ c[a + size] = b; return c;}, ret); + return ret; + } + + public static function pairsMerge(table1:Table, table2:Table){ + var ret = copy(table1); + pairsEach(table2, function(a,b:B) ret[cast a] = b); + return ret; + } + + public static function ipairsExist(table:Table, func: Int->T->Bool) { + untyped __lua__("for k,v in _G.ipairs(table) do if func(k,v) then return true end end"); + } + + public static function pairsExist(table:Table, func: A->B->Bool) { + untyped __lua__("for k,v in _G.pairs(table) do if func(k,v) then return true end end"); + } + + public static function copy(table1:Table) : Table { + var ret : Table = Table.create(); + untyped __lua__("for k,v in _G.pairs(table1) do ret[k] = v end"); + return ret; + } +} diff --git a/std/lua/Result.hx b/std/lua/Result.hx new file mode 100644 index 00000000..fd396cc1 --- /dev/null +++ b/std/lua/Result.hx @@ -0,0 +1,5 @@ +package lua; +@:multiReturn extern class Result { + var result : T; + var message : String; +} diff --git a/std/lua/Table.hx b/std/lua/Table.hx new file mode 100644 index 00000000..2bf80c67 --- /dev/null +++ b/std/lua/Table.hx @@ -0,0 +1,34 @@ +package lua; + +/** + This library provides generic functions for table manipulation. +**/ +// TODO: use an abstract here? +@:native("_G.table") +extern class Table implements ArrayAccess implements Dynamic { + public inline static function create(?arr:Array, ?hsh:Dynamic) : Table { + return untyped __lua_table__(arr,hsh); + } + + @:overload(function(table:Table):Void{}) + public static function concat(table:Table, ?sep:String) : String; + + public static function foreach(table:Table, f:A->B->Void) : Void; + public static function foreachi(table:Table, f:A->B->Int->Void) : Void; + + public static function sort(table:Table, ?order : A->A->Bool) : Void; + + @:overload(function(table:Table, value:B):Void{}) + public static function insert(table:Table, pos:Int, value:B) : Void; + + @:overload(function(table:Table):Void{}) + public static function remove(table:Table, ?pos:Int) : Void; + +#if (lua_ver >= 5.2) + public static function pack(args:haxe.extern.Rest) : Table; + public static function unpack(args:lua.Table, ?min : Int, ?max : Int) : Dynamic; +#end + +} + +typedef AnyTable = Table; diff --git a/std/lua/TableTools.hx b/std/lua/TableTools.hx new file mode 100644 index 00000000..f95fdac0 --- /dev/null +++ b/std/lua/TableTools.hx @@ -0,0 +1,15 @@ + +package lua; + +/** + This library provides generic functions for table manipulation. +**/ +@:native("_hx_table") +extern class TableTools { + public static function pack(args:haxe.extern.Rest) : Table; + public static function unpack(args:lua.Table, ?min : Int, ?max : Int) : Dynamic; + public static function maxn(t:Table.AnyTable) : Int; + public static function __init__() : Void { + untyped __define_feature__("use._hx_table", null); + } +} diff --git a/std/lua/Thread.hx b/std/lua/Thread.hx new file mode 100644 index 00000000..9762f739 --- /dev/null +++ b/std/lua/Thread.hx @@ -0,0 +1,30 @@ + +/* + * Copyright (C)2005-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 lua; + +/** + The sole purpose of this extern is to provide a concrete type for + basic reflection purposes. +**/ +class Thread {} diff --git a/std/lua/Time.hx b/std/lua/Time.hx new file mode 100644 index 00000000..035e453c --- /dev/null +++ b/std/lua/Time.hx @@ -0,0 +1,6 @@ +package lua; +/* + Note: Lua timestamps are usually ints. Platform differences can produce + Floats in certain cases. + */ +typedef Time = Float; diff --git a/std/lua/UserData.hx b/std/lua/UserData.hx new file mode 100644 index 00000000..35561532 --- /dev/null +++ b/std/lua/UserData.hx @@ -0,0 +1,2 @@ +package lua; +class UserData {} diff --git a/std/lua/_lua/_hx_anon.lua b/std/lua/_lua/_hx_anon.lua new file mode 100644 index 00000000..3a5c9656 --- /dev/null +++ b/std/lua/_lua/_hx_anon.lua @@ -0,0 +1,28 @@ +local function _hx_anon_newindex(t,k,v) t.__fields__[k] = true; rawset(t,k,v); end +local _hx_anon_mt = {__newindex=_hx_anon_newindex} +local function _hx_a(...) + local __fields__ = {}; + local ret = {__fields__ = __fields__}; + local max = select('#',...); + local tab = {...}; + local cur = 1; + while cur < max do + local v = tab[cur]; + __fields__[v] = true; + ret[v] = tab[cur+1]; + cur = cur + 2 + end + return setmetatable(ret, _hx_anon_mt) +end + +local function _hx_e() + return setmetatable({__fields__ = {}}, _hx_anon_mt) +end + +local function _hx_o(obj) + return setmetatable(obj, _hx_anon_mt) +end + +local function _hx_new(prototype) + return setmetatable({__fields__ = {}}, {__newindex=_hx_anon_newindex, __index=prototype}) +end diff --git a/std/lua/_lua/_hx_apply.lua b/std/lua/_lua/_hx_apply.lua new file mode 100644 index 00000000..007e4cf9 --- /dev/null +++ b/std/lua/_lua/_hx_apply.lua @@ -0,0 +1,6 @@ +local function _hx_apply(f, ...) + return f(...) +end +local function _hx_apply_self(self, f, ...) + return self[f](self,...) +end diff --git a/std/lua/_lua/_hx_classes.lua b/std/lua/_lua/_hx_classes.lua new file mode 100644 index 00000000..d499a18c --- /dev/null +++ b/std/lua/_lua/_hx_classes.lua @@ -0,0 +1,13 @@ +local _hxClasses = {} +Int = (function() _hxClasses.Int = _hx_o({__fields__={__name__=true},__name__={"Int"}}); return _hxClasses.Int end)(); +Dynamic = (function() +_hxClasses.Dynamic = _hx_o({__fields__={__name__=true},__name__={"Dynamic"}}); return _hxClasses.Dynamic end)(); +Float = (function() +_hxClasses.Float = _hx_e(); return _hxClasses.Float end)(); +Float.__name__ = {"Float"} +Bool = (function() +_hxClasses.Bool = _hx_e(); return _hxClasses.Bool end)(); +Bool.__ename__ = {"Bool"} +Class = (function() +_hxClasses.Class = _hx_o({__fields__={__name__=true},__name__={"Class"}}); return _hxClasses.Class end)(); +Enum = _hx_e(); diff --git a/std/lua/_lua/_hx_tab_array.lua b/std/lua/_lua/_hx_tab_array.lua new file mode 100644 index 00000000..23d48a8f --- /dev/null +++ b/std/lua/_lua/_hx_tab_array.lua @@ -0,0 +1,12 @@ +local _hx_array_mt = { + __newindex = function(t,k,v) + local len = t.length + t.length = k >= len and (k + 1) or len + rawset(t,k,v) + end +} + +local function _hx_tab_array(tab,length) + tab.length = length + return setmetatable(tab, _hx_array_mt) +end diff --git a/std/lua/_std/Array.hx b/std/lua/_std/Array.hx new file mode 100644 index 00000000..2354c5b8 --- /dev/null +++ b/std/lua/_std/Array.hx @@ -0,0 +1,219 @@ +/* + * Copyright (C)2005-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. + */ +@:coreApi +class Array { + + public var length(default,null) : Int; + + public function new() : Void { + untyped _hx_tab_array(this, 0); + } + public function concat( a : Array ) : Array { + var ret = this.copy(); + for (i in a) ret.push(i); + return ret; + } + public function join( sep : String ) : String { + var tbl : lua.Table = lua.Table.create(); + for (i in iterator()){ + lua.Table.insert(tbl,Std.string(i)); + } + return lua.Table.concat(tbl,sep); + } + + public function pop() : Null { + if (length == 0 ) return null; + var rawlength = lua.Lua.rawget(cast this, 'length'); + var ret = lua.Lua.rawget(cast this, rawlength-1); + lua.Lua.rawset(cast this, 'length', rawlength-1); + return ret; + } + public function push(x : T) : Int { + lua.Lua.rawset(cast this,length,x); + lua.Lua.rawset(cast this,'length', length + 1); + return lua.Lua.rawget(cast this,'length'); + } + public function reverse() : Void { + var tmp:T; + var i = 0; + while(i < Std.int(this.length/2)){ + tmp = this[i]; + this[i] = this[this.length-i-1]; + this[this.length-i-1] = tmp; + i++; + } + } + public function shift() : Null { + if (this.length == 0) return null; + var ret = this[0]; + for (i in 0...length){ + this[i] = this[i+1]; + } + this.length-=1; + return ret; + } + public function slice( pos : Int, ?end : Int ) : Array { + if (end == null || end > length) end = length; + else if (end < 0) end = (length-(-end % length)) % length; // negative pos needs to be wrapped from the end, and mod according to array length + if (pos < 0) pos = (length -(-pos % length)) % length; // and here + if (pos > end || pos > length) return []; + + var ret = []; + for (i in pos...end){ + ret.push(this[i]); + } + return ret; + } + + // TODO: copied from neko Array.sort, move to general util library? + public function sort( f : T -> T -> Int ) : Void { + var i = 0; + var l = this.length; + while( i < l ) { + var swap = false; + var j = 0; + var max = l - i - 1; + while( j < max ) { + if( f(this[j],this[j+1]) > 0 ) { + var tmp = this[j+1]; + this[j+1] = this[j]; + this[j] = tmp; + swap = true; + } + j += 1; + } + if( !swap ) + break; + i += 1; + } + } + + public function splice( pos : Int, len : Int ) : Array { + if (len < 0 || pos > length) return []; + else if (pos < 0) pos = length -(-pos % length); + len = cast Math.min(len,this.length-pos); + var ret = []; + for (i in pos...(pos+len)){ + ret.push(this[i]); + this[i] = this[i+len]; + } + for (i in (pos+len)...length){ + this[i] = this[i+len]; + } + this.length-= len; + return ret; + } + + public function toString() : String { + var tbl : lua.Table = lua.Table.create(); + lua.Table.insert(tbl, '['); + lua.Table.insert(tbl, join(",")); + lua.Table.insert(tbl, ']'); + return lua.Table.concat(tbl,""); + } + + public function unshift( x : T ) : Void { + var len = length; + for (i in 0...len) this[len - i] = this[len - i - 1]; + this[0] = x; + } + + public inline function insert( pos : Int, x : T ) : Void { + if (pos > length) pos = length; + if (pos < 0) { + pos = (length + pos); + if (pos < 0) pos = 0; + } + var cur_len = length; + while (cur_len > pos){ + this[cur_len] = this[cur_len-1]; + cur_len -=1; + } + this[pos] = x; + } + + public function remove( x : T ) : Bool { + for (i in 0...length){ + if (this[i] == x){ + for (j in i...length-1){ + this[j] = this[j+1]; + } + // We need to decrement the length variable, and set its + // value to null to avoid hanging on to a reference in the + // underlying lua table. + this[length-1] = null; + // Do this in two steps to avoid re-updating the __index metamethod + length--; + + return true; + } + } + return false; + } + + public function indexOf( x : T, ?fromIndex:Int ) : Int { + var end = length; + if (fromIndex == null) fromIndex = 0; + else if (fromIndex < 0 ) { + fromIndex = length + fromIndex; + if (fromIndex < 0) fromIndex = 0; + } + for (i in fromIndex...end){ + if (x == this[i]) return i; + } + return -1; + } + public function lastIndexOf( x : T, ?fromIndex:Int ) : Int { + if (fromIndex == null || fromIndex >= length ) fromIndex = length-1; + else if (fromIndex < 0) { + fromIndex = length + fromIndex; + if (fromIndex < 0) return -1; + } + var i = fromIndex; + while(i >= 0){ + if (this[i] == x) return i; + else i--; + } + return -1; + } + public inline function copy() : Array { + return [for (i in this) i]; + } + public function map(f:T->S):Array { + return [for (i in this) f(i)]; + } + public function filter(f:T->Bool):Array { + return [for (i in this) if (f(i)) i]; + } + public inline function iterator() : Iterator { + var cur_length = 0; + return { + hasNext : function() return cur_length < length, + next : function() return this[cur_length++] + } + } + private static function __init__() : Void{ + // table-to-array helper + haxe.macro.Compiler.includeFile("lua/_lua/_hx_tab_array.lua"); + } + +} diff --git a/std/lua/_std/Date.hx b/std/lua/_std/Date.hx new file mode 100644 index 00000000..ad4be014 --- /dev/null +++ b/std/lua/_std/Date.hx @@ -0,0 +1,68 @@ +/* + * Copyright (C)2005-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. + */ +@:coreApi class Date { + var d : lua.Os.DateType; + var t : lua.Time; + + public function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) { + t = lua.Os.time({ + year : year, + month : month+1, + day : day, + hour : hour, + min : min, + sec : sec + }); + d =lua.Os.date("*t", t); + }; + public function getTime() : Float return cast t * 1000; + public function getHours() : Int return d.hour; + public function getMinutes() : Int return d.min; + public function getSeconds() : Int return d.sec; + public function getFullYear() : Int return d.year; + public function getMonth() : Int return d.month-1; + public function getDate() : Int return d.day; + public function getDay() : Int return d.wday-1; + + public inline function toString() : String { + return lua.Boot.dateStr(this); + } + + public static inline function now() : Date { + return fromTime(lua.Os.time()*1000); + } + + public static inline function fromTime( t : Float ) : Date { + var d : Dynamic = {} + untyped { + lua.Lua.setmetatable(d, untyped {__index : Date.prototype}); + d.t = t/1000; + d.d = lua.Os.date("*t", Std.int(d.t)); + } + return d; + } + + public static inline function fromString( s : String ) : Date { + return lua.Boot.strDate(s); + } +} + diff --git a/std/lua/_std/EReg.hx b/std/lua/_std/EReg.hx new file mode 100644 index 00000000..3cf5fd55 --- /dev/null +++ b/std/lua/_std/EReg.hx @@ -0,0 +1,163 @@ +/* + * Copyright (C)2005-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. + */ +import lua.lib.lrexlib.Rex; +import lua.Table; +import lua.Lib; +import lua.NativeStringTools; + +@:coreApi +class EReg { + + var r : Rex; // the Rex extern instance. + var global : Bool; // whether the regex is in global mode. + var s : String; // the last matched string + var m : Table; // the [start:Int, end:Int, and submatches:String (matched groups)] as a single table. + + static var FLAGS : Table = Rex.flags(); + + public function new( r : String, opt : String ) : Void { + var ropt = 0; + for (i in 0...opt.length){ + switch(opt.charAt(i)){ + case "i" : ropt |= FLAGS.CASELESS; + case "m" : ropt |= FLAGS.MULTILINE; + case "s" : ropt |= FLAGS.DOTALL; + case "u" : ropt |= FLAGS.UTF8; + case "g" : global = true; + default : null; + } + } + if (global == null) global = false; + this.r = Rex.create(r, ropt); + } + + public function match( s : String ) : Bool { + if (s == null) return false; + this.m = lua.TableTools.pack(r.exec(s)); + this.s = s; + return m[1] != null; + } + + public function matched( n : Int ) : String { + if (m[1] == null || n < 0) throw "EReg::matched"; + else if (n == 0) { + var k = NativeStringTools.sub(s, m[1], m[2]).match; + return k; + } else if (Std.is(m[3], lua.Table)){ + var mn = 2 * (n - 1); + if (Std.is(untyped m[3][mn+1], Bool)) return null; + return NativeStringTools.sub(s, untyped m[3][mn + 1], untyped m[3][mn + 2]).match; + } else { + throw "EReg:matched"; + } + } + + public function matchedLeft() : String { + if( m[1] == null ) throw "No string matched"; + return NativeStringTools.sub(s, 1, m[1]-1).match; + } + + public function matchedRight() : String { + if( m[1] == null ) throw "No string matched"; + return NativeStringTools.sub(s, m[2]+1).match; + } + + public function matchedPos() : { pos : Int, len : Int } { + if( m[1] == null ) throw "No string matched"; + return { + pos : m[1]-1, + len : m[2]-m[1]+ 1 + } + } + + public function matchSub( s : String, pos : Int, len : Int = -1):Bool { + + var ss = s.substr(0, len < 0 ? s.length : pos + len); + + if (global){ + m = lua.TableTools.pack(r.exec(ss, pos + 1)); + var b = m[1] != null; + if (b){ + this.s = s; + } + return b; + } else { + m = lua.TableTools.pack(r.exec(ss, pos + 1)); + var b = m[1] != null; + if (b){ + this.s = s; + } + return b; + } + } + + public function split( s : String ) : Array { + if (global){ + return Lib.fillArray(Rex.split(s, r)); + } else { + // we can't use directly Rex.split because it's ignoring the 'g' flag + var d = "#__delim__#"; + return Lib.fillArray(Rex.split(replace(s,d), d)); + } + } + + public function replace( s : String, by : String ) : String { + by = Rex.gsub(by, "\\$(\\d)", "%%1"); // convert dollar sign matched groups to Rex equivalent + by = Rex.gsub(by, "\\${2}", "$"); // escape double dollar signs + return Rex.gsub(s,r,by, global ? null : 1); + } + + public function map( s : String, f : EReg -> String ) : String { + var offset = 0; + var buf = new StringBuf(); + do { + if (offset >= s.length){ + break; + } + else if (!matchSub(s, offset)) { + buf.add(s.substr(offset)); + break; + } + var p = matchedPos(); + + buf.add(s.substr(offset, p.pos - offset)); + buf.add(f(this)); + if (p.len == 0) { + buf.add(s.substr(p.pos, 1)); + offset = p.pos + 1; + } + else + offset = p.pos + p.len; + + } while (global); + if (!global && offset > 0 && offset < s.length) + buf.add(s.substr(offset)); + return buf.toString(); + } + + static function __init__() : Void { + if (Rex == null){ + throw "Rex is missing. Please install lrexlib-pcre."; + } + } +} + diff --git a/std/lua/_std/Math.hx b/std/lua/_std/Math.hx new file mode 100644 index 00000000..6d5090f3 --- /dev/null +++ b/std/lua/_std/Math.hx @@ -0,0 +1,77 @@ +/* + * Copyright (C)2005-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; + +class Math +{ + public static var PI(get,null) : Float; + static inline function get_PI () : Float return lua.Math.pi; + + public static var NEGATIVE_INFINITY(get, null) : Float; + static inline function get_NEGATIVE_INFINITY () : Float return -lua.Math.huge; + + public static var POSITIVE_INFINITY(get,null) : Float; + static inline function get_POSITIVE_INFINITY () : Float return lua.Math.huge; + + public static var NaN(get, null) : Float; + + // Note: this has to be an untyped literal, otherwise the compiler tries + // to unify it to an Int, which defeats useful numeric reflection behavior. + static inline function get_NaN () : Float return untyped __lua__("(0/0)"); + + public static function isNaN( f : Float ) : Bool return (f != f); + public static inline function isFinite( f : Float ) : Bool { + return (f > Math.NEGATIVE_INFINITY && f < Math.POSITIVE_INFINITY); + } + + public static inline function abs(v:Float) :Float return lua.Math.abs(v); + public static inline function acos(v:Float):Float return lua.Math.acos(v); + public static inline function asin(v:Float):Float return lua.Math.asin(v); + public static inline function atan(v:Float):Float return lua.Math.atan(v); + public static inline function ceil(v:Float):Int return lua.Math.ceil(v); + public static inline function cos(v:Float):Float return lua.Math.cos(v); + public static inline function exp(v:Float):Float return lua.Math.exp(v); + public static inline function sin(v:Float):Float return lua.Math.sin(v); + public static inline function sqrt(v:Float):Float return lua.Math.sqrt(v); + public static inline function tan(v:Float):Float return lua.Math.tan(v); + + public static inline function floor(v:Float):Int return lua.Math.floor(v); + public static inline function log(v:Float):Float return lua.Math.log(v); + + public static inline function random() : Float return untyped __define_feature__("Math.random", lua.Math.random()); + + public static inline function atan2(y:Float, x:Float):Float return lua.Math.atan2(y,x); + public static inline function max(a:Float, b:Float):Float { + return Math.isNaN(a) || Math.isNaN(b) ? Math.NaN : lua.Math.max(a,b); + } + public static inline function min(a:Float, b:Float):Float { + return Math.isNaN(a) || Math.isNaN(b) ? Math.NaN : lua.Math.min(a,b); + } + public static inline function pow(v:Float, exp:Float):Float return lua.Math.pow(v,exp); + + public static inline function round(v:Float):Int return Math.floor(v + 0.5); + + public static inline function ffloor( v : Float ) : Float return floor(v); + public static inline function fceil( v : Float ) : Float return ceil(v); + public static inline function fround( v : Float ) : Float return round(v); + +} diff --git a/std/lua/_std/Reflect.hx b/std/lua/_std/Reflect.hx new file mode 100644 index 00000000..48a848a7 --- /dev/null +++ b/std/lua/_std/Reflect.hx @@ -0,0 +1,157 @@ +/* + * Copyright (C)2005-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. + */ +import lua.Lua; +import lua.TableTools; +import lua.Boot; +@:coreApi class Reflect { + + public inline static function hasField( o : Dynamic, field : String ) : Bool { + return untyped o.__fields__ != null ? o.__fields__[field] != null : o[field] != null; + } + + public static function field( o : Dynamic, field : String ) : Dynamic untyped { + return try o[field] catch( e : Dynamic ) null; + } + + public inline static function setField( o : Dynamic, field : String, value : Dynamic ) : Void untyped { + o[field] = value; + } + + public static inline function getProperty( o : Dynamic, field : String ) : Dynamic { + var tmp : Dynamic; + return if( o == null ) { + untyped __define_feature__("Reflect.getProperty",null); + } else if( o.__properties__ != null && Reflect.field(o, "get_" + field) != null){ + callMethod(o, Reflect.field(o,"get_" + field), []); + } else { + Reflect.field(o,field); + } + } + + public static inline function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void untyped { + var tmp : String; + if( o.__properties__ && o.__properties__["set_"+field]) { + tmp = o.__properties__["set_" + field]; + if (o.__name__ != null){ + callMethod(null,Reflect.field(o, tmp), [value]) ; + } else { + callMethod(o,Reflect.field(o, tmp), [value]) ; + } + } else { + o[field] = __define_feature__("Reflect.setProperty",value); + } + } + + public inline static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array ) : Dynamic { + if (args == null || args.length == 0){ + return func(o); + } else { + var self_arg = false; + if (o != null && Type.getClass(o) != null){ + // if o is not null, it means we need to pass it as the "self" + // parameter. However, we should also check to see if it's + // a valid class instance in the first place. + // TODO: Find a more flexible way of determining if we need + // self or not + self_arg = true; + } + var new_args = lua.Table.create(); + for (i in 0...args.length){ + // copy args to 1-indexed table + new_args[i + 1] = args[i]; + } + return if (self_arg){ + // call with o as leading self param + func(o, lua.TableTools.unpack(new_args, 1, TableTools.maxn(new_args))); + } else { + // call with no self param + func(lua.TableTools.unpack(new_args, 1, TableTools.maxn(new_args))); + } + } + } + + public static function fields( o : Dynamic ) : Array { + return [for (f in lua.Boot.fieldIterator(o)) f]; + } + + public static function isFunction( f : Dynamic ) : Bool { + return Lua.type(f) == "function" && !(Boot.isClass(f) || Boot.isEnum(f)); + } + + public static function compare( a : T, b : T ) : Int { + if (a == b) return 0 + else if (a == null) return -1 + else if (b == null) return 1 + else return (cast a) > (cast b) ? 1 : -1; + } + + public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool { + return f1 == f2; + } + + public static function isObject( v : Dynamic ) : Bool untyped { + if( v == null ) + return false; + var t = __lua__("type(v)"); + return (t == "string" || (t == "table" && v.__enum__ == null)) || (t == "function" && (lua.Boot.isClass(v) || lua.Boot.isEnum(v)) != null); + } + + public static function isEnumValue( v : Dynamic ) : Bool { + return v != null && Std.is(v,lua.Table) && v.__enum__ != null; + } + + public static function deleteField( o : Dynamic, field : String ) : Bool untyped { + if( !hasField(o,field) ) return false; + o[field] = null; + o.__fields__[field]=null; + return true; + } + + public static function copy( o : T ) : T { + var o2 : Dynamic = {}; + for( f in Reflect.fields(o) ) + Reflect.setField(o2,f,Reflect.field(o,f)); + return o2; + } + + @:overload(function( f : Array -> Void ) : Dynamic {}) + public static function makeVarArgs( f : Array -> Dynamic ) : Dynamic { + /* + - Convert var arg to table + - Set indexing from zero + - Extract real table length + - Recreate as dynamic array + - Return function called with this array + */ + return untyped __lua__("function(...) + local a = {...} + local b = {} + local l = 0 + for k, v in pairs(a) do + b[k-1] = v + l = math.max(k,l) + end + return f(_hx_tab_array(b, l)) + end"); + } + +} diff --git a/std/lua/_std/Std.hx b/std/lua/_std/Std.hx new file mode 100644 index 00000000..01a9777e --- /dev/null +++ b/std/lua/_std/Std.hx @@ -0,0 +1,94 @@ +/* + * Copyright (C)2005-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. + */ +import lua.Boot; +import lua.NativeStringTools; + +@:keepInit +@:coreApi class Std { + + public static inline function is( v : Dynamic, t : Dynamic ) : Bool { + return untyped lua.Boot.__instanceof(v,t); + } + + public static inline function instance( value : T, c : Class ) : S { + return untyped lua.Boot.__instanceof(value, c) ? cast value : null; + } + + @:keep + public static function string( s : Dynamic ) : String { + return untyped lua.Boot.__string_rec(s); + } + + public static function int( x : Float ) : Int { + return lua.Boot.clamp(x); + } + + public static function parseInt( x : String ) : Null { + if (x == null) return null; + var hexMatch = NativeStringTools.match(x, "^ *[%-+]*0[xX][%da-FA-F]*"); + if (hexMatch != null){ + return lua.Lua.tonumber(hexMatch.substr(2), 16); + } else { + var intMatch = NativeStringTools.match(x, "^ *[%-+]?%d*"); + if (intMatch != null){ + return lua.Lua.tonumber(intMatch); + } else { + return null; + } + } + } + + public static function parseFloat( x : String ) : Float { + if (x == null || x == "") return Math.NaN; + var digitMatch = NativeStringTools.match(x, "^ *[%.%-+]?[0-9]%d*"); + if (digitMatch == null){ + return Math.NaN; + } + x = x.substr(digitMatch.length); + + var decimalMatch = NativeStringTools.match(x, "^%.%d*"); + if (decimalMatch == null) decimalMatch = ""; + x = x.substr(decimalMatch.length); + + var eMatch = NativeStringTools.match(x, "^[eE][+%-]?%d+"); + if (eMatch == null) eMatch = ""; + var result = lua.Lua.tonumber(digitMatch + decimalMatch + eMatch); + return result != null ? result : Math.NaN; + } + + public static function random( x : Int ) : Int { + return untyped x <= 0 ? 0 : Math.floor(Math.random()*x); + } + + static function __init__() : Void untyped { + // lua workarounds for basic anonymous object functionality + haxe.macro.Compiler.includeFile("lua/_lua/_hx_anon.lua"); + + // class reflection metadata + haxe.macro.Compiler.includeFile("lua/_lua/_hx_classes.lua"); + __feature__("lua.Boot.getClass", String.prototype.__class__ = __feature__("Type.resolveClass",_hxClasses["String"] = String,String)); + __feature__("lua.Boot.isClass", String.__name__ = __feature__("Type.getClassName", __lua_table__(["String"]),true)); + __feature__("Type.resolveClass",_hxClasses["Array"] = Array); + __feature__("lua.Boot.isClass",Array.__name__ = __feature__("Type.getClassName",__lua_table__(["Array"]),true)); + } + +} diff --git a/std/lua/_std/String.hx b/std/lua/_std/String.hx new file mode 100644 index 00000000..a45191a1 --- /dev/null +++ b/std/lua/_std/String.hx @@ -0,0 +1,129 @@ +/* + * Copyright (C)2005-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. + */ + +import lua.Lua; +import lua.Table; +import lua.Boot; +import lua.NativeStringTools; + +@:coreApi +class String { + static var __oldindex : Table; + public var length(default,null) : Int; + + + public function new(string:String) untyped {} + + @:keep + static function __index(s:Dynamic, k:Dynamic) : Dynamic { + if (k == "length") return NativeStringTools.len(s); + else if (Reflect.hasField(untyped String.prototype, k)) return untyped String.prototype[k]; + else if (__oldindex != null) return __oldindex[k]; + else return null; + } + + public function toUpperCase() : String return NativeStringTools.upper(this); + public function toLowerCase() : String return NativeStringTools.lower(this); + public function indexOf( str : String, ?startIndex : Int ) : Int { + if (startIndex == null) startIndex = 1; + else startIndex += 1; + var r = NativeStringTools.find(this, str, startIndex, true).begin; + if (r != null && r > 0) return r-1; + else return -1; + } + + public function lastIndexOf( str : String, ?startIndex : Int ) : Int { + var i = 0; + var ret = -1; + if( startIndex == null ) startIndex = length; + while( true ) { + var p = indexOf(str, ret+1); + if( p == -1 || p > startIndex ) return ret; + ret = p; + } + } + + public function split( delimiter : String ) : Array { + var idx = 1; + var ret = []; + var delim_offset = delimiter.length > 0 ? delimiter.length : 1; + while (idx != null){ + var newidx = 0; + if (delimiter.length > 0){ + newidx = NativeStringTools.find(this, delimiter, idx, true).begin; + } else if (idx >= this.length){ + newidx = null; + } else { + newidx = idx + 1; + } + + if (newidx != null){ + var match = NativeStringTools.sub(this, idx, newidx-1).match; + ret.push(match); + idx = newidx + delimiter.length; + } else { + ret.push(NativeStringTools.sub(this,idx,NativeStringTools.len(this)).match); + idx = null; + } + } + return ret; + } + + public function toString() : String { + return this; + } + public function substring( startIndex : Int, ?endIndex : Int ) : String { + if (endIndex == null) endIndex = this.length; + if (endIndex < 0) endIndex = 0; + if (startIndex < 0) startIndex = 0; + if (endIndex < startIndex) { + // swap the index positions + return NativeStringTools.sub(this, endIndex+1, startIndex).match; + } else { + return NativeStringTools.sub(this, startIndex+1, endIndex).match; + } + } + + function get_length() : Int { + return NativeStringTools.len(this); + } + public function charAt( index : Int) : String { + return NativeStringTools.sub(this,index+1, index+1).match; + } + public function charCodeAt( index : Int) : Null { + return NativeStringTools.byte(this,index+1); + } + + public function substr( pos : Int, ?len : Int ) : String { + if (len == null || len > pos + this.length) len = this.length; + else if (len < 0) len = length + len; + if (pos < 0) pos = length + pos; + if (pos < 0) pos = 0; + return NativeStringTools.sub(this, pos + 1, pos+len).match; + } + + public inline static function fromCharCode( code : Int ) : String { + return NativeStringTools.char(code); + } + +} + diff --git a/std/lua/_std/StringBuf.hx b/std/lua/_std/StringBuf.hx new file mode 100644 index 00000000..50529ebe --- /dev/null +++ b/std/lua/_std/StringBuf.hx @@ -0,0 +1,111 @@ +/* + * Copyright (C)2005-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. + */ +/** + A String buffer is an efficient way to build a big string by appending small + elements together. + + Its cross-platform implementation uses String concatenation internally, but + StringBuf may be optimized for different targets. + + Unlike String, an instance of StringBuf is not immutable in the sense that + it can be passed as argument to functions which modify it by appending more + values. However, the internal buffer cannot be modified. +**/ +import lua.Table; + +class StringBuf { + + var b:Dynamic; + + /* + The length of `this` StringBuf in characters. + **/ + public var length(get,null) : Int; + + /** + Creates a new StringBuf instance. + + This may involve initialization of the internal buffer. + **/ + public inline function new() { + b = {}; + this.length = 0; + } + + inline function get_length() : Int { + return length; + } + + /** + Appends the representation of `x` to `this` StringBuf. + + The exact representation of `x` may vary per platform. To get more + consistent behavior, this function should be called with + Std.string(x). + + If `x` is null, the String "null" is appended. + **/ + public inline function add( x : T ) : Void { + var str = Std.string(x); + Table.insert(b, str); + length += str.length; + } + + /** + Appends the character identified by `c` to `this` StringBuf. + + If `c` is negative or has another invalid value, the result is + unspecified. + **/ + public inline function addChar( c : Int ) : Void { + Table.insert(b, String.fromCharCode(c)); + length += 1; + } + + /** + Appends a substring of `s` to `this` StringBuf. + + This function expects `pos` and `len` to describe a valid substring of + `s`, or else the result is unspecified. To get more robust behavior, + `this.add(s.substr(pos,len))` can be used instead. + + If `s` or `pos` are null, the result is unspecified. + + If `len` is omitted or null, the substring ranges from `pos` to the end + of `s`. + **/ + public inline function addSub( s : String, pos : Int, ?len : Int) : Void { + var part = len == null ? s.substr(pos) : s.substr(pos, len); + Table.insert(b, part); + length += part.length; + } + + /** + Returns the content of `this` StringBuf as String. + + The buffer is not emptied by this operation. + **/ + public inline function toString() : String { + return Table.concat(b); + } + +} diff --git a/std/lua/_std/Sys.hx b/std/lua/_std/Sys.hx new file mode 100644 index 00000000..27264030 --- /dev/null +++ b/std/lua/_std/Sys.hx @@ -0,0 +1,123 @@ + +/* + * Copyright (C)2005-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. + */ + +using lua.NativeStringTools; +import lua.Package; +import lua.Lua; +import lua.Table; +import lua.TableTools; +import lua.Os; +import lua.FileHandle; +import lua.Io; +import lua.Boot; +import sys.io.FileInput; +import sys.io.FileOutput; + +@:coreApi +class Sys { + static var _system_name : String; + public static inline function print( v : Dynamic ) : Void { + return lua.Lib.print(v); + } + public static inline function println( v : Dynamic ) : Void { + return lua.Lib.println(v); + } + public inline static function args() : Array { + var args = lua.Lib.tableToArray(lua.Lua.arg).copy(); + args.shift(); + return args; + } + public static function command( cmd : String, ?args : Array ) : Int { + var p = new sys.io.Process(cmd, args); + var code = p.exitCode(); + p.close(); + return code; + } + + + public inline static function cpuTime() : Float { + return lua.Os.clock(); + } + + public inline static function exit(code : Int) : Void { + lua.Os.exit(code); + } + + public inline static function getChar(echo : Bool) : Int { + return lua.Io.read(1).byte(); + } + + static function getSystemName() : String { + return lua.Boot.systemName(); + } + + public static function systemName() : String { + if (_system_name == null) _system_name = getSystemName(); + return _system_name; + } + + public static function environment() : Map { + var map = new Map(); + var f = function(k,v) map.set(k,v); + untyped __lua__("for k,v in lua.lib.environ.Environ.enum() do f(k,v) end"); + return map; + } + + @:deprecated("Use programPath instead") public static function executablePath() : String { + return lua.lib.luv.Misc.exepath(); + } + + public inline static function programPath() : String { + return haxe.io.Path.join([getCwd(), Lua.arg[0]]); + } + + public inline static function getCwd() : String + return lua.lib.luv.Misc.cwd(); + + public inline static function setCwd(s : String) : Void + lua.lib.luv.Misc.chdir(s); + + public inline static function getEnv(s : String) : String { + return lua.Os.getenv(s); + } + public inline static function putEnv(s : String, v : String ) : Void { + lua.lib.environ.Environ.setenv(s,v); + } + + public inline static function setTimeLocale(loc : String) : Bool { + // TODO Verify + return lua.Os.setlocale(loc) != null; + } + + public static function sleep(seconds : Float) : Void + lua.lib.luv.Thread.sleep(Math.floor(seconds * 1000)); + + + public inline static function stderr() : haxe.io.Output return new FileOutput(Io.stderr); + public inline static function stdin() : haxe.io.Input return new FileInput(Io.stdin); + public inline static function stdout() : haxe.io.Output return new FileOutput(Io.stdout); + + public static function time() : Float + return lua.lib.luasocket.Socket.gettime(); + +} diff --git a/std/lua/_std/Type.hx b/std/lua/_std/Type.hx new file mode 100644 index 00000000..1c9b8212 --- /dev/null +++ b/std/lua/_std/Type.hx @@ -0,0 +1,207 @@ +/* + * Copyright (C)2005-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. + */ +import lua.Lua; +import lua.Table; + +enum ValueType { + TNull; + TInt; + TFloat; + TBool; + TObject; + TFunction; + TClass( c : Class ); + TEnum( e : Enum ); + TUnknown; +} + +@:coreApi class Type { + + public static function getClass( o : T ) : Class untyped { + if( o == null ) + return null; + return lua.Boot.getClass(o); + } + + public static function getEnum( o : EnumValue ) : Enum untyped { + if( o == null ) + return null; + return o.__enum__; + } + + public static function getSuperClass( c : Class ) : Class untyped { + return c.__super__; + } + + + public static function getClassName( c : Class ) : String { + if (untyped c.__name__ == null) return null; + return lua.Table.concat(untyped c.__name__,'.'); + } + + public static function getEnumName( e : Enum ) : String { + if (untyped e.__ename__ == null) return null; + return lua.Table.concat(untyped e.__ename__,'.'); + } + + public static function resolveClass( name : String ) : Class untyped { + // TODO: better tmp name for _hxClasses + var cl : Class = _hxClasses[name]; + // ensure that this is a class + if( cl == null || !lua.Boot.isClass(cl) ) + return null; + return cl; + } + + public static function resolveEnum( name : String ) : Enum untyped { + // TODO: better tmp name for _hxClasses + var e : Dynamic = _hxClasses[name]; + // ensure that this is an enum + if( e == null || !lua.Boot.isEnum(e) ) + return null; + return e; + } + + public static function createInstance( cl : Class, args : Array ) : T untyped { + return __new__(cl, lua.TableTools.unpack(cast args, 0)); + } + + public static function createEmptyInstance( cl : Class ) : T untyped { + var ret = __lua_table__(); + Lua.setmetatable(ret, untyped {__index : cl.prototype}); + return ret; + } + + public static function createEnum( e : Enum, constr : String, ?params : Array ) : T { + var f:Dynamic = Reflect.field(e,constr); + if( f == null ) throw "No such constructor "+constr; + if( Reflect.isFunction(f) ) { + if( params == null ) throw "Constructor "+constr+" need parameters"; + return Reflect.callMethod(null,f,params); + } + if( params != null && params.length != 0 ) + throw "Constructor "+constr+" does not need parameters"; + return f; + } + + public static function createEnumIndex( e : Enum, index : Int, ?params : Array ) : T { + var c : String = (untyped e.__constructs__)[index]; + if( c == null ) throw index+" is not a valid enum constructor index"; + return createEnum(e,c,params); + } + + public static function getInstanceFields( c : Class ) : Array { + var p : Dynamic = untyped c.prototype; + var a :Array = []; + while (p != null){ + for (f in lua.Boot.fieldIterator(p)){ + if (!Lambda.has(a,f)) a.push(f); + } + var mt = lua.Lua.getmetatable(p); + if (mt != null && mt.__index != null ) p = mt.__index; + else p = null; + } + return a; + } + + public static function getClassFields( c : Class ) : Array { + var a = Reflect.fields(c); + a.remove("__name__"); + a.remove("__interfaces__"); + a.remove("__properties__"); + a.remove("__super__"); + a.remove("__meta__"); + a.remove("prototype"); + a.remove("new"); + return a; + } + + public static function getEnumConstructs( e : Enum ) : Array { + var a : Array = untyped e.__constructs__; + return a.copy(); + } + + public static function typeof( v : Dynamic ) : ValueType { + + switch( Lua.type(v) ) { + case "boolean": return TBool; + case "string": return TClass(String); + case "number": + // this should handle all cases : NaN, +/-Inf and Floats outside range + if( Math.ceil(v) == v%2147483648.0 ) + return TInt; + return TFloat; + case "table": + var e = v.__enum__; + if( e != null ) + return TEnum(e); + var c = lua.Boot.getClass(v); + if( c != null ) + return TClass(c); + return TObject; + case "function": + if( lua.Boot.isClass(v) || lua.Boot.isEnum(v) ) + return TObject; + return TFunction; + case "nil": + return TNull; + default: + return TUnknown; + } + } + + public static function enumEq( a : T, b : T ) : Bool untyped { + if( a == b ) + return true; + try { + if( a[0] != b[0] ) + return false; + for( i in 2...a.length ) + if( !enumEq(a[i],b[i]) ) + return false; + var e = a.__enum__; + if( e != b.__enum__ || e == null ) + return false; + } catch( e : Dynamic ) { + return false; + } + return true; + } + + public inline static function enumConstructor( e : EnumValue ) : String { + return untyped e[0]; + } + + public inline static function enumParameters( e : EnumValue ) : Array { + return untyped e.slice(2); + } + + public inline static function enumIndex( e : EnumValue ) : Int { + return untyped e[1]; + } + + public static function allEnums( e : Enum ) : Array { + return untyped e.__empty_constructs__; + } + +} + diff --git a/std/lua/_std/haxe/Json.hx b/std/lua/_std/haxe/Json.hx new file mode 100644 index 00000000..c8e994d6 --- /dev/null +++ b/std/lua/_std/haxe/Json.hx @@ -0,0 +1,35 @@ +/* + * Copyright (C)2005-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 haxe; + +@:coreApi +class Json { + + public static function parse( text : String ) : Dynamic { + return haxe.format.JsonParser.parse(text); + } + + public static function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String ) : String { + return haxe.format.JsonPrinter.print(value, replacer, space); + } + +} diff --git a/std/lua/_std/haxe/Utf8.hx b/std/lua/_std/haxe/Utf8.hx new file mode 100644 index 00000000..fd2c6ebd --- /dev/null +++ b/std/lua/_std/haxe/Utf8.hx @@ -0,0 +1,250 @@ +/* + * Copyright (C)2005-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 haxe; + +import lua.NativeStringTools; + +class Utf8 { + + var __b : String; + + public function new( ?size : Int ) { + __b = ""; + } + + public inline function addChar( c : Int ) : Void { + __b += char(c); + } + + public inline function toString() : String { + return __b; + } + + static inline function decodeChar( s : String, pos : Int, code : Int, width : Int ) { + return + if (width == 1) + code; + else if (width == 2) + ((code & 0x3F) << 6) | + (s.charCodeAt(pos+1) & 0x7F); + else if (width == 3) + ((code & 0x1F) << 12) | + ((s.charCodeAt(pos+1) & 0x7F) << 6) | + (s.charCodeAt(pos+2) & 0x7F); + else + ((code & 0x0F) << 18) | + ((s.charCodeAt(pos+1) & 0x7F) << 12) | + ((s.charCodeAt(pos+2) & 0x7F) << 6) | + (s.charCodeAt(pos+3) & 0x7F); + } + + public static function iter( s : String, chars : Int -> Void ) { + var cur = 0; + while (cur < s.length){ + var code = s.charCodeAt(cur); + var width = charWidth(code); + chars( decodeChar( s, cur, code, width ) ); + cur += width; + } + } + + public static function encode( s : String ) : String { + // ported from : http://phpjs.org/functions/utf8_encode/ + if (s == null ) { + return ''; + } + var string = (s + ''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n"); + var utftext = ''; + var start = 0; + var end = 0; + var n = 0; + while (n < s.length) { + var c1 = string.charCodeAt(n); + var enc = null; + + if (c1 < 128) { + end++; + } else if (c1 > 127 && c1 < 2048) { + enc = String.fromCharCode( (c1 >> 6) | 192) + + String.fromCharCode( (c1 & 63) | 128); + } else if ((c1 & 0xF800) != 0xD800) { + enc = String.fromCharCode( (c1 >> 12) | 224) + + String.fromCharCode( ((c1 >> 6) & 63) | 128) + + String.fromCharCode( (c1 & 63) | 128); + } else { // surrogate pairs + if ((c1 & 0xFC00) != 0xD800) { + throw 'Unmatched trail surrogate at ' + n; + } + var c2 = string.charCodeAt(++n); + if ((c2 & 0xFC00) != 0xDC00) { + throw 'Unmatched lead surrogate at ' + (n - 1); + } + c1 = ((c1 & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000; + enc = String.fromCharCode( (c1 >> 18) | 240) + + String.fromCharCode( ((c1 >> 12) & 63) | 128) + + String.fromCharCode(((c1 >> 6) & 63) | 128) + + String.fromCharCode((c1 & 63) | 128); + } + if (enc != null) { + if (end > start) { + utftext += string.substring(start, end); + } + utftext += enc; + start = end = n + 1; + } + n++; + } + + if (end > start) { + utftext += string.substring(start, s.length); + } + + return utftext; + + } + + public static function decode( s : String ) : String { + var ret = new StringBuf(); + iter(s, function(c){ + if( c == 8364 ) // euro symbol + c = 164; + else if( c > 255 ){ + // throw new RangeError('Utf8 decode invalid character ($c)'); + throw 'Utf8::decode invalid character ($c)'; + } + + if (c != 0xFEFF) // BOM + ret.add(String.fromCharCode(c)); + }); + return ret.toString(); + } + + public static inline function charCodeAt( s : String, index : Int ) : Int { + var cur_idx = 0; + var pos = 0; + for (i in 0...index){ + pos += charWidth(s.charCodeAt(pos)); + } + var ret = 0; + var code = s.charCodeAt(pos); + var bytes = charWidth(code); + return decodeChar( s, pos, code, bytes ); + } + + public static function validate( s : String ) : Bool { + if (s == null) return false; + var cur = 0; + while (cur < s.length){ + var c1 = s.charCodeAt(cur++); + if (c1 < 0x80) continue; + if (c1 < 0xC0) return false; + if (s.length <= cur) return false; + var c2 = s.charCodeAt(cur++); + if (c1 < 0xE0) { + if ((c1 & 0x1E != 0) && (c2 & 0xC0 == 0x80)) continue; + return false; + } + if (s.length <= cur) return false; + var c3 = s.charCodeAt(cur++); + if (c1 < 0xF0) { + if (((c1 & 0x0F != 0) || (c2 & 0x20 != 0)) && (c2 & 0xC0 == 0x80) && (c3 & 0xC0 == 0x80) + && !(c1 == 0xED && 0xA0 <= c2 && c2 <= 0xBF)) + continue; + return false; + } + if (s.length <= cur) return false; + var c4 = s.charCodeAt(cur++); + if (c1 < 0xF8) { + if (((c1 & 0x07 != 0) || (c2 & 0x30 != 0)) && (c2 & 0xC0 == 0x80) && (c3 & 0xC0 == 0x80) && (c4 & 0xC0 == 0x80) + && !((c1 == 0xF4 && c2 > 0x8F) || c1 > 0xF4)) + continue; + return false; + } + return false; + } + return true; + } + + public static inline function length( s : String ) : Int { + var pos = 0; + var len = 0; + while (pos < s.length){ + pos += charWidth(s.charCodeAt(pos)); + len++; + } + return len; + } + + public static function compare( a : String, b : String ) : Int { + return a > b ? 1 : (a == b ? 0 : -1); + } + + public static inline function sub( s : String, pos : Int, len : Int ) : String { + var startpos = 0; + var ret = new StringBuf(); + for (i in 0...pos){ + startpos += charWidth(s.charCodeAt(startpos)); + } + var endpos = startpos; + for (i in 0...len){ + endpos += charWidth(s.charCodeAt(endpos)); + } + return s.substring(startpos, endpos); + } + + static function charWidth(c:Int) : Int { + return if (c > 0 && c <= 127) 1; + else if (c >= 194 && c <= 223) 2; + else if (c >= 224 && c <= 239) 3; + else if (c >= 240 && c <= 244) 4; + else null; + } + + public static function char( unicode : Int ) : String { + if (unicode <= 0x7F) { + return String.fromCharCode(unicode); + } else if (unicode <= 0x7FF) { + var b0 = 0xC0 + Math.floor(unicode / 0x40); + var b1 = 0x80 + (unicode % 0x40); + return NativeStringTools.char(b0, b1); + } else if (unicode <= 0xFFFF) { + var b0 = 0xE0 + Math.floor(unicode / 0x1000); + var b1 = 0x80 + (Math.floor(unicode / 0x40) % 0x40); + var b2 = 0x80 + (unicode % 0x40); + return NativeStringTools.char(b0, b1, b2); + } else if (unicode <= 0x10FFFF) { + var code = unicode; + var b3 = 0x80 + (code % 0x40); + code = Math.floor(code / 0x40); + var b2 = 0x80 + (code % 0x40); + code = Math.floor(code / 0x40); + var b1 = 0x80 + (code % 0x40); + code = Math.floor(code / 0x40); + var b0 = 0xF0 + code; + + return NativeStringTools.char(b0, b1, b2, b3); + } else { + throw 'Unicode greater than U+10FFFF'; + } + } +} + diff --git a/std/lua/_std/haxe/ds/IntMap.hx b/std/lua/_std/haxe/ds/IntMap.hx new file mode 100644 index 00000000..38d5769b --- /dev/null +++ b/std/lua/_std/haxe/ds/IntMap.hx @@ -0,0 +1,86 @@ +/* + * Copyright (C)2005-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 haxe.ds; +import lua.Lua; + +class IntMap implements haxe.Constraints.IMap { + + private var h : Dynamic; + + public inline function new() : Void { + h = {}; + } + + public inline function set( key : Int, value : T ) : Void { + h[key] = value; + } + + public inline function get( key : Int ) : Null { + return h[key]; + } + + public inline function exists( key : Int ) : Bool { + return Reflect.hasField(h,cast key); + } + + public function remove( key : Int ) : Bool { + if (!Reflect.hasField(h,cast key)) return false; + Reflect.deleteField(h, cast key); + return true; + } + + public function keys() : Iterator { + var cur = Reflect.fields(h).iterator(); + return { + next : function() { + var ret = cur.next(); + return cast ret; + }, + hasNext : function() return cur.hasNext() + } + } + + public function iterator() : Iterator { + var it = keys(); + return untyped { + hasNext : function() return it.hasNext(), + next : function() return h[it.next()] + }; + } + + public function toString() : String { + var s = new StringBuf(); + s.add("{"); + var it = keys(); + for( i in it ) { + s.add(i); + s.add(" => "); + s.add(Std.string(get(i))); + if( it.hasNext() ) + s.add(", "); + } + s.add("}"); + return s.toString(); + } + +} + diff --git a/std/lua/_std/haxe/ds/ObjectMap.hx b/std/lua/_std/haxe/ds/ObjectMap.hx new file mode 100644 index 00000000..79019d5b --- /dev/null +++ b/std/lua/_std/haxe/ds/ObjectMap.hx @@ -0,0 +1,99 @@ +/* + * Copyright (C)2005-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 haxe.ds; +class ObjectMap implements haxe.Constraints.IMap { + + static var count = 0; + + static inline function assignId(obj: { } ):Int { + return untyped obj.__id__ = ++count; + } + + static inline function getId(obj: { } ):Int { + return untyped obj.__id__; + } + + var h : Dynamic; + var k : Dynamic; + + public inline function new() : Void { + h = lua.Table.create(); + k = lua.Table.create(); + } + + public inline function set( key : A, value : B ) : Void untyped { + h[key] = value; + k[key] = true; + } + + public inline function get( key : A ) : Null untyped { + return h[key]; + } + + public inline function exists( key : A ) : Bool untyped { + return k[key] != null; + } + + public function remove( key : A ) : Bool untyped { + if ( k[key] == null) return false; + k[key] = null; + h[key] = null; + return true; + } + + public function keys() : Iterator untyped { + var cur = next(h,null); + return { + next : function() { + var ret = cur; + cur = untyped next(k, cur); + return ret; + }, + hasNext : function() return cur != null + } + } + + public function iterator() : Iterator { + var itr = keys(); + return untyped { + hasNext : itr.hasNext, + next : function() return h[itr.next()] + }; + } + + public function toString() : String { + var s = new StringBuf(); + s.add("{"); + var it = keys(); + for( i in it ) { + s.add(i); + s.add(" => "); + s.add(Std.string(get(i))); + if( it.hasNext() ) + s.add(", "); + } + s.add("}"); + return s.toString(); + } + +} + diff --git a/std/lua/_std/haxe/ds/StringMap.hx b/std/lua/_std/haxe/ds/StringMap.hx new file mode 100644 index 00000000..f3478aa0 --- /dev/null +++ b/std/lua/_std/haxe/ds/StringMap.hx @@ -0,0 +1,95 @@ +/* + * Copyright (C)2005-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 haxe.ds; +import lua.Lua; + +class StringMap implements haxe.Constraints.IMap { + + private var k : Dynamic; // Is item exists + private var v : Dynamic; // Values table + + public inline function new() : Void { + // these need to be plain anonymous tables, + // so that we can set arbitrary string values. + v = untyped __lua__("{}"); + k = untyped __lua__("{}"); + } + + public inline function set( key : String, value : T ) : Void untyped { + untyped __lua__("{0}[{1}] = {2}", v, key, value); + untyped __lua__("{0}[{1}] = true", k, key); + } + + public inline function get( key : String ) : Null untyped { + return untyped __lua__("{0}[{1}]", v, key); + } + + public inline function exists( key : String ) : Bool untyped { + return untyped __lua__("({0}[{1}] or false)", k, key); + } + + public function remove( key : String ) : Bool untyped { + if (untyped __lua__("not {0}[{1}]", k, key)) return false; + untyped __lua__("{0}[{1}] = nil", v, key); + untyped __lua__("{0}[{1}] = nil", k, key); + return true; + } + + public function keys() : Iterator { + var cur : Array = []; + untyped __lua__("for _k,_v in pairs({1}) do + if(_v)then {0}:push(_k) end + end", cur, k); + return { + next : function() { + var ret = cur.pop(); + return ret; + }, + hasNext : function() return cur.length > 0 + } + } + + public function iterator() : Iterator { + var it = keys(); + return { + hasNext : function() return it.hasNext(), + next : function() return untyped __lua__("{0}[{1}]", v, it.next()) + }; + } + + public function toString() : String { + var s = new StringBuf(); + s.add("{"); + var it = keys(); + for( i in it ) { + s.add(i); + s.add(" => "); + s.add(Std.string(get(i))); + if( it.hasNext() ) + s.add(", "); + } + s.add("}"); + return s.toString(); + } + +} + diff --git a/std/lua/_std/sys/FileSystem.hx b/std/lua/_std/sys/FileSystem.hx new file mode 100644 index 00000000..c2479b5a --- /dev/null +++ b/std/lua/_std/sys/FileSystem.hx @@ -0,0 +1,124 @@ +/* + * Copyright (C)2005-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 sys; + +import lua.Io; +import lua.Os; +import lua.Lib; +import lua.Table; +import haxe.io.Path; +typedef LFileSystem = lua.lib.luv.fs.FileSystem; + +class FileSystem { + public static function exists( path : String ) : Bool { + if (path == null) return false; + else{ + var f = Io.open(path); + if (f == null) return false; + else { + f.close(); + return true; + } + } + } + + public inline static function rename( path : String, newPath : String ) : Void { + var ret = Os.rename(path, newPath); + if (!ret.success){ + throw ret.message; + } + } + + public inline static function stat( path : String ) : FileStat { + var ls = LFileSystem.stat(path); + if (ls.result == null) throw ls.message; + var l = ls.result; + return { + gid : l.gid, + uid : l.uid, + rdev : l.rdev, + size : l.size, + nlink : l.nlink, + mtime : Date.fromTime(l.mtime.sec + l.mtime.nsec/1000000), + mode : l.mode, + ino : l.ino, + dev : l.dev, + ctime : Date.fromTime(l.ctime.sec + l.ctime.nsec/1000000), + atime : Date.fromTime(l.atime.sec + l.atime.nsec/1000000) + }; + } + + public inline static function fullPath( relPath : String ) : String { + return Path.normalize(absolutePath(relPath)); + } + + public inline static function absolutePath( relPath : String ) : String { + var pwd = lua.lib.luv.Misc.cwd(); + if (pwd == null) return relPath; + return Path.join([pwd, relPath]); + } + + public inline static function deleteFile( path : String ) : Void { + var ret = lua.Os.remove(path); + if (!ret.success){ + throw ret.message; + } + } + + public inline static function readDirectory( path : String ) : Array { + var scandir = LFileSystem.scandir(path); + + var itr = function() { + var next = LFileSystem.scandir_next(scandir).name; + return next; + } + return lua.Lib.fillArray(itr); + } + + public inline static function isDirectory( path : String ) : Bool { + var result = LFileSystem.stat(path).result; + if (result == null) return false; + else return result.type == "directory"; + } + + public inline static function deleteDirectory( path : String ) : Void { + var ret = LFileSystem.rmdir(path); + if (ret.result == null){ + throw ret.message; + } + } + + public inline static function createDirectory( path : String ) : Void { + + var path = haxe.io.Path.addTrailingSlash(path); + var _p = null; + var parts = []; + while (path != (_p = haxe.io.Path.directory(path))) { + parts.unshift(path); + path = _p; + } + for (part in parts) { + if (part.charCodeAt(part.length - 1) != ":".code && !exists(part) && !LFileSystem.mkdir( part, 511 ).result) + throw "Could not create directory:" + part; + } + } +} diff --git a/std/lua/_std/sys/io/File.hx b/std/lua/_std/sys/io/File.hx new file mode 100644 index 00000000..07928096 --- /dev/null +++ b/std/lua/_std/sys/io/File.hx @@ -0,0 +1,76 @@ +/* + * Copyright (C)2005-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 sys.io; +import lua.Lua; +import lua.Io; +import lua.Os; +import lua.FileHandle; +import lua.Boot; + +@:coreApi +class File { + public static function getContent( path : String ) : String { + var f = Io.open(path, "r"); + var s = f.read("*all"); + f.close(); + return s; + } + + public static function append( path : String, binary : Bool = true ) : FileOutput { + return new FileOutput(Io.open(path, "a")); + + } + + public static function copy( srcPath : String, dstPath : String ) : Void { + switch (Sys.systemName()) { + case "Windows" : Os.execute('copy ${StringTools.quoteWinArg(srcPath, true)} ${StringTools.quoteWinArg(dstPath,true)}'); + default : Os.execute('copy ${StringTools.quoteUnixArg(srcPath)} ${StringTools.quoteUnixArg(dstPath)}'); + }; + } + + public static function getBytes( path : String ) : haxe.io.Bytes { + var finput = read(path, true); + var res = finput.readAll(); + finput.close(); + return res; + } + + public static function read( path : String, binary : Bool = true ) : FileInput { + return new FileInput(Io.open(path, binary ? 'rb' : 'r')); + } + + public static function write( path : String, binary : Bool = true ) : FileOutput { + return new FileOutput(Io.open(path, binary ? 'wb' : 'w')); + } + + public static function saveBytes( path : String, bytes : haxe.io.Bytes ) : Void { + var f = write(path, true); + f.writeBytes(bytes, 0, bytes.length); + f.close(); + } + + public static function saveContent( path : String, content : String ) : Void { + var f = write(path, false); + f.writeString(content); + f.close(); + } +} diff --git a/std/lua/_std/sys/io/FileInput.hx b/std/lua/_std/sys/io/FileInput.hx new file mode 100644 index 00000000..ab9b704c --- /dev/null +++ b/std/lua/_std/sys/io/FileInput.hx @@ -0,0 +1,89 @@ +/* + * Copyright (C)2005-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 sys.io; + +import lua.FileHandle; +import lua.Io; +import lua.NativeStringTools; +import lua.Boot; +import lua.Os; +import haxe.io.Bytes; +import haxe.io.Error; +import haxe.io.Eof; + +class FileInput extends haxe.io.Input { + var f:FileHandle; + var _eof:Bool; + + public function new(f:FileHandle){ + this.bigEndian = Boot.platformBigEndian; + this.f = f; + this._eof = false; + } + + inline public function seek( p : Int, pos : FileSeek ) : Void { + var arg = switch(pos){ + case SeekBegin : "set"; + case SeekCur : "cur"; + case SeekEnd : "end"; + } + _eof = false; + return f.seek(arg, p); + } + + inline public function tell() : Int { + return f.seek(); + } + + inline public function eof() : Bool { + return _eof; + } + + override inline public function readByte() : Int { + var byte = f.read(1); + if (byte == null) { + _eof = true; + throw new haxe.io.Eof(); + } + return NativeStringTools.byte(byte); + } + + override inline public function close() : Void { + f.close(); + } + override public function readAll( ?bufsize : Int ) : Bytes { + if( bufsize == null ) + bufsize = (1 << 14); // 16 Ko + var buf = Bytes.alloc(bufsize); + var total = new haxe.io.BytesBuffer(); + try { + while( true ) { + var len = readBytes(buf,0,bufsize); + if (len == 0) break; + total.addBytes(buf,0,len); + } + } catch( e : Eof ) _eof = true; + return total.getBytes(); + } + + +} diff --git a/std/lua/_std/sys/io/FileOutput.hx b/std/lua/_std/sys/io/FileOutput.hx new file mode 100644 index 00000000..d6edad60 --- /dev/null +++ b/std/lua/_std/sys/io/FileOutput.hx @@ -0,0 +1,54 @@ +/* + * Copyright (C)2005-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 sys.io; + +import lua.FileHandle; + +class FileOutput extends haxe.io.Output { + var f:FileHandle; + + public function new(f:FileHandle){ + this.f = f; + } + + public inline function seek( p : Int, pos : FileSeek ) : Void { + var arg = switch(pos){ + case SeekBegin : "set"; + case SeekCur : "cur"; + case SeekEnd : "end"; + } + return f.seek(arg, p); + } + + public inline function tell() : Int { + return f.seek(); + } + + override inline public function writeByte(c : Int) : Void { + f.write(String.fromCharCode(c)); + } + + override public function close() { + f.close(); + } + +} diff --git a/std/lua/_std/sys/io/Process.hx b/std/lua/_std/sys/io/Process.hx new file mode 100644 index 00000000..6800ba56 --- /dev/null +++ b/std/lua/_std/sys/io/Process.hx @@ -0,0 +1,186 @@ +/* + * Copyright (C)2005-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 sys.io; +import lua.Io; +import lua.lib.luv.Pipe; +import lua.lib.luv.Signal; +import lua.lib.luv.Loop; +import lua.Boot; +import lua.Table; + +import haxe.io.Bytes; +import haxe.io.Error; +import haxe.io.Eof; + +@:coreApi +class Process { + var _pid : Int; + var _handle : lua.lib.luv.Process; + var _code : Int; + var closef : Int->Signal->Void; + + public var stdout(default,null) : haxe.io.Input; + public var stderr(default,null) : haxe.io.Input; + public var stdin(default,null) : haxe.io.Output; + + static var argQuote = Sys.systemName() == "Windows" ? function(x) return StringTools.quoteWinArg(x,true) : StringTools.quoteUnixArg; + static var _shell = Sys.systemName() == "Window" ? 'cmd.exe' : '/bin/bash'; + + /** + Sets the args for the shell, which will include the cmd to be executed + by the shell. + **/ + static function setArgs(cmd : String, ?args : Array) : Table{ + var pargs = lua.Table.create(); + var idx = 1; + if (sys.FileSystem.exists(cmd)) cmd = '"$cmd"'; // escape simple paths + var all = [cmd]; + if (args != null) { + for (a in args){ + all.push(argQuote(a)); + } + } + + if (Sys.systemName() == "Windows") { + pargs[idx++] = '/s'; + pargs[idx++] = '/c'; + pargs[idx++] = all.join(" "); + } else { + pargs[idx++] = "-c"; + pargs[idx++] = all.join(" "); + } + return pargs; + } + + + public function new( cmd : String, ?args : Array){ + var _stdout = new Pipe(false); + var _stderr = new Pipe(false); + var _stdin = new Pipe(false); + stdout = new ProcessInput(_stdout); + stderr = new ProcessInput(_stderr); + stdin = new ProcessOutput(_stdin); + var stdio = untyped __lua_table__([_stdin,_stdout,_stderr]); + + var opt = { args: setArgs(cmd, args), stdio : stdio }; + + var p : lua.lib.luv.Process.LuvSpawn; + p = lua.lib.luv.Process.spawn( _shell, opt, function(code : Int, signal : Signal){ + _code = code; + }); + + if (p.handle == null) throw p.pid; + _pid = p.pid; + _handle = p.handle; + } + + + public function getPid() : Int { + return _pid; + } + + public function close() : Void { + stdout.close(); + stdin.close(); + stderr.close(); + _handle.close(); + } + + public function exitCode( block : Bool = true ) : Null { + if (!block) return _code; + while (_handle.is_active()) { + Loop.run(); // process io until the handle closes (emulate blocking) + } + return _code; + } + + public function kill() : Void { + _handle.kill("sigterm"); + } +} + +class ProcessInput extends haxe.io.Input { + var b : Pipe; + var buf : String; + var idx : Int; + + public function new(pipe:Pipe) { + b = pipe; + } + + override public function readByte() { + var err_str = null; + if (buf == null || idx >= buf.length){ + buf = null; + idx = 0; + var pending = true; + b.read_start(function(err, chunk){ + if (chunk != null) buf = chunk; + if (err != null) err_str = err; + pending = false; + }); + // process io until we read our input (emulate blocking) + while (pending) Loop.run(); + } + if (buf == null) throw new haxe.io.Eof(); + if (err_str != null) throw err_str; + var code : Int = cast buf.charCodeAt(idx++); + return code; + } + + override public function readAll( ?bufsize : Int ) : Bytes { + if( bufsize == null ) bufsize = (1 << 14); // 16 Ko + + var buf = Bytes.alloc(bufsize); + var total = new haxe.io.BytesBuffer(); + try { + while( true ) { + var len = readBytes(buf,0,bufsize); + // don't throw blocked error here + if (len != 0) + total.addBytes(buf,0,len); + if (len < bufsize) break; + } + } catch( e : Eof ) {} + return total.getBytes(); + } + +} + +class ProcessOutput extends haxe.io.Output { + var b : Pipe; + + public function new(pipe:Pipe) { + b = pipe; + set_bigEndian(Boot.platformBigEndian); + } + + override public function writeByte(c : Int ) : Void { + b.write(String.fromCharCode(c)); + } + + override public function close(){ + b.close(); + } +} + diff --git a/std/lua/lib/environ/Environ.hx b/std/lua/lib/environ/Environ.hx new file mode 100644 index 00000000..769287f6 --- /dev/null +++ b/std/lua/lib/environ/Environ.hx @@ -0,0 +1,30 @@ +/* + * Copyright (C)2005-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 lua.lib.environ; +@:luaRequire("environ.process") +extern class Environ { + static function getenv(arg : String) : String; + static function setenv(arg : String, value : String) : Bool; + static var ENV : Table; +} + diff --git a/std/lua/lib/lrexlib/Rex.hx b/std/lua/lib/lrexlib/Rex.hx new file mode 100644 index 00000000..ab8c1da9 --- /dev/null +++ b/std/lua/lib/lrexlib/Rex.hx @@ -0,0 +1,89 @@ +/* + * Copyright (C)2005-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 lua.lib.lrexlib; +@:luaRequire("rex_pcre") +extern class Rex { + + @:overload( function (expr : String, flag : Int) : Rex{}) + inline public static function create(expr : String, flag : String) : Rex{ + return untyped Rex['new'](expr, flag); + } + + /** + The function searches for the first match of the regexp `patt` in the + string `subj`, starting from offset `init`, subject to flags `cf` and `ef`. + + @return matched string, or array of strings. + **/ + public static function match(patt : String, ?init : Int, ?ef : Int) : Dynamic; + + /** + The function searches for the first match of the regexp patt in the string + `subj`, starting from offset `init`, subject to flags `cf` and `ef`. + **/ + public static function find(subj : String, ?init : Int, ?ef : Int) : Dynamic; + + + /** + The function is intended for use in the generic for Lua construct. It is + used for splitting a subject string `subj` into parts (sections). The `sep` + parameter is a regular expression pattern representing separators between + the sections. + **/ + @:overload( function (subj : String, sep : Rex, ?cf : Int, ?ef : Int) : Void->String{}) + public static function split(subj : String, sep : String, ?cf : Int, ?ef : Int) : Void->String; + + + /** + This function counts matches of the pattern `patt` in the string `subj`. + **/ + public static function count(subj : String, patt : String, cf : Int, ef : Int) : Dynamic; + public static function flags(?tb:Dynamic) : Dynamic; + + /** + The function searches for the first match of the regexp in the string + `subj`, starting from offset `init`, subject to execution flags `ef`. + **/ + public function tfind(subj : String, ?init : Int, ?ef : Int) : Dynamic; + + /** + This function searches for the first match of the regexp in the string + `subj`, starting from offset `init`, subject to execution flags `ef`. + **/ + public function exec(subj : String, ?init : Int, ?ef : Int) : Dynamic; + + /** + The function is intended for use in the generic for Lua construct. It + returns an iterator for repeated matching of the pattern patt in the + string `subj`, subject to flags `cf` and `ef`. + **/ + public static function gmatch(subj : String, patt : String, ?cf : Int, ?ef : Int) : Void->String; + + /** + This function searches for all matches of the pattern `patt` in the string + `subj` and replaces them according to the parameters `repl` and `n`. + **/ + @:overload( function (subj : String, patt : Rex, repl: Dynamic, ?n: Int, ?cf : Int, ?ef : Int) : String {}) + public static function gsub(subj : String, patt : String, repl: Dynamic, ?n: Int, ?cf : Int, ?ef : Int) : String; +} + diff --git a/std/js/html/DOMFormData.hx b/std/lua/lib/luasocket/Socket.hx similarity index 84% rename from std/js/html/DOMFormData.hx rename to std/lua/lib/luasocket/Socket.hx index 6e6a8c6d..c786bf70 100644 --- a/std/js/html/DOMFormData.hx +++ b/std/lua/lib/luasocket/Socket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,8 +20,8 @@ * DEALINGS IN THE SOFTWARE. */ -package js.html; - -/** @deprecated Use FormData instead. */ -@:deprecated("DOMFormData is deprecated, use FormData instead") -typedef DOMFormData = FormData; +package lua.lib.luasocket; +@:luaRequire("socket") +extern class Socket { + public static function gettime() : Float; // TODO : find a smaller lib for this? +} diff --git a/std/lua/lib/luv/Async.hx b/std/lua/lib/luv/Async.hx new file mode 100644 index 00000000..68b19559 --- /dev/null +++ b/std/lua/lib/luv/Async.hx @@ -0,0 +1,30 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + +@:luaRequire("luv") +extern class Async extends Handle { + static function new_async() : Async; + @:native("new_async") function new() : Void; + function send() : Int; +} diff --git a/std/lua/lib/luv/Check.hx b/std/lua/lib/luv/Check.hx new file mode 100644 index 00000000..2f66a76e --- /dev/null +++ b/std/lua/lib/luv/Check.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; +@:luaRequire("luv") +extern class Check extends Handle { + static function new_check() : Check; + @:native("new_check") function new() : Void; + + function start(handle : Handle) : Int; + function stop() : Int; +} diff --git a/std/lua/lib/luv/Handle.hx b/std/lua/lib/luv/Handle.hx new file mode 100644 index 00000000..035a9b0e --- /dev/null +++ b/std/lua/lib/luv/Handle.hx @@ -0,0 +1,36 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + +@:luaRequire("luv") +extern class Handle { + function is_active() : Bool; + function is_closing() : Bool; + function close() : Void; + function ref() : Void; + function unref() : Void; + function has_ref() : Bool; + function send_buffer_size(size : Int) : Int; + function recv_buffer_size(size : Int) : Int; + function fileno() : Int; +} diff --git a/std/lua/lib/luv/Idle.hx b/std/lua/lib/luv/Idle.hx new file mode 100644 index 00000000..abbe60b2 --- /dev/null +++ b/std/lua/lib/luv/Idle.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + +@:luaRequire("luv") +extern class Idle extends Handle { + static function new_idle() : Idle; + @:native("new_idle") function new() : Void; + function start(cb : Void->Void) : Int; + function stop(cb : Void->Void) : Int; +} diff --git a/std/lua/lib/luv/Loop.hx b/std/lua/lib/luv/Loop.hx new file mode 100644 index 00000000..e93858c4 --- /dev/null +++ b/std/lua/lib/luv/Loop.hx @@ -0,0 +1,14 @@ +package lua.lib.luv; + +@:luaRequire("luv") +extern class Loop { + static function loop_close() : Bool; + static function run(?mode : String) : Bool; + static function loop_alive() : Bool; + static function stop() : Void; + static function backend_fd() : Int; + static function backend_timeout() : Int; + static function now() : Int; + static function update_time() : Void; + static function walk(cb : Handle->Void) : Void; +} diff --git a/std/lua/lib/luv/Misc.hx b/std/lua/lib/luv/Misc.hx new file mode 100644 index 00000000..9bf93d08 --- /dev/null +++ b/std/lua/lib/luv/Misc.hx @@ -0,0 +1,102 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + +@:luaRequire("luv") +extern class Misc { + public static function chdir(path : String) : Bool; + + public static function os_homedir() : String; + public static function os_tmpdir() : String; + public static function os_get_passwd() : String; + public static function cpu_info() : Table; + + public static function cwd() : String; + public static function exepath() : String; + public static function get_process_title() : String; + public static function get_total_memory() : Int; + public static function get_free_memory() : Int; + public static function getpid() : Int; + + // TODO Windows only? + public static function getuid() : Int; + public static function setuid(from : Int, to : Int) : String; + public static function getgid() : Int; + public static function setgid(from : Int, to : Int) : Void; + + public static function getrusage() : ResourceUsage; + public static function guess_handle(handle : Int) : String; + public static function hrtime() : Float; + + // TODO: implement this + // public static function interface_addresses() : String; + + public static function loadavg() : Float; + public static function resident_set_memory() : Int; + public static function set_process_title(title : String) : Bool; + public static function uptime() : Int; + public static function version() : Int; + public static function version_string() : String; + + // TODO : Windows only + public static function print_all_handles() : Table; + public static function print_active_handles() : Table; + +} + +typedef CpuInfo = { + model : String, + times : CpuTimes, + speed : Int +} + +typedef CpuTimes = { + sys : Int, + idle : Int, + irq : Int, + user : Int +} + +typedef ResourceUsage = { + nivcsw : Int, + maxrss : Int, + msgrcv : Int, + isrss : Int, + inblock : Int, + ixrss : Int, + nvcsw : Int, + nsignals : Int, + minflt : Int, + nswap : Int, + msgsnd : Int, + oublock : Int, + majflt : Int, + stime : MicroTimeStamp, + idrss : Int, + utime : MicroTimeStamp +} + +typedef MicroTimeStamp = { + usec : Int, + sec : Int +} diff --git a/std/lua/lib/luv/Pipe.hx b/std/lua/lib/luv/Pipe.hx new file mode 100644 index 00000000..e20d4a58 --- /dev/null +++ b/std/lua/lib/luv/Pipe.hx @@ -0,0 +1,38 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; +import haxe.extern.EitherType; + +@:luaRequire("luv") +extern class Pipe extends Stream { + static function new_pipe(ipc : Bool) : Pipe; + @:native("new_pipe") function new(ipc : Bool) : Void; + + function open(file : EitherType) : Pipe; + function bind(name : String) : Pipe; + function connect(name : String, cb: String->Bool->Void) : Int; + function getsockname() : String; + function pending_instances(count : Int) : Int; + function pending_count() : Int; + function pending_type() : Int; +} diff --git a/std/lua/lib/luv/Poll.hx b/std/lua/lib/luv/Poll.hx new file mode 100644 index 00000000..ae911699 --- /dev/null +++ b/std/lua/lib/luv/Poll.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + +@:luaRequire("luv") +extern class Poll extends Handle { + static function new_poll() : Async; + @:native("new_poll") function new() : Void; + + function start(?type : Int, ?cb : Void->Void ) : Int; + function stop() : Int; +} diff --git a/std/lua/lib/luv/Prepare.hx b/std/lua/lib/luv/Prepare.hx new file mode 100644 index 00000000..1a74ca2a --- /dev/null +++ b/std/lua/lib/luv/Prepare.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + +@:luaRequire("luv") +extern class Prepare extends Handle { + static function new_prepare() : Prepare; + @:native("new_prepare") function new() : Void; + + function start() : Int; + function stop() : Int; +} diff --git a/std/lua/lib/luv/Process.hx b/std/lua/lib/luv/Process.hx new file mode 100644 index 00000000..17f0f092 --- /dev/null +++ b/std/lua/lib/luv/Process.hx @@ -0,0 +1,40 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + +@:luaRequire("luv") +extern class Process extends Handle { + static function disable_stdio_inheritance() : Void; + static function spawn(path : String, options : Dynamic, cb : Int->Signal->Void ) : LuvSpawn; + function kill(sig:String) : Int; +} + +typedef ProcessOptions = { + args : Table, + stdio : Table +} + +@:multiReturn extern class LuvSpawn { + var handle : Process; + var pid : Int; +} diff --git a/std/lua/lib/luv/Request.hx b/std/lua/lib/luv/Request.hx new file mode 100644 index 00000000..d5761341 --- /dev/null +++ b/std/lua/lib/luv/Request.hx @@ -0,0 +1,28 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + +@:luaRequire("luv") +extern class Request { + function cancel() : Bool; +} diff --git a/std/lua/lib/luv/Signal.hx b/std/lua/lib/luv/Signal.hx new file mode 100644 index 00000000..27e46c36 --- /dev/null +++ b/std/lua/lib/luv/Signal.hx @@ -0,0 +1,33 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + +@:luaRequire("luv") +extern class Signal extends Handle { + static function new_signal() : Signal; + @:native("new_signal") function new() : Void; + + function start(sigtype : haxe.extern.EitherType, ?cb : Void-> Void ) : Int; + function stop() : Int; + +} diff --git a/std/lua/lib/luv/Stream.hx b/std/lua/lib/luv/Stream.hx new file mode 100644 index 00000000..b661d381 --- /dev/null +++ b/std/lua/lib/luv/Stream.hx @@ -0,0 +1,41 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; +import lua.lib.luv.net.Tcp; + +@:luaRequire("luv") +extern class Stream extends Handle { + function shutdown(?cb : Void->Void) : Int; + function listen(backlog : Int, cb : String->String->Void) : Int; + function accept(client_stream : Stream) : Int; + function read_start(cb : String->String->Void) : Int; + function read_stop() : Int; + function write(data : StreamData, ?cb : String->Bool->Void) : Int; + function write2(data : StreamData, send_handle : Tcp, cb: String->Bool->Void) : Int; + function try_write(data : StreamData) : Int; + function is_readable() : Bool; + function is_writable() : Bool; + function set_blocking(blocking : Bool) : Int; +} + +typedef StreamData = haxe.extern.EitherType>; diff --git a/std/lua/lib/luv/Thread.hx b/std/lua/lib/luv/Thread.hx new file mode 100644 index 00000000..5a717c39 --- /dev/null +++ b/std/lua/lib/luv/Thread.hx @@ -0,0 +1,34 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + +@:luaRequire("luv") +extern class Thread { + static function new_thread() : Timer; + @:native("new_thread") function new() : Void; + + static function self() : Thread; + static function sleep(msec : Int) : Void; + function equal(t : Thread) : Bool; + function join(t : Thread) : Bool; +} diff --git a/std/lua/lib/luv/Timer.hx b/std/lua/lib/luv/Timer.hx new file mode 100644 index 00000000..f24c19e9 --- /dev/null +++ b/std/lua/lib/luv/Timer.hx @@ -0,0 +1,35 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + +@:luaRequire("luv") +extern class Timer extends Handle { + static function new_timer() : Timer; + @:native("new_timer") function new() : Void; + + function start(timeout : Int, repeat : Int, cb : Void->Void) : Int; + function stop() : Int; + function again() : Int; + function set_repeat(repeat : Int) : Void; + function get_repeat() : Int; +} diff --git a/std/lua/lib/luv/Tty.hx b/std/lua/lib/luv/Tty.hx new file mode 100644 index 00000000..5ef9cd09 --- /dev/null +++ b/std/lua/lib/luv/Tty.hx @@ -0,0 +1,41 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + + +@:luaRequire("luv") +extern class Tty extends Stream { + static function new_tty(fd : Int, readable : Bool) : Tty; + @:native("new_tty") function new(fd : Int, readable : Bool) : Void; + + static function reset_mode() : Int; + + function set_mode(mode : Int) : Int; + function get_winsize() : WidthHeight; +} + +@:multiReturn +extern class WidthHeight { + var width : Int; + var height : Int; +} diff --git a/std/lua/lib/luv/Work.hx b/std/lua/lib/luv/Work.hx new file mode 100644 index 00000000..450e746c --- /dev/null +++ b/std/lua/lib/luv/Work.hx @@ -0,0 +1,30 @@ +/* + * Copyright (C)2005-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 lua.lib.luv; + +@:luaRequire("luv") +extern class Work { + static function new_work() : Work; + @:native("new_work") function new() : Void; + static function queue_work(work : Work) : Bool; +} diff --git a/std/lua/lib/luv/fs/FileDescriptor.hx b/std/lua/lib/luv/fs/FileDescriptor.hx new file mode 100644 index 00000000..e1ad7479 --- /dev/null +++ b/std/lua/lib/luv/fs/FileDescriptor.hx @@ -0,0 +1,25 @@ +/* + * Copyright (C)2005-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 lua.lib.luv.fs; + +typedef FileDescriptor = Int; diff --git a/std/lua/lib/luv/fs/FileSystem.hx b/std/lua/lib/luv/fs/FileSystem.hx new file mode 100644 index 00000000..80daf2c2 --- /dev/null +++ b/std/lua/lib/luv/fs/FileSystem.hx @@ -0,0 +1,177 @@ +/* + * Copyright (C)2005-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 lua.lib.luv.fs; +import lua.lib.luv.fs.Open; +import lua.Result; + +@:luaRequire("luv") +extern class FileSystem { + @:native("fs_close") + @:overload(function(file : FileDescriptor, cb : String->Bool->Void) : Request {}) + static function close(file : FileDescriptor) : Result; + + @:native("fs_open") + @:overload(function(path : String, flags : Open, mode : Int, ?cb : String->FileDescriptor->Void) : Request {}) + static function open(path : String, flags : Open, mode : Int) : Result; + + @:native("fs_read") + @:overload(function(file : FileDescriptor, len : Int, offset : Int, ?cb : String->String->Void) : Request {} ) + static function read(file : FileDescriptor, len : Int, offset : Int) : Result; + + @:native("fs_unlink") + @:overload(function(file : FileDescriptor, ?cb : String->String->Void) : Request {} ) + static function unlink(file : FileDescriptor, content : String) : Result; + + @:native("fs_write") + @:overload(function(file : FileDescriptor, content : String, offset : Int, ?cb : String->Bool->Void) : Int {}) + static function write(file : FileDescriptor, content : String, offset : Int) : Result; + + @:native("fs_mkdir") + @:overload(function(path : String, mode : Int, cb : String->Bool->Void) : Request {}) + static function mkdir(path : String, mode :Int) : Result; + + @:native("fs_mkdtemp") + @:overload(function(data : String, cb : String->Bool->Void) : Request {}) + static function mkdtemp(data : String) : Result; + + @:native("fs_rmdir") + @:overload(function(path : String, cb : String->Bool->Void) : Request {}) + static function rmdir(path : String) : Result; + + @:native("fs_scandir") + @:overload(function(path : String, cb : String->Bool->Void) : Request {}) + static function scandir(path : String) : ScanDirMarker; + + @:native("fs_scandir_next") + static function scandir_next(scandir : ScanDirMarker) : ScandirNext; + + @:native("fs_stat") + @:overload(function(path : String, cb : String->Stat->Void) : Request {}) + static function stat(path : String) : Result; + + @:native("fs_fstat") + @:overload(function(descriptor : FileDescriptor, cb : String->Stat->Void) : Request {}) + static function fstat(descriptor : FileDescriptor) : Result; + + @:native("fs_lstat") + @:overload(function(path : String, cb : String->Stat->Void) : Request {}) + static function lstat(path : String) : Result; + + @:native("fs_rename") + @:overload(function(path : String, newpath : String, cb : String->Bool->Void) : Request {}) + static function rename(path : String, newpath : String) : Result; + + @:native("fs_fsync") + @:overload(function(descriptor : FileDescriptor, cb : String->Bool->Void) : Request {}) + static function fsync(descriptor : FileDescriptor) : Result; + + @:native("fs_fdatasync") + @:overload(function(descriptor : FileDescriptor, cb : String->Bool->Void) : Request {}) + static function fdatasync(descriptor : FileDescriptor) : Result; + + @:native("fs_ftruncate") + @:overload(function(descriptor : FileDescriptor, offset : Int, cb : String->Bool->Void) : Request {}) + static function ftruncate(descriptor : FileDescriptor, offset : Int) : Result; + + @:native("fs_sendfile") + @:overload(function(fin : FileDescriptor, fout : FileDescriptor, cb : String->Int->Void) : Request {}) + static function sendfile(fin : FileDescriptor, fout : FileDescriptor) : Result; + + @:native("fs_access") + @:overload(function(path : String, mode : Int, cb : String->Bool->Void) : Request {}) + static function access(path : String, mode :Int) : Result; + + @:native("fs_chmod") + @:overload(function(path : String, mode : Int, cb : String->Bool->Void) : Request {}) + static function chmod(path : String, mode :Int) : Result; + + @:native("fs_fchmod") + @:overload(function(descriptor : FileDescriptor, mode : Int, cb : String->Bool->Void) : Request {}) + static function fchmod(descriptor : FileDescriptor, mode :Int) : Result; + + @:native("fs_futime") + @:overload(function(descriptor : FileDescriptor, actime : Int, modtime : Int, cb : String->Bool->Void) : Request {}) + static function futime(descriptor : FileDescriptor, actime : Int, modtime : Int) : Result; + + @:native("fs_utime") + @:overload(function(path : String, actime : Int, modtime : Int, cb : String->Bool->Void) : Request {}) + static function utime(path : String, actime : Int, modtime : Int) : Result; + + @:native("fs_link") + @:overload(function(oldpath : String, newpath : String, cb : String->Bool->Void) : Request {}) + static function link(oldpath : String, newpath : String) : Result; + + @:native("fs_symlink") + @:overload(function(oldpath : String, newpath : String, flags : Int, cb : String->Bool->Void) : Request {}) + static function symlink(oldpath : String, newpath : String, flags : Int) : Bool; + + // @:native("fs_readlink") + // @:overload(function(path : String, cb : String->String->Void) : Request {}) + // static function readlink(path : String) : String; + + @:native("fs_realpath") + @:overload(function(path : String, cb : String->String->Void) : Request{}) + static function realpath(path : String) : String; + + @:native("fs_chown") + @:overload(function(path : String, uid : Int, gid : Int, cb : String->Bool->Void) : Request {}) + static function chown(path : String, uid : Int, gid : Int) : Bool; + + @:native("fs_fchown") + @:overload(function(descriptor : FileDescriptor, uid : Int, gid : Int, cb : String->Bool->Void) : Request {}) + static function fchown(descriptor : FileDescriptor, uid : Int, gid : Int) : Bool; +} + +extern class ScanDirMarker {} + +@:multiReturn +extern class ScandirNext { + var name : String; + var type : String; +} + +typedef Stat = { + ino : Int, + ctime : TimeStamp, + uid : Int, + dev : Int, + nlink : Int, + mode : Int, + size : Int, + birthtime : TimeStamp, + gid : Int, + type : String, + rdev : Int, + gen : Int, + blocks : Int, + mtime : TimeStamp, + atime : TimeStamp, + blksize : Int, + flags : Int +} + +typedef TimeStamp = { + sec : Int, + nsec : Int +} + diff --git a/std/lua/lib/luv/fs/FileSystemEvent.hx b/std/lua/lib/luv/fs/FileSystemEvent.hx new file mode 100644 index 00000000..8353f378 --- /dev/null +++ b/std/lua/lib/luv/fs/FileSystemEvent.hx @@ -0,0 +1,39 @@ +/* + * Copyright (C)2005-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 lua.lib.luv.fs; + +@:luaRequire("luv") +extern class FileSystemEvent { + static function new_fs_event() : FileSystemEvent; + @:native("new_fs_event") function new() : Void; + + function start(path : String, options : StartOptions, cb : String->Bool->Void) : Int; + function stop() : Int; + function getpath() : String; +} + +typedef StartOptions = { + watch_entry : Bool, + stat : Bool, + recursive : Bool +} diff --git a/std/lua/lib/luv/fs/FileSystemPoll.hx b/std/lua/lib/luv/fs/FileSystemPoll.hx new file mode 100644 index 00000000..30055718 --- /dev/null +++ b/std/lua/lib/luv/fs/FileSystemPoll.hx @@ -0,0 +1,32 @@ +/* + * Copyright (C)2005-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 lua.lib.luv.fs; +@:luaRequire("luv") +extern class FileSystemPoll { + static function new_fs_poll() : FileSystemPoll; + @:native("new_fs_poll") function new() : Void; + + function start(path : String, interval : Int, cb : String->Bool->Void) : Bool; + function stop() : Bool; + function getpath() : String; +} diff --git a/std/lua/lib/luv/fs/Open.hx b/std/lua/lib/luv/fs/Open.hx new file mode 100644 index 00000000..85de10b6 --- /dev/null +++ b/std/lua/lib/luv/fs/Open.hx @@ -0,0 +1,39 @@ +/* + * Copyright (C)2005-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 lua.lib.luv.fs; + +@:enum +abstract Open(String) { + var ReadOnly = "r"; + var ReadOnlySync = "rs"; + var ReadWrite = "r+"; + var ReadWriteSync = "rs+"; + var ReadWriteAppend = "a+"; + var ReadWriteTruncate = "w+"; + var ReadWriteTruncateNewFile = "wx+"; + var ReadWriteAppendNewFile = "ax+"; + var WriteOnly = "w"; + var WriteNewFile = "wx"; + var Append = "a"; + var AppendNewFile = "ax"; +} diff --git a/std/lua/lib/luv/net/Dns.hx b/std/lua/lib/luv/net/Dns.hx new file mode 100644 index 00000000..1523f780 --- /dev/null +++ b/std/lua/lib/luv/net/Dns.hx @@ -0,0 +1,41 @@ +/* + * Copyright (C)2005-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 lua.lib.luv.net; + +@:luaRequire("luv") +extern class Dns { + + @:overload(function(node : String, service : String, ?hints : AddrInfo, cb : String->Table->Void) : Request {}) + public static function getaddrinfo(node : String, service : String, ?hints : AddrInfo ) : Result>; + + @:overload(function(ip: String, port : Int, family : String, cb : String->AddrInfo->Void) : Request {}) + public static function getnameinfo(info:AddrInfo) : Result; +} + +typedef AddrInfo = { + ?ip : String, + ?addr : String, + ?port : Int, + ?family : String, + ?socktype : String +} diff --git a/std/lua/lib/luv/net/Tcp.hx b/std/lua/lib/luv/net/Tcp.hx new file mode 100644 index 00000000..3590f287 --- /dev/null +++ b/std/lua/lib/luv/net/Tcp.hx @@ -0,0 +1,38 @@ +/* + * Copyright (C)2005-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 lua.lib.luv.net; + +@:luaRequire("luv") +extern class Tcp extends Stream { + static function new_tcp() : Tcp; + @:native("new_tcp") function new() : Void; + function open(sock : Int) : Int; + function nodelay(enable : Bool) : Int; + function keepalive(enable : Bool, ?delay : Int) : Int; + function simultaneous_accepts(enable : Bool) : Int; + function bind(address : String, port : Int) : Int; + function getsockname() : Int; + function getpeername() : String; + function connect(host : String, port : Int, cb : String->Bool->Void) : Int; + function write_queue_size() : Int; +} diff --git a/std/lua/lib/luv/net/Udp.hx b/std/lua/lib/luv/net/Udp.hx new file mode 100644 index 00000000..e0df42ea --- /dev/null +++ b/std/lua/lib/luv/net/Udp.hx @@ -0,0 +1,43 @@ +/* + * Copyright (C)2005-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 lua.lib.luv.net; + +@:luaRequire("luv") +extern class Udp extends Handle { + static function new_udp() : Udp; + @:native("new_udp") function new() : Void; + + function open(fd : Int) : Int; + function bind(host : String, port : Int) : Int; + function getsockname() : String; + function set_membership(multicast_addr : String, interface_addr : String, membership : String) : Int; + function set_multicast_loop(on : Bool) : Int; + function set_multicast_ttl(ttl : Int ) : Int; + function set_multicast_interface(interface_addr : String) : Int; + function set_broadcast(on : Bool) : Int; + function set_ttl(ttl : Int) : Int; + function send(data : String, host : String, port : Int, cb : Bool->Void) : Int; + function try_send(data : String, host : String, port : Int) : Int; + function recv_start(cb : String->Bool->Void) : Int; + function recv_stop() : Int; +} diff --git a/std/neko/Boot.hx b/std/neko/Boot.hx index fffac84a..e51bd60c 100644 --- a/std/neko/Boot.hx +++ b/std/neko/Boot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,7 @@ */ package neko; +@:dox(hide) @:keep class Boot { diff --git a/std/neko/Lib.hx b/std/neko/Lib.hx index 52634635..d5908c5d 100644 --- a/std/neko/Lib.hx +++ b/std/neko/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,11 @@ */ package neko; +/** + Platform-specific Neko Library. Provides some platform-specific functions + for the Neko target, such as conversion from Haxe types to native types + and vice-versa. +**/ class Lib { /** @@ -69,14 +74,14 @@ class Lib { } /** - Unserialize a string using native Neko serialization. See [serialize]. + Unserialize a string using native Neko serialization. See `serialize`. **/ public static function unserialize( s : haxe.io.Bytes ) : Dynamic { return untyped __unserialize(s.getData(),__dollar__loader); } /** - Unserialize a string using native Neko serialization. See [serialize]. + Unserialize a string using native Neko serialization. See `serialize`. This function assume that all the serialized data was serialized with current module, even if the module name was different. This can happen if you are unserializing some data into mod_neko that was serialized on a different server using a different diff --git a/std/neko/NativeArray.hx b/std/neko/NativeArray.hx index 93c542aa..64b24973 100644 --- a/std/neko/NativeArray.hx +++ b/std/neko/NativeArray.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/NativeString.hx b/std/neko/NativeString.hx index 531f90c0..2e30a8cd 100644 --- a/std/neko/NativeString.hx +++ b/std/neko/NativeString.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/NativeXml.hx b/std/neko/NativeXml.hx index 2e2a3834..97c8956b 100644 --- a/std/neko/NativeXml.hx +++ b/std/neko/NativeXml.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,20 +21,19 @@ */ package neko; -enum XmlType { -} +@:enum abstract XmlType(String) {} typedef NativeXml = Xml; class Xml { - public static var Element(default,null) : XmlType; - public static var PCData(default,null) : XmlType; - public static var CData(default,null) : XmlType; - public static var Comment(default,null) : XmlType; - public static var DocType(default,null) : XmlType; - public static var ProcessingInstruction(default,null) : XmlType; - public static var Document(default,null) : XmlType; + public static var Element(default,never) : XmlType; + public static var PCData(default,never) : XmlType; + public static var CData(default,never) : XmlType; + public static var Comment(default,never) : XmlType; + public static var DocType(default,never) : XmlType; + public static var ProcessingInstruction(default,never) : XmlType; + public static var Document(default,never) : XmlType; public var nodeName(get,set) : String; diff --git a/std/neko/Random.hx b/std/neko/Random.hx index e704719f..0ae121ae 100644 --- a/std/neko/Random.hx +++ b/std/neko/Random.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,22 +21,37 @@ */ package neko; +/** + A seeded pseudo-random generator. +*/ class Random { var r : Dynamic; + /** + Create a new random with random seed. + */ public function new() { r = random_new(); } + /** + Set the generator seed. + */ public function setSeed( s : Int ) { random_set_seed(r,s); } + /** + Return a random integer modulo max. + */ public function int( max : Int ) : Int { return random_int(r,max); } + /** + Return a random float. + */ public function float() : Float { return random_float(r); } @@ -45,5 +60,4 @@ class Random { static var random_set_seed = Lib.load("std","random_set_seed",2); static var random_int = Lib.load("std","random_int",2); static var random_float = Lib.load("std","random_float",1); - } diff --git a/std/neko/Web.hx b/std/neko/Web.hx index 84f7b2fe..bac91d21 100644 --- a/std/neko/Web.hx +++ b/std/neko/Web.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -44,8 +44,8 @@ class Web { /** Returns an Array of Strings built using GET / POST values. - If you have in your URL the parameters [a[]=foo;a[]=hello;a[5]=bar;a[3]=baz] then - [neko.Web.getParamValues("a")] will return [["foo","hello",null,"baz",null,"bar"]] + If the URL contains the parameters `[a[]=foo;a[]=hello;a[5]=bar;a[3]=baz]` then + `neko.Web.getParamValues("a")` will return `["foo","hello",null,"baz",null,"bar"]` **/ public static function getParamValues( param : String ) : Array { var reg = new EReg("^"+param+"(\\[|%5B)([0-9]*?)(\\]|%5D)=(.*?)$", ""); @@ -72,7 +72,7 @@ class Web { } /** - Returns the local server host name + Returns the local server host name. **/ public static function getHostName() { return new String(_get_host_name()); @@ -138,7 +138,7 @@ class Web { } /** - Returns all the GET parameters String + Returns all the GET parameters String. **/ public static function getParamsString() { var p = _get_params_string(); @@ -147,10 +147,10 @@ class Web { /** Returns all the POST data. POST Data is always parsed as - being application/x-www-form-urlencoded and is stored into + being `application/x-www-form-urlencoded` and is stored into the getParams hashtable. POST Data is maximimized to 256K - unless the content type is multipart/form-data. In that - case, you will have to use [getMultipart] or [parseMultipart] + unless the content type is `multipart/form-data`. In that + case, you will have to use `getMultipart` or `parseMultipart` methods. **/ public static function getPostData() { @@ -162,7 +162,7 @@ class Web { /** Returns an hashtable of all Cookies sent by the client. - Modifying the hashtable will not modify the cookie, use setCookie instead. + Modifying the hashtable will not modify the cookie, use `setCookie` instead. **/ public static function getCookies():Map { var p = _get_cookies(); @@ -178,7 +178,7 @@ class Web { /** - Set a Cookie value in the HTTP headers. Same remark as setHeader. + Set a Cookie value in the HTTP headers. Same remark as `setHeader`. **/ public static function setCookie( key : String, value : String, ?expire: Date, ?domain: String, ?path: String, ?secure: Bool, ?httpOnly: Bool ) { var buf = new StringBuf(); @@ -260,9 +260,9 @@ class Web { } /** - Parse the multipart data. Call [onPart] when a new part is found + Parse the multipart data. Call `onPart` when a new part is found with the part name and the filename if present - and [onData] when some part data is readed. You can this way + and `onData` when some part data is read. You can this way directly save the data on hard drive in the case of a file upload. **/ public static function parseMultipart( onPart : String -> String -> Void, onData : haxe.io.Bytes -> Int -> Int -> Void ) : Void { @@ -281,14 +281,14 @@ class Web { } /** - Get the HTTP method used by the client. This api requires Neko 1.7.1+ + Get the HTTP method used by the client. This API requires Neko 1.7.1+. **/ public static function getMethod() : String { return new String(_get_http_method()); } /** - Write a message into the web server log file. This api requires Neko 1.7.1+ + Write a message into the web server log file. This API requires Neko 1.7.1+. **/ public static function logMessage( msg : String ) { _log_message(untyped msg.__s); diff --git a/std/neko/_std/Array.hx b/std/neko/_std/Array.hx index 4c741841..b03303f9 100644 --- a/std/neko/_std/Array.hx +++ b/std/neko/_std/Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/Date.hx b/std/neko/_std/Date.hx index b484bc05..811e608b 100644 --- a/std/neko/_std/Date.hx +++ b/std/neko/_std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/EReg.hx b/std/neko/_std/EReg.hx index 245fc56e..de5fc310 100644 --- a/std/neko/_std/EReg.hx +++ b/std/neko/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/Math.hx b/std/neko/_std/Math.hx index 59a4ca98..c6f2b7b5 100644 --- a/std/neko/_std/Math.hx +++ b/std/neko/_std/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,52 +21,26 @@ */ import neko.Lib; -@:coreApi @:final class Math { - - public static var PI(default,null) : Float; - public static var NaN(default,null) : Float; - public static var POSITIVE_INFINITY(default,null) : Float; - public static var NEGATIVE_INFINITY(default,null) : Float; - - public static function min(a:Float,b:Float) : Float { return if( a < b ) a else if( untyped $isnan(a) ) a else b; } - public static function max(a:Float,b:Float) : Float { return if( a < b ) b else if( untyped $isnan(b) ) b else a; } - - public static function abs( v : Float ) : Float return 0.; - public static function sin( v : Float ) : Float return 0.; - public static function cos( v : Float ) : Float return 0.; - public static function atan2( y : Float, x : Float ) : Float return 0.; - public static function tan( v : Float ) : Float return 0.; - public static function exp( v : Float ) : Float return 0.; - public static function log( v : Float ) : Float return 0.; - public static function sqrt( v : Float ) : Float return 0.; - public static function round( v : Float ) : Int return 0; - public static function floor( v : Float ) : Int return 0; - public static function ceil( v : Float ) : Int return 0; - public static function atan( v : Float ) : Float return 0.; - public static function asin( v : Float ) : Float return 0.; - public static function acos( v : Float ) : Float return 0.; - public static function pow( v : Float, exp : Float ) : Float return 0.; - - public static function fround( v : Float ) : Float return 0.; - public static function ffloor( v : Float ) : Float return 0.; - public static function fceil( v : Float ) : Float return 0.; - +@:native("Math") +@:keep +private class MathImpl { static var __rnd; static var _rand_float = Lib.load("std","random_float",1); static var _rand_int = Lib.load("std","random_int",2); + public static function min(a:Float,b:Float) : Float { return if( a < b ) a else if( untyped $isnan(a) ) a else b; } + public static function max(a:Float,b:Float) : Float { return if( a < b ) b else if( untyped $isnan(b) ) b else a; } public static function random() : Float { return _rand_float(__rnd); } - public static function isNaN(f:Float) : Bool { return untyped __dollar__isnan(f); } public static function isFinite(f:Float) : Bool { return !untyped (__dollar__isinfinite(f) || __dollar__isnan(f)); } static function __init__() : Void { + var M : Dynamic = MathImpl; __rnd = Lib.load("std","random_new",0)(); - PI = Lib.load("std","math_pi",0)(); - NaN = 0.0 / 0.0; - POSITIVE_INFINITY = 1.0 / 0.0; - NEGATIVE_INFINITY = -POSITIVE_INFINITY; - var M : Dynamic = Math; + M.PI = Lib.load("std","math_pi",0)(); + M.NaN = 0.0 / 0.0; + M.POSITIVE_INFINITY = 1.0 / 0.0; + M.NEGATIVE_INFINITY = -M.POSITIVE_INFINITY; M.abs = Lib.load("std","math_abs",1); M.sin = Lib.load("std","math_sin",1); M.cos = Lib.load("std","math_cos",1); @@ -86,7 +60,38 @@ import neko.Lib; M.ffloor = try Lib.load("std", "math_ffloor", 1) catch( e : Dynamic ) M.floor; M.fround = try Lib.load("std", "math_fround", 1) catch( e : Dynamic ) M.round; } - } +@:coreApi +@:final +extern class Math { + + public static var PI(default,null) : Float; + public static var NaN(default,null) : Float; + public static var POSITIVE_INFINITY(default,null) : Float; + public static var NEGATIVE_INFINITY(default,null) : Float; + public static function min(a:Float,b:Float) : Float; + public static function max(a:Float,b:Float) : Float; + public static function abs( v : Float ) : Float; + public static function sin( v : Float ) : Float; + public static function cos( v : Float ) : Float; + public static function atan2( y : Float, x : Float ) : Float; + public static function tan( v : Float ) : Float; + public static function exp( v : Float ) : Float; + public static function log( v : Float ) : Float; + public static function sqrt( v : Float ) : Float; + public static function round( v : Float ) : Int; + public static function floor( v : Float ) : Int; + public static function ceil( v : Float ) : Int; + public static function atan( v : Float ) : Float; + public static function asin( v : Float ) : Float; + public static function acos( v : Float ) : Float; + public static function pow( v : Float, exp : Float ) : Float; + public static function fround( v : Float ) : Float; + public static function ffloor( v : Float ) : Float; + public static function fceil( v : Float ) : Float; + public static function random() : Float; + public static function isNaN(f:Float) : Bool; + public static function isFinite(f:Float) : Bool; +} \ No newline at end of file diff --git a/std/neko/_std/Reflect.hx b/std/neko/_std/Reflect.hx index 499c4f8b..9febf2f0 100644 --- a/std/neko/_std/Reflect.hx +++ b/std/neko/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/Std.hx b/std/neko/_std/Std.hx index 5484dbff..27b88413 100644 --- a/std/neko/_std/Std.hx +++ b/std/neko/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/String.hx b/std/neko/_std/String.hx index 2377f265..6e849bc1 100644 --- a/std/neko/_std/String.hx +++ b/std/neko/_std/String.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -77,7 +77,6 @@ return last; last = p; } - return null; } } diff --git a/std/neko/_std/StringBuf.hx b/std/neko/_std/StringBuf.hx index 947f7215..5f594f04 100644 --- a/std/neko/_std/StringBuf.hx +++ b/std/neko/_std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/Sys.hx b/std/neko/_std/Sys.hx index 70c50b7c..0fdb3e58 100644 --- a/std/neko/_std/Sys.hx +++ b/std/neko/_std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -91,30 +91,22 @@ return new String(sys_string()); } - static function escapeArgument( arg : String, windows : Bool ) : String { - var ok = true; - for( i in 0...arg.length ) - switch( arg.charCodeAt(i) ) { - case ' '.code, '\t'.code, '"'.code, '&'.code, '|'.code, '<'.code, '>'.code, '#'.code , ';'.code, '*'.code, '?'.code, '('.code, ')'.code, '{'.code, '}'.code, '$'.code: - ok = false; - case 0, 13, 10: // [eof] [cr] [lf] - arg = arg.substr(0,i); - break; - } - if( ok ) - return arg; - return windows ? '"'+arg.split('"').join('""').split("%").join('"%"')+'"' : "'"+arg.split("'").join("'\\''")+"'"; - } - public static function command( cmd : String, ?args : Array ) : Int { - var win = systemName() == "Windows"; - cmd = escapeArgument(cmd, win); - if( args != null ) { - for( a in args ) - cmd += " "+escapeArgument(a, win); + if (args == null) { + return sys_command(untyped cmd.__s); + } else { + switch (systemName()) { + case "Windows": + cmd = [ + for (a in [StringTools.replace(cmd, "/", "\\")].concat(args)) + StringTools.quoteWinArg(a, true) + ].join(" "); + return sys_command(untyped cmd.__s); + case _: + cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" "); + return sys_command(untyped cmd.__s); + } } - if (win) cmd = '"$cmd"'; - return sys_command(untyped cmd.__s); } public static function exit( code : Int ) : Void { @@ -129,10 +121,20 @@ return sys_cpu_time(); } - public static function executablePath() : String { + @:deprecated("Use programPath instead") public static function executablePath() : String { return new String(sys_exe_path()); } + public static function programPath() : String { + #if macro + return null; + #elseif interp + return new String(sys_program_path()); + #else + return sys_program_path; + #end + } + public static function environment() : Map { var l : Array = sys_env(); var h = new haxe.ds.StringMap(); @@ -155,6 +157,28 @@ private static var sys_time = neko.Lib.load("std","sys_time",0); private static var sys_cpu_time = neko.Lib.load("std","sys_cpu_time",0); private static var sys_exe_path = neko.Lib.load("std","sys_exe_path",0); + #if interp + private static var sys_program_path = neko.Lib.load("std","sys_program_path",0); + #elseif !macro + // It has to be initialized before any call to loadModule or Sys.setCwd()... + private static var sys_program_path = { + var m = neko.vm.Module.local().name; + try { + sys.FileSystem.fullPath(m); + } catch (e:Dynamic) { + // maybe the neko module name was supplied without .n extension... + if (!StringTools.endsWith(m, ".n")) { + try { + sys.FileSystem.fullPath(m + ".n"); + } catch (e:Dynamic) { + m; + } + } else { + m; + } + } + } + #end private static var sys_env = neko.Lib.load("std","sys_env",0); private static var file_stdin = neko.Lib.load("std","file_stdin",0); diff --git a/std/neko/_std/Type.hx b/std/neko/_std/Type.hx index a03886fb..7154dc33 100644 --- a/std/neko/_std/Type.hx +++ b/std/neko/_std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + enum ValueType { TNull; TInt; @@ -68,7 +69,7 @@ enum ValueType { public static function resolveClass( name : String ) : Class untyped { var path = name.split("."); - cl = Reflect.field(untyped neko.Boot.__classes,path[0]); + var cl = Reflect.field(untyped neko.Boot.__classes,path[0]); var i = 1; while( cl != null && i < path.length ) { cl = Reflect.field(cl,path[i]); @@ -83,7 +84,7 @@ enum ValueType { public static function resolveEnum( name : String ) : Enum untyped { var path = name.split("."); - e = Reflect.field(neko.Boot.__classes,path[0]); + var e = Reflect.field(neko.Boot.__classes,path[0]); var i = 1; while( e != null && i < path.length ) { e = Reflect.field(e,path[i]); diff --git a/std/neko/_std/haxe/Utf8.hx b/std/neko/_std/haxe/Utf8.hx index df516611..0cc45b87 100644 --- a/std/neko/_std/haxe/Utf8.hx +++ b/std/neko/_std/haxe/Utf8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/haxe/ds/IntMap.hx b/std/neko/_std/haxe/ds/IntMap.hx index 24ff8549..39cec941 100644 --- a/std/neko/_std/haxe/ds/IntMap.hx +++ b/std/neko/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/haxe/ds/ObjectMap.hx b/std/neko/_std/haxe/ds/ObjectMap.hx index 95046c28..f30cd3e8 100644 --- a/std/neko/_std/haxe/ds/ObjectMap.hx +++ b/std/neko/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-2017 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of h software and associated documentation files (the "Software"), diff --git a/std/neko/_std/haxe/ds/StringMap.hx b/std/neko/_std/haxe/ds/StringMap.hx index efcf8043..c9437d98 100644 --- a/std/neko/_std/haxe/ds/StringMap.hx +++ b/std/neko/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/haxe/zip/Compress.hx b/std/neko/_std/haxe/zip/Compress.hx index 47f64926..537dbb6f 100644 --- a/std/neko/_std/haxe/zip/Compress.hx +++ b/std/neko/_std/haxe/zip/Compress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/haxe/zip/Uncompress.hx b/std/neko/_std/haxe/zip/Uncompress.hx index d621a5ba..12797366 100644 --- a/std/neko/_std/haxe/zip/Uncompress.hx +++ b/std/neko/_std/haxe/zip/Uncompress.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/sys/FileSystem.hx b/std/neko/_std/sys/FileSystem.hx index bacc1297..4c4bd875 100644 --- a/std/neko/_std/sys/FileSystem.hx +++ b/std/neko/_std/sys/FileSystem.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -31,7 +31,7 @@ private enum FileKind { class FileSystem { public static function exists( path : String ) : Bool { - return sys_exists(untyped (haxe.io.Path.removeTrailingSlashes(path)).__s); + return sys_exists(untyped (makeCompatiblePath(path)).__s); } public static function rename( path : String, newPath : String ) : Void { @@ -39,7 +39,7 @@ class FileSystem { } public static function stat( path : String ) : FileStat { - var s : FileStat = sys_stat(untyped path.__s); + var s : FileStat = sys_stat(untyped (makeCompatiblePath(path)).__s); s.atime = untyped Date.new1(s.atime); s.mtime = untyped Date.new1(s.mtime); s.ctime = untyped Date.new1(s.ctime); @@ -56,7 +56,7 @@ class FileSystem { } static function kind( path : String ) : FileKind { - var k = new String(sys_file_type(untyped (haxe.io.Path.removeTrailingSlashes(path)).__s)); + var k = new String(sys_file_type(untyped (makeCompatiblePath(path)).__s)); return switch(k) { case "file": kfile; case "dir": kdir; @@ -64,7 +64,7 @@ class FileSystem { } } - public static function isDirectory( path : String ) : Bool { + public static inline function isDirectory( path : String ) : Bool { return kind(path) == kdir; } @@ -100,6 +100,14 @@ class FileSystem { return a; } + private static inline function makeCompatiblePath(path:String):String { + return if (path.charCodeAt(1) == ":".code && path.length <= 3) { + haxe.io.Path.addTrailingSlash(path); + } else { + haxe.io.Path.removeTrailingSlashes(path); + } + } + private static var sys_exists = neko.Lib.load("std","sys_exists",1); private static var file_delete = neko.Lib.load("std","file_delete",1); private static var sys_rename = neko.Lib.load("std","sys_rename",2); diff --git a/std/neko/_std/sys/db/Mysql.hx b/std/neko/_std/sys/db/Mysql.hx index 42d827f0..a4e523a5 100644 --- a/std/neko/_std/sys/db/Mysql.hx +++ b/std/neko/_std/sys/db/Mysql.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/sys/db/Sqlite.hx b/std/neko/_std/sys/db/Sqlite.hx index bc20f1d7..12058a01 100644 --- a/std/neko/_std/sys/db/Sqlite.hx +++ b/std/neko/_std/sys/db/Sqlite.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/sys/io/File.hx b/std/neko/_std/sys/io/File.hx index f9571538..7ddc2817 100644 --- a/std/neko/_std/sys/io/File.hx +++ b/std/neko/_std/sys/io/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/sys/io/FileInput.hx b/std/neko/_std/sys/io/FileInput.hx index 0706a688..a4d9b5a6 100644 --- a/std/neko/_std/sys/io/FileInput.hx +++ b/std/neko/_std/sys/io/FileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/sys/io/FileOutput.hx b/std/neko/_std/sys/io/FileOutput.hx index a39949de..fbf1b130 100644 --- a/std/neko/_std/sys/io/FileOutput.hx +++ b/std/neko/_std/sys/io/FileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/_std/sys/io/Process.hx b/std/neko/_std/sys/io/Process.hx index 82409d25..343d11d2 100644 --- a/std/neko/_std/sys/io/Process.hx +++ b/std/neko/_std/sys/io/Process.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -92,8 +92,11 @@ private class Stdout extends haxe.io.Input { public var stderr(default,null) : haxe.io.Input; public var stdin(default,null) : haxe.io.Output; - public function new( cmd : String, args : Array ) : Void { - p = try _run(untyped cmd.__s,neko.Lib.haxeToNeko(args)) catch( e : Dynamic ) throw "Process creation failure : "+cmd; + public function new( cmd : String, ?args : Array ) : Void { + p = try + _run(untyped cmd.__s, neko.Lib.haxeToNeko(args)) + catch( e : Dynamic ) + throw "Process creation failure : "+cmd; stdin = new Stdin(p); stdout = new Stdout(p,true); stderr = new Stdout(p,false); @@ -103,7 +106,8 @@ private class Stdout extends haxe.io.Input { return _pid(p); } - public function exitCode() : Int { + public function exitCode( block : Bool = true ) : Null { + if( block == false ) throw "Non blocking exitCode() not supported on this platform"; return _exit(p); } diff --git a/std/neko/_std/sys/net/Host.hx b/std/neko/_std/sys/net/Host.hx index c6cfa752..c2ef874c 100644 --- a/std/neko/_std/sys/net/Host.hx +++ b/std/neko/_std/sys/net/Host.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,9 +25,12 @@ package sys.net; @:keepInit class Host { + public var host(default,null) : String; + public var ip(default,null) : Int; public function new( name : String ) : Void { + host = name; ip = host_resolve(untyped name.__s); } diff --git a/std/neko/_std/sys/net/Socket.hx b/std/neko/_std/sys/net/Socket.hx index 4394fac5..9a8210bc 100644 --- a/std/neko/_std/sys/net/Socket.hx +++ b/std/neko/_std/sys/net/Socket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -39,6 +39,8 @@ private class SocketOutput extends haxe.io.Output { } catch( e : Dynamic ) { if( e == "Blocking" ) throw Blocked; + else if ( e == "EOF" ) + throw new haxe.io.Eof(); else throw Custom(e); } @@ -122,6 +124,10 @@ class Socket { public var custom : Dynamic; public function new() : Void { + init(); + } + + private function init() : Void { if( __s == null ) __s = socket_new(false); input = new SocketInput(__s); output = new SocketOutput(__s); @@ -138,7 +144,7 @@ class Socket { } public function read() : String { - return socket_read(__s); + return new String(socket_read(__s)); } public function write( content : String ) : Void { @@ -151,6 +157,10 @@ class Socket { } catch( s : String ) { if( s == "std@socket_connect" ) throw "Failed to connect on "+host.toString()+":"+port; + else if ( s == "Blocking" ) { + // Do nothing, this is not a real error, it simply indicates + // that a non-blocking connect is in progress + } else neko.Lib.rethrow(s); } @@ -179,6 +189,9 @@ class Socket { public function peer() : { host : Host, port : Int } { var a : Dynamic = socket_peer(__s); + if (a == null) { + return null; + } var h = new Host("127.0.0.1"); untyped h.ip = a[0]; return { host : h, port : a[1] }; @@ -186,6 +199,9 @@ class Socket { public function host() : { host : Host, port : Int } { var a : Dynamic = socket_host(__s); + if (a == null) { + return null; + } var h = new Host("127.0.0.1"); untyped h.ip = a[0]; return { host : h, port : a[1] }; diff --git a/std/neko/_std/sys/net/UdpSocket.hx b/std/neko/_std/sys/net/UdpSocket.hx index e38db2b1..38d73acc 100644 --- a/std/neko/_std/sys/net/UdpSocket.hx +++ b/std/neko/_std/sys/net/UdpSocket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,9 +25,9 @@ import haxe.io.Error; @:coreApi class UdpSocket extends Socket { - public function new() : Void { + private override function init() : Void { __s = Socket.socket_new(true); - super(); + super.init(); } public function sendTo( buf : haxe.io.Bytes, pos : Int, len : Int, addr : Address ) : Int { diff --git a/std/neko/_std/sys/ssl/Certificate.hx b/std/neko/_std/sys/ssl/Certificate.hx new file mode 100644 index 00000000..57102299 --- /dev/null +++ b/std/neko/_std/sys/ssl/Certificate.hx @@ -0,0 +1,131 @@ +package sys.ssl; + +@:coreApi +class Certificate { + + var __h : Null; + var __x : Dynamic; + + @:allow(sys.ssl.Socket) + function new( x : Dynamic, ?h: Null ){ + __x = x; + __h = h; + } + + public static function loadFile( file : String ) : Certificate { + return new Certificate( cert_load_file( untyped file.__s ) ); + } + + public static function loadPath( path : String ) : Certificate { + return new Certificate( cert_load_path( untyped path.__s ) ); + } + + public static function fromString( str : String ) : Certificate { + return new Certificate( cert_add_pem(null, untyped str.__s) ); + } + + public static function loadDefaults() : Certificate { + var x = cert_load_defaults(); + if ( x != null ) + return new Certificate( x ); + + var defPaths = null; + switch( Sys.systemName() ){ + case "Linux": + defPaths = [ + "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. + "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL + "/etc/ssl/ca-bundle.pem", // OpenSUSE + "/etc/pki/tls/cacert.pem", // OpenELEC + "/etc/ssl/certs", // SLES10/SLES11 + "/system/etc/security/cacerts" // Android + ]; + case "BSD": + defPaths = [ + "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly + "/etc/ssl/cert.pem", // OpenBSD + "/etc/openssl/certs/ca-certificates.crt", // NetBSD + ]; + case "Android": + defPaths = ["/system/etc/security/cacerts"]; + default: + } + if( defPaths != null ){ + for( path in defPaths ){ + if( sys.FileSystem.exists(path) ){ + if( sys.FileSystem.isDirectory(path) ) + return loadPath(path); + else + return loadFile(path); + } + } + } + return null; + } + + public var commonName(get,null) : Null; + public var altNames(get, null) : Array; + public var notBefore(get,null) : Date; + public var notAfter(get,null) : Date; + + function get_commonName() : Null { + return subject("CN"); + } + + function get_altNames() : Array { + var l : Dynamic = cert_get_altnames(__x); + var a = new Array(); + while( l != null ){ + a.push(new String(l[0])); + l = l[1]; + } + return a; + } + + public function subject( field : String ) : Null { + var s = cert_get_subject(__x, untyped field.__s); + return s==null ? null : new String( cast s ); + } + + public function issuer( field : String ) : Null { + var s = cert_get_issuer(__x, untyped field.__s); + return s==null ? null : new String( cast s ); + } + + function get_notBefore() : Date { + var a = cert_get_notbefore( __x ); + return new Date( a[0], a[1] - 1, a[2], a[3], a[4], a[5] ); + } + + function get_notAfter() : Date { + var a = cert_get_notafter( __x ); + return new Date( a[0], a[1] - 1, a[2], a[3], a[4], a[5] ); + } + + public function next() : Null { + var n = cert_get_next(__x); + return n == null ? null : new Certificate( n, __h==null ? this : __h ); + } + + public function add( pem : String ) : Void { + cert_add_pem(__x,untyped pem.__s); + } + + public function addDER( der : haxe.io.Bytes ) : Void { + cert_add_der(__x,der.getData()); + } + + private static var cert_load_defaults = neko.Lib.loadLazy("ssl", "cert_load_defaults",0); + private static var cert_load_file = neko.Lib.loadLazy("ssl", "cert_load_file",1); + private static var cert_load_path = neko.Lib.loadLazy("ssl","cert_load_path",1); + private static var cert_get_subject = neko.Lib.loadLazy("ssl", "cert_get_subject", 2); + private static var cert_get_issuer = neko.Lib.loadLazy("ssl","cert_get_issuer",2); + private static var cert_get_altnames = neko.Lib.loadLazy("ssl","cert_get_altnames",1); + private static var cert_get_notbefore = neko.Lib.loadLazy("ssl","cert_get_notbefore",1); + private static var cert_get_notafter = neko.Lib.loadLazy("ssl","cert_get_notafter",1); + private static var cert_get_next = neko.Lib.loadLazy("ssl","cert_get_next",1); + private static var cert_add_pem = neko.Lib.loadLazy("ssl","cert_add_pem",2); + private static var cert_add_der = neko.Lib.loadLazy("ssl","cert_add_der",2); + + +} diff --git a/std/neko/_std/sys/ssl/Digest.hx b/std/neko/_std/sys/ssl/Digest.hx new file mode 100644 index 00000000..26d8979b --- /dev/null +++ b/std/neko/_std/sys/ssl/Digest.hx @@ -0,0 +1,22 @@ +package sys.ssl; + +@:coreApi +class Digest { + + public static function make( data : haxe.io.Bytes, alg : DigestAlgorithm ) : haxe.io.Bytes { + return haxe.io.Bytes.ofData( dgst_make( data.getData(), untyped alg.__s ) ); + } + + public static function sign( data : haxe.io.Bytes, privKey : Key, alg : DigestAlgorithm ) : haxe.io.Bytes { + return haxe.io.Bytes.ofData( dgst_sign( data.getData(), @:privateAccess privKey.__k, untyped alg.__s ) ); + } + + public static function verify( data : haxe.io.Bytes, signature : haxe.io.Bytes, pubKey : Key, alg : DigestAlgorithm ) : Bool{ + return dgst_verify( data.getData(), signature.getData(), @:privateAccess pubKey.__k, untyped alg.__s ); + } + + private static var dgst_make = neko.Lib.loadLazy("ssl","dgst_make",2); + private static var dgst_sign = neko.Lib.loadLazy("ssl","dgst_sign",3); + private static var dgst_verify = neko.Lib.loadLazy("ssl","dgst_verify",4); + +} diff --git a/std/neko/_std/sys/ssl/Key.hx b/std/neko/_std/sys/ssl/Key.hx new file mode 100644 index 00000000..b8294cf0 --- /dev/null +++ b/std/neko/_std/sys/ssl/Key.hx @@ -0,0 +1,34 @@ +package sys.ssl; + +private typedef PKEY = Dynamic; + +@:coreApi +class Key { + + private var __k : PKEY; + + private function new( k : PKEY ){ + __k = k; + } + + public static function loadFile( file : String, ?isPublic : Bool, ?pass : String ) : Key { + var data = sys.io.File.getBytes( file ); + var str = neko.Lib.stringReference(data); + if( str.indexOf("-----BEGIN ") >= 0 ) + return readPEM( str, isPublic==true, pass ); + else + return readDER( data, isPublic==true ); + } + + public static function readPEM( data : String, isPublic : Bool, ?pass : String ) : Key { + return new Key( key_from_pem( untyped data.__s, isPublic, pass == null ? null : untyped pass.__s ) ); + } + + public static function readDER( data : haxe.io.Bytes, isPublic : Bool ) : Key { + return new Key( key_from_der( data.getData(), isPublic ) ); + } + + private static var key_from_pem = neko.Lib.loadLazy("ssl","key_from_pem",3); + private static var key_from_der = neko.Lib.loadLazy("ssl","key_from_der",2); + +} diff --git a/std/neko/_std/sys/ssl/Socket.hx b/std/neko/_std/sys/ssl/Socket.hx new file mode 100644 index 00000000..4a6ceeb7 --- /dev/null +++ b/std/neko/_std/sys/ssl/Socket.hx @@ -0,0 +1,289 @@ +package sys.ssl; + +private typedef SocketHandle = Dynamic; +private typedef CTX = Dynamic; +private typedef SSL = Dynamic; + +private class SocketInput extends haxe.io.Input { + @:allow(sys.ssl.Socket) private var __s : Socket; + + public function new( s : Socket ) { + this.__s = s; + } + + public override function readByte() { + return try { + __s.handshake(); + ssl_recv_char( @:privateAccess __s.ssl ); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw haxe.io.Error.Blocked; + else if( __s == null ) + throw haxe.io.Error.Custom(e); + else + throw new haxe.io.Eof(); + } + } + + public override function readBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int { + var r : Int; + if( __s == null ) + throw "Invalid handle"; + try { + __s.handshake(); + r = ssl_recv( @:privateAccess __s.ssl, buf.getData(), pos, len ); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw haxe.io.Error.Blocked; + else + throw haxe.io.Error.Custom(e); + } + if( r == 0 ) + throw new haxe.io.Eof(); + return r; + } + + public override function close() { + super.close(); + if( __s != null ) __s.close(); + } + + private static var ssl_recv = neko.Lib.loadLazy( "ssl", "ssl_recv", 4 ); + private static var ssl_recv_char = neko.Lib.loadLazy( "ssl", "ssl_recv_char", 1 ); + +} + +private class SocketOutput extends haxe.io.Output { + @:allow(sys.ssl.Socket) private var __s : Socket; + + public function new( s : Socket ) { + this.__s = s; + } + + public override function writeByte( c : Int ) { + if( __s == null ) + throw "Invalid handle"; + try { + __s.handshake(); + ssl_send_char( @:privateAccess __s.ssl, c); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw haxe.io.Error.Blocked; + else + throw haxe.io.Error.Custom(e); + } + } + + public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int { + return try { + __s.handshake(); + ssl_send( @:privateAccess __s.ssl, buf.getData(), pos, len); + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw haxe.io.Error.Blocked; + else + throw haxe.io.Error.Custom(e); + } + } + + public override function close() { + super.close(); + if( __s != null ) __s.close(); + } + + private static var ssl_send_char = neko.Lib.loadLazy( "ssl", "ssl_send_char", 2 ); + private static var ssl_send = neko.Lib.loadLazy( "ssl", "ssl_send", 4 ); +} + +@:coreApi +class Socket extends sys.net.Socket { + + public static var DEFAULT_VERIFY_CERT : Null = true; + + public static var DEFAULT_CA : Null; + + private var ctx : CTX; + private var ssl : SSL; + + public var verifyCert : Null; + private var caCert : Null; + private var hostname : String; + + private var ownCert : Null; + private var ownKey : Null; + private var altSNIContexts : NullBool, key: Key, cert: Certificate}>>; + private var sniCallback : Dynamic; + private var handshakeDone : Bool; + + private override function init() : Void { + __s = socket_new( false ); + input = new SocketInput( this ); + output = new SocketOutput( this ); + if( DEFAULT_VERIFY_CERT && DEFAULT_CA == null ){ + try { + DEFAULT_CA = Certificate.loadDefaults(); + }catch( e : Dynamic ){} + } + verifyCert = DEFAULT_VERIFY_CERT; + caCert = DEFAULT_CA; + } + + public override function connect(host : sys.net.Host, port : Int) : Void { + try { + ctx = buildSSLContext( false ); + ssl = ssl_new( ctx ); + ssl_set_socket( ssl, __s ); + handshakeDone = false; + if( hostname == null ) + hostname = host.host; + if( hostname != null ) + ssl_set_hostname( ssl, untyped hostname.__s ); + socket_connect( __s, host.ip, port ); + handshake(); + } catch( s : String ) { + if( s == "std@socket_connect" ) + throw "Failed to connect on "+host.host+":"+port; + else + neko.Lib.rethrow(s); + } catch( e : Dynamic ) { + neko.Lib.rethrow(e); + } + } + + public function handshake() : Void { + if( !handshakeDone ){ + try { + ssl_handshake( ssl ); + handshakeDone = true; + } catch( e : Dynamic ) { + if( e == "Blocking" ) + throw haxe.io.Error.Blocked; + else + neko.Lib.rethrow( e ); + } + } + } + + public function setCA( cert : Certificate ) : Void { + caCert = cert; + } + + public function setHostname( name : String ) : Void { + hostname = name; + } + + public function setCertificate( cert : Certificate, key : Key ) : Void { + ownCert = cert; + ownKey = key; + } + + public override function read() : String { + handshake(); + var b = ssl_read( ssl ); + if( b == null ) + return ""; + return new String(cast b); + } + + public override function write( content : String ) : Void { + handshake(); + ssl_write( ssl, untyped content.__s ); + } + + public override function close() : Void { + if( ssl != null ) ssl_close( ssl ); + if( ctx != null ) conf_close( ctx ); + if( altSNIContexts != null ) + sniCallback = null; + socket_close( __s ); + var input : SocketInput = cast input; + var output : SocketOutput = cast output; + @:privateAccess input.__s = output.__s = null; + input.close(); + output.close(); + } + + public function addSNICertificate( cbServernameMatch : String->Bool, cert : Certificate, key : Key ) : Void { + if( altSNIContexts == null ) + altSNIContexts = []; + altSNIContexts.push( {match: cbServernameMatch, cert: cert, key: key} ); + } + + public override function bind( host : sys.net.Host, port : Int ) : Void { + ctx = buildSSLContext( true ); + + socket_bind( __s, host.ip, port ); + } + + public override function accept() : Socket { + var c = socket_accept( __s ); + var ssl = ssl_new( ctx ); + ssl_set_socket( ssl, c ); + + var s = Type.createEmptyInstance( sys.ssl.Socket ); + s.__s = c; + s.ssl = ssl; + s.input = new SocketInput(s); + s.output = new SocketOutput(s); + s.handshakeDone = false; + + return s; + } + + public function peerCertificate() : sys.ssl.Certificate { + var x = ssl_get_peer_certificate( ssl ); + return x==null ? null : new sys.ssl.Certificate( x ); + } + + private function buildSSLContext( server : Bool ) : CTX { + var ctx : CTX = conf_new( server ); + + if( ownCert != null && ownKey != null ) + conf_set_cert( ctx, @:privateAccess ownCert.__x, @:privateAccess ownKey.__k ); + + if ( altSNIContexts != null ) { + sniCallback = function(servername) { + var servername = new String(cast servername); + for( c in altSNIContexts ){ + if( c.match(servername) ) + return @:privateAccess {key: c.key.__k, cert: c.cert.__x}; + } + if( ownKey != null && ownCert != null ) + return @:privateAccess { key: ownKey.__k, cert: ownCert.__x }; + return null; + } + conf_set_servername_callback( ctx, sniCallback ); + } + + if ( caCert != null ) + conf_set_ca( ctx, caCert == null ? null : @:privateAccess caCert.__x ); + conf_set_verify( ctx, verifyCert ); + + return ctx; + } + + + private static var ssl_new = neko.Lib.loadLazy( "ssl", "ssl_new", 1 ); + private static var ssl_close = neko.Lib.loadLazy( "ssl", "ssl_close", 1 ); + private static var ssl_handshake = neko.Lib.loadLazy( "ssl", "ssl_handshake", 1 ); + private static var ssl_set_socket = neko.Lib.loadLazy( "ssl", "ssl_set_socket", 2 ); + private static var ssl_set_hostname = neko.Lib.loadLazy( "ssl", "ssl_set_hostname", 2 ); + private static var ssl_get_peer_certificate = neko.Lib.loadLazy( "ssl", "ssl_get_peer_certificate", 1 ); + + private static var ssl_read = neko.Lib.loadLazy( "ssl", "ssl_read", 1 ); + private static var ssl_write = neko.Lib.loadLazy( "ssl", "ssl_write", 2 ); + + private static var conf_new = neko.Lib.loadLazy( "ssl", "conf_new", 1 ); + private static var conf_close = neko.Lib.loadLazy( "ssl", "conf_close", 1 ); + private static var conf_set_ca = neko.Lib.loadLazy( "ssl", "conf_set_ca", 2 ); + private static var conf_set_verify = neko.Lib.loadLazy( "ssl", "conf_set_verify", 2 ); + private static var conf_set_cert = neko.Lib.loadLazy( "ssl", "conf_set_cert", 3 ); + private static var conf_set_servername_callback = neko.Lib.loadLazy( "ssl", "conf_set_servername_callback", 2 ); + + private static var socket_new = neko.Lib.load("std","socket_new",1); + private static var socket_close = neko.Lib.load("std","socket_close",1); + private static var socket_connect = neko.Lib.load("std","socket_connect",3); + private static var socket_bind = neko.Lib.load("std","socket_bind",3); + private static var socket_accept = neko.Lib.load("std","socket_accept",1); + +} diff --git a/std/neko/net/Poll.hx b/std/neko/net/Poll.hx index 8f5aed98..dff7373e 100644 --- a/std/neko/net/Poll.hx +++ b/std/neko/net/Poll.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/net/ProxyDetect.hx b/std/neko/net/ProxyDetect.hx index afc5e08c..02cd55f9 100644 --- a/std/neko/net/ProxyDetect.hx +++ b/std/neko/net/ProxyDetect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/net/ServerLoop.hx b/std/neko/net/ServerLoop.hx index 67ff8378..76c2b1d6 100644 --- a/std/neko/net/ServerLoop.hx +++ b/std/neko/net/ServerLoop.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -59,16 +59,16 @@ class ServerLoop { public var listenCount : Int; /** - See [update]. + See `update`. **/ public var updateTime : Float; var newData : Socket -> ClientData; - var socks : Array; + var socks : Array; public var clients : List; /** - Creates a server instance. The [newData] methods must return + Creates a server instance. The `newData` methods must return the data associated with the Client. **/ public function new( ?newData ) { @@ -93,9 +93,9 @@ class ServerLoop { } /** - The [update] method is called after each socket event has been - processed or when [updateTime] has been reached. It can be used - to perform time-regular tasks such as pings. By default [updateTime] + The `update` method is called after each socket event has been + processed or when `updateTime` has been reached. It can be used + to perform time-regular tasks such as pings. By default `updateTime` is set to one second. **/ public function update() { @@ -126,7 +126,7 @@ class ServerLoop { } /** - This method is called when some data has been readed into a Client buffer. + This method is called when some data has been read into a Client buffer. If the data can be handled, then you can return the number of bytes handled that needs to be removed from the buffer. It the data can't be handled (some part of the message is missing for example), returns 0. @@ -138,7 +138,7 @@ class ServerLoop { /** Called when an error occured. This enable you to log the error somewhere. - By default the error is displayed using [trace]. + By default the error is displayed using `trace`. **/ public function onError( e : Dynamic ) { trace(Std.string(e)+"\n"+haxe.CallStack.toString(haxe.CallStack.exceptionStack())); diff --git a/std/neko/net/ThreadRemotingServer.hx b/std/neko/net/ThreadRemotingServer.hx index 133fb83b..3eb55db2 100644 --- a/std/neko/net/ThreadRemotingServer.hx +++ b/std/neko/net/ThreadRemotingServer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/neko/net/ThreadServer.hx b/std/neko/net/ThreadServer.hx index a24d4f09..a5f1ddc1 100644 --- a/std/neko/net/ThreadServer.hx +++ b/std/neko/net/ThreadServer.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -36,22 +36,65 @@ private typedef ClientInfos = { var bufpos : Int; } +/** + The ThreadServer can be used to easily create a multithreaded server where each thread polls multiple connections. + To use it, at a minimum you must override or rebind clientConnected, readClientMessage, and clientMessage and you must define your Client and Message. +**/ class ThreadServer { var threads : Array; var sock : sys.net.Socket; var worker : neko.vm.Thread; var timer : neko.vm.Thread; + + /** + Number of total connections the server will accept. + **/ public var listen : Int; + + /** + Number of server threads. + **/ public var nthreads : Int; + + /** + Polling timeout. + **/ public var connectLag : Float; + + /** + Stream to send error messages. + **/ public var errorOutput : haxe.io.Output; + + /** + Space allocated to buffers when they are created. + **/ public var initialBufferSize : Int; + + /** + Maximum size of buffered data read from a socket. An exception is thrown if the buffer exceeds this value. + **/ public var maxBufferSize : Int; + + /** + Minimum message size. + **/ public var messageHeaderSize : Int; + + /** + Time between calls to update. + **/ public var updateTime : Float; + + /** + The most sockets a thread will handle. + **/ public var maxSockPerThread : Int; + /** + Creates a ThreadServer. + **/ public function new() { threads = new Array(); nthreads = if( Sys.systemName() == "Windows" ) 150 else 10; @@ -152,6 +195,9 @@ class ThreadServer { } } + /** + Internally used to delegate something to the worker thread. + **/ public function work( f : Void -> Void ) { worker.sendMessage(f); } @@ -212,11 +258,17 @@ class ThreadServer { } } + /** + Called when the server gets a new connection. + **/ public function addSocket( s : sys.net.Socket ) { s.setBlocking(false); work(addClient.bind(s)); } + /** + Start the server at the specified host and port. + **/ public function run( host, port ) { sock = new sys.net.Socket(); sock.bind(new sys.net.Host(host),port); @@ -231,6 +283,9 @@ class ThreadServer { } } + /** + Sends data to a client. + **/ public function sendData( s : sys.net.Socket, data : String ) { try { s.write(data); @@ -239,6 +294,9 @@ class ThreadServer { } } + /** + Shutdown a client's connection and remove them from the server. + **/ public function stopClient( s : sys.net.Socket ) { var infos : ClientInfos = s.custom; try s.shutdown(true,true) catch( e : Dynamic ) { }; @@ -247,19 +305,33 @@ class ThreadServer { // --- CUSTOMIZABLE API --- + /** + Called when an error has occurred. + **/ public dynamic function onError( e : Dynamic, stack ) { var estr = try Std.string(e) catch( e2 : Dynamic ) "???" + try "["+Std.string(e2)+"]" catch( e : Dynamic ) ""; errorOutput.writeString( estr + "\n" + haxe.CallStack.toString(stack) ); errorOutput.flush(); } + /** + Called when a client connects. Returns a client object. + **/ public dynamic function clientConnected( s : sys.net.Socket ) : Client { return null; } + /** + Called when a client disconnects or an error forces the connection to close. + **/ public dynamic function clientDisconnected( c : Client ) { } + /** + Called when data has been read from a socket. This method should try to extract a message from the buffer. + The available data resides in buf, starts at pos, and is len bytes wide. Return the new message and the number of bytes read from the buffer. + If no message could be read, return null. + **/ public dynamic function readClientMessage( c : Client, buf : haxe.io.Bytes, pos : Int, len : Int ) : { msg : Message, bytes : Int } { return { msg : null, @@ -267,12 +339,21 @@ class ThreadServer { }; } + /** + Called when a message has been received. Message handling code should go here. + **/ public dynamic function clientMessage( c : Client, msg : Message ) { } + /** + This method is called periodically. It can be used to do server maintenance. + **/ public dynamic function update() { } + /** + Called after a client connects, disconnects, a message is received, or an update is performed. + **/ public dynamic function afterEvent() { } diff --git a/std/neko/vm/Deque.hx b/std/neko/vm/Deque.hx index ffdec97e..36b48f15 100644 --- a/std/neko/vm/Deque.hx +++ b/std/neko/vm/Deque.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,20 +21,41 @@ */ package neko.vm; +/** + A message queue for multithread access. +*/ class Deque { var q : Dynamic; + + /** + Create a message queue for multithread access. + */ public function new() { q = deque_create(); } + + /** + Add a message at the end of the queue. + */ public function add( i : T ) { deque_add(q,i); } + + /** + Add a message at the head of the queue. + */ public function push( i : T ) { deque_push(q,i); } + + /** + Pop a message from the queue head. Either block until a message + is available or return immediately with `null`. + */ public function pop( block : Bool ) : Null { return deque_pop(q,block); } + static var deque_create = neko.Lib.loadLazy("std","deque_create",0); static var deque_add = neko.Lib.loadLazy("std","deque_add",2); static var deque_push = neko.Lib.loadLazy("std","deque_push",2); diff --git a/std/neko/vm/Gc.hx b/std/neko/vm/Gc.hx index 69237641..64f3282d 100644 --- a/std/neko/vm/Gc.hx +++ b/std/neko/vm/Gc.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,17 +21,25 @@ */ package neko.vm; +/** + Neko garbage collector utility. +*/ class Gc { - + /** + Run the Neko garbage collector. + */ public static function run( major : Bool ) { _run(major); } + /** + Return the size of the GC heap and the among of free space, + in bytes. + */ public static function stats() : { heap : Int, free : Int } { return _stats(); } static var _run = neko.Lib.load("std","run_gc",1); static var _stats = neko.Lib.load("std","gc_stats",0); - } diff --git a/std/neko/vm/Loader.hx b/std/neko/vm/Loader.hx index 1fec4fe6..d8a9885a 100644 --- a/std/neko/vm/Loader.hx +++ b/std/neko/vm/Loader.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -54,8 +54,8 @@ class Loader { } /** - The default loader contains a search path in its [path] field. It's a - linked list of Neko strings that is a parsed version of the [NEKOPATH]. + The default loader contains a search path in its `path` field. It's a + linked list of Neko strings that is a parsed version of the `NEKOPATH`. This path is used to lookup for modules and libraries. **/ public function getPath() { @@ -69,7 +69,7 @@ class Loader { } /** - Adds a directory to the search path. See [getPath] + Adds a directory to the search path. See `getPath`. **/ public function addPath( s : String ) { untyped l.path = __dollar__array(s.__s,l.path); @@ -115,7 +115,7 @@ class Loader { } /** - Loads a neko primitive. By default, the name is of the form [library@method]. + Loads a neko primitive. By default, the name is of the form `[library@method]`. The primitive might not be used directly in Haxe since some of the Neko values needs an object wrapper in Haxe. **/ @@ -124,7 +124,7 @@ class Loader { } /** - Loads a Module with the given name. If [loader] is defined, this will be + Loads a Module with the given name. If `loader` is defined, this will be this Module loader, else this loader will be inherited. When loaded this way, the module is directly executed. **/ @@ -143,7 +143,7 @@ class Loader { /** Creates a loader using two methods. This loader will not have an accessible cache or path, - although you can implement such mecanism in the methods body. + although you can implement such mechanism in the methods body. **/ public static function make( loadPrim : String -> Int -> Dynamic, loadModule : String -> Loader -> Module ) { var l = { diff --git a/std/neko/vm/Lock.hx b/std/neko/vm/Lock.hx index 35886842..01209380 100644 --- a/std/neko/vm/Lock.hx +++ b/std/neko/vm/Lock.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -23,15 +23,32 @@ package neko.vm; class Lock { var l : Dynamic; + + /** + Creates a lock which is initially locked. + */ public function new() { l = lock_create(); } + + /** + Waits for a lock to be released and acquire it. If timeout + (in seconds) is not `null` and expires then the returned + value is `false`. + */ public function wait( ?timeout : Float ) : Bool { return lock_wait(l,timeout); } + + /** + Release a lock. The thread does not need to own the lock + to be able to release it. If a lock is released several + times, it can be acquired as many times. + */ public function release() { lock_release(l); } + static var lock_create = neko.Lib.load("std","lock_create",0); static var lock_release = neko.Lib.load("std","lock_release",1); static var lock_wait = neko.Lib.load("std","lock_wait",2); diff --git a/std/neko/vm/Module.hx b/std/neko/vm/Module.hx index 10a5bc6f..2d4d75d3 100644 --- a/std/neko/vm/Module.hx +++ b/std/neko/vm/Module.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -28,8 +28,8 @@ enum ModuleHandle { } /** - A Neko Module represent a execution unit for the Neko Virtual Machine. Each compiled [.n] bytecode - file is a module once loaded by the NekoVM. + A Neko Module represent a execution unit for the Neko Virtual Machine. + Each compiled `.n` bytecode file is a module once loaded by the NekoVM. **/ class Module { @@ -63,7 +63,7 @@ class Module { /** - Returns the Loader that this Module was loaded with.s + Returns the Loader that this Module was loaded with. **/ public function loader() { return new Loader(_module_loader(m)); diff --git a/std/neko/vm/Mutex.hx b/std/neko/vm/Mutex.hx index 3862ff09..90471b3d 100644 --- a/std/neko/vm/Mutex.hx +++ b/std/neko/vm/Mutex.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,20 +21,47 @@ */ package neko.vm; +/** + Creates a mutex, which can be used to acquire a temporary lock + to access some ressource. The main difference with a lock is + that a mutex must always be released by the owner thread. +*/ class Mutex { var m : Dynamic; + + /** + Creates a mutex. + */ public function new() { m = mutex_create(); } + + /** + The current thread acquire the mutex or wait if not available. + The same thread can acquire several times the same mutex but + must release it as many times it has been acquired. + */ public function acquire() { mutex_acquire(m); } + + /** + Try to acquire the mutex, returns true if acquire or false + if it's already locked by another thread. + */ public function tryAcquire() : Bool { return mutex_try(m); } + + /** + Release a mutex that has been acquired by the current thread. + The behavior is undefined if the current thread does not own + the mutex. + */ public function release() { mutex_release(m); } + static var mutex_create = neko.Lib.loadLazy("std","mutex_create",0); static var mutex_release = neko.Lib.loadLazy("std","mutex_release",1); static var mutex_acquire = neko.Lib.loadLazy("std","mutex_acquire",1); diff --git a/std/neko/vm/Thread.hx b/std/neko/vm/Thread.hx index a877c85a..7cf23df8 100644 --- a/std/neko/vm/Thread.hx +++ b/std/neko/vm/Thread.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -33,7 +33,7 @@ class Thread { } /** - Send a message to the thread queue. This message can be readed by using [readMessage]. + Send a message to the thread queue. This message can be read by using `readMessage`. **/ public function sendMessage( msg : Dynamic ) { thread_send(handle,msg); @@ -48,16 +48,16 @@ class Thread { } /** - Creates a new thread that will execute the [callb] function, then exit. + Creates a new thread that will execute the `callb` function, then exit. **/ public static function create( callb : Void -> Void ) { return new Thread(thread_create(function(_) { return callb(); },null)); } /** - Reads a message from the thread queue. If [block] is true, the function - blocks until a message is available. If [block] is false, the function - returns [null] if no message is available. + Reads a message from the thread queue. If `block` is true, the function + blocks until a message is available. If `block` is false, the function + returns `null` if no message is available. **/ public static function readMessage( block : Bool ) : Dynamic { return thread_read_message(block); diff --git a/std/neko/vm/Tls.hx b/std/neko/vm/Tls.hx index 193dbab9..aa1d3052 100644 --- a/std/neko/vm/Tls.hx +++ b/std/neko/vm/Tls.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,19 +21,34 @@ */ package neko.vm; +/** + Creates thread local storage. +*/ class Tls { var t : Dynamic; public var value(get,set) : T; + /** + Creates thread local storage. This is placeholder that can store + a value that will be different depending on the local thread. + Set the tls value to `null` before exiting the thread + or the memory will never be collected. + */ public function new() { t = tls_create(); } + /** + Returns the value set by tls_set for the local thread. + */ function get_value() : T { return tls_get(t); } + /** + Set the value of the TLS for the local thread. + */ function set_value( v : T ) { tls_set(t,v); return v; @@ -42,5 +57,4 @@ class Tls { static var tls_create = neko.Lib.load("std","tls_create",0); static var tls_get = neko.Lib.load("std","tls_get",1); static var tls_set = neko.Lib.load("std","tls_set",2); - -} \ No newline at end of file +} diff --git a/std/neko/vm/Ui.hx b/std/neko/vm/Ui.hx index 56e5c3f5..20615323 100644 --- a/std/neko/vm/Ui.hx +++ b/std/neko/vm/Ui.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,20 +21,42 @@ */ package neko.vm; +/** + Core native User Interface support. This API uses native WIN32 API + on Windows, Carbon API on OSX, and GTK2 on Linux. +*/ class Ui { + /** + Tells if the current thread is the main loop thread or not. + The main loop thread is the one in which the first "ui" + library primitive has been loaded. + */ public static function isMainThread() { return _is_main_thread(); } + /** + Starts the native UI event loop. This method can only be called + from the main thread. + */ public static function loop() { _loop(); } + /** + Stop the native UI event loop. This method can only be called + from the main thread. + */ public static function stopLoop() { _sync(_stop_loop); } + /** + Queue a method call callb to be executed by the main thread while + running the UI event loop. This can be used to perform UI updates + in the UI thread using results processed by another thread. + */ public static function sync( f : Void -> Void ) { _sync(f); } @@ -64,4 +86,4 @@ class Ui { static var _stop_loop = neko.Lib.load("ui","ui_stop_loop",0); static var _sync = neko.Lib.load("ui","ui_sync",1); -} \ No newline at end of file +} diff --git a/std/neko/zip/Compress.hx b/std/neko/zip/Compress.hx index e1d186db..92dd0700 100644 --- a/std/neko/zip/Compress.hx +++ b/std/neko/zip/Compress.hx @@ -1,5 +1,26 @@ -package neko.zip; +/* + * Copyright (C)2005-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 neko.zip; -#if (haxe_ver < 3.4) +#if (haxe_ver < 4.0) typedef Compress = haxe.zip.Compress; #end \ No newline at end of file diff --git a/std/neko/zip/Flush.hx b/std/neko/zip/Flush.hx index 69eabaa4..1dac15fe 100644 --- a/std/neko/zip/Flush.hx +++ b/std/neko/zip/Flush.hx @@ -1,5 +1,26 @@ -package neko.zip; +/* + * Copyright (C)2005-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 neko.zip; -#if (haxe_ver < 3.4) +#if (haxe_ver < 4.0) typedef Flush = haxe.zip.FlushMode; #end \ No newline at end of file diff --git a/std/neko/zip/Uncompress.hx b/std/neko/zip/Uncompress.hx index 6f34a14b..4bc86f12 100644 --- a/std/neko/zip/Uncompress.hx +++ b/std/neko/zip/Uncompress.hx @@ -1,5 +1,26 @@ -package neko.zip; +/* + * Copyright (C)2005-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 neko.zip; -#if (haxe_ver < 3.4) +#if (haxe_ver < 4.0) typedef Uncompress = haxe.zip.Uncompress; #end \ No newline at end of file diff --git a/std/php/Boot.hx b/std/php/Boot.hx index 16a78a0d..4d43d837 100644 --- a/std/php/Boot.hx +++ b/std/php/Boot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,7 @@ */ package php; +@:dox(hide) @:keep class Boot { static var qtypes; @@ -95,8 +96,8 @@ class _hx_array implements ArrayAccess, IteratorAggregate { } function remove($x) { - for($i = 0; $i < count($this->a); $i++) - if($this->a[$i] === $x) { + foreach($this->a as $i => $val) + if($val === $x) { unset($this->a[$i]); $this->a = array_values($this->a); $this->length--; @@ -318,8 +319,8 @@ function _hx_error_handler($errno, $errmsg, $filename, $linenum, $vars) { if (!(error_reporting() & $errno)) { return false; } - $msg = $errmsg . ' (errno: ' . $errno . ') in ' . $filename . ' at line #' . $linenum; - $e = new HException($msg, $errmsg, $errno, _hx_anonymous(array('fileName' => 'Boot.hx', 'lineNumber' => __LINE__, 'className' => 'php.Boot', 'methodName' => '_hx_error_handler'))); + $msg = $errmsg . ' (errno: ' . $errno . ')'; + $e = new HException($msg, '', $errno, _hx_anonymous(array('fileName' => 'Boot.hx', 'lineNumber' => __LINE__, 'className' => 'php.Boot', 'methodName' => '_hx_error_handler'))); $e->setFile($filename); $e->setLine($linenum); throw $e; @@ -343,9 +344,10 @@ function _hx_exception_handler($e) { $i = $GLOBALS['%s']->length; while(--$i >= 0) $stack .= 'Called from '.$GLOBALS['%s'][$i].$nl; - die($pre.'uncaught exception: '.$msg.$nl.$nl.$stack.$post); + echo $pre.'uncaught exception: '.$msg.$nl.$nl.$stack.$post; } else - die($pre.'uncaught exception: '.$msg.$nl.$nl.'in file: '.$e->getFile().' line '.$e->getLine().$nl.$e->getTraceAsString().$post); + echo $pre.'uncaught exception: '.$msg.$nl.$nl.'in file: '.$e->getFile().' line '.$e->getLine().$nl.$e->getTraceAsString().$post; + exit(1); } function _hx_explode($delimiter, $s) { @@ -398,7 +400,7 @@ function _hx_field($o, $field) { return $o->$field; } } - } else if(isset($o->__dynamics[$field])) { + } else if(isset($o->__dynamics) && isset($o->__dynamics[$field])) { return $o->__dynamics[$field]; } else { return array($o, $field); @@ -415,10 +417,8 @@ function _hx_get_object_vars($o) { if(isset($o->__dynamics)) $a = array_merge($a, array_keys($o->__dynamics)); $arr = array(); - for($i=0;$i__tname__ != 'Enum'; case 'Enum' : return $v instanceof _hx_enum; + case 'php.NativeArray': return is_array($v); default : return is_a($v, $t->__tname__); } } @@ -538,7 +539,11 @@ _hx_nullob::$inst = new _hx_nullob(); function _hx_nullob() { return _hx_nullob::$inst; } function _hx_qtype($n) { - return isset(php_Boot::$qtypes[$n]) ? php_Boot::$qtypes[$n] : null; + if(!isset(php_Boot::$qtypes[$n])) { + php_Boot::$qtypes[$n] = new _hx_type($n, null); + } + + return php_Boot::$qtypes[$n]; } function _hx_register_type($t) { @@ -554,7 +559,7 @@ function _hx_set_method($o, $field, $func) { } function _hx_shift_right($v, $n) { - return ($v >= 0) ? ($v >> $n) : ($v >> $n) & (0x7fffffff >> ($n-1)); + return ($n == 0) ? $v : ($v >= 0) ? ($v >> $n) : ($v >> $n) & (0x7fffffff >> ($n-1)); } function _hx_string_call($s, $method, $params) { @@ -589,11 +594,11 @@ function _hx_string_rec($o, $s) { if(!empty($o->params)) { $s .= \"\t\"; $b .= '('; - for($i = 0; $i < count($o->params); $i++) { + foreach($o->params as $i => $val) { if($i > 0) - $b .= ',' . _hx_string_rec($o->params[$i], $s); + $b .= ',' . _hx_string_rec($val, $s); else - $b .= _hx_string_rec($o->params[$i], $s); + $b .= _hx_string_rec($val, $s); } $b .= ')'; } @@ -608,8 +613,7 @@ function _hx_string_rec($o, $s) { $s .= \"\t\"; $properties = $rfl->getProperties(); - for($i = 0; $i < count($properties); $i++) { - $prop = $properties[$i]; + foreach($properties as $i => $prop) { $f = $prop->getName(); if($i > 0) $b2 .= \", \n\"; @@ -767,6 +771,12 @@ class _hx_type { $this->__meta__ = eval($cn.'::$__meta__'); } + public function __ensureMeta__() { + if(property_exists($this->__tname__, '__meta__') && !$this->__meta__) { + $this->__meta__ = eval($this->__tname__.'::$__meta__'); + } + } + public function toString() { return $this->__toString(); } public function __toString() { @@ -789,9 +799,13 @@ class _hx_type { public function __get($n) { if(($r = $this->__rfl__())==null) return null; - if($r->hasProperty($n)) - return $r->getStaticPropertyValue($n); - else if($r->hasMethod($n)) + if($r->hasProperty($n)) { + try { + return $r->getStaticPropertyValue($n); + } catch(Exception $e) { + return null; + } + } else if($r->hasMethod($n)) return array($r->name, $n); else return null; @@ -804,7 +818,7 @@ class _hx_type { public function __isset($n) { if(($r = $this->__rfl__())==null) return null; - return $r->hasProperty($n) || $r->hasMethod($n); + return array_key_exists($n, $r->getStaticProperties()) || $r->hasMethod($n); } } @@ -843,7 +857,7 @@ class _hx_lambda { // if use $this->locals directly in array_merge it works only if I make the assignement loop, // so I've decided to reference $arr $arr = array(); - for ($i = 0; $ilocals);$i++) + foreach($this->locals as $i => $val) $arr[] = & $this->locals[$i]; $args = func_get_args(); return call_user_func_array($this->func, array_merge($arr, $args)); @@ -862,7 +876,7 @@ class Enum { } error_reporting(E_ALL & ~E_STRICT); -set_error_handler('_hx_error_handler', E_ALL); +set_error_handler('_hx_error_handler', E_ALL & ~E_STRICT); set_exception_handler('_hx_exception_handler'); php_Boot::$qtypes = array(); @@ -930,24 +944,24 @@ if(!file_exists($_hx_autload_cache_file)) { _hx_build_paths($_hx_libdir, $_hx_types_array, array(), $_hx_class_prefix); - for($i=0;$is[{1}] = chr({2})", this, index, val); + } + + public var length(get, never):Int; + + public inline function compare (other:BytesData):Int { + return untyped __php__("{0} < {1} ? -1 : ({0} == {1} ? 0 : 1)", str(), other.str()); + } + + public inline function get (pos:Int):Int { + return untyped __call__("ord", str()[pos]); + } + + public inline function copy ():BytesData { + return ofNativeString(str()); + } + + public inline function getString (pos:Int, len:Int):String { + return untyped __call__("substr", str(), pos, len); + } + + public inline function sub (pos:Int, len:Int):BytesData { + return ofString(untyped __call__("substr", str(), pos, len)); + } + + public inline function blit (pos : Int, src : BytesData, srcpos : Int, len : Int):Void { + setNativeString(untyped __php__("substr({0}, 0, {2}) . substr({1}, {3}, {4}) . substr({0}, {2}+{4})", str(), src.str(), pos, srcpos, len)); + } + + public inline function toString():String return cast str(); + + public static inline function ofString (s:String) { + return ofNativeString(cast s); + } + + public static inline function alloc (length:Int) { + return ofNativeString(untyped __call__("str_repeat", __call__("chr", 0), length)); + } +} \ No newline at end of file diff --git a/std/php/Exception.hx b/std/php/Exception.hx index bcd591e6..03b7536b 100644 --- a/std/php/Exception.hx +++ b/std/php/Exception.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/HException.hx b/std/php/HException.hx index d07d4e7c..3c830346 100644 --- a/std/php/HException.hx +++ b/std/php/HException.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/IteratorAggregate.hx b/std/php/IteratorAggregate.hx index c3981835..8605d41a 100644 --- a/std/php/IteratorAggregate.hx +++ b/std/php/IteratorAggregate.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/Lib.hx b/std/php/Lib.hx index 49e047aa..91b1c2e1 100644 --- a/std/php/Lib.hx +++ b/std/php/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,11 @@ */ package php; +/** + Platform-specific PHP Library. Provides some platform-specific functions + for the PHP target, such as conversion from Haxe types to native types + and vice-versa. +**/ class Lib { /** Print the specified value on the default output. @@ -30,32 +35,41 @@ class Lib { } /** - Print the specified value on the default output followed by a newline character. + Print the specified value on the default output followed by + a newline character. **/ public static function println( v : Dynamic ) : Void { print(v); print("\n"); } + /** + Displays structured information about one or more expressions + that includes its type and value. Arrays and objects are + explored recursively with values indented to show structure. + */ public static function dump(v : Dynamic) : Void { untyped __call__("var_dump", v); } /** - Serialize using native PHP serialization. This will return a Binary string that can be - stored for long term usage. + Serialize using native PHP serialization. This will return a binary + `String` that can be stored for long term usage. **/ public static function serialize( v : Dynamic ) : String { return untyped __call__("serialize", v); } /** - Unserialize a string using native PHP serialization. See [serialize]. + Unserialize a `String` using native PHP serialization. See `php.Lib.serialize()`. **/ public static function unserialize( s : String ) : Dynamic { return untyped __call__("unserialize", s); } + /** + Find out whether an extension is loaded. + */ public static function extensionLoaded(name : String) { return untyped __call__("extension_loaded", name); } @@ -64,6 +78,9 @@ class Lib { return untyped __php__("(0 == strncasecmp(PHP_SAPI, 'cli', 3))"); } + /** + Output file content from the given file name. + */ public static function printFile(file : String) { return untyped __call__("fpassthru", __call__("fopen", file, "r")); } @@ -99,7 +116,7 @@ class Lib { /** * See the documentation for the equivalent PHP function for details on usage: - * http://php.net/manual/en/function.mail.php + * * @param to * @param subject * @param message @@ -160,17 +177,17 @@ class Lib { //Calling this function will put all types present in the specified types in the $_hx_types_array _hx_build_paths($pathToLib, $_hx_types_array, array(), $prefix); - for($i=0;$i__qname__, php_Boot::$qtypes)) { @@ -179,4 +196,4 @@ class Lib { } "); } -} \ No newline at end of file +} diff --git a/std/php/NativeArray.hx b/std/php/NativeArray.hx index 22ab6a57..0028ad2a 100644 --- a/std/php/NativeArray.hx +++ b/std/php/NativeArray.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/NativeString.hx b/std/php/NativeString.hx index a9f505b4..487cac2b 100644 --- a/std/php/NativeString.hx +++ b/std/php/NativeString.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/NativeXml.hx b/std/php/NativeXml.hx index 313acc60..6f440a73 100644 --- a/std/php/NativeXml.hx +++ b/std/php/NativeXml.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/Session.hx b/std/php/Session.hx index 96f7092a..6d017dc6 100644 --- a/std/php/Session.hx +++ b/std/php/Session.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -20,8 +20,10 @@ * DEALINGS IN THE SOFTWARE. */ package php; + /** -* TODO: TEST IT! + Session consists of a way to preserve certain data across + subsequent accesses. */ class Session { public static function getCacheLimiter() { @@ -163,4 +165,4 @@ enum CacheLimiter { Private; NoCache; PrivateNoExpire; -} \ No newline at end of file +} diff --git a/std/php/Web.hx b/std/php/Web.hx index 6e3c650e..03d5f0d8 100644 --- a/std/php/Web.hx +++ b/std/php/Web.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -32,7 +32,7 @@ class Web { /** Returns the GET and POST parameters. **/ - public static function getParams() { + public static function getParams() : Map { #if force_std_separator var a : NativeArray = untyped __php__("$_POST"); if(untyped __call__("get_magic_quotes_gpc")) @@ -57,8 +57,8 @@ class Web { /** Returns an Array of Strings built using GET / POST values. - If you have in your URL the parameters [a[]=foo;a[]=hello;a[5]=bar;a[3]=baz] then - [php.Web.getParamValues("a")] will return [["foo","hello",null,"baz",null,"bar"]] + If you have in your URL the parameters `a[]=foo;a[]=hello;a[5]=bar;a[3]=baz` then + `php.Web.getParamValues("a")` will return `["foo","hello",null,"baz",null,"bar"]`. **/ public static function getParamValues( param : String ) : Array { var reg = new EReg("^"+param+"(\\[|%5B)([0-9]*?)(\\]|%5D)=(.*?)$", ""); @@ -97,7 +97,7 @@ class Web { } /** - Returns the local server host name + Returns the local server host name. **/ public static inline function getHostName() : String { return untyped __php__("$_SERVER['SERVER_NAME']"); @@ -111,7 +111,7 @@ class Web { } /** - Returns the original request URL (before any server internal redirections) + Returns the original request URL (before any server internal redirections). **/ public static function getURI() : String { var s : String = untyped __php__("$_SERVER['REQUEST_URI']"); @@ -119,7 +119,7 @@ class Web { } /** - Tell the client to redirect to the given url ("Location" header) + Tell the client to redirect to the given url ("Location" header). **/ public static function redirect( url : String ) { untyped __call__('header', "Location: " + url); @@ -134,7 +134,7 @@ class Web { } /** - Set the HTTP return code. Same remark as setHeader. + Set the HTTP return code. Same remark as `php.Web.setHeader()`. See status code explanation here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html **/ public static function setReturnCode( r : Int ) { @@ -189,7 +189,6 @@ class Web { Retrieve a client header value sent with the request. **/ public static function getClientHeader( k : String ) : String { - //Remark : PHP puts all headers in uppercase and replaces - with _, we deal with that here var k = StringTools.replace(k.toUpperCase(),"-","_"); for(i in getClientHeaders()) { if(i.header == k) @@ -215,12 +214,21 @@ class Web { _client_headers.add({ header : k, value : h.get(k)}); } } + // and these(issue #5270) + if(untyped __php__("isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])")) { + _client_headers.add({header: 'AUTHORIZATION', value: untyped __php__("(string)$_SERVER['REDIRECT_HTTP_AUTHORIZATION']")}); + } else if(untyped __php__("isset($_SERVER['PHP_AUTH_USER'])")) { + var basic_pass = untyped __php__("isset($_SERVER['PHP_AUTH_PW']) ? (string)$_SERVER['PHP_AUTH_PW'] : ''"); + _client_headers.add({header: 'AUTHORIZATION', value: 'Basic ' + untyped __php__("base64_encode($_SERVER['PHP_AUTH_USER'] + ':' + $basic_pass)")}); + } else if(untyped __php__("isset($_SERVER['PHP_AUTH_DIGEST'])")) { + _client_headers.add({header: 'AUTHORIZATION', value: untyped __php__("(string)$_SERVER['PHP_AUTH_DIGEST']")}); + } } return _client_headers; } /** - Returns all the GET parameters String + Returns all the GET parameters `String` **/ public static function getParamsString() : String { if(untyped __call__("isset", __var__("_SERVER", "QUERY_STRING"))) @@ -234,8 +242,8 @@ class Web { being application/x-www-form-urlencoded and is stored into the getParams hashtable. POST Data is maximimized to 256K unless the content type is multipart/form-data. In that - case, you will have to use [getMultipart] or [parseMultipart] - methods. + case, you will have to use `php.Web.getMultipart()` or + `php.Web.parseMultipart()` methods. **/ public static function getPostData() { var h = untyped __call__("fopen", "php://input", "r"); @@ -253,7 +261,8 @@ class Web { /** Returns an hashtable of all Cookies sent by the client. - Modifying the hashtable will not modify the cookie, use setCookie instead. + Modifying the hashtable will not modify the cookie, use `php.Web.setCookie()` + instead. **/ public static function getCookies():Map { return Lib.hashOfAssociativeArray(untyped __php__("$_COOKIE")); @@ -261,7 +270,7 @@ class Web { /** - Set a Cookie value in the HTTP headers. Same remark as setHeader. + Set a Cookie value in the HTTP headers. Same remark as `php.Web.setHeader()`. **/ public static function setCookie( key : String, value : String, ?expire: Date, ?domain: String, ?path: String, ?secure: Bool, ?httpOnly: Bool ) { var t = expire == null ? 0 : Std.int(expire.getTime()/1000.0); @@ -316,9 +325,9 @@ class Web { } /** - Parse the multipart data. Call [onPart] when a new part is found + Parse the multipart data. Call `onPart` when a new part is found with the part name and the filename if present - and [onData] when some part data is readed. You can this way + and `onData` when some part data is read. You can this way directly save the data on hard drive in the case of a file upload. **/ public static function parseMultipart( onPart : String -> String -> Void, onData : Bytes -> Int -> Int -> Void ) : Void { diff --git a/std/php/_std/Date.hx b/std/php/_std/Date.hx index 95e3e95b..8e515b98 100644 --- a/std/php/_std/Date.hx +++ b/std/php/_std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/EReg.hx b/std/php/_std/EReg.hx index 41fdc82e..fe754ca5 100644 --- a/std/php/_std/EReg.hx +++ b/std/php/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -90,7 +90,7 @@ public function replace( s : String, by : String ) : String { by = untyped __call__("str_replace", "\\$", "\\\\$", by); by = untyped __call__("str_replace", "$$", "\\$", by); - untyped __php__("if(!preg_match('/\\\\([^?].+?\\\\)/', $this->re)) $by = preg_replace('/\\$(\\d+)/', '\\\\\\$\\1', $by)"); + untyped __php__("if(!preg_match('/\\\\([^?].*?\\\\)/', $this->re)) $by = preg_replace('/\\$(\\d+)/', '\\\\\\$\\1', $by)"); return untyped __call__("preg_replace", re, by, s, global ? -1 : 1); } diff --git a/std/php/_std/List.hx b/std/php/_std/List.hx index 5e6cefb7..92de70db 100644 --- a/std/php/_std/List.hx +++ b/std/php/_std/List.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/Math.hx b/std/php/_std/Math.hx index f026b353..344a8685 100644 --- a/std/php/_std/Math.hx +++ b/std/php/_std/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/Reflect.hx b/std/php/_std/Reflect.hx index 98f53df3..8572bd78 100644 --- a/std/php/_std/Reflect.hx +++ b/std/php/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -40,17 +40,17 @@ if (untyped __php__("isset($cls_vars['__properties__']) && isset($cls_vars['__properties__']['get_'.$field]) && ($field = $cls_vars['__properties__']['get_'.$field])")) return untyped __php__("$o->$field()"); else - return untyped __php__("$o->$field"); + return untyped __call__("_hx_field", o, field); } - public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void untyped { + public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void { if (null == o) return null; var cls : String = Std.is(o, Class) ? untyped __php__("$o->__tname__") : untyped __call__("get_class", o); var cls_vars : php.NativeArray = untyped __call__("get_class_vars", cls); if (untyped __php__("isset($cls_vars['__properties__']) && isset($cls_vars['__properties__']['set_'.$field]) && ($field = $cls_vars['__properties__']['set_'.$field])")) - return untyped __php__("$o->$field($value)"); + untyped __php__("$o->$field($value)"); else - return untyped __php__("$o->$field = $value"); + untyped __setfield__(o, field, value); } public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array ) : Dynamic untyped { @@ -86,12 +86,14 @@ if( v == null ) return false; if(untyped __call__("is_object", v)) - return untyped __php__("$v instanceof _hx_anonymous") || Type.getClass(v) != null; + return untyped __php__("$v instanceof _hx_anonymous") || Type.getClass(v) != null + || untyped __php__("$v instanceof _hx_class") + || untyped __php__("$v instanceof _hx_enum"); return untyped __php__("is_string($v) && !_hx_is_lambda($v)"); } public static function isEnumValue( v : Dynamic ) : Bool { - return untyped __php__("$v instanceof _hx_enum"); + return untyped __php__("$v instanceof Enum"); } public static function deleteField( o : Dynamic, field : String ) : Bool { diff --git a/std/php/_std/Std.hx b/std/php/_std/Std.hx index 5401ac9c..a26dca49 100644 --- a/std/php/_std/Std.hx +++ b/std/php/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -41,26 +41,44 @@ } public static function parseInt( x : String ) : Null { - untyped if (!__call__("is_numeric", x)) { - var matches = null; - __call__('preg_match', '/^-?\\d+/', x, matches); - return __call__("count", matches) == 0 ? null : __call__('intval', matches[0]); - } else - return x.substr(0, 2).toLowerCase() == "0x" ? __php__("(int) hexdec(substr($x, 2))") : __php__("intval($x)"); + x = untyped __call__("ltrim", x); + var firstCharIndex = (x.charAt(0) == '-' ? 1 : 0); + var firstCharCode = x.charCodeAt(firstCharIndex); + if (!isDigitCode(firstCharCode)) { + return null; + } + var secondChar = x.charAt(firstCharIndex + 1); + if (secondChar == 'x' || secondChar == 'X') { + return untyped __call__("intval", x, 0); + } else { + return untyped __call__("intval", x, 10); + } } public static function parseFloat( x : String ) : Float { - var v : Float = untyped __call__("floatval", x); - untyped if (v==0.0) { - x=untyped __call__("rtrim", x); - v=untyped __call__("floatval", x); - if (v == 0.0 && !__call__("is_numeric", x)) v = untyped __call__("acos", 1.01); + var result = untyped __call__("floatval", x); + if (untyped __php__("$result != 0")) return result; + + x = untyped __call__("ltrim", x); + var firstCharIndex = (x.charAt(0) == '-' ? 1 : 0); + var charCode = x.charCodeAt(firstCharIndex); + + if (charCode == '.'.code) { + charCode = x.charCodeAt(firstCharIndex + 1); + } + + if (isDigitCode(charCode)) { + return 0.0; + } else { + return Math.NaN; } - return v; } public static function random( x : Int ) : Int { return untyped x <= 0 ? 0 : __call__("mt_rand", 0, x-1); } + static inline function isDigitCode( charCode:Null ) : Bool { + return charCode != null && charCode >= '0'.code && charCode <= '9'.code; + } } diff --git a/std/php/_std/StringBuf.hx b/std/php/_std/StringBuf.hx index 76d12266..339caf59 100644 --- a/std/php/_std/StringBuf.hx +++ b/std/php/_std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/StringTools.hx b/std/php/_std/StringTools.hx index afb1a437..786e723a 100644 --- a/std/php/_std/StringTools.hx +++ b/std/php/_std/StringTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -95,4 +95,104 @@ return untyped __physeq__(c, 0); } + /** + Returns a String that can be used as a single command line argument + on Unix. + The input will be quoted, or escaped if necessary. + */ + public static function quoteUnixArg(argument:String):String { + // Based on cpython's shlex.quote(). + // https://hg.python.org/cpython/file/a3f076d4f54f/Lib/shlex.py#l278 + + if (argument == "") + return "''"; + + if (!~/[^a-zA-Z0-9_@%+=:,.\/-]/.match(argument)) + return argument; + + // use single quotes, and put single quotes into double quotes + // the string $'b is then quoted as '$'"'"'b' + return "'" + replace(argument, "'", "'\"'\"'") + "'"; + } + + /** + Character codes of the characters that will be escaped by `quoteWinArg(_, true)`. + */ + public static var winMetaCharacters = [" ".code, "(".code, ")".code, "%".code, "!".code, "^".code, "\"".code, "<".code, ">".code, "&".code, "|".code, "\n".code, "\r".code]; + + /** + Returns a String that can be used as a single command line argument + on Windows. + The input will be quoted, or escaped if necessary, such that the output + will be parsed as a single argument using the rule specified in + http://msdn.microsoft.com/en-us/library/ms880421 + + Examples: + ``` + quoteWinArg("abc") == "abc"; + quoteWinArg("ab c") == '"ab c"'; + ``` + */ + public static function quoteWinArg(argument:String, escapeMetaCharacters:Bool):String { + // If there is no space, tab, back-slash, or double-quotes, and it is not an empty string. + if (!~/^[^ \t\\"]+$/.match(argument)) { + + // Based on cpython's subprocess.list2cmdline(). + // https://hg.python.org/cpython/file/50741316dd3a/Lib/subprocess.py#l620 + + var result = new StringBuf(); + var needquote = argument.indexOf(" ") != -1 || argument.indexOf("\t") != -1 || argument == ""; + + if (needquote) + result.add('"'); + + var bs_buf = new StringBuf(); + for (i in 0...argument.length) { + switch (argument.charCodeAt(i)) { + case "\\".code: + // Don't know if we need to double yet. + bs_buf.add("\\"); + case '"'.code: + // Double backslashes. + var bs = bs_buf.toString(); + result.add(bs); + result.add(bs); + bs_buf = new StringBuf(); + result.add('\\"'); + case c: + // Normal char + if (bs_buf.length > 0) { + result.add(bs_buf.toString()); + bs_buf = new StringBuf(); + } + result.addChar(c); + } + } + + // Add remaining backslashes, if any. + result.add(bs_buf.toString()); + + if (needquote) { + result.add(bs_buf.toString()); + result.add('"'); + } + + argument = result.toString(); + } + + if (escapeMetaCharacters) { + var result = new StringBuf(); + for (i in 0...argument.length) { + var c = argument.charCodeAt(i); + if (winMetaCharacters.indexOf(c) >= 0) { + result.addChar("^".code); + } + result.addChar(c); + } + return result.toString(); + } else { + return argument; + } + } + } diff --git a/std/php/_std/Sys.hx b/std/php/_std/Sys.hx index afa56106..8095ecf9 100644 --- a/std/php/_std/Sys.hx +++ b/std/php/_std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -35,7 +35,8 @@ } public static function getEnv( s : String ) : String { - return untyped __call__("getenv", s); + var ret:Dynamic = untyped __call__("getenv", s); + return ret == false ? null : ret; } public static function putEnv( s : String, v : String ) : Void { @@ -69,27 +70,18 @@ return s; } - static function escapeArgument( arg : String ) : String { - var ok = true; - for( i in 0...arg.length ) - switch( arg.charCodeAt(i) ) { - case ' '.code, '\t'.code, '"'.code, '&'.code, '|'.code, '<'.code, '>'.code, '#'.code , ';'.code, '*'.code, '?'.code, '('.code, ')'.code, '{'.code, '}'.code, '$'.code: - ok = false; - case 0, 13, 10: // [eof] [cr] [lf] - arg = arg.substr(0,i); - } - if( ok ) - return arg; - return '"'+arg.split('\\').join("\\\\").split('"').join('\\"')+'"'; - } - public static function command( cmd : String, ?args : Array ) : Int { - if( args != null ) { - cmd = escapeArgument(cmd); - for( a in args ) - cmd += " "+escapeArgument(a); + if (args != null) { + switch (systemName()) { + case "Windows": + cmd = [ + for (a in [StringTools.replace(cmd, "/", "\\")].concat(args)) + StringTools.quoteWinArg(a, true) + ].join(" "); + case _: + cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" "); + } } - if (systemName() == "Windows") cmd = '"$cmd"'; var result = 0; untyped __call__("system", cmd, result); return result; @@ -107,24 +99,30 @@ return untyped __call__("microtime", true) - __php__("$_SERVER['REQUEST_TIME']"); } - public static function executablePath() : String { + @:deprecated("Use programPath instead") public static function executablePath() : String { return untyped __php__("$_SERVER['SCRIPT_FILENAME']"); } + // It has to be initialized before any call to Sys.setCwd()... + static var _programPath = sys.FileSystem.fullPath(untyped __php__("$_SERVER['SCRIPT_FILENAME']")); + public static function programPath() : String { + return _programPath; + } + public static function environment() : Map { return php.Lib.hashOfAssociativeArray(untyped __php__("$_SERVER")); } public static function stdin() : haxe.io.Input { - return untyped new sys.io.FileInput(__call__('fopen', 'php://stdin', "r")); + return untyped new sys.io.FileInput(__php__("STDIN")); } public static function stdout() : haxe.io.Output { - return untyped new sys.io.FileOutput(__call__('fopen', 'php://stdout', "w")); + return untyped new sys.io.FileOutput(__php__("STDOUT")); } public static function stderr() : haxe.io.Output { - return untyped new sys.io.FileOutput(__call__('fopen', 'php://stderr', "w")); + return untyped new sys.io.FileOutput(__php__("STDERR")); } public static function getChar( echo : Bool ) : Int { @@ -134,4 +132,4 @@ return v; } -} \ No newline at end of file +} diff --git a/std/php/_std/Type.hx b/std/php/_std/Type.hx index da726318..a516c903 100644 --- a/std/php/_std/Type.hx +++ b/std/php/_std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,6 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ + enum ValueType { TNull; TInt; @@ -183,7 +184,7 @@ enum ValueType { if($cls->getName() == $c->__tname__ && ($name = $p->getName()) !== '__properties__') $r[] = $name; } "); - return untyped __php__("new _hx_array(array_unique($r))"); + return untyped __php__("new _hx_array(array_values(array_unique($r)))"); } public static function getEnumConstructs( e : Enum ) : Array untyped { diff --git a/std/php/_std/haxe/Json.hx b/std/php/_std/haxe/Json.hx index 8e1b1c5e..a4a0c9e3 100644 --- a/std/php/_std/haxe/Json.hx +++ b/std/php/_std/haxe/Json.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -42,6 +42,9 @@ class Json { static function phpJsonDecode(json:String):Dynamic { var val = untyped __call__("json_decode", json); + if (val == null && untyped __php__("json_last_error() != JSON_ERROR_NONE")) { + throw untyped __call__("json_last_error_msg"); + } return convertAfterDecode(val); } @@ -73,7 +76,9 @@ class Json { var arr:php.NativeArray; if (untyped __call__("is_object", val)) { switch (untyped __call__("get_class", val)) { - case "_hx_anonymous", "stdClass" : arr = php.Lib.associativeArrayOfObject(val); + case "_hx_anonymous", "stdClass" : + arr = php.Lib.associativeArrayOfObject(val); + if(untyped __php__('!{0}', arr)) return {}; case "_hx_array" : arr = php.Lib.toPhpArray(val); case "Date" : return Std.string(val); //.split(" ").join("T"); //better with "T"? case "HList" : arr = php.Lib.toPhpArray(Lambda.array(val)); //convert List to array? diff --git a/std/php/_std/haxe/Resource.hx b/std/php/_std/haxe/Resource.hx index c04df4ca..afd5d38b 100644 --- a/std/php/_std/haxe/Resource.hx +++ b/std/php/_std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -49,11 +49,19 @@ class Resource { } public static function getString( name : String ) : String { - return sys.io.File.getContent(getPath(name)); + var path = getPath(name); + return if (!sys.FileSystem.exists(path)) + null; + else + sys.io.File.getContent(path); } public static function getBytes( name : String ) : haxe.io.Bytes { - return sys.io.File.getBytes(getPath(name)); + var path = getPath(name); + return if (!sys.FileSystem.exists(path)) + null; + else + sys.io.File.getBytes(path); } } diff --git a/std/php/_std/haxe/Utf8.hx b/std/php/_std/haxe/Utf8.hx index 4f225e8d..24881b7a 100644 --- a/std/php/_std/haxe/Utf8.hx +++ b/std/php/_std/haxe/Utf8.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/haxe/ds/IntMap.hx b/std/php/_std/haxe/ds/IntMap.hx index 5a5f0d4d..79643b5c 100644 --- a/std/php/_std/haxe/ds/IntMap.hx +++ b/std/php/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/haxe/ds/ObjectMap.hx b/std/php/_std/haxe/ds/ObjectMap.hx index 6d890ec4..0bf79c88 100644 --- a/std/php/_std/haxe/ds/ObjectMap.hx +++ b/std/php/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/haxe/ds/StringMap.hx b/std/php/_std/haxe/ds/StringMap.hx old mode 100755 new mode 100644 index 35e58532..3f27ba09 --- a/std/php/_std/haxe/ds/StringMap.hx +++ b/std/php/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/haxe/zip/Compress.hx b/std/php/_std/haxe/zip/Compress.hx new file mode 100644 index 00000000..d1cf8236 --- /dev/null +++ b/std/php/_std/haxe/zip/Compress.hx @@ -0,0 +1,55 @@ +/* + * Copyright (C)2005-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 haxe.zip; + +@:coreApi +class Compress { + + private var level : Int; + + public function new( level : Int ) : Void { + this.level = level; + } + + public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { + var input = src.sub( srcPos , src.length - srcPos ); + var data = run( input , level ); + dst.blit( dstPos , data , 0 , data.length ); + + return { + done: true, + read: input.length, + write: data.length + }; + } + + public function setFlushMode( f : FlushMode ) : Void { + } + + public function close() : Void { + } + + public static function run( s : haxe.io.Bytes, level : Int ) : haxe.io.Bytes { + var c = untyped __call__("gzcompress", s.toString(), level); + return haxe.io.Bytes.ofString(c); + } +} diff --git a/std/php/_std/haxe/zip/Uncompress.hx b/std/php/_std/haxe/zip/Uncompress.hx new file mode 100644 index 00000000..1a16bcb2 --- /dev/null +++ b/std/php/_std/haxe/zip/Uncompress.hx @@ -0,0 +1,45 @@ +/* + * Copyright (C)2005-2012 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 haxe.zip; + +class Uncompress { + + public function new( ?windowBits : Int ) { + throw "Not implemented for this platform"; + } + + public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { + return null; + } + + public function setFlushMode( f : FlushMode ) { + } + + public function close() { + } + + public static function run( src : haxe.io.Bytes, ?bufsize : Int ) : haxe.io.Bytes { + var c = untyped __call__("gzuncompress", src.toString()); + return haxe.io.Bytes.ofString(c); + } + +} diff --git a/std/php/_std/sys/FileSystem.hx b/std/php/_std/sys/FileSystem.hx index 308013a5..84c8030d 100644 --- a/std/php/_std/sys/FileSystem.hx +++ b/std/php/_std/sys/FileSystem.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -96,11 +96,11 @@ class FileSystem { } public static inline function deleteFile( path : String ) : Void { - untyped __call__("@unlink", path); + untyped __call__("unlink", path); } public static inline function deleteDirectory( path : String ) : Void { - untyped __call__("@rmdir", path); + untyped __call__("rmdir", path); } public static function readDirectory( path : String ) : Array { diff --git a/std/php/_std/sys/db/Mysql.hx b/std/php/_std/sys/db/Mysql.hx index 7ca97c62..cc607411 100644 --- a/std/php/_std/sys/db/Mysql.hx +++ b/std/php/_std/sys/db/Mysql.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/sys/db/Sqlite.hx b/std/php/_std/sys/db/Sqlite.hx index 0e9e7b5b..a136696f 100644 --- a/std/php/_std/sys/db/Sqlite.hx +++ b/std/php/_std/sys/db/Sqlite.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/sys/io/File.hx b/std/php/_std/sys/io/File.hx index 45de45f7..0021be1d 100644 --- a/std/php/_std/sys/io/File.hx +++ b/std/php/_std/sys/io/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/sys/io/FileInput.hx b/std/php/_std/sys/io/FileInput.hx index e505c7d6..1085f301 100644 --- a/std/php/_std/sys/io/FileInput.hx +++ b/std/php/_std/sys/io/FileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/sys/io/FileOutput.hx b/std/php/_std/sys/io/FileOutput.hx index 2e54c5ed..f30e16eb 100644 --- a/std/php/_std/sys/io/FileOutput.hx +++ b/std/php/_std/sys/io/FileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php/_std/sys/io/Process.hx b/std/php/_std/sys/io/Process.hx index 0f788857..543303fd 100644 --- a/std/php/_std/sys/io/Process.hx +++ b/std/php/_std/sys/io/Process.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -85,14 +85,25 @@ class Process { public var stderr(default,null) : haxe.io.Input; public var stdin(default,null) : haxe.io.Output; - public function new( cmd : String, args : Array ) : Void { + public function new( cmd : String, ?args : Array ) : Void { var pipes = untyped __call__("array"); var descriptorspec = untyped __php__("array( array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w') )"); - p = untyped __call__('proc_open', cmd+sargs(args), descriptorspec, pipes); + if (args != null) { + switch (Sys.systemName()) { + case "Windows": + cmd = [ + for (a in [StringTools.replace(cmd, "/", "\\")].concat(args)) + StringTools.quoteWinArg(a, true) + ].join(" "); + case _: + cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" "); + } + } + p = untyped __call__('proc_open', cmd, descriptorspec, pipes); if(untyped __physeq__(p, false)) throw "Process creation failure : "+cmd; stdin = new Stdin( pipes[0]); stdout = new Stdout(pipes[1]); @@ -104,18 +115,8 @@ class Process { st = untyped __call__('proc_get_status', p); replaceStream(stderr); replaceStream(stdout); - cl = untyped __call__('proc_close', p); - } - - function sargs(args : Array) : String { - var b = ''; - for(arg in args) { - arg = arg.split('"').join('\"'); - if(arg.indexOf(' ') >= 0) - arg = '"'+arg+'"'; - b += ' '+arg; - } - return b; + if(null == cl) + cl = untyped __call__('proc_close', p); } public function getPid() : Int { @@ -138,11 +139,12 @@ class Process { untyped input.p = fp; } - public function exitCode() : Int { + public function exitCode( block : Bool = true ) : Null { if (null == cl) { st = untyped __call__('proc_get_status', p); while(st[untyped 'running']) { + if( block == false ) return null; Sys.sleep(0.01); st = untyped __call__('proc_get_status', p); } diff --git a/std/php/_std/sys/net/Host.hx b/std/php/_std/sys/net/Host.hx index 923cbe12..b9a0c89f 100644 --- a/std/php/_std/sys/net/Host.hx +++ b/std/php/_std/sys/net/Host.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,10 +24,13 @@ package sys.net; @:coreApi class Host { + public var host(default,null) : String; + private var _ip : String; public var ip(default,null) : Int; public function new( name : String ) : Void { + host = name; if(~/^(\d{1,3}\.){3}\d{1,3}$/.match(name)) { _ip = name; } else { diff --git a/std/php/_std/sys/net/Socket.hx b/std/php/_std/sys/net/Socket.hx index 3b20052d..0afbab10 100644 --- a/std/php/_std/sys/net/Socket.hx +++ b/std/php/_std/sys/net/Socket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -66,7 +66,7 @@ class Socket { public function connect(host : Host, port : Int) : Void { var errs = null; var errn = null; - var r = untyped __call__('stream_socket_client', protocol + '://' +host._ip + ':' + port, errn, errs); + var r = untyped __call__('stream_socket_client', protocol + '://' +host.host + ':' + port, errn, errs); Socket.checkError(r, errn, errs); __s = cast r; assignHandler(); diff --git a/std/php/db/PDO.hx b/std/php/db/PDO.hx index c5de9fb4..ec4c2fb6 100644 --- a/std/php/db/PDO.hx +++ b/std/php/db/PDO.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -138,7 +138,7 @@ private class PDOConnection implements Connection { public function quote( s : String ) { if( s.indexOf("\000") >= 0 ) - return "x'"+base16_encode(s)+"'"; + return "x'"+untyped __call__('bin2hex', s)+"'"; return pdo.quote(s); } @@ -170,12 +170,6 @@ private class PDOConnection implements Connection { public function rollback() { pdo.rollBack(); } - - function base16_encode(str : String) { - str = untyped __call__("unpack", "H"+(2 * str.length), str); - str = untyped __call__("chunk_split", untyped str[1]); - return str; - } } private class TypeStrategy { diff --git a/std/php/net/SslSocket.hx b/std/php/net/SslSocket.hx index 2f69abc2..c3f6a47a 100644 --- a/std/php/net/SslSocket.hx +++ b/std/php/net/SslSocket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/php7/ArrayAccess.hx b/std/php7/ArrayAccess.hx new file mode 100644 index 00000000..a69539d8 --- /dev/null +++ b/std/php7/ArrayAccess.hx @@ -0,0 +1,13 @@ +package php; + +/** + Native PHP interface. + @see http://php.net/manual/en/class.arrayaccess.php +**/ +@:native('ArrayAccess') +extern interface ArrayAccess { + function offsetExists( offset:K ) : Bool; + function offsetGet( offset:K ) : V; + function offsetSet( offset:K, value:V ) : Void; + function offsetUnset( offset:K ) : Void; +} \ No newline at end of file diff --git a/std/php7/Boot.hx b/std/php7/Boot.hx new file mode 100644 index 00000000..502c80f4 --- /dev/null +++ b/std/php7/Boot.hx @@ -0,0 +1,850 @@ +/* + * Copyright (C)2005-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 php; + +import haxe.PosInfos; + +using php.Global; + +/** + Various Haxe->PHP compatibility utilities. + You should not use this class directly. +**/ +@:keep +@:dox(hide) +class Boot { + /** List of Haxe classes registered by their PHP class names */ + @:protected static var aliases = new NativeAssocArray(); + /** Cache of HxClass instances */ + @:protected static var classes = new NativeAssocArray(); + /** List of getters (for Reflect) */ + @:protected static var getters = new NativeAssocArray>(); + /** List of setters (for Reflect) */ + @:protected static var setters = new NativeAssocArray>(); + /** Metadata storage */ + @:protected static var meta = new NativeAssocArray<{}>(); + + /** + Initialization stuff. + This method is called once before invoking any Haxe-generated user code. + **/ + static function __init__() { + if (!Global.defined('HAXE_CUSTOM_ERROR_HANDLER') || !Const.HAXE_CUSTOM_ERROR_HANDLER) { + var previousLevel = Global.error_reporting(Const.E_ALL); + var previousHandler = Global.set_error_handler( + function (errno:Int, errstr:String, errfile:String, errline:Int) { + if (Global.error_reporting() & errno == 0) { + return false; + } + throw new ErrorException(errstr, 0, errno, errfile, errline); + } + ); + //Already had user-defined handler. Return it. + if (previousHandler != null) { + Global.error_reporting(previousLevel); + Global.set_error_handler(previousHandler); + } + } + } + + /** + Returns root namespace based on a value of `--php-prefix` compiler flag. + Returns empty string if no `--php-prefix` provided. + **/ + public static inline function getPrefix() : String { + return untyped __php__('self::PHP_PREFIX'); + } + + /** + Register list of getters to be able to call getters using reflection + **/ + public static function registerGetters( phpClassName:String, list:NativeAssocArray ) : Void { + getters[phpClassName] = list; + } + + /** + Register list of setters to be able to call getters using reflection + **/ + public static function registerSetters( phpClassName:String, list:NativeAssocArray ) : Void { + setters[phpClassName] = list; + } + + /** + Check if specified property has getter + **/ + public static function hasGetter( phpClassName:String, property:String ) : Bool { + ensureLoaded(phpClassName); + + var has = false; + var phpClassName:haxe.extern.EitherType = phpClassName; + do { + has = Global.isset(getters[phpClassName][property]); + phpClassName = Global.get_parent_class(phpClassName); + } while (!has && phpClassName != false && Global.class_exists(phpClassName)); + + return has; + } + + /** + Check if specified property has setter + **/ + public static function hasSetter( phpClassName:String, property:String ) : Bool { + ensureLoaded(phpClassName); + + var has = false; + var phpClassName:haxe.extern.EitherType = phpClassName; + do { + has = Global.isset(setters[phpClassName][property]); + phpClassName = Global.get_parent_class(phpClassName); + } while (!has && phpClassName != false && Global.class_exists(phpClassName)); + + return has; + } + + /** + Save metadata for specified class + **/ + public static function registerMeta( phpClassName:String, data:Dynamic ) : Void { + meta[phpClassName] = data; + } + + /** + Retrieve metadata for specified class + **/ + public static function getMeta( phpClassName:String ) : Null { + ensureLoaded(phpClassName); + return Global.isset(meta[phpClassName]) ? meta[phpClassName] : null; + } + + /** + Associate PHP class name with Haxe class name + **/ + public static function registerClass( phpClassName:String, haxeClassName:String ) : Void { + aliases[phpClassName] = haxeClassName; + } + + /** + Get Class instance for PHP fully qualified class name (E.g. '\some\pack\MyClass') + It's always the same instance for the same `phpClassName` + **/ + public static function getClass( phpClassName:String ) : HxClass { + if (phpClassName.charAt(0) == '\\') { + phpClassName = phpClassName.substr(1); + } + if (!Global.isset(classes[phpClassName])) { + classes[phpClassName] = new HxClass(phpClassName); + } + + return classes[phpClassName]; + } + + /** + Returns Class + **/ + public static inline function getHxAnon() : HxClass { + return cast HxAnon; + } + + /** + Returns Class + **/ + public static inline function getHxClass() : HxClass { + return cast HxClass; + } + + /** + Returns either Haxe class name for specified `phpClassName` or (if no such Haxe class registered) `phpClassName`. + **/ + public static function getClassName( phpClassName:String ) : String { + var hxClass = getClass(phpClassName); + var name = getHaxeName(hxClass); + return (name == null ? hxClass.phpClassName : name); + } + + /** + Returns original Haxe fully qualified class name for this type (if exists) + **/ + public static function getHaxeName( hxClass:HxClass) : Null { + switch (hxClass.phpClassName) { + case 'Int': return 'Int'; + case 'String': return 'String'; + case 'Bool': return 'Bool'; + case 'Float': return 'Float'; + case 'Class': return 'Class'; + case 'Enum': return 'Enum'; + case 'Dynamic': return 'Dynamic'; + case _: + } + + inline function exists() return Global.isset(aliases[hxClass.phpClassName]); + + if (exists()) { + return aliases[hxClass.phpClassName]; + } else if (Global.class_exists(hxClass.phpClassName) && exists()) { + return aliases[hxClass.phpClassName]; + } else if (Global.interface_exists(hxClass.phpClassName) && exists()) { + return aliases[hxClass.phpClassName]; + } + + return null; + } + + /** + Find corresponding PHP class name. + Returns `null` if specified class does not exist. + **/ + public static function getPhpName( haxeName:String ) : Null { + var prefix = getPrefix(); + var phpParts = (prefix.length == 0 ? [] : [prefix]); + + var haxeParts = haxeName.split('.'); + for (part in haxeParts) { + switch (part.toLowerCase()) { + case "__halt_compiler" | "abstract" | "and" | "array" | "as" | "break" | "callable" | "case" | "catch" | "class" + | "clone" | "const" | "continue" | "declare" | "default" | "die" | "do" | "echo" | "else" | "elseif" | "empty" + | "enddeclare" | "endfor" | "endforeach" | "endif" | "endswitch" | "endwhile" | "eval" | "exit" | "extends" + | "final" | "finally" | "for" | "foreach" | "function" | "global" | "goto" | "if" | "implements" | "include" + | "include_once" | "instanceof" | "insteadof" | "interface" | "isset" | "list" | "namespace" | "new" | "or" + | "print" | "private" | "protected" | "public" | "require" | "require_once" | "return" | "static" | "switch" + | "throw" | "trait" | "try" | "unset" | "use" | "var" | "while" | "xor" | "yield" | "__class__" | "__dir__" + | "__file__" | "__function__" | "__line__" | "__method__" | "__trait__" | "__namespace__" | "int" | "float" + | "bool" | "string" | "true" | "false" | "null" | "parent" | "void" | "iterable": + part += '_hx'; + case _: + } + phpParts.push(part); + } + + return phpParts.join('\\'); + } + + /** + Creates Haxe-compatible closure. + @param type `this` for instance methods; full php class name for static methods + @param func Method name + **/ + public static inline function closure( target:Dynamic, func:Dynamic ) : HxClosure { + return new HxClosure(target, func); + } + + /** + Unsafe cast to HxClosure + **/ + public static inline function castClosure(value:Dynamic) : HxClosure { + return value; + } + + /** + Returns `Class` for `HxClosure` + **/ + public static inline function closureHxClass() : HxClass { + return cast HxClosure; + } + + /** + Implementation for `cast(value, Class)` + @throws HxException if `value` cannot be casted to this type + **/ + public static function typedCast( hxClass:HxClass, value:Dynamic ) : Dynamic { + switch (hxClass.phpClassName) { + case 'Int': + if (Boot.isNumber(value)) { + return Global.intval(value); + } + case 'Float': + if (Boot.isNumber(value)) { + return value.floatval(); + } + case 'Bool': + if (value.is_bool()) { + return value; + } + case 'String': + if (value.is_string()) { + return value; + } + case 'php\\NativeArray': + if (value.is_array()) { + return value; + } + case _: + if (value.is_object() && Std.is(value, cast hxClass)) { + return value; + } + } + throw 'Cannot cast ' + Std.string(value) + ' to ' + getClassName(hxClass.phpClassName); + } + + /** + `trace()` implementation + **/ + public static function trace( value:Dynamic, infos:PosInfos ) : Void { + if (infos != null) { + Global.echo('${infos.fileName}:${infos.lineNumber}: '); + } + Global.echo(stringify(value)); + if (infos.customParams != null) { + for (value in infos.customParams) { + Global.echo(',' + stringify(value)); + } + } + Global.echo('\n'); + } + + /** + Returns string representation of `value` + **/ + public static function stringify( value : Dynamic ) : String { + if (value == null) { + return 'null'; + } + if (value.is_string()) { + return value; + } + if (value.is_int() || value.is_float()) { + return Syntax.string(value); + } + if (value.is_bool()) { + return value ? 'true' : 'false'; + } + if (value.is_array()) { + var strings = Syntax.arrayDecl(); + Syntax.foreach(value, function(key:Dynamic, item:Dynamic) { + Global.array_push(strings, (key:String) + ' => ' + stringify(item)); + }); + return '[' + Global.implode(', ', strings) + ']'; + } + if (value.is_object()) { + if (value.method_exists('toString')) { + return value.toString(); + } + if (value.method_exists('__toString')) { + return value.__toString(); + } + if (Std.is(value, StdClass)) { + if (value.toString.isset() && value.toString.is_callable()) { + return value.toString(); + } + var result = new NativeIndexedArray(); + var data = Global.get_object_vars(value); + for (key in data.array_keys()) { + result.array_push('$key : ' + stringify(data[key])); + } + return '{ ' + Global.implode(', ', result) + ' }'; + } + if (isFunction(value)) { + return ''; + } + if (Std.is(value, HxClass)) { + return '[class ' + getClassName((value:HxClass).phpClassName) + ']'; + } else { + return '[object ' + getClassName(Global.get_class(value)) + ']'; + } + } + throw "Unable to stringify value"; + } + + static public inline function isNumber( value:Dynamic ) { + return value.is_int() || value.is_float(); + } + + /** + Check if specified values are equal + **/ + public static function equal( left:Dynamic, right:Dynamic ) : Bool { + if (isNumber(left) && isNumber(right)) { + return Syntax.binop(left, '==', right); + } + return Syntax.binop(left, '===', right); + } + + /** + Concat `left` and `right` if both are strings or string and null. + Otherwise return sum of `left` and `right`. + **/ + public static function addOrConcat( left:Dynamic, right:Dynamic ) : Dynamic { + if (left.is_string() || right.is_string()) { + return (left:String) + (right:String); + } + return Syntax.binop(left, '+', right); + } + + /** + `Std.is()` implementation + **/ + public static function is( value:Dynamic, type:HxClass ) : Bool { + if (type == null) return false; + + var phpType = type.phpClassName; + switch (phpType) { + case 'Dynamic': + return true; + case 'Int': + return ( + value.is_int() + || ( + value.is_float() + && Syntax.binop(Syntax.int(value), '==', value) + && !Global.is_nan(value) + ) + ) + && Global.abs(value) <= 2147483648; + case 'Float': + return value.is_float() || value.is_int(); + case 'Bool': + return value.is_bool(); + case 'String': + return value.is_string(); + case 'php\\NativeArray', 'php\\_NativeArray\\NativeArray_Impl_': + return value.is_array(); + case 'Enum', 'Class': + if (Std.is(value, HxClass)) { + var valuePhpClass = (cast value:HxClass).phpClassName; + var enumPhpClass = (cast HxEnum:HxClass).phpClassName; + var isEnumType = Global.is_subclass_of(valuePhpClass, enumPhpClass); + return (phpType == 'Enum' ? isEnumType : !isEnumType); + } + case _: + if (value.is_object()) { + var type:Class = cast type; + return Syntax.instanceof(value, type); + } + } + return false; + } + + /** + Check if `value` is a `Class` + **/ + public static inline function isClass(value:Dynamic) : Bool { + return Std.is(value, HxClass); + } + + /** + Check if `value` is an enum constructor instance + **/ + public static inline function isEnumValue(value:Dynamic) : Bool { + return Std.is(value, HxEnum); + } + + /** + Check if `value` is a function + **/ + public static inline function isFunction(value:Dynamic) : Bool { + return Std.is(value, Closure) || Std.is(value, HxClosure); + } + + /** + Check if `value` is an instance of `HxClosure` + **/ + public static inline function isHxClosure(value:Dynamic) : Bool { + return Std.is(value, HxClosure); + } + + /** + Performs `left >>> right` operation + **/ + public static function shiftRightUnsigned( left:Int, right:Int ) : Int { + if (right == 0) { + return left; + } else if (left >= 0) { + return (left >> right); + } else { + return (left >> right) & (0x7fffffff >> (right - 1)); + } + } + + /** + Helper method to avoid "Cannot use temporary expression in write context" error for expressions like this: + ``` + (new MyClass()).fieldName = 'value'; + ``` + **/ + static public function deref( value:Dynamic ) : Dynamic { + return value; + } + + /** + Create Haxe-compatible anonymous structure of `data` associative array + **/ + static public inline function createAnon( data:NativeArray ) : Dynamic { + return new HxAnon(data); + } + + /** + Make sure specified class is loaded + **/ + static public inline function ensureLoaded(phpClassName:String ) : Bool { + return Global.class_exists(phpClassName) || Global.interface_exists(phpClassName); + } +} + + +/** + Class implementation for Haxe->PHP internals. +**/ +@:keep +@:dox(hide) +private class HxClass { + + public var phpClassName (default,null) : String; + + public function new( phpClassName:String ) : Void { + this.phpClassName = phpClassName; + } + + /** + Magic method to call static methods of this class, when `HxClass` instance is in a `Dynamic` variable. + **/ + @:phpMagic + function __call( method:String, args:NativeArray ) : Dynamic { + var callback = phpClassName + '::' + method; + return Global.call_user_func_array(callback, args); + } + + /** + Magic method to get static vars of this class, when `HxClass` instance is in a `Dynamic` variable. + **/ + @:phpMagic + function __get( property:String ) : Dynamic { + if (Boot.hasGetter(phpClassName, property)) { + return Syntax.staticCall(phpClassName, 'get_$property'); + } else { + return Syntax.getStaticField(phpClassName, property); + } + } + + /** + Magic method to set static vars of this class, when `HxClass` instance is in a `Dynamic` variable. + **/ + @:phpMagic + function __set( property:String, value:Dynamic ) : Void { + if (Boot.hasSetter(phpClassName, property)) { + Syntax.staticCall(phpClassName, 'set_$property', value); + } else { + Syntax.setStaticField(phpClassName, property, value); + } + } +} + + +/** + Base class for enum types +**/ +@:keep +@:dox(hide) +private class HxEnum { + static var singletons = new Map(); + + var tag : String; + var index : Int; + var params : NativeArray; + + /** + Returns instances of constructors without arguments + **/ + public static function singleton( enumClass:String, tag:String, index:Int ) : HxEnum { + var key = '$enumClass::$tag'; + + var instance = singletons.get(key); + if (instance == null) { + instance = Syntax.construct(enumClass, tag, index); + singletons.set(key, instance); + } + + return instance; + } + + public function new( tag:String, index:Int, arguments:NativeArray = null ) : Void { + this.tag = tag; + this.index = index; + params = (arguments == null ? new NativeArray() : arguments); + } + + /** + Get string representation of this `Class` + **/ + public function toString() : String { + return __toString(); + } + + /** + PHP magic method to get string representation of this `Class` + **/ + @:phpMagic + public function __toString() : String { + var result = tag; + if (Global.count(params) > 0) { + var strings = Global.array_map(function (item) return Boot.stringify(item), params); + result += '(' + Global.implode(',', strings) + ')'; + } + return result; + } +} + + +/** + `String` implementation +**/ +@:keep +@:dox(hide) +private class HxString { + + public static function toUpperCase( str:String ) : String { + return Global.strtoupper(str); + } + + public static function toLowerCase( str:String ) : String { + return Global.strtolower(str); + } + + public static function charAt( str:String, index:Int) : String { + if (index < 0 || index >= str.length) { + return ''; + } else { + return (str:NativeString)[index]; + } + } + + public static function charCodeAt( str:String, index:Int) : Null { + if (index < 0 || index >= str.length) { + return null; + } else { + return Global.ord((str:NativeString)[index]); + } + } + + public static function indexOf( str:String, search:String, startIndex:Int = 0 ) : Int { + if (startIndex < 0) startIndex += str.length; + var index = Global.strpos(str, search, startIndex); + if (index == false) { + return -1; + } else { + return index; + } + } + + public static function lastIndexOf( str:String, search:String, startIndex:Int = null ) : Int { + var index = Global.strrpos(str, search, (startIndex == null ? 0 : startIndex - str.length)); + if (index == false) { + return -1; + } else { + return index; + } + } + + public static function split( str:String, delimiter:String ) : Array { + if (delimiter == '') { + return @:privateAccess Array.wrap(Global.str_split(str)); + } else { + return @:privateAccess Array.wrap(Global.explode(delimiter, str)); + } + } + + public static function substr( str:String, pos:Int, ?len:Int ) : String { + if (pos < -str.length) { + pos = 0; + } else if (pos >= str.length) { + return ''; + } + if (len == null) { + return Global.substr(str, pos); + } else { + var result = Global.substr(str, pos, len); + return (result == false ? '' : result); + } + } + + public static function substring( str:String, startIndex:Int, ?endIndex:Int ) : String { + if (endIndex == null) { + endIndex = str.length; + } else if (endIndex < 0) { + endIndex = 0; + } + if (startIndex < 0) startIndex = 0; + if (startIndex > endIndex) { + var tmp = endIndex; + endIndex = startIndex; + startIndex = tmp; + } + var result = Global.substr(str, startIndex, endIndex - startIndex); + return (result == false ? '' : result); + } + + public static function toString( str:String ) : String { + return str; + } + + public static function fromCharCode( code:Int ) : String { + return Global.chr(code); + } +} + +/** + For Dynamic access which looks like String +**/ +@:dox(hide) +@:keep +private class HxDynamicStr { + static var hxString : String = (cast HxString:HxClass).phpClassName; + var str : String; + + /** + Returns HxDynamicStr instance if `value` is a string. + Otherwise returns `value` as-is. + **/ + static function wrap( value:Dynamic ) : Dynamic { + if (value.is_string()) { + return new HxDynamicStr(value); + } else { + return value; + } + } + + function new( str:String ) { + this.str = str; + } + + @:phpMagic + function __get( field:String ) : Dynamic { + switch (field) { + case 'length': return str.length; + case 'toUpperCase': return HxString.toUpperCase.bind(str); + case 'toLowerCase': return HxString.toLowerCase.bind(str); + case 'charAt': return HxString.charAt.bind(str); + case 'indexOf': return HxString.indexOf.bind(str); + case 'lastIndexOf': return HxString.lastIndexOf.bind(str); + case 'split': return HxString.split.bind(str); + case 'toString': return HxString.toString.bind(str); + case 'substring': return HxString.substring.bind(str); + case 'substr': return HxString.substr.bind(str); + case 'charCodeAt': return HxString.charCodeAt.bind(str); + } + /** Force invalid field access error */ + return Syntax.getField(str, field); + } + + @:phpMagic + function __call( method:String, args:NativeArray ) : Dynamic { + Global.array_unshift(args, str); + return Global.call_user_func_array(hxString + '::' + method, args); + } +} + + +/** + Anonymous objects implementation +**/ +@:keep +@:dox(hide) +private class HxAnon extends StdClass { + + public function new( fields:NativeArray = null ) { + super(); + if (fields != null) { + Syntax.foreach(fields, function(name, value) Syntax.setField(this, name, value)); + } + } + + @:phpMagic + function __get( name:String ) { + return null; + } + + @:phpMagic + function __call( name:String, args:NativeArray ) : Dynamic { + var method = Syntax.getField(this, name); + Syntax.keepVar(method); + return method(Syntax.splat(args)); + } +} + +/** + Closures implementation +**/ +@:keep +@:dox(hide) +private class HxClosure { + /** `this` for instance methods; php class name for static methods */ + var target : Dynamic; + /** Method name for methods */ + var func : String; + + public function new( target:Dynamic, func:String ) : Void { + this.target = target; + this.func = func; + //Force runtime error if trying to create a closure of an instance which happen to be `null` + if (target.is_null()) { + throw "Unable to create closure on `null`"; + } + } + + /** + @see http://php.net/manual/en/language.oop5.magic.php#object.invoke + **/ + @:phpMagic + public function __invoke() { + return Global.call_user_func_array(getCallback(), Global.func_get_args()); + } + + /** + Generates callable value for PHP + **/ + public function getCallback(eThis:Dynamic = null) : NativeIndexedArray { + if (eThis == null) { + eThis = target; + } + if (Std.is(eThis, StdClass)) { + if (Std.is(eThis, HxAnon)) { + return Syntax.getField(eThis, func); + } + } + return Syntax.arrayDecl(eThis, func); + } + + /** + Check if this is the same closure + **/ + public function equals( closure:HxClosure ) : Bool { + return (target == closure.target && func == closure.func); + } + + /** + Invoke this closure with `newThis` instead of `this` + **/ + public function callWith( newThis:Dynamic, args:NativeArray ) : Dynamic { + return Global.call_user_func_array(getCallback(newThis), args); + } +} + +/** + Special exception which is used to wrap non-throwable values +**/ +@:keep +@:dox(hide) +private class HxException extends Exception { + var e : Dynamic; + public function new( e:Dynamic ) : Void { + this.e = e; + super(Boot.stringify(e)); + } +} \ No newline at end of file diff --git a/std/php7/Closure.hx b/std/php7/Closure.hx new file mode 100644 index 00000000..4ac23389 --- /dev/null +++ b/std/php7/Closure.hx @@ -0,0 +1,12 @@ +package php; + +import haxe.extern.Rest; + +/** + @see http://php.net/manual/en/class.closure.php +**/ +@:native('Closure') +extern class Closure { + public function bindTo( newthis:{}, newscope:Dynamic = "static" ) : Closure; + public function call ( newthis:{}, args:Rest ) : Dynamic; +} \ No newline at end of file diff --git a/std/php7/Const.hx b/std/php7/Const.hx new file mode 100644 index 00000000..a3b98d37 --- /dev/null +++ b/std/php7/Const.hx @@ -0,0 +1,302 @@ +package php; + +/** + This class contains externs for native PHP constants defined in global namespace. + For native PHP functions in global namespace see `php.Global`. +**/ +@:phpGlobal +extern class Const { + /** + If this constant is defined and equals `true` then Haxe will not set error handler automatically. + **/ + static var HAXE_CUSTOM_ERROR_HANDLER : Bool; + /** + @see http://php.net/manual/en/reserved.constants.php + **/ + static var PHP_OS : String; + static var PHP_SAPI : String; + static var PHP_EOL : String; + static var PHP_INT_MAX : Int; + static var PHP_INT_MIN : Int; + static var PHP_INT_SIZE : Int; + /** + @see http://php.net/manual/en/language.constants.predefined.php + **/ + static var __LINE__ : Int; + static var __FILE__ : String; + static var __DIR__ : String; + static var __FUNCTION__ : String; + static var __CLASS__ : String; + static var __TRAIT__ : String; + static var __METHOD__ : String; + static var __NAMESPACE__ : String; + /** + @see http://php.net/manual/en/errorfunc.constants.php + **/ + static var E_ERROR : Int; + static var E_WARNING : Int; + static var E_PARSE : Int; + static var E_NOTICE : Int; + static var E_CORE_ERROR : Int; + static var E_CORE_WARNING : Int; + static var E_COMPILE_ERROR : Int; + static var E_COMPILE_WARNING : Int; + static var E_USER_ERROR : Int; + static var E_USER_WARNING : Int; + static var E_USER_NOTICE : Int; + static var E_STRICT : Int; + static var E_RECOVERABLE_ERROR : Int; + static var E_DEPRECATED : Int; + static var E_USER_DEPRECATED : Int; + static var E_ALL : Int; + /** + @see http://php.net/manual/en/function.count.php + **/ + static var COUNT_NORMAL : Int; + static var COUNT_RECURSIVE : Int; + /** + @see http://php.net/manual/en/function.array-filter.php + **/ + static var ARRAY_FILTER_USE_KEY : Int; + static var ARRAY_FILTER_USE_BOTH : Int; + /** + @see http://php.net/manual/en/function.debug-backtrace.php + **/ + static var DEBUG_BACKTRACE_PROVIDE_OBJECT : Int; + static var DEBUG_BACKTRACE_IGNORE_ARGS : Int; + /** + @see http://php.net/manual/en/math.constants.php + **/ + static var M_PI : Float; + static var M_E : Float; + static var M_LOG2E : Float; + static var M_LOG10E : Float; + static var M_LN2 : Float; + static var M_LN10 : Float; + static var M_PI_2 : Float; + static var M_PI_4 : Float; + static var M_1_PI : Float; + static var M_2_PI : Float; + static var M_SQRTPI : Float; + static var M_2_SQRTPI : Float; + static var M_SQRT2 : Float; + static var M_SQRT3 : Float; + static var M_SQRT1_2 : Float; + static var M_LNPI : Float; + static var M_EULER : Float; + static var PHP_ROUND_HALF_UP : Int; + static var PHP_ROUND_HALF_DOWN : Int; + static var PHP_ROUND_HALF_EVEN : Int; + static var PHP_ROUND_HALF_ODD : Int; + static var NAN : Float; + static var INF : Float; + /** + @see http://php.net/manual/en/function.setlocale.php + **/ + static var LC_ALL : Int; + static var LC_COLLATE : Int; + static var LC_CTYPE : Int; + static var LC_MONETARY : Int; + static var LC_NUMERIC : Int; + static var LC_TIME : Int; + static var LC_MESSAGES : Int; + /** + @see http://php.net/manual/en/features.commandline.io-streams.php + **/ + static var STDIN : Resource; + static var STDOUT : Resource; + static var STDERR : Resource; + /** + @see http://php.net/manual/en/function.preg-match-all.php + **/ + static var PREG_PATTERN_ORDER : Int; + static var PREG_SET_ORDER : Int; + static var PREG_OFFSET_CAPTURE : Int; + /** + @see http://php.net/manual/en/function.preg-split.php + **/ + static var PREG_SPLIT_NO_EMPTY : Int; + static var PREG_SPLIT_DELIM_CAPTURE : Int; + static var PREG_SPLIT_OFFSET_CAPTURE : Int; + /** + @see http://php.net/manual/en/function.htmlspecialchars.php + **/ + static var ENT_COMPAT : Int; + static var ENT_QUOTES : Int; + static var ENT_NOQUOTES : Int; + static var ENT_IGNORE : Int; + static var ENT_SUBSTITUTE : Int; + static var ENT_DISALLOWED : Int; + static var ENT_HTML401 : Int; + static var ENT_XML1 : Int; + static var ENT_XHTML : Int; + static var ENT_HTML5 : Int; + /** + @see http://php.net/manual/en/function.str-pad.php + **/ + static var STR_PAD_RIGHT : Int; + static var STR_PAD_LEFT : Int; + static var STR_PAD_BOTH : Int; + /** + @see http://php.net/manual/en/function.feof.php + **/ + static var SEEK_SET : Int; + static var SEEK_CUR : Int; + static var SEEK_END : Int; + /** + @see http://php.net/manual/en/function.stream-socket-server.php + **/ + static var STREAM_SERVER_BIND : Int; + static var STREAM_SERVER_LISTEN : Int; + /** + @see http://php.net/manual/en/function.stream-socket-client.php + **/ + static var STREAM_CLIENT_CONNECT : Int; + static var STREAM_CLIENT_ASYNC_CONNECT : Int; + static var STREAM_CLIENT_PERSISTENT : Int; + /** + @see http://php.net/manual/en/function.socket-create.php + **/ + static var SOCK_STREAM : Int; + static var SOCK_DGRAM : Int; + static var SOCK_SEQPACKET : Int; + static var SOCK_RAW : Int; + static var SOCK_RDM : Int; + static var AF_INET : Int; + static var AF_INET6 : Int; + static var AF_UNIX : Int; + /** + @see http://php.net/manual/en/json.constants.php + **/ + static var JSON_ERROR_NONE : Int; + static var JSON_ERROR_DEPTH : Int; + static var JSON_ERROR_STATE_MISMATCH : Int; + static var JSON_ERROR_CTRL_CHAR : Int; + static var JSON_ERROR_SYNTAX : Int; + static var JSON_ERROR_UTF8 : Int; + static var JSON_ERROR_RECURSION : Int; + static var JSON_ERROR_INF_OR_NAN : Int; + static var JSON_ERROR_UNSUPPORTED_TYPE : Int; + static var JSON_HEX_TAG : Int; + static var JSON_HEX_AMP : Int; + static var JSON_HEX_APOS : Int; + static var JSON_HEX_QUOT : Int; + static var JSON_FORCE_OBJECT : Int; + static var JSON_NUMERIC_CHECK : Int; + static var JSON_BIGINT_AS_STRING : Int; + static var JSON_PRETTY_PRINT : Int; + static var JSON_UNESCAPED_SLASHES : Int; + static var JSON_UNESCAPED_UNICODE : Int; + static var JSON_PARTIAL_OUTPUT_ON_ERROR : Int; + static var JSON_PRESERVE_ZERO_FRACTION : Int; + /** + @see http://php.net/manual/en/mysqli.constants.php + **/ + static var MYSQLI_READ_DEFAULT_GROUP : Int; + static var MYSQLI_READ_DEFAULT_FILE : Int; + static var MYSQLI_OPT_CONNECT_TIMEOUT : Int; + static var MYSQLI_OPT_LOCAL_INFILE : Int; + static var MYSQLI_INIT_COMMAND : Int; + static var MYSQLI_CLIENT_SSL : Int; + static var MYSQLI_CLIENT_COMPRESS : Int; + static var MYSQLI_CLIENT_INTERACTIVE : Int; + static var MYSQLI_CLIENT_IGNORE_SPACE : Int; + static var MYSQLI_CLIENT_NO_SCHEMA : Int; + static var MYSQLI_CLIENT_MULTI_QUERIES : Int; + static var MYSQLI_STORE_RESULT : Int; + static var MYSQLI_USE_RESULT : Int; + static var MYSQLI_ASSOC : Int; + static var MYSQLI_NUM : Int; + static var MYSQLI_BOTH : Int; + static var MYSQLI_NOT_NULL_FLAG : Int; + static var MYSQLI_PRI_KEY_FLAG : Int; + static var MYSQLI_UNIQUE_KEY_FLAG : Int; + static var MYSQLI_MULTIPLE_KEY_FLAG : Int; + static var MYSQLI_BLOB_FLAG : Int; + static var MYSQLI_UNSIGNED_FLAG : Int; + static var MYSQLI_ZEROFILL_FLAG : Int; + static var MYSQLI_AUTO_INCREMENT_FLAG : Int; + static var MYSQLI_TIMESTAMP_FLAG : Int; + static var MYSQLI_SET_FLAG : Int; + static var MYSQLI_NUM_FLAG : Int; + static var MYSQLI_PART_KEY_FLAG : Int; + static var MYSQLI_GROUP_FLAG : Int; + static var MYSQLI_TYPE_DECIMAL : Int; + static var MYSQLI_TYPE_NEWDECIMAL : Int; + static var MYSQLI_TYPE_BIT : Int; + static var MYSQLI_TYPE_TINY : Int; + static var MYSQLI_TYPE_SHORT : Int; + static var MYSQLI_TYPE_LONG : Int; + static var MYSQLI_TYPE_FLOAT : Int; + static var MYSQLI_TYPE_DOUBLE : Int; + static var MYSQLI_TYPE_NULL : Int; + static var MYSQLI_TYPE_TIMESTAMP : Int; + static var MYSQLI_TYPE_LONGLONG : Int; + static var MYSQLI_TYPE_INT24 : Int; + static var MYSQLI_TYPE_DATE : Int; + static var MYSQLI_TYPE_TIME : Int; + static var MYSQLI_TYPE_DATETIME : Int; + static var MYSQLI_TYPE_YEAR : Int; + static var MYSQLI_TYPE_NEWDATE : Int; + static var MYSQLI_TYPE_INTERVAL : Int; + static var MYSQLI_TYPE_ENUM : Int; + static var MYSQLI_TYPE_SET : Int; + static var MYSQLI_TYPE_TINY_BLOB : Int; + static var MYSQLI_TYPE_MEDIUM_BLOB : Int; + static var MYSQLI_TYPE_LONG_BLOB : Int; + static var MYSQLI_TYPE_BLOB : Int; + static var MYSQLI_TYPE_VAR_STRING : Int; + static var MYSQLI_TYPE_STRING : Int; + static var MYSQLI_TYPE_CHAR : Int; + static var MYSQLI_TYPE_GEOMETRY : Int; + static var MYSQLI_NEED_DATA : Int; + static var MYSQLI_NO_DATA : Int; + static var MYSQLI_DATA_TRUNCATED : Int; + static var MYSQLI_ENUM_FLAG : Int; + static var MYSQLI_BINARY_FLAG : Int; + static var MYSQLI_CURSOR_TYPE_FOR_UPDATE : Int; + static var MYSQLI_CURSOR_TYPE_NO_CURSOR : Int; + static var MYSQLI_CURSOR_TYPE_READ_ONLY : Int; + static var MYSQLI_CURSOR_TYPE_SCROLLABLE : Int; + static var MYSQLI_STMT_ATTR_CURSOR_TYPE : Int; + static var MYSQLI_STMT_ATTR_PREFETCH_ROWS : Int; + static var MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH : Int; + static var MYSQLI_SET_CHARSET_NAME : Int; + static var MYSQLI_REPORT_INDEX : Int; + static var MYSQLI_REPORT_ERROR : Int; + static var MYSQLI_REPORT_STRICT : Int; + static var MYSQLI_REPORT_ALL : Int; + static var MYSQLI_REPORT_OFF : Int; + static var MYSQLI_DEBUG_TRACE_ENABLED : Int; + static var MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED : Int; + static var MYSQLI_SERVER_QUERY_NO_INDEX_USED : Int; + static var MYSQLI_REFRESH_GRANT : Int; + static var MYSQLI_REFRESH_LOG : Int; + static var MYSQLI_REFRESH_TABLES : Int; + static var MYSQLI_REFRESH_HOSTS : Int; + static var MYSQLI_REFRESH_STATUS : Int; + static var MYSQLI_REFRESH_THREADS : Int; + static var MYSQLI_REFRESH_SLAVE : Int; + static var MYSQLI_REFRESH_MASTER : Int; + static var MYSQLI_TRANS_COR_AND_CHAIN : Int; + static var MYSQLI_TRANS_COR_AND_NO_CHAIN : Int; + static var MYSQLI_TRANS_COR_RELEASE : Int; + static var MYSQLI_TRANS_COR_NO_RELEASE : Int; + static var MYSQLI_TRANS_START_READ_ONLY : Int; + static var MYSQLI_TRANS_START_READ_WRITE : Int; + static var MYSQLI_TRANS_START_CONSISTENT_SNAPSHOT : Int; + /** + @see http://php.net/manual/en/sqlite3.constants.php + **/ + static var SQLITE3_ASSOC : Int; + static var SQLITE3_NUM : Int; + static var SQLITE3_BOTH : Int; + static var SQLITE3_INTEGER : Int; + static var SQLITE3_FLOAT : Int; + static var SQLITE3_TEXT : Int; + static var SQLITE3_BLOB : Int; + static var SQLITE3_NULL : Int; + static var SQLITE3_OPEN_READONLY : Int; + static var SQLITE3_OPEN_READWRITE : Int; + static var SQLITE3_OPEN_CREATE : Int; +} \ No newline at end of file diff --git a/std/php7/Error.hx b/std/php7/Error.hx new file mode 100644 index 00000000..8044f90a --- /dev/null +++ b/std/php7/Error.hx @@ -0,0 +1,42 @@ +/* + * Copyright (C)2005-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 php; + +@:native('Error') +extern class Error implements Throwable { + function new(?message : String, ?code : Int, ?previous:Throwable) : Void; + + private var message : String; + private var code : Int; + private var file : String; + private var line : Int; + + @:final + function getPrevious() : Throwable; // Returns previous Throwable + function getMessage() : String; // message of the exception + function getCode() : Int; // code of the exception + function getFile() : String; // source filename + function getLine() : Int; // source line + function getTrace() : NativeIndexedArray>; // an array of the backtrace + function getTraceAsString() : String; // formated string of trace + @:phpMagic function __toString() : String; // formated string for display +} \ No newline at end of file diff --git a/std/php7/ErrorException.hx b/std/php7/ErrorException.hx new file mode 100644 index 00000000..15d087c5 --- /dev/null +++ b/std/php7/ErrorException.hx @@ -0,0 +1,40 @@ +/* + * Copyright (C)2005-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 php; + +/** + @see http://php.net/manual/en/class.errorexception.php +**/ +@:native('ErrorException') +extern class ErrorException implements Throwable { + function new (?message:String, ?code:Int, ?severety:Int, ?filename:String, ?lineno:Int, ?previous:Throwable) : Void; + + @:final function getSeverity() : Int; + @:final function getPrevious() : Throwable; // Returns previous Throwable + @:final function getMessage() : String; // message of the exception + @:final function getCode() : Int; // code of the exception + @:final function getFile() : String; // source filename + @:final function getLine() : Int; // source line + @:final function getTrace() : NativeIndexedArray>; // an array of the backtrace + @:final function getTraceAsString() : String; // formated string of trace + @:phpMagic function __toString() : String; // formated string for display +} \ No newline at end of file diff --git a/std/php7/Exception.hx b/std/php7/Exception.hx new file mode 100644 index 00000000..e8818bb9 --- /dev/null +++ b/std/php7/Exception.hx @@ -0,0 +1,42 @@ +/* + * Copyright (C)2005-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 php; + +@:native('Exception') +extern class Exception implements Throwable { + public function new(?message : String, ?code : Int, ?previous:Throwable) : Void; + + private var message : String; + private var code : Int; + private var file : String; + private var line : Int; + + @:final + function getPrevious() : Throwable; // Returns previous Throwable + function getMessage() : String; // message of the exception + function getCode() : Int; // code of the exception + function getFile() : String; // source filename + function getLine() : Int; // source line + function getTrace() : NativeIndexedArray>; // an array of the backtrace + function getTraceAsString() : String; // formated string of trace + @:phpMagic function __toString() : String; // formated string for display +} \ No newline at end of file diff --git a/std/php7/Global.hx b/std/php7/Global.hx new file mode 100644 index 00000000..5e75e2fb --- /dev/null +++ b/std/php7/Global.hx @@ -0,0 +1,1160 @@ +package php; + +import haxe.extern.*; +import haxe.Constraints; + +/** + This class contains externs for native PHP functions defined in global namespace. + For native PHP constants in global namespace see `php.Const`. +**/ +@:phpGlobal +extern class Global { + /** + @see http://php.net/manual/en/function.exit.php + **/ + static function exit( status:EitherType ) : Void ; + + /** + @see http://php.net/manual/en/function.exit.php + **/ + static function die( status:EitherType ) : Void ; + + /** + @see http://php.net/manual/en/function.error-reporting.php + **/ + static function error_reporting( ?level:Int ) : Int ; + + /** + @see http://php.net/manual/en/function.set-error-handler.php + **/ + @:overload(function( error_handler:Int->String->Bool, ?error_types:Int ) : Dynamic {}) + @:overload(function( error_handler:Int->String->String->Bool, ?error_types:Int ) : Dynamic {}) + @:overload(function( error_handler:Int->String->String->Int->Bool, ?error_types:Int ) : Dynamic {}) + static function set_error_handler( ?error_handler:Int->String->String->Int->Array->Bool, ?error_types:Int ) : Dynamic ; + + /** + @see http://php.net/manual/en/function.restore-error-handler.php + **/ + static function restore_error_handler() : Bool ; + + /** + @see http://php.net/manual/en/function.set-exception-handler.php + **/ + static function set_exception_handler( exception_handler:Throwable->Void ) : Dynamic ; + + /** + @see http://php.net/manual/en/function.restore-exception-handler.php + **/ + static function restore_exception_handler() : Bool ; + + /** + @see http://php.net/manual/en/function.is-int.php + **/ + static function is_int( value:Dynamic ) : Bool ; + + /** + @see http://php.net/manual/en/function.is-float.php + **/ + static function is_float( value:Dynamic ) : Bool ; + + /** + @see http://php.net/manual/en/function.is-string.php + **/ + static function is_string( value:Dynamic ) : Bool ; + + /** + @see http://php.net/manual/en/function.is-numeric.php + **/ + static function is_numeric( value:Dynamic ) : Bool ; + + /** + @see http://php.net/manual/en/function.is-bool.php + **/ + static function is_bool( value:Dynamic ) : Bool ; + + /** + Checks if `values` is `php.NativeArray` + @see http://php.net/manual/en/function.is-array.php + **/ + static function is_array( value:Dynamic ) : Bool ; + + /** + @see http://php.net/manual/en/function.is-object.php + **/ + static function is_object( value:Dynamic ) : Bool ; + + /** + @see http://php.net/manual/en/function.is-null.php + **/ + static function is_null( value:Dynamic ) : Bool ; + + /** + @see http://php.net/manual/en/function.is-subclass-of.php + **/ + static function is_subclass_of( value:Dynamic, className:String, allow_string:Bool = true ) : Bool ; + + /** + @see http://php.net/manual/en/function.class-exists.php + **/ + static function class_exists( class_name:String, autoload:Bool = true ) : Bool ; + + /** + @see http://php.net/manual/en/function.interface-exists.php + **/ + static function interface_exists( interface_name:String, autoload:Bool = true ) : Bool ; + + /** + @see http://php.net/manual/en/function.intval.php + **/ + static function intval( value:Dynamic, base:Int = 10 ) : Int ; + + /** + @see http://php.net/manual/en/function.floatval.php + **/ + static function floatval( value:Dynamic ) : Float ; + + /** + @see http://php.net/manual/en/function.boolval.php + **/ + static function boolval( value:Dynamic ) : Bool ; + + /** + @see http://php.net/manual/en/function.strval.php + **/ + static function strval( value:Dynamic ) : String ; + + /** + @see http://php.net/manual/en/function.phpversion.php + **/ + static function phpversion( ?extension:String ) : String ; + + /** + @see http://php.net/manual/en/function.class-alias.php + **/ + static function class_alias( original:String, alias:String, autoload:Bool = true ) : Bool ; + + /** + @see http://php.net/manual/en/function.count.php + **/ + static function count( array:Dynamic, ?mode:Int ) : Int ; + + /** + @see http://php.net/manual/en/function.array-filter.php + **/ + @:overload(function(array:NativeArray,callback:Dynamic->Bool,?flag:Int):NativeArray {}) + static function array_filter( array:NativeArray, ?callback:Dynamic->?Dynamic->Bool, flag:Int = 0 ) : NativeArray ; + + /** + @see http://php.net/manual/en/function.implode.php + **/ + @:overload(function(pieces:NativeArray):String {}) + static function implode( glue:String, pieces:NativeArray ) : String ; + + /** + @see http://php.net/manual/en/function.array-map.php + **/ + static function array_map( callback:EitherTypeDynamic, String>, array:Rest ) : NativeArray ; + + /** + @see http://php.net/manual/en/function.array-merge.php + **/ + static function array_merge( array:Rest ) : NativeArray ; + + /** + @see http://php.net/manual/en/function.array-diff.php + **/ + static function array_diff( array:Rest ) : NativeArray ; + + /** + @see http://php.net/manual/en/function.array-pop.php + **/ + static function array_pop( array:NativeArray ) : Dynamic; + + /** + @see http://php.net/manual/en/function.array-push.php + **/ + static function array_push( array:Ref, value:Rest ) : Int ; + + /** + @see http://php.net/manual/en/function.array-reverse.php + **/ + static function array_reverse( array:NativeArray, preserve_keys:Bool = false ) : NativeArray ; + + /** + @see http://php.net/manual/en/function.array-search.php + **/ + static function array_search( needle:Dynamic, haystack:NativeArray, strict:Bool = false) : EitherType> ; + + /** + @see http://php.net/manual/en/function.array-shift.php + **/ + static function array_shift( array:Ref ) : Dynamic ; + + /** + @see http://php.net/manual/en/function.array-slice.php + **/ + static function array_slice( array:NativeArray, offset:Int, length:Int = null, preserve_keys:Bool = false ) : NativeArray ; + + /** + @see http://php.net/manual/en/function.array-splice.php + **/ + static function array_splice( array:Ref, offset:Int, lenght:Int = 0, ?replacement:Dynamic ) : NativeArray ; + + /** + @see http://php.net/manual/en/function.array-unshift.php + **/ + static function array_unshift( arr:Ref, value:Rest ) : Int ; + + /** + @see http://php.net/manual/en/function.array-values.php + **/ + static function array_values( arr:NativeArray ) : NativeIndexedArray ; + + /** + @see http://php.net/manual/en/function.array-keys.php + **/ + static function array_keys( arr:NativeArray ) : NativeIndexedArray> ; + + /** + @see http://php.net/manual/en/function.array-key-exists.php + **/ + static function array_key_exists( key:EitherType, arr:NativeArray ) : Bool ; + + /** + @see http://php.net/manual/en/function.array-fill.php + **/ + static function array_fill( start_index:Int, num:Int, value:Dynamic ) : NativeArray ; + + /** + @see http://php.net/manual/en/function.in-array.php + **/ + static function in_array( needle:Dynamic, haystack:NativeArray, strict:Bool = false ) : Bool ; + + /** + @see http://php.net/manual/en/function.usort.php + **/ + static function usort( array:Ref, value_compare_func:Dynamic->Dynamic->Int ) : Bool ; + + /** + @see http://php.net/manual/en/function.reset.php + **/ + static function reset( array:Ref ) : Dynamic; + + /** + @see http://php.net/manual/en/function.current.php + **/ + static function current( array:Ref ) : Dynamic; + + /** + @see http://php.net/manual/en/function.next.php + **/ + static function next( array:Ref ) : Dynamic; + + /** + @see http://php.net/manual/en/function.prev.php + **/ + static function prev( array:Ref ) : Dynamic; + + /** + @see http://php.net/manual/en/function.end.php + **/ + static function end( array:Ref ) : Dynamic; + + /** + @see http://php.net/manual/en/function.key.php + **/ + static function key( array:NativeArray ) : EitherType; + + /** + @see http://php.net/manual/en/function.each.php + **/ + static function each( array:Ref ) : NativeArray; + + /** + @see http://php.net/manual/en/function.defined.php + **/ + static function defined( name:String ) : Bool; + + /** + @see http://php.net/manual/en/function.define.php + **/ + static function define( name:String, value:Dynamic, case_insensitive:Bool = false ) : Bool; + + /** + @see http://php.net/manual/en/function.echo.php + **/ + static function echo( args:Rest ) : Void; + + /** + @see http://php.net/manual/en/function.sprintf.php + **/ + static function sprintf( format:String, args:Rest ) : EitherType; + + /** + @see http://php.net/manual/en/function.method-exists.php + **/ + static function method_exists( object:Dynamic, method_name:String ) : Bool; + + /** + @see http://php.net/manual/en/function.property-exists.php + **/ + static function property_exists( object:Dynamic, property_name:String ) : Bool; + + /** + @see http://php.net/manual/en/function.is-callable.php + **/ + static function is_callable( value:Dynamic, syntax_only:Bool = false, ?callable_name:String ) : Bool; + + /** + @see http://php.net/manual/en/function.isset.php + **/ + static function isset( value:Dynamic, args:Rest ) : Bool; + + /** + @see http://php.net/manual/en/function.unset.php + **/ + static function unset( value:Dynamic, values:Rest ) : Void; + + /** + @see http://php.net/manual/en/function.get-object-vars.php + **/ + static function get_object_vars( object:{} ) : NativeAssocArray; + + /** + @see http://php.net/manual/en/function.get-class.php + **/ + static function get_class( object:{} = null ) : EitherType; + + /** + @see http://php.net/manual/en/function.get-parent-class.php + **/ + static function get_parent_class( ?object:Dynamic ) : EitherType; + + /** + @see http://php.net/manual/en/function.var-dump.php + **/ + static function var_dump( args:Rest ) : Void; + + /** + @see http://php.net/manual/en/function.ord.php + **/ + static function ord( string:String ) : Int; + + /** + @see http://php.net/manual/en/function.chr.php + **/ + static function chr( code:Int ) : String; + + /** + @see http://php.net/manual/en/function.strpos.php + **/ + static function strpos( haystack:String, needle:String, offset:Int = 0 ) : EitherType; + + /** + @see http://php.net/manual/en/function.strrpos.php + **/ + static function strrpos( haystack:String, needle:String, offset:Int = 0 ) : EitherType; + + /** + @see http://php.net/manual/en/function.str-split.php + **/ + static function str_split( string:String, split_length:Int = 1 ) : EitherType>; + + /** + @see http://php.net/manual/en/function.strlen.php + **/ + static function strlen( string:String ) : Int; + + /** + @see http://php.net/manual/en/function.strcmp.php + **/ + static function strcmp( str1:String, str2:String ) : Int; + + /** + @see http://php.net/manual/en/function.str-repeat.php + **/ + static function str_repeat( input:String, multiplier:Int ) : String; + + /** + @see http://php.net/manual/en/function.str-replace.php + **/ + static function str_replace( search:EitherType, replace:EitherType, subject:EitherType, ?count:Int ) : EitherType; + + /** + @see http://php.net/manual/en/function.explode.php + **/ + static function explode( delimiter:String, string:String, ?limit:Int ) : EitherType>; + + /** + @see http://php.net/manual/en/function.substr.php + **/ + static function substr( string:String, start:Int, ?length:Int ) : EitherType; + + /** + @see http://php.net/manual/en/function.substr_replace.php + **/ + static function substr_replace( string:EitherType, replacement:EitherType, start:EitherType, ?length:EitherType ) : EitherType; + + /** + @see http://php.net/manual/en/function.strtoupper.php + **/ + static function strtoupper( string:String ) : String; + + /** + @see http://php.net/manual/en/function.strtolower.php + **/ + static function strtolower( string:String ) : String; + + /** + @see http://php.net/manual/en/function.debug-backtrace.php + **/ + static function debug_backtrace( ?options:Int, ?limit:Int ) : NativeIndexedArray>; + + /** + @see http://php.net/manual/en/function.call-user-func.php + **/ + static function call_user_func( callback:Dynamic, arguments:Rest ) : Dynamic; + + /** + @see http://php.net/manual/en/function.call-user-func-array.php + **/ + static function call_user_func_array( callback:Dynamic, arguments:NativeArray ) : Dynamic; + + /** + @see http://php.net/manual/en/function.func-get-args.php + **/ + static function func_get_args() : NativeIndexedArray; + + /** + @see http://php.net/manual/en/function.abs.php + **/ + static function abs( number:T ) : T; + + /** + @see http://php.net/manual/en/function.min.php + **/ + static function min( values:Rest ) : Dynamic; + + /** + @see http://php.net/manual/en/function.max.php + **/ + static function max( values:Rest ) : Dynamic; + + /** + @see http://php.net/manual/en/function.sin.php + **/ + static function sin( arg:Float ) : Float; + + /** + @see http://php.net/manual/en/function.cos.php + **/ + static function cos( arg:Float ) : Float; + + /** + @see http://php.net/manual/en/function.atan2.php + **/ + static function atan2( y:Float, x:Float ) : Float; + + /** + @see http://php.net/manual/en/function.tan.php + **/ + static function tan( arg:Float ) : Float; + + /** + @see http://php.net/manual/en/function.exp.php + **/ + static function exp( arg:Float ) : Float; + + /** + @see http://php.net/manual/en/function.log.php + **/ + static function log( arg:Float ) : Float; + + /** + @see http://php.net/manual/en/function.sqrt.php + **/ + static function sqrt( arg:Float ) : Float; + + /** + @see http://php.net/manual/en/function.floor.php + **/ + static function floor( arg:Float ) : Float; + + /** + @see http://php.net/manual/en/function.ceil.php + **/ + static function ceil( arg:Float ) : Float; + + /** + @see http://php.net/manual/en/function.round.php + **/ + static function round( val:Float, precision:Int = 0, ?mode:Int ) : Float; + + /** + @see http://php.net/manual/en/function.atan.php + **/ + static function atan( arg:Float ) : Float; + + /** + @see http://php.net/manual/en/function.asin.php + **/ + static function asin( arg:Float ) : Float; + + /** + @see http://php.net/manual/en/function.acos.php + **/ + static function acos( arg:Float ) : Float; + + /** + @see http://php.net/manual/en/function.pow.php + **/ + static function pow( base:Float, exp:Float ) : Float; + + /** + @see http://php.net/manual/en/function.mt-rand.php + **/ + @:overload(function() : Int {}) + static function mt_rand( base:Int, exp:Int ) : Int; + + /** + @see http://php.net/manual/en/function.mt-getrandmax.php + **/ + static function mt_getrandmax() : Int; + + /** + @see http://php.net/manual/en/function.is-nan.php + **/ + static function is_nan( arg:Float ) : Bool; + + /** + @see http://php.net/manual/en/function.is-finite.php + **/ + static function is_finite( arg:Float ) : Bool; + + /** + @see http://php.net/manual/en/function.trim.php + **/ + static function trim( str:String, ?character_mask:String ) : String; + + /** + @see http://php.net/manual/en/function.rtrim.php + **/ + static function rtrim( str:String, ?character_mask:String ) : String; + + /** + @see http://php.net/manual/en/function.ltrim.php + **/ + static function ltrim( str:String, ?character_mask:String ) : String; + + /** + @see http://php.net/manual/en/function.getenv.php + **/ + static function getenv( varname:String ) : EitherType; + + /** + @see http://php.net/manual/en/function.putenv.php + **/ + static function putenv( setting:String ) : Bool; + + /** + @see http://php.net/manual/en/function.sleep.php + **/ + static function sleep( seconds:Int ) : EitherType; + + /** + @see http://php.net/manual/en/function.usleep.php + **/ + static function usleep( micro_seconds:Int ) : Void; + + /** + @see http://php.net/manual/en/function.setlocale.php + **/ + @:overload(function( category:Int, locale:NativeIndexedArray ) : EitherType {}) + static function setlocale( category:Int, locale:Rest ) : EitherType; + + /** + @see http://php.net/manual/en/function.getcwd.php + **/ + static function getcwd() : EitherType; + + /** + @see http://php.net/manual/en/function.chdir.php + **/ + static function chdir( directory:String ) : Bool; + + /** + @see http://php.net/manual/en/function.php-uname.php + **/ + static function php_uname( mode:String = 'a' ) : String; + + /** + @see http://php.net/manual/en/function.system.php + **/ + static function system( command:String, ?return_var:Ref ) : EitherType; + + /** + @see http://php.net/manual/en/function.microtime.php + **/ + static function microtime( get_as_float:Bool = false ) : EitherType; + + /** + @see http://php.net/manual/en/function.fopen.php + **/ + static function fopen( filename:String, mode:String, use_include_path:Bool = false, ?context:Resource ) : EitherType; + + /** + @see http://php.net/manual/en/function.fclose.php + **/ + static function fclose( handle:Resource ) : Bool; + + /** + @see http://php.net/manual/en/function.feof.php + **/ + static function feof( handle:Resource ) : Bool; + + /** + @see http://php.net/manual/en/function.fseek.php + **/ + static function fseek( handle:Resource, offset:Int, ?whence:Int ) : EitherType; + + /** + @see http://php.net/manual/en/function.ftell.php + **/ + static function ftell( handle:Resource ) : EitherType; + + /** + @see http://php.net/manual/en/function.rewind.php + **/ + static function rewind( handle:Resource ) : Bool; + + /** + @see http://php.net/manual/en/function.fgetc.php + **/ + static function fgetc( handle:Resource ) : EitherType; + + /** + @see http://php.net/manual/en/function.fgets.php + **/ + static function fgets( handle:Resource ) : EitherType; + + /** + @see http://php.net/manual/en/function.fflush.php + **/ + static function fflush( handle:Resource ) : Bool; + + /** + @see http://php.net/manual/en/function.fwrite.php + **/ + static function fwrite( handle:Resource, string:String, ?length:Int ) : EitherType; + + /** + @see http://php.net/manual/en/function.fread.php + **/ + static function fread( handle:Resource, length:Int ) : EitherType; + + /** + @see http://php.net/manual/en/function.file-exists.php + **/ + static function file_exists( filename:String ) : Bool; + + /** + @see http://php.net/manual/en/function.file-get-contents.php + **/ + static function file_get_contents( filename:String, use_include_path:Bool = false, ?context:Resource, offset:Int = 0, ?maxlen:Int ) : EitherType; + + /** + @see http://php.net/manual/en/function.file-put-contents.php + **/ + static function file_put_contents( filename:String, data:Dynamic, flags:Int = 0, ?context:Resource ) : EitherType; + + /** + @see http://php.net/manual/en/function.clearstatcache.php + **/ + static function clearstatcache( clear_realpath_cache:Bool = false, ?filename:String ) : Bool; + + /** + @see http://php.net/manual/en/function.fstat.php + **/ + static function fstat( handle:Resource ) : NativeArray; + + /** + @see http://php.net/manual/en/function.stat.php + **/ + static function stat( filename:String ) : EitherType; + + /** + @see http://php.net/manual/en/function.realpath.php + **/ + static function realpath( path:String ) : EitherType; + + /** + @see http://php.net/manual/en/function.filetype.php + **/ + static function filetype( filename:String ) : EitherType; + + /** + @see http://php.net/manual/en/function.mkdir.php + **/ + static function mkdir( pathname:String, mode:Int = 511, recursive:Bool = false, ?context:Resource ) : Bool; + + /** + @see http://php.net/manual/en/function.unlink.php + **/ + static function unlink( filename:String, ?context:Resource ) : Bool; + + /** + @see http://php.net/manual/en/function.rmdir.php + **/ + static function rmdir( dirname:String, ?context:Resource ) : Bool; + + /** + @see http://php.net/manual/en/function.dirname.php + **/ + static function dirname( path:String, levels:Int = 1 ) : String; + + /** + @see http://php.net/manual/en/function.opendir.php + **/ + static function opendir( path:String, ?context:Resource ) : EitherType; + + /** + @see http://php.net/manual/en/function.closedir.php + **/ + static function closedir( dir_handle:Resource ) : Void; + + /** + @see http://php.net/manual/en/function.readdir.php + **/ + static function readdir( ?dir_handle:Resource ) : EitherType; + + /** + @see http://php.net/manual/en/function.rewinddir.php + **/ + static function rewinddir( ?dir_handle:Resource ) : Void; + + /** + @see http://php.net/manual/en/function.is-dir.php + **/ + static function is_dir( filename:String ) : Bool; + + /** + @see http://php.net/manual/en/function.rename.php + **/ + static function rename( oldname:String, newname:String, ?context:Resource ) : Bool; + + /** + @see http://php.net/manual/en/function.copy.php + **/ + static function copy( source:String, dest:String, ?context:Resource ) : Bool; + + /** + @see http://php.net/manual/en/function.preg-match.php + **/ + static function preg_match( pattern:String, subject:String, ?matches:NativeArray, ?flags:Int, ?offset:Int ) : EitherType ; + + /** + @see http://php.net/manual/en/function.preg-match-all.php + **/ + static function preg_match_all( pattern:String, subject:String, ?matches:NativeArray, ?flags:Int, ?offset:Int ) : EitherType ; + + /** + @see http://php.net/manual/en/function.preg-split.php + **/ + static function preg_split( pattern:String, subject:String, limit:Int = -1, flags:Int = 0 ) : EitherType ; + + /** + @see http://php.net/manual/en/function.preg-replace.php + **/ + static function preg_replace( pattern:EitherType, replacement:EitherType, subject:EitherType, limit:Int = -1, ?count:Int ) : EitherType ; + + /** + @see http://php.net/manual/en/function.md5.php + **/ + static function md5( str:String, raw_output:Bool = false ) : String; + + /** + @see http://php.net/manual/en/function.sha1.php + **/ + static function sha1( str:String, raw_output:Bool = false ) : String; + + /** + @see http://php.net/manual/en/function.hash.php + **/ + static function hash( algo:String, str:String, raw_output:Bool = false ) : String; + + /** + @see http://php.net/manual/en/function.pack.php + **/ + static function pack( format:String, args:Rest ) : String; + + /** + @see http://php.net/manual/en/function.unpack.php + **/ + static function unpack( format:String, data:String ) : NativeArray; + + /** + @see http://php.net/manual/en/function.chunk-split.php + **/ + static function chunk_split( body:String, chunklen:Int = 76, end:String = "\r\n" ) : String; + + /** + @see http://php.net/manual/en/function.urlencode.php + **/ + static function urlencode( str:String ) : String; + + /** + @see http://php.net/manual/en/function.urldecode.php + **/ + static function urldecode( str:String ) : String; + + /** + @see http://php.net/manual/en/function.rawurlencode.php + **/ + static function rawurlencode( str:String ) : String; + + /** + @see http://php.net/manual/en/function.rawurldecode.php + **/ + static function rawurldecode( str:String ) : String; + + /** + @see http://php.net/manual/en/function.header.php + **/ + static function header( string:String, replace:Bool = true, ?http_response_code:Int ) : Void; + + /** + @see http://php.net/manual/en/function.setcookie.php + **/ + static function setcookie( name:String, value:String = "", expire:Int = 0, path:String = "", domain:String = "", secure:Bool = false, httponly:Bool = false ) : Bool; + + /** + @see http://php.net/manual/en/function.htmlspecialchars.php + **/ + static function htmlspecialchars( string:String, ?flags:Int, ?encoding:String, double_encode:Bool = true ) : String; + + /** + @see http://php.net/manual/en/function.htmlspecialchars_decode.php + **/ + static function htmlspecialchars_decode( string:String, ?flags:Int ) : String; + + /** + @see http://php.net/manual/en/function.str-pad.php + **/ + static function str_pad( input:String, pad_length:Int, pad_String:String = ' ', ?pad_type:Int ) : String; + + /** + @see http://php.net/manual/en/function.dechex.php + **/ + static function dechex( number:Int ) : String; + + /** + @see http://php.net/manual/en/function.hexdec.php + **/ + static function hexdec( hex_string:String ) : Int; + + /** + @see http://php.net/manual/en/function.bin2hex.php + **/ + static function bin2hex( str:String ) : String; + + /** + @see http://php.net/manual/en/function.hex2bin.php + **/ + static function hex2bin( str:String ) : EitherType; + + /** + @see http://php.net/manual/en/function.serialize.php + **/ + static function serialize( value:Dynamic ) : String; + + /** + @see http://php.net/manual/en/function.unserialize.php + **/ + static function unserialize( str:String, ?options:NativeArray ) : Dynamic; + + /** + @see http://php.net/manual/en/function.extension-loaded.php + **/ + static function extension_loaded( name:String ) : Bool; + + /** + @see http://php.net/manual/en/function.strncasecmp.php + **/ + static function strncasecmp( str1:String, str2:String, len:Int ) : Int; + + /** + @see http://php.net/manual/en/function.strcasecmp.php + **/ + static function strcasecmp( str1:String, str2:String ) : Int; + + /** + @see http://php.net/manual/en/function.fpassthru.php + **/ + static function fpassthru( handle:Resource ) : Int; + + /** + @see http://php.net/manual/en/function.json-encode.php + **/ + static function json_encode( value:Dynamic, options:Int = 0, depth:Int = 512 ) : EitherType; + + /** + @see http://php.net/manual/en/function.json-decode.php + **/ + static function json_decode( json:String, assoc:Bool = false, depth:Int = 512, options:Int = 512 ) : Dynamic; + + /** + @see http://php.net/manual/en/function.json-last-error.php + **/ + static function json_last_error() : Int; + + /** + @see http://php.net/manual/en/function.json-last-error-msg.php + **/ + static function json_last_error_msg() : EitherType; + + /** + @see http://php.net/manual/en/function.spl-object-hash.php + **/ + static function spl_object_hash( obj:{} ) : String; + + /** + @see http://php.net/manual/en/function.utf8-encode.php + **/ + static function utf8_encode( data:String ) : String; + + /** + @see http://php.net/manual/en/function.utf8-decode.php + **/ + static function utf8_decode( data:String ) : String; + + /** + @see http://php.net/manual/en/function.mb-convert-encoding.php + **/ + static function mb_convert_encoding( str:String, to_encoding:String, ?from_encoding:Dynamic ) : String; + + /** + @see http://php.net/manual/en/function.mb-check-encoding.php + **/ + static function mb_check_encoding( str:String = null, ?encoding:String ) : Bool; + + /** + @see http://php.net/manual/en/function.mb-strlen.php + **/ + static function mb_strlen( str:String, ?encoding:String ) : EitherType; + + /** + @see http://php.net/manual/en/function.mb-substr.php + **/ + static function mb_substr( str:String, start:Int, length:Int = null, ?encoding:String ) : String; + + /** + @see http://php.net/manual/en/function.proc-open.php + **/ + static function proc_open( cmd:String, descriptorspec:NativeArray, pipes:NativeIndexedArray, ?cwd:String, ?env:NativeArray, ?other_options:NativeArray ) : EitherType; + + /** + @see http://php.net/manual/en/function.proc-get-status.php + **/ + static function proc_get_status( process:Resource ) : EitherType>; + + /** + @see http://php.net/manual/en/function.proc-close.php + **/ + static function proc_close( process:Resource ) : Int; + + /** + @see http://php.net/manual/en/function.proc-terminate.php + **/ + static function proc_terminate( process:Resource, signal:Int = 15 ) : Bool; + + /** + @see http://php.net/manual/en/function.stream-select.php + **/ + static function stream_select( read:NativeArray, write:NativeArray, except:NativeArray, tv_sec:Int, tv_usec:Int = 0 ) : Bool; + + /** + @see http://php.net/manual/en/function.stream-socket-shutdown.php + **/ + static function stream_socket_shutdown( stream:Resource, how:Int ) : Bool; + + /** + @see http://php.net/manual/en/function.stream-set-timeout.php + **/ + static function stream_set_timeout( stream:Resource, seconds:Int, microseconds:Int = 0 ) : Bool; + + /** + @see http://php.net/manual/en/function.stream-set-blocking.php + **/ + static function stream_set_blocking( stream:Resource, mode:Bool ) : Bool; + + /** + @see http://php.net/manual/en/function.stream-socket-accept.php + **/ + static function stream_socket_accept( server_socket:Resource, ?timeout:Float, ?peername:Ref ) : EitherType; + + /** + @see http://php.net/manual/en/function.stream-socket-client.php + **/ + static function stream_socket_client( remote_socket:String, ?errno:Ref, ?errstr:Ref, ?timeout:Float, ?flags:Int, ?context:Resource ) : EitherType; + + /** + @see http://php.net/manual/en/function.stream-socket-server.php + **/ + static function stream_socket_server( local_socket:String, ?errno:Ref, ?errstr:Ref, ?flags:Int, ?context:Resource ) : EitherType; + + /** + @see http://php.net/manual/en/function.stream-socket-get-name.php + **/ + static function stream_socket_get_name( stream:Resource, want_peer:Bool ) : EitherType; + + /** + @see http://php.net/manual/en/function.ini-get.php + **/ + static function ini_get( var_name:String ) : EitherType; + + /** + @see http://php.net/manual/en/function.ini-set.php + **/ + static function ini_set( var_name:String, newvalue:String ) : EitherType; + + /** + @see http://php.net/manual/en/function.sqlite-error-string.php + **/ + static function sqlite_error_string( error_code:Int ) : String; + + /** + @see http://php.net/manual/en/function.sqlite-escape-string.php + **/ + static function sqlite_escape_string( item:String ) : String; + + /** + @see http://php.net/manual/en/function.set-time-limit.php + **/ + static function set_time_limit( seconds:Int ) : Bool; + + /** + @see http://php.net/manual/en/function.function-exists.php + **/ + static function function_exists( function_name:String ) : Bool; + + /** + @see http://php.net/manual/en/function.getallheaders.php + **/ + static function getallheaders() : NativeAssocArray; + + /** + @see http://php.net/manual/en/function.ucwords.php + **/ + static function ucwords( str:String, ?delimiters:String ) : String; + + /** + @see http://php.net/manual/en/function.base64-encode.php + **/ + static function base64_encode( data:String ) : EitherType; + + /** + @see http://php.net/manual/en/function.base64-decode.php + **/ + static function base64_decode( data:String, strict:Bool = false ) : EitherType; + + /** + @see http://php.net/manual/en/function.gethostbyname.php + **/ + static function gethostbyname( hostname:String ) : String; + + /** + @see http://php.net/manual/en/function.gethostbyaddr.php + **/ + static function gethostbyaddr( ip_address:String ) : EitherType; + + /** + @see http://php.net/manual/en/function.getprotobyname.php + **/ + static function getprotobyname( name:String ) : EitherType; + + /** + @see http://php.net/manual/en/function.mktime.php + **/ + static function mktime( ?hour:Int, ?minute:Int, ?second:Int, ?month:Int, ?day:Int, ?year:Int, ?is_dst:Int ) : EitherType; + + /** + @see http://php.net/manual/en/function.date.php + **/ + static function date( format:String, ?timestamp:Int ) : EitherType; + + /** + @see http://php.net/manual/en/function.strtotime.php + **/ + static function strtotime( time:String, ?now:Int ) : EitherType; + + /** + @see http://php.net/manual/en/function.flush.php + **/ + static function flush() : Void; + + /** + @see http://php.net/manual/en/function.session-cache-limiter.php + **/ + static function session_cache_limiter( ?cache_limiter:String ) : String; + + /** + @see http://php.net/manual/en/function.session-cache-expire.php + **/ + static function session_cache_expire( ?new_cache_expire:Int ) : Int; + + /** + @see http://php.net/manual/en/function.session-name.php + **/ + static function session_name( ?name:String ) : String; + + /** + @see http://php.net/manual/en/function.session-start.php + **/ + static function session_start( ?options:NativeArray ) : Bool; + + /** + @see http://php.net/manual/en/function.session-unset.php + **/ + static function session_unset() : Void; + + /** + @see http://php.net/manual/en/function.session-write-close.php + **/ + static function session_write_close() : Void; + + /** + @see http://php.net/manual/en/function.session-id.php + **/ + static function session_id( ?id:String ) : String; + + /** + @see http://php.net/manual/en/function.session-save-path.php + **/ + static function session_save_path( ?path:String ) : String; + + /** + @see http://php.net/manual/en/function.session-module-name.php + **/ + static function session_module_name( ?module:String ) : String; + + /** + @see http://php.net/manual/en/function.session-regenerate-id.php + **/ + static function session_regenerate_id( delete_old_session:Bool = false ) : Bool; + + /** + @see http://php.net/manual/en/function.session-set-cookie-params.php + **/ + static function session_set_cookie_params( lifetime:Int, ?path:String, ?domain:String, secure:Bool = false, httponly:Bool = false ) : Bool; + + /** + @see http://php.net/manual/en/function.session-get-cookie-params.php + **/ + static function session_get_cookie_params() : NativeAssocArray; + + /** + @see http://php.net/manual/en/function.session-set-save-handler.php + **/ + @:overload(function( sessionhandler:SessionHandlerInterface, register_shutdown:Bool = true ) : Bool {}) + static function session_set_save_handler( open:String->String->Bool, close:Void->Bool, read:String->String, write:String->String->Bool, destroy:String->Bool, gc:Int->Bool, ?create_sid:Void->String, ?validate_sid:Function, ?update_timestamp:Function ) : Bool; +} \ No newline at end of file diff --git a/std/js/html/Clipboard.hx b/std/php7/IteratorAggregate.hx similarity index 76% rename from std/js/html/Clipboard.hx rename to std/php7/IteratorAggregate.hx index 62b36206..fd7852c7 100644 --- a/std/js/html/Clipboard.hx +++ b/std/php7/IteratorAggregate.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,9 +19,14 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +package php; -package js.html; - -/** @deprecated Use DataTransfer instead. */ -@:deprecated("Clipboard is deprecated, use DataTransfer instead") -typedef Clipboard = DataTransfer; +@:native('IteratorAggregate') +extern interface IteratorAggregate { + /** + This method is not public to not induce Haxe users to use it ;) + Use iterator() instead. + The return type would be Aggregator that is unusable in Haxe + **/ + private function getIterator() : Iterator; // +} \ No newline at end of file diff --git a/std/php7/Lib.hx b/std/php7/Lib.hx new file mode 100644 index 00000000..07366045 --- /dev/null +++ b/std/php7/Lib.hx @@ -0,0 +1,152 @@ +/* + * Copyright (C)2005-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 php; + +import haxe.ds.StringMap; + +/** + Platform-specific PHP Library. Provides some platform-specific functions + for the PHP target, such as conversion from Haxe types to native types + and vice-versa. +**/ +class Lib { + /** + Print the specified value on the default output. + **/ + public static inline function print( v : Dynamic ) : Void { + Global.echo(Std.string(v)); + } + + /** + Print the specified value on the default output followed by + a newline character. + **/ + public static function println( v : Dynamic ) : Void { + print(v); + print("\n"); + } + + /** + Displays structured information about one or more expressions + that includes its type and value. Arrays and objects are + explored recursively with values indented to show structure. + */ + public static inline function dump(v : Dynamic) : Void { + Global.var_dump(v); + } + + /** + Serialize using native PHP serialization. This will return a binary + `String` that can be stored for long term usage. + **/ + public static inline function serialize( v : Dynamic ) : String { + return Global.serialize(v); + } + + /** + Unserialize a `String` using native PHP serialization. See `php.Lib.serialize()`. + **/ + public static inline function unserialize( s : String ) : Dynamic { + return Global.unserialize(s); + } + + /** + Find out whether an extension is loaded. + */ + public static inline function extensionLoaded(name : String) { + return Global.extension_loaded(name); + } + + public static inline function isCli() : Bool { + return 0 == Global.strncasecmp(Const.PHP_SAPI, 'cli', 3); + } + + /** + Output file content from the given file name. + */ + public static inline function printFile(file : String) { + return Global.fpassthru(Global.fopen(file, "r")); + } + + public static inline function toPhpArray(a : Array) : NativeArray { + return @:privateAccess a.arr; + } + + public static inline function toHaxeArray(a : NativeArray) : Array { + return @:privateAccess Array.wrap(a); + } + + public static function hashOfAssociativeArray(arr : NativeAssocArray) : Map { + var result = new StringMap(); + @:privateAccess result.data = arr; + return result; + } + + public static inline function associativeArrayOfHash(hash : haxe.ds.StringMap) : NativeArray { + return @:privateAccess hash.data; + } + + public static inline function objectOfAssociativeArray(arr : NativeArray) : Dynamic { + return Boot.createAnon(arr); + } + + public static inline function associativeArrayOfObject(ob : Dynamic) : NativeArray { + return Syntax.array(ob); + } + + /** + * See the documentation for the equivalent PHP function for details on usage: + * + * @param to + * @param subject + * @param message + * @param ?additionalHeaders + * @param ?additionalParameters + */ + public static function mail(to : String, subject : String, message : String, ?additionalHeaders : String, ?additionalParameters : String) : Bool + { + throw "Not implemented"; + } + + /** + For neko compatibility only. + **/ + public static function rethrow( e : Dynamic ) { + throw "Not implemented"; + } + + static function appendType(o : Dynamic, path : Array, t : Dynamic) { + throw "Not implemented"; + } + + public static function getClasses() { + throw "Not implemented"; + } + + /** + * Loads types defined in the specified directory. + */ + public static function loadLib(pathToLib : String) : Void + { + throw "Not implemented"; + } +} diff --git a/std/php7/NativeArray.hx b/std/php7/NativeArray.hx new file mode 100644 index 00000000..41590b1f --- /dev/null +++ b/std/php7/NativeArray.hx @@ -0,0 +1,67 @@ +/* + * Copyright (C)2005-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 php; + +using php.Global; + +/** + Native PHP array. +**/ +@:coreType @:runtimeValue abstract NativeArray { + public inline function new() + this = Syntax.arrayDecl(); + + @:arrayAccess function getByInt(key:Int):Dynamic; + @:arrayAccess function setByInt(key:Int, val:Dynamic):Dynamic; + @:arrayAccess function getByFloat(key:Float):Dynamic; + @:arrayAccess function setByFloat(key:Float, val:Dynamic):Dynamic; + @:arrayAccess function getByString(key:String):Dynamic; + @:arrayAccess function setByString(key:String, val:Dynamic):Dynamic; + @:arrayAccess function getByBool(key:Bool):Dynamic; + @:arrayAccess function setByBool(key:Bool, val:Dynamic):Dynamic; + + public inline function iterator() + return new NativeArrayIterator(this); +} + +/** + Allows iterating over native PHP array with Haxe for-loop +**/ +private class NativeArrayIterator { + var arr:NativeArray; + var hasMore:Bool; + + public inline function new( a:NativeArray ) { + arr = a; + hasMore = (arr.reset() != false); + } + + public inline function hasNext() : Bool { + return hasMore; + } + + public inline function next() : Dynamic { + var result = arr.current(); + hasMore = (arr.next() != false); + return result; + } +} diff --git a/std/php7/NativeAssocArray.hx b/std/php7/NativeAssocArray.hx new file mode 100644 index 00000000..7bec6831 --- /dev/null +++ b/std/php7/NativeAssocArray.hx @@ -0,0 +1,40 @@ +/* + * Copyright (C)2005-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 php; + +@:forward +abstract NativeAssocArray(NativeArray) from NativeArray to NativeArray { + public inline function new() + this = Syntax.arrayDecl(); + + @:arrayAccess + inline function get(key:String):T + return this[key]; + + @:arrayAccess + inline function set(key:String, val:T):T + return this[key] = val; + + //TODO + // @:to function toMap():Map + // @:from static function fromMap(map:Map):NativeAssocArray +} diff --git a/std/php7/NativeIndexedArray.hx b/std/php7/NativeIndexedArray.hx new file mode 100644 index 00000000..6319ffec --- /dev/null +++ b/std/php7/NativeIndexedArray.hx @@ -0,0 +1,44 @@ +/* + * Copyright (C)2005-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 php; + +@:forward +abstract NativeIndexedArray(NativeArray) from NativeArray to NativeArray { + public inline function new() + this = Syntax.arrayDecl(); + + @:arrayAccess + inline function get(idx:Int):T + return this[idx]; + + @:arrayAccess + inline function set(idx:Int, val:T):T + return this[idx] = val; + + @:to + inline function toHaxeArray():Array + return @:privateAccess Array.wrap(this); + + @:from + static inline function fromHaxeArray(a:Array):NativeIndexedArray + return @:privateAccess a.arr; +} \ No newline at end of file diff --git a/std/php7/NativeString.hx b/std/php7/NativeString.hx new file mode 100644 index 00000000..644d85ab --- /dev/null +++ b/std/php7/NativeString.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-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 php; + +/** + Native PHP string. +**/ +@:coreType @:runtimeValue abstract NativeString from String to String { + + @:arrayAccess function get(key:Int):String; + @:arrayAccess function set(key:Int, val:String):String; +} \ No newline at end of file diff --git a/std/php7/Ref.hx b/std/php7/Ref.hx new file mode 100644 index 00000000..55d1ecb6 --- /dev/null +++ b/std/php7/Ref.hx @@ -0,0 +1,7 @@ +package php; + +/** + Special type which allows passing function arguments by reference. + This type should be used for externs only. +**/ +typedef Ref = T; \ No newline at end of file diff --git a/std/php7/Resource.hx b/std/php7/Resource.hx new file mode 100644 index 00000000..f2b43532 --- /dev/null +++ b/std/php7/Resource.hx @@ -0,0 +1,7 @@ +package php; + +import sys.io.File.FileHandle; + +abstract Resource(Dynamic) { + +} \ No newline at end of file diff --git a/std/php7/RuntimeException.hx b/std/php7/RuntimeException.hx new file mode 100644 index 00000000..258f4c02 --- /dev/null +++ b/std/php7/RuntimeException.hx @@ -0,0 +1,4 @@ +package php; + +@:native('RuntimeException') +extern class RuntimeException extends Exception {} \ No newline at end of file diff --git a/std/php7/Scalar.hx b/std/php7/Scalar.hx new file mode 100644 index 00000000..b201aa0f --- /dev/null +++ b/std/php7/Scalar.hx @@ -0,0 +1,9 @@ +package php; + +import haxe.extern.EitherType; + + +/** + `Scalar` is a type that is compatible with any scalar value (int, float, bool, string) +**/ +typedef Scalar = EitherType>>; \ No newline at end of file diff --git a/std/php7/Session.hx b/std/php7/Session.hx new file mode 100644 index 00000000..78e2c4b5 --- /dev/null +++ b/std/php7/Session.hx @@ -0,0 +1,171 @@ +/* + * Copyright (C)2005-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 php; + +import php.Boot; +import php.Global.*; +import php.SuperGlobal.*; + +/** + Session consists of a way to preserve certain data across + subsequent accesses. +*/ +class Session { + public static function getCacheLimiter() { + switch(session_cache_limiter()) { + case "public": + return Public; + case "private": + return Private; + case "nocache": + return NoCache; + case "private_no_expire": + return PrivateNoExpire; + } + return null; + } + + public static function setCacheLimiter(l : CacheLimiter) { + if(started) throw "You can't set the cache limiter while the session is already in use"; + switch(l) { + case Public: + session_cache_limiter("public"); + case Private: + session_cache_limiter("private"); + case NoCache: + session_cache_limiter("nocache"); + case PrivateNoExpire: + session_cache_limiter("private_no_expire"); + } + } + + public static function getCacheExpire() : Int { + return session_cache_expire(); + } + + public static function setCacheExpire(minutes : Int) { + if(started) throw "You can't set the cache expire time while the session is already in use"; + session_cache_expire(minutes); + } + + public static function setName(name : String) { + if(started) throw "You can't set the name while the session is already in use"; + session_name(name); + } + + public static function getName() : String { + return session_name(); + } + + public static function getId() : String { + return session_id(); + } + + public static function setId(id : String) { + if(started) throw "You can't set the session id while the session is already in use"; + session_id(id); + } + + public static function getSavePath() : String { + return session_save_path(); + } + + public static function setSavePath(path : String) { + if(started) throw "You can't set the save path while the session is already in use"; + session_save_path(path); + } + + public static function getModule() : String { + return session_module_name(); + } + + public static function setModule(module : String) { + if(started) throw "You can't set the module while the session is already in use"; + session_module_name(module); + } + + public static function regenerateId(?deleteold : Bool) : Bool { + return session_regenerate_id(deleteold); + } + + public static function get(name : String) : Dynamic { + start(); + if(!isset(_SESSION[name])) return null; + return _SESSION[name]; + } + + public static function set(name : String, value : Dynamic) { + start(); + return _SESSION[name] = value; + } + + public static function setCookieParams(?lifetime : Int, ?path : String, ?domain : String, ?secure : Bool, ?httponly : Bool) { + if(started) throw "You can't set the cookie params while the session is already in use"; + session_set_cookie_params(lifetime, path, domain, secure, httponly); + } + + public static function getCookieParams() : { lifetime : Int, path : String, domain : String, secure : Bool, httponly : Bool} { + return Boot.createAnon(session_get_cookie_params()); + } + + // TODO: completely untested + public static function setSaveHandler(open : String -> String -> Bool, close : Void -> Bool, read : String -> String, write : String -> String -> Bool, destroy, gc) : Bool { + return session_set_save_handler(open, close, read, write, destroy, gc); + } + + public static function exists(name : String) { + start(); + return array_key_exists(name, _SESSION); + } + + public static function remove(name : String) { + start(); + unset(_SESSION[name]); + } + + public static var started(default, null) : Bool; + public static function start() { + if(started) return; + started = true; + session_start(); + } + + public static function clear() { + session_unset(); + } + + public static function close() { + session_write_close(); + started = false; // TODO: not sure this useful; test if a closed session can be re-opened (I doubt) + } + + static function __init__() { + started = isset(_SESSION); + } +} + +enum CacheLimiter { + Public; + Private; + NoCache; + PrivateNoExpire; +} diff --git a/std/php7/SessionHandlerInterface.hx b/std/php7/SessionHandlerInterface.hx new file mode 100644 index 00000000..51def6cc --- /dev/null +++ b/std/php7/SessionHandlerInterface.hx @@ -0,0 +1,14 @@ +package php; + +/** + @see http://php.net/manual/en/class.sessionhandlerinterface.php +**/ +@:native('SessionHandlerInterface') +extern interface SessionHandlerInterface { + function close() : Bool; + function destroy( session_id:String ) : Bool; + function gc( maxlifetime:Int ) : Bool; + function open( save_path:String, session_name:String ) : Bool; + function read( session_id:String ) : String; + function write( session_id:String, session_data:String ) : Bool; +} \ No newline at end of file diff --git a/std/php7/StdClass.hx b/std/php7/StdClass.hx new file mode 100644 index 00000000..64179a75 --- /dev/null +++ b/std/php7/StdClass.hx @@ -0,0 +1,7 @@ +package php; + +@:native('StdClass') +@:phpNoConstructor +extern class StdClass implements Dynamic { + function new() : Void; +} \ No newline at end of file diff --git a/std/php7/SuperGlobal.hx b/std/php7/SuperGlobal.hx new file mode 100644 index 00000000..885bb93e --- /dev/null +++ b/std/php7/SuperGlobal.hx @@ -0,0 +1,60 @@ +package php; + + + +class SuperGlobal { + /** + @see http://php.net/manual/en/reserved.variables.globals.php + **/ + public static var GLOBALS (get,never):NativeAssocArray; + static inline function get_GLOBALS() return untyped __php__("$GLOBALS"); + + /** + @see http://php.net/manual/en/reserved.variables.server.php + **/ + public static var _SERVER (get,never):NativeAssocArray; + static inline function get__SERVER() return untyped __php__("$_SERVER"); + + /** + @see http://php.net/manual/en/reserved.variables.get.php + **/ + public static var _GET (get,never):NativeAssocArray; + static inline function get__GET() return untyped __php__("$_GET"); + + /** + @see http://php.net/manual/en/reserved.variables.post.php + **/ + public static var _POST (get,never):NativeAssocArray; + static inline function get__POST() return untyped __php__("$_POST"); + + /** + @see http://php.net/manual/en/reserved.variables.files.php + **/ + public static var _FILES (get,never):NativeAssocArray; + static inline function get__FILES() return untyped __php__("$_FILES"); + + /** + @see http://php.net/manual/en/reserved.variables.cookie.php + **/ + public static var _COOKIE (get,never):NativeAssocArray; + static inline function get__COOKIE() return untyped __php__("$_COOKIE"); + + /** + @see http://php.net/manual/en/reserved.variables.session.php + **/ + public static var _SESSION (get,never):NativeAssocArray; + static inline function get__SESSION() return untyped __php__("$_SESSION"); + + /** + @see http://php.net/manual/en/reserved.variables.request.php + **/ + public static var _REQUEST (get,never):NativeAssocArray; + static inline function get__REQUEST() return untyped __php__("$_REQUEST"); + + /** + @see http://php.net/manual/en/reserved.variables.env.php + **/ + public static var _ENV (get,never):NativeAssocArray; + static inline function get__ENV() return untyped __php__("$_ENV"); + +} \ No newline at end of file diff --git a/std/php7/Syntax.hx b/std/php7/Syntax.hx new file mode 100644 index 00000000..ac41e85f --- /dev/null +++ b/std/php7/Syntax.hx @@ -0,0 +1,127 @@ +package php; + +import haxe.extern.Rest; +import haxe.extern.AsVar; +import haxe.extern.EitherType; + +/** + Special extern class to support PHP language specifics. + Don't use these functions unless you are really sure what you are doing. +**/ +extern class Syntax { + /** + This method allows to force specified binary operation for `left` and `right` values. + `operator` must be a constant string like "+" or "==". + **/ + static function binop( left:Dynamic, operator:String, right:Dynamic ) : Dynamic; + + /** + Generates `(int)$value` + **/ + static function int( value:Dynamic ) : Int; + + /** + Generates `(float)$value` + **/ + static function float( value:Dynamic ) : Float; + + /** + Generates `(string)$value` + **/ + static function string( value:Dynamic ) : String; + + /** + Generates `(bool)$value` + **/ + static function bool( value:Dynamic ) : Bool; + + /** + Generates `(object)$value` + **/ + static function object( value:Dynamic ) : Dynamic; + + /** + Generates `(array)$value` + **/ + static function array( value:Dynamic ) : NativeArray; + + /** + Ggenerates `$value instanceof $phpClassName`. + Haxe generates `Std.is(value, Type)` calls to `$value instanceof Type` automatically where possible. + `type` only accepts direct class names. That means `Type.resolveClass('MyClass')` is not allowed, but `MyClass` is. + **/ + static function instanceof( value:AsVar, type:AsVar> ) : Bool; + + /** + ``` + PHP.foreach(collection, function(key, value) trace(key, value)); + ``` + generates: + ``` + foreach($collection as $key => $value) { + trace($key, $value); + } + ``` + **/ + static function foreach( collection:TCollection, body:TKey->TValue->Void ) : Void; + + /** + Generates `new $className($arg1, ...$argN)` + **/ + static function construct( className:AsVar, args:Rest) : Dynamic; + + /** + Generates instance field access for reading on `object` + **/ + static function getField( object:AsVar, fieldName:AsVar ) : Dynamic; + + /** + Generates instance field access for writing on `object` + **/ + static function setField( object:AsVar, fieldName:AsVar, value:Dynamic ) : Void; + + /** + Generates static field access for reading on `className` + **/ + static function getStaticField( className:AsVar,String>>, fieldName:AsVar ) : Dynamic; + + /** + Generates static field access for writing on `object` + **/ + static function setStaticField( object:AsVar,String>>, fieldName:AsVar, value:Dynamic ) : Void; + + /** + Generates a call to instance method: `$object->{$methodName}()` + **/ + static function call( object:AsVar, methodName:AsVar, args:Rest ) : Dynamic; + /** + Generates a call to static method: `$className::{$methodName}()` + **/ + static function staticCall( className:AsVar,String>>, methodName:AsVar, args:Rest ) : Dynamic; + + /** + ``` + PHP.arrayDecl(arg1, arg2, arg3); + ``` + Generates native array declaration: + ``` + [$arg1, $arg2, $arg3] + ``` + **/ + static function arrayDecl( args:Rest ) : NativeIndexedArray; + + /** + Don't let compiler to optimize away local var passed to this method. + **/ + static function keepVar( localVar:Dynamic ) : Void; + + /** + Adds `...` operator before `args` + **/ + static function splat( args:EitherType ) : Rest; + + /** + Add errors suppression operator `@` before `expression` + **/ + static function suppress( expression:T ) : T; +} \ No newline at end of file diff --git a/std/php7/Throwable.hx b/std/php7/Throwable.hx new file mode 100644 index 00000000..80cc5ee7 --- /dev/null +++ b/std/php7/Throwable.hx @@ -0,0 +1,16 @@ +package php; + +/** + @see http://php.net/manual/en/class.throwable.php +**/ +@:native('Throwable') +extern interface Throwable { + function getPrevious() : Throwable; // Returns previous Throwable + function getMessage() : String; // message of the exception + function getCode() : Int; // code of the exception + function getFile() : String; // source filename + function getLine() : Int; // source line + function getTrace() : NativeIndexedArray>; // an array of the backtrace + function getTraceAsString() : String; // formated string of trace + @:phpMagic function __toString() : String; // formated string for display +} \ No newline at end of file diff --git a/std/php7/Traversable.hx b/std/php7/Traversable.hx new file mode 100644 index 00000000..ee15e051 --- /dev/null +++ b/std/php7/Traversable.hx @@ -0,0 +1,7 @@ +package php; + +/** + @see http://php.net/manual/en/class.traversable.php +**/ +@:native('Traversable') +extern interface Traversable {} \ No newline at end of file diff --git a/std/php7/Web.hx b/std/php7/Web.hx new file mode 100644 index 00000000..1209a201 --- /dev/null +++ b/std/php7/Web.hx @@ -0,0 +1,420 @@ +/* + * Copyright (C)2005-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 php; + +import haxe.io.Bytes; +import php.Syntax.*; +import php.Global.*; +import php.SuperGlobal.*; + +/** + This class is used for accessing the local Web server and the current + client request and informations. +**/ +class Web { + + /** + Returns the GET and POST parameters. + **/ + public static function getParams() : Map { + #if force_std_separator + var h = Lib.hashOfAssociativeArray(_POST); + var params = getParamsString(); + if( params == "" ) + return h; + for( p in ~/[;&]/g.split(params) ) { + var a = p.split("="); + var n = a.shift(); + h.set(StringTools.urlDecode(n),StringTools.urlDecode(a.join("="))); + } + return h; + #else + return Lib.hashOfAssociativeArray(array_merge(_GET, _POST)); + #end + } + + /** + Returns an Array of Strings built using GET / POST values. + If you have in your URL the parameters `a[]=foo;a[]=hello;a[5]=bar;a[3]=baz` then + `php.Web.getParamValues("a")` will return `["foo","hello",null,"baz",null,"bar"]`. + **/ + public static function getParamValues( param : String ) : Array { + var reg = new EReg("^"+param+"(\\[|%5B)([0-9]*?)(\\]|%5D)=(.*?)$", ""); + var res = new Array(); + var explore = function(data:String){ + if (data == null || data.length == 0) + return; + for (part in data.split("&")){ + if (reg.match(part)){ + var idx = reg.matched(2); + var val = StringTools.urlDecode(reg.matched(4)); + if (idx == "") + res.push(val); + else + res[Std.parseInt(idx)] = val; + } + } + } + explore(StringTools.replace(getParamsString(), ";", "&")); + explore(getPostData()); + + if (res.length == 0) { + var post:haxe.ds.StringMap = Lib.hashOfAssociativeArray(_POST); + var data = post.get(param); + if (is_array(data)) { + foreach(data, function(key:Int, value:String) { + res[key] = value; + }); + } + } + + if (res.length == 0) + return null; + return res; + } + + /** + Returns the local server host name. + **/ + public static inline function getHostName() : String { + return _SERVER['SERVER_NAME']; + } + + /** + Surprisingly returns the client IP address. + **/ + public static inline function getClientIP() : String { + return _SERVER['REMOTE_ADDR']; + } + + /** + Returns the original request URL (before any server internal redirections). + **/ + public static function getURI() : String { + var s : String = _SERVER['REQUEST_URI']; + return s.split("?")[0]; + } + + /** + Tell the client to redirect to the given url ("Location" header). + **/ + public static function redirect( url : String ) { + header("Location: " + url); + } + + /** + Set an output header value. If some data have been printed, the headers have + already been sent so this will raise an exception. + **/ + public static inline function setHeader( h : String, v : String ) { + header('$h: $v'); + } + + /** + Set the HTTP return code. Same remark as `php.Web.setHeader()`. + See status code explanation here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html + **/ + public static function setReturnCode( r : Int ) { + var code : String; + switch(r) { + case 100: code = "100 Continue"; + case 101: code = "101 Switching Protocols"; + case 200: code = "200 OK"; + case 201: code = "201 Created"; + case 202: code = "202 Accepted"; + case 203: code = "203 Non-Authoritative Information"; + case 204: code = "204 No Content"; + case 205: code = "205 Reset Content"; + case 206: code = "206 Partial Content"; + case 300: code = "300 Multiple Choices"; + case 301: code = "301 Moved Permanently"; + case 302: code = "302 Found"; + case 303: code = "303 See Other"; + case 304: code = "304 Not Modified"; + case 305: code = "305 Use Proxy"; + case 307: code = "307 Temporary Redirect"; + case 400: code = "400 Bad Request"; + case 401: code = "401 Unauthorized"; + case 402: code = "402 Payment Required"; + case 403: code = "403 Forbidden"; + case 404: code = "404 Not Found"; + case 405: code = "405 Method Not Allowed"; + case 406: code = "406 Not Acceptable"; + case 407: code = "407 Proxy Authentication Required"; + case 408: code = "408 Request Timeout"; + case 409: code = "409 Conflict"; + case 410: code = "410 Gone"; + case 411: code = "411 Length Required"; + case 412: code = "412 Precondition Failed"; + case 413: code = "413 Request Entity Too Large"; + case 414: code = "414 Request-URI Too Long"; + case 415: code = "415 Unsupported Media Type"; + case 416: code = "416 Requested Range Not Satisfiable"; + case 417: code = "417 Expectation Failed"; + case 500: code = "500 Internal Server Error"; + case 501: code = "501 Not Implemented"; + case 502: code = "502 Bad Gateway"; + case 503: code = "503 Service Unavailable"; + case 504: code = "504 Gateway Timeout"; + case 505: code = "505 HTTP Version Not Supported"; + default: code = Std.string(r); + } + header("HTTP/1.1 " + code, true, r); + } + + /** + Retrieve a client header value sent with the request. + **/ + public static function getClientHeader( k : String ) : String { + return loadClientHeaders().get(k); + } + + + private static var _clientHeaders : Map; + /** + Based on https://github.com/ralouphie/getallheaders + **/ + static function loadClientHeaders():Map { + if(_clientHeaders != null) return _clientHeaders; + + _clientHeaders = new Map(); + + if(function_exists('getallheaders')) { + foreach(getallheaders(), function(key:String, value:Dynamic) { + _clientHeaders.set(key, Std.string(value)); + }); + return _clientHeaders; + } + + var copyServer = [ + 'CONTENT_TYPE' => 'Content-Type', + 'CONTENT_LENGTH' => 'Content-Length', + 'CONTENT_MD5' => 'Content-Md5' + ]; + foreach(_SERVER, function(key:String, value:Dynamic) { + if((substr(key, 0, 5):String) == 'HTTP_') { + key = substr(key, 5); + if(!copyServer.exists(key) || !isset(_SERVER[key])) { + key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', key)))); + _clientHeaders[key] = Std.string(value); + } + } else if(copyServer[key] != null) { + _clientHeaders[copyServer[key]] = Std.string(value); + } + }); + if(!_clientHeaders.exists('Authorization')) { + if(isset(_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) { + _clientHeaders['Authorization'] = Std.string(_SERVER['REDIRECT_HTTP_AUTHORIZATION']); + } else if(isset(_SERVER['PHP_AUTH_USER'])) { + var basic_pass = isset(_SERVER['PHP_AUTH_PW']) ? Std.string(_SERVER['PHP_AUTH_PW']) : ''; + _clientHeaders['Authorization'] = 'Basic ' + base64_encode(_SERVER['PHP_AUTH_USER'] + ':' + basic_pass); + } else if(isset(_SERVER['PHP_AUTH_DIGEST'])) { + _clientHeaders['Authorization'] = Std.string(_SERVER['PHP_AUTH_DIGEST']); + } + } + + return _clientHeaders; + } + + /** + Retrieve all the client headers. + **/ + public static function getClientHeaders():List<{value:String, header:String}> { + var headers = loadClientHeaders(); + var result = new List(); + for(key in headers.keys()) { + result.push({value:headers.get(key), header:key}); + } + return result; + } + + /** + Returns all the GET parameters `String` + **/ + public static function getParamsString() : String { + if(isset(_SERVER['QUERY_STRING'])) + return _SERVER['QUERY_STRING']; + else + return ""; + } + + /** + Returns all the POST data. POST Data is always parsed as + being application/x-www-form-urlencoded and is stored into + the getParams hashtable. POST Data is maximimized to 256K + unless the content type is multipart/form-data. In that + case, you will have to use `php.Web.getMultipart()` or + `php.Web.parseMultipart()` methods. + **/ + public static function getPostData() { + var h = fopen("php://input", "r"); + var bsize = 8192; + var max = 32; + var data : String = null; + var counter = 0; + while (!feof(h) && counter < max) { + data += fread(h, bsize); + counter++; + } + fclose(h); + return data; + } + + /** + Returns an hashtable of all Cookies sent by the client. + Modifying the hashtable will not modify the cookie, use `php.Web.setCookie()` + instead. + **/ + public static function getCookies():Map { + return Lib.hashOfAssociativeArray(_COOKIE); + } + + + /** + Set a Cookie value in the HTTP headers. Same remark as `php.Web.setHeader()`. + **/ + public static function setCookie( key : String, value : String, ?expire: Date, ?domain: String, ?path: String, ?secure: Bool, ?httpOnly: Bool ) { + var t = expire == null ? 0 : Std.int(expire.getTime()/1000.0); + if(path == null) path = '/'; + if(domain == null) domain = ''; + if(secure == null) secure = false; + if(httpOnly == null) httpOnly = false; + setcookie(key, value, t, path, domain, secure, httpOnly); + } + + /** + Returns an object with the authorization sent by the client (Basic scheme only). + **/ + public static function getAuthorization() : { user : String, pass : String } { + if(!isset(_SERVER['PHP_AUTH_USER'])) + return null; + return {user: _SERVER['PHP_AUTH_USER'], pass: _SERVER['PHP_AUTH_PW']}; + } + + /** + Get the current script directory in the local filesystem. + **/ + public static inline function getCwd() : String { + return dirname(_SERVER['SCRIPT_FILENAME']) + "/"; + } + + /** + Get the multipart parameters as an hashtable. The data + cannot exceed the maximum size specified. + **/ + public static function getMultipart( maxSize : Int ) : Map { + var h = new haxe.ds.StringMap(); + var buf : StringBuf = null; + var curname = null; + parseMultipart(function(p,_) { + if( curname != null ) + h.set(curname,buf.toString()); + curname = p; + buf = new StringBuf(); + maxSize -= p.length; + if( maxSize < 0 ) + throw "Maximum size reached"; + }, function(str,pos,len) { + maxSize -= len; + if( maxSize < 0 ) + throw "Maximum size reached"; + buf.addSub(str.toString(),pos,len); + }); + if( curname != null ) + h.set(curname,buf.toString()); + return h; + } + + /** + Parse the multipart data. Call `onPart` when a new part is found + with the part name and the filename if present + and `onData` when some part data is readed. You can this way + directly save the data on hard drive in the case of a file upload. + **/ + public static function parseMultipart( onPart : String -> String -> Void, onData : Bytes -> Int -> Int -> Void ) : Void { + var post = Lib.hashOfAssociativeArray(_POST); + + for (key in post.keys()) + { + onPart(key, ""); + var v = post.get(key); + onData(Bytes.ofString(v), 0, strlen(v)); + } + + if(!isset(_FILES)) return; + var parts : Array = @:privateAccess Array.wrap(array_keys(_FILES)); + for(part in parts) { + var info : NativeAssocArray = _FILES[part]; + var tmp : String = info['tmp_name']; + var file : String = info['name']; + var err : Int = info['error']; + + if(err > 0) { + switch(err) { + case 1: throw "The uploaded file exceeds the max size of " + ini_get('upload_max_filesize'); + case 2: throw "The uploaded file exceeds the max file size directive specified in the HTML form (max is" + ini_get('post_max_size') + ")"; + case 3: throw "The uploaded file was only partially uploaded"; + case 4: continue; // No file was uploaded + case 6: throw "Missing a temporary folder"; + case 7: throw "Failed to write file to disk"; + case 8: throw "File upload stopped by extension"; + } + } + onPart(part, file); + if ("" != file) + { + var h = fopen(tmp, "r"); + var bsize = 8192; + while (!feof(h)) { + var buf : String = fread(h, bsize); + var size : Int = strlen(buf); + onData(Bytes.ofString(buf), 0, size); + } + fclose(h); + } + } + } + + /** + Flush the data sent to the client. By default on Apache, outgoing data is buffered so + this can be useful for displaying some long operation progress. + **/ + public static inline function flush() : Void { + flush(); + } + + /** + Get the HTTP method used by the client. + **/ + public static function getMethod() : String { + if(isset(_SERVER['REQUEST_METHOD'])) + return _SERVER['REQUEST_METHOD']; + else + return null; + } + + public static var isModNeko(default,null) : Bool; + + static function __init__() { + isModNeko = !Lib.isCli(); + } +} diff --git a/std/php7/_std/Array.hx b/std/php7/_std/Array.hx new file mode 100644 index 00000000..88d44712 --- /dev/null +++ b/std/php7/_std/Array.hx @@ -0,0 +1,245 @@ +/* + * Copyright (C)2005-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. + */ +import php.*; + +using php.Global; + +@:coreApi +@:final +class Array implements ArrayAccess { + public var length(default, null):Int; + var arr:NativeIndexedArray; + + public function new() { + arr = new NativeIndexedArray(); + length = 0; + } + + public function concat(a:Array):Array { + return wrap(Global.array_merge(arr, a.arr)); + } + + public function copy():Array { + return wrap(arr); + } + + public function filter(f:T->Bool):Array { + return wrap(Global.array_values(Global.array_filter(arr, f))); + } + + public function indexOf(x:T, ?fromIndex:Int):Int { + if (fromIndex == null) { + var index = Global.array_search(x, arr, true); + if (index == false) { + return -1; + } else { + return index; + } + } + if (fromIndex < 0) fromIndex += length; + if (fromIndex < 0) fromIndex = 0; + while (fromIndex < length) { + if (arr[fromIndex] == x) + return fromIndex; + fromIndex++; + } + return -1; + } + + public function insert(pos:Int, x:T):Void { + length++; + Global.array_splice(arr, pos, 0, Syntax.arrayDecl(x)); + } + + @:keep + public function iterator() : Iterator { + return new ArrayIterator(this); + } + + public function join(sep:String):String { + return Global.implode(sep, Global.array_map('strval', arr)); + } + + public function lastIndexOf(x:T, ?fromIndex:Int):Int { + if (fromIndex == null || fromIndex >= length) fromIndex = length - 1; + if (fromIndex < 0) fromIndex += length; + while (fromIndex >= 0) { + if (arr[fromIndex] == x) + return fromIndex; + fromIndex--; + } + return -1; + } + + public inline function map(f:T->S):Array { + var result = Syntax.arrayDecl(); + for(i in 0...length) { + result[i] = f(arr[i]); + } + return wrap(result); + } + + public inline function pop():Null { + if (length > 0) length--; + return Global.array_pop(arr); + } + + public inline function push(x:T):Int { + arr[length] = x; + return ++length; + } + + public function remove(x:T):Bool { + for (i in 0...length) { + if (arr[i] == x) { + Global.array_splice(arr, i, 1); + length--; + return true; + } + } + return false; + } + + public inline function reverse():Void { + arr = Global.array_reverse(arr); + } + + public inline function shift():Null { + if (length > 0) length--; + return Global.array_shift(arr); + } + + public function slice(pos:Int, ?end:Int):Array { + if (pos < 0) pos += length; + if (pos < 0) pos = 0; + if (end == null) { + return wrap(Global.array_slice(arr, pos)); + } else { + if (end < 0) end += length; + if (end <= pos) { + return []; + } else { + return wrap(Global.array_slice(arr, pos, end - pos)); + } + } + } + + public inline function sort(f:T->T->Int):Void { + arr.usort(f); + } + + public function splice(pos:Int, len:Int):Array { + if (len < 0) return []; + var result = wrap(Global.array_splice(arr, pos, len)); + length -= result.length; + return result; + } + + public inline function unshift(x:T):Void { + length = Global.array_unshift(arr, x); + } + + public function toString():String { + var strings = Syntax.arrayDecl(); + Syntax.foreach(arr, function(index:Int, value:T) { + strings[index] = Boot.stringify(value); + }); + return '[' + Global.implode(',', strings) + ']'; + } + + @:noCompletion + function offsetExists( offset:Int ) : Bool { + return offset < length; + } + + @:noCompletion + function offsetGet( offset:Int ) : Ref { + try { + return arr[offset]; + } catch(e:Dynamic) { + return null; + } + } + + @:noCompletion + function offsetSet( offset:Int, value:T ) : Void { + if (length <= offset) { + arr = Global.array_merge(arr, Global.array_fill(0, offset + 1 - length, null)); + length = offset + 1; + } + arr[offset] = value; + } + + @:noCompletion + function offsetUnset( offset:Int ) : Void { + if (offset >= 0 && offset < length ) { + Global.array_splice(arr, offset, 1); + --length; + } + } + + static function wrap(arr:NativeIndexedArray):Array { + var a = new Array(); + a.arr = arr; + a.length = Global.count(arr); + return a; + } +} + +private class ArrayIterator { + var idx:Int; + var arr:Array; + + public inline function new(arr:Array) { + this.arr = arr; + idx = 0; + } + + public inline function hasNext():Bool { + return idx < arr.length; + } + + public inline function next():T { + return arr[idx++]; + } + + @:keep + @:phpMagic + function __get(method:String) { + return switch(method) { + case 'hasNext', 'next': Boot.closure(this, method); + case _: null; + } + } +} + + +/** + This one is required for `Array` +**/ +@:native('ArrayAccess') +private extern interface ArrayAccess { + private function offsetExists( offset:K ) : Bool; + private function offsetGet( offset:K ) : V; + private function offsetSet( offset:K, value:V ) : Void; + private function offsetUnset( offset:K ) : Void; +} \ No newline at end of file diff --git a/std/php7/_std/Date.hx b/std/php7/_std/Date.hx new file mode 100644 index 00000000..19e92db1 --- /dev/null +++ b/std/php7/_std/Date.hx @@ -0,0 +1,96 @@ +/* + * Copyright (C)2005-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. + */ + +import php.Global.*; +import php.Syntax.*; + +@:coreApi @:final class Date +{ + private var __t : Float; + + public function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void { + __t = mktime(hour, min, sec, month + 1, day, year); + } + + public function getTime() : Float { + return __t * 1000.0; + } + + private function getPhpTime() : Float { + return __t; + } + + public function getFullYear() : Int { + return int(date("Y", int(__t))); + } + + public function getMonth() : Int { + var m : Int = int(date("n", int(__t))); + return -1 + m; + } + + public function getDate() : Int { + return int(date("j", int(__t))); + } + + public function getHours() : Int { + return int(date("G", int(__t))); + } + + public function getMinutes() : Int { + return int(date("i", int(__t))); + } + + public function getSeconds() : Int { + return int(date("s", int(__t))); + } + + public function getDay() : Int { + return int(date("w", int(__t))); + } + + public function toString():String { + return date("Y-m-d H:i:s", int(__t)); + } + + public static function now() : Date { + return fromPhpTime(round(microtime(true), 3)); + } + + static function fromPhpTime( t : Float ) : Date { + var d = new Date(2000, 1, 1, 0, 0, 0); + d.__t = t; + return d; + } + + public static function fromTime( t : Float ) : Date { + var d = new Date(2000, 1, 1, 0, 0, 0); + d.__t = t / 1000; + return d; + } + + public static function fromString( s : String ) : Date { + return fromPhpTime(strtotime(s)); + } +} + + diff --git a/std/php7/_std/EReg.hx b/std/php7/_std/EReg.hx new file mode 100644 index 00000000..4f91a909 --- /dev/null +++ b/std/php7/_std/EReg.hx @@ -0,0 +1,137 @@ +/* + * Copyright (C)2005-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. + */ + +import haxe.extern.EitherType; +import php.*; + +@:coreApi @:final class EReg { + + var r : Dynamic; + var last : String; + var global : Bool; + var pattern : String; + var options : String; + var re : String; + var matches : NativeIndexedArray>>; + + public function new( r : String, opt : String ) : Void { + this.pattern = r; + var a = opt.split("g"); + global = a.length > 1; + if (global) { + opt = a.join(""); + } + this.options = opt; + this.re = '"' + Global.str_replace('"', '\\"', r) + '"' + opt; + } + + public function match( s : String ) : Bool { + var p : Int = Global.preg_match(re, s, matches, Const.PREG_OFFSET_CAPTURE); + + if (p > 0) { + last = s; + } else { + last = null; + } + return p > 0; + } + + public function matched( n : Int ) : String { + if (matches == null || n < 0) throw "EReg::matched"; + // we can't differenciate between optional groups at the end of a match + // that have not been matched and invalid groups + if (n >= Global.count(matches)) return null; + if ((matches[n][1]:Int) < 0) return null; + return matches[n][0]; + } + + public function matchedLeft() : String { + if (Global.count(matches) == 0) throw "No string matched"; + return last.substr(0, matches[0][1]); + } + + public function matchedRight() : String { + if (Global.count(matches) == 0) throw "No string matched"; + var x : Int = (matches[0][1]:Int) + Global.strlen(matches[0][0]); + return last.substr(x); + } + + public function matchedPos() : { pos : Int, len : Int } { + return { + pos : matches[0][1], + len : Global.strlen(matches[0][0]) + }; + } + + public function matchSub( s : String, pos : Int, len : Int = -1):Bool { + var subject = len < 0 ? s : s.substr(0,pos + len); + var p : Int = Global.preg_match(re, subject, matches, Const.PREG_OFFSET_CAPTURE, pos); + if(p > 0) { + last = s; + } + else { + last = null; + } + return p > 0; + } + + public function split( s : String ) : Array { + var parts:NativeArray = Global.preg_split(re, s, (global ? -1 : 2)); + return @:privateAccess Array.wrap(parts); + } + + public function replace( s : String, by : String ) : String { + by = Global.str_replace("\\$", "\\\\$", by); + by = Global.str_replace("$$", "\\$", by); + if (!Global.preg_match('/\\\\([^?].*?\\\\)/', re)) { + by = Global.preg_replace('/\\$(\\d+)/', '\\$\\1', by); + } + return Global.preg_replace(re, by, s, global ? -1 : 1); + } + + public function map( s : String, f : EReg -> String ) : String { + var offset = 0; + var buf = new StringBuf(); + do { + if (offset >= s.length) { + break; + } else if (!matchSub(s, offset)) { + buf.add(s.substr(offset)); + break; + } + var p = matchedPos(); + buf.add(s.substr(offset, p.pos - offset)); + buf.add(f(this)); + if (p.len == 0) { + buf.add(s.substr(p.pos, 1)); + offset = p.pos + 1; + } + else { + offset = p.pos + p.len; + } + } while (global); + if (!global && offset > 0 && offset < s.length) { + buf.add(s.substr(offset)); + } + return buf.toString(); + } +} diff --git a/std/php7/_std/Math.hx b/std/php7/_std/Math.hx new file mode 100644 index 00000000..73b5e540 --- /dev/null +++ b/std/php7/_std/Math.hx @@ -0,0 +1,59 @@ +/* + * Copyright (C)2005-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. + */ + +import php.Global; +import php.Const; +import php.Syntax.*; + +@:coreApi class Math { + public static var PI(default,null) : Float = Const.M_PI; + public static var NaN(default,null) : Float = Const.NAN; + public static var POSITIVE_INFINITY(default,null) : Float = Const.INF; + public static var NEGATIVE_INFINITY(default,null) : Float = -Const.INF; + + public static inline function abs( v:Float ) : Float return Global.abs(v); + public static inline function min( a:Float, b:Float ) : Float return isNaN(a) ? NaN : Global.min(a, b); + public static inline function max( a:Float, b:Float ) : Float return isNaN(b) ? NaN : Global.max(a, b); + public static inline function sin( v:Float ) : Float return Global.sin(v); + public static inline function cos( v:Float ) : Float return Global.cos(v); + public static inline function atan2( y:Float, x:Float ) : Float return Global.atan2(y, x); + public static inline function tan( v:Float ) : Float return Global.tan(v); + public static inline function exp( v:Float ) : Float return Global.exp(v); + public static inline function log( v:Float ) : Float return Global.log(v); + public static inline function sqrt( v:Float ) : Float return Global.sqrt(v); + public static inline function round( v:Float ) : Int return int(Global.floor(v + 0.5)); + public static inline function floor( v:Float ) : Int return int(Global.floor(v)); + public static inline function ceil( v:Float ) : Int return int(Global.ceil(v)); + public static inline function atan( v:Float ) : Float return Global.atan(v); + public static inline function asin( v:Float ) : Float return Global.asin(v); + public static inline function acos( v:Float ) : Float return Global.acos(v); + public static inline function pow( v:Float, exp:Float ) : Float return Global.pow(v, exp); + public static inline function random() : Float return Global.mt_rand() / Global.mt_getrandmax(); + public static inline function isNaN( f:Float ) : Bool return Global.is_nan(f); + public static inline function isFinite( f:Float ) : Bool return Global.is_finite(f); + + public static inline function fround( v:Float ) : Float return Global.floor(v + 0.5); + public static inline function ffloor( v:Float ) : Float return Global.floor(v); + public static inline function fceil( v:Float ) : Float return Global.ceil(v); +} + + diff --git a/std/php7/_std/Reflect.hx b/std/php7/_std/Reflect.hx new file mode 100644 index 00000000..e28b8264 --- /dev/null +++ b/std/php7/_std/Reflect.hx @@ -0,0 +1,174 @@ +/* + * Copyright (C)2005-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. + */ + +import php.Boot; +import php.Syntax; +import php.Closure; +import haxe.Constraints; + +using php.Global; + +@:coreApi class Reflect { + + public static function hasField( o : Dynamic, field : String ) : Bool { + if (!o.is_object()) return false; + if (o.property_exists(field)) return true; + + if (Boot.isClass(o)) { + if (Global.property_exists(o.phpClassName, field)) return true; + return Global.method_exists(o.phpClassName, field); + } + + return false; + } + + public static function field( o : Dynamic, field : String ) : Dynamic { + if (!o.is_object()) return null; + + if (o.property_exists(field)) { + return Syntax.getField(o, field); + } + if (o.method_exists(field)) { + return Boot.closure(o, field); + } + + if (Boot.isClass(o)) { + if (Global.property_exists(o.phpClassName, field)) { + return Syntax.getField(o, field); + } + if (Global.method_exists(o.phpClassName, field)) { + return Boot.closure(o.phpClassName, field); + } + } + + return null; + } + + public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void { + Syntax.setField(o, field, value); + } + + public static function getProperty( o : Dynamic, field : String ) : Dynamic { + if (o.is_object()) { + if (Boot.hasGetter(Global.get_class(o), field)) { + return Syntax.call(o, 'get_$field'); + } else if (Global.method_exists(o, field)) { + return Boot.closure(o, field); + } else { + return Syntax.getField(o, field); + } + } + if (o.is_string() && field == 'length') { + return Global.strlen(o); + } + return null; + } + + public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void { + if (o.is_object()) { + if (Boot.hasSetter(Global.get_class(o), field)) { + Syntax.call(o, 'set_$field', value); + } else { + Syntax.setField(o, field, value); + } + } + } + + public static function callMethod( o : Dynamic, func : Function, args : Array ) : Dynamic { + if (Std.is(func, Closure)) { + if (o != null) { + func = cast cast(func, Closure).bindTo(o); + } + return Global.call_user_func_array(func, @:privateAccess args.arr); + } else { + return Boot.castClosure(func).callWith(o, @:privateAccess args.arr); + } + } + + public static function fields( o : Dynamic ) : Array { + if (Global.is_object(o)) { + return @:privateAccess Array.wrap(Global.get_object_vars(o).array_keys()); + } + return []; + } + + public static inline function isFunction( f : Dynamic ) : Bool { + return Boot.isFunction(f); + } + + public static function compare( a : T, b : T ) : Int { + if (a == b) return 0; + if (Global.is_string(a)){ + return Global.strcmp(cast a, cast b); + } else { + return ((cast a) > (cast b) ? 1 : -1); + } + } + + public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool { + if (Boot.isHxClosure(f1) && Boot.isHxClosure(f2)) { + return f1.equals(f2); + } else { + return f1 == f2; + } + } + + public static function isObject( v : Dynamic ) : Bool { + if (Boot.isEnumValue(v)) { + return false; + } else { + return v.is_object() || v.is_string(); + } + } + + public static inline function isEnumValue( v : Dynamic ) : Bool { + return Boot.isEnumValue(v); + } + + public static function deleteField( o : Dynamic, field : String ) : Bool { + if (hasField(o, field)) { + Global.unset(Syntax.getField(o, field)); + return true; + } else { + return false; + } + } + + public static function copy( o : T ) : T { + if (Global.is_object(o)) { + var fields = Global.get_object_vars(cast o); + var hxAnon = Boot.getHxAnon().phpClassName; + return Syntax.construct(hxAnon, fields); + } else { + return null; + } + } + + @:overload(function( f : Array -> Void ) : Dynamic {}) + public static function makeVarArgs( f : Array -> Dynamic ) : Dynamic { + return function () { + return Global.call_user_func(f, @:privateAccess Array.wrap(Global.func_get_args())); + } + } + + +} diff --git a/std/php7/_std/Std.hx b/std/php7/_std/Std.hx new file mode 100644 index 00000000..8ffd1367 --- /dev/null +++ b/std/php7/_std/Std.hx @@ -0,0 +1,94 @@ +import php.Boot; + +/* + * Copyright (C)2005-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. + */ + +import php.Global; +import php.Const; +import php.Syntax; + +@:keep +@:coreApi class Std { + + public static inline function is( v : Dynamic, t : Dynamic ) : Bool { + return Boot.is(v, t); + } + + public static inline function instance( value : T, c : Class ) : S { + return Boot.is(value, cast c) ? cast value : null; + } + + public static function string( s : Dynamic ) : String { + return Boot.stringify(s); + } + + public static inline function int( x : Float ) : Int { + return Syntax.int(x); + } + + public static function parseInt( x : String ) : Null { + if (Global.is_numeric(x)) { + return Global.intval(x, 10); + } else { + x = Global.ltrim(x); + var firstCharIndex = (x.charAt(0) == '-' ? 1 : 0); + var firstCharCode = x.charCodeAt(firstCharIndex); + if (!isDigitCode(firstCharCode)) { + return null; + } + var secondChar = x.charAt(firstCharIndex + 1); + if (secondChar == 'x' || secondChar == 'X') { + return Global.intval(x, 0); + } else { + return Global.intval(x, 10); + } + } + } + + public static function parseFloat( x : String ) : Float { + var result = Global.floatval(x); + if (result != 0) return result; + + x = Global.ltrim(x); + var firstCharIndex = (x.charAt(0) == '-' ? 1 : 0); + var charCode = x.charCodeAt(firstCharIndex); + + if (charCode == '.'.code) { + charCode = x.charCodeAt(firstCharIndex + 1); + } + + if (isDigitCode(charCode)) { + return 0.0; + } else { + return Const.NAN; + } + } + + public static inline function random( x : Int ) : Int { + return x <= 1 ? 0 : Global.mt_rand(0, x - 1); + } + + static inline function isDigitCode( charCode:Null ) : Bool { + return charCode != null && charCode >= '0'.code && charCode <= '9'.code; + } + +} diff --git a/std/php7/_std/StringBuf.hx b/std/php7/_std/StringBuf.hx new file mode 100644 index 00000000..9230ff21 --- /dev/null +++ b/std/php7/_std/StringBuf.hx @@ -0,0 +1,60 @@ +/* + * Copyright (C)2005-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. + */ + +import php.Global; +import php.Syntax; + +@:coreApi class StringBuf { + private var b : String; + + public var length(get,never) : Int; + + public function new() : Void { + b = ""; + } + + inline function get_length() : Int { + return b.length; + } + + public function add( x : T ) : Void { + if( x == null ) { + Syntax.binop(b, '.=', 'null'); + } else if( Global.is_bool(x) ) { + Syntax.binop(b, '.=', ((x:Dynamic) ? 'true' : 'false')); + } else { + b += x; + } + } + + public inline function addSub( s : String, pos : Int, ?len : Int ) : Void { + b += s.substr(pos,len); + } + + public inline function addChar( c : Int ) : Void { + b += String.fromCharCode(c); + } + + public inline function toString() : String { + return b; + } +} diff --git a/std/php7/_std/StringTools.hx b/std/php7/_std/StringTools.hx new file mode 100644 index 00000000..410b5ec9 --- /dev/null +++ b/std/php7/_std/StringTools.hx @@ -0,0 +1,205 @@ +/* + * Copyright (C)2005-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. + */ + +import php.*; + +@:coreApi class StringTools { + + public inline static function urlEncode( s : String ) : String { + return Global.rawurlencode(s); + } + + public inline static function urlDecode( s : String ) : String { + return Global.urldecode(s); + } + + public inline static function htmlEscape( s : String, ?quotes : Bool ) : String { + return Global.htmlspecialchars(s, (quotes ? Const.ENT_QUOTES | Const.ENT_HTML401 : Const.ENT_NOQUOTES)); + } + + public inline static function htmlUnescape( s : String ) : String { + return Global.htmlspecialchars_decode(s, Const.ENT_QUOTES); + } + + public static function startsWith( s : String, start : String ) : Bool { + return start == '' || Global.strpos(s, start) == 0; + } + + public static function endsWith( s : String, end : String ) : Bool { + return end == '' || Global.substr(s, -end.length) == end; + } + + public static function isSpace( s : String, pos : Int ) : Bool { + var c = s.charCodeAt( pos ); + return (c >= 9 && c <= 13) || c == 32; + } + + public inline static function ltrim( s : String ) : String { + return Global.ltrim(s); + } + + public inline static function rtrim( s : String ) : String { + return Global.rtrim(s); + } + + public inline static function trim( s : String ) : String { + return Global.trim(s); + } + + public static function rpad( s : String, c : String, l : Int ) : String { + if (c.length == 0 || s.length >= l) return s; + var padLength = Math.ceil((l - s.length) / c.length) * c.length + s.length; + return Global.str_pad(s, padLength, c, Const.STR_PAD_RIGHT); + } + + public static function lpad( s : String, c : String, l : Int ) : String { + if (c.length == 0 || s.length >= l) return s; + var padLength = Math.ceil((l - s.length) / c.length) * c.length + s.length; + return Global.str_pad(s, padLength, c, Const.STR_PAD_LEFT); + } + + public static function replace( s : String, sub : String, by : String ) : String { + if (sub == '') { + return Global.implode(by, Global.str_split(s)); + } + return Global.str_replace(sub, by, s); + } + + public static function hex( n : Int, ?digits : Int ) : String { + var s = Global.dechex(n); + var len = 8; + if (s.length > (null == digits ? len : (len = digits > len ? digits : len))) + s = s.substr(-len); + else if ( digits != null ) + s = lpad(s, '0', digits); + return s.toUpperCase(); + } + + public static inline function fastCodeAt( s : String, index : Int ) : Int { + return (s.length == index ? 0 : Global.ord((s:NativeString)[index])); + } + + public static inline function isEof( c : Int ) : Bool { + return c == 0; + } + + /** + Returns a String that can be used as a single command line argument + on Unix. + The input will be quoted, or escaped if necessary. + */ + public static function quoteUnixArg(argument:String):String { + // Based on cpython's shlex.quote(). + // https://hg.python.org/cpython/file/a3f076d4f54f/Lib/shlex.py#l278 + + if (argument == "") + return "''"; + + if (!~/[^a-zA-Z0-9_@%+=:,.\/-]/.match(argument)) + return argument; + + // use single quotes, and put single quotes into double quotes + // the string $'b is then quoted as '$'"'"'b' + return "'" + replace(argument, "'", "'\"'\"'") + "'"; + } + + /** + Character codes of the characters that will be escaped by `quoteWinArg(_, true)`. + */ + public static var winMetaCharacters = [";".code, ",".code, " ".code, "(".code, ")".code, "%".code, "!".code, "^".code, "\"".code, "<".code, ">".code, "&".code, "|".code, "\n".code, "\r".code]; + + /** + Returns a String that can be used as a single command line argument + on Windows. + The input will be quoted, or escaped if necessary, such that the output + will be parsed as a single argument using the rule specified in + http://msdn.microsoft.com/en-us/library/ms880421 + + Examples: + ``` + quoteWinArg("abc") == "abc"; + quoteWinArg("ab c") == '"ab c"'; + ``` + */ + public static function quoteWinArg(argument:String, escapeMetaCharacters:Bool):String { + // If there is no space, tab, back-slash, or double-quotes, and it is not an empty string. + if (!~/^[^ \t\\"]+$/.match(argument)) { + + // Based on cpython's subprocess.list2cmdline(). + // https://hg.python.org/cpython/file/50741316dd3a/Lib/subprocess.py#l620 + + var result = new StringBuf(); + var needquote = argument.indexOf(" ") != -1 || argument.indexOf("\t") != -1 || argument == ""; + + if (needquote) + result.add('"'); + + var bs_buf = new StringBuf(); + for (i in 0...argument.length) { + switch (argument.charCodeAt(i)) { + case "\\".code: + // Don't know if we need to double yet. + bs_buf.add("\\"); + case '"'.code: + // Double backslashes. + var bs = bs_buf.toString(); + result.add(bs); + result.add(bs); + bs_buf = new StringBuf(); + result.add('\\"'); + case c: + // Normal char + if (bs_buf.length > 0) { + result.add(bs_buf.toString()); + bs_buf = new StringBuf(); + } + result.addChar(c); + } + } + + // Add remaining backslashes, if any. + result.add(bs_buf.toString()); + + if (needquote) { + result.add(bs_buf.toString()); + result.add('"'); + } + + argument = result.toString(); + } + + if (escapeMetaCharacters) { + var result = new StringBuf(); + for (i in 0...argument.length) { + var c = argument.charCodeAt(i); + if (winMetaCharacters.indexOf(c) >= 0) { + result.addChar("^".code); + } + result.addChar(c); + } + return result.toString(); + } else { + return argument; + } + } + +} diff --git a/std/php7/_std/Sys.hx b/std/php7/_std/Sys.hx new file mode 100644 index 00000000..7f3c19e0 --- /dev/null +++ b/std/php7/_std/Sys.hx @@ -0,0 +1,145 @@ +/* + * Copyright (C)2005-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. + */ + +import php.*; +import sys.io.FileOutput; +import sys.io.FileInput; + +@:coreApi class Sys { + + public static inline function print( v : Dynamic ) : Void { + Global.echo(Std.string(v)); + } + + public static function println( v : Dynamic ) : Void { + print(v); + print("\n"); + } + + public static function args() : Array { + if (Global.array_key_exists('argv', SuperGlobal._SERVER)) { + return @:privateAccess Array.wrap(Global.array_slice(SuperGlobal._SERVER['argv'], 1)); + } else { + return []; + } + } + + public static function getEnv( s : String ) : String { + var value = Global.getenv(s); + return value == false ? null : value; + } + + public static inline function putEnv( s : String, v : String ) : Void { + Global.putenv('$s=$v'); + } + + public static inline function sleep( seconds : Float ) : Void { + return Global.usleep(Std.int(seconds * 1000000)); + } + + public static inline function setTimeLocale( loc : String ) : Bool { + return Global.setlocale(Const.LC_TIME, loc) != false; + } + + public static function getCwd() : String { + var cwd = Global.getcwd(); + if (cwd == false) return null; + var l = (cwd:String).substr(-1); + return (cwd:String) + (l == '/' || l == '\\' ? '' : '/'); + } + + public static inline function setCwd( s : String ) : Void { + Global.chdir(s); + } + + public static function systemName() : String { + var s = Global.php_uname('s'); + var p = s.indexOf(" "); + return (p >= 0 ? s.substr(0, p) : s); + } + + public static function command( cmd : String, ?args : Array ) : Int { + if (args != null) { + switch (systemName()) { + case "Windows": + cmd = [ + for (a in [StringTools.replace(cmd, "/", "\\")].concat(args)) + StringTools.quoteWinArg(a, true) + ].join(" "); + case _: + cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" "); + } + } + var result = Boot.deref(0); + Global.system(cmd, result); + return result; + } + + public static inline function exit( code : Int ) : Void { + Global.exit(code); + } + + public static inline function time() : Float { + return Global.microtime(true); + } + + public static function cpuTime() : Float { + return time() - SuperGlobal._SERVER['REQUEST_TIME']; + } + + @:deprecated("Use programPath instead") public static inline function executablePath() : String { + return SuperGlobal._SERVER['SCRIPT_FILENAME']; + } + + // It has to be initialized before any call to Sys.setCwd()... + static var _programPath = sys.FileSystem.fullPath(SuperGlobal._SERVER['SCRIPT_FILENAME']); + public static function programPath() : String { + return _programPath; + } + + public static function environment() : Map { + return php.Lib.hashOfAssociativeArray(SuperGlobal._SERVER); + } + + public static function stdin() : haxe.io.Input { + return @:privateAccess new FileInput(Const.STDIN); + } + + public static function stdout() : haxe.io.Output { + return @:privateAccess new FileOutput(Const.STDOUT); + } + + public static function stderr() : haxe.io.Output { + return @:privateAccess new FileOutput(Const.STDERR); + } + + public static function getChar( echo : Bool ) : Int { + var c = Global.fgetc(Const.STDIN); + if (c == false) { + return 0; + } else { + if(echo) Global.echo(c); + return Global.ord(c); + } + } + +} diff --git a/std/php7/_std/Type.hx b/std/php7/_std/Type.hx new file mode 100644 index 00000000..a75c0974 --- /dev/null +++ b/std/php7/_std/Type.hx @@ -0,0 +1,361 @@ +/* + * Copyright (C)2005-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. + */ + +import php.*; +import php.reflection.*; +import haxe.extern.EitherType; + +using php.Global; + +enum ValueType { + TNull; + TInt; + TFloat; + TBool; + TObject; + TFunction; + TClass( c : Class ); + TEnum( e : Enum ); + TUnknown; +} + +@:coreApi class Type { + + public static function getClass( o : T ) : Class { + if(Global.is_object(o) && !Boot.isClass(o) && !Boot.isEnumValue(o)) { + var cls = Boot.getClass(Global.get_class(cast o)); + return (cls == Boot.getHxAnon() ? null : cast cls); + } else if(Global.is_string(o)) { + return cast String; + } else { + return null; + } + } + + public static function getEnum( o : EnumValue ) : Enum { + if(o == null) return null; + return cast Boot.getClass(Global.get_class(cast o)); + } + + public static function getSuperClass( c : Class ) : Class { + if(c == null) return null; + var parentClass = Global.get_parent_class((cast c).phpClassName); + if(!parentClass) return null; + return cast Boot.getClass(parentClass); + } + + public static function getClassName( c : Class ) : String { + if(c == null) return null; + return Boot.getHaxeName(cast c); + } + + public static function getEnumName( e : Enum ) : String { + return getClassName(cast e); + } + + public static function resolveClass( name : String ) : Class { + if (name == null) return null; + switch(name) { + case 'Dynamic': return cast Dynamic; + case 'Int': return cast Int; + case 'Float': return cast Float; + case 'Bool': return cast Bool; + case 'String': return String; + case 'Class': return cast Class; + case 'Enum': return cast Enum; + } + + var phpClass = Boot.getPhpName(name); + if (!Global.class_exists(phpClass) && !Global.interface_exists(phpClass)) return null; + + var hxClass = Boot.getClass(phpClass); + + return cast hxClass; + } + + public static function resolveEnum( name : String ) : Enum { + if (name == null) return null; + if (name == 'Bool') return cast Bool; + + var phpClass = Boot.getPhpName(name); + if (!Global.class_exists(phpClass)) return null; + + var hxClass = Boot.getClass(phpClass); + + return cast hxClass; + } + + public static function createInstance( cl : Class, args : Array ) : T { + if (String == cast cl) return args[0]; + + var phpName = getPhpName(cl); + if (phpName == null) return null; + var nativeArgs:NativeArray = @:privateAccess args.arr; + return Syntax.construct(phpName, Syntax.splat(nativeArgs)); + } + + public static function createEmptyInstance( cl : Class ) : T { + if (String == cast cl) return cast ''; + if (Array == cast cl) return cast []; + + var phpName = getPhpName(cl); + if (phpName == null) return null; + + var reflection = new ReflectionClass(phpName); + return reflection.newInstanceWithoutConstructor(); + } + + public static function createEnum( e : Enum, constr : String, ?params : Array ) : T { + if (e == null || constr == null) return null; + + var phpName = getPhpName(e); + if (phpName == null) return null; + + if (!Global.in_array(constr, Syntax.staticCall(phpName, "__hx__list"))) { + throw 'No such constructor $constr'; + } + + var paramsCounts:NativeAssocArray = Syntax.staticCall(phpName, "__hx__paramsCount"); + if ((params == null && paramsCounts[constr] != 0) || (params != null && params.length != paramsCounts[constr])) { + throw 'Provided parameters count does not match expected parameters count'; + } + + if (params == null) { + return Syntax.staticCall(phpName, constr); + } else { + var nativeArgs:NativeArray = @:privateAccess params.arr; + return Syntax.staticCall(phpName, constr, Syntax.splat(nativeArgs)); + } + } + + public static function createEnumIndex( e : Enum, index : Int, ?params : Array ) : T { + if (e == null || index == null) return null; + + var phpName = getPhpName(e); + if (phpName == null) return null; + + var constructors:NativeIndexedArray = Syntax.staticCall(phpName, "__hx__list"); + if (index < 0 || index >= Global.count(constructors)) { + throw '$index is not a valid enum constructor index'; + } + + var constr = constructors[index]; + var paramsCounts:NativeAssocArray = Syntax.staticCall(phpName, "__hx__paramsCount"); + if ((params == null && paramsCounts[constr] != 0) || (params != null && params.length != paramsCounts[constr])) { + throw 'Provided parameters count does not match expected parameters count'; + } + + if (params == null) { + return Syntax.staticCall(phpName, constr); + } else { + var nativeArgs:NativeArray = @:privateAccess params.arr; + return Syntax.staticCall(phpName, constr, Syntax.splat(nativeArgs)); + } + } + + public static function getInstanceFields( c : Class ) : Array { + if (c == null) return null; + if (c == String) { + return [ + 'substr', 'charAt', 'charCodeAt', 'indexOf', + 'lastIndexOf', 'split', 'toLowerCase', + 'toUpperCase', 'toString', 'length' + ]; + } + + var phpName = getPhpName(c); + if (phpName == null) return null; + + var reflection = new ReflectionClass(phpName); + + var methods = new NativeArray(); + for (m in reflection.getMethods()) { + var method:ReflectionMethod = m; + if (!method.isStatic()) { + var name = method.getName(); + if (!isServiceFieldName(name)) { + methods.array_push(name); + } + } + } + + var properties = new NativeArray(); + for (p in reflection.getProperties()) { + var property:ReflectionProperty = p; + if (!property.isStatic()) { + var name = property.getName(); + if (!isServiceFieldName(name)) { + properties.array_push(name); + } + } + } + properties = Global.array_diff(properties, methods); + + var fields = Global.array_merge(properties, methods); + + return @:privateAccess Array.wrap(fields); + } + + public static function getClassFields( c : Class ) : Array { + if (c == null) return null; + if (c == String) return ['fromCharCode']; + + var phpName = getPhpName(c); + if (phpName == null) return null; + + var reflection = new ReflectionClass(phpName); + + var methods = new NativeArray(); + for (m in reflection.getMethods(ReflectionMethod.IS_STATIC)) { + //TODO: report an issue on invalid type inference for iteration over `NativeIndexedArray` + var m:ReflectionMethod = m; + var name = m.getName(); + if (!isServiceFieldName(name) && phpName == m.getDeclaringClass().getName()) { + methods.array_push(name); + } + } + + var properties = new NativeArray(); + for (p in reflection.getProperties(ReflectionProperty.IS_STATIC)) { + var p:ReflectionMethod = p; + var name = p.getName(); + if (!isServiceFieldName(name) && phpName == p.getDeclaringClass().getName()) { + properties.array_push(name); + } + } + properties = Global.array_diff(properties, methods); + var fields = Global.array_merge(properties, methods); + + return @:privateAccess Array.wrap(fields); + } + + public static function getEnumConstructs( e : Enum ) : Array { + if (e == null) return null; + return @:privateAccess Array.wrap(untyped e.__hx__list()); + } + + public static function typeof( v : Dynamic ) : ValueType { + if (v == null) return TNull; + + if (v.is_object()) { + if (Reflect.isFunction(v)) return TFunction; + if (Std.is(v, StdClass)) return TObject; + if (Boot.isClass(v)) return TObject; + + var hxClass = Boot.getClass(Global.get_class(v)); + if (Boot.isEnumValue(v)) return TEnum(cast hxClass); + return TClass(cast hxClass); + } + + if (v.is_bool()) return TBool; + if (v.is_int()) return TInt; + if (v.is_float()) return TFloat; + if (v.is_string()) return TClass(String); + + return TUnknown; + } + + public static function enumEq( a : T, b : T ) : Bool { + if (a == b) return true; + if (a == null || b == null) return false; + + try { + if (Global.get_class(cast a) != Global.get_class(cast b)) return false; + if (enumIndex(a) != enumIndex(b)) return false; + + var aParams:NativeIndexedArray = untyped a.params; + var bParams:NativeIndexedArray = untyped b.params; + for (i in 0...Global.count(aParams)) { + //enums + if (Boot.isEnumValue(aParams[i])) { + if (!enumEq(aParams[i], bParams[i])) { + return false; + } + continue; + } + //functions + if (Reflect.isFunction(aParams[i])) { + if (!Reflect.compareMethods(aParams[i], bParams[i])) { + return false; + } + continue; + } + //everything else + if (aParams[i] != bParams[i]) { + return false; + } + } + + return true; + } catch (e:Dynamic) { + return false; + } + } + + public static function enumConstructor( e : EnumValue ) : String { + return untyped e.tag; + } + + public inline static function enumParameters( e : EnumValue ) : Array { + return @:privateAccess Array.wrap(untyped e.params); + } + + public inline static function enumIndex( e : EnumValue ) : Int { + return untyped e.index; + } + + public static function allEnums( e : Enum ) : Array { + if (e == null) return null; + + var phpName = getPhpName(e); + if (phpName == null) return null; + + var result = []; + + for (name in getEnumConstructs(e)) { + var reflection = new ReflectionMethod(phpName, name); + if (reflection.getNumberOfParameters() == 0) { + result.push(reflection.invoke(null)); + } + } + + return result; + } + + /** + Get corresponding PHP name for specified `type`. + Returns `null` if `type` does not exist. + **/ + static function getPhpName( type:EitherType,Enum> ) : Null { + var haxeName = Boot.getHaxeName(cast type); + + return (haxeName == null ? null : Boot.getPhpName(haxeName)); + } + + /** + check if specified `name` is a special field name generated by compiler. + **/ + static inline function isServiceFieldName(name:String) : Bool { + return (name == '__construct' || name.indexOf('__hx__') == 0); + } +} + diff --git a/std/php7/_std/haxe/CallStack.hx b/std/php7/_std/haxe/CallStack.hx new file mode 100644 index 00000000..5decfe17 --- /dev/null +++ b/std/php7/_std/haxe/CallStack.hx @@ -0,0 +1,142 @@ +package haxe; + +import php.*; + +private typedef NativeTrace = NativeIndexedArray>; + +/** + Elements return by `CallStack` methods. +**/ +enum StackItem { + CFunction; + Module( m : String ); + FilePos( s : Null, file : String, line : Int ); + Method( classname : String, method : String ); + LocalFunction( ?v : Int ); +} + +@:dox(hide) +@:noCompletion +class CallStack { + static var lastExceptionTrace : NativeTrace; + + /** + Return the call stack elements, or an empty array if not available. + **/ + public static function callStack() : Array { + return makeStack(Global.debug_backtrace(Const.DEBUG_BACKTRACE_IGNORE_ARGS)); + } + + /** + Return the exception stack : this is the stack elements between + the place the last exception was thrown and the place it was + caught, or an empty array if not available. + **/ + public static function exceptionStack() : Array { + return makeStack(lastExceptionTrace == null ? new NativeIndexedArray() : lastExceptionTrace); + } + + /** + Returns a representation of the stack as a printable string. + **/ + public static function toString( stack : Array ) { + var b = new StringBuf(); + for( s in stack ) { + b.add("\nCalled from "); + itemToString(b,s); + } + return b.toString(); + } + + static function itemToString( b:StringBuf, s ) { + switch( s ) { + case CFunction: + b.add("a C function"); + case Module(m): + b.add("module "); + b.add(m); + case FilePos(s,file,line): + if( s != null ) { + itemToString(b,s); + b.add(" ("); + } + b.add(file); + b.add(" line "); + b.add(line); + if( s != null ) b.add(")"); + case Method(cname,meth): + b.add(cname); + b.add("."); + b.add(meth); + case LocalFunction(n): + b.add("local function"); + } + } + + @:keep + static function saveExceptionTrace( e:Throwable ) : Void { + lastExceptionTrace = e.getTrace(); + + //Reduce exception stack to the place where exception was caught + var currentTrace = Global.debug_backtrace(Const.DEBUG_BACKTRACE_IGNORE_ARGS); + var count = Global.count(currentTrace); + + for (i in -(count - 1)...1) { + var exceptionEntry:NativeAssocArray = Global.end(lastExceptionTrace); + + if(!Global.isset(exceptionEntry['file'])) { + Global.array_pop(lastExceptionTrace); + } else if (currentTrace[-i]['file'] == exceptionEntry['file'] && currentTrace[-i]['line'] == exceptionEntry['line']) { + Global.array_pop(lastExceptionTrace); + } else { + break; + } + } + + //Remove arguments from trace to avoid blocking some objects from GC + var count = Global.count(lastExceptionTrace); + for (i in 0...count) { + lastExceptionTrace[i]['args'] = new NativeArray(); + } + + var thrownAt = new NativeAssocArray(); + thrownAt['function'] = ''; + thrownAt['line'] = e.getLine(); + thrownAt['file'] = e.getFile(); + thrownAt['class'] = ''; + thrownAt['args'] = new NativeArray(); + Global.array_unshift(lastExceptionTrace, thrownAt); + } + + static function makeStack (native:NativeTrace) : Array { + var result = []; + var count = Global.count(native); + + for (i in 0...count) { + var entry = native[i]; + var item = null; + + if (i + 1 < count) { + var next = native[i + 1]; + + if(!Global.isset(next['function'])) next['function'] = ''; + if(!Global.isset(next['class'])) next['class'] = ''; + + if ((next['function']:String).indexOf('{closure}') >= 0) { + item = LocalFunction(); + } else if ((next['class']:String).length > 0 && (next['function']:String).length > 0) { + var cls = Boot.getClassName(next['class']); + item = Method(cls, next['function']); + } + } + if (Global.isset(entry['file'])) { + result.push(FilePos(item, entry['file'], entry['line'])); + } else if (item != null) { + result.push(item); + } + } + + return result; + } + +} \ No newline at end of file diff --git a/std/php7/_std/haxe/Json.hx b/std/php7/_std/haxe/Json.hx new file mode 100644 index 00000000..0ba16010 --- /dev/null +++ b/std/php7/_std/haxe/Json.hx @@ -0,0 +1,114 @@ +/* + * Copyright (C)2005-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 haxe; + +import php.*; +import haxe.format.JsonPrinter; + +@:coreApi +class Json { + + public static inline function parse( text : String ) : Dynamic { + #if haxeJSON + return haxe.format.JsonParser.parse(text); + #else + return phpJsonDecode(text); + #end + } + + public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String ) : String { + #if haxeJSON + return JsonPrinter.print(value, replacer, space); + #else + return phpJsonEncode(value, replacer, space); + #end + } + + static function phpJsonDecode(json:String):Dynamic { + var value = Global.json_decode(json); + if (value == null && Global.json_last_error() != Const.JSON_ERROR_NONE) { + throw Global.json_last_error_msg(); + } + return convertAfterDecode(value); + } + + static function convertAfterDecode(value:Dynamic):Dynamic { + if (Global.is_object(value)) { + var result = new NativeAssocArray(); + var data = Syntax.array(value); + Syntax.foreach(data, function(fieldName:String, fieldValue:Dynamic) { + result[fieldName] = convertAfterDecode(fieldValue); + }); + + return Boot.createAnon(result); + } + + if (Global.is_array(value)) { + var result = new NativeIndexedArray(); + Syntax.foreach(value, function(index:Int, item:Dynamic) { + result[index] = convertAfterDecode(item); + }); + + return @:privateAccess Array.wrap(result); + } + + return value; + } + + static function phpJsonEncode(value:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String):String { + if(null != replacer || null != space) { + return JsonPrinter.print(value, replacer, space); + } + + var json = Global.json_encode(convertBeforeEncode(value)); + if (Global.json_last_error() != Const.JSON_ERROR_NONE) { + return throw Global.json_last_error_msg(); + } + return json; + } + + static function convertBeforeEncode(value:Dynamic):Dynamic { + if (Std.is(value, Array)) { + var result = new NativeIndexedArray(); + Syntax.foreach(value.arr, function(index:Int, item:Dynamic) { + result[index] = convertBeforeEncode(item); + }); + + return result; + } + + if (Global.is_object(value)) { + var result = {}; + Syntax.foreach(value, function(fieldName:String, fieldValue:Dynamic) { + Syntax.setField(result, fieldName, convertBeforeEncode(fieldValue)); + }); + + return result; + } + + if (Global.is_float(value) && !Global.is_finite(value)) { + return null; + } + + return value; + } +} \ No newline at end of file diff --git a/std/php7/_std/haxe/Resource.hx b/std/php7/_std/haxe/Resource.hx new file mode 100644 index 00000000..e31c78d3 --- /dev/null +++ b/std/php7/_std/haxe/Resource.hx @@ -0,0 +1,68 @@ +/* + * Copyright (C)2005-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 haxe; + +import php.*; +import haxe.io.Bytes; +import haxe.crypto.Base64; + +@:coreApi +class Resource { + + static function cleanName(name : String) : String { + return ~/[\\\/:?"*<>|]/.replace(name, '_'); + } + + static function getDir() : String { + return Global.dirname(Const.__FILE__) + "/../../res"; + } + + @:access(haxe.io.Path.escape) + static function getPath(name : String) : String { + return getDir()+'/'+haxe.io.Path.escape(name); + } + + @:access(haxe.io.Path.unescape) + public static function listNames() : Array { + var a = sys.FileSystem.readDirectory(getDir()); + if(a[0] == '.') a.shift(); + if(a[0] == '..') a.shift(); + return a.map(function(s) return haxe.io.Path.unescape(s)); + } + + public static function getString( name : String ) : String { + var path = getPath(name); + return if (!sys.FileSystem.exists(path)) + null; + else + sys.io.File.getContent(path); + } + + public static function getBytes( name : String ) : haxe.io.Bytes { + var path = getPath(name); + return if (!sys.FileSystem.exists(path)) + null; + else + sys.io.File.getBytes(path); + } + +} diff --git a/std/php7/_std/haxe/Utf8.hx b/std/php7/_std/haxe/Utf8.hx new file mode 100644 index 00000000..2f8b61b1 --- /dev/null +++ b/std/php7/_std/haxe/Utf8.hx @@ -0,0 +1,88 @@ +/* + * Copyright (C)2005-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 haxe; + +import php.Global; + +@:coreApi +class Utf8 { + + var __b : String; + + public function new( ?size : Int ) : Void { + __b = ''; + } + + public function addChar( c : Int ) : Void { + __b += uchr(c); + } + + public function toString() : String { + return __b; + } + + public static function encode( s : String ) : String { + return Global.utf8_encode(s); + } + + public static function decode( s : String ) : String { + return Global.utf8_decode(s); + } + + public static function iter(s : String, chars : Int -> Void ) : Void { + var len = length(s); + for(i in 0...len) { + chars(charCodeAt(s, i)); + } + } + + public static function charCodeAt( s : String, index : Int ) : Int { + return uord(sub(s, index, 1)); + } + + static function uchr(i : Int) : String { + return Global.mb_convert_encoding(Global.pack('N', i), 'UTF-8', 'UCS-4BE'); + } + + static function uord(s : String) : Int { + var c = Global.unpack('N', Global.mb_convert_encoding(s, 'UCS-4BE', 'UTF-8')); + return c[1]; + } + + public static function validate( s : String ) : Bool { + return Global.mb_check_encoding(s, enc); + } + + public static function length( s : String ) : Int { + return Global.mb_strlen(s, enc); + } + + public static function compare( a : String, b : String ) : Int { + return Global.strcmp(a, b); + } + + public static function sub( s : String, pos : Int, len : Int ) : String { + return Global.mb_substr(s, pos, len, enc); + } + + private static inline var enc = "UTF-8"; +} \ No newline at end of file diff --git a/std/php7/_std/haxe/crypto/Md5.hx b/std/php7/_std/haxe/crypto/Md5.hx new file mode 100644 index 00000000..7741261b --- /dev/null +++ b/std/php7/_std/haxe/crypto/Md5.hx @@ -0,0 +1,39 @@ +/* + * Copyright (C)2005-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 haxe.crypto; + +import php.Global; +import haxe.io.Bytes; + +/** + Creates a MD5 of a String. +**/ +class Md5 { + + public static inline function encode( s : String ) : String { + return Global.md5(s); + } + + public static inline function make( b : haxe.io.Bytes ) : haxe.io.Bytes { + return Bytes.ofData(Global.md5(b.getData(), true)); + } +} diff --git a/std/php7/_std/haxe/crypto/Sha1.hx b/std/php7/_std/haxe/crypto/Sha1.hx new file mode 100644 index 00000000..829820f6 --- /dev/null +++ b/std/php7/_std/haxe/crypto/Sha1.hx @@ -0,0 +1,39 @@ +/* + * Copyright (C)2005-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 haxe.crypto; + +import php.Global; +import haxe.io.Bytes; + +/** + Creates a Sha1 of a String. +*/ +class Sha1 { + + public static inline function encode( s:String ) : String { + return Global.sha1(s); + } + + public static inline function make( b : haxe.io.Bytes ) : haxe.io.Bytes { + return Bytes.ofData(Global.sha1(b.getData(), true)); + } +} diff --git a/std/php7/_std/haxe/crypto/Sha224.hx b/std/php7/_std/haxe/crypto/Sha224.hx new file mode 100644 index 00000000..0ca5cb37 --- /dev/null +++ b/std/php7/_std/haxe/crypto/Sha224.hx @@ -0,0 +1,39 @@ +/* + * Copyright (C)2005-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 haxe.crypto; + +import php.Global; +import haxe.io.Bytes; + +/** + Creates a Sha224 of a String. +*/ +class Sha224 { + + public static inline function encode( s:String ) : String { + return Global.hash('sha224', s); + } + + public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes { + return Bytes.ofData(Global.hash('sha224', b.getData(), true)); + } +} diff --git a/std/php7/_std/haxe/crypto/Sha256.hx b/std/php7/_std/haxe/crypto/Sha256.hx new file mode 100644 index 00000000..ec2ab0bd --- /dev/null +++ b/std/php7/_std/haxe/crypto/Sha256.hx @@ -0,0 +1,39 @@ +/* + * Copyright (C)2005-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 haxe.crypto; + +import php.Global; +import haxe.io.Bytes; + +/** + Creates a Sha256 of a String. +*/ +class Sha256 { + + public static inline function encode( s:String ) : String { + return Global.hash('sha256', s); + } + + public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes { + return Bytes.ofData(Global.hash('sha256', b.getData(), true)); + } +} diff --git a/std/php7/_std/haxe/ds/IntMap.hx b/std/php7/_std/haxe/ds/IntMap.hx new file mode 100644 index 00000000..a19df22a --- /dev/null +++ b/std/php7/_std/haxe/ds/IntMap.hx @@ -0,0 +1,98 @@ +/* + * Copyright (C)2005-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 haxe.ds; + +import php.Syntax; +import php.Global; +import php.NativeArray; +import php.NativeIndexedArray; + +@:coreApi class IntMap implements haxe.Constraints.IMap { + + var data:NativeIndexedArray; + + /** + Creates a new IntMap. + **/ + public function new() : Void { + data = new NativeIndexedArray(); + } + + /** + See `Map.set` + **/ + public inline function set( key : Int, value : T ) : Void { + data[key] = value; + } + + /** + See `Map.get` + **/ + public inline function get( key : Int ) : Null { + return Syntax.binop(data[key], '??', null); + } + + /** + See `Map.exists` + **/ + public inline function exists( key : Int ) : Bool { + return Global.array_key_exists(key, data); + } + + /** + See `Map.remove` + **/ + public function remove( key : Int ) : Bool { + if (Global.array_key_exists(key, data)) { + Global.unset(data[key]); + return true; + } + + return false; + } + + /** + See `Map.keys` + **/ + public inline function keys() : Iterator { + return Global.array_keys(data).iterator(); + } + + /** + See `Map.iterator` + **/ + public inline function iterator() : Iterator { + return Global.array_values(data).iterator(); + } + + /** + See `Map.toString` + **/ + public function toString() : String { + var parts = new NativeArray(); + Syntax.foreach(data, function(key:Int, value:T) { + Global.array_push(parts, '$key => ' + Std.string(value)); + }); + + return '{' + Global.implode(', ', parts) + '}'; + } +} diff --git a/std/php7/_std/haxe/ds/ObjectMap.hx b/std/php7/_std/haxe/ds/ObjectMap.hx new file mode 100644 index 00000000..f42a6d97 --- /dev/null +++ b/std/php7/_std/haxe/ds/ObjectMap.hx @@ -0,0 +1,82 @@ +/* + * Copyright (C)2005-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 haxe.ds; + +import php.*; + +@:coreApi +class ObjectMap implements haxe.Constraints.IMap { + var _keys:NativeAssocArray; + var _values:NativeAssocArray; + + public function new():Void { + _keys = new NativeAssocArray(); + _values = new NativeAssocArray(); + } + + public function set(key:K, value:V):Void { + var id = Global.spl_object_hash(key); + _keys[id] = key; + _values[id] = value; + } + + public function get(key:K):Null { + var id = Global.spl_object_hash(key); + return Global.isset(_values[id]) ? _values[id] : null; + } + + public function exists(key:K):Bool { + return Global.array_key_exists(Global.spl_object_hash(key), _values); + } + + public function remove( key : K ) : Bool { + var id = Global.spl_object_hash(key); + if (Global.array_key_exists(id, _values)) { + Global.unset(_keys[id], _values[id]); + return true; + } else { + return false; + } + } + + public inline function keys() : Iterator { + return _keys.iterator(); + } + + public inline function iterator() : Iterator { + return _values.iterator(); + } + + public function toString() : String { + var s = "{"; + var it = keys(); + for( i in it ) { + s += Std.string(i); + s += " => "; + s += Std.string(get(i)); + if( it.hasNext() ) + s += ", "; + } + return s + "}"; + } +} \ No newline at end of file diff --git a/std/php7/_std/haxe/ds/StringMap.hx b/std/php7/_std/haxe/ds/StringMap.hx new file mode 100644 index 00000000..68718ecd --- /dev/null +++ b/std/php7/_std/haxe/ds/StringMap.hx @@ -0,0 +1,74 @@ +/* + * Copyright (C)2005-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 haxe.ds; + +import php.Syntax; +import php.Global; +import php.NativeArray; +import php.NativeAssocArray; +import haxe.Constraints; + +@:coreApi class StringMap implements IMap { + private var data : NativeAssocArray; + + public inline function new() : Void { + data = new NativeAssocArray(); + } + + public inline function set( key : String, value : T ) : Void { + data[key] = value; + } + + public inline function get( key : String ) : Null { + return Syntax.binop(data[key], '??', null); + } + + public inline function exists( key : String ) : Bool { + return Global.array_key_exists(key, data); + } + + public function remove( key : String ) : Bool { + if (Global.array_key_exists(key, data)) { + Global.unset(data[key]); + return true; + } else { + return false; + } + } + + public inline function keys() : Iterator { + return Global.array_map('strval', Global.array_keys(data)).iterator(); + } + + public inline function iterator() : Iterator { + return data.iterator(); + } + + public function toString() : String { + var parts = new NativeArray(); + Syntax.foreach(data, function(key:String, value:T) { + Global.array_push(parts, '$key => ' + Std.string(value)); + }); + + return '{' + Global.implode(', ', parts) + '}'; + } +} diff --git a/std/php7/_std/haxe/io/Bytes.hx b/std/php7/_std/haxe/io/Bytes.hx new file mode 100644 index 00000000..3733785f --- /dev/null +++ b/std/php7/_std/haxe/io/Bytes.hx @@ -0,0 +1,206 @@ +/* + * Copyright (C)2005-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 haxe.io; + +class Bytes { + + public var length(default,null) : Int; + + var b:BytesData; + + function new(length:Int, b:BytesData) : Void { + this.length = length; + this.b = b; + } + + public inline function get( pos : Int ) : Int { + return b.get(pos); + } + + public inline function set( pos : Int, v : Int ) : Void { + b.set(pos, v); + } + + public inline function blit( pos : Int, src : Bytes, srcpos : Int, len : Int ) : Void { + if( pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length ) { + throw Error.OutsideBounds; + } else { + b.blit(pos, src.b, srcpos, len); + } + } + + public function fill( pos : Int, len : Int, value : Int ) : Void { + for(i in pos...pos+len) b.set(i, value); + } + + public inline function sub( pos : Int, len : Int ) : Bytes { + if( pos < 0 || len < 0 || pos + len > length ) { + throw Error.OutsideBounds; + } else { + return new Bytes(len, b.sub(pos, len)); + } + } + + public inline function compare( other : Bytes ) : Int { + return b.compare(other.b); + } + + /** + Returns the IEEE double precision value at given position (in low endian encoding). + Result is unspecified if reading outside of the bounds + **/ + public function getDouble( pos : Int ) : Float { + return FPHelper.i64ToDouble(getInt32(pos),getInt32(pos+4)); + } + + /** + Returns the IEEE single precision value at given position (in low endian encoding). + Result is unspecified if reading outside of the bounds + **/ + public function getFloat( pos : Int ) : Float { + var b = new haxe.io.BytesInput(this,pos,4); + return b.readFloat(); + } + + /** + Store the IEEE double precision value at given position in low endian encoding. + Result is unspecified if writing outside of the bounds. + **/ + public function setDouble( pos : Int, v : Float ) : Void { + var i = FPHelper.doubleToI64(v); + setInt32(pos, i.low); + setInt32(pos + 4, i.high); + } + + /** + Store the IEEE single precision value at given position in low endian encoding. + Result is unspecified if writing outside of the bounds. + **/ + public function setFloat( pos : Int, v : Float ) : Void { + setInt32(pos, FPHelper.floatToI32(v)); + } + + /** + Returns the 16 bit unsigned integer at given position (in low endian encoding). + **/ + public inline function getUInt16( pos : Int ) : Int { + return get(pos) | (get(pos + 1) << 8); + } + + /** + Store the 16 bit unsigned integer at given position (in low endian encoding). + **/ + public inline function setUInt16( pos : Int, v : Int ) : Void { + set(pos, v); + set(pos + 1, v >> 8); + } + + /** + Returns the 32 bit integer at given position (in low endian encoding). + **/ + public inline function getInt32( pos : Int ) : Int { + var v = get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos+3) << 24); + return if( v & 0x80000000 != 0 ) v | 0x80000000 else v; + } + + /** + Returns the 64 bit integer at given position (in low endian encoding). + **/ + public inline function getInt64( pos : Int ) : haxe.Int64 { + return haxe.Int64.make(getInt32(pos+4), getInt32(pos)); + } + + /** + Store the 32 bit integer at given position (in low endian encoding). + **/ + public inline function setInt32( pos : Int, v : Int ) : Void { + set(pos, v); + set(pos + 1, v >> 8); + set(pos + 2, v >> 16); + set(pos + 3, v >>> 24); + } + + /** + Store the 64 bit integer at given position (in low endian encoding). + **/ + public inline function setInt64( pos : Int, v : haxe.Int64 ) : Void { + setInt32(pos, v.low); + setInt32(pos + 4, v.high); + } + + public inline function getString( pos : Int, len : Int ) : String { + if( pos < 0 || len < 0 || pos + len > length ) { + throw Error.OutsideBounds; + } else { + return b.getString(pos, len); + } + } + + @:deprecated("readString is deprecated, use getString instead") + @:noCompletion + public inline function readString(pos:Int, len:Int):String { + return getString(pos, len); + } + + public function toString() : String { + return b; + } + + public function toHex() : String { + var s = new StringBuf(); + var chars = []; + var str = "0123456789abcdef"; + for( i in 0...str.length ) + chars.push(str.charCodeAt(i)); + for( i in 0...length ) { + var c = get(i); + s.addChar(chars[c >> 4]); + s.addChar(chars[c & 15]); + } + return s.toString(); + } + + public inline function getData() : BytesData { + return b; + } + + public static function alloc( length : Int ) : Bytes { + return new Bytes(length, BytesData.alloc(length)); + } + + public static inline function ofString( s : String ) : Bytes { + return new Bytes(s.length, s); + } + + public static inline function ofData( b : BytesData ) : Bytes { + return new Bytes(b.length, b); + } + + /** + Read the most efficiently possible the n-th byte of the data. + Behavior when reading outside of the available data is unspecified. + **/ + public inline static function fastGet( b : BytesData, pos : Int ) : Int { + return b.get(pos); + } + +} diff --git a/std/php7/_std/haxe/io/BytesBuffer.hx b/std/php7/_std/haxe/io/BytesBuffer.hx new file mode 100644 index 00000000..b5871cb7 --- /dev/null +++ b/std/php7/_std/haxe/io/BytesBuffer.hx @@ -0,0 +1,89 @@ +/* + * Copyright (C)2005-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 haxe.io; + +import php.*; + +class BytesBuffer { + var b : String; + + /** The length of the buffer in bytes. **/ + public var length(get,never) : Int; + + public function new() { + b = ""; + } + + public inline function addByte( byte : Int ) { + Syntax.binop(b, '.=', Global.chr(byte)); + } + + public inline function add( src : Bytes ) { + Syntax.binop(b, '.=', src.getData().toNativeString()); + } + + public inline function addString( v : String ) { + Syntax.binop(b, '.=', v); + } + + public function addInt32( v : Int ) { + addByte(v&0xFF); + addByte((v>>8)&0xFF); + addByte((v>>16)&0xFF); + addByte(v>>>24); + } + + public function addInt64( v : haxe.Int64 ) { + addInt32(v.low); + addInt32(v.high); + } + + public inline function addFloat( v : Float ) { + addInt32(FPHelper.floatToI32(v)); + } + + public inline function addDouble( v : Float ) { + addInt64(FPHelper.doubleToI64(v)); + } + + public inline function addBytes( src : Bytes, pos : Int, len : Int ) { + if( pos < 0 || len < 0 || pos + len > src.length ) { + throw Error.OutsideBounds; + } else { + Syntax.binop(b, '.=', src.getData().sub(pos, len).toString()); + } + } + + /** + Returns either a copy or a reference of the current bytes. + Once called, the buffer can no longer be used. + **/ + public function getBytes() : Bytes untyped { + var bytes = new Bytes(b.length, b); + b = null; + return bytes; + } + + inline function get_length() : Int { + return b.length; + } +} diff --git a/std/php7/_std/haxe/io/BytesData.hx b/std/php7/_std/haxe/io/BytesData.hx new file mode 100644 index 00000000..391071cd --- /dev/null +++ b/std/php7/_std/haxe/io/BytesData.hx @@ -0,0 +1,88 @@ +/* + * Copyright (C)2005-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 haxe.io; + +import php.*; + +private class Container { + public var s:NativeString; + public inline function new(s:NativeString) this.s = s; +} + +abstract BytesData(Container) from Container to Container { + + public var length (get,never):Int; + + public static inline function alloc (length:Int):BytesData { + return Global.str_repeat(Global.chr(0), length); + } + + @:arrayAccess + public inline function get (pos:Int):Int { + return Global.ord(this.s[pos]); + } + + @:arrayAccess + public inline function set (index:Int, val:Int):Void { + this.s = Global.substr_replace(this.s, Global.chr(val), index, 1); + } + + public inline function compare (other:BytesData):Int { + return Syntax.binop(this.s, '<=>', (other:Container).s); + } + + public inline function getString (pos:Int, len:Int):String { + return Global.substr(this.s, pos, len); + } + + public inline function sub (pos:Int, len:Int):BytesData { + return (Global.substr(this.s, pos, len):String); + } + + public inline function blit (pos : Int, src : BytesData, srcpos : Int, len : Int):Void { + this.s = Syntax.binop(Syntax.binop(Global.substr(this.s, 0, pos), '.', Global.substr(src, srcpos, len)), '.', Global.substr(this.s, pos + len)); + } + + inline function get_length ():Int { + return Global.strlen(this.s); + } + + @:from + static inline function fromNativeString (s:NativeString):BytesData { + return new Container(s); + } + + @:to + public inline function toNativeString ():NativeString { + return this.s; + } + + @:from + static inline function fromString (s:String):BytesData { + return new Container(s); + } + + @:to + public inline function toString ():String { + return this.s; + } +} \ No newline at end of file diff --git a/std/php7/_std/haxe/io/BytesInput.hx b/std/php7/_std/haxe/io/BytesInput.hx new file mode 100644 index 00000000..aff0d9ba --- /dev/null +++ b/std/php7/_std/haxe/io/BytesInput.hx @@ -0,0 +1,79 @@ +/* + * Copyright (C)2005-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 haxe.io; + +class BytesInput extends Input { + var b : BytesData; + var pos : Int; + var len : Int; + var totlen : Int; + + /** The current position in the stream in bytes. */ + public var position(get,set) : Int; + + /** The length of the stream in bytes. */ + public var length(get,never) : Int; + + public function new( b : Bytes, ?pos : Int, ?len : Int ) { + if( pos == null ) pos = 0; + if( len == null ) len = b.length - pos; + if( pos < 0 || len < 0 || pos + len > b.length ) throw Error.OutsideBounds; + + this.b = b.getData(); + this.pos = pos; + this.len = len; + this.totlen = len; + } + + inline function get_position() : Int { + return pos; + } + + inline function get_length() : Int { + return totlen; + } + + function set_position( p : Int ) : Int { + if( p < 0 ) p = 0; + else if( p > length ) p = length; + len = totlen - p; + return pos = p; + } + + public override function readByte() : Int { + return b[pos++]; + } + + public override function readBytes( buf : Bytes, pos, len ) : Int { + if( pos < 0 || len < 0 || pos + len > buf.length ) + throw Error.OutsideBounds; + if( this.len == 0 && len > 0 ) + throw new Eof(); + if( this.len < len ) + len = this.len; + buf.getData().blit(pos, b, this.pos, len); + this.pos += len; + this.len -= len; + + return len; + } +} diff --git a/std/php7/_std/haxe/io/BytesOutput.hx b/std/php7/_std/haxe/io/BytesOutput.hx new file mode 100644 index 00000000..21c88066 --- /dev/null +++ b/std/php7/_std/haxe/io/BytesOutput.hx @@ -0,0 +1,57 @@ +/* + * Copyright (C)2005-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 haxe.io; + +class BytesOutput extends Output { + + var b : BytesBuffer; + + /** The length of the stream in bytes. **/ + public var length(get,never) : Int; + + public function new() { + b = new BytesBuffer(); + } + + override function writeByte(c) { + b.addByte(c); + } + + override function writeBytes( buf : Bytes, pos, len ) : Int { + b.addBytes(buf,pos,len); + return len; + } + + /** + Returns the `Bytes` of this output. + + This function should not be called more than once on a given + `BytesOutput` instance. + **/ + public function getBytes() : Bytes { + return b.getBytes(); + } + + inline function get_length() : Int { + return b.length; + } +} diff --git a/std/php7/_std/haxe/io/FPHelper.hx b/std/php7/_std/haxe/io/FPHelper.hx new file mode 100644 index 00000000..41f2f20f --- /dev/null +++ b/std/php7/_std/haxe/io/FPHelper.hx @@ -0,0 +1,61 @@ +/* + * Copyright (C)2005-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 haxe.io; + +import php.*; + +/** + Helper that converts between floating point and binary representation. + Always works in low-endian encoding. +**/ +class FPHelper { + + static var isLittleEndian : Bool = Global.unpack('S','\x01\x00')[1] == 1; + static var i64tmp = Int64.ofInt(0); + + public static inline function i32ToFloat( i : Int ) : Float { + return Global.unpack('f', Global.pack('l', i))[1]; + } + + public static inline function floatToI32( f : Float ) : Int { + return Global.unpack('l', Global.pack('f', f))[1]; + } + + public static inline function i64ToDouble( low : Int, high : Int ) : Float { + return Global.unpack('d', Global.pack('ii', isLittleEndian ? low : high, isLittleEndian ? high : low))[1]; + } + + /** + Returns an Int64 representing the bytes representation of the double precision IEEE float value. + WARNING : for performance reason, the same Int64 value might be reused every time. Copy its low/high values before calling again. + We still ensure that this is safe to use in a multithread environment + **/ + public static function doubleToI64( v : Float ) : Int64 { + var a = Global.unpack(isLittleEndian ? 'V2' : 'N2', Global.pack('d', v)); + var i64 = i64tmp; + @:privateAccess i64.set_low(a[isLittleEndian ? 1 : 2]); + @:privateAccess i64.set_high(a[isLittleEndian ? 2 : 1]); + + return i64; + } + +} \ No newline at end of file diff --git a/std/php7/_std/haxe/zip/Compress.hx b/std/php7/_std/haxe/zip/Compress.hx new file mode 100644 index 00000000..d1cf8236 --- /dev/null +++ b/std/php7/_std/haxe/zip/Compress.hx @@ -0,0 +1,55 @@ +/* + * Copyright (C)2005-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 haxe.zip; + +@:coreApi +class Compress { + + private var level : Int; + + public function new( level : Int ) : Void { + this.level = level; + } + + public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { + var input = src.sub( srcPos , src.length - srcPos ); + var data = run( input , level ); + dst.blit( dstPos , data , 0 , data.length ); + + return { + done: true, + read: input.length, + write: data.length + }; + } + + public function setFlushMode( f : FlushMode ) : Void { + } + + public function close() : Void { + } + + public static function run( s : haxe.io.Bytes, level : Int ) : haxe.io.Bytes { + var c = untyped __call__("gzcompress", s.toString(), level); + return haxe.io.Bytes.ofString(c); + } +} diff --git a/std/php7/_std/haxe/zip/Uncompress.hx b/std/php7/_std/haxe/zip/Uncompress.hx new file mode 100644 index 00000000..1a16bcb2 --- /dev/null +++ b/std/php7/_std/haxe/zip/Uncompress.hx @@ -0,0 +1,45 @@ +/* + * Copyright (C)2005-2012 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 haxe.zip; + +class Uncompress { + + public function new( ?windowBits : Int ) { + throw "Not implemented for this platform"; + } + + public function execute( src : haxe.io.Bytes, srcPos : Int, dst : haxe.io.Bytes, dstPos : Int ) : { done : Bool, read : Int, write : Int } { + return null; + } + + public function setFlushMode( f : FlushMode ) { + } + + public function close() { + } + + public static function run( src : haxe.io.Bytes, ?bufsize : Int ) : haxe.io.Bytes { + var c = untyped __call__("gzuncompress", src.toString()); + return haxe.io.Bytes.ofString(c); + } + +} diff --git a/std/php7/_std/sys/FileSystem.hx b/std/php7/_std/sys/FileSystem.hx new file mode 100644 index 00000000..e5cbb8d7 --- /dev/null +++ b/std/php7/_std/sys/FileSystem.hx @@ -0,0 +1,112 @@ +/* + * Copyright (C)2005-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 sys; + +import php.*; +import haxe.io.Path; + +private enum FileKind { + kdir; + kfile; + kother( k : String ); +} + +@:coreApi +class FileSystem { + + public static inline function exists( path : String ) : Bool { + return Global.file_exists(path); + } + + public static inline function rename( path : String, newPath : String ) : Void { + Global.rename(path, newPath); + } + + public static function stat( path : String ) : FileStat { + var info = Global.stat(path); + if (info == false) throw 'Unable to stat $path'; + var info:NativeArray = info; + + return { + gid : info['gid'], + uid : info['uid'], + atime : Date.fromTime(info['atime'] * 1000), + mtime : Date.fromTime(info['mtime'] * 1000), + ctime : Date.fromTime(info['ctime'] * 1000), + dev : info['dev'], + ino : info['ino'], + nlink : info['nlink'], + rdev : info['rdev'], + size : info['size'], + mode : info['mode'] + }; + } + + public static inline function fullPath( relPath : String ) : String { + return (Syntax.binop(Global.realpath(relPath), "?:", null)); + } + + public static function absolutePath ( relPath : String ) : String { + if (Path.isAbsolute(relPath)) return relPath; + return Path.join([Sys.getCwd(), relPath]); + } + + static function kind( path : String ) : FileKind { + var kind = Global.filetype(path); + if (kind == false) throw 'Failed to check file type $path'; + + switch(kind) { + case "file": return kfile; + case "dir": return kdir; + default: return kother(kind); + } + } + + public static inline function isDirectory( path : String ) : Bool { + return Global.is_dir(path); + } + + public static inline function createDirectory( path : String ) : Void { + Global.mkdir(path, 493, true); + } + + public static inline function deleteFile( path : String ) : Void { + Global.unlink(path); + } + + public static inline function deleteDirectory( path : String ) : Void { + Global.rmdir(path); + } + + public static function readDirectory( path : String ) : Array { + var list = []; + var dir = Global.opendir(path); + var file; + while ((file = Global.readdir(dir)) != false) { + if (file != '.' && file != '..') { + list.push(file); + } + } + Global.closedir(dir); + return list; + } +} diff --git a/std/php7/_std/sys/db/Mysql.hx b/std/php7/_std/sys/db/Mysql.hx new file mode 100644 index 00000000..11c34134 --- /dev/null +++ b/std/php7/_std/sys/db/Mysql.hx @@ -0,0 +1,238 @@ +/* + * Copyright (C)2005-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 sys.db; + +import php.*; +import sys.db.*; +import php.db.*; +import php.db.Mysqli_result; + +@:coreApi class Mysql { + public static function connect( + params : { + host : String, + ?port : Int, + user : String, + pass : String, + ?socket : String, + database : String + } + ) : Connection { + return new MysqlConnection(params); + } +} + +private class MysqlConnection implements Connection { + var db : Mysqli; + + public function new( + params : { + host : String, + ?port : Int, + user : String, + pass : String, + ?socket : String, + database : String + } + ) : Void { + if (params.port == null) params.port = Std.parseInt(Global.ini_get('mysqli.default_port')); + if (params.socket == null) params.socket = Global.ini_get('mysqli.default_socket'); + + db = new Mysqli(params.host, params.user, params.pass, params.database, params.port, params.socket); + } + + public function request( s : String ) : ResultSet { + var result = db.query(s); + if (result == false) throw 'Failed to perform db query'; + if (result == true) return null; + + return new MysqlResultSet(result); + } + + public function close() : Void { + close(); + } + + public function escape( s : String ) : String { + return db.escape_string(s); + } + + public function quote( s : String ) : String { + if (s.indexOf("\000") >= 0) return "x'" + Global.bin2hex(s) + "'"; + return "'" + db.escape_string(s) + "'"; + } + + public function addValue( s : StringBuf, v : Dynamic ) : Void { + if (Global.is_int(v) + || Global.is_null(v)) { + s.add(v); + } else if (Global.is_bool(v)) { + s.add(v ? 1 : 0); + } else { + s.add(quote(Std.string(v))); + } + } + + public function lastInsertId() : Int { + return db.insert_id; + } + + public function dbName() : String { + return 'MySQL'; + } + + public function startTransaction() : Void { + var success = db.begin_transaction(); + if (!success) throw 'Failed to start transaction'; + } + + public function commit() : Void { + var success = db.commit(); + if (!success) throw 'Failed to commit transaction'; + } + + public function rollback() : Void { + var success = db.rollback(); + if (!success) throw 'Failed to rollback transaction'; + } + +} + +private class MysqlResultSet implements ResultSet { + static var hxAnonClassName = Boot.getHxAnon().phpClassName; + + public var length(get,null) : Int; + public var nfields(get,null) : Int; + + var result:Mysqli_result; + var fetchedRow:NativeAssocArray; + var fieldsInfo:NativeAssocArray; + + public function new( result:Mysqli_result ) { + this.result = result; + } + + public function hasNext() : Bool { + if (fetchedRow == null) fetchNext(); + return fetchedRow != null; + } + + public function next() : Dynamic { + if (fetchedRow == null) fetchNext(); + return withdrawFetched(); + } + + public function results() : List { + var list = new List(); + + result.data_seek(0); + var row = result.fetch_object(hxAnonClassName); + while (row != null) { + row = correctObjectTypes(row); + list.add(row); + row = result.fetch_object(hxAnonClassName); + } + + return list; + } + + public function getResult( n : Int ) : String { + if (fetchedRow == null) fetchNext(); + return Global.array_values(fetchedRow)[n]; + } + + public function getIntResult( n : Int ) : Int { + return Syntax.int(getResult(n)); + } + + public function getFloatResult( n : Int ) : Float { + return Syntax.float(getResult(n)); + } + + public function getFieldsNames() : Null> { + var fields = result.fetch_fields(); + return [for (field in fields) field.name]; + } + + function fetchNext() { + var row = result.fetch_assoc(); + if (row != null) fetchedRow = correctArrayTypes(row); + } + + function withdrawFetched() : Dynamic { + if (fetchedRow == null) return null; + return Boot.createAnon(fetchedRow); + } + + function correctArrayTypes(row:NativeAssocArray):NativeAssocArray { + var fieldsInfo = getFieldsInfo(); + Syntax.foreach(row, function(field:String, value:String) { + row[field] = correctType(value, fieldsInfo[field].type); + }); + return cast row; + } + + function correctObjectTypes(row:{}):{} { + var fieldsInfo = getFieldsInfo(); + Syntax.foreach(row, function(field:String, value:String) { + value = correctType(value, fieldsInfo[field].type); + Syntax.setField(row, field, value); + }); + return row; + } + + inline function getFieldsInfo():NativeAssocArray { + if (fieldsInfo == null) { + fieldsInfo = cast Syntax.arrayDecl(); + Syntax.foreach(result.fetch_fields(), function(_, info) { + fieldsInfo[info.name] = info; + }); + } + return fieldsInfo; + } + + function correctType(value:String, type:Int):Scalar { + if (value == null) return null; + if ( + type == Const.MYSQLI_TYPE_BIT + || type == Const.MYSQLI_TYPE_TINY + || type == Const.MYSQLI_TYPE_SHORT + || type == Const.MYSQLI_TYPE_LONG + || type == Const.MYSQLI_TYPE_INT24 + || type == Const.MYSQLI_TYPE_CHAR + ) { + return Syntax.int(value); + } + if ( + type == Const.MYSQLI_TYPE_DECIMAL + || type == Const.MYSQLI_TYPE_NEWDECIMAL + || type == Const.MYSQLI_TYPE_FLOAT + || type == Const.MYSQLI_TYPE_DOUBLE + ) { + return Syntax.float(value); + } + return value; + } + + function get_length() return result.num_rows; + function get_nfields() return result.field_count; +} \ No newline at end of file diff --git a/std/php7/_std/sys/db/Sqlite.hx b/std/php7/_std/sys/db/Sqlite.hx new file mode 100644 index 00000000..f3cb1366 --- /dev/null +++ b/std/php7/_std/sys/db/Sqlite.hx @@ -0,0 +1,192 @@ +/* + * Copyright (C)2005-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 sys.db; + +import php.*; +import php.db.*; +import sys.db.*; + +@:coreApi class Sqlite { + public static function open( file:String ) : Connection { + return new SQLiteConnection(file); + } +} + +private class SQLiteConnection implements Connection { + var db:SQLite3; + + public function new( file:String ) { + db = new SQLite3('sqlite:$file'); + db.enableExceptions(true); + } + + public function request( s : String ) : ResultSet { + var result = db.query(s); + return new SQLiteResultSet(result); + } + + public function close() : Void { + db.close(); + } + + public function escape( s : String ) : String { + return SQLite3.escapeString(s); + } + + public function quote( s : String ) : String { + if (s.indexOf("\000") >= 0) return "x'" + Global.bin2hex(s) + "'"; + return "'" + SQLite3.escapeString(s) + "'"; + } + + public function addValue( s : StringBuf, v : Dynamic ) : Void { + if (Global.is_int(v) || Global.is_null(v)) { + s.add(v); + } else if (Global.is_bool(v)) { + s.add(v ? 1 : 0); + } else { + s.add(quote(Std.string(v))); + } + } + + public function lastInsertId() : Int { + return Syntax.int(db.lastInsertRowID()); + } + + public function dbName() : String { + return 'SQLite'; + } + + public function startTransaction() : Void { + db.query('BEGIN TRANSACTION'); + } + + public function commit() : Void { + db.query('COMMIT'); + } + + public function rollback() : Void { + db.query('ROLLBACK'); + } +} + +private class SQLiteResultSet implements ResultSet { + public var length(get,null) : Int; + public var nfields(get,null) : Int; + + var _length : Int = 0; + var _nfields : Int = 0; + + var loaded:Bool = false; + var currentIndex:Int = 0; + var rows:NativeIndexedArray>; + var result:SQLite3Result; + var fetchedRow:NativeArray; + var fieldsInfo:NativeAssocArray; + + public function new( result:SQLite3Result ) { + this.result = result; + } + + public function hasNext() : Bool { + if (!loaded) load(); + return currentIndex < _length; + } + + public function next() : Dynamic { + if (!loaded) load(); + var next:Dynamic = rows[currentIndex++]; + return Boot.createAnon(correctArrayTypes(next)); + } + + public function results() : List { + if (!loaded) load(); + var list = new List(); + Syntax.foreach(rows, function(_, row) list.add(Boot.createAnon(correctArrayTypes(row)))); + return list; + } + + public function getResult( n : Int ) : String { + if (!loaded) load(); + if (!hasNext()) return null; + return Global.array_values(rows[currentIndex])[n]; + } + + public function getIntResult( n : Int ) : Int { + return Syntax.int(getResult(n)); + } + + public function getFloatResult( n : Int ) : Float { + return Syntax.float(getResult(n)); + } + + public function getFieldsNames() : Null> { + var fieldsInfo = getFieldsInfo(); + return Global.array_keys(fieldsInfo); + } + + function correctArrayTypes(row:NativeAssocArray):NativeAssocArray { + var fieldsInfo = getFieldsInfo(); + Syntax.foreach(row, function(field:String, value:String) { + row[field] = correctType(value, fieldsInfo[field]); + }); + return cast row; + } + + inline function getFieldsInfo():NativeAssocArray { + if (fieldsInfo == null) { + fieldsInfo = cast Syntax.arrayDecl(); + for(i in 0...nfields) { + fieldsInfo[result.columnName(i)] = result.columnType(i); + } + } + return fieldsInfo; + } + + function load() { + loaded = true; + _nfields = result.numColumns(); + getFieldsInfo(); + fetchAll(); + } + + function correctType(value:String, type:Int):Scalar { + if (value == null) return null; + if (type == Const.SQLITE3_INTEGER) return Syntax.int(value); + if (type == Const.SQLITE3_FLOAT) return Syntax.float(value); + return value; + } + + function fetchAll() { + rows = Syntax.arrayDecl(); + var index = 0; + var row = result.fetchArray(Const.SQLITE3_ASSOC); + while(row != false) { + rows[index] = correctArrayTypes(row); + row = result.fetchArray(Const.SQLITE3_ASSOC); + index++; + } + _length = index; + } + + function get_length() return _length; + function get_nfields() return _nfields; +} \ No newline at end of file diff --git a/std/php7/_std/sys/io/File.hx b/std/php7/_std/sys/io/File.hx new file mode 100644 index 00000000..e05dc096 --- /dev/null +++ b/std/php7/_std/sys/io/File.hx @@ -0,0 +1,63 @@ +/* + * Copyright (C)2005-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 sys.io; + +import php.Global.*; +import php.Global; + +@:coreApi class File { + + public static function getContent( path : String ) : String { + return file_get_contents(path); + } + + public static function getBytes( path : String ) : haxe.io.Bytes { + return haxe.io.Bytes.ofString(file_get_contents(path)); + } + + public static function saveContent( path : String, content : String) : Void { + file_put_contents(path, content); + } + + public static function saveBytes( path : String, bytes : haxe.io.Bytes ) : Void { + var f = write(path); + f.write(bytes); + f.close(); + } + + public static function read( path : String, binary : Bool = true ) : FileInput { + return @:privateAccess new FileInput(fopen(path, binary ? "rb" : "r")); + } + + public static function write( path : String, binary : Bool = true ) : FileOutput { + return untyped new FileOutput(fopen(path, binary ? "wb" : "w")); + } + + public static function append( path : String, binary : Bool = true ) : FileOutput { + return untyped new FileOutput(fopen(path, binary ? "ab" : "a")); + } + + public static function copy( srcPath : String, dstPath : String ) : Void { + Global.copy(srcPath, dstPath); + } + +} diff --git a/std/php7/_std/sys/io/FileInput.hx b/std/php7/_std/sys/io/FileInput.hx new file mode 100644 index 00000000..6ddb4d07 --- /dev/null +++ b/std/php7/_std/sys/io/FileInput.hx @@ -0,0 +1,87 @@ +/* + * Copyright (C)2005-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 sys.io; + +import haxe.io.Eof; +import haxe.io.Error; +import haxe.io.Bytes; +import php.*; +import php.Global.*; +import php.Const.*; + +@:coreApi +class FileInput extends haxe.io.Input { + + private var __f : Resource; + + function new(f:Resource) : Void { + __f = f; + } + + public override function readByte() : Int { + var r = fread(__f, 1); + if(feof(__f)) throw new Eof(); + if(r == false) throw Custom('An error occurred'); + return ord(r); + } + + public override function readBytes( s : Bytes, p : Int, l : Int ) : Int { + if(feof(__f)) throw new Eof(); + var r = fread(__f, l); + if(r == false) throw Custom('An error occurred'); + var b = Bytes.ofString(r); + s.blit(p, b, 0, (r:String).length); + return (r:String).length; + } + + public override function close() : Void { + super.close(); + if(__f != null) fclose(__f); + } + + public function seek( p : Int, pos : FileSeek ) : Void { + var w; + switch( pos ) { + case SeekBegin: w = SEEK_SET; + case SeekCur : w = SEEK_CUR; + case SeekEnd : w = SEEK_END; + } + var r = fseek(__f, p, w); + if(r == false) throw Custom('An error occurred'); + } + + public function tell() : Int { + var r = ftell(__f); + if(r == false) throw Custom('An error occurred'); + return cast r; + } + + public function eof() : Bool { + return feof(__f); + } + + override function readLine() : String { + var r = fgets(__f); + if (false == r) throw new Eof(); + return rtrim(r, "\r\n"); + } +} diff --git a/std/php7/_std/sys/io/FileOutput.hx b/std/php7/_std/sys/io/FileOutput.hx new file mode 100644 index 00000000..f3e5ef09 --- /dev/null +++ b/std/php7/_std/sys/io/FileOutput.hx @@ -0,0 +1,76 @@ +/* + * Copyright (C)2005-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 sys.io; + +import php.*; +import php.Global.*; +import php.Const.*; + +@:coreApi +class FileOutput extends haxe.io.Output { + private var __f : Resource; + + function new(f:Resource) : Void { + __f = f; + } + + public override function writeByte( c : Int ) : Void { + var r = fwrite(__f, chr(c)); + if(r == false) throw haxe.io.Error.Custom('An error occurred'); + } + + public override function writeBytes( b : haxe.io.Bytes, p : Int, l : Int ) : Int { + var s = b.getString(p, l); + if(feof(__f)) throw new haxe.io.Eof(); + var r = fwrite(__f, s, l); + if(r == false) throw haxe.io.Error.Custom('An error occurred'); + return r; + } + + public override function flush() : Void { + var r = fflush(__f); + if(r == false) throw haxe.io.Error.Custom('An error occurred'); + } + + public override function close() : Void { + super.close(); + if(__f != null) fclose(__f); + } + + public function seek( p : Int, pos : FileSeek ) : Void { + var w; + switch( pos ) { + case SeekBegin: w = SEEK_SET; + case SeekCur : w = SEEK_CUR; + case SeekEnd : w = SEEK_END; + } + var r = fseek(__f, p, w); + if(r == false) throw haxe.io.Error.Custom('An error occurred'); + } + + public function tell() : Int { + var r = ftell(__f); + if(r == false) throw haxe.io.Error.Custom('An error occurred'); + return r; + } + +} diff --git a/std/php7/_std/sys/io/Process.hx b/std/php7/_std/sys/io/Process.hx new file mode 100644 index 00000000..8550c3cb --- /dev/null +++ b/std/php7/_std/sys/io/Process.hx @@ -0,0 +1,213 @@ +/* + * Copyright (C)2005-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 sys.io; + +import php.*; +import haxe.io.*; + +using StringTools; +using php.Global; + +@:forward(iterator) +private abstract ProcessPipes(NativeIndexedArray) from NativeIndexedArray to NativeIndexedArray { + public var stdin (get,never) : Resource; + public var stdout (get,never) : Resource; + public var stderr (get,never) : Resource; + + inline function get_stdin() return this[0]; + inline function get_stdout() return this[1]; + inline function get_stderr() return this[2]; +} + +private class ReadablePipe extends Input { + var pipe : Resource; + var tmpBytes : Bytes; + + public function new(pipe:Resource) { + this.pipe = pipe; + tmpBytes = Bytes.alloc(1); + } + + override public function close() : Void { + pipe.fclose(); + } + + override public function readByte() : Int { + if (readBytes(tmpBytes, 0, 1) == 0) throw Error.Blocked; + return tmpBytes.get(0); + } + + override public function readBytes( s:Bytes, pos:Int, len:Int ) : Int { + if(pipe.feof()) throw new Eof(); + + var result = pipe.fread(len); + if(result == "") throw new Eof(); + if(result == false) return throw Error.Custom('Failed to read process output'); + var result:String = result; + + var bytes = Bytes.ofString(result); + s.blit(pos, bytes, 0, result.length); + return result.length; + } +} + +private class WritablePipe extends Output { + var pipe : Resource; + var tmpBytes : Bytes; + + public function new(pipe:Resource) { + this.pipe = pipe; + tmpBytes = Bytes.alloc(1); + } + + override public function close() : Void { + pipe.fclose(); + } + + override public function writeByte(c:Int) : Void { + tmpBytes.set(0, c); + writeBytes(tmpBytes, 0, 1); + } + + override public function writeBytes( b : Bytes, pos : Int, l : Int ) : Int { + var s = b.getString(pos, l); + if(pipe.feof()) throw new Eof(); + + var result = Global.fwrite(pipe, s, l); + if(result == false) throw Error.Custom('Failed to write to process input'); + return result; + } +} + +class Process { + /** + Standard output. The output stream where a process writes its output data. + **/ + public var stdout(default, null) : Input; + + /** + Standard error. The output stream to output error messages or diagnostics. + **/ + public var stderr(default, null) : Input; + + /** + Standard input. The stream data going into a process. + **/ + public var stdin(default, null) : Output; + + var process : Resource; + var pipes : ProcessPipes; + var pid : Int = -1; + var running : Bool = true; + var _exitCode : Int = -1; + + /** + Construct a `Process` object, which run the given command immediately. + + Command arguments can be passed in two ways: 1. using `args`, 2. appending to `cmd` and leaving `args` as `null`. + + 1. When using `args` to pass command arguments, each argument will be automatically quoted, and shell meta-characters will be escaped if needed. + `cmd` should be an executable name that can be located in the `PATH` environment variable, or a path to an executable. + + 2. When `args` is not given or is `null`, command arguments can be appended to `cmd`. No automatic quoting/escaping will be performed. `cmd` should be formatted exactly as it would be when typed at the command line. + It can run executables, as well as shell commands that are not executables (e.g. on Windows: `dir`, `cd`, `echo` etc). + + `close()` should be called when the `Process` is no longer used. + */ + public function new( cmd : String, ?args : Array ) : Void { + var descriptors = Syntax.arrayDecl( + Syntax.arrayDecl('pipe', 'r'), + Syntax.arrayDecl('pipe', 'w'), + Syntax.arrayDecl('pipe', 'w') + ); + var result = buildCmd(cmd, args).proc_open(descriptors, pipes); + if (result == false) throw Error.Custom('Failed to start process: $cmd'); + process = result; + + updateStatus(); + + stdin = new WritablePipe(pipes.stdin); + stdout = new ReadablePipe(pipes.stdout); + stderr = new ReadablePipe(pipes.stderr); + } + + /** + Return the process ID. + */ + public function getPid() : Int { + return pid; + } + + public function exitCode( block : Bool = true ) : Null { + if(!block) { + updateStatus(); + return (running ? null : _exitCode); + } + while (running) { + var arr = Syntax.arrayDecl(process); + Syntax.suppress(Global.stream_select(arr, arr, arr, null)); + updateStatus(); + } + return _exitCode; + } + + /** + Close the process handle and release the associated resources. + All `Process` fields should not be used after `close()` is called. + */ + public function close() : Void { + if (!running) return; + + for (pipe in pipes) Global.fclose(pipe); + process.proc_close(); + } + + /** + Kill the process. + */ + public function kill() : Void { + process.proc_terminate(); + } + + function buildCmd( cmd:String, ?args:Array ) : String { + if (args == null) return cmd; + + return switch (Sys.systemName()) { + case "Windows": + [cmd.replace("/", "\\")].concat(args).map(StringTools.quoteWinArg.bind(_, true)).join(" "); + case _: + [cmd].concat(args).map(StringTools.quoteUnixArg).join(" "); + } + } + + function updateStatus() : Void { + if (!running) return; + + var status = process.proc_get_status(); + if (status == false) throw Error.Custom('Failed to obtain process status'); + var status:NativeAssocArray = status; + + pid = status['pid']; + running = status['running']; + _exitCode = status['exitcode']; + } +} \ No newline at end of file diff --git a/std/php7/_std/sys/net/Host.hx b/std/php7/_std/sys/net/Host.hx new file mode 100644 index 00000000..acc0ac18 --- /dev/null +++ b/std/php7/_std/sys/net/Host.hx @@ -0,0 +1,61 @@ +/* + * Copyright (C)2005-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 sys.net; + +import php.Global.*; +import php.SuperGlobal.*; + +@:coreApi +class Host { + + public var host(default,null) : String; + + private var _ip : String; + public var ip(default,null) : Int; + + public function new( name : String ) : Void { + host = name; + if(~/^(\d{1,3}\.){3}\d{1,3}$/.match(name)) { + _ip = name; + } else { + _ip = gethostbyname(name); + if(_ip == name) { + ip = 0; + return; + } + } + var p = _ip.split('.'); + ip = intval(sprintf('%02X%02X%02X%02X', p[3], p[2], p[1], p[0]), 16); + } + + public function toString() : String { + return _ip; + } + + public function reverse() : String { + return gethostbyaddr(_ip); + } + + public static function localhost() : String { + return _SERVER['HTTP_HOST']; + } +} diff --git a/std/php7/_std/sys/net/Socket.hx b/std/php7/_std/sys/net/Socket.hx new file mode 100644 index 00000000..faf10ebd --- /dev/null +++ b/std/php7/_std/sys/net/Socket.hx @@ -0,0 +1,174 @@ +/* + * Copyright (C)2005-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 sys.net; + +import php.*; +import php.Global.*; +import php.Const.*; +import sys.io.FileInput; +import sys.io.FileOutput; + +@:coreApi +class Socket { + + private var __s : Resource; + private var protocol : String; + public var input(default,null) : haxe.io.Input; + public var output(default,null) : haxe.io.Output; + public var custom : Dynamic; + + public function new() : Void { + input = @:privateAccess new sys.io.FileInput(null); + output = @:privateAccess new sys.io.FileOutput(null); + protocol = "tcp"; + } + + private function assignHandler() : Void { + @:privateAccess (cast input:FileInput).__f = __s; + @:privateAccess (cast output:FileOutput).__f = __s; + } + + public function close() : Void { + fclose(__s); + @:privateAccess (cast input:FileInput).__f = null; + @:privateAccess (cast output:FileOutput).__f = null; + input.close(); + output.close(); + } + + public function read() : String { + var b = ''; + while(!feof(__s)) Syntax.binop(b, '.=', fgets(__s)); + return b; + } + + public function write( content : String ) : Void { + fwrite(__s, content); + } + + public function connect(host : Host, port : Int) : Void { + var errs = null; + var errn = null; + var r = stream_socket_client(protocol + '://' + host.host + ':' + port, errn, errs); + Socket.checkError(r, errn, errs); + __s = r; + assignHandler(); + } + + public function listen(connections : Int) : Void { + throw "Not implemented"; +/* TODO: ?????? + var r = socket_listen(__s, connections); + checkError(r); +*/ + } + + public function shutdown( read : Bool, write : Bool ) : Void { + var rw = read && write ? 2 : (write ? 1 : (read ? 0 : 2)); + var r = stream_socket_shutdown(__s, rw); + checkError(r, 0, 'Unable to Shutdown'); + } + + public function bind(host : Host, port : Int) : Void { + var errs = Boot.deref(null); + var errn = Boot.deref(null); + var r = stream_socket_server( + protocol + '://' + host.ip + ':' + port, + errn, + errs, + (protocol == "udp" ? STREAM_SERVER_BIND : STREAM_SERVER_BIND | STREAM_SERVER_LISTEN) + ); + Socket.checkError(r, errn, errs); + __s = cast r; + assignHandler(); + } + + public function accept() : Socket { + var r = stream_socket_accept(__s); + checkError(r, 0, 'Unable to accept connections on socket'); + var s = new Socket(); + s.__s = r; + s.assignHandler(); + return s; + } + + private function hpOfString(s : String) : { host : Host, port : Int } { + var parts = s.split(':'); + if(parts.length == 2) { + return { host : new Host(parts[0]), port : Std.parseInt(parts[1]) }; + } else { + return { host : new Host(parts[1].substr(2)), port : Std.parseInt(parts[2]) }; + } + } + + public function peer() : { host : Host, port : Int } { + var r = stream_socket_get_name(__s, true); + checkError(r, 0, 'Unable to retrieve the peer name'); + return hpOfString(r); + } + + public function host() : { host : Host, port : Int } { + var r = stream_socket_get_name(__s, false); + checkError(r, 0, 'Unable to retrieve the host name'); + return hpOfString(r); + } + + public function setTimeout( timeout : Float ) : Void { + var s = Std.int(timeout); + var ms = Std.int((timeout - s) * 1000000); + var r = stream_set_timeout(__s, s, ms); + checkError(r, 0, 'Unable to set timeout'); + } + + public function setBlocking( b : Bool ) : Void { + var r = stream_set_blocking(__s, b); + checkError(r, 0, 'Unable to block'); + } + + public function setFastSend( b : Bool ) : Void { + throw "Not implemented"; + } + + public function waitForRead() : Void { + select([this], null, null); + } + + private static function checkError(r : Bool, code : Int, msg : String) : Void { + if(r != false) return; + throw haxe.io.Error.Custom('Error [$code]: $msg'); + } + + private static function getType(isUdp : Bool) : Int { + return isUdp ? SOCK_DGRAM : SOCK_STREAM; + } + + private static function getProtocol(protocol : String) : Int { + return getprotobyname(protocol); + } + + public static function select(read : Array, write : Array, others : Array, ?timeout : Float) : { read: Array,write: Array,others: Array } + { + throw "Not implemented"; + return null; + } + +} diff --git a/std/php7/db/Mysqli.hx b/std/php7/db/Mysqli.hx new file mode 100644 index 00000000..3bf619f3 --- /dev/null +++ b/std/php7/db/Mysqli.hx @@ -0,0 +1,71 @@ +package php.db; + +import haxe.extern.*; +import php.*; +import haxe.Constraints.Function; + +/** + @see http://php.net/manual/en/class.mysqli.php +**/ +@:native('Mysqli') +extern class Mysqli { + var affected_rows (default,null) : Int; + var client_info (default,null) : String; + var client_version (default,null) : Int; + var connect_errno (default,null) : Int; + var connect_error (default,null) : String; + var errno (default,null) : Int; + var error_list (default,null) : NativeAssocArray; + var error (default,null) : String; + var field_count (default,null) : Int; + var host_info (default,null) : String; + var protocol_version (default,null) : String; + var server_info (default,null) : String; + var server_version (default,null) : Int; + var info (default,null) : String; + var insert_id (default,null) : EitherType; + var sqlstate (default,null) : String; + var thread_id (default,null) : Int; + var warning_count (default,null) : Int; + + static function poll( read:Ref , error:Ref , reject:Ref , sec:Int, ?usec:Int ) : Int; + + function new( ?host:String, ?username:String, ?passwd:String, dbname:String = "", ?port:Int, ?socket:String ) : Void; + function autocommit( mode:Bool ) : Bool; + function begin_transaction( ?flags:Int, ?name:String ) : Bool; + function change_user( user:String, password:String, database:String ) : Bool; + function character_set_name() : String; + function close() : Bool; + function commit( ?flags:Int, ?name:String ) : Bool; + function debug( message:String ) : Bool; + function dump_debug_info() : Bool; + function get_charset() : {charset:String, collation:String, dir:String, min_length:Int, number:Int, state:Int}; + function get_client_info() : String; + function get_connection_stats() : Bool; + function get_warnings() : Mysqli_warning; + function init() : Mysqli; + function kill( processid:Int ) : Bool; + function more_results() : Bool; + function multi_query( query:String ) : Bool; + function next_result() : Bool; + function options( option:Int , value:Scalar ) : Bool; + function ping() : Bool; + function prepare( query:String ) : Mysqli_stmt; + function query( query:String, ?resultmode:Int ) : EitherType; + function real_connect( ?host:String, ?username:String, ?passwd:String, ?dbname:String, ?port:Int, ?socket:String, ?flags:Int ) : Bool; + function escape_string( escapestr:String ) : String; + function real_query( query:String ) : Bool; + function reap_async_query() : Mysqli_result; + function refresh( options:Int ) : Bool; + function rollback( ?flags:Int, ?name:String ) : Bool; + function rpl_query_type( query:String ) : Int; + function select_db( dbname:String ) : Bool; + function send_query( query:String ) : Bool; + function set_charset( charset:String ) : Bool; + function set_local_infile_handler( read_func:Function ) : Bool; + function ssl_set( key:String, cert:String, ca:String, capath:String, cipher:String) : Bool; + function stat() : String; + function stmt_init() : Mysqli_stmt; + function store_result( ?option:Int ) : Mysqli_result; + function use_result() : Mysqli_result; +} \ No newline at end of file diff --git a/std/php7/db/Mysqli_driver.hx b/std/php7/db/Mysqli_driver.hx new file mode 100644 index 00000000..b211f197 --- /dev/null +++ b/std/php7/db/Mysqli_driver.hx @@ -0,0 +1,16 @@ +package php.db; + +import php.NativeArray; + +@:native('Mysqli_driver') +extern class Mysqli_driver { + var client_info (default,null) : String ; + var client_version (default,null) : String ; + var driver_version (default,null) : String ; + var embedded (default,null) : String ; + var reconnect (default,null) : Bool ; + var report_mode (default,null) : Int ; + + function embedded_server_end() : Void; + function embedded_server_start( start:Bool, arguments:NativeArray, groups:NativeArray ) : Bool; +} \ No newline at end of file diff --git a/std/php7/db/Mysqli_result.hx b/std/php7/db/Mysqli_result.hx new file mode 100644 index 00000000..7c9624b5 --- /dev/null +++ b/std/php7/db/Mysqli_result.hx @@ -0,0 +1,40 @@ +package php.db; + +import php.*; +import haxe.extern.*; + +/** + @see http://php.net/manual/en/class.mysqli-result.php +**/ +@:native('Myslqi_result') +extern class Mysqli_result implements Traversable { + var current_field (default,null) : Int; + var field_count (default,null) : Int; + var lengths (default,null) : EitherType>; + var num_rows (default,null) : Int; + + function data_seek( offset:Int ) : Bool; + function fetch_all( ?resulttype:Int ) : NativeArray; + function fetch_array( ?resulttype:Int ) : NativeArray; + function fetch_assoc() : NativeAssocArray; + function fetch_field_direct( fieldnr:Int ) : MysqliFieldInfo; + function fetch_field() : MysqliFieldInfo; + function fetch_fields() : NativeIndexedArray; + function fetch_object( ?class_name:String = "stdClass", ?params:NativeArray ) : {}; + function fetch_row() : NativeIndexedArray; + function field_seek( fieldnr:Int ) : Bool; + function free() : Void; +} + +typedef MysqliFieldInfo = { + name : String, + orgname : String, + table : String, + orgtable : String, + max_length : Int, + length : Int, + charsetnr : Int, + flags : Int, + type : Int, + decimals : Int +} \ No newline at end of file diff --git a/std/php7/db/Mysqli_stmt.hx b/std/php7/db/Mysqli_stmt.hx new file mode 100644 index 00000000..5206b1c3 --- /dev/null +++ b/std/php7/db/Mysqli_stmt.hx @@ -0,0 +1,35 @@ +package php.db; + +import haxe.extern.*; +import php.*; + +@:native('Mysqli_stmt') +extern class Mysqli_stmt { + var affected_rows (default,null) : Int; + var errno (default,null) : Int; + var error_list (default,null) : NativeArray; + var error (default,null) : String; + var field_count (default,null) : Int; + var insert_id (default,null) : Int; + var num_rows (default,null) : Int; + var param_count (default,null) : Int; + var sqlstate (default,null) : String; + + function new( link:Mysqli, ?query:String ) : Void; + function attr_get( attr:Int ) : Int; + function attr_set( attr:Int , mode:Int ) : Bool; + function bind_param( types:String , var1:Ref, args:Rest> ) : Bool; + function bind_result( var1:Ref, args:Rest> ) : Bool; + function close() : Bool; + function data_seek( offset:Int ) : Void; + function execute() : Bool; + function fetch() : Bool; + function free_result() : Void; + function get_result() : Mysqli_result; + function get_warnings( stmt:Mysqli_stmt ) : {}; + function prepare( query:String ) : Bool; + function reset() : Bool; + function result_metadata() : Mysqli_result; + function send_long_data( param_nr:Int , data:String ) : Bool; + function store_result() : Bool; +} \ No newline at end of file diff --git a/std/php7/db/Mysqli_warning.hx b/std/php7/db/Mysqli_warning.hx new file mode 100644 index 00000000..d5b53157 --- /dev/null +++ b/std/php7/db/Mysqli_warning.hx @@ -0,0 +1,10 @@ +package php.db; + +@:native('Mysqli_warning') +extern class Mysqli_warning { + var message (default,null): String; + var sqlstate (default,null): Dynamic; + var errno (default,null): Int; + + function next() : Void; +} \ No newline at end of file diff --git a/std/php7/db/PDO.hx b/std/php7/db/PDO.hx new file mode 100644 index 00000000..ae9f709d --- /dev/null +++ b/std/php7/db/PDO.hx @@ -0,0 +1,107 @@ +/* + * Copyright (C)2005-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 php.db; + +import php.*; + +@:native('PDO') +extern class PDO { + @:phpClassConst static var PARAM_BOOL : Int; + @:phpClassConst static var PARAM_NULL : Int; + @:phpClassConst static var PARAM_INT : Int; + @:phpClassConst static var PARAM_STR : Int; + @:phpClassConst static var PARAM_LOB : Int; + @:phpClassConst static var PARAM_STMT : Int; + @:phpClassConst static var PARAM_INPUT_OUTPUT : Int; + @:phpClassConst static var FETCH_LAZY : Int; + @:phpClassConst static var FETCH_ASSOC : Int; + @:phpClassConst static var FETCH_NAMED : Int; + @:phpClassConst static var FETCH_NUM : Int; + @:phpClassConst static var FETCH_BOTH : Int; + @:phpClassConst static var FETCH_OBJ : Int; + @:phpClassConst static var FETCH_BOUND : Int; + @:phpClassConst static var FETCH_COLUMN : Int; + @:phpClassConst static var FETCH_CLASS : Int; + @:phpClassConst static var FETCH_INTO : Int; + @:phpClassConst static var FETCH_FUNC : Int; + @:phpClassConst static var FETCH_GROUP : Int; + @:phpClassConst static var FETCH_UNIQUE : Int; + @:phpClassConst static var FETCH_KEY_PAIR : Int; + @:phpClassConst static var FETCH_CLASSTYPE : Int; + @:phpClassConst static var FETCH_SERIALIZE : Int; + @:phpClassConst static var FETCH_PROPS_LATE : Int; + @:phpClassConst static var ATTR_AUTOCOMMIT : Int; + @:phpClassConst static var ATTR_PREFETCH : Int; + @:phpClassConst static var ATTR_TIMEOUT : Int; + @:phpClassConst static var ATTR_ERRMODE : Int; + @:phpClassConst static var ATTR_SERVER_VERSION : Int; + @:phpClassConst static var ATTR_CLIENT_VERSION : Int; + @:phpClassConst static var ATTR_SERVER_INFO : Int; + @:phpClassConst static var ATTR_CONNECTION_STATUS : Int; + @:phpClassConst static var ATTR_CASE : Int; + @:phpClassConst static var ATTR_CURSOR_NAME : Int; + @:phpClassConst static var ATTR_CURSOR : Int; + @:phpClassConst static var ATTR_DRIVER_NAME : String; + @:phpClassConst static var ATTR_ORACLE_NULLS : Int; + @:phpClassConst static var ATTR_PERSISTENT : Int; + @:phpClassConst static var ATTR_STATEMENT_CLASS : Int; + @:phpClassConst static var ATTR_FETCH_TABLE_NAMES : Int; + @:phpClassConst static var ATTR_STRINGIFY_FETCHES : Int; + @:phpClassConst static var ATTR_EMULATE_PREPARES : Int; + @:phpClassConst static var ERRMODE_SILENT : Int; + @:phpClassConst static var ERRMODE_WARNING : Int; + @:phpClassConst static var ERRMODE_EXCEPTION : Int; + @:phpClassConst static var CASE_NATURAL : Int; + @:phpClassConst static var CASE_LOWER : Int; + @:phpClassConst static var CASE_UPPER : Int; + @:phpClassConst static var NULL_NATURAL : Int; + @:phpClassConst static var FETCH_ORI_PRIOR : Int; + @:phpClassConst static var FETCH_ORI_FIRST : Int; + @:phpClassConst static var FETCH_ORI_LAST : Int; + @:phpClassConst static var FETCH_ORI_ABS : Int; + @:phpClassConst static var FETCH_ORI_REL : Int; + @:phpClassConst static var CURSOR_FWDONLY : Int; + @:phpClassConst static var CURSOR_SCROLL : Int; + @:phpClassConst static var ERR_NONE : String; + @:phpClassConst static var PARAM_EVT_ALLOC : Int; + @:phpClassConst static var PARAM_EVT_FREE : Int; + @:phpClassConst static var PARAM_EVT_EXEC_PRE : Int; + @:phpClassConst static var PARAM_EVT_EXEC_POST : Int; + @:phpClassConst static var PARAM_EVT_FETCH_PRE : Int; + @:phpClassConst static var PARAM_EVT_FETCH_POST : Int; + @:phpClassConst static var PARAM_EVT_NORMALIZE : Int; + + function new( dns : String, ?username : String, ?password : String, ?options : NativeArray) : Void; + function beginTransaction() : Bool; + function commit() : Bool; + function errorCode() : Dynamic; + function errorInfo() : NativeArray; + function exec(statement : String) : Int; + function getAttribute(attribute : Int) : Dynamic; + function getAvailableDrivers() : NativeArray; + function lastInsertId(?name : String) : String; + function prepare(statement : String, driver_options : NativeArray) : PDOStatement; + function query(statement : String, ?mode : Int) : PDOStatement; + function quote(String : String, ?parameter_type : Int = 2) : String; + function rollBack() : Bool; + function setAttribute(attribute : Int, value : Dynamic) : Bool; +} \ No newline at end of file diff --git a/std/php7/db/PDOException.hx b/std/php7/db/PDOException.hx new file mode 100644 index 00000000..73f034ad --- /dev/null +++ b/std/php7/db/PDOException.hx @@ -0,0 +1,8 @@ +package php.db; + +import php.RuntimeException; + +@:native('PDOException') +extern class PDOException extends RuntimeException { + var errorInfo : NativeArray; +} \ No newline at end of file diff --git a/std/php7/db/PDOStatement.hx b/std/php7/db/PDOStatement.hx new file mode 100644 index 00000000..7d5f2475 --- /dev/null +++ b/std/php7/db/PDOStatement.hx @@ -0,0 +1,26 @@ +package php.db; + +import php.*; + +@:native('PDOStatement') +extern class PDOStatement { + function bindColumn(column : Dynamic, param : Dynamic, ?type : Int, ?maxlen : Int, ?driverdata : Dynamic) : Bool; + function bindParam(parameter : Dynamic, variable : Dynamic, ?data_type : Int, ?length : Int, ?driver_options : Dynamic) : Bool; + function bindValue(parameter : Dynamic, value : Dynamic, ?data_type : Int) : Bool; + function closeCursor() : Bool; + function columnCount() : Int; + function debugDumpParams() : Bool; + function errorCode() : String; + function errorInfo() : NativeArray; + function execute(input_parameters : NativeArray) : Bool; + function fetch(?fetch_style : Int = 4, ?cursor_orientation : Int = 0, ?cursor_offset : Int = 0) : Dynamic; + function fetchAll(?fetch_style : Int, ?fetch_argument:Dynamic, ?ctor_args:NativeArray) : NativeArray; + function fetchColumn(?column_number : Int = 0) : String; + function fetchObject(?class_name : String, ?ctor_args : NativeArray) : Dynamic; + function getAttribute(attribute : Int) : Dynamic; + function getColumnMeta(column : Int) : NativeArray; + function nextRowset() : Bool; + function rowCount() : Int; + function setAttribute(attribute : Int, value : Dynamic) : Bool; + function setFetchMode(mode : Int, ?fetch : Dynamic, ?ctorargs : NativeArray) : Bool; +} \ No newline at end of file diff --git a/std/php7/db/SQLite3.hx b/std/php7/db/SQLite3.hx new file mode 100644 index 00000000..a91f2b9f --- /dev/null +++ b/std/php7/db/SQLite3.hx @@ -0,0 +1,28 @@ +package php.db; + +import haxe.Constraints; +import php.*; +import haxe.extern.EitherType; + +@:native('SQLite3') +extern class SQLite3 { + static function version() : NativeArray; + static function escapeString(value:String) : String; + function busyTimeout(msecs:Int) : Bool; + function changes() : Int; + function close() : Bool; + function new(filename:String, ?flags:Int, encryption_key:String = null) : Void; + function createAggregate(name:String, step_callback:Function, final_callback:Function, argument_count:Int = -1) : Bool; + function createCollation(name:String, callback:Function) : Bool; + function createFunction(name:String, callback:Function, argument_count:Int = -1) : Bool; + function enableExceptions( enableExceptions:Bool = false) : Bool; + function exec(query:String) : Bool; + function lastErrorCode() : Int; + function lastErrorMsg() : String; + function lastInsertRowID() : Int; + function loadExtension(shared_library:String) : Bool; + function open(filename:String, ?flags:Int, encryption_key:String = null) : Void; + function prepare(query:String) : SQLite3Stmt; + function query(query:String) : EitherType; + function querySingle(query:String, entire_row:Bool = false) : Dynamic; +} \ No newline at end of file diff --git a/std/php7/db/SQLite3Result.hx b/std/php7/db/SQLite3Result.hx new file mode 100644 index 00000000..3760d1d3 --- /dev/null +++ b/std/php7/db/SQLite3Result.hx @@ -0,0 +1,14 @@ +package php.db; + +import php.*; +import haxe.extern.EitherType; + +@:native('SQLite3Result') +extern class SQLite3Result { + function columnName(column_number:Int) : String; + function columnType(column_number:Int) : Int; + function fetchArray(?mode:Int) : EitherType>; + function finalize() : Bool; + function numColumns() : Int; + function reset() : Bool; +} \ No newline at end of file diff --git a/std/php7/db/SQLite3Stmt.hx b/std/php7/db/SQLite3Stmt.hx new file mode 100644 index 00000000..471527a5 --- /dev/null +++ b/std/php7/db/SQLite3Stmt.hx @@ -0,0 +1,16 @@ +package php.db; + +import php.*; +import haxe.extern.EitherType; + +@:native('SQLite3Stmt') +extern class SQLite3Stmt { + function bindParam(sql_param:EitherType, param:Ref, ?type:Int) : Bool; + function bindValue(sql_param:EitherType, value:Dynamic, ?type:Int) : Bool; + function clear() : Bool; + function close() : Bool; + function execute() : SQLite3Result; + function paramCount() : Int; + function readOnly() : Bool; + function reset() : Bool; +} \ No newline at end of file diff --git a/std/php7/net/SslSocket.hx b/std/php7/net/SslSocket.hx new file mode 100644 index 00000000..c3f6a47a --- /dev/null +++ b/std/php7/net/SslSocket.hx @@ -0,0 +1,31 @@ +/* + * Copyright (C)2005-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 php.net; + +class SslSocket extends sys.net.Socket { + + public function new() : Void { + super(); + protocol = "ssl"; + } + +} diff --git a/std/php7/reflection/ReflectionClass.hx b/std/php7/reflection/ReflectionClass.hx new file mode 100644 index 00000000..ea522e5f --- /dev/null +++ b/std/php7/reflection/ReflectionClass.hx @@ -0,0 +1,64 @@ +package php.reflection; + +import haxe.extern.Rest; + +@:native('ReflectionClass') +extern class ReflectionClass implements Reflector { + @:phpClassConst static var IS_IMPLICIT_ABSTRACT : Int; + @:phpClassConst static var IS_EXPLICIT_ABSTRACT : Int; + @:phpClassConst static var IS_FINAL : Int; + + static function export( argument:Dynamic, returnValue:Bool = false ) : String; + + var name : String; + + function new( argument:Dynamic ) : Void; + function getConstant( name:String ) : Dynamic; + function getConstants() : NativeAssocArray; + function getConstructor() : ReflectionMethod; + function getDefaultProperties() : NativeAssocArray; + function getDocComment() : String; + function getEndLine() : Int; + // function getExtension() : ReflectionExtension; + function getExtensionName() : String; + function getFileName() : String; + function getInterfaceNames() : NativeIndexedArray; + function getInterfaces() : NativeIndexedArray; + function getMethod( name:String ) : ReflectionMethod; + function getMethods( ?filter:Int ) : NativeIndexedArray; + function getModifiers() : Int; + function getName() : String; + function getNamespaceName() : String; + function getParentClass() : Null; + function getProperties( ?filter:Int ) : NativeIndexedArray; + function getProperty( name:String ) : ReflectionProperty; + function getShortName() : String; + function getStartLine() : Int; + function getStaticProperties() : NativeAssocArray; + function getStaticPropertyValue( name:String, ?def_value:Ref ) : Dynamic; + function getTraitAliases() : NativeAssocArray; + function getTraitNames() : NativeIndexedArray; + function getTraits() : NativeIndexedArray; + function hasConstant( name:String ) : Bool; + function hasMethod( name:String ) : Bool; + function hasProperty( name:String ) : Bool; + function implementsInterface( interfaceName:String ) : Bool; + function inNamespace() : Bool; + function isAbstract() : Bool; + function isAnonymous() : Bool; + function isCloneable() : Bool; + function isFinal() : Bool; + function isInstance( object:{} ) : Bool; + function isInstantiable() : Bool; + function isInterface() : Bool; + function isInternal() : Bool; + function isIterateable() : Bool; + function isSubclassOf( className:String ) : Bool; + function isTrait() : Bool; + function isUserDefined() : Bool; + function newInstance( args:Rest ) : Dynamic; + function newInstanceArgs( ?args:NativeIndexedArray ) : Dynamic; + function newInstanceWithoutConstructor() : Dynamic; + function setStaticPropertyValue( name:String , value:String ) : Void; + @:phpMagic function __toString() : String; +} \ No newline at end of file diff --git a/std/php7/reflection/ReflectionFunctionAbstract.hx b/std/php7/reflection/ReflectionFunctionAbstract.hx new file mode 100644 index 00000000..1a1912d2 --- /dev/null +++ b/std/php7/reflection/ReflectionFunctionAbstract.hx @@ -0,0 +1,35 @@ +package php.reflection; + + +@:native('ReflectionFunctionAbstract') +extern class ReflectionFunctionAbstract implements Reflector { + + var name : String; + + function getClosureScopeClass() : ReflectionClass; + function getClosureThis() : Dynamic; + function getDocComment() : String; + function getEndLine() : Int; + // function getExtension() : ReflectionExtension; + function getExtensionName() : String; + function getFileName() : String; + function getName() : String; + function getNamespaceName() : String; + function getNumberOfParameters() : Int; + function getNumberOfRequiredParameters() : Int; + // function getParameters() : NativeIndexedArray; + // function getReturnType() : ReflectionType; + function getShortName() : String; + function getStartLine() : Int; + function getStaticVariables() : NativeAssocArray; + function hasReturnType() : Bool; + function inNamespace() : Bool; + function isClosure() : Bool; + function isDeprecated() : Bool; + function isGenerator() : Bool; + function isInternal() : Bool; + function isUserDefined() : Bool; + function isVariadic() : Bool; + function returnsReference() : Bool; + @:phpMagic function __toString() : String; +} \ No newline at end of file diff --git a/std/php7/reflection/ReflectionMethod.hx b/std/php7/reflection/ReflectionMethod.hx new file mode 100644 index 00000000..76f2f3f4 --- /dev/null +++ b/std/php7/reflection/ReflectionMethod.hx @@ -0,0 +1,35 @@ +package php.reflection; + +import haxe.Constraints; +import haxe.extern.Rest; + +@:native('ReflectionMethod') +extern class ReflectionMethod extends ReflectionFunctionAbstract { + @:phpClassConst static var IS_STATIC : Int; + @:phpClassConst static var IS_PUBLIC : Int; + @:phpClassConst static var IS_PROTECTED : Int; + @:phpClassConst static var IS_PRIVATE : Int; + @:phpClassConst static var IS_ABSTRACT : Int; + @:phpClassConst static var IS_FINAL : Int; + + // public var class : String; + + public static function export( className:String, name:String, ?returnValue:Bool) : String; + + public function new( cls:Dynamic, name:String ) : Void; + public function getClosure( object:{} ) : Function; + public function getDeclaringClass() : ReflectionClass; + public function getModifiers() : Int; + public function getPrototype() : ReflectionMethod; + public function invoke( object:{}, args:Rest ) : Dynamic; + public function invokeArgs( object:{}, args:NativeIndexedArray ) : Dynamic; + public function isAbstract() : Bool; + public function isConstructor() : Bool; + public function isDestructor() : Bool; + public function isFinal() : Bool; + public function isPrivate() : Bool; + public function isProtected() : Bool; + public function isPublic() : Bool; + public function isStatic() : Bool; + public function setAccessible( accessible:Bool ) : Void; +} \ No newline at end of file diff --git a/std/php7/reflection/ReflectionProperty.hx b/std/php7/reflection/ReflectionProperty.hx new file mode 100644 index 00000000..99b95c09 --- /dev/null +++ b/std/php7/reflection/ReflectionProperty.hx @@ -0,0 +1,28 @@ +package php.reflection; + + +@:native('ReflectionProperty') +extern class ReflectionProperty implements Reflector { + @:phpClassConst static var IS_STATIC : Int; + @:phpClassConst static var IS_: Int; + @:phpClassConst static var IS_PROTECTED : Int; + @:phpClassConst static var IS_PRIVATE : Int; + + var name : String; + + static function export( className:Dynamic, name:String, ?returnValue:Bool ) : String; + + function new ( cls:Dynamic, name:String ) : Void; + function getDeclaringClass() : ReflectionClass; + function getDocComment() : String; + function getModifiers() : Int; + function getName() : String; + function getValue( ?object:{} ) : Dynamic; + function isPrivate() : Bool; + function isProtected() : Bool; + function isPublic() : Bool; + function isStatic() : Bool; + function setAccessible ( accessible:Bool ) : Void; + function setValue( object:{}, value:Dynamic ) : Void; + @:phpMagic function __toString() : String; +} \ No newline at end of file diff --git a/std/php7/reflection/Reflector.hx b/std/php7/reflection/Reflector.hx new file mode 100644 index 00000000..e8a1abac --- /dev/null +++ b/std/php7/reflection/Reflector.hx @@ -0,0 +1,6 @@ +package php.reflection; + +@:native('Reflector') +extern interface Reflector { + public function __toString() : String; +} \ No newline at end of file diff --git a/std/python/Boot.hx b/std/python/Boot.hx index c3ae1e9d..a9e4401f 100644 --- a/std/python/Boot.hx +++ b/std/python/Boot.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -33,6 +33,7 @@ import python.lib.Inspect; import python.Syntax; +@:dox(hide) class Boot { static var keywords:Set = new Set( @@ -254,14 +255,14 @@ class Boot { var handler = unhandleKeywords; Syntax.pythonCode("for k in keys:"); - Syntax.pythonCode(" a.append(handler(k))"); + Syntax.pythonCode(" a.append(handler(k))"); } else if (UBuiltins.hasattr(o, "__dict__")) { var a = []; var d = Syntax.field(o, "__dict__"); var keys1 = Syntax.callField(d, "keys"); Syntax.pythonCode("for k in keys1:"); - Syntax.pythonCode(" a.append(k)"); + Syntax.pythonCode(" a.append(k)"); } } diff --git a/std/python/Bytearray.hx b/std/python/Bytearray.hx index ab461b56..b5fbab3a 100644 --- a/std/python/Bytearray.hx +++ b/std/python/Bytearray.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/Bytes.hx b/std/python/Bytes.hx index 5f1c0e97..8c4b1966 100644 --- a/std/python/Bytes.hx +++ b/std/python/Bytes.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/Dict.hx b/std/python/Dict.hx index 2022dfef..c5b2feb6 100644 --- a/std/python/Dict.hx +++ b/std/python/Dict.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/Exceptions.hx b/std/python/Exceptions.hx index 469b1475..d5253b5a 100644 --- a/std/python/Exceptions.hx +++ b/std/python/Exceptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/HaxeIterable.hx b/std/python/HaxeIterable.hx index 2336b64f..2e8b962a 100644 --- a/std/python/HaxeIterable.hx +++ b/std/python/HaxeIterable.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/HaxeIterator.hx b/std/python/HaxeIterator.hx index 7294a470..a6a75784 100644 --- a/std/python/HaxeIterator.hx +++ b/std/python/HaxeIterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/KwArgs.hx b/std/python/KwArgs.hx index a27e7505..c266306c 100644 --- a/std/python/KwArgs.hx +++ b/std/python/KwArgs.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -29,8 +29,10 @@ import python.Dict; Example: - function f(kwargs:KwArgs<{a:Int}>) {} - f({a: 10}); + ```haxe + function f(kwargs:KwArgs<{a:Int}>) {} + f({a: 10}); + ``` **/ abstract KwArgs(Dict) { inline function new (d:Dict) { diff --git a/std/python/Lib.hx b/std/python/Lib.hx index 78174801..0d566023 100644 --- a/std/python/Lib.hx +++ b/std/python/Lib.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -27,8 +27,15 @@ import python.NativeStringTools; typedef PySys = python.lib.Sys; +/** + Platform-specific Python Library. Provides some platform-specific functions + for the Python target, such as conversion from Haxe types to native types + and vice-versa. +**/ class Lib { - + /** + Print the specified value on the default output. + **/ public static function print(v:Dynamic):Void { var str = Std.string(v); @@ -36,6 +43,9 @@ class Lib { PySys.stdout.flush(); } + /** + Print the specified value on the default output followed by a newline character. + **/ public static function println(v:Dynamic):Void { var str = Std.string(v); @@ -85,6 +95,9 @@ class Lib { return new AnonObject(d); } + /** + Return Python native iterable from Haxe iterable. + **/ public static function toPythonIterable (it:Iterable):python.NativeIterable { return { __iter__ : function () { @@ -105,10 +118,16 @@ class Lib { } } + /** + Return Haxe iterable from Python native iterable. + **/ public static inline function toHaxeIterable (it:NativeIterable):HaxeIterable { return new HaxeIterable(it); } + /** + Return Haxe iterator instance from Python native iterable. + **/ public static inline function toHaxeIterator (it:NativeIterator):HaxeIterator { return new HaxeIterator(it); } diff --git a/std/python/NativeArrayTools.hx b/std/python/NativeArrayTools.hx index 0eaf9527..5e13b07c 100644 --- a/std/python/NativeArrayTools.hx +++ b/std/python/NativeArrayTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/NativeIterable.hx b/std/python/NativeIterable.hx index f19d0161..425916b4 100644 --- a/std/python/NativeIterable.hx +++ b/std/python/NativeIterable.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,24 +25,24 @@ import python.HaxeIterable; import python.NativeIterator; /** - This type represents native python iterables (objects that implement __iter__() method). - It supports haxe iteration and conversion to `Iterable` by creating wrapper objects. + This type represents native Python iterables (objects that implement `__iter__()` method). + It supports Haxe iteration and conversion to `Iterable` by creating wrapper objects. **/ abstract NativeIterable(NativeIterableRaw) to NativeIterableRaw from NativeIterableRaw { /** - Return haxe `Iterable` object wrapping `this` native iterable. + Return Haxe `Iterable` object wrapping `this` native iterable. **/ @:to public inline function toHaxeIterable():HaxeIterable return new HaxeIterable(this); /** - Return haxe `Iterator` object by wrapping `this.__iter__()` native iterator. + Return Haxe `Iterator` object by wrapping `this.__iter__()` native iterator. **/ public inline function iterator():HaxeIterator return new HaxeIterator(this.__iter__()); } /** - Native python iterable protocol. + Native Python iterable protocol. **/ typedef NativeIterableRaw = { private function __iter__():NativeIterator; diff --git a/std/python/NativeIterator.hx b/std/python/NativeIterator.hx index acd04861..a6510896 100644 --- a/std/python/NativeIterator.hx +++ b/std/python/NativeIterator.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,20 +24,20 @@ package python; import python.NativeIterable.NativeIterableRaw; /** - This type represents native python iterators. - It supports automatic conversion to haxe `Iterator` by creating wrapper object. + This type represents native Python iterators. + It supports automatic conversion to Haxe `Iterator` by creating wrapper object. **/ abstract NativeIterator(NativeIteratorRaw) to NativeIteratorRaw to NativeIterable { public inline function new(p:NativeIteratorRaw) this = p; /** - Return haxe `Iterator` object by wrapping `this` native iterator. + Return Haxe `Iterator` object by wrapping `this` native iterator. **/ @:to public inline function toHaxeIterator():HaxeIterator return new HaxeIterator(this); } /** - Native python iterator protocol. + Native Python iterator protocol. **/ typedef NativeIteratorRaw = { >NativeIterableRaw, diff --git a/std/python/NativeStringTools.hx b/std/python/NativeStringTools.hx index 5ed024f0..81c6ce20 100644 --- a/std/python/NativeStringTools.hx +++ b/std/python/NativeStringTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/Set.hx b/std/python/Set.hx index ecba0ed6..3c481cdb 100644 --- a/std/python/Set.hx +++ b/std/python/Set.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/Syntax.hx b/std/python/Syntax.hx index 98702bb3..a0de2d62 100644 --- a/std/python/Syntax.hx +++ b/std/python/Syntax.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -28,7 +28,6 @@ import haxe.macro.ExprTools; #end @:noPackageRestrict -@:analyzer(no_simplification) extern class Syntax { #if macro diff --git a/std/python/Tuple.hx b/std/python/Tuple.hx index 55291067..cf2e64e2 100644 --- a/std/python/Tuple.hx +++ b/std/python/Tuple.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/VarArgs.hx b/std/python/VarArgs.hx index 8437bd1a..07f4c4ad 100644 --- a/std/python/VarArgs.hx +++ b/std/python/VarArgs.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -29,8 +29,10 @@ import python.internal.UBuiltins.list; Example: - function f(args:VarArgs) {} - f([1, 2, 3]); + ```haxe + function f(args:VarArgs) {} + f([1, 2, 3]); + ``` **/ @:analyzer(no_simplification) abstract VarArgs(Dynamic) { diff --git a/std/python/_std/Array.hx b/std/python/_std/Array.hx index 0239b988..7e21ea93 100644 --- a/std/python/_std/Array.hx +++ b/std/python/_std/Array.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/_std/Date.hx b/std/python/_std/Date.hx index 99af7ca5..4dd8b98d 100644 --- a/std/python/_std/Date.hx +++ b/std/python/_std/Date.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,9 +26,6 @@ import python.Syntax; @:coreApi class Date { static var EPOCH_UTC = Datetime.fromtimestamp(0, python.lib.datetime.Timezone.utc); - static var EPOCH_LOCAL = Datetime.fromtimestamp(0); - - var epoch : Datetime; private var date:Datetime; @@ -41,7 +38,7 @@ import python.Syntax; public inline function getTime() : Float { - return datetimeTimestamp(date, EPOCH_LOCAL); + return python.lib.Time.mktime(date.timetuple()) * 1000; } public inline function getHours() : Int diff --git a/std/python/_std/EReg.hx b/std/python/_std/EReg.hx index e0e07e5d..f0b3dcf0 100644 --- a/std/python/_std/EReg.hx +++ b/std/python/_std/EReg.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,15 +26,6 @@ import python.lib.Re.Pattern; @:coreApi class EReg { - - /** - Creates a new regular expression with pattern `r` and modifiers `opt`. - - This is equivalent to the shorthand syntax `~/r/opt` - - If `r` or `opt` are null, the result is unspecified. - **/ - var pattern:Regex; var matchObj:MatchObject; var global:Bool; @@ -53,89 +44,27 @@ class EReg { pattern = Re.compile(r, options); } - /** - Tells if `this` regular expression matches String `s`. - - This method modifies the internal state. - - If `s` is `null`, the result is unspecified. - **/ public inline function match( s : String ) : Bool { matchObj = Re.search(pattern, s); return matchObj != null; } - /** - Returns the matched sub-group `n` of `this` EReg. - - This method should only be called after `this.match` or - `this.matchSub`, and then operates on the String of that operation. - - The index `n` corresponds to the n-th set of parentheses in the pattern - of `this` EReg. If no such sub-group exists, an exception is thrown. - - If `n` equals 0, the whole matched substring is returned. - **/ public inline function matched( n : Int ) : String { return matchObj.group(n); } - /** - Returns the part to the left of the last matched substring. - - If the most recent call to `this.match` or `this.matchSub` did not - match anything, the result is unspecified. - - If the global g modifier was in place for the matching, only the - substring to the left of the leftmost match is returned. - - The result does not include the matched part. - **/ public inline function matchedLeft() : String { return matchObj.string.substr(0, matchObj.start()); } - /** - Returns the part to the right of the last matched substring. - - If the most recent call to `this.match` or `this.matchSub` did not - match anything, the result is unspecified. - - If the global g modifier was in place for the matching, only the - substring to the right of the leftmost match is returned. - - The result does not include the matched part. - **/ public inline function matchedRight() : String { return matchObj.string.substr(matchObj.end()); } - /** - Returns the position and length of the last matched substring, within - the String which was last used as argument to `this.match` or - `this.matchSub`. - - If the most recent call to `this.match` or `this.matchSub` did not - match anything, the result is unspecified. - - If the global g modifier was in place for the matching, the position and - length of the leftmost substring is returned. - **/ public inline function matchedPos() : { pos : Int, len : Int } { return { pos : matchObj.start(), len : matchObj.end() - matchObj.start() }; } - /** - Tells if `this` regular expression matches a substring of String `s`. - - This function expects `pos` and `len` to describe a valid substring of - `s`, or else the result is unspecified. To get more robust behavior, - `this.matchSub(s.substr(pos,len))` can be used instead. - - This method modifies the internal state. - - If `s` is null, the result is unspecified. - **/ public function matchSub( s : String, pos : Int, len : Int = -1):Bool { if (len != -1) { matchObj = pattern.search(s, pos, pos+len); @@ -147,24 +76,6 @@ class EReg { } - /** - Splits String `s` at all substrings `this` EReg matches. - - If a match is found at the start of `s`, the result contains a leading - empty String "" entry. - - If a match is found at the end of `s`, the result contains a trailing - empty String "" entry. - - If two matching substrings appear next to each other, the result - contains the empty String "" between them. - - By default, this method splits `s` into two parts at the first matched - substring. If the global g modifier is in place, `s` is split at each - matched substring. - - If `s` is null, the result is unspecified. - **/ public function split( s : String ) : Array { return if (global) { var ret = []; @@ -188,20 +99,6 @@ class EReg { } } - /** - Replaces the first substring of `s` which `this` EReg matches with `by`. - - If `this` EReg does not match any substring, the result is `s`. - - By default, this method replaces only the first matched substring. If - the global g modifier is in place, all matched substrings are replaced. - - If `by` contains `$1` to `$9`, the digit corresponds to number of a - matched sub-group and its value is used instead. If no such sub-group - exists, the replacement is unspecified. The string `$$` becomes `$`. - - If `s` or `by` are null, the result is unspecified. - **/ public function replace( s : String, by : String ) : String { var by = by.split("$$").join("_hx_#repl#__"); @@ -209,8 +106,10 @@ class EReg { var res = by; var g = x.groups(); for (i in 0...g.length) { - - res = res.split("$"+UBuiltins.str(i+1)).join(g[i]); + var gs = g[i]; + if (gs == null) + continue; + res = res.split("$"+UBuiltins.str(i+1)).join(gs); } res = res.split("_hx_#repl#__").join("$"); return res; @@ -218,11 +117,6 @@ class EReg { return Re.sub(pattern, replace, s, global ? 0 : 1 ); } - /** - For each occurence of the pattern in the string `s`, the function `f` is called and - can return the string that needs to be replaced. All occurences are matched anyway, - and setting the `g` flag might cause some incorrect behavior on some platforms. - **/ public function map( s : String, f : EReg -> String ) : String { var buf = new StringBuf(); @@ -274,4 +168,4 @@ class EReg { return buf.toString(); } -} \ No newline at end of file +} diff --git a/std/python/_std/Math.hx b/std/python/_std/Math.hx index 70dc27bd..8e92223d 100644 --- a/std/python/_std/Math.hx +++ b/std/python/_std/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/_std/Reflect.hx b/std/python/_std/Reflect.hx index be662ce9..d6493ab5 100644 --- a/std/python/_std/Reflect.hx +++ b/std/python/_std/Reflect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -114,6 +114,7 @@ class Reflect { } public static function deleteField( o : Dynamic, field : String ) : Bool { + field = handleKeywords(field); if( !hasField(o,field) ) return false; Syntax.callField(o, "__delattr__", field); return true; diff --git a/std/python/_std/Std.hx b/std/python/_std/Std.hx index 55862a33..a1bac1a2 100644 --- a/std/python/_std/Std.hx +++ b/std/python/_std/Std.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -45,6 +45,7 @@ import python.Syntax; } @:access(python.Boot) + @:ifFeature("typed_cast") public static function is( v : Dynamic, t : Dynamic ) : Bool { if (v == null && t == null) { diff --git a/std/python/_std/String.hx b/std/python/_std/String.hx index a62b5d72..f8f73746 100644 --- a/std/python/_std/String.hx +++ b/std/python/_std/String.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -19,175 +19,57 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -/** - The basic String class. - - A haxe String is immutable, it is not possible to modify individual - characters. No method of this class changes the state of [this] String. - - Strings can be constructed using the string literal syntax "string value". - - String can be concatenated by using the + operator. If an operand is not a - String, it is passed through Std.string() first. -**/ #if !macro import python.internal.StringImpl; #end @:coreApi @:native("str") extern class String { - /** - The number of characters in [this] String. - **/ var length(default,null) : Int; - - /** - Creates a copy from a given String. - **/ + function new(string:String) : Void; - - /** - Returns a String where all characters of [this] String are upper case. - - Affects the characters [a-z]. Other characters remain unchanged. - **/ + @:runtime public inline function toUpperCase() : String { return StringImpl.toUpperCase(this); } - /** - Returns a String where all characters of [this] String are lower case. - - Affects the characters [A-Z]. Other characters remain unchanged. - **/ @:runtime public inline function toLowerCase() : String { return StringImpl.toLowerCase(this); } - /** - Returns the character at position [index] of [this] String. - - If [index] is negative or exceeds [this].length, the empty String "" - is returned. - **/ inline public function charAt(index : Int) : String { return StringImpl.charAt(this, index); } - /** - Returns the character code at position [index] of [this] String. - - If [index] is negative or exceeds [this].length, null is returned. - - To obtain the character code of a single character, "x".code can be used - instead to inline the character code at compile time. Note that this - only works on String literals of length 1. - **/ inline public function charCodeAt( index : Int) : Null { return StringImpl.charCodeAt(this, index); } - /** - Returns the position of the leftmost occurence of [str] within [this] - String. - - If [startIndex] is given, the search is performed within the substring - of [this] String starting from [startIndex]. Otherwise the search is - performed within [this] String. In either case, the returned position - is relative to the beginning of [this] String. - - If [str] cannot be found, -1 is returned. - **/ inline function indexOf( str : String, ?startIndex : Int ) : Int { return StringImpl.indexOf(this, str, startIndex); } - /** - Returns the position of the rightmost occurence of [str] within [this] - String. - - If [startIndex] is given, the search is performed within the substring - of [this] String from 0 to [startIndex]. Otherwise the search is - performed within [this] String. In either case, the returned position - is relative to the beginning of [this] String. - - If [str] cannot be found, -1 is returned. - **/ inline function lastIndexOf( str : String, ?startIndex : Int ) : Int { return StringImpl.lastIndexOf(this, str, startIndex); } - /** - Splits [this] String at each occurence of [delimiter]. - - If [delimiter] is the empty String "", [this] String is split into an - Array of [this].length elements, where the elements correspond to the - characters of [this] String. - - If [delimiter] is not found within [this] String, the result is an Array - with one element, which equals [this] String. - - If [delimiter] is null, the result is unspecified. - - Otherwise, [this] String is split into parts at each occurence of - [delimiter]. If [this] String starts (or ends) with [delimiter}, the - result Array contains a leading (or trailing) empty String "" element. - Two subsequent delimiters also result in an empty String "" element. - **/ inline function split( delimiter : String ) : Array { return StringImpl.split(this, delimiter); } - /** - Returns [len] characters of [this] String, starting at position [pos]. - - If [len] is omitted, all characters from position [pos] to the end of - [this] String are included. - - If [pos] is negative, its value is calculated from the end of [this] - String by [this].length + [pos]. If this yields a negative value, 0 is - used instead. - - If the calculated position + [len] exceeds [this].length, the characters - from that position to the end of [this] String are returned. - - If [len] is negative, the result is unspecified. - **/ inline public function substr( pos : Int, ?len : Int ) : String { return StringImpl.substr(this, pos, len); } - /** - Returns the part of [this] String from [startIndex] to [endIndex]. - - If [startIndex] or [endIndex] are negative, 0 is used instead. - - If [startIndex] exceeds [endIndex], they are swapped. - - If the (possibly swapped) [endIndex] is omitted or exceeds - [this].length, [this].length is used instead. - - If the (possibly swapped) [startIndex] exceeds [this].length, the empty - String "" is returned. - **/ inline function substring( startIndex : Int, ?endIndex : Int ) : String { return StringImpl.substring(this, startIndex, endIndex); } - /** - Returns the String itself. - **/ inline function toString() : String return StringImpl.toString(this); - /** - Returns the String corresponding to the character code [code]. - - If [code] is negative or has another invalid value, the result is - unspecified. - **/ public static inline function fromCharCode( code : Int ) : String { return StringImpl.fromCharCode(code); } diff --git a/std/python/_std/StringBuf.hx b/std/python/_std/StringBuf.hx index b51cc1ef..c5efe8ab 100644 --- a/std/python/_std/StringBuf.hx +++ b/std/python/_std/StringBuf.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), @@ -23,28 +23,9 @@ import python.lib.io.IOBase.SeekSet; import python.lib.io.StringIO; - -/** - A String buffer is an efficient way to build a big string by appending small - elements together. - - Its cross-platform implementation uses String concatenation internally, but - StringBuf may be optimized for different targets. - - Unlike String, an instance of StringBuf is not immutable in the sense that - it can be passed as argument to functions which modify it by appending more - values. However, the internal buffer cannot be modified. -**/ - @:coreApi class StringBuf { - /** - Creates a new StringBuf instance. - - This may involve initialization of the internal buffer. - **/ - private var b : StringIO; public inline function new():Void { @@ -53,7 +34,7 @@ class StringBuf { public var length(get, never):Int; - public function get_length ():Int { + function get_length ():Int { var pos = b.tell(); b.seek(0, SeekEnd); var len = b.tell(); @@ -61,15 +42,6 @@ class StringBuf { return len; } - /** - Appends the representation of [x] to [this] StringBuf. - - The exact representation of [x] may vary per platform. To get more - consistent behavior, this function should be called with - Std.string(x). - - If [x] is null, the String "null" is appended. - **/ public inline function add( x : T ) : Void { add1(Std.string(x)); } @@ -78,37 +50,14 @@ class StringBuf { b.write(s); } - /** - Appends the character identified by [c] to [this] StringBuf. - - If [c] is negative or has another invalid value, the result is - unspecified. - **/ public inline function addChar( c : Int ) : Void { add1(String.fromCharCode(c)); } - /** - Appends a substring of [s] to [this] StringBuf. - - This function expects [pos] and [len] to describe a valid substring of - [s], or else the result is unspecified. To get more robust behavior, - [this].add(s.substr(pos,len)) can be used instead. - - If [s] or [pos] are null, the result is unspecified. - - If [len] is omitted or null, the substring ranges from [pos] to the end - of [s]. - **/ public inline function addSub( s : String, pos : Int, ?len : Int) : Void { add1((len == null ? s.substr(pos) : s.substr(pos, len))); } - /** - Returns the content of [this] StringBuf as String. - - The buffer is not emptied by this operation. - **/ public inline function toString() : String { return b.getvalue(); } diff --git a/std/python/_std/Sys.hx b/std/python/_std/Sys.hx index 1bc76398..fecb5af1 100644 --- a/std/python/_std/Sys.hx +++ b/std/python/_std/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -38,7 +38,7 @@ class Sys { environ; } - public static function time():Float { + public static inline function time():Float { return Time.time(); } @@ -100,18 +100,27 @@ class Sys { } public static function command( cmd : String, ?args : Array ) : Int { - var args = args == null ? [cmd] : [cmd].concat(args); - return python.lib.Subprocess.call(args); + return + if (args == null) + python.lib.Subprocess.call(cmd, { shell: true }); + else + python.lib.Subprocess.call([cmd].concat(args)); } - public static function cpuTime() : Float { - return python.lib.Time.clock(); + public static inline function cpuTime() : Float { + return python.lib.Timeit.default_timer(); } - public static function executablePath() : String { + @:deprecated("Use programPath instead") public static function executablePath() : String { return python.lib.Sys.argv[0]; } + // It has to be initialized before any call to Sys.setCwd()... + static var _programPath = sys.FileSystem.fullPath(python.lib.Inspect.getsourcefile(Sys)); + public static function programPath() : String { + return _programPath; + } + public static function getChar( echo : Bool ) : Int { var ch = switch (systemName()) { diff --git a/std/python/_std/Type.hx b/std/python/_std/Type.hx index f068f42a..62151c4c 100644 --- a/std/python/_std/Type.hx +++ b/std/python/_std/Type.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -75,18 +75,17 @@ enum ValueType { if (Internal.hasClassName(c)) { return Internal.fieldClassName(c); } else { - // it's not a haxe class + // it's not a Haxe class if (c == Array) return "Array"; if (c == Math) return "Math"; if (c == String) return "String"; try { - var s :String = Syntax.field(c, "__name__"); - } catch (e:Dynamic) {} + return Syntax.field(c, "__name__"); + } catch (e:Dynamic) { + return null; + } } - var res = null; - - return res; } public static function getEnumName( e : Enum ) : String { @@ -112,32 +111,9 @@ enum ValueType { return if (Internal.hasConstructs(o)) cast o else null; } - public static function createInstance( cl : Class, args : Array ) : T + public static inline function createInstance( cl : Class, args : Array ) : T { - var l = args.length; - switch( l ) - { - case 0: - return Syntax.newInstance(cl); - case 1: - return Syntax.newInstance(cl,args[0]); - case 2: - return Syntax.newInstance(cl,args[0],args[1]); - case 3: - return Syntax.newInstance(cl,args[0],args[1],args[2]); - case 4: - return Syntax.newInstance(cl,args[0],args[1],args[2],args[3]); - case 5: - return Syntax.newInstance(cl,args[0],args[1],args[2],args[3],args[4]); - case 6: - return Syntax.newInstance(cl,args[0],args[1],args[2],args[3],args[4],args[5]); - case 7: - return Syntax.newInstance(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6]); - case 8: - return Syntax.newInstance(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]); - default: - throw "Too many arguments"; - } + return Syntax.newInstance(cl, Syntax.varArgs(args)); } public static function createEmptyInstance( cl : Class ) : T diff --git a/std/python/_std/haxe/Json.hx b/std/python/_std/haxe/Json.hx index 8f213bb1..440b1293 100644 --- a/std/python/_std/haxe/Json.hx +++ b/std/python/_std/haxe/Json.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/_std/haxe/Resource.hx b/std/python/_std/haxe/Resource.hx index 910c3315..5b27886e 100644 --- a/std/python/_std/haxe/Resource.hx +++ b/std/python/_std/haxe/Resource.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2014 Haxe Foundation + * Copyright (C)2005-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"), @@ -38,29 +38,16 @@ import haxe.io.BytesData; } public static function getString( name : String ) : String { - #if embed_resources - for (k in getContent().keys().iter()) { - if (k == name) { - var b : haxe.io.Bytes = haxe.crypto.Base64.decode(getContent().get(k, null)); - return b.toString(); - } - } + var bytes = getBytes(name); + if (bytes != null) + return bytes.toString(); return null; - #else - return getContent().hasKey(name) ? Bytes.ofData(getContent().get(name, null)).toString() : null; - #end } public static function getBytes( name : String ) : haxe.io.Bytes { - #if embed_resources - for( k in getContent().keys().iter() ) - if( k == name ) { - var b : haxe.io.Bytes = haxe.crypto.Base64.decode(getContent().get(k, null)); - return b; - - } - #else - return Bytes.ofData(getContent().get(name,null)); - #end + var data = getContent().get(name, null); + if (data == null) + return null; + return Bytes.ofData(data); } } diff --git a/std/python/_std/haxe/ds/IntMap.hx b/std/python/_std/haxe/ds/IntMap.hx index 82a918a7..89a245a5 100644 --- a/std/python/_std/haxe/ds/IntMap.hx +++ b/std/python/_std/haxe/ds/IntMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/_std/haxe/ds/ObjectMap.hx b/std/python/_std/haxe/ds/ObjectMap.hx index 289860b9..b665508c 100644 --- a/std/python/_std/haxe/ds/ObjectMap.hx +++ b/std/python/_std/haxe/ds/ObjectMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/_std/haxe/ds/StringMap.hx b/std/python/_std/haxe/ds/StringMap.hx index 72c2f1d1..51cc300a 100644 --- a/std/python/_std/haxe/ds/StringMap.hx +++ b/std/python/_std/haxe/ds/StringMap.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/_std/sys/FileSystem.hx b/std/python/_std/sys/FileSystem.hx index 9e65771e..397e953b 100644 --- a/std/python/_std/sys/FileSystem.hx +++ b/std/python/_std/sys/FileSystem.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -43,7 +43,7 @@ class FileSystem { dev : s.st_dev, ino : s.st_ino, nlink : s.st_nlink, - rdev : s.st_rdev, + rdev : python.internal.UBuiltins.getattr(s, "st_rdev", 0), // st_rdev is not available on Windows mode : s.st_mode } } diff --git a/std/python/_std/sys/io/File.hx b/std/python/_std/sys/io/File.hx index 07acae99..897d70da 100644 --- a/std/python/_std/sys/io/File.hx +++ b/std/python/_std/sys/io/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -24,11 +24,6 @@ package sys.io; import python.io.IoTools; import sys.io.FileInput; -/** - API for reading and writing to files. - - See `sys.FileSystem` for the complementary file system API. -**/ @:coreApi class File { diff --git a/std/python/_std/sys/io/FileInput.hx b/std/python/_std/sys/io/FileInput.hx index b14c78cf..9d06c3e7 100644 --- a/std/python/_std/sys/io/FileInput.hx +++ b/std/python/_std/sys/io/FileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/_std/sys/io/FileOutput.hx b/std/python/_std/sys/io/FileOutput.hx index fb8a065f..12de1ee6 100644 --- a/std/python/_std/sys/io/FileOutput.hx +++ b/std/python/_std/sys/io/FileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/_std/sys/io/Process.hx b/std/python/_std/sys/io/Process.hx index 07caba56..847fff0a 100644 --- a/std/python/_std/sys/io/Process.hx +++ b/std/python/_std/sys/io/Process.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -36,10 +36,8 @@ class Process { var p:Popen; - public function new( cmd : String, args : Array ) : Void { - - p = Popen.create([cmd].concat(args), { stdin : Subprocess.PIPE, stdout: Subprocess.PIPE, stderr : Subprocess.PIPE }); - + public function new( cmd : String, ?args : Array ) : Void { + p = Popen.create(args == null ? cmd : [cmd].concat(args), { shell : args == null, stdin : Subprocess.PIPE, stdout: Subprocess.PIPE, stderr : Subprocess.PIPE }); this.stdout = IoTools.createFileInputFromText(new TextIOWrapper(new BufferedReader(p.stdout))); this.stderr = IoTools.createFileInputFromText(new TextIOWrapper(new BufferedReader(p.stderr))); this.stdin = IoTools.createFileOutputFromText(new TextIOWrapper(new BufferedWriter(p.stdin))); @@ -48,11 +46,25 @@ class Process { public function getPid() : Int { return p.pid; } - public function exitCode() : Int { + public function exitCode( block : Bool = true ) : Null { + if( block == false ) + return p.poll(); return p.wait(); } public function close() : Void { - p.terminate(); + var ver = python.lib.Sys.version_info; + if (ver[0] > 3 || (ver[0] == 3 && ver[1] >= 3)) // >= 3.3 + try { + p.terminate(); + } catch (e:python.Exceptions.ProcessLookupError) { + // it has already terminated + } + else + try { + p.terminate(); + } catch (e:python.Exceptions.OSError) { + // it has already terminated + } } public function kill() : Void { p.kill(); diff --git a/std/python/_std/sys/net/Host.hx b/std/python/_std/sys/net/Host.hx index a45feff5..235b523a 100644 --- a/std/python/_std/sys/net/Host.hx +++ b/std/python/_std/sys/net/Host.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,44 +21,26 @@ */ package sys.net; -/** - A given IP host name. -**/ class Host { - - /** - The actual IP corresponding to the host. - **/ + public var host(default,null) : String; public var ip(default,null) : Int; - /** - Creates a new Host : the name can be an IP in the form "127.0.0.1" or an host name such as "google.com", in which case - the corresponding IP address is resolved using DNS. An exception occur if the host name could not be found. - **/ - var name:String; + var name:String; + public function new( name : String ) : Void { - this.name = name; - } + host = name; + this.name = name; + } - /** - Returns the IP representation of the host - **/ public function toString() : String { - return name; - } - - /** - Perform a reverse-DNS query to resolve a host name from an IP. - **/ + return name; + } + public function reverse() : String { - return ""; - } - - /** - Returns the local computer host name - **/ + return ""; + } + public static function localhost() : String { - return ""; - } - -} \ No newline at end of file + return ""; + } +} diff --git a/std/python/_std/sys/net/Socket.hx b/std/python/_std/sys/net/Socket.hx index 83345ed2..ad25e4ec 100644 --- a/std/python/_std/sys/net/Socket.hx +++ b/std/python/_std/sys/net/Socket.hx @@ -1,5 +1,5 @@ /* -* Copyright (C)2005-2012 Haxe Foundation +* Copyright (C)2005-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"), @@ -27,6 +27,7 @@ import haxe.io.BytesData; import python.Exceptions; import python.Tuple; import python.lib.net.Socket in PSocket; +import python.lib.net.Socket.SocketModule in PSocketModule; import python.lib.net.Address in PAddress; import python.lib.Select; @@ -92,7 +93,7 @@ private class SocketOutput extends haxe.io.Output { public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int { try { var data = buf.getData(); - var payload = python.Syntax.pythonCode("data[pos:pos+len]"); + var payload = python.Syntax.pythonCode("data[{0}:{0}+{1}]", pos, len); var r = __s.send(payload,0); return r; } catch( e : BlockingIOError ) { @@ -115,7 +116,7 @@ private class SocketOutput extends haxe.io.Output { var __s:PSocket; /** The stream on which you can read available data. By default the stream is blocking until the requested data is available, - use [setBlocking(false)] or [setTimeout] to prevent infinite waiting. + use `setBlocking(false)` or `setTimeout` to prevent infinite waiting. **/ public var input(default,null) : haxe.io.Input; @@ -125,7 +126,7 @@ private class SocketOutput extends haxe.io.Output { public var output(default,null) : haxe.io.Output; /** - A custom value that can be associated with the socket. Can be used to retreive your custom infos after a [select]. + A custom value that can be associated with the socket. Can be used to retreive your custom infos after a `select`. ***/ public var custom : Dynamic; @@ -172,7 +173,7 @@ private class SocketOutput extends haxe.io.Output { } /** - Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use [accept()] to accept incoming connections. + Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use `accept()` to accept incoming connections. **/ public function listen( connections : Int ) : Void { __s.listen(connections); @@ -182,7 +183,7 @@ private class SocketOutput extends haxe.io.Output { Shutdown the socket, either for reading or writing. **/ public function shutdown( read : Bool, write : Bool ) : Void - __s.shutdown( (read && write) ? PSocket.SHUT_RDWR : read ? PSocket.SHUT_RD : PSocket.SHUT_WR ); + __s.shutdown( (read && write) ? PSocketModule.SHUT_RDWR : read ? PSocketModule.SHUT_RD : PSocketModule.SHUT_WR ); /** Bind the socket to the given host/port so it can afterwards listen for connections there. @@ -251,11 +252,11 @@ private class SocketOutput extends haxe.io.Output { /** Wait until one of the sockets groups is ready for the given operation : - [read] contains sockets on which we want to wait for available data to be read, - [write] contains sockets on which we want to wait until we are allowed to write some data to their output buffers, - [others] contains sockets on which we want to wait for exceptional conditions. - [select] will block until one of the condition is met, in which case it will return the sockets for which the condition was true. - In case a [timeout] (in seconds) is specified, select might wait at worse until the timeout expires. + - `read` contains sockets on which we want to wait for available data to be read, + - `write` contains sockets on which we want to wait until we are allowed to write some data to their output buffers, + - `others` contains sockets on which we want to wait for exceptional conditions. + - `select` will block until one of the condition is met, in which case it will return the sockets for which the condition was true. + In case a `timeout` (in seconds) is specified, select might wait at worse until the timeout expires. **/ public static function select(read : Array, write : Array, others : Array, ?timeout : Float) : { read: Array,write: Array,others: Array } { var t3 = Select.select(read,write,others,timeout); diff --git a/std/python/internal/AnonObject.hx b/std/python/internal/AnonObject.hx index fc61dcb8..3b126cc7 100644 --- a/std/python/internal/AnonObject.hx +++ b/std/python/internal/AnonObject.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/internal/ArrayImpl.hx b/std/python/internal/ArrayImpl.hx index 07c9e1ee..e7a10933 100644 --- a/std/python/internal/ArrayImpl.hx +++ b/std/python/internal/ArrayImpl.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -27,25 +27,25 @@ import python.lib.Functools; @:allow(Array) class ArrayImpl { - @:ifFeature("dynamic_read.length", "anon_optional_read.length") + @:ifFeature("dynamic_read.length", "anon_optional_read.length", "python.internal.ArrayImpl.length") public static inline function get_length (x:Array):Int return UBuiltins.len(x); - @:ifFeature("dynamic_read.concat", "anon_optional_read.concat") + @:ifFeature("dynamic_read.concat", "anon_optional_read.concat", "python.internal.ArrayImpl.concat") public static inline function concat(a1:Array, a2 : Array) : Array { return Syntax.binop(a1, "+", a2); } - @:ifFeature("dynamic_read.copy", "anon_optional_read.copy") + @:ifFeature("dynamic_read.copy", "anon_optional_read.copy", "python.internal.ArrayImpl.copy") public static inline function copy(x:Array) : Array { return UBuiltins.list(x); } - @:ifFeature("dynamic_read.iterator", "anon_optional_read.iterator") + @:ifFeature("dynamic_read.iterator", "anon_optional_read.iterator", "python.internal.ArrayImpl.iterator") public static inline function iterator(x:Array) : Iterator { return new HaxeIterator(Syntax.callField(x, "__iter__")); } - @:ifFeature("dynamic_read.indexOf", "anon_optional_read.indexOf") + @:ifFeature("dynamic_read.indexOf", "anon_optional_read.indexOf", "python.internal.ArrayImpl.indexOf") public static function indexOf(a:Array, x : T, ?fromIndex:Int) : Int { var len = a.length; var l = @@ -59,7 +59,7 @@ class ArrayImpl { return -1; } - @:ifFeature("dynamic_read.lastIndexOf", "anon_optional_read.lastIndexOf") + @:ifFeature("dynamic_read.lastIndexOf", "anon_optional_read.lastIndexOf", "python.internal.ArrayImpl.lastIndexOf") public static function lastIndexOf(a:Array, x : T, ?fromIndex:Int) : Int { var len = a.length; var l = @@ -74,33 +74,33 @@ class ArrayImpl { } @:access(python.Boot) - @:ifFeature("dynamic_read.join", "anon_optional_read.join") + @:ifFeature("dynamic_read.join", "anon_optional_read.join", "python.internal.ArrayImpl.join") public static inline function join(x:Array, sep : String ) : String { return Boot.arrayJoin(x, sep); } - @:ifFeature("dynamic_read.toString", "anon_optional_read.toString") + @:ifFeature("dynamic_read.toString", "anon_optional_read.toString", "python.internal.ArrayImpl.toString") public static inline function toString(x:Array) : String { return "[" + join(x, ",") + "]"; } - @:ifFeature("dynamic_read.pop", "anon_optional_read.pop") + @:ifFeature("dynamic_read.pop", "anon_optional_read.pop", "python.internal.ArrayImpl.pop") public static inline function pop(x:Array) : Null { return if (x.length == 0) null else Syntax.callField(x, "pop"); } - @:ifFeature("dynamic_read.push", "anon_optional_read.push") + @:ifFeature("dynamic_read.push", "anon_optional_read.push", "python.internal.ArrayImpl.push") public static inline function push(x:Array, e:T) : Int { Syntax.callField(x, "append", e); return x.length; } - @:ifFeature("dynamic_read.unshift", "anon_optional_read.unshift") + @:ifFeature("dynamic_read.unshift", "anon_optional_read.unshift", "python.internal.ArrayImpl.unshift") public static inline function unshift(x:Array,e : T) : Void { x.insert(0,e); } - @:ifFeature("dynamic_read.remove", "anon_optional_read.remove") + @:ifFeature("dynamic_read.remove", "anon_optional_read.remove", "python.internal.ArrayImpl.remove") public static function remove(x:Array,e : T) : Bool { try { Syntax.callField(x, "remove", e); @@ -110,22 +110,22 @@ class ArrayImpl { } } - @:ifFeature("dynamic_read.shift", "anon_optional_read.shift") + @:ifFeature("dynamic_read.shift", "anon_optional_read.shift", "python.internal.ArrayImpl.shift") public static inline function shift(x:Array) : Null { if (x.length == 0) return null; return Syntax.callField(x, "pop", 0); } - @:ifFeature("dynamic_read.slice", "anon_optional_read.slice") + @:ifFeature("dynamic_read.slice", "anon_optional_read.slice", "python.internal.ArrayImpl.slice") public static inline function slice(x:Array, pos : Int, ?end : Int ) : Array { return Syntax.arrayAccess(x, pos, end); } - @:ifFeature("dynamic_read.sort", "anon_optional_read.sort") + @:ifFeature("dynamic_read.sort", "anon_optional_read.sort", "python.internal.ArrayImpl.sort") public static inline function sort(x:Array, f:T->T->Int) : Void { Syntax.callNamedUntyped(Syntax.field(x, "sort"), { key : Functools.cmp_to_key(f) }); } - @:ifFeature("dynamic_read.splice", "anon_optional_read.splice") + @:ifFeature("dynamic_read.splice", "anon_optional_read.splice", "python.internal.ArrayImpl.splice") public static inline function splice(x:Array, pos : Int, len : Int ) : Array { if (pos < 0) pos = x.length+pos; if (pos < 0) pos = 0; @@ -134,21 +134,21 @@ class ArrayImpl { return res; } - @:ifFeature("dynamic_read.map", "anon_optional_read.map") + @:ifFeature("dynamic_read.map", "anon_optional_read.map", "python.internal.ArrayImpl.map") public static inline function map(x:Array, f : T -> S) : Array { return UBuiltins.list(UBuiltins.map(f, cast x)); } - @:ifFeature("dynamic_read.filter", "anon_optional_read.filter") + @:ifFeature("dynamic_read.filter", "anon_optional_read.filter", "python.internal.ArrayImpl.filter") public static inline function filter(x:Array, f : T -> Bool) : Array { return UBuiltins.list(UBuiltins.filter(f, cast x)); } - @:ifFeature("dynamic_read.insert", "anon_optional_read.insert") + @:ifFeature("dynamic_read.insert", "anon_optional_read.insert", "python.internal.ArrayImpl.insert") public static inline function insert(a:Array, pos : Int, x : T ) : Void { Syntax.callField(a, "insert", pos, x); } - @:ifFeature("dynamic_read.reverse", "anon_optional_read.reverse") + @:ifFeature("dynamic_read.reverse", "anon_optional_read.reverse", "python.internal.ArrayImpl.reverse") public static inline function reverse(a:Array) : Void { Syntax.callField(a, "reverse"); } diff --git a/std/python/internal/EnumImpl.hx b/std/python/internal/EnumImpl.hx index e7705615..50fef952 100644 --- a/std/python/internal/EnumImpl.hx +++ b/std/python/internal/EnumImpl.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/internal/HxException.hx b/std/python/internal/HxException.hx index 8510426f..0930afbb 100644 --- a/std/python/internal/HxException.hx +++ b/std/python/internal/HxException.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/internal/HxOverrides.hx b/std/python/internal/HxOverrides.hx index f3398d69..e94118dc 100644 --- a/std/python/internal/HxOverrides.hx +++ b/std/python/internal/HxOverrides.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/internal/Internal.hx b/std/python/internal/Internal.hx index 46fe0b72..d62ac471 100644 --- a/std/python/internal/Internal.hx +++ b/std/python/internal/Internal.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/internal/StringImpl.hx b/std/python/internal/StringImpl.hx index 845017f5..1d0bcd33 100644 --- a/std/python/internal/StringImpl.hx +++ b/std/python/internal/StringImpl.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,24 +26,24 @@ import python.internal.Internal; @:native("HxString") class StringImpl { - @:ifFeature("dynamic_read.split", "anon_optional_read.split") + @:ifFeature("dynamic_read.split", "anon_optional_read.split", "python.internal.StringImpl.split") public static inline function split (s:String, d:String) { return if (d == "") UBuiltins.list(s) else Syntax.callField(s, "split", d); } - @:ifFeature("dynamic_read.charCodeAt", "anon_optional_read.charCodeAt") + @:ifFeature("dynamic_read.charCodeAt", "anon_optional_read.charCodeAt", "python.internal.StringImpl.charCodeAt") public static function charCodeAt(s:String, index:Int) { return if (s == null || s.length == 0 || index < 0 || index >= s.length) null else UBuiltins.ord(Syntax.arrayAccess(s, index)); } - @:ifFeature("dynamic_read.charAt", "anon_optional_read.charAt") + @:ifFeature("dynamic_read.charAt", "anon_optional_read.charAt", "python.internal.StringImpl.charAt") public static inline function charAt(s:String, index:Int) { return if (index < 0 || index >= s.length) "" else Syntax.arrayAccess(s,index); } - @:ifFeature("dynamic_read.lastIndexOf", "anon_optional_read.lastIndexOf") + @:ifFeature("dynamic_read.lastIndexOf", "anon_optional_read.lastIndexOf", "python.internal.StringImpl.lastIndexOf") public static inline function lastIndexOf(s:String, str:String, ?startIndex:Int):Int { if (startIndex == null) { return Syntax.callField(s, "rfind", str, 0, s.length); @@ -60,30 +60,31 @@ class StringImpl { } } - @:ifFeature("dynamic_read.toUpperCase", "anon_optional_read.toUpperCase") + @:ifFeature("dynamic_read.toUpperCase", "anon_optional_read.toUpperCase", "python.internal.StringImpl.toUpperCase") public static inline function toUpperCase (s:String) { + return Syntax.callField(s, "upper"); } - @:ifFeature("dynamic_read.toLowerCase", "anon_optional_read.toLowerCase") + @:ifFeature("dynamic_read.toLowerCase", "anon_optional_read.toLowerCase", "python.internal.StringImpl.toLowerCase") public static inline function toLowerCase (s:String) { return Syntax.callField(s, "lower"); } - @:ifFeature("dynamic_read.indexOf", "anon_optional_read.indexOf") + @:ifFeature("dynamic_read.indexOf", "anon_optional_read.indexOf", "python.internal.StringImpl.indexOf") public static inline function indexOf (s:String, str:String, ?startIndex:Int) { if (startIndex == null) return Syntax.callField(s, "find", str); else return Syntax.callField(s, "find", str, startIndex); } - @:ifFeature("dynamic_read.toString", "anon_optional_read.toString") + @:ifFeature("dynamic_read.toString", "anon_optional_read.toString", "python.internal.StringImpl.toString") public static inline function toString (s:String) { return s; } - @:ifFeature("dynamic_read.length", "anon_optional_read.length") + @:ifFeature("dynamic_read.length", "anon_optional_read.length", "python.internal.StringImpl.length") public static inline function get_length (s:String) { return UBuiltins.len(s); } - @:ifFeature("dynamic_read.fromCharCode", "anon_optional_read.fromCharCode") + @:ifFeature("dynamic_read.fromCharCode", "anon_optional_read.fromCharCode", "python.internal.StringImpl.fromCharCode") public static inline function fromCharCode( code : Int ) : String { #if doc_gen return ""; @@ -91,7 +92,7 @@ class StringImpl { return Syntax.callField('', "join", UBuiltins.map(UBuiltins.chr, cast [code])); // TODO: check cast #end } - @:ifFeature("dynamic_read.substring", "anon_optional_read.substring") + @:ifFeature("dynamic_read.substring", "anon_optional_read.substring", "python.internal.StringImpl.substring") public static function substring( s:String, startIndex : Int, ?endIndex : Int ) : String { if (startIndex < 0) startIndex = 0; if (endIndex == null) { @@ -107,7 +108,7 @@ class StringImpl { } } } - @:ifFeature("dynamic_read.substr", "anon_optional_read.substr") + @:ifFeature("dynamic_read.substr", "anon_optional_read.substr", "python.internal.StringImpl.substr") public static function substr( s:String, startIndex : Int, ?len : Int ) : String { if (len == null) { return Syntax.arrayAccessWithTrailingColon(s, startIndex); diff --git a/std/python/internal/UBuiltins.hx b/std/python/internal/UBuiltins.hx index 3b25965b..ae0cf508 100644 --- a/std/python/internal/UBuiltins.hx +++ b/std/python/internal/UBuiltins.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -36,7 +36,7 @@ extern class UBuiltins { static function min(a:T, b:T):T; static function max(a:T, b:T):T; static function hasattr(o:Dynamic, a:String):Bool; - static function getattr(o:Dynamic, a:String):Dynamic; + static function getattr(o:Dynamic, a:String, ?def:Dynamic):Dynamic; static function setattr(o:Dynamic, a:String, v:Dynamic):Void; static function delattr(o:Dynamic, attr:String):Void; static function callable(x:Dynamic):Bool; diff --git a/std/python/io/FileBytesInput.hx b/std/python/io/FileBytesInput.hx index c3c4a633..72da0c78 100644 --- a/std/python/io/FileBytesInput.hx +++ b/std/python/io/FileBytesInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/io/FileBytesOutput.hx b/std/python/io/FileBytesOutput.hx index 34cb1fe4..12baf1d0 100644 --- a/std/python/io/FileBytesOutput.hx +++ b/std/python/io/FileBytesOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/io/FileTextInput.hx b/std/python/io/FileTextInput.hx index ca5ebf2c..b5c6cae1 100644 --- a/std/python/io/FileTextInput.hx +++ b/std/python/io/FileTextInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/io/FileTextOutput.hx b/std/python/io/FileTextOutput.hx index 275d0447..760fc8aa 100644 --- a/std/python/io/FileTextOutput.hx +++ b/std/python/io/FileTextOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/io/IFileInput.hx b/std/python/io/IFileInput.hx index b5ad400f..803a92af 100644 --- a/std/python/io/IFileInput.hx +++ b/std/python/io/IFileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/io/IFileOutput.hx b/std/python/io/IFileOutput.hx index b4eda69c..5d8ec8f9 100644 --- a/std/python/io/IFileOutput.hx +++ b/std/python/io/IFileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/io/IInput.hx b/std/python/io/IInput.hx index 85415b1b..ca67167f 100644 --- a/std/python/io/IInput.hx +++ b/std/python/io/IInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/io/IOutput.hx b/std/python/io/IOutput.hx index d013faff..7408a223 100644 --- a/std/python/io/IOutput.hx +++ b/std/python/io/IOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/io/IoTools.hx b/std/python/io/IoTools.hx index 7d89038e..fcd6a959 100644 --- a/std/python/io/IoTools.hx +++ b/std/python/io/IoTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/io/NativeBytesInput.hx b/std/python/io/NativeBytesInput.hx index 9d5bc6ea..4e0670ff 100644 --- a/std/python/io/NativeBytesInput.hx +++ b/std/python/io/NativeBytesInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/io/NativeBytesOutput.hx b/std/python/io/NativeBytesOutput.hx index 99b5a29d..eed68d24 100644 --- a/std/python/io/NativeBytesOutput.hx +++ b/std/python/io/NativeBytesOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/io/NativeInput.hx b/std/python/io/NativeInput.hx index 7031a141..85242fdd 100644 --- a/std/python/io/NativeInput.hx +++ b/std/python/io/NativeInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -27,23 +27,20 @@ import python.Bytearray; import python.lib.io.IOBase; import python.lib.io.RawIOBase; -class NativeInput extends Input{ +class NativeInput extends Input { var stream:T; var wasEof:Bool; function new (s:T) { this.stream = s; + this.bigEndian = false; wasEof = false; if (!stream.readable()) throw "Write-only stream"; } - public var canSeek(get_canSeek, null):Bool; - - private function get_canSeek():Bool - { - return stream.seekable(); - } + public var canSeek(get,never):Bool; + inline function get_canSeek():Bool return stream.seekable(); override public function close():Void { @@ -72,22 +69,15 @@ class NativeInput extends Input{ throw "abstract method, should be overriden"; } - override public function readBytes(s:haxe.io.Bytes, pos:Int, len:Int):Int - { + override public function readBytes(s:haxe.io.Bytes, pos:Int, len:Int):Int { if( pos < 0 || len < 0 || pos + len > s.length ) throw haxe.io.Error.OutsideBounds; - - if (canSeek) { - seek(pos, SeekBegin); - } else if (pos > 0) { - throw "Cannot call readBytes for pos > 0 (" + pos + ") on not seekable stream"; - } var ba = new Bytearray(len); var ret = readinto(ba); - s.blit(pos, haxe.io.Bytes.ofData(ba) ,0,len); if (ret == 0) throwEof(); + s.blit(pos, haxe.io.Bytes.ofData(ba), 0, len); return ret; } } \ No newline at end of file diff --git a/std/python/io/NativeOutput.hx b/std/python/io/NativeOutput.hx index e2e9b258..ee933a33 100644 --- a/std/python/io/NativeOutput.hx +++ b/std/python/io/NativeOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -30,9 +30,11 @@ class NativeOutput extends Output { var stream:T; - public var canSeek(get_canSeek, null):Bool; + public var canSeek(get,never):Bool; + inline function get_canSeek():Bool return stream.seekable(); public function new (stream:T) { + this.bigEndian = false; this.stream = stream; if (!stream.writable()) throw "Read only stream"; } @@ -42,11 +44,6 @@ class NativeOutput extends Output { stream.close(); } - private function get_canSeek():Bool - { - return stream.seekable(); - } - override public function prepare(nbytes:Int):Void { stream.truncate(nbytes); diff --git a/std/python/io/NativeTextInput.hx b/std/python/io/NativeTextInput.hx index 817094f4..e7c2351f 100644 --- a/std/python/io/NativeTextInput.hx +++ b/std/python/io/NativeTextInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/io/NativeTextOutput.hx b/std/python/io/NativeTextOutput.hx index 008ad1cd..ff0403f4 100644 --- a/std/python/io/NativeTextOutput.hx +++ b/std/python/io/NativeTextOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Builtins.hx b/std/python/lib/Builtins.hx index 5e3f0a01..aa5fa777 100644 --- a/std/python/lib/Builtins.hx +++ b/std/python/lib/Builtins.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Codecs.hx b/std/python/lib/Codecs.hx index 163d196e..d1c4f9fa 100644 --- a/std/python/lib/Codecs.hx +++ b/std/python/lib/Codecs.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/FileDescriptor.hx b/std/python/lib/FileDescriptor.hx index 93b81552..9adb4073 100644 --- a/std/python/lib/FileDescriptor.hx +++ b/std/python/lib/FileDescriptor.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/FileObject.hx b/std/python/lib/FileObject.hx index 7bb95862..70ff1a69 100644 --- a/std/python/lib/FileObject.hx +++ b/std/python/lib/FileObject.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Functools.hx b/std/python/lib/Functools.hx index 2db8aa62..67c1612f 100644 --- a/std/python/lib/Functools.hx +++ b/std/python/lib/Functools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Glob.hx b/std/python/lib/Glob.hx index b19fd21b..06050bcc 100644 --- a/std/python/lib/Glob.hx +++ b/std/python/lib/Glob.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Inspect.hx b/std/python/lib/Inspect.hx index 77456d17..51ab05fd 100644 --- a/std/python/lib/Inspect.hx +++ b/std/python/lib/Inspect.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -29,4 +29,5 @@ extern class Inspect { static function ismethod(object:Dynamic):Bool; static function isclass(object:Dynamic):Bool; static function isfunction(object:Dynamic):Bool; + static function getsourcefile(object:Dynamic):String; } diff --git a/std/python/lib/Io.hx b/std/python/lib/Io.hx index ddec82e5..1925010d 100644 --- a/std/python/lib/Io.hx +++ b/std/python/lib/Io.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Json.hx b/std/python/lib/Json.hx index 832e141b..ab83f1f0 100644 --- a/std/python/lib/Json.hx +++ b/std/python/lib/Json.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Math.hx b/std/python/lib/Math.hx index 43569ce0..c59e1844 100644 --- a/std/python/lib/Math.hx +++ b/std/python/lib/Math.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Msvcrt.hx b/std/python/lib/Msvcrt.hx index 1f5869e4..7a569b0b 100644 --- a/std/python/lib/Msvcrt.hx +++ b/std/python/lib/Msvcrt.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Os.hx b/std/python/lib/Os.hx index ac8ac2cf..70751633 100644 --- a/std/python/lib/Os.hx +++ b/std/python/lib/Os.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Pprint.hx b/std/python/lib/Pprint.hx index a687f960..7d1c5865 100644 --- a/std/python/lib/Pprint.hx +++ b/std/python/lib/Pprint.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Random.hx b/std/python/lib/Random.hx index e6c4edf1..fd6846e2 100644 --- a/std/python/lib/Random.hx +++ b/std/python/lib/Random.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Re.hx b/std/python/lib/Re.hx index 4ad2b65d..f83ca6d2 100644 --- a/std/python/lib/Re.hx +++ b/std/python/lib/Re.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Select.hx b/std/python/lib/Select.hx index 35316ded..e51a1cbc 100644 --- a/std/python/lib/Select.hx +++ b/std/python/lib/Select.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2015 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Shutil.hx b/std/python/lib/Shutil.hx index 3e82cbe9..183a88da 100644 --- a/std/python/lib/Shutil.hx +++ b/std/python/lib/Shutil.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Subprocess.hx b/std/python/lib/Subprocess.hx index cce8d334..b51598fb 100644 --- a/std/python/lib/Subprocess.hx +++ b/std/python/lib/Subprocess.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,8 @@ */ package python.lib; +import haxe.extern.EitherType; + extern class StartupInfo { public var dwFlags : Int; @@ -47,6 +49,6 @@ extern class Subprocess { public static var STDOUT:Int; - public static function call(args:Array):Int; + public static function call(args:EitherType>, ?kwArgs:python.KwArgs):Int; } \ No newline at end of file diff --git a/std/python/lib/Sys.hx b/std/python/lib/Sys.hx index 4b0b4738..0b69f2fe 100644 --- a/std/python/lib/Sys.hx +++ b/std/python/lib/Sys.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,7 +25,7 @@ import python.Exceptions.BaseException; import python.lib.io.FileIO; import python.lib.io.RawIOBase; import python.lib.io.TextIOBase; -import python.Tuple.Tuple3; +import python.Tuple; extern class TB {} @@ -36,6 +36,8 @@ extern class Sys { public static var argv(default, never):Array; + public static var executable(default, never):String; + public static function exit (x:Int):Void; public static function getfilesystemencoding():String; @@ -53,4 +55,5 @@ extern class Sys { public static function exc_info():Tuple3, T, TB>; + public static var version_info:Tuple5; } diff --git a/std/python/lib/Tempfile.hx b/std/python/lib/Tempfile.hx index d7130bbb..bf519dfc 100644 --- a/std/python/lib/Tempfile.hx +++ b/std/python/lib/Tempfile.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Termios.hx b/std/python/lib/Termios.hx index 6668e192..41fa6c18 100644 --- a/std/python/lib/Termios.hx +++ b/std/python/lib/Termios.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/ThreadLowLevel.hx b/std/python/lib/ThreadLowLevel.hx index 32b582cc..57c904ee 100644 --- a/std/python/lib/ThreadLowLevel.hx +++ b/std/python/lib/ThreadLowLevel.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Threading.hx b/std/python/lib/Threading.hx new file mode 100644 index 00000000..cb7355ce --- /dev/null +++ b/std/python/lib/Threading.hx @@ -0,0 +1,40 @@ +/* + * Copyright (C)2005-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 python.lib; + +import python.lib.threading.Thread; + +@:pythonImport("threading") +extern class Threading { + + public static function active_count():Int; + public static function current_thread():Thread; + public static function get_ident():Int; + public static function enumerate():Array; + public static function main_thread():Thread; + public static function settrace(func:Dynamic):Void; + public static function setprofile(func:Dynamic):Void; + public static function stack_size(?size:Int):Int; + public static function local():Dynamic; + public static var TIMEOUT_MAX:Float; + +} \ No newline at end of file diff --git a/std/python/lib/Time.hx b/std/python/lib/Time.hx index 540ae100..3a036806 100644 --- a/std/python/lib/Time.hx +++ b/std/python/lib/Time.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,10 +21,13 @@ */ package python.lib; +import python.lib.time.StructTime; + @:pythonImport("time") extern class Time { public static function time ():Float; public static function clock ():Float; public static function sleep (t:Float):Void; + public static function mktime(s:StructTime):Float; } \ No newline at end of file diff --git a/std/python/lib/Timeit.hx b/std/python/lib/Timeit.hx new file mode 100644 index 00000000..e7c1beac --- /dev/null +++ b/std/python/lib/Timeit.hx @@ -0,0 +1,5 @@ +package python.lib; +@:pythonImport("timeit") +extern class Timeit { + public static function default_timer():Float; +} \ No newline at end of file diff --git a/std/python/lib/Traceback.hx b/std/python/lib/Traceback.hx index 31a30468..b6eef625 100644 --- a/std/python/lib/Traceback.hx +++ b/std/python/lib/Traceback.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/Tty.hx b/std/python/lib/Tty.hx index 1567d23d..2bff3dab 100644 --- a/std/python/lib/Tty.hx +++ b/std/python/lib/Tty.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/codecs/Codec.hx b/std/python/lib/codecs/Codec.hx index b7ba47a8..666627ef 100644 --- a/std/python/lib/codecs/Codec.hx +++ b/std/python/lib/codecs/Codec.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/codecs/StreamReader.hx b/std/python/lib/codecs/StreamReader.hx index f98e28a6..6d24a783 100644 --- a/std/python/lib/codecs/StreamReader.hx +++ b/std/python/lib/codecs/StreamReader.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/codecs/StreamReaderWriter.hx b/std/python/lib/codecs/StreamReaderWriter.hx index fcfab56a..31f67387 100644 --- a/std/python/lib/codecs/StreamReaderWriter.hx +++ b/std/python/lib/codecs/StreamReaderWriter.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/codecs/StreamWriter.hx b/std/python/lib/codecs/StreamWriter.hx index fdf73ca0..0f27eb88 100644 --- a/std/python/lib/codecs/StreamWriter.hx +++ b/std/python/lib/codecs/StreamWriter.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/datetime/Datetime.hx b/std/python/lib/datetime/Datetime.hx index 09177465..2ca67317 100644 --- a/std/python/lib/datetime/Datetime.hx +++ b/std/python/lib/datetime/Datetime.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,7 @@ */ package python.lib.datetime; +import python.lib.time.StructTime; @:pythonImport("datetime", "datetime") extern class Datetime { @@ -49,6 +50,7 @@ extern class Datetime { public static function utcfromtimestamp (timestamp:Int):Datetime; public static function fromordinal (ordinal:Int):Datetime; + public function timetuple():StructTime; public function strftime (format:String):String; public function replace (?year:Int = 1970, ?month:Int = 1, ?day:Int = 1, ?hour:Int = 0, ?minute:Int = 0, ?second:Int, ?microsecond:Int, ?tzinfo:Tzinfo):Datetime; /* 0-6 */ diff --git a/std/python/lib/datetime/Timedelta.hx b/std/python/lib/datetime/Timedelta.hx index ec7c77bd..eadc0376 100644 --- a/std/python/lib/datetime/Timedelta.hx +++ b/std/python/lib/datetime/Timedelta.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/datetime/Timezone.hx b/std/python/lib/datetime/Timezone.hx index 1b99db92..c3b29945 100644 --- a/std/python/lib/datetime/Timezone.hx +++ b/std/python/lib/datetime/Timezone.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/datetime/Tzinfo.hx b/std/python/lib/datetime/Tzinfo.hx index 874146b5..becbc965 100644 --- a/std/python/lib/datetime/Tzinfo.hx +++ b/std/python/lib/datetime/Tzinfo.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/BlockingIOError.hx b/std/python/lib/io/BlockingIOError.hx index d5dbd3c3..5cc7f6f3 100644 --- a/std/python/lib/io/BlockingIOError.hx +++ b/std/python/lib/io/BlockingIOError.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/BufferedIOBase.hx b/std/python/lib/io/BufferedIOBase.hx index ca9b0c79..4579b175 100644 --- a/std/python/lib/io/BufferedIOBase.hx +++ b/std/python/lib/io/BufferedIOBase.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/BufferedRWPair.hx b/std/python/lib/io/BufferedRWPair.hx index 4155a747..8ad224ad 100644 --- a/std/python/lib/io/BufferedRWPair.hx +++ b/std/python/lib/io/BufferedRWPair.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/BufferedRandom.hx b/std/python/lib/io/BufferedRandom.hx index 4e689303..c9c771a1 100644 --- a/std/python/lib/io/BufferedRandom.hx +++ b/std/python/lib/io/BufferedRandom.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/BufferedReader.hx b/std/python/lib/io/BufferedReader.hx index b499e46c..46840aa0 100644 --- a/std/python/lib/io/BufferedReader.hx +++ b/std/python/lib/io/BufferedReader.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/BufferedWriter.hx b/std/python/lib/io/BufferedWriter.hx index 86563253..342b6db9 100644 --- a/std/python/lib/io/BufferedWriter.hx +++ b/std/python/lib/io/BufferedWriter.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/BytesIO.hx b/std/python/lib/io/BytesIO.hx index 11bb30db..294f8fe2 100644 --- a/std/python/lib/io/BytesIO.hx +++ b/std/python/lib/io/BytesIO.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/FileIO.hx b/std/python/lib/io/FileIO.hx index bf351fa5..7a44ecbe 100644 --- a/std/python/lib/io/FileIO.hx +++ b/std/python/lib/io/FileIO.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/IOBase.hx b/std/python/lib/io/IOBase.hx index 81d1b1b5..44b39111 100644 --- a/std/python/lib/io/IOBase.hx +++ b/std/python/lib/io/IOBase.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/RawIOBase.hx b/std/python/lib/io/RawIOBase.hx index fcc75477..d621fa7f 100644 --- a/std/python/lib/io/RawIOBase.hx +++ b/std/python/lib/io/RawIOBase.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/StringIO.hx b/std/python/lib/io/StringIO.hx index 68913cc0..ee30f051 100644 --- a/std/python/lib/io/StringIO.hx +++ b/std/python/lib/io/StringIO.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/TextIOBase.hx b/std/python/lib/io/TextIOBase.hx index d55479c6..802dff3d 100644 --- a/std/python/lib/io/TextIOBase.hx +++ b/std/python/lib/io/TextIOBase.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/TextIOWrapper.hx b/std/python/lib/io/TextIOWrapper.hx index 8ea53aec..8fe1fb03 100644 --- a/std/python/lib/io/TextIOWrapper.hx +++ b/std/python/lib/io/TextIOWrapper.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/io/UnsupportedOperation.hx b/std/python/lib/io/UnsupportedOperation.hx index d45a98f6..ef433aae 100644 --- a/std/python/lib/io/UnsupportedOperation.hx +++ b/std/python/lib/io/UnsupportedOperation.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/json/JSONDecoder.hx b/std/python/lib/json/JSONDecoder.hx index 4fa296b1..42bf44fd 100644 --- a/std/python/lib/json/JSONDecoder.hx +++ b/std/python/lib/json/JSONDecoder.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/json/JSONEncoder.hx b/std/python/lib/json/JSONEncoder.hx index a5c2313f..5526ad05 100644 --- a/std/python/lib/json/JSONEncoder.hx +++ b/std/python/lib/json/JSONEncoder.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/net/Address.hx b/std/python/lib/net/Address.hx index e732b295..56c139b2 100644 --- a/std/python/lib/net/Address.hx +++ b/std/python/lib/net/Address.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/net/Socket.hx b/std/python/lib/net/Socket.hx index bd5595c3..f49201f5 100644 --- a/std/python/lib/net/Socket.hx +++ b/std/python/lib/net/Socket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -30,7 +30,93 @@ import python.Tuple; @:pythonImport("socket", "socket") extern class Socket { + function send(d:BytesData,flags:Int):Int; + function recv(n:Int,flags:Int):BytesData; + + /** + Creates a new unconnected socket. + **/ + function new() : Void; + + /** + Closes the socket : make sure to properly close all your sockets or you will crash when you run out of file descriptors. + **/ + function close() : Void; + + /** + Connect to the given server host/port. Throw an exception in case we couldn't sucessfully connect. + **/ + function connect( addr : python.lib.net.Address ) : Void; + + //function create_connection() : + + /** + Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use `accept()` to accept incoming connections. + **/ + function listen( connections : Int ) : Void; + + /** + Shutdown the socket, either for reading or writing. + **/ + function shutdown( how :Int ) : Void; + + /** + Bind the socket to the given host/port so it can afterwards listen for connections there. + **/ + function bind( address : python.lib.net.Address ) : Void; + + /** + Accept a new connected client. This will return a connected socket on which you can read/write some data. + **/ + function accept() : Tuple2; + /** + Return the informations about the other side of a connected socket. + **/ + function getpeername() : python.lib.net.Address; + + /** + Return the informations about our side of a connected socket. + **/ + function getsockname() : python.lib.net.Address; + + /** + Gives a timeout after which blocking socket operations (such as reading and writing) will abort and throw an exception. + **/ + function settimeout( timeout : Float ) : Void; + + /** + Block until some data is available for read on the socket. + **/ + function waitForRead() : Void; + + /** + Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediatly by throwing a haxe.io.Error.Blocking value. + **/ + function setblocking( b : Bool ) : Void; + + /** + + **/ + function setsockopt( family:Int, option:Int, value : Bool ) : Void; + + + function fileno():Int; + + /** + Wait until one of the sockets groups is ready for the given operation : + - `read` contains sockets on which we want to wait for available data to be read, + - `write` contains sockets on which we want to wait until we are allowed to write some data to their output buffers, + - `others` contains sockets on which we want to wait for exceptional conditions. + - `select` will block until one of the condition is met, in which case it will return the sockets for which the condition was true. + In case a `timeout` (in seconds) is specified, select might wait at worse until the timeout expires. + **/ + //static function select(read : Array, write : Array, others : Array, ?timeout : Float) : { read: Array,write: Array,others: Array }; + +} + +@:pythonImport("socket") +extern class SocketModule { static var AF_APPLETALK:Int; static var AF_ASH:Int; static var AF_ATMPVC:Int; @@ -292,90 +378,4 @@ extern class Socket { static var TIPC_WITHDRAWN:Int; static var TIPC_ZONE_SCOPE:Int; static var _GLOBAL_DEFAULT_TIMEOUT:Int; - - function send(d:BytesData,flags:Int):Int; - function recv(n:Int,flags:Int):BytesData; - - - - /** - Creates a new unconnected socket. - **/ - function new() : Void; - - /** - Closes the socket : make sure to properly close all your sockets or you will crash when you run out of file descriptors. - **/ - function close() : Void; - - /** - Connect to the given server host/port. Throw an exception in case we couldn't sucessfully connect. - **/ - function connect( addr : python.lib.net.Address ) : Void; - - //function create_connection() : - - /** - Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use [accept()] to accept incoming connections. - **/ - function listen( connections : Int ) : Void; - - /** - Shutdown the socket, either for reading or writing. - **/ - function shutdown( how :Int ) : Void; - - /** - Bind the socket to the given host/port so it can afterwards listen for connections there. - **/ - function bind( address : python.lib.net.Address ) : Void; - - /** - Accept a new connected client. This will return a connected socket on which you can read/write some data. - **/ - function accept() : Tuple2; - - /** - Return the informations about the other side of a connected socket. - **/ - function getpeername() : python.lib.net.Address; - - /** - Return the informations about our side of a connected socket. - **/ - function getsockname() : python.lib.net.Address; - - /** - Gives a timeout after which blocking socket operations (such as reading and writing) will abort and throw an exception. - **/ - function settimeout( timeout : Float ) : Void; - - /** - Block until some data is available for read on the socket. - **/ - function waitForRead() : Void; - - /** - Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediatly by throwing a haxe.io.Error.Blocking value. - **/ - function setblocking( b : Bool ) : Void; - - /** - - **/ - function setsockopt( family:Int, option:Int, value : Bool ) : Void; - - - function fileno():Int; - - /** - Wait until one of the sockets groups is ready for the given operation : - [read] contains sockets on which we want to wait for available data to be read, - [write] contains sockets on which we want to wait until we are allowed to write some data to their output buffers, - [others] contains sockets on which we want to wait for exceptional conditions. - [select] will block until one of the condition is met, in which case it will return the sockets for which the condition was true. - In case a [timeout] (in seconds) is specified, select might wait at worse until the timeout expires. - **/ - //static function select(read : Array, write : Array, others : Array, ?timeout : Float) : { read: Array,write: Array,others: Array }; - } diff --git a/std/python/lib/os/Path.hx b/std/python/lib/os/Path.hx index 7b19fa01..fedce00d 100644 --- a/std/python/lib/os/Path.hx +++ b/std/python/lib/os/Path.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/subprocess/Popen.hx b/std/python/lib/subprocess/Popen.hx index 7ebccd09..89cdf6d9 100644 --- a/std/python/lib/subprocess/Popen.hx +++ b/std/python/lib/subprocess/Popen.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -27,6 +27,7 @@ import python.lib.io.TextIOBase; import python.lib.Subprocess.StartupInfo; import python.Tuple; import python.Dict; +import haxe.extern.EitherType; typedef PopenOptions = { ?bufsize : Int, @@ -47,7 +48,7 @@ typedef PopenOptions = { @:pythonImport("subprocess", "Popen") extern class Popen { - public static inline function create (args:Array, o:PopenOptions):Popen { + public static inline function create (args:EitherType>, o:PopenOptions):Popen { o.bufsize = if (Reflect.hasField(o, "bufsize")) o.bufsize else 0; o.executable = if (Reflect.hasField(o, "executable")) o.executable else null; diff --git a/std/python/lib/threading/Lock.hx b/std/python/lib/threading/Lock.hx new file mode 100644 index 00000000..b2548071 --- /dev/null +++ b/std/python/lib/threading/Lock.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-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 python.lib.threading; + +@:pythonImport("threading", "Lock") +extern class Lock { + public function new():Void; + public function acquire(?blocking:Bool, ?timeout:Float):Bool; + public function release():Void; +} \ No newline at end of file diff --git a/std/python/lib/threading/RLock.hx b/std/python/lib/threading/RLock.hx new file mode 100644 index 00000000..e76025b9 --- /dev/null +++ b/std/python/lib/threading/RLock.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-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 python.lib.threading; + +@:pythonImport("threading", "RLock") +extern class RLock { + public function new():Void; + public function acquire(?blocking:Bool, ?timeout:Float):Bool; + public function release():Void; +} \ No newline at end of file diff --git a/std/python/lib/threading/Thread.hx b/std/python/lib/threading/Thread.hx index 1ba8c707..38501931 100644 --- a/std/python/lib/threading/Thread.hx +++ b/std/python/lib/threading/Thread.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,23 @@ */ package python.lib.threading; +typedef ThreadOptions = { + @:optional var group : Dynamic; + @:optional var target : Dynamic; + @:optional var name : String; + @:optional var args : Tuple; + @:optional var kwargs : Dict; + @:optional var daemon : Dynamic; +} + @:pythonImport("threading", "Thread") extern class Thread { + public var name:String; + public var ident:Int; + public var daemon:Bool; + public function new (?options:KwArgs):Void; + public function start():Void; + public function run():Void; + public function join(?timeout:Float):Void; + public function is_alive():Bool; } \ No newline at end of file diff --git a/std/python/lib/time/StructTime.hx b/std/python/lib/time/StructTime.hx new file mode 100644 index 00000000..7eb3ddca --- /dev/null +++ b/std/python/lib/time/StructTime.hx @@ -0,0 +1,30 @@ +/* + * Copyright (C)2005-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 python.lib.time; + +@:pythonImport("time", "struct_time") +extern class StructTime implements ArrayAccess { + + + + +} \ No newline at end of file diff --git a/std/python/lib/urllib/Parse.hx b/std/python/lib/urllib/Parse.hx index 0fc6bfcb..f0bb5e2a 100644 --- a/std/python/lib/urllib/Parse.hx +++ b/std/python/lib/urllib/Parse.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/python/lib/xml/etree/ElementTree.hx b/std/python/lib/xml/etree/ElementTree.hx index 3b268684..9f941988 100644 --- a/std/python/lib/xml/etree/ElementTree.hx +++ b/std/python/lib/xml/etree/ElementTree.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/sys/FileStat.hx b/std/sys/FileStat.hx index 4dbb7427..907e6802 100644 --- a/std/sys/FileStat.hx +++ b/std/sys/FileStat.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,24 +22,62 @@ package sys; /** - File informations, as given by [sys.FileSystem.stat] + File informations, as given by `sys.FileSystem.stat`. **/ typedef FileStat = { - /** the user group id for the file **/ + + /** + The user group id for the file's owner. + **/ var gid : Int; - /** the user id for the file **/ + + /** + The user id for the file's owner. + **/ var uid : Int; - /** the last access time for the file (when enabled by the file system) **/ + + /** + The last access time for the file (when enabled by the file system). + **/ var atime : Date; - /** the last modification time for the file **/ + + /** + The last modification time for the file. + **/ var mtime : Date; - /** the creation time for the file **/ + + /** + The creation time for the file (not all filesystems support this). + **/ var ctime : Date; - /** the size of the file **/ + + /** + The size of the file, in bytes. + **/ var size : Int; + + /** + The device on which stat resides. + **/ var dev : Int; + + /** + The inode number for stat. + **/ var ino : Int; + + /** + The number of hard links to stat. + **/ var nlink : Int; + + /** + The device type on which stat resides (special files only). + **/ var rdev : Int; + + /** + The permission bits of stat. The meaning of the bits is platform dependent. + **/ var mode : Int; } diff --git a/std/sys/FileSystem.hx b/std/sys/FileSystem.hx index caae8320..54da294d 100644 --- a/std/sys/FileSystem.hx +++ b/std/sys/FileSystem.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/sys/db/Connection.hx b/std/sys/db/Connection.hx index 8871c125..b9063579 100644 --- a/std/sys/db/Connection.hx +++ b/std/sys/db/Connection.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/sys/db/Manager.hx b/std/sys/db/Manager.hx index 71afd922..526e160f 100644 --- a/std/sys/db/Manager.hx +++ b/std/sys/db/Manager.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -29,6 +29,7 @@ import sys.db.RecordInfos; Haxe website to learn how to use Record. **/ #if !macro @:build(sys.db.RecordMacros.addRtti()) #end +@:deprecated("This class will be removed soon, please install the record-macros library") class Manager { /* ----------------------------- STATICS ------------------------------ */ @@ -525,6 +526,11 @@ class Manager { } public static function nullCompare( a : String, b : String, eq : Bool ) { + if (a == null || a == 'NULL') { + return eq ? '$b IS NULL' : '$b IS NOT NULL'; + } else if (b == null || b == 'NULL') { + return eq ? '$a IS NULL' : '$a IS NOT NULL'; + } // we can't use a null-safe operator here if( cnx.dbName() != "MySQL" ) return a + (eq ? " = " : " != ") + b; @@ -718,6 +724,10 @@ class Manager { /* ---------------------------- QUOTES -------------------------- */ public static function quoteAny( v : Dynamic ) { + if (v == null) { + return 'NULL'; + } + var s = new StringBuf(); cnx.addValue(s, v); return s.toString(); diff --git a/std/sys/db/Mysql.hx b/std/sys/db/Mysql.hx index 315d787d..809b7337 100644 --- a/std/sys/db/Mysql.hx +++ b/std/sys/db/Mysql.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/sys/db/Object.hx b/std/sys/db/Object.hx index 02db2ae8..8b535592 100644 --- a/std/sys/db/Object.hx +++ b/std/sys/db/Object.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -27,6 +27,7 @@ package sys.db; **/ @:keepSub @:autoBuild(sys.db.RecordMacros.macroBuild()) @:skipFields +@:deprecated("This class will be removed soon, please install the record-macros library") class Object { var _lock(default,never) : Bool; diff --git a/std/sys/db/RecordInfos.hx b/std/sys/db/RecordInfos.hx index 002f5099..bdfc09d8 100644 --- a/std/sys/db/RecordInfos.hx +++ b/std/sys/db/RecordInfos.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -21,6 +21,7 @@ */ package sys.db; +@:deprecated("This class will be removed soon, please install the record-macros library") enum RecordType { DId; DInt; @@ -59,12 +60,14 @@ enum RecordType { DNull; } +@:deprecated("This class will be removed soon, please install the record-macros library") typedef RecordField = { var name : String; var t : RecordType; var isNull : Bool; } +@:deprecated("This class will be removed soon, please install the record-macros library") typedef RecordRelation = { var prop : String; var key : String; @@ -75,6 +78,7 @@ typedef RecordRelation = { var isNull : Bool; } +@:deprecated("This class will be removed soon, please install the record-macros library") typedef RecordInfos = { var name : String; var key : Array; diff --git a/std/sys/db/RecordMacros.hx b/std/sys/db/RecordMacros.hx index b8571aae..9dda10aa 100644 --- a/std/sys/db/RecordMacros.hx +++ b/std/sys/db/RecordMacros.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -36,6 +36,7 @@ private typedef SqlFunction = { var sql : String; } +@:deprecated("This class will be removed soon, please install the record-macros library") class RecordMacros { static var GLOBAL = null; @@ -363,7 +364,7 @@ class RecordMacros { }; var isId = switch( fi.t ) { case DId, DUId, DBigId: true; - default: fi.name == "id"; + default: i.key == null && fi.name == "id"; } if( isId ) { switch(fi.t) @@ -488,7 +489,7 @@ class RecordMacros { return { expr : EBinop(OpAdd, sql, makeString(s,sql.pos)), pos : sql.pos }; } - function sqlQuoteValue( v : Expr, t : RecordType ) { + function sqlQuoteValue( v : Expr, t : RecordType, isNull : Bool ) { switch( v.expr ) { case EConst(c): switch( c ) { @@ -498,18 +499,18 @@ class RecordMacros { case CIdent(n): switch( n ) { case "null": return { expr : EConst(CString("NULL")), pos : v.pos }; - case "true": return { expr : EConst(CInt("TRUE")), pos : v.pos }; - case "false": return { expr : EConst(CInt("FALSE")), pos : v.pos }; + case "true": return { expr : EConst(CString("TRUE")), pos : v.pos }; + case "false": return { expr : EConst(CString("FALSE")), pos : v.pos }; } default: } default: } - return { expr : ECall( { expr : EField(manager, "quoteAny"), pos : v.pos }, [ensureType(v,t)]), pos : v.pos } + return { expr : ECall( { expr : EField(manager, "quoteAny"), pos : v.pos }, [ensureType(v,t,isNull)]), pos : v.pos } } - inline function sqlAddValue( sql : Expr, v : Expr, t : RecordType ) { - return { expr : EBinop(OpAdd, sql, sqlQuoteValue(v,t)), pos : sql.pos }; + inline function sqlAddValue( sql : Expr, v : Expr, t : RecordType, isNull : Bool ) { + return { expr : EBinop(OpAdd, sql, sqlQuoteValue(v,t, isNull)), pos : sql.pos }; } function unifyClass( t : RecordType ) { @@ -639,8 +640,12 @@ class RecordMacros { var epath = e.split('.'); var ename = epath.pop(); var etype = TPath({ name:ename, pack:epath }); - var expr = macro std.Type.enumIndex( @:pos(e2.pos) ( $e2 : $etype ) ); //make sure we have the correct type - return { sql: makeOp(eq?" = ":" != ", r1.sql, expr, pos), t : DBool, n : r1.n }; + if (r1.n) { + return { sql: macro $manager.nullCompare(${r1.sql}, { var tmp = @:pos(e2.pos) (${e2} : $etype); tmp == null ? null : (std.Type.enumIndex(tmp) + ''); }, ${eq ? macro true : macro false}), t : DBool, n: true }; + } else { + var expr = macro { @:pos(e2.pos) var tmp : $etype = $e2; (tmp == null ? null : (std.Type.enumIndex(tmp) + '')); }; + return { sql: makeOp(eq?" = ":" != ", r1.sql, expr, pos), t : DBool, n : r1.n }; + } } default: } @@ -673,7 +678,7 @@ class RecordMacros { var t = typeof(cond); isNull = false; var d = try makeType(t) catch( e : String ) try makeType(follow(t)) catch( e : String ) error("Unsupported type " + Std.string(t), cond.pos); - return { sql : sqlQuoteValue(cond, d), t : d, n : isNull }; + return { sql : sqlQuoteValue(cond, d, isNull), t : d, n : isNull }; } function getField( f : { field : String, expr : Expr } ) { @@ -691,7 +696,7 @@ class RecordMacros { var m = getManager(typeof(mpath),p); var getid = { expr : ECall( { expr : EField(mpath, "unsafeGetId"), pos : p }, [f.expr]), pos : p }; f.field = r.key; - f.expr = ensureType(getid, m.inf.hfields.get(m.inf.key[0]).t); + f.expr = ensureType(getid, m.inf.hfields.get(m.inf.key[0]).t, r.isNull); return inf.hfields.get(r.key); } error("No database field '" + f.field+"'", f.expr.pos); @@ -714,7 +719,7 @@ class RecordMacros { else sql = sqlAddString(sql, " AND "); sql = sqlAddString(sql, quoteField(fi.name) + (fi.isNull ? " <=> " : " = ")); - sql = sqlAddValue(sql, f.expr, fi.t); + sql = sqlAddValue(sql, f.expr, fi.t, fi.isNull); if( fields.exists(fi.name) ) error("Duplicate field " + fi.name, p); else @@ -807,7 +812,7 @@ class RecordMacros { switch( c ) { case CInt(s): return { sql : makeString(s, p), t : DInt, n : false }; case CFloat(s): return { sql : makeString(s, p), t : DFloat, n : false }; - case CString(s): return { sql : sqlQuoteValue(cond, DText), t : DString(s.length), n : false }; + case CString(s): return { sql : sqlQuoteValue(cond, DText, false), t : DString(s.length), n : false }; case CRegexp(_): error("Unsupported", p); case CIdent(n): if( n.charCodeAt(0) == "$".code ) { @@ -911,8 +916,12 @@ class RecordMacros { return null; } - function ensureType( e : Expr, rt : RecordType ) { - return { expr : ECheckType(e, convertType(rt)), pos : e.pos }; + function ensureType( e : Expr, rt : RecordType, isNull : Bool ) { + var t = convertType(rt); + if (isNull) { + t = macro : Null<$t>; + } + return { expr : ECheckType(e, t), pos : e.pos }; } function checkKeys( econd : Expr ) { @@ -928,14 +937,14 @@ class RecordMacros { else error("Field " + f.field + " is not part of table key (" + inf.key.join(",") + ")", p); } - f.expr = ensureType(f.expr, fi.t); + f.expr = ensureType(f.expr, fi.t, fi.isNull); } return econd; default: if( inf.key.length > 1 ) error("You can't use a single value on a table with multiple keys (" + inf.key.join(",") + ")", p); var fi = inf.hfields.get(inf.key[0]); - return ensureType(econd, fi.t); + return ensureType(econd, fi.t, fi.isNull); } } diff --git a/std/sys/db/ResultSet.hx b/std/sys/db/ResultSet.hx index aff4c328..b310911c 100644 --- a/std/sys/db/ResultSet.hx +++ b/std/sys/db/ResultSet.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/sys/db/Sqlite.hx b/std/sys/db/Sqlite.hx index 5fd435ea..225ff9db 100644 --- a/std/sys/db/Sqlite.hx +++ b/std/sys/db/Sqlite.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/sys/db/TableCreate.hx b/std/sys/db/TableCreate.hx index 1a317397..8a78cc17 100644 --- a/std/sys/db/TableCreate.hx +++ b/std/sys/db/TableCreate.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,6 +22,7 @@ package sys.db; import sys.db.RecordInfos; +@:deprecated("This class will be removed soon, please install the record-macros library") class TableCreate { static function autoInc( dbName ) { diff --git a/std/sys/db/Transaction.hx b/std/sys/db/Transaction.hx index e33d203c..44a3461c 100644 --- a/std/sys/db/Transaction.hx +++ b/std/sys/db/Transaction.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/sys/db/Types.hx b/std/sys/db/Types.hx index 413e5343..359ede61 100644 --- a/std/sys/db/Types.hx +++ b/std/sys/db/Types.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -25,103 +25,137 @@ package sys.db; /** int with auto increment **/ @:noPackageRestrict +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SId = Null /** int unsigned with auto increment **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SUId = Null /** big int with auto increment **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SBigId = Null +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SInt = Null +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SUInt = Null +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SBigInt = Null /** single precision float **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SSingle = Null /** double precision float **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SFloat = Null -/** use tinyint(1) to distinguish with int **/ +/** use `tinyint(1)` to distinguish with int **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SBool = Null -/** same as varchar(n) **/ +/** same as `varchar(n)` **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SString = String -/** date only, use SDateTime for date+time **/ +/** date only, use `SDateTime` for date+time **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SDate = Date /** mysql DateTime **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SDateTime = Date /** mysql Timestamp **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef STimeStamp = Date /** TinyText (up to 255 bytes) **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef STinyText = String /** Text (up to 64KB) **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SSmallText = String /** MediumText (up to 24MB) **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SText = String /** Blob type (up to 64KB) **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SSmallBinary = haxe.io.Bytes /** LongBlob type (up to 4GB) **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SLongBinary = haxe.io.Bytes /** MediumBlob type (up to 24MB) **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SBinary = haxe.io.Bytes /** same as binary(n) **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SBytes = haxe.io.Bytes -/** one byte signed [-128...127] **/ +/** one byte signed `-128...127` **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef STinyInt = Null -/** two bytes signed [-32768...32767] **/ +/** two bytes signed `-32768...32767` **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SSmallInt = Null -/** three bytes signed [-8388608...8388607] **/ +/** three bytes signed `-8388608...8388607` **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SMediumInt = Null -/** one byte [0...255] **/ +/** one byte `0...255` **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef STinyUInt = Null -/** two bytes [0...65535] **/ +/** two bytes `0...65535` **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SSmallUInt = Null -/** three bytes [0...16777215] **/ +/** three bytes `0...16777215` **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SMediumUInt = Null // extra /** specify that this field is nullable **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SNull = Null /** specify that the integer use custom encoding **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SEncoded = Null -/** haxe Serialized string **/ +/** Haxe Serialized string **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SSerialized = String /** native neko serialized bytes **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SNekoSerialized = haxe.io.Bytes /** a set of bitflags of different enum values **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SFlags = Null> -/** same as [SFlags] but will adapt the storage size to the number of flags **/ +/** same as `SFlags` but will adapt the storage size to the number of flags **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SSmallFlags = SFlags; /** allow to store any value in serialized form **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SData = Null /** allow to store an enum value that does not have parameters as a simple int **/ +@:deprecated("This class will be removed soon, please install the record-macros library") typedef SEnum = Null diff --git a/std/sys/io/File.hx b/std/sys/io/File.hx index 06ddf45a..419c3a12 100644 --- a/std/sys/io/File.hx +++ b/std/sys/io/File.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/sys/io/FileInput.hx b/std/sys/io/FileInput.hx index 6dc8178f..af2aa57c 100644 --- a/std/sys/io/FileInput.hx +++ b/std/sys/io/FileInput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,7 +22,7 @@ package sys.io; /** - Use [sys.io.File.read] to create a [FileInput] + Use `sys.io.File.read` to create a `FileInput`. **/ extern class FileInput extends haxe.io.Input { diff --git a/std/sys/io/FileOutput.hx b/std/sys/io/FileOutput.hx index 815a032f..554c7d5f 100644 --- a/std/sys/io/FileOutput.hx +++ b/std/sys/io/FileOutput.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,7 +22,7 @@ package sys.io; /** - Use [sys.io.File.write] to create a [FileOutput] + Use `sys.io.File.write` to create a `FileOutput`. **/ extern class FileOutput extends haxe.io.Output { diff --git a/std/sys/io/FileSeek.hx b/std/sys/io/FileSeek.hx index a7a84df5..b99de9b6 100644 --- a/std/sys/io/FileSeek.hx +++ b/std/sys/io/FileSeek.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/sys/io/Process.hx b/std/sys/io/Process.hx index 2ad4b14c..792eebff 100644 --- a/std/sys/io/Process.hx +++ b/std/sys/io/Process.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,15 +22,58 @@ package sys.io; extern class Process { + /** + Standard output. The output stream where a process writes its output data. + **/ + var stdout(default, null) : haxe.io.Input; - var stdout(default,null) : haxe.io.Input; - var stderr(default,null) : haxe.io.Input; - var stdin(default,null) : haxe.io.Output; + /** + Standard error. The output stream to output error messages or diagnostics. + **/ + var stderr(default, null) : haxe.io.Input; - function new( cmd : String, args : Array ) : Void; + /** + Standard input. The stream data going into a process. + **/ + var stdin(default, null) : haxe.io.Output; + + /** + Construct a `Process` object, which run the given command immediately. + + Command arguments can be passed in two ways: 1. using `args`, 2. appending to `cmd` and leaving `args` as `null`. + + 1. When using `args` to pass command arguments, each argument will be automatically quoted, and shell meta-characters will be escaped if needed. + `cmd` should be an executable name that can be located in the `PATH` environment variable, or a path to an executable. + + 2. When `args` is not given or is `null`, command arguments can be appended to `cmd`. No automatic quoting/escaping will be performed. `cmd` should be formatted exactly as it would be when typed at the command line. + It can run executables, as well as shell commands that are not executables (e.g. on Windows: `dir`, `cd`, `echo` etc). + + `close()` should be called when the `Process` is no longer used. + */ + function new( cmd : String, ?args : Array ) : Void; + + /** + Return the process ID. + */ function getPid() : Int; - function exitCode() : Int; + + /** + Query the exit code of the process. + If `block` is true or not specified, it will block until the process terminates. + If `block` is false, it will return either the process exit code if it's already terminated or null if it's still running. + If the process has already exited, return the exit code immediately. + */ + function exitCode( block : Bool = true ) : Null; + + /** + Close the process handle and release the associated resources. + All `Process` fields should not be used after `close()` is called. + */ function close() : Void; + + /** + Kill the process. + */ function kill() : Void; } \ No newline at end of file diff --git a/std/sys/net/Address.hx b/std/sys/net/Address.hx index 04db161d..de70125b 100644 --- a/std/sys/net/Address.hx +++ b/std/sys/net/Address.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), @@ -22,7 +22,8 @@ package sys.net; /** - An address is used to represent a port on a given host ip. It is used by UdpSocket. + An address is used to represent a port on a given host ip. + It is used by `sys.net.UdpSocket`. **/ class Address { public var host : Int; diff --git a/std/sys/net/Host.hx b/std/sys/net/Host.hx index c49dfe49..93dccc4f 100644 --- a/std/sys/net/Host.hx +++ b/std/sys/net/Host.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -26,6 +26,11 @@ package sys.net; **/ extern class Host { + /** + The provided host string. + **/ + var host(default,null) : String; + /** The actual IP corresponding to the host. **/ diff --git a/std/sys/net/Socket.hx b/std/sys/net/Socket.hx index ff1c0276..aedda612 100644 --- a/std/sys/net/Socket.hx +++ b/std/sys/net/Socket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), @@ -28,17 +28,17 @@ extern class Socket { /** The stream on which you can read available data. By default the stream is blocking until the requested data is available, - use [setBlocking(false)] or [setTimeout] to prevent infinite waiting. + use `setBlocking(false)` or `setTimeout` to prevent infinite waiting. **/ var input(default,null) : haxe.io.Input; /** - The stream on which you can send data. Please note that in case the output buffer you will block while writing the data, use [setBlocking(false)] or [setTimeout] to prevent that. + The stream on which you can send data. Please note that in case the output buffer you will block while writing the data, use `setBlocking(false)` or `setTimeout` to prevent that. **/ var output(default,null) : haxe.io.Output; /** - A custom value that can be associated with the socket. Can be used to retreive your custom infos after a [select]. + A custom value that can be associated with the socket. Can be used to retreive your custom infos after a `select`. ***/ var custom : Dynamic; @@ -68,7 +68,7 @@ extern class Socket { function connect( host : Host, port : Int ) : Void; /** - Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use [accept()] to accept incoming connections. + Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use `accept()` to accept incoming connections. **/ function listen( connections : Int ) : Void; @@ -119,11 +119,11 @@ extern class Socket { /** Wait until one of the sockets groups is ready for the given operation : - [read] contains sockets on which we want to wait for available data to be read, - [write] contains sockets on which we want to wait until we are allowed to write some data to their output buffers, - [others] contains sockets on which we want to wait for exceptional conditions. - [select] will block until one of the condition is met, in which case it will return the sockets for which the condition was true. - In case a [timeout] (in seconds) is specified, select might wait at worse until the timeout expires. + - `read`contains sockets on which we want to wait for available data to be read, + - `write` contains sockets on which we want to wait until we are allowed to write some data to their output buffers, + - `others` contains sockets on which we want to wait for exceptional conditions. + - `select` will block until one of the condition is met, in which case it will return the sockets for which the condition was true. + In case a `timeout` (in seconds) is specified, select might wait at worse until the timeout expires. **/ static function select(read : Array, write : Array, others : Array, ?timeout : Float) : { read: Array,write: Array,others: Array }; diff --git a/std/sys/net/UdpSocket.hx b/std/sys/net/UdpSocket.hx index 87a86585..b61e9283 100644 --- a/std/sys/net/UdpSocket.hx +++ b/std/sys/net/UdpSocket.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2012 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/std/sys/ssl/Certificate.hx b/std/sys/ssl/Certificate.hx new file mode 100644 index 00000000..22211468 --- /dev/null +++ b/std/sys/ssl/Certificate.hx @@ -0,0 +1,39 @@ +package sys.ssl; + +extern class Certificate { + + public static function loadFile( file : String ) : Certificate; + + public static function loadPath( path : String ) : Certificate; + + public static function fromString( str : String ) : Certificate; + + public static function loadDefaults() : Certificate; + + public var commonName(get,null) : Null; + + public var altNames(get,null) : Array; + + public var notBefore(get,null) : Date; + + public var notAfter(get,null) : Date; + + public function subject( field : String ) : Null; + + public function issuer( field : String ) : Null; + + public function next() : Null; + + public function add( pem : String ) : Void; + + public function addDER( der : haxe.io.Bytes ) : Void; + + private function get_commonName() : Null; + + private function get_altNames() : Array; + + private function get_notBefore() : Date; + + private function get_notAfter() : Date; + +} diff --git a/std/sys/ssl/Digest.hx b/std/sys/ssl/Digest.hx new file mode 100644 index 00000000..3499a2b1 --- /dev/null +++ b/std/sys/ssl/Digest.hx @@ -0,0 +1,11 @@ +package sys.ssl; + +extern class Digest { + + static function make( data : haxe.io.Bytes, alg : DigestAlgorithm ) : haxe.io.Bytes; + + static function sign( data : haxe.io.Bytes, privKey : Key, alg : DigestAlgorithm ) : haxe.io.Bytes; + + static function verify( data : haxe.io.Bytes, signature : haxe.io.Bytes, pubKey : Key, alg : DigestAlgorithm ) : Bool; + +} diff --git a/std/sys/ssl/DigestAlgorithm.hx b/std/sys/ssl/DigestAlgorithm.hx new file mode 100644 index 00000000..aed3b049 --- /dev/null +++ b/std/sys/ssl/DigestAlgorithm.hx @@ -0,0 +1,12 @@ +package sys.ssl; + +@:enum +abstract DigestAlgorithm(String) to String { + var MD5 = "MD5"; + var SHA1 = "SHA1"; + var SHA224 = "SHA224"; + var SHA256 = "SHA256"; + var SHA384 = "SHA384"; + var SHA512 = "SHA512"; + var RIPEMD160 = "RIPEMD160"; +} diff --git a/std/sys/ssl/Key.hx b/std/sys/ssl/Key.hx new file mode 100644 index 00000000..1bc013fb --- /dev/null +++ b/std/sys/ssl/Key.hx @@ -0,0 +1,11 @@ +package sys.ssl; + +extern class Key { + + static function loadFile( file : String, ?isPublic : Bool, ?pass : String ) : Key; + + static function readPEM( data : String, isPublic : Bool, ?pass : String ) : Key; + + static function readDER( data : haxe.io.Bytes, isPublic : Bool ) : Key; + +} diff --git a/std/sys/ssl/Socket.hx b/std/sys/ssl/Socket.hx new file mode 100644 index 00000000..d5c8da1f --- /dev/null +++ b/std/sys/ssl/Socket.hx @@ -0,0 +1,50 @@ +package sys.ssl; + +/** + A TLS socket class : allow you to both connect to a given server and exchange messages or start your own server and wait for connections. +**/ +extern class Socket extends sys.net.Socket { + + static var DEFAULT_VERIFY_CERT : Null; + + static var DEFAULT_CA : Null; + + /** + Define if peer certificate is verified during SSL handshake. + **/ + var verifyCert : Null; + + function new() : Void; + + /** + Perform the SSL handshake. + **/ + function handshake() : Void; + + /** + Configure the certificate chain for peer certificate verification. + **/ + function setCA( cert : sys.ssl.Certificate ) : Void; + + /** + Configure the hostname for Server Name Indication TLS extension. + **/ + function setHostname( name : String ) : Void; + + /** + Configure own certificate and private key. + **/ + function setCertificate( cert : Certificate, key : Key ) : Void; + + /** + Configure additionals certificates and private keys for Server Name Indication extension. + The callback may be called during handshake to determine the certificate to use. + **/ + function addSNICertificate( cbServernameMatch : String->Bool, cert : Certificate, key : Key ) : Void; + + /** + Return the certificate received from the other side of a connection. + **/ + function peerCertificate() : sys.ssl.Certificate; + +} diff --git a/tests/README.md b/tests/README.md index 660b68d6..b17024f6 100644 --- a/tests/README.md +++ b/tests/README.md @@ -45,7 +45,7 @@ It is possible to run it in local machines too: 1. Change to this directory. 2. Compile the script: `haxe RunCi.hxml`. - 3. Define the test target by `export TEST=$TARGET` (or `set "TEST=$TARGET"` on Windows), where `$TARGET` should be a comma-seperated list of targets, e.g. `neko,macro`. Possible targets are `macro`, `neko`, `js`, `php`, `cpp`, `flash9`, `as3`, `java`, `cs`, `python`, and `third-party`. However, `flash9`, `as3`, and `third-party` are not likely to work on local machines (TODO). + 3. Define the test target by `export TEST=$TARGET` (or `set "TEST=$TARGET"` on Windows), where `$TARGET` should be a comma-seperated list of targets, e.g. `neko,macro`. Possible targets are `macro`, `neko`, `js`, `lua`, `php`, `cpp`, `flash9`, `as3`, `java`, `cs`, `python`, and `third-party`. However, `flash9`, `as3`, and `third-party` are not likely to work on local machines (TODO). 4. Run it: `neko RunCi.n`. Note that the script will try to look for test dependencies and install them if they are not found. Look at the `getXXXDependencies` functions for the details. @@ -59,7 +59,11 @@ Assuming all test dependencies has been installed, we compile and run the unit t 1. Change to the "unit" directory. 2. Compile: `haxe compile.hxml`. 3. Start a dev server: `nekotools server`. - 4. Open `http://localhost:2000/unit.html` in your browser. + 4. Open [http://localhost:2000/unit.html](http://localhost:2000/unit.html) in your browser. + +### Cpp unit tests + +Cpp unit tests are compiled with `-D HXCPP_NO_DEBUG_LINK` (removes debug symbols) to speed up compilation times. You can remove this from `compile-cpp.hxml` to be able to open the generated `Test-debug.exe` in Visual Studio and debug it. This is useful if it's difficult to figure out why a test is failing, or also _which_ test is failing (for instance with a segmentation fault). ## Sys tests diff --git a/tests/RunCi.hx b/tests/RunCi.hx index cb5311ff..83ff6c9a 100644 --- a/tests/RunCi.hx +++ b/tests/RunCi.hx @@ -19,13 +19,16 @@ private typedef TravisConfig = { var Macro = "macro"; var Neko = "neko"; var Js = "js"; + var Lua = "lua"; var Php = "php"; + var Php7 = "php7"; var Cpp = "cpp"; var Flash9 = "flash9"; var As3 = "as3"; var Java = "java"; var Cs = "cs"; var Python = "python"; + var Hl = "hl"; var ThirdParty = "third-party"; } @@ -34,6 +37,10 @@ enum Ci { AppVeyor; } +enum Failure { + Fail; +} + /** Will be run by CI services, currently TravisCI and AppVeyor. @@ -56,6 +63,11 @@ class RunCi { Sys.println('\x1b[36m' + msg + '\x1b[0m'); } + static function fail():Void { + success = false; + throw Fail; + } + /** Run a command using `Sys.command()`. If the command exits with non-zero code, exit the whole script with the same code. @@ -63,21 +75,22 @@ class RunCi { If `useRetry` is `true`, the command will be re-run if it exits with non-zero code (3 trials). It is useful for running network-dependent commands. */ - static function runCommand(cmd:String, args:Array, useRetry:Bool = false):Void { + static function runCommand(cmd:String, ?args:Array, useRetry:Bool = false, allowFailure:Bool = false):Void { var trials = useRetry ? 3 : 1; var exitCode:Int = 1; + var cmdStr = cmd + (args == null ? '' : ' $args'); while (trials-->0) { - Sys.println('Command: $cmd $args'); + Sys.println('Command: $cmdStr'); var t = Timer.stamp(); exitCode = Sys.command(cmd, args); var dt = Math.round(Timer.stamp() - t); if (exitCode == 0) - successMsg('Command exited with $exitCode in ${dt}s: $cmd $args'); + successMsg('Command exited with $exitCode in ${dt}s: $cmdStr'); else - failMsg('Command exited with $exitCode in ${dt}s: $cmd $args'); + failMsg('Command exited with $exitCode in ${dt}s: $cmdStr'); if (exitCode == 0) { return; @@ -86,7 +99,18 @@ class RunCi { } } - Sys.exit(exitCode); + if (!allowFailure) + fail(); + } + + static function isAptPackageInstalled(aptPackage:String):Bool { + return commandSucceed("dpkg-query", ["-W", "-f='${Status}'", aptPackage]); + } + + static function requireAptPackages(packages:Array):Void { + var notYetInstalled = [for (p in packages) if (!isAptPackageInstalled(p)) p]; + if (notYetInstalled.length > 0) + runCommand("sudo", ["apt-get", "install", "-y"].concat(notYetInstalled), true); } static function haxelibInstallGit(account:String, repository:String, ?branch:String, ?srcPath:String, useRetry:Bool = false, ?altName:String):Void { @@ -154,15 +178,16 @@ class RunCi { switch (systemName) { case "Linux": - Sys.putEnv("DISPLAY", ":99.0"); - runCommand("sh", ["-e", "/etc/init.d/xvfb", "start"]); - Sys.putEnv("AUDIODEV", "null"); - runCommand("sudo", ["apt-get", "install", "-qq", "libgd2-xpm", "ia32-libs", "ia32-libs-multiarch"], true); + requireAptPackages([ + "libcurl3:i386", "libglib2.0-0:i386", "libx11-6:i386", "libxext6:i386", + "libxt6:i386", "libxcursor1:i386", "libnss3:i386", "libgtk2.0-0:i386" + ]); runCommand("wget", ["-nv", "http://fpdownload.macromedia.com/pub/flashplayer/updaters/11/flashplayer_11_sa_debug.i386.tar.gz"], true); runCommand("tar", ["-xf", "flashplayer_11_sa_debug.i386.tar.gz", "-C", Sys.getEnv("HOME")]); File.saveContent(mmcfgPath, "ErrorReportingEnable=1\nTraceOutputFileEnable=1"); runCommand(Sys.getEnv("HOME") + "/flashplayerdebugger", ["-v"]); case "Mac": + runCommand("brew", ["tap", "caskroom/versions"]); runCommand("brew", ["cask", "install", "flash-player-debugger"]); var dir = Path.directory(mmcfgPath); runCommand("sudo", ["mkdir", "-p", dir]); @@ -171,14 +196,19 @@ class RunCi { } } - static function runFlash(swf:String):Void { + /** + Run a Flash swf file. + Return whether the test is successful or not. + It detemines the test result by reading the flashlog.txt, looking for "SUCCESS: true". + */ + static function runFlash(swf:String):Bool { swf = FileSystem.fullPath(swf); Sys.println('going to run $swf'); switch (systemName) { case "Linux": new Process(Sys.getEnv("HOME") + "/flashplayerdebugger", [swf]); case "Mac": - Sys.command("open", ["-a", Sys.getEnv("HOME") + "/Applications/Flash Player Debugger.app", swf]); + Sys.command("open", ["-a", "/Applications/Flash Player Debugger.app", swf]); } //wait a little until flashlog.txt is created @@ -198,7 +228,7 @@ class RunCi { } if (!FileSystem.exists(flashlogPath)) { failMsg('$flashlogPath not found.'); - Sys.exit(1); + return false; } //read flashlog.txt continously @@ -209,11 +239,13 @@ class RunCi { line = traceProcess.stdout.readLine(); Sys.println(line); if (line.indexOf("SUCCESS: ") >= 0) { - Sys.exit(line.indexOf("SUCCESS: true") >= 0 ? 0 : 1); + return line.indexOf("SUCCESS: true") >= 0; } - } catch (e:haxe.io.Eof) {} + } catch (e:haxe.io.Eof) { + break; + } } - Sys.exit(1); + return false; } static function runCs(exe:String, ?args:Array):Void { @@ -224,6 +256,13 @@ class RunCi { runCommand("mono", [exe].concat(args)); case "Windows": runCommand(exe, args); + switch (ci) { + case AppVeyor: + // https://github.com/HaxeFoundation/haxe/issues/4873 + // runCommand("mono", [exe].concat(args)); + case _: + //pass + } } } @@ -298,10 +337,28 @@ class RunCi { static function commandSucceed(cmd:String, args:Array):Bool { return try { - new Process(cmd, args).exitCode() == 0; + var p = new Process(cmd, args); + var succeed = p.exitCode() == 0; + p.close(); + succeed; } catch(e:Dynamic) false; } + static function commandResult(cmd:String, args:Array):{ + stdout:String, + stderr:String, + exitCode:Int + } { + var p = new Process(cmd, args); + var out = { + stdout: p.stdout.readAll().toString(), + stderr: p.stderr.readAll().toString(), + exitCode: p.exitCode() + } + p.close(); + return out; + } + static function addToPATH(path:String):Void { switch (systemName) { case "Windows": @@ -314,11 +371,16 @@ class RunCi { static function getPhpDependencies() { switch (systemName) { case "Linux": - if (commandSucceed("php", ["-v"])) { + var phpCmd = commandResult("php", ["-v"]); + var phpVerReg = ~/PHP ([0-9]+\.[0-9]+)/i; + var phpVer = if (phpVerReg.match(phpCmd.stdout)) + Std.parseFloat(phpVerReg.matched(1)); + else + null; + if (phpCmd.exitCode == 0 && phpVer != null && phpVer >= 5.5) { infoMsg('php has already been installed.'); } else { - runCommand("sudo", ["apt-get", "install", "php5", "-qq"], true); - runCommand("sudo", ["apt-get", "install", "php5-mysql", "php5-sqlite", "-qq"], true); + requireAptPackages(["php5-cli", "php5-mysql", "php5-sqlite"]); } case "Mac": //pass @@ -340,7 +402,7 @@ class RunCi { //hxcpp dependencies switch (systemName) { case "Linux": - runCommand("sudo", ["apt-get", "install", "gcc-multilib", "g++-multilib", "-qq"], true); + requireAptPackages(["gcc-multilib", "g++-multilib"]); case "Mac": //pass } @@ -355,19 +417,27 @@ class RunCi { var oldDir = Sys.getCwd(); changeDirectory(getHaxelibPath("hxcpp") + "tools/hxcpp/"); runCommand("haxe", ["compile.hxml"]); - changeDirectory(getHaxelibPath("hxcpp") + "project/"); - switch (ci) { - case AppVeyor: - runCommand("neko", ["build.n", "windows-m32"]); - case _: - runCommand("neko", ["build.n"]); - } changeDirectory(oldDir); } gotCppDependencies = true; } + static var gotSpodDependencies = false; + static function getSpodDependencies() { + if (gotSpodDependencies ) return; + + //install and build hxcpp + try { + getHaxelibPath("record-macros"); + infoMsg('record-macros has already been installed.'); + } catch(e:Dynamic) { + haxelibInstallGit("HaxeFoundation", "record-macros", true); + } + + gotSpodDependencies = true; + } + static function getJavaDependencies() { haxelibInstallGit("HaxeFoundation", "hxjava", true); @@ -380,7 +450,7 @@ class RunCi { if (commandSucceed("node", ["-v"])) { infoMsg('node has already been installed.'); } else { - runCommand("sudo", ["apt-get", "install", "nodejs", "-qq"], true); + requireAptPackages(["nodejs"]); } case "Mac": //pass @@ -389,13 +459,34 @@ class RunCi { runCommand("node", ["-v"]); } + static function getLuaDependencies(){ + switch (systemName){ + case "Linux": requireAptPackages(["libpcre3-dev"]); + case "Mac": { + runCommand("brew", ["install", "pcre"], false, true); + runCommand("brew", ["install", "python"], false, true); + } + } + runCommand("pip", ["install", "hererocks"]); + } + + static function installLuaVersionDependencies(lv:String){ + if (lv == "-l5.1"){ + runCommand("luarocks", ["install", "luabitop", "1.0.2-3", "--server=https://luarocks.org/dev"]); + } + runCommand("luarocks", ["install", "lrexlib-pcre", "2.8.0-1", "--server=https://luarocks.org/dev"]); + runCommand("luarocks", ["install", "luv", "1.9.1-0", "--server=https://luarocks.org/dev"]); + runCommand("luarocks", ["install", "luasocket", "3.0rc1-2", "--server=https://luarocks.org/dev"]); + runCommand("luarocks", ["install", "environ", "0.1.0-1", "--server=https://luarocks.org/dev"]); + } + static function getCsDependencies() { switch (systemName) { case "Linux": if (commandSucceed("mono", ["--version"])) infoMsg('mono has already been installed.'); else - runCommand("sudo", ["apt-get", "install", "mono-devel", "mono-mcs", "-qq"], true); + requireAptPackages(["mono-devel", "mono-mcs"]); runCommand("mono", ["--version"]); case "Mac": if (commandSucceed("mono", ["--version"])) @@ -404,7 +495,13 @@ class RunCi { runCommand("brew", ["install", "mono"], true); runCommand("mono", ["--version"]); case "Windows": - //pass + switch (ci) { + case AppVeyor: + addToPATH("C:\\Program Files (x86)\\Mono\\bin"); + runCommand("mono", ["--version"]); + case _: + //pass + } } haxelibInstallGit("HaxeFoundation", "hxcs", true); @@ -446,7 +543,7 @@ class RunCi { if (commandSucceed("python3", ["-V"])) infoMsg('python3 has already been installed.'); else - runCommand("sudo", ["apt-get", "install", "python3", "-qq"], true); + requireAptPackages(["python3"]); runCommand("python3", ["-V"]); var pypy = "pypy3"; @@ -475,6 +572,13 @@ class RunCi { runCommand("pypy3", ["-V"]); return ["python3", "pypy3"]; + case "Windows": + if (commandSucceed("python3", ["-V"])) + infoMsg('python3 has already been installed.'); + else + throw "please install python 3.x and make it available as python3 in PATH"; + runCommand("python3", ["-V"]); + return ["python3"]; } return []; @@ -494,6 +598,168 @@ class RunCi { static var sysDir(default, never) = cwd + "sys/"; static var optDir(default, never) = cwd + "optimization/"; static var miscDir(default, never) = cwd + "misc/"; + static var displayDir(default, never) = cwd + "display/"; + static var gitInfo(get, null):{repo:String, branch:String, commit:String, timestamp:Float, date:String}; + static var success(default, null) = true; + static function get_gitInfo() return if (gitInfo != null) gitInfo else gitInfo = { + repo: switch (ci) { + case TravisCI: + Sys.getEnv("TRAVIS_REPO_SLUG"); + case AppVeyor: + Sys.getEnv("APPVEYOR_PROJECT_SLUG"); + case _: + commandResult("git", ["config", "--get", "remote.origin.url"]).stdout.trim(); + }, + branch: switch (ci) { + case TravisCI: + Sys.getEnv("TRAVIS_BRANCH"); + case AppVeyor: + Sys.getEnv("APPVEYOR_REPO_BRANCH"); + case _: + commandResult("git", ["rev-parse", "--abbrev-ref", "HEAD"]).stdout.trim(); + }, + commit: commandResult("git", ["rev-parse", "HEAD"]).stdout.trim(), + timestamp: Std.parseFloat(commandResult("git", ["show", "-s", "--format=%ct", "HEAD"]).stdout), + date: { + var gitTime = commandResult("git", ["show", "-s", "--format=%ct", "HEAD"]).stdout; + var tzd = { + var z = Date.fromTime(0); + z.getHours() * 60 * 60 * 1000 + z.getMinutes() * 60 * 1000; + } + // make time in the UTC time zone + var time = Date.fromTime(Std.parseFloat(gitTime) * 1000 - tzd); + DateTools.format(time, "%FT%TZ"); + } + } + static var haxeVer(default, never) = { + var haxe_ver = haxe.macro.Compiler.getDefine("haxe_ver"); + switch (haxe_ver.split(".")) { + case [major]: + major; + case [major, minor] if (minor.length == 1): + '${major}.${minor}'; + case [major, minor] if (minor.length > 1): + var minor = minor.charAt(0); + var patch = Std.parseInt(minor.substr(1)); + '${major}.${minor}.${patch}'; + case _: + throw haxe_ver; + } + } + static var haxeVerFull(default, never) = { + var ver = haxeVer.split("."); + while (ver.length < 3) { + ver.push("0"); + } + ver.join("."); + } + + static function deploy():Void { + if ( + Sys.getEnv("DEPLOY") != null + ) { + changeDirectory(repoDir); + + // generate doc + runCommand("make", ["-s", "install_dox"]); + runCommand("make", ["-s", "package_doc"]); + + // deployBintray(); + deployApiDoc(); + deployPPA(); + } + } + + static function deployBintray():Void { + if ( + Sys.getEnv("BINTRAY") != null && + Sys.getEnv("BINTRAY_USERNAME") != null && + Sys.getEnv("BINTRAY_API_KEY") != null + ) { + // generate bintray config + var tpl = new Template(File.getContent("extra/bintray.tpl.json")); + var compatDate = ~/[^0-9]/g.replace(gitInfo.date, ""); + var json = tpl.execute({ + packageSubject: { + var sub = Sys.getEnv("BINTRAY_SUBJECT"); + sub != null ? sub : Sys.getEnv("BINTRAY_USERNAME"); + }, + os: systemName.toLowerCase(), + versionName: '${haxeVer}+${compatDate}.${gitInfo.commit.substr(0,7)}', + versionDesc: "Automated CI build.", + gitRepo: gitInfo.repo, + gitBranch: gitInfo.branch, + gitCommit: gitInfo.commit, + gitDate: gitInfo.date, + }); + var path = "extra/bintray.json"; + File.saveContent("extra/bintray.json", json); + infoMsg("saved " + FileSystem.absolutePath(path) + " with content:"); + Sys.println(json); + } + } + + /** + Deploy doc to api.haxe.org. + */ + static function deployApiDoc():Void { + if ( + gitInfo.branch == "development" && + Sys.getEnv("DEPLOY") != null && + Sys.getEnv("deploy_key_decrypt") != null + ) { + // setup deploy_key + runCommand("openssl aes-256-cbc -k \"$deploy_key_decrypt\" -in extra/deploy_key.enc -out extra/deploy_key -d"); + runCommand("chmod 600 extra/deploy_key"); + runCommand("ssh-add extra/deploy_key"); + + runCommand("make", ["-s", "deploy_doc"]); + } + } + + /** + Deploy source package to ppa:haxe/snapshots. + */ + static function deployPPA():Void { + if ( + gitInfo.branch == "development" && + Sys.getEnv("DEPLOY") != null && + Sys.getEnv("haxeci_decrypt") != null + ) { + // setup deb info + runCommand("git config --global user.name \"${DEBFULLNAME}\""); + runCommand("git config --global user.email \"${DEBEMAIL}\""); + // setup haxeci_ssh + runCommand("openssl aes-256-cbc -k \"$haxeci_decrypt\" -in extra/haxeci_ssh.enc -out extra/haxeci_ssh -d"); + runCommand("chmod 600 extra/haxeci_ssh"); + runCommand("ssh-add extra/haxeci_ssh"); + // setup haxeci_sec.gpg + runCommand("openssl aes-256-cbc -k \"$haxeci_decrypt\" -in extra/haxeci_sec.gpg.enc -out extra/haxeci_sec.gpg -d"); + runCommand("gpg --allow-secret-key-import --import extra/haxeci_sec.gpg"); + runCommand("sudo apt-get install devscripts git-buildpackage ubuntu-dev-tools dh-make -y"); + var compatDate = ~/[^0-9]/g.replace(gitInfo.date, ""); + var SNAPSHOT_VERSION = '${haxeVerFull}+1SNAPSHOT${compatDate}+${gitInfo.commit.substr(0,7)}'; + runCommand('cp out/haxe*_src.tar.gz "../haxe_${SNAPSHOT_VERSION}.orig.tar.gz"'); + changeDirectory(".."); + runCommand("git clone https://github.com/HaxeFoundation/haxe-debian.git"); + changeDirectory("haxe-debian"); + runCommand("git checkout upstream"); + runCommand("git checkout next"); + runCommand('gbp import-orig "../haxe_${SNAPSHOT_VERSION}.orig.tar.gz" -u "${SNAPSHOT_VERSION}" --debian-branch=next'); + runCommand('dch -v "1:${SNAPSHOT_VERSION}-1" --urgency low "snapshot build"'); + runCommand("debuild -S -sa"); + runCommand("backportpackage -d yakkety --upload ${PPA} --yes ../haxe_*.dsc"); + runCommand("backportpackage -d xenial --upload ${PPA} --yes ../haxe_*.dsc"); + runCommand("backportpackage -d wily --upload ${PPA} --yes ../haxe_*.dsc"); + runCommand("backportpackage -d vivid --upload ${PPA} --yes ../haxe_*.dsc"); + runCommand("backportpackage -d trusty --upload ${PPA} --yes ../haxe_*.dsc"); + runCommand("git checkout debian/changelog"); + runCommand("git merge -X ours --no-edit origin/next-precise"); + runCommand('dch -v "1:${SNAPSHOT_VERSION}-1" --urgency low "snapshot build"'); + runCommand("debuild -S -sa"); + runCommand("backportpackage -d precise --upload ${PPA} --yes ../haxe_*.dsc"); + } + } static function main():Void { Sys.putEnv("OCAMLRUNPARAM", "b"); @@ -507,264 +773,339 @@ class RunCi { Sys.println('Going to test: $tests'); for (test in tests) { - infoMsg('Now test $test'); - changeDirectory(unitDir); - switch (test) { - case Macro: - runCommand("haxe", ["compile-macro.hxml"]); - - changeDirectory(miscDir); - getCsDependencies(); - runCommand("haxe", ["compile.hxml"]); - - switch (ci) { - case AppVeyor: - //save time... - case _: - //generate documentation - haxelibInstallGit("Simn", "hxparse", "development", "src", true); - haxelibInstallGit("Simn", "hxtemplo", true); - haxelibInstallGit("Simn", "hxargs", true); - haxelibInstallGit("dpeek", "haxe-markdown", "master", "src", true, "markdown"); - - haxelibInstallGit("HaxeFoundation", "hxcpp", true); - haxelibInstallGit("HaxeFoundation", "hxjava", true); - haxelibInstallGit("HaxeFoundation", "hxcs", true); - - haxelibInstallGit("dpeek", "dox", true); - changeDirectory(getHaxelibPath("dox")); - runCommand("haxe", ["run.hxml"]); - runCommand("haxe", ["gen.hxml"]); - haxelibRun(["dox", "-o", "bin/api.zip", "-i", "bin/xml"]); - } - - changeDirectory(sysDir); - runCommand("haxe", ["compile-macro.hxml"]); - runCommand("haxe", ["compile-each.hxml", "--run", "Main"]); - - //BYTECODE - switch (ci) { - case null: - //pass - case TravisCI: - changeDirectory(repoDir); - runCommand("make", ["BYTECODE=1", "-s"]); - runCommand("sudo", ["make", "install", "-s"]); - changeDirectory(unitDir); - runCommand("haxe", ["compile-macro.hxml"]); - case AppVeyor: - // save time... - // changeDirectory(repoDir); - // runCommand(Sys.getEnv("CYG_ROOT") + "/bin/bash", ["-lc", 'cd \"$$OLDPWD\" && make -s -f Makefile.win BYTECODE=1']); - // changeDirectory(unitDir); - // runCommand("haxe", ["compile-macro.hxml"]); - } - case Neko: - runCommand("haxe", ["compile-neko.hxml"]); - runCommand("neko", ["bin/unit.n"]); - - changeDirectory(sysDir); - runCommand("haxe", ["compile-neko.hxml"]); - runCommand("neko", ["bin/neko/sys.n"]); - case Php: - getPhpDependencies(); - var args = switch (ci) { - case TravisCI: - ["-D","travis"]; - case _: - []; - } - runCommand("haxe", ["compile-php.hxml"].concat(args)); - runCommand("php", ["bin/php/index.php"]); - - changeDirectory(sysDir); - runCommand("haxe", ["compile-php.hxml"]); - runCommand("php", ["bin/php/Main/index.php"]); - case Python: - var pys = getPythonDependencies(); - - runCommand("haxe", ["compile-python.hxml"]); - for (py in pys) { - runCommand(py, ["bin/unit.py"]); - } + switch (ci) { + case TravisCI: + Sys.println('travis_fold:start:test-${test}'); + case _: + //pass + } - changeDirectory(sysDir); - runCommand("haxe", ["compile-python.hxml"]); - for (py in pys) { - runCommand(py, ["bin/python/sys.py"]); - } + infoMsg('test $test'); + var success = true; + try { + changeDirectory(unitDir); - changeDirectory(miscDir + "pythonImport"); - runCommand("haxe", ["compile.hxml"]); - for (py in pys) { - runCommand(py, ["test.py"]); - } - case Cpp: - getCppDependencies(); - runCommand("haxe", ["compile-cpp.hxml", "-D", "HXCPP_M32"]); - runCpp("bin/cpp/Test-debug", []); - - switch (ci) { - case AppVeyor: - //save time... - case _: - runCommand("rm", ["-rf", "cpp"]); - runCommand("haxe", ["compile-cpp.hxml", "-D", "HXCPP_M64"]); - runCpp("bin/cpp/Test-debug", []); - } - changeDirectory(sysDir); - runCommand("haxe", ["compile-cpp.hxml"]); - runCpp("bin/cpp/Main-debug", []); - case Js: - getJSDependencies(); + var args = switch (ci) { + case TravisCI: + ["-D","travis"]; + case AppVeyor: + ["-D","appveyor"]; + case _: + []; + } + switch (test) { + case Macro: + runCommand("haxe", ["compile-macro.hxml"].concat(args)); + + changeDirectory(displayDir); + runCommand("haxe", ["build.hxml"]); + + changeDirectory(miscDir); + getCsDependencies(); + getPythonDependencies(); + runCommand("haxe", ["compile.hxml"]); + + changeDirectory(sysDir); + runCommand("haxe", ["compile-macro.hxml"]); + runCommand("haxe", ["compile-each.hxml", "--run", "Main"]); + case Neko: + getSpodDependencies(); + runCommand("haxe", ["compile-neko.hxml", "-D", "dump", "-D", "dump_ignore_var_ids"].concat(args)); + runCommand("neko", ["bin/unit.n"]); + + changeDirectory(sysDir); + runCommand("haxe", ["compile-neko.hxml"]); + runCommand("neko", ["bin/neko/sys.n"]); + case Php7: + getSpodDependencies(); + runCommand("haxe", ["compile-php7.hxml"].concat(args)); + runCommand("php", ["bin/php7/index.php"]); + + changeDirectory(sysDir); + runCommand("haxe", ["compile-php7.hxml"]); + runCommand("php", ["bin/php7/Main/index.php"]); + case Php: + getSpodDependencies(); + getPhpDependencies(); + runCommand("haxe", ["compile-php.hxml"].concat(args)); + runCommand("php", ["bin/php/index.php"]); + + changeDirectory(sysDir); + runCommand("haxe", ["compile-php.hxml"]); + runCommand("php", ["bin/php/Main/index.php"]); + case Python: + var pys = getPythonDependencies(); + + runCommand("haxe", ["compile-python.hxml"].concat(args)); + for (py in pys) { + runCommand(py, ["bin/unit.py"]); + } - for (flatten in [true, false]) { - runCommand("haxe", ["compile-js.hxml"].concat(flatten ? [] : ["-D", "js-unflatten"])); - runCommand("node", ["-e", "var unit = require('./bin/unit.js').unit; unit.Test.main(); process.exit(unit.Test.success ? 0 : 1);"]); - } + changeDirectory(sysDir); + runCommand("haxe", ["compile-python.hxml"]); + for (py in pys) { + runCommand(py, ["bin/python/sys.py"]); + } - if (Sys.getEnv("TRAVIS_SECURE_ENV_VARS") == "true" && systemName == "Linux") { - var scVersion = "sc-4.3-linux"; - runCommand("wget", ['https://saucelabs.com/downloads/${scVersion}.tar.gz'], true); - runCommand("tar", ["-xf", '${scVersion}.tar.gz']); - - //start sauce-connect - var scReadyFile = "sauce-connect-ready-" + Std.random(100); - var sc = new Process('${scVersion}/bin/sc', [ - "-i", Sys.getEnv("TRAVIS_JOB_NUMBER"), - "-f", scReadyFile - ]); - while(!FileSystem.exists(scReadyFile)) { - Sys.sleep(0.5); + changeDirectory(miscDir + "pythonImport"); + runCommand("haxe", ["compile.hxml"]); + for (py in pys) { + runCommand(py, ["test.py"]); + } + case Lua: + getLuaDependencies(); + var envpath = Sys.getEnv("HOME") + '/lua_env'; + addToPATH(envpath + '/bin'); + for (lv in ["-l5.1", "-l5.2", "-l5.3", "-j2.0", "-j2.1" ]){ + if (systemName == "Mac" && lv.startsWith("-j")) continue; + Sys.println('--------------------'); + Sys.println('Lua Version: $lv'); + runCommand("hererocks", [envpath, lv, "-rlatest", "-i"]); + trace('path: ' + Sys.getEnv("PATH")); + runCommand("lua",["-v"]); + runCommand("luarocks",[]); + installLuaVersionDependencies(lv); + + changeDirectory(unitDir); + runCommand("haxe", ["compile-lua.hxml"].concat(args)); + runCommand("lua", ["bin/unit.lua"]); + + changeDirectory(sysDir); + runCommand("haxe", ["compile-lua.hxml"].concat(args)); + runCommand("lua", ["bin/lua/sys.lua"]); + } + case Cpp: + getCppDependencies(); + getSpodDependencies(); + runCommand("haxe", ["compile-cpp.hxml", "-D", "HXCPP_M32"].concat(args)); + runCpp("bin/cpp/TestMain-debug", []); + + switch (ci) { + case AppVeyor: + //save time... + case _: + runCommand("rm", ["-rf", "cpp"]); + runCommand("haxe", ["compile-cpp.hxml", "-D", "HXCPP_M64"].concat(args)); + runCpp("bin/cpp/TestMain-debug", []); + + runCommand("haxe", ["compile-cppia-host.hxml"]); + runCommand("haxe", ["compile-cppia.hxml"]); + runCpp("bin/cppia/Host-debug", ["bin/unit.cppia"]); } - runCommand("npm", ["install", "wd", "q"], true); - haxelibInstallGit("dionjwa", "nodejs-std", "master", null, true, "nodejs"); - runCommand("haxe", ["compile-saucelabs-runner.hxml"]); - var server = new Process("nekotools", ["server"]); - runCommand("node", ["bin/RunSauceLabs.js", "unit-js.html"]); + changeDirectory(sysDir); + runCommand("haxe", ["compile-cpp.hxml"]); + runCpp("bin/cpp/Main-debug", []); + + // if (Sys.systemName() == "Mac") + // { + // changeDirectory(miscDir + "cppObjc"); + // runCommand("haxe", ["build.hxml"]); + // runCpp("bin/TestObjc-debug"); + // } + case Js: + getJSDependencies(); + + var jsOutputs = [ + for (es3 in [[], ["-D", "js-es=3"]]) + for (unflatten in [[], ["-D", "js-unflatten"]]) + for (classic in [[], ["-D", "js-classic"]]) + { + var extras = args.concat(es3).concat(unflatten).concat(classic); - server.close(); - sc.close(); - } + runCommand("haxe", ["compile-js.hxml"].concat(extras)); - infoMsg("Test optimization:"); - changeDirectory(optDir); - runCommand("haxe", ["run.hxml"]); - case Java: - getJavaDependencies(); - runCommand("haxe", ["compile-java.hxml"]); - runCommand("java", ["-jar", "bin/java/Test-Debug.jar"]); - - runCommand("haxe", ["compile-java.hxml","-dce","no"]); - runCommand("java", ["-jar", "bin/java/Test-Debug.jar"]); - - changeDirectory(sysDir); - runCommand("haxe", ["compile-java.hxml"]); - runCommand("java", ["-jar", "bin/java/Main-Debug.jar"]); - - infoMsg("Testing java-lib extras"); - changeDirectory('$unitDir/bin'); - runCommand("git", ["clone", "https://github.com/waneck/java-lib-tests.git", "--depth", "1"], true); - for (dir in FileSystem.readDirectory('java-lib-tests')) - { - var path = 'java-lib-tests/$dir'; - if (FileSystem.isDirectory(path)) for (file in FileSystem.readDirectory(path)) + var output = if (extras.length > 0) { + "bin/js/" + extras.join("") + "/unit.js"; + } else { + "bin/js/default/unit.js"; + } + var outputDir = Path.directory(output); + if (!FileSystem.exists(outputDir)) { + FileSystem.createDirectory(outputDir); + } + FileSystem.rename("bin/unit.js", output); + FileSystem.rename("bin/unit.js.map", output + ".map"); + runCommand("node", ["-e", "require('./" + output + "').unit.TestMain.nodejsMain();"]); + output; + } + ]; + + var env = Sys.environment(); + if ( + env.exists("SAUCE") && + env.exists("SAUCE_USERNAME") && + env.exists("SAUCE_ACCESS_KEY") + ) { + // sauce-connect should have been started + + // var scVersion = "sc-4.3-linux"; + // runCommand("wget", ['https://saucelabs.com/downloads/${scVersion}.tar.gz'], true); + // runCommand("tar", ["-xf", '${scVersion}.tar.gz']); + + // //start sauce-connect + // var scReadyFile = "sauce-connect-ready-" + Std.random(100); + // var sc = new Process('${scVersion}/bin/sc', [ + // "-i", Sys.getEnv("TRAVIS_JOB_NUMBER"), + // "-f", scReadyFile + // ]); + // while(!FileSystem.exists(scReadyFile)) { + // Sys.sleep(0.5); + // } + + runCommand("npm", ["install", "wd", "q"], true); + haxelibInstall("hxnodejs"); + runCommand("haxe", ["compile-saucelabs-runner.hxml"]); + var server = new Process("nekotools", ["server"]); + runCommand("node", ["bin/RunSauceLabs.js"].concat([for (js in jsOutputs) "unit-js.html?js=" + js.urlEncode()])); + + server.close(); + // sc.close(); + } + + infoMsg("Test optimization:"); + changeDirectory(optDir); + runCommand("haxe", ["run.hxml"]); + case Java: + getSpodDependencies(); + getJavaDependencies(); + runCommand("haxe", ["compile-java.hxml"].concat(args)); + runCommand("java", ["-jar", "bin/java/TestMain-Debug.jar"]); + + runCommand("haxe", ["compile-java.hxml","-dce","no"].concat(args)); + runCommand("java", ["-jar", "bin/java/TestMain-Debug.jar"]); + + changeDirectory(sysDir); + runCommand("haxe", ["compile-java.hxml"]); + runCommand("java", ["-jar", "bin/java/Main-Debug.jar"]); + + infoMsg("Testing java-lib extras"); + changeDirectory('$unitDir/bin'); + runCommand("git", ["clone", "https://github.com/waneck/java-lib-tests.git", "--depth", "1"], true); + for (dir in FileSystem.readDirectory('java-lib-tests')) { - if (file.endsWith('.hxml')) + var path = 'java-lib-tests/$dir'; + if (FileSystem.isDirectory(path)) for (file in FileSystem.readDirectory(path)) { - runCommand("haxe", ["--cwd",'java-lib-tests/$dir',file]); + if (file.endsWith('.hxml')) + { + runCommand("haxe", ["--cwd",'java-lib-tests/$dir',file]); + } } } - } - case Cs: - getCsDependencies(); + case Cs: + getSpodDependencies(); + getCsDependencies(); - var compl = switch [ci, systemName] { - case [TravisCI, "Linux"]: - "-travis"; - case _: - ""; - }; + var compl = switch [ci, systemName] { + case [TravisCI, "Linux"]: + "-travis"; + case _: + ""; + }; - runCommand("haxe", ['compile-cs$compl.hxml']); - runCs("bin/cs/bin/Test-Debug.exe"); - - runCommand("haxe", ['compile-cs$compl.hxml','-dce','no']); - runCs("bin/cs/bin/Test-Debug.exe"); - - runCommand("haxe", ['compile-cs-unsafe$compl.hxml']); - runCs("bin/cs_unsafe/bin/Test-Debug.exe"); + for (fastcast in [[], ["-D", "fast_cast"]]) + for (noroot in [[], ["-D", "no_root"]]) + for (erasegenerics in [[], ["-D", "erase_generics"]]) + { + var extras = fastcast.concat(erasegenerics).concat(noroot); + runCommand("haxe", ['compile-cs$compl.hxml'].concat(extras)); + runCs("bin/cs/bin/TestMain-Debug.exe"); - runCommand("haxe", ['compile-cs$compl.hxml',"-D","erase_generics"]); - runCs("bin/cs/bin/Test-Debug.exe"); + runCommand("haxe", ['compile-cs-unsafe$compl.hxml'].concat(extras)); + runCs("bin/cs_unsafe/bin/TestMain-Debug.exe"); + } - runCommand("haxe", ['compile-cs-unsafe$compl.hxml',"-D","erase_generics"]); - runCs("bin/cs_unsafe/bin/Test-Debug.exe"); + runCommand("haxe", ['compile-cs$compl.hxml','-dce','no']); + runCs("bin/cs/bin/TestMain-Debug.exe"); - runCommand("haxe", ['compile-cs$compl.hxml',"-D","no_root"]); - runCs("bin/cs/bin/Test-Debug.exe"); + changeDirectory(sysDir); + runCommand("haxe", ["compile-cs.hxml",'-D','fast_cast']); + runCs("bin/cs/bin/Main-Debug.exe", []); - runCommand("haxe", ['compile-cs-unsafe$compl.hxml',"-D","no_root","-D","erase_generics"]); - runCs("bin/cs_unsafe/bin/Test-Debug.exe"); + changeDirectory(miscDir + "csTwoLibs"); + for (i in 1...5) + { + runCommand("haxe", ['compile-$i.hxml','-D','fast_cast']); + runCs("bin/main/bin/Main.exe"); + } - changeDirectory(sysDir); - runCommand("haxe", ["compile-cs.hxml"]); - runCs("bin/cs/bin/Main-Debug.exe", []); + case Flash9: + setupFlashPlayerDebugger(); + runCommand("haxe", ["compile-flash9.hxml", "-D", "fdb", "-D", "dump", "-D", "dump_ignore_var_ids"].concat(args)); + var success = runFlash("bin/unit9.swf"); + if (!success) + fail(); + case As3: + setupFlashPlayerDebugger(); + + //setup flex sdk + if (commandSucceed("mxmlc", ["--version"])) { + infoMsg('mxmlc has already been installed.'); + } else { + var apacheMirror = Json.parse(Http.requestUrl("http://www.apache.org/dyn/closer.lua?as_json=1")).preferred; + var flexVersion = "4.15.0"; + runCommand("wget", ['${apacheMirror}/flex/${flexVersion}/binaries/apache-flex-sdk-${flexVersion}-bin.tar.gz'], true); + runCommand("tar", ["-xf", 'apache-flex-sdk-${flexVersion}-bin.tar.gz', "-C", Sys.getEnv("HOME")]); + var flexsdkPath = Sys.getEnv("HOME") + '/apache-flex-sdk-${flexVersion}-bin'; + addToPATH(flexsdkPath + "/bin"); + var playerglobalswcFolder = flexsdkPath + "/player"; + FileSystem.createDirectory(playerglobalswcFolder + "/11.1"); + runCommand("wget", ["-nv", "http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_1.swc", "-O", playerglobalswcFolder + "/11.1/playerglobal.swc"], true); + File.saveContent(flexsdkPath + "/env.properties", 'env.PLAYERGLOBAL_HOME=$playerglobalswcFolder'); + runCommand("mxmlc", ["--version"]); + } - changeDirectory(miscDir + "csTwoLibs"); - for (i in 1...5) - { - runCommand("haxe", ['compile-$i.hxml']); - runCs("bin/main/bin/Main.exe"); - } + runCommand("haxe", ["compile-as3.hxml", "-D", "fdb"].concat(args)); + var success = runFlash("bin/unit9_as3.swf"); + if (!success) + fail(); + case Hl: + runCommand("haxe", ["compile-hl.hxml"]); + case ThirdParty: + getPhpDependencies(); + getJavaDependencies(); + getJSDependencies(); + getCsDependencies(); + getPythonDependencies(); + getCppDependencies(); + //getOpenFLDependencies(); + + //testPolygonalDs(); + // if (systemName == "Linux") testFlambe(); //#3439 + testHxTemplo(); + testMUnit(); + testHaxeQuake(); + //testOpenflSamples(); + //testFlixelDemos(); + case t: + throw "unknown target: " + t; + } + } catch(f:Failure) { + success = false; + } - case Flash9: - setupFlashPlayerDebugger(); - runCommand("haxe", ["compile-flash9.hxml", "-D", "fdb"]); - runFlash("bin/unit9.swf"); - case As3: - setupFlashPlayerDebugger(); - - //setup flex sdk - if (commandSucceed("mxmlc", ["--version"])) { - infoMsg('mxmlc has already been installed.'); - } else { - var flexVersion = "4.14.0"; - runCommand("wget", ['http://archive.apache.org/dist/flex/${flexVersion}/binaries/apache-flex-sdk-${flexVersion}-bin.tar.gz'], true); - runCommand("tar", ["-xf", 'apache-flex-sdk-${flexVersion}-bin.tar.gz', "-C", Sys.getEnv("HOME")]); - var flexsdkPath = Sys.getEnv("HOME") + '/apache-flex-sdk-${flexVersion}-bin'; - addToPATH(flexsdkPath + "/bin"); - var playerglobalswcFolder = flexsdkPath + "/player"; - FileSystem.createDirectory(playerglobalswcFolder + "/11.1"); - runCommand("wget", ["-nv", "http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_1.swc", "-O", playerglobalswcFolder + "/11.1/playerglobal.swc"], true); - File.saveContent(flexsdkPath + "/env.properties", 'env.PLAYERGLOBAL_HOME=$playerglobalswcFolder'); - runCommand("mxmlc", ["--version"]); - } + switch (ci) { + case TravisCI: + Sys.println('travis_fold:end:test-${test}'); + case _: + //pass + } - runCommand("haxe", ["compile-as3.hxml", "-D", "fdb"]); - runFlash("bin/unit9_as3.swf"); - case ThirdParty: - getPhpDependencies(); - getJavaDependencies(); - getJSDependencies(); - getCsDependencies(); - getPythonDependencies(); - getCppDependencies(); - //getOpenFLDependencies(); - - //testPolygonalDs(); - // if (systemName == "Linux") testFlambe(); //#3439 - testHxTemplo(); - testMUnit(); - //testOpenflSamples(); - //testFlixelDemos(); - case t: - throw "unknown target: " + t; + if (success) { + successMsg('test ${test} succeeded'); + } else { + failMsg('test ${test} failed'); } } + + if (success) { + deploy(); + } else { + Sys.exit(1); + } } static function testHxTemplo() { @@ -772,7 +1113,7 @@ class RunCi { changeDirectory(unitDir); - haxelibInstallGit("Simn", "hxparse", "development", "src"); + haxelibInstallGit("Simn", "hxparse", "master", "src"); haxelibInstallGit("Simn", "hxtemplo"); var buildArgs = [ @@ -808,7 +1149,7 @@ class RunCi { haxelibInstallGit("massiveinteractive", "mconsole", "master", "src"); haxelibInstallGit("massiveinteractive", "MassiveCover", "master", "src", false, "mcover"); haxelibInstallGit("massiveinteractive", "MassiveLib", "master", "src", false, "mlib"); - haxelibInstallGit("massiveinteractive", "MassiveUnit", "master", "src", false, "munit"); + haxelibInstallGit("massiveinteractive", "MassiveUnit", "2.1.2", "src", false, "munit"); changeDirectory(Path.join([getHaxelibPath("munit"), "..", "tool"])); runCommand("haxe", ["build.hxml"]); haxelibRun(["munit", "test", "-result-exit-code", "-neko"], true); @@ -816,6 +1157,15 @@ class RunCi { haxelibRun(["munit", "test", "-result-exit-code", "-neko"], true); } + static function testHaxeQuake() { + infoMsg("Test HaxeQuake:"); + + changeDirectory(unitDir); + runCommand("git", ["clone", "https://github.com/nadako/HaxeQuake"]); + changeDirectory("HaxeQuake/Client"); + runCommand("haxe", ["build.hxml"]); + } + static function testFlambe() { infoMsg("Test Flambe:"); diff --git a/tests/TestMakefile.hx b/tests/TestMakefile.hx new file mode 100644 index 00000000..bb0f4446 --- /dev/null +++ b/tests/TestMakefile.hx @@ -0,0 +1,76 @@ +class TestMakefile { + static public function main() { + Sys.setCwd("../"); + var mlFiles = []; + FileSystemTools.mapFiles("./src", function(s) { + mlFiles.push(s); + }, ~/\.ml$/); + + var failure = false; + var times = []; + + function makeWithTimer(name) { + var start = haxe.Timer.stamp(); + var code = make(); + var time = haxe.Timer.stamp() - start; + times.push({name: name, time: time}); + return code; + } + + Sys.command("make", ["clean_haxe"]); + makeWithTimer("initial"); + + for (mlFile in mlFiles) { + Sys.command("touch", [mlFile]); + Sys.println('[START] $mlFile'); + var code = makeWithTimer(mlFile); + if (code == 0) { + Sys.println('[DONE] $mlFile'); + } else { + Sys.println('[ERROR] $mlFile'); + failure = true; + break; + } + } + + times.sort(function(t1, t2) return t1.time < t2.time ? -1 : 1); + var total = 0.; + for (time in times) { + Sys.println('${time.name}: ${ghettoFormatTime(time.time)}'); + total += time.time; + } + Sys.println('Total: ${ghettoFormatTime(total)}'); + Sys.exit(failure ? 1 : 0); + } + + static function make() { + return Sys.command("make", ["LFLAGS=-c", "haxe"]); + } + + static function ghettoFormatTime(f:Float) { + var s = Std.string(f); + return s.substr(0, s.indexOf(".") + 3); + } +} + +class FileSystemTools { + static public function mapFiles(directory:String, f:String -> Void, ?match:EReg) { + var workList = [directory]; + while (workList.length > 0) { + var current = workList.shift(); + if (sys.FileSystem.isDirectory(current)) { + var files = sys.FileSystem.readDirectory(current); + for (file in files) { + switch (file) { + case "." | "..": + case _: workList.push(haxe.io.Path.join([current, file])); + } + } + } else { + if (match.match == null || match.match(current)) { + f(current); + } + } + } + } +} \ No newline at end of file diff --git a/tests/TestMakefile.hxml b/tests/TestMakefile.hxml new file mode 100644 index 00000000..dba22395 --- /dev/null +++ b/tests/TestMakefile.hxml @@ -0,0 +1,2 @@ +-main TestMakefile +-neko TestMakefile.n \ No newline at end of file diff --git a/tests/benchs/mandelbrot/Mandelbrot.hx b/tests/benchs/mandelbrot/Mandelbrot.hx new file mode 100644 index 00000000..38c1e72a --- /dev/null +++ b/tests/benchs/mandelbrot/Mandelbrot.hx @@ -0,0 +1,153 @@ +#if (!js && !flash) +import haxe.io.Bytes; +#end + +#if anon_objects +typedef RGB = { r:Int, g:Int, b:Int }; +typedef Complex = { i:Float, j:Float }; +#else +class RGB +{ + public var r:Int; + public var g:Int; + public var b:Int; + + public function new(inR:Int, inG:Int, inB:Int) + { + r = inR; + g = inG; + b = inB; + } +} + +class Complex +{ + public var i:Float; + public var j:Float; + + public function new(inI:Float, inJ:Float) + { + i = inI; + j = inJ; + } +} +#end + + + +class Mandelbrot +{ + static inline var SIZE = 25; + static inline var MaxIterations = 1000; + static inline var MaxRad = 1<<16; + static inline var width = 35*SIZE; + static inline var height = 20*SIZE; + + + public static function main() + { + var t0 = now(); + + var palette = []; + for(i in 0...MaxIterations+1) + palette.push( createPalette(i/MaxIterations) ); + + var image = []; + image[ width*height-1 ] = null; + var outPixel = 0; + var scale = 0.1/SIZE; + for(y in 0...height) + { + if ( (y%10)== 0) + trace(y); + for(x in 0...width) + { + var iteration = 0; + + #if reduce_allocs + var offsetI = x*scale - 2.5; + var offsetJ = y*scale - 1.0; + var valI = 0.0; + var valJ = 0.0; + while( valI*valI+valJ*valJVoid>; + var numTests:Int; + var numFailures:Int; + var testName:String; + + // api + inline function pos(name) return ctx.pos(name); + inline function fields(pos) return ctx.fields(pos); + inline function signatures(pos) return ctx.signatures(pos); + inline function toplevel(pos) return ctx.toplevel(pos); + inline function type(pos) return ctx.type(pos); + inline function position(pos) return ctx.position(pos); + inline function usage(pos) return ctx.usage(pos); + inline function range(pos1, pos2) return ctx.range(pos1, pos2); + inline function signature(pos1) return ctx.signature(pos1); + inline function metadataDoc(pos1) return ctx.metadataDoc(pos1); + + function assert(v:Bool) if (!v) throw "assertion failed"; + + function eq(expected:T, actual:T, ?pos:haxe.PosInfos) { + numTests++; + if (expected != actual) { + numFailures++; + report("Assertion failed", pos); + report("Expected: " + expected, pos); + report("Actual: " + actual, pos); + } + } + + function arrayEq(expected:Array, actual:Array, ?pos:haxe.PosInfos) { + numTests++; + var leftover = expected.copy(); + for (actual in actual) { + if (!leftover.remove(actual)) { + numFailures++; + report("Result not part of expected Array:", pos); + report(actual, pos); + } + } + for (leftover in leftover) { + numFailures++; + report("Expected result was not part of actual Array:", pos); + report(leftover, pos); + return; + } + } + + function arrayCheck(expected:Array, actual:Array, f : T -> String, ?pos:haxe.PosInfos) { + var expected = [for (expected in expected) f(expected) => expected]; + for (actual in actual) { + var key = f(actual); + if (!expected.exists(key)) { + numFailures++; + report("Result not part of expected Array:", pos); + report(Std.string(actual), pos); + } + expected.remove(key); + } + + for (expected in expected) { + numFailures++; + report("Expected result was not part of actual Array:", pos); + report(Std.string(expected), pos); + return; + } + } + + function hasField(a:Array, name:String, type:String):Bool { + return a.exists(function(t) return t.type == type && t.name == name); + } + + function hasPath(a:Array, name:String):Bool { + return a.exists(function(t) return t.name == name); + } + + function report(message, pos:haxe.PosInfos) { + haxe.Log.trace(message, pos); + } + + public function run() { + for (method in methods) { + method(); + } + return { + testName: testName, + numTests: numTests, + numFailures: numFailures + } + } +} \ No newline at end of file diff --git a/tests/display/src/DisplayTestContext.hx b/tests/display/src/DisplayTestContext.hx new file mode 100644 index 00000000..78da5007 --- /dev/null +++ b/tests/display/src/DisplayTestContext.hx @@ -0,0 +1,181 @@ +using StringTools; +import Types; + +class HaxeInvocationException { + + public var message:String; + public var fieldName:String; + public var arguments:Array; + public var source:String; + + public function new(message:String, fieldName:String, arguments:Array, source:String) { + this.message = message; + this.fieldName = fieldName; + this.arguments = arguments; + this.source = source; + } +} + +class DisplayTestContext { + var source:File; + var markers:Map; + var fieldName:String; + + public function new(path:String, fieldName:String, source:String, markers:Map) { + this.fieldName = fieldName; + this.source = new File(path, source); + this.markers = markers; + } + + public function pos(id:Int):Position { + var r = markers[id]; + if (r == null) throw "No such marker: " + id; + return new Position(r); + } + + public function range(pos1:Int, pos2:Int) { + return normalizePath(source.formatPosition(pos(pos1), pos(pos2))); + } + + public function fields(pos:Position):Array { + return extractFields(callHaxe('$pos')); + } + + public function signatures(pos:Position):Array { + return extractSignatures(callHaxe('$pos')); + } + + public function toplevel(pos:Position):Array { + return extractToplevel(callHaxe('$pos@toplevel')); + } + + public function type(pos:Position):String { + return extractType(callHaxe('$pos@type')); + } + + public function positions(pos:Position):Array { + return extractPositions(callHaxe('$pos@position')); + } + + public function position(pos:Position):String { + return positions(pos)[0]; + } + + public function usage(pos:Position):Array { + return extractPositions(callHaxe('$pos@usage')); + } + + public function documentSymbols():Array { + return haxe.Json.parse(callHaxe("0@module-symbols"))[0].symbols; + } + + public function signature(pos:Position):SignatureHelp { + return haxe.Json.parse(callHaxe('$pos@signature')); + } + + public function metadataDoc(pos:Position):String { + return extractMetadata(callHaxe('$pos@type')); + } + + function callHaxe(displayPart:String):String { + var args = [ + "-cp", "src", + "-D", "display-stdin", + "--display", + source.path + "@" + displayPart, + ]; + var stdin = source.content; + var proc = new sys.io.Process("haxe", args); + proc.stdin.writeString(stdin); + proc.stdin.close(); + var stderr = proc.stderr.readAll(); + var stdout = proc.stdout.readAll(); + var exit = proc.exitCode(); + proc.close(); + var success = exit == 0; + var s = stderr.toString(); + if (!success || s == "") { + throw new HaxeInvocationException(s, fieldName, args, stdin); + } + return s; + } + + static function extractType(result:String) { + var xml = Xml.parse(result); + xml = xml.firstElement(); + if (xml.nodeName != "type") { + return null; + } + return StringTools.trim(xml.firstChild().nodeValue); + } + + static function extractSignatures(result:String) { + var xml = Xml.parse('$result'); + xml = xml.firstElement(); + var ret = []; + for (xml in xml.elementsNamed("type")) { + ret.push(StringTools.trim(xml.firstChild().nodeValue)); + } + return ret; + } + + static function extractPositions(result:String) { + var xml = Xml.parse(result); + xml = xml.firstElement(); + if (xml.nodeName != "list") { + return null; + } + var ret = []; + for (xml in xml.elementsNamed("pos")) { + ret.push(normalizePath(xml.firstChild().nodeValue.trim())); + } + return ret; + } + + static function extractToplevel(result:String) { + var xml = Xml.parse(result); + xml = xml.firstElement(); + if (xml.nodeName != "il") { + return null; + } + var ret = []; + for (xml in xml.elementsNamed("i")) { + ret.push({kind: xml.get("k"), name: xml.firstChild().nodeValue}); + } + return ret; + } + + static function extractFields(result:String) { + var xml = Xml.parse(result); + xml = xml.firstElement(); + if (xml.nodeName != "list") { + return null; + } + var ret = []; + for (xml in xml.elementsNamed("i")) { + ret.push({name: xml.get("n"), type: xml.firstElement().firstChild().nodeValue}); + } + return ret; + } + + static function extractMetadata(result:String) { + var xml = Xml.parse(result); + xml = xml.firstElement(); + if (xml.nodeName != "metadata") { + return null; + } + return xml.firstChild().nodeValue; + } + + static function normalizePath(p:String):String { + if (!haxe.io.Path.isAbsolute(p)) { + p = Sys.getCwd() + p; + } + if (Sys.systemName() == "Windows") { + // on windows, haxe returns paths with backslashes, drive letter uppercased + p = p.substr(0, 1).toUpperCase() + p.substr(1); + p = p.replace("/", "\\"); + } + return p; + } +} diff --git a/tests/display/src/File.hx b/tests/display/src/File.hx new file mode 100644 index 00000000..676284d0 --- /dev/null +++ b/tests/display/src/File.hx @@ -0,0 +1,62 @@ +class File { + public var content(default,null):String; + public var path(default,null):String; + var lines:Array; + + public function new(path:String, content:String) { + this.path = path; + this.content = content; + initLines(); + } + + function initLines() { + lines = []; + // составляем массив позиций начала строк + var s = 0, p = 0; + while (p < content.length) { + inline function nextChar() return StringTools.fastCodeAt(content, p++); + inline function line() { lines.push(s); s = p; }; + switch (nextChar()) { + case "\n".code: + line(); + case "\r".code: + p++; + line(); + } + } + } + + function findLine(pos:Int):{line:Int, pos:Int} { + function loop(min, max) { + var mid = (min + max) >> 1; + var start = lines[mid]; + return + if (mid == min) + {line: mid, pos: pos - start}; + else if (start > pos) + loop(min, mid); + else + loop(mid, max); + } + return loop(0, lines.length); + } + + public function formatPosition(min:Int, max:Int):String { + var start = findLine(min); + var end = findLine(max); + var pos = + if (start.line == end.line) { + if (start.pos == end.pos) + 'character ${start.pos}'; + else + 'characters ${start.pos}-${end.pos}'; + } else { + 'lines ${start.line + 1}-${end.line + 1}'; + } + return '$path:${start.line + 1}: $pos'; + } + + public static inline function read(path:String) { + return new File(path, sys.io.File.getContent(path)); + } +} \ No newline at end of file diff --git a/tests/display/src/Macro.hx b/tests/display/src/Macro.hx new file mode 100644 index 00000000..4f543068 --- /dev/null +++ b/tests/display/src/Macro.hx @@ -0,0 +1,63 @@ +import haxe.macro.Context; +import haxe.macro.Expr; + +using Lambda; + +class Macro { + static function buildTestCase():Array { + var fields = Context.getBuildFields(); + var markerRe = ~/{-(\d+)-}/g; + var testCases = []; + var c = Context.getLocalClass().get(); + for (field in fields) { + var markers = []; + var posAcc = 0; + if (field.doc == null) { + continue; + } + var doc = (c.pack.length > 0 ? "package " + c.pack.join(".") + ";\n" : ""); + if (field.meta.exists(function(meta) return meta.name == ":funcCode")) { + doc += "class Main { static function main() { " + field.doc + "}}"; + } else { + doc += field.doc; + } + var src = markerRe.map(doc, function(r) { + var p = r.matchedPos(); + var name = r.matched(1); + var pos = p.pos - posAcc; + posAcc += p.len; + markers.push(macro $v{Std.parseInt(name)} => $v{pos}); + return ""; + }); + var markers = markers.length > 0 ? macro $a{markers} : macro new Map(); + testCases.push(macro function() { + ctx = new DisplayTestContext($v{Context.getPosInfos(c.pos).file}, $v{field.name}, $v{src}, $markers); + $i{field.name}(); + }); + } + + fields.push((macro class { + public function new() { + testName = $v{c.name}; + numTests = 0; + numFailures = 0; + this.methods = $a{testCases}; + } + }).fields[0]); + + return fields; + } + + macro static public function getCases(pack:String) { + var path = Context.resolvePath(pack); + var cases = []; + for (file in sys.FileSystem.readDirectory(path)) { + var p = new haxe.io.Path(file); + if (p.ext == "hx") { + var tp = {pack: [pack], name: p.file}; + cases.push(macro new $tp()); + } + } + return macro $a{cases}; + } +} diff --git a/tests/display/src/Main.hx b/tests/display/src/Main.hx new file mode 100644 index 00000000..c7ae3453 --- /dev/null +++ b/tests/display/src/Main.hx @@ -0,0 +1,24 @@ +class Main { + static function main() { + var tests = Macro.getCases("cases"); + var numTests = 0; + var numFailures = 0; + for (test in tests) { + try { + var result = test.run(); + numTests += result.numTests; + numFailures += result.numFailures; + Sys.println('${result.testName}: ${result.numTests} tests, ${result.numFailures} failures'); + } catch(e:DisplayTestContext.HaxeInvocationException) { + Sys.println("Error: " + e.message); + Sys.println("Field name: " + e.fieldName); + Sys.println("Arguments: " + e.arguments.join(" ")); + Sys.println("Source: " + e.source); + numTests++; + numFailures++; + } + } + Sys.println('Finished with $numTests tests, $numFailures failures'); + Sys.exit(numFailures == 0 ? 0 : 1); + } +} diff --git a/tests/display/src/ModuleSymbolEntry.hx b/tests/display/src/ModuleSymbolEntry.hx new file mode 100644 index 00000000..25af5dbb --- /dev/null +++ b/tests/display/src/ModuleSymbolEntry.hx @@ -0,0 +1,22 @@ +// Taken from vshaxe... not ideal to copy it here + +@:enum +private abstract ModuleSymbolKind(Int) { + var MClass = 1; + var MInterface = 2; + var MEnum = 3; + var MTypedef = 4; + var MAbstract = 5; + var MField = 6; + var MProperty = 7; + var MMethod = 8; + var MConstructor = 9; + var MFunction = 10; + var MVariable = 11; +} + +typedef ModuleSymbolEntry = { + var name:String; + var kind:ModuleSymbolKind; + @:optional var containerName:String; +} \ No newline at end of file diff --git a/tests/display/src/SignatureHelp.hx b/tests/display/src/SignatureHelp.hx new file mode 100644 index 00000000..184cdc60 --- /dev/null +++ b/tests/display/src/SignatureHelp.hx @@ -0,0 +1,18 @@ +// from vshaxe + +typedef SignatureHelp = { + var signatures:Array; + @:optional var activeSignature:Int; + @:optional var activeParameter:Int; +} + +typedef SignatureInformation = { + var label:String; + @:optional var documentation:String; + @:optional var parameters:Array; +} + +typedef ParameterInformation = { + var label:String; + @:optional var documentation:String; +} \ No newline at end of file diff --git a/tests/display/src/Types.hx b/tests/display/src/Types.hx new file mode 100644 index 00000000..81c65a81 --- /dev/null +++ b/tests/display/src/Types.hx @@ -0,0 +1,15 @@ +typedef ToplevelElement = { + kind: String, + name: String +} + +typedef FieldElement = { + name: String, + type: String +} + +abstract Position(Int) to Int { + public inline function new(i:Int) { + this = i; + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Abstract.hx b/tests/display/src/cases/Abstract.hx new file mode 100644 index 00000000..7c58ac0f --- /dev/null +++ b/tests/display/src/cases/Abstract.hx @@ -0,0 +1,16 @@ +package cases; + +class Abstract extends DisplayTestCase { + /** + abstract A(Int) { + public function new({-3-}i{-4-}) { + this = i{-1-}; + trace("f{-2-}oo"); + } + } + **/ + function test() { + eq(range(3, 4), position(pos(1))); + eq("String", type(pos(2))); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Basic.hx b/tests/display/src/cases/Basic.hx new file mode 100644 index 00000000..e261c7a8 --- /dev/null +++ b/tests/display/src/cases/Basic.hx @@ -0,0 +1,100 @@ +package cases; + +class Basic extends DisplayTestCase { + /** + class Some { + function main() { + var a = 5; + a{-1-} + } + } + **/ + function testType1() { + eq("Int", type(pos(1))); + } + + /** + class Some { + function main() { + var {-1-}variable{-2-} = 5; + variable{-3-}; + } + } + **/ + function testPosition1() { + eq(range(1, 2), position(pos(3))); + } + + /** + class Some { + function main() { + var variable{-1-} = 5; + {-2-}variable{-3-}; + } + } + **/ + function testUsage1() { + eq(range(2, 3), usage(pos(1))[0]); + } + + /** + class Some { + function main() { + var variable{-1-} = 5; + {-2-}variable{-3-}; + {-4-}variable{-5-}; + } + } + **/ + function testUsage2() { + arrayEq([range(2, 3), range(4, 5)], usage(pos(1))); + } + + /** + function test(na{-1-}me:St{-2-}ring) { } + **/ + @:funcCode function testLocalFunction() { + eq("String", type(pos(1))); + eq("String", type(pos(2))); + } + + /** + class Some { + var x1 = "fo{-1-}"; + static var x2 = "fo{-2-}"; + static inline var x3 = "fo{-3-}"; + + var x4(default, null) = "fo{-4-}"; + static var x5(default, null) = "fo{-5-}"; + + static var x{-6-}6:String; + } + **/ + function testFieldDisplay() { + eq("String", type(pos(1))); + eq("String", type(pos(2))); + eq("String", type(pos(3))); + eq("String", type(pos(4))); + eq("String", type(pos(5))); + eq("String", type(pos(6))); + } + + /** + var a:Ar{-1-}ray; + **/ + @:funcCode function testMissingParams() { + eq("Array", type(pos(1))); + } + + /** + class Some { + function new(someName:Int) {} + function main() { + Some.new{-1-} + } + } + **/ + function testCtorClosureType() { + eq("someName : Int -> cases.Some", type(pos(1))); + } +} diff --git a/tests/display/src/cases/BuildMacro.hx b/tests/display/src/cases/BuildMacro.hx new file mode 100644 index 00000000..93fca562 --- /dev/null +++ b/tests/display/src/cases/BuildMacro.hx @@ -0,0 +1,34 @@ +package cases; + +class BuildMacro extends DisplayTestCase { + /** + class MyMacro { + macro static public function build():Array { + var fields = haxe.macro.Context.getBuildFields(); + return fields; + } + } + + {-7-}typedef MyString = String{-8-}; + + #if !macro + @:build(cases.BuildMacro.MyMacro.build()) + #end + class Main { + function te{-1-}st({-5-}na{-2-}me{-6-}:MySt{-3-}ring):MyStr{-4-}ing { + return {-9-}name{-10-}; + } + + static function main() { } + } + **/ + function test1() { + eq("cases.MyString", type(pos(2))); + eq("cases.MyString", type(pos(3))); + eq("cases.MyString", type(pos(4))); + eq(range(7, 8), position(pos(3))); + eq(range(7, 8), position(pos(4))); + eq(range(5, 6), position(pos(2))); + arrayEq([range(9, 10)], usage(pos(10))); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Completion.hx b/tests/display/src/cases/Completion.hx new file mode 100644 index 00000000..04b5a256 --- /dev/null +++ b/tests/display/src/cases/Completion.hx @@ -0,0 +1,48 @@ +package cases; + +class Completion extends DisplayTestCase { + /** + var s = { foo: 1 }; + s.{-1-} + **/ + @:funcCode function testHaxeUnitPort1() { + eq(true, hasField(fields(pos(1)), "foo", "Int")); + } + + /** + var s = { foo: 1 }; + for (k in [s].iterator()) { + k.{-1-} + } + **/ + @:funcCode function testHaxeUnitPort2() { + eq(true, hasField(fields(pos(1)), "foo", "Int")); + } + + /** + var f = function():Iterator<{foo:Int}> { + return [s].iterator(); + }; + var s = { foo: 1 }; + for (k in f()) { + k.{-1-} + } + **/ + @:funcCode function testHaxeUnitPort3() { + eq(true, hasField(fields(pos(1)), "foo", "Int")); + } + + /** + var x:haxe.macro.{-1-} + **/ + @:funcCode function testHaxeUnitPort4() { + eq(true, hasPath(fields(pos(1)), "Expr")); + } + + /** + var x:haxe.macro.Expr.{-1-} + **/ + @:funcCode function testHaxeUnitPort5() { + eq(true, hasPath(fields(pos(1)), "ExprDef")); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/DocumentSymbols.hx b/tests/display/src/cases/DocumentSymbols.hx new file mode 100644 index 00000000..e07aea64 --- /dev/null +++ b/tests/display/src/cases/DocumentSymbols.hx @@ -0,0 +1,102 @@ +package cases; + +class DocumentSymbols extends DisplayTestCase { + /** + class Some { + function main() { } + static var x:String; + var y:Int; + var z(default, null):Bool; + function new() { } + } + **/ + function testClassFields() { + checkDocumentSymbols([ + { name: "Some", kind: MClass, containerName: null }, + { name: "main", kind: MMethod, containerName: "Some" }, + { name: "x", kind: MField, containerName: "Some" }, + { name: "y", kind: MField, containerName: "Some" }, + { name: "z", kind: MProperty, containerName: "Some" }, + { name: "new", kind: MConstructor, containerName: "Some" } + ], ctx.documentSymbols()); + } + + /** + interface Some { + function test():Void; + } + **/ + function testInterface() { + checkDocumentSymbols([ + { name: "Some", kind: MInterface, containerName: null }, + { name: "test", kind: MMethod, containerName: "Some" } + ], ctx.documentSymbols()); + } + + /** + enum E { + A; + B(s:String); + } + **/ + function testEnum() { + checkDocumentSymbols([ + { name: "E", kind: MEnum, containerName: null }, + { name: "A", kind: MMethod, containerName: "E" }, + { name: "B", kind: MMethod, containerName: "E" } + ], ctx.documentSymbols()); + } + + /** + typedef T = { + x:Int, + } + **/ + function testTypedef() { + checkDocumentSymbols([ + { name: "T", kind: MTypedef, containerName: null }, + { name: "x", kind: MField, containerName: "T" } + ], ctx.documentSymbols()); + } + + /** + abstract A(Int) { + public function new() { } + function f() { } + } + **/ + function testAbstract() { + checkDocumentSymbols([ + { name: "A", kind: MAbstract, containerName: null }, + { name: "new", kind: MConstructor, containerName: "A" }, + { name: "f", kind: MMethod, containerName: "A" } + ], ctx.documentSymbols()); + } + + /** + class Main { + static function main() { + var a = 12; + var b, c = 13; + var d = 1, e; + function f() { } + } + } + **/ + function testExpression() { + checkDocumentSymbols([ + { name: "Main", kind: MClass, containerName: null }, + { name: "main", kind: MMethod, containerName: "Main" }, + { name: "a", kind: MVariable, containerName: "Main.main" }, + { name: "b", kind: MVariable, containerName: "Main.main" }, + { name: "c", kind: MVariable, containerName: "Main.main" }, + { name: "d", kind: MVariable, containerName: "Main.main" }, + { name: "e", kind: MVariable, containerName: "Main.main" }, + { name: "f", kind: MFunction, containerName: "Main.main" } + ], ctx.documentSymbols()); + } + + function checkDocumentSymbols(expected:Array, actual:Array, ?pos:haxe.PosInfos) { + arrayCheck(expected, actual, function(entry) return entry.kind + ":" + entry.name + ":" + entry.containerName, pos); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/IImport.hx b/tests/display/src/cases/IImport.hx new file mode 100644 index 00000000..fbdd29ae --- /dev/null +++ b/tests/display/src/cases/IImport.hx @@ -0,0 +1,59 @@ +package cases; + +import Types; +using Lambda; + +class IImport extends DisplayTestCase { + /** + import ha{-1-}xe.ma{-2-}cro.Exp{-3-}rTools.Expr{-4-}ArrayTools.it{-5-}er; + **/ + function testImport1() { + eq(true, hasPath(fields(pos(1)), "Serializer")); + eq(true, hasPath(fields(pos(2)), "ExprTools")); + eq(true, hasPath(fields(pos(3)), "ExprArrayTools")); + eq(true, hasField(fields(pos(4)), "iter", "el : Array -> f : (haxe.macro.Expr -> Void) -> Void")); + eq("el : Array -> f : (haxe.macro.Expr -> Void) -> Void", type(pos(5))); + // TODO: test @position display. A bit annoying because it actually ends up in other files and we can't use markers. + } + + /** + import haxe.{-1-} + **/ + function testImport2() { + eq(true, hasPath(fields(pos(1)), "Serializer")); + } + + /** + import haxe.Serializer.{-1-} + **/ + function testImport3() { + eq(true, hasPath(fields(pos(1)), "run")); + eq(true, hasPath(fields(pos(1)), "Serializer")); + } + + /** + using ha{-1-}xe.ma{-2-}cro.Exp{-3-}rTools.Expr{-4-}ArrayTools; + **/ + function testUsing1() { + eq(true, hasPath(fields(pos(1)), "Serializer")); + eq(true, hasPath(fields(pos(2)), "ExprTools")); + eq(true, hasPath(fields(pos(3)), "ExprArrayTools")); + eq(true, hasField(fields(pos(4)), "iter", "el : Array -> f : (haxe.macro.Expr -> Void) -> Void")); + // TODO: test @position display. A bit annoying because it actually ends up in other files and we can't use markers. + } + + /** + using haxe.{-1-} + **/ + function testUsing2() { + eq(true, hasPath(fields(pos(1)), "Serializer")); + } + + /** + using haxe.Serializer.{-1-} + **/ + function testUsing3() { + eq(false, hasPath(fields(pos(1)), "run")); + eq(true, hasPath(fields(pos(1)), "Serializer")); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Issue5141.hx b/tests/display/src/cases/Issue5141.hx new file mode 100644 index 00000000..6d943e72 --- /dev/null +++ b/tests/display/src/cases/Issue5141.hx @@ -0,0 +1,36 @@ +package cases; + +class Issue5141 extends DisplayTestCase { + /** + typedef MyHandler = Int->String->Void + + class Some { + function main() { + var a:MyHandler; + a{-1-}; + a({-2-} + } + } + **/ + function testTypedef() { + eq("cases.MyHandler", type(pos(1))); + arrayEq(["Int -> String -> Void"], signatures(pos(2))); + } + + /** + @:callable + abstract MyCallable(Int->String->Void) {} + + class Some { + function main() { + var a:MyCallable; + a{-1-}; + a({-2-} + } + } + **/ + function testAbstract() { + eq("cases.MyCallable", type(pos(1))); + arrayEq(["Int -> String -> Void"], signatures(pos(2))); + } +} diff --git a/tests/display/src/cases/Issue5166.hx b/tests/display/src/cases/Issue5166.hx new file mode 100644 index 00000000..d09eef4c --- /dev/null +++ b/tests/display/src/cases/Issue5166.hx @@ -0,0 +1,14 @@ +package cases; + +class Issue5166 extends DisplayTestCase { + /** + @:enum abstract E(Int) { + {-2-}var A{-1-} = 5;{-3-} + } + + **/ + function test() { + eq("cases.E", type(pos(1))); + eq(range(2, 3), position(pos(1))); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Issue5171.hx b/tests/display/src/cases/Issue5171.hx new file mode 100644 index 00000000..d3bede8f --- /dev/null +++ b/tests/display/src/cases/Issue5171.hx @@ -0,0 +1,14 @@ +package cases; + +class Issue5171 extends DisplayTestCase { + /** + {-2-}class Main { + static function main() { + Ma{-1-}in; + } + }{-3-} + **/ + function test() { + eq(range(2, 3), position(pos(1))); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Issue5172.hx b/tests/display/src/cases/Issue5172.hx new file mode 100644 index 00000000..b8e554d3 --- /dev/null +++ b/tests/display/src/cases/Issue5172.hx @@ -0,0 +1,21 @@ +package cases; + +class Issue5172 extends DisplayTestCase { + /** + class Main { + static function main() { + for ({-3-}i{-1-} in 0...10) { + {-4-}i{-2-}; + } + } + } + **/ + function test() { + eq("Int", type(pos(1))); + eq("Int", type(pos(2))); + eq(range(3, 1), position(pos(1))); + eq(range(3, 1), position(pos(2))); + arrayEq([range(4, 2)], usage(pos(1))); + arrayEq([range(4, 2)], usage(pos(2))); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Issue5173.hx b/tests/display/src/cases/Issue5173.hx new file mode 100644 index 00000000..f29f5d2f --- /dev/null +++ b/tests/display/src/cases/Issue5173.hx @@ -0,0 +1,22 @@ +package cases; + +class Issue5173 extends DisplayTestCase { + /** + class Main { + static function main() { + var map = new haxe.DynamicAccess(); + for ({-3-}ke{-1-}y{-4-} in map.keys()) { + {-5-}ke{-2-}y{-6-}; + } + } + } + **/ + function test() { + eq("String", type(pos(1))); + eq("String", type(pos(2))); + eq(range(3, 4), position(pos(1))); + eq(range(3, 4), position(pos(2))); + arrayEq([range(5, 6)], usage(pos(1))); + arrayEq([range(5, 6)], usage(pos(2))); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Issue5684.hx b/tests/display/src/cases/Issue5684.hx new file mode 100644 index 00000000..1d394cb4 --- /dev/null +++ b/tests/display/src/cases/Issue5684.hx @@ -0,0 +1,15 @@ +package cases; + +class Issue5684 extends DisplayTestCase { + /** + abstract Test(String) { + public function hi(){ + this.{-1-} + } + } + **/ + function testType1() { + // eq("Int", type(pos(1))); + eq(true, hasField(fields(pos(1)), "length", "Int")); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Issue5712.hx b/tests/display/src/cases/Issue5712.hx new file mode 100644 index 00000000..104286bf --- /dev/null +++ b/tests/display/src/cases/Issue5712.hx @@ -0,0 +1,21 @@ +package cases; + +class Issue5712 extends DisplayTestCase { + /** + typedef Struct = { + {-1-}field:Float{-2-} + } + class Main { + public static function main() { + var s:Struct = { fi{-3-}eld: 0 }; + s.fi{-4-}eld; + } + } + **/ + function testType1() { + eq(range(1, 2), position(pos(3))); + eq(range(1, 2), position(pos(4))); + eq("Float", type(pos(3))); // not sure about this one, maybe it should be Int... + eq("Float", type(pos(4))); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Issue5729.hx b/tests/display/src/cases/Issue5729.hx new file mode 100644 index 00000000..6ca5b523 --- /dev/null +++ b/tests/display/src/cases/Issue5729.hx @@ -0,0 +1,20 @@ +package cases; + +class Issue5729 extends DisplayTestCase { + /** + enum TestEnum { + Constructor(i:Int); + } + class Main { + public static function main() { + var c = Constructor(1); + switch (c) { + case Constructor(int{-1-}eger): trace("test"); + } + } + } + **/ + function testType1() { + eq("Int", type(pos(1))); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Issue5775.hx b/tests/display/src/cases/Issue5775.hx new file mode 100644 index 00000000..fdd8389b --- /dev/null +++ b/tests/display/src/cases/Issue5775.hx @@ -0,0 +1,15 @@ +package cases; + +class Issue5775 extends DisplayTestCase { + /** + class Main { + static function main () { + var a = []; + trace('${a.{-1-}}'); + } + } + **/ + function testType1() { + eq(true, hasField(fields(pos(1)), "length", "Int")); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Issue5796.hx b/tests/display/src/cases/Issue5796.hx new file mode 100644 index 00000000..b8b464ac --- /dev/null +++ b/tests/display/src/cases/Issue5796.hx @@ -0,0 +1,17 @@ +package cases; + +class Issue5796 extends DisplayTestCase { + /** + class Main { + static function main() {} + } + + typedef Test = { + @:gen{-1-}eric var f{-2-}oo:Int; + } + **/ + function test() { + eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(1))); + eq("Int", type(pos(2))); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Metadata.hx b/tests/display/src/cases/Metadata.hx new file mode 100644 index 00000000..5122031d --- /dev/null +++ b/tests/display/src/cases/Metadata.hx @@ -0,0 +1,113 @@ +package cases; + +class Metadata extends DisplayTestCase { + /** + @{-1-} + class Some { } + **/ + function testCompletion() { + eq(true, hasPath(fields(pos(1)), "@:generic")); + } + + /** + @{-1-}:{-2-} + class Some { } + **/ + function testCompletion2() { + eq(true, hasPath(fields(pos(1)), "@:generic")); + eq(true, hasPath(fields(pos(2)), "@:generic")); + } + + /** + @{-1-}:{-2-}gen{-3-}oric + class Some { } + **/ + function testCompletion3() { + eq(true, hasPath(fields(pos(1)), "@:generic")); + eq(true, hasPath(fields(pos(2)), "@:generic")); + eq(true, hasPath(fields(pos(3)), "@:generic")); + } + + /** + @:gen{-1-}eric + class Some { } + **/ + function testHover() { + eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(1))); + } + + /** + {-1-}class SomeOther { }{-2-} + + @:myMeta(Som{-3-}eOther) + class Some { } + **/ + function testArgs() { + eq(range(1, 2), position(pos(3))); + eq("Class", type(pos(3))); + } + + + /** + class Main { + public static function main() { @{-1-} } + } + **/ + function testExpression1() { + eq(true, hasPath(fields(pos(1)), "@:generic")); + } + + /** + class Main { + public static function main() { @{-1-}:{-2-} } + } + **/ + function testExpression2() { + eq(true, hasPath(fields(pos(1)), "@:generic")); + eq(true, hasPath(fields(pos(2)), "@:generic")); + } + + /** + class Main { + public static function main() { @{-1-}:{-2-}gene{-3-}ric } + } + **/ + function testExpression3() { + eq(true, hasPath(fields(pos(1)), "@:generic")); + eq(true, hasPath(fields(pos(2)), "@:generic")); + eq(true, hasPath(fields(pos(3)), "@:generic")); + } + + /** + class Main { + public static function main() { @{-1-}:{-2-}gene{-3-}ric null; } + } + **/ + function testExpression4() { + eq(true, hasPath(fields(pos(1)), "@:generic")); + eq(true, hasPath(fields(pos(2)), "@:generic")); + eq(true, hasPath(fields(pos(3)), "@:generic")); + } + + /** + class Main { + public static function main() { @{-1-}:{-2-}gene{-3-}ric } + } + **/ + function testExpression5() { + eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(1))); + eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(2))); + eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(3))); + } + + /** + class Main { + public static function main() { @{-1-}:{-2-}gene{-3-}ric null; } + } + **/ + function testExpression6() { + eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(1))); + eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(2))); + eq("Marks a class or class field as generic so each type parameter combination generates its own type/field", metadataDoc(pos(3))); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/PropertyAccessors.hx b/tests/display/src/cases/PropertyAccessors.hx new file mode 100644 index 00000000..07f3a0ad --- /dev/null +++ b/tests/display/src/cases/PropertyAccessors.hx @@ -0,0 +1,20 @@ +package cases; + +class PropertyAccessors extends DisplayTestCase { + /** + class Main { + static var test(ge{-1-}t, se{-2-}t):String; + + static public {-3-}function get_test() return "foo"{-4-}; + static public {-5-}function set_test(s:String) return s{-6-}; + + static function main() { } + } + **/ + function test() { + eq(range(3, 4), position(pos(1))); + eq(range(5, 6), position(pos(2))); + eq("Void -> String", type(pos(1))); + eq("s : String -> String", type(pos(2))); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Signature.hx b/tests/display/src/cases/Signature.hx new file mode 100644 index 00000000..35d8c055 --- /dev/null +++ b/tests/display/src/cases/Signature.hx @@ -0,0 +1,188 @@ +package cases; + +import SignatureHelp; + +class Signature extends DisplayTestCase { + /** + class Some { + function main() { + test({-1-}"foo"{-2-},{-3-}12{-4-}) + } + + static function test(a:String, b:Int) { } + } + **/ + function testGoodAst() { + sigEq(0, [["a:String", "b:Int"]], signature(pos(1))); + sigEq(0, [["a:String", "b:Int"]], signature(pos(2))); + sigEq(1, [["a:String", "b:Int"]], signature(pos(3))); + sigEq(1, [["a:String", "b:Int"]], signature(pos(4))); + } + + /** + class Some { + function main() { + test({-1-}"foo"{-2-} + } + + static function test(a:String, b:Int) { } + } + **/ + function testBadAst() { + sigEq(0, [["a:String", "b:Int"]], signature(pos(1))); + sigEq(0, [["a:String", "b:Int"]], signature(pos(2))); + } + + /** + class Some { + static function someFunc(a:String, b:Float) { } + + static function main() { + var a = "foo"; + var b = 12; + someFunc(a, {v: [a, b, {-1-} + } + } + **/ + function testUglyAst() { + sigEq(1, [["a:String", "b:Float"]], signature(pos(1))); + } + + /** + class Some { + function main() { + test({-1-} + } + + @:overload(function (a:String, b:Bool):Void { }) + static function test(a:String, b:Int) { } + } + **/ + function testOverloads1() { + sigEq(0, [["a:String", "b:Bool"], ["a:String", "b:Int"]], signature(pos(1))); + } + + /** + class Some { + function main() { + test("foo",{-1-} + } + + @:overload(function (a:String, b:Bool):Void { }) + static function test(a:String, b:Int) { } + } + **/ + function testOverloads2() { + sigEq(1, [["a:String", "b:Bool"], ["a:String", "b:Int"]], signature(pos(1))); + } + + /** + class Some { + function main() { + test("foo", 12{-1-} + } + + @:overload(function (a:String, b:Bool):Void { }) + static function test(a:String, b:Int) { } + } + **/ + function testOverloads3() { + sigEq(1, [["a:String", "b:Int"]], signature(pos(1))); + } + + /** + class Some { + function main() { + test({-1-} {-2-} + var x = 12; + } + + static function test(a:String, b:Int) { } + } + **/ + function testInsert1() { + sigEq(0, [["a:String", "b:Int"]], signature(pos(1))); + sigEq(0, [["a:String", "b:Int"]], signature(pos(2))); + } + + /** + class Some { + function main() { + test("foo",{-1-} {-2-} + var x = 12; + } + + static function test(a:String, b:Int) { } + } + **/ + function testInsert2() { + sigEq(1, [["a:String", "b:Int"]], signature(pos(1))); + sigEq(1, [["a:String", "b:Int"]], signature(pos(2))); + } + + /** + class SomeBase { + function new(a:Bool, b:Float) { } + } + + class Some extends SomeBase { + function new(a:String, b:Int) { + super({-1-}); + super(true, 1{-2-}); + } + + static function main() { + new Some({-3-}"fo{-4-}o"{-5-},{-6-} {-7-}12{-8-}); + } + } + **/ + function testConstructorGood() { + sigEq(0, [["a:Bool", "b:Float"]], signature(pos(1))); + sigEq(1, [["a:Bool", "b:Float"]], signature(pos(2))); + sigEq(0, [["a:String", "b:Int"]], signature(pos(3))); + sigEq(0, [["a:String", "b:Int"]], signature(pos(4))); + sigEq(0, [["a:String", "b:Int"]], signature(pos(5))); + sigEq(1, [["a:String", "b:Int"]], signature(pos(6))); + sigEq(1, [["a:String", "b:Int"]], signature(pos(7))); + sigEq(1, [["a:String", "b:Int"]], signature(pos(8))); + } + + /** + class Some { + function new(a:String, b:Int) { } + + static function main() { + new Some({-1-} + } + } + **/ + function testConstructorBad() { + sigEq(0, [["a:String", "b:Int"]], signature(pos(1))); + } + + /** + class Some { + static function main() { + test(test({-1-} + } + + static function test(a:String, b:Int) { } + } + **/ + function testNested() { + sigEq(0, [["a:String", "b:Int"]], signature(pos(1))); + } + + function sigEq(arg:Int, params:Array>, sig:SignatureHelp, ?pos:haxe.PosInfos) { + eq(arg, sig.activeParameter, pos); + eq(params.length, sig.signatures.length, pos); + for (i in 0...params.length) { + var sigInf = sig.signatures[i]; + var args = params[i]; + eq(sigInf.parameters.length, args.length, pos); + for (i in 0...args.length) { + eq(sigInf.parameters[i].label, args[i], pos); + } + } + } +} \ No newline at end of file diff --git a/tests/display/src/cases/StructureCompletion.hx b/tests/display/src/cases/StructureCompletion.hx new file mode 100644 index 00000000..5345458e --- /dev/null +++ b/tests/display/src/cases/StructureCompletion.hx @@ -0,0 +1,56 @@ +package cases; + +class StructureCompletion extends DisplayTestCase { + /** + var o:{a:Float, b:String} = {{-1-} + **/ + @:funcCode function testStructureCompletion1() { + eq(true, hasField(fields(pos(1)), "a", "Float")); + eq(true, hasField(fields(pos(1)), "b", "String")); + } + + /** + var x, o:{a:Float, b:String} = {{-1-} + **/ + @:funcCode function testStructureCompletion2() { + eq(true, hasField(fields(pos(1)), "a", "Float")); + eq(true, hasField(fields(pos(1)), "b", "String")); + } + + /** + var o:{a:Float, b:String}; + o = {{-1-} + **/ + @:funcCode function testStructureCompletion3() { + eq(true, hasField(fields(pos(1)), "a", "Float")); + eq(true, hasField(fields(pos(1)), "b", "String")); + } + + /** + class Main { + static function main () { + test({{-1-} + } + + static function test(o:{a:Float, b:String}) { } + } + **/ + function testStructureCompletion4() { + eq(true, hasField(fields(pos(1)), "a", "Float")); + eq(true, hasField(fields(pos(1)), "b", "String")); + } + + /** + class Main { + static function main () { + test(0, {{-1-} + } + + static function test(x, o:{a:Float, b:String}) { } + } + **/ + function testStructureCompletion5() { + eq(true, hasField(fields(pos(1)), "a", "Float")); + eq(true, hasField(fields(pos(1)), "b", "String")); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Super.hx b/tests/display/src/cases/Super.hx new file mode 100644 index 00000000..67cd85ec --- /dev/null +++ b/tests/display/src/cases/Super.hx @@ -0,0 +1,36 @@ +package cases; + +class Super extends DisplayTestCase { + /** + class Base { + public {-1-}function new() { }{-2-} + } + class Main extends Base { + function new() { + {-4-}su{-3-}per(){-5-}; + } + } + **/ + function testSuperCall() { + eq(range(1, 2), position(pos(3))); + eq("cases.Base", type(pos(3))); + arrayEq([range(4, 5)], usage(pos(3))); + } + + /** + {-1-}class Base { + public {-4-}function test() { }{-5-} + }{-2-} + class Main extends Base { + override function test() { + su{-3-}per.te{-6-}st(); + } + } + **/ + function testSuperField() { + eq(range(1, 2), position(pos(3))); + eq("cases.Base", type(pos(3))); + eq(range(4, 5), position(pos(6))); + eq("Void -> Void", type(pos(6))); + } +} \ No newline at end of file diff --git a/tests/display/src/cases/Toplevel.hx b/tests/display/src/cases/Toplevel.hx new file mode 100644 index 00000000..0d18d122 --- /dev/null +++ b/tests/display/src/cases/Toplevel.hx @@ -0,0 +1,150 @@ +package cases; + +import Types; +using Lambda; + +class Toplevel extends DisplayTestCase { + /** + class Main { + static var myField; + static function main() {{-1-} + {-2-} + **/ + function testToplevelResuming() { + eq(true, hasToplevel(toplevel(pos(1)), "static", "myField")); + eq(true, hasToplevel(toplevel(pos(2)), "static", "myField")); + } + + /** + class Main { + static var myField; + static function main() { + {-1-} + var a = "foo"; + {-2-} + **/ + function testToplevelScoping() { + var toplevel1 = toplevel(pos(1)); + var toplevel2 = toplevel(pos(2)); + eq(true, hasToplevel(toplevel1, "static", "myField")); + eq(true, hasToplevel(toplevel2, "static", "myField")); + eq(false, hasToplevel(toplevel1, "local", "a")); + eq(true, hasToplevel(toplevel2, "local", "a")); + } + + /** + class Main { + static var myField; + static function main() { + var a:{-1-} + **/ + function testTypeCompletionLocal() { + var typesCompletion = toplevel(pos(1)); + eq(true, hasToplevel(typesCompletion, "type", "Main")); + eq(true, hasToplevel(typesCompletion, "type", "Array")); + eq(true, hasToplevel(typesCompletion, "package", "haxe")); + eq(false, hasToplevel(typesCompletion, "static", "myField")); + } + + /** + class Main { + var a:{-1-} + **/ + function testTypeCompletionField() { + var typesCompletion = toplevel(pos(1)); + eq(true, hasToplevel(typesCompletion, "type", "Main")); + eq(true, hasToplevel(typesCompletion, "type", "Array")); + eq(true, hasToplevel(typesCompletion, "package", "haxe")); + } + + /** + class Main { + static function f(a:{-1-}) + **/ + function testTypeCompletionArgument() { + // TODO: this currently doesn't work if there's no closing paren for function arguments + var typesCompletion = toplevel(pos(1)); + eq(true, hasToplevel(typesCompletion, "type", "Main")); + eq(true, hasToplevel(typesCompletion, "type", "Array")); + eq(true, hasToplevel(typesCompletion, "package", "haxe")); + } + + /** + var a = function(a:{-1-} + **/ + @:funcCode function testTypeCompletionArgumentLocal() { + var typesCompletion = toplevel(pos(1)); + eq(true, hasToplevel(typesCompletion, "type", "Array")); + eq(true, hasToplevel(typesCompletion, "package", "haxe")); + } + + /** + import {-1-} + **/ + function testTypeCompletionImport() { + var typesCompletion = toplevel(pos(1)); + eq(true, hasToplevel(typesCompletion, "type", "Array")); + eq(true, hasToplevel(typesCompletion, "package", "haxe")); + } + + /** + using {-1-} + **/ + function testTypeCompletionUsing() { + var typesCompletion = toplevel(pos(1)); + eq(true, hasToplevel(typesCompletion, "type", "Array")); + eq(true, hasToplevel(typesCompletion, "package", "haxe")); + } + + /** + class C extends {-1-} { + **/ + function testTypeCompletionExtends() { + // TODO: this currently doesn't work if there's no token after extends + var typesCompletion = toplevel(pos(1)); + eq(true, hasToplevel(typesCompletion, "type", "Array")); + eq(true, hasToplevel(typesCompletion, "package", "haxe")); + } + + /** + class C implements {-1-} { + **/ + function testTypeCompletionImplements() { + // TODO: this currently doesn't work if there's no token after implements + var typesCompletion = toplevel(pos(1)); + eq(true, hasToplevel(typesCompletion, "type", "Array")); + eq(true, hasToplevel(typesCompletion, "package", "haxe")); + } + + /** + typedef T = {a:{-1-}} + **/ + function testTypeCompletionStructureField() { + // TODO: this currently doesn't work if there's no token after the completion position + var typesCompletion = toplevel(pos(1)); + eq(true, hasToplevel(typesCompletion, "type", "Array")); + eq(true, hasToplevel(typesCompletion, "package", "haxe")); + } + + /** + var a:{a:{-1-} + **/ + @:funcCode function testTypeCompletionStructureFieldAsType() { + var typesCompletion = toplevel(pos(1)); + eq(true, hasToplevel(typesCompletion, "type", "Array")); + eq(true, hasToplevel(typesCompletion, "package", "haxe")); + } + + /** + Xml.parse({-1-} + **/ + @:funcCode function testIssue5969() { + var typesCompletion = toplevel(pos(1)); + eq(true, hasToplevel(typesCompletion, "type", "Array")); + eq(true, hasToplevel(typesCompletion, "package", "haxe")); + } + + static function hasToplevel(a:Array, kind:String, name:String):Bool { + return a.exists(function(t) return t.kind == kind && t.name == name); + } +} diff --git a/tests/display/src/cases/Type.hx b/tests/display/src/cases/Type.hx new file mode 100644 index 00000000..eff39223 --- /dev/null +++ b/tests/display/src/cases/Type.hx @@ -0,0 +1,10 @@ +package cases; + +class Type extends DisplayTestCase { + /** + abstract A{-1-}(Int) {} + **/ + function testAbstractDecl() { + eq("cases.A", type(pos(1))); + } +} \ No newline at end of file diff --git a/tests/misc/compile.hxml b/tests/misc/compile.hxml index b01bba15..93ebe20e 100644 --- a/tests/misc/compile.hxml +++ b/tests/misc/compile.hxml @@ -1,2 +1,3 @@ -cp src +#-D MISC_TEST_FILTER=3802 --run Main \ No newline at end of file diff --git a/tests/misc/cppObjc/TestObjc.hx b/tests/misc/cppObjc/TestObjc.hx new file mode 100644 index 00000000..d75196ee --- /dev/null +++ b/tests/misc/cppObjc/TestObjc.hx @@ -0,0 +1,202 @@ +class TestObjc extends haxe.unit.TestCase +{ + static function main() + { + var x:TestObjc = null; + var c:TestClass = null; + var runner = new haxe.unit.TestRunner(); + runner.add(new TestObjc()); + var code = runner.run() ? 0 : 1; + Sys.exit(code); + } + + var cls:TestClass; + + public function testCall() + { + assertEquals(TestClass.aStatic(), 42); + cls = TestClass.alloc().init(); + assertEquals(cls.getOtherThing(), 0); + cls.setOtherThing(42); + assertEquals(cls.otherThing, 42); + assertEquals(cls.getOtherThing(), 42); + assertEquals(cls.getOtherThingChar(), 42); + assertEquals(cls.isBiggerThan10(2), false); + assertEquals(cls.isBiggerThan10(12), true); + assertEquals(cls.isBiggerThan10Int(3), false); + assertEquals(cls.isBiggerThan10Int(14), true); + assertEquals(cls.isBiggerThan10Num(3).boolValue(), false); + assertEquals(cls.isBiggerThan10Num(14).boolValue(), true); + assertEquals(cls.addHello("World"), "Hello, World"); + cls.something = " test"; + assertEquals(cls.something, " test"); + assertEquals(cls.addSomething("Hey,"), "Hey, test"); + assertEquals(cls.addHelloAndString("World"," it works"), "Hello, World it works"); + cls.release(); + } + + public function testVar() + { + cls = TestClass.alloc().init(); + cls.setOtherThing(142); + assertEquals(cls.otherThing, 142); + assertEquals(cls.getOtherThing(), 142); + cls.release(); + } + + public function testBoxing() + { + cls = TestClass.alloc().init(); + + cls.setOtherThing(255); + + var dyn:Dynamic = cls; + this.assertTrue(dyn != null); + this.assertTrue(cls != null); + + var someObjDecl = { a:10, b: cls }; + dyn = someObjDecl; // don't let Haxe inline that TObjectDecl + assertEquals(someObjDecl.b.getOtherThing(), 255); + assertEquals(getFieldB(someObjDecl).getOtherThing(), 255); + cls = someObjDecl.b; + assertTrue(someObjDecl.b == cls); + dyn = cls; + + cls.release(); + cls = null; + this.assertTrue(cls == null); + cls = dyn; + + assertEquals(cls.getOtherThing(), 255); + cls = null; + dyn = null; + dyn = cls; + assertTrue(dyn == null); + assertEquals(dyn,null); + assertTrue(dyn == cls); + assertEquals(dyn,cls); + cls.release(); + } + + static function getFieldB(d:{ a:Int, b: T }):T + return d.b; + + public function testNull() + { + this.assertTrue(TestClass.isNull(null)); + this.assertFalse(TestClass.isNull(TestClass.alloc().init())); + } + + public function testInterface() + { + cls = TestClass.alloc().init(); + cls.setOtherThing(21); + this.assertTrue(cls.getSelf() == cls); + this.assertEquals(cls.getSelf(), cls); + + var iface:TestInterface = cls; + var obj:Dynamic = iface; + this.assertTrue(iface == cls); + this.assertEquals(iface, cls); + this.assertTrue(obj == cls); + this.assertEquals(obj, cls); + this.assertEquals(iface.getSelf(), cls); + this.assertEquals(iface.getSelf(), cls.getSelf()); + + this.assertEquals(iface.getOtherThing(), 21); + this.assertEquals(iface.getOtherThingChar(), 21); + cls.setOtherThing(100); + this.assertEquals(iface.getOtherThing(), 100); + this.assertEquals(iface.getOtherThingChar(), 100); + + this.assertEquals("someOptionalMethod!",iface.someOptionalMethod()); + + cls.release(); + } +} + +@:include("./native/include/test.h") +@:objc extern interface TestInterface +{ + function getSelf():TestInterface; + function getOtherThing():Int; + function getOtherThingChar():cpp.Int8; + + @:optional function someOptionalMethod():NSString; + @:optional function unimplementedOptional():NSString; +} + +@:include("./native/include/test.h") +@:sourceFile("./native/test.m") +@:objc extern class TestClass implements TestInterface +{ + static function aStatic():Int; + static function isNull(t:TestClass):Bool; + + static function alloc():TestClass; + function init():TestClass; + + var something(get,set):NSString; + var otherThing:Int; + + @:native("something") private function get_something():NSString; + @:native("setSomething") private function set_something(value:NSString):NSString; + + function setOtherThing(value:Int):Void; + function getOtherThing():Int; + function getOtherThingChar():cpp.Int8; + function addHello(str:NSString):NSString; + @:native("addHello:andString") function addHelloAndString(str:NSString, str2:NSString):NSString; + function addSomething(str:NSString):NSString; + function isBiggerThan10(value:NSNumber):Bool; + function isBiggerThan10Num(value:NSNumber):NSNumber; + function isBiggerThan10Int(integer:Int):Bool; + + function release():Void; + function retainCount():Int; + + function getSelf():TestClass; + + function someOptionalMethod():NSString; + + @:deprecated('This method is not implemented on this class') + @:noCompletion @:optional function unimplementedOptional():NSString; + + @:plain static function some_c_call(t:TestClass):Int; + @:plain static function is_bigger_than_10(t:TestClass, val:Int):Bool; +} + +@:forward abstract NSString(_NSString) from _NSString to _NSString +{ + @:from @:extern inline public static function fromString(str:String):NSString + return _NSString.stringWithUTF8String(str); + + @:to @:extern inline public function toString():String + return this.UTF8String(); +} + +@:native("NSString") @:objc extern class _NSString +{ + static function stringWithUTF8String(str:cpp.CastCharStar):NSString; + + function UTF8String():cpp.ConstCharStar; +} + +@:forward abstract NSNumber(_NSNumber) from _NSNumber to _NSNumber +{ + @:from @:extern inline public static function fromInt(i:Int):NSNumber + return _NSNumber.numberWithInt(i); + + @:to @:extern inline public function toInt():Int + return this.intValue(); + + @:to @:extern inline public function toBool():Bool + return this.boolValue(); +} + +@:native("NSNumber") @:objc extern class _NSNumber +{ + static function numberWithInt(i:Int):NSNumber; + function intValue():Int; + function boolValue():Bool; +} diff --git a/tests/misc/cppObjc/build.hxml b/tests/misc/cppObjc/build.hxml new file mode 100644 index 00000000..b0946a22 --- /dev/null +++ b/tests/misc/cppObjc/build.hxml @@ -0,0 +1,4 @@ +-main TestObjc +-cpp bin +-debug +-D objc diff --git a/tests/misc/cppObjc/native/Makefile b/tests/misc/cppObjc/native/Makefile new file mode 100644 index 00000000..e7304967 --- /dev/null +++ b/tests/misc/cppObjc/native/Makefile @@ -0,0 +1,20 @@ +CC=clang + +SOURCES=$(wildcard *.m) +OBJECTS=$(SOURCES:.m=.o) + +libtest.a : $(OBJECTS) + $(AR) rcs libtest.a $(OBJECTS) + ranlib libtest.a + +%.c.o : %.c $(C_DEPS) + $(VERBOSE)$(CC) $(ALL_CFLAGS) -o $@ -c $< + +%.cpp.o : %.cpp $(C_DEPS) + $(VERBOSE)$(CXX) $(CXXFLAGS) -o $@ -c $< + +%.m.o : %.m $(C_DEPS) + $(VERBOSE)$(CXX) $(ALL_CFLAGS) -o $@ -c $< + +%.mm.o : %.mm $(C_DEPS) + $(VERBOSE)$(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/tests/misc/cppObjc/native/include/test.h b/tests/misc/cppObjc/native/include/test.h new file mode 100644 index 00000000..a02935b5 --- /dev/null +++ b/tests/misc/cppObjc/native/include/test.h @@ -0,0 +1,59 @@ +#ifndef TEST_H_INCLUDED +#define TEST_H_INCLUDED +#import + +@protocol TestInterface + +- (id )getSelf; + +- (int)getOtherThing; + +- (char)getOtherThingChar; + +@optional + +- (NSString *)someOptionalMethod; + +- (NSString *)unimplementedOptional; + +@end + +@interface TestClass : NSObject { + @public int otherThing; +} + +@property (retain) NSString *something; + ++ (int)aStatic; + ++ (BOOL)isNull:(TestClass *)t; + +- (void)setOtherThing:(int) value; + +- (int)getOtherThing; + +- (char)getOtherThingChar; + +- (NSString *)addHello:(NSString *)str; + +- (NSString *)addHello:(NSString *)str andString:(NSString *) str2; + +- (NSString *)addSomething:(NSString *)str; + +- (BOOL)isBiggerThan10:(NSNumber *)value; + +- (NSNumber *)isBiggerThan10Num:(NSNumber *)value; + +- (BOOL)isBiggerThan10Int:(int)integer; + +- (TestClass *)getSelf; + +- (NSString *)someOptionalMethod; + + +@end + +int some_c_call(TestClass *t); + +BOOL is_bigger_than_10(TestClass *t, int val); +#endif diff --git a/tests/misc/cppObjc/native/test.m b/tests/misc/cppObjc/native/test.m new file mode 100644 index 00000000..a1b71600 --- /dev/null +++ b/tests/misc/cppObjc/native/test.m @@ -0,0 +1,82 @@ +#import "include/test.h" + +@implementation TestClass + +@synthesize something = _something; + ++ (int)aStatic +{ + return 42; +} + ++ (BOOL)isNull:(TestClass *)t +{ + return t == nil; +} + +- (void)setOtherThing:(int) value +{ + self->otherThing = value; +} + +- (int)getOtherThing +{ + return self->otherThing; +} + +- (char)getOtherThingChar +{ + return (char) self->otherThing; +} + +- (NSString *)addHello:(NSString *)str +{ + return [@"Hello, " stringByAppendingString: str]; +} + +- (NSString *)addHello:(NSString *)str andString:(NSString *) str2 +{ + return [[@"Hello, " stringByAppendingString: str] stringByAppendingString: str2]; +} + +- (NSString *)addSomething:(NSString *)str +{ + return [str stringByAppendingString: self->_something]; +} + +- (BOOL)isBiggerThan10:(NSNumber *)value +{ + return [value doubleValue] > 10; +} + +- (NSNumber *)isBiggerThan10Num:(NSNumber *)value +{ + return [NSNumber numberWithBool:[value doubleValue] > 10]; +} + +- (BOOL)isBiggerThan10Int:(int)integer +{ + return integer > 10; +} + +- (TestClass *)getSelf +{ + return self; +} + +- (NSString *)someOptionalMethod +{ + return @"someOptionalMethod!"; +} + +@end + +int some_c_call(TestClass *t) +{ + return [t getOtherThing] + 10; +} + +BOOL is_bigger_than_10(TestClass *t, int val) +{ + return [t isBiggerThan10Int: val]; +} diff --git a/tests/misc/eventLoop/Main.hx b/tests/misc/eventLoop/Main.hx new file mode 100644 index 00000000..bc184e53 --- /dev/null +++ b/tests/misc/eventLoop/Main.hx @@ -0,0 +1,57 @@ +class Main { + + static function main() { + var event : haxe.MainLoop.MainEvent = null; + var count = 0; + event = haxe.MainLoop.add(function() { + trace(count++); + if( count == 10 ) { + event.stop(); + trace(haxe.MainLoop.hasEvents()); + } + }); + + #if sys + // if we don't use native timer, this should execute before + var t = new haxe.Timer(100); + t.run = function() { + trace("BEFORE1"); + t.stop(); + }; + #end + + var t = new haxe.Timer(200); + var count = 0; + t.run = function() { + trace("T" + count++); + if( count == 5 ) + t.stop(); + }; + + #if sys + // if we don't use native timer, this should execute before + var t = new haxe.Timer(100); + t.run = function() { + trace("BEFORE2"); + t.stop(); + }; + #end + + #if sys + Sys.sleep(0.3); + #end + + haxe.MainLoop.addThread(function() { + var event : haxe.MainLoop.MainEvent = null; + var count = 0; + event = haxe.MainLoop.add(function() { + trace(String.fromCharCode("A".code + count++)); + if( count == 5 ) event.stop(); + }); + #if sys + Sys.sleep(3); + #end + }); + } + +} \ No newline at end of file diff --git a/tests/misc/eventLoop/all.hxml b/tests/misc/eventLoop/all.hxml new file mode 100644 index 00000000..0184c54b --- /dev/null +++ b/tests/misc/eventLoop/all.hxml @@ -0,0 +1,19 @@ +-main Main +-dce full +--each +-swf eventLoop.swf +-swf-version 14 +--next +-neko eventLoop.n +--next +-js eventLoop.js +--next +-python eventLoop.py +--next +-php php +--next +-java java +--next +-cs cs +--next +-cpp cpp diff --git a/extra/haxelib_src/src/tools/legacyhaxelib/haxelib.hxproj b/tests/misc/eventLoop/eventLoop.hxproj similarity index 72% rename from extra/haxelib_src/src/tools/legacyhaxelib/haxelib.hxproj rename to tests/misc/eventLoop/eventLoop.hxproj index 93e9bb6d..fd694b4e 100644 --- a/extra/haxelib_src/src/tools/legacyhaxelib/haxelib.hxproj +++ b/tests/misc/eventLoop/eventLoop.hxproj @@ -1,52 +1,57 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - haxe haxelib.hxml - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + haxe all.hxml + + + + + + + \ No newline at end of file diff --git a/tests/misc/eventLoop/test.html b/tests/misc/eventLoop/test.html new file mode 100644 index 00000000..24eb5ab2 --- /dev/null +++ b/tests/misc/eventLoop/test.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/misc/projects/Issue1138/compile1.hxml b/tests/misc/projects/Issue1138/compile1.hxml new file mode 100644 index 00000000..0e04fcc0 --- /dev/null +++ b/tests/misc/projects/Issue1138/compile1.hxml @@ -0,0 +1,4 @@ +-cp src1 +-cp src2 +-main C +--interp diff --git a/tests/misc/projects/Issue1138/compile1.hxml.stderr b/tests/misc/projects/Issue1138/compile1.hxml.stderr new file mode 100644 index 00000000..b26d3770 --- /dev/null +++ b/tests/misc/projects/Issue1138/compile1.hxml.stderr @@ -0,0 +1 @@ +some1some2 \ No newline at end of file diff --git a/tests/misc/projects/Issue1138/compile2.hxml b/tests/misc/projects/Issue1138/compile2.hxml new file mode 100644 index 00000000..603d3b5d --- /dev/null +++ b/tests/misc/projects/Issue1138/compile2.hxml @@ -0,0 +1,4 @@ +-cp src1 +-cp src2 +-main p2.C2 +--interp diff --git a/tests/misc/projects/Issue1138/compile2.hxml.stderr b/tests/misc/projects/Issue1138/compile2.hxml.stderr new file mode 100644 index 00000000..ea59fac9 --- /dev/null +++ b/tests/misc/projects/Issue1138/compile2.hxml.stderr @@ -0,0 +1 @@ +some1some23 \ No newline at end of file diff --git a/tests/misc/projects/Issue1138/compile3-fail.hxml b/tests/misc/projects/Issue1138/compile3-fail.hxml new file mode 100644 index 00000000..136153c6 --- /dev/null +++ b/tests/misc/projects/Issue1138/compile3-fail.hxml @@ -0,0 +1,4 @@ +-cp src1 +-cp src2 +-main D +--interp diff --git a/tests/misc/projects/Issue1138/compile3-fail.hxml.stderr b/tests/misc/projects/Issue1138/compile3-fail.hxml.stderr new file mode 100644 index 00000000..dae048be --- /dev/null +++ b/tests/misc/projects/Issue1138/compile3-fail.hxml.stderr @@ -0,0 +1 @@ +src1/D.hx:3: characters 8-16 : Int has no field triple diff --git a/tests/misc/projects/Issue1138/compile4-fail.hxml b/tests/misc/projects/Issue1138/compile4-fail.hxml new file mode 100644 index 00000000..95b848b0 --- /dev/null +++ b/tests/misc/projects/Issue1138/compile4-fail.hxml @@ -0,0 +1,3 @@ +-cp src3 +-main Main +--interp diff --git a/tests/misc/projects/Issue1138/compile4-fail.hxml.stderr b/tests/misc/projects/Issue1138/compile4-fail.hxml.stderr new file mode 100644 index 00000000..87b99dd5 --- /dev/null +++ b/tests/misc/projects/Issue1138/compile4-fail.hxml.stderr @@ -0,0 +1 @@ +$$normPath(::cwd::/src3/import.hx):1: characters 0-14 : Only import and using is allowed in import.hx files \ No newline at end of file diff --git a/tests/misc/projects/Issue1138/src1/C.hx b/tests/misc/projects/Issue1138/src1/C.hx new file mode 100644 index 00000000..92085e31 --- /dev/null +++ b/tests/misc/projects/Issue1138/src1/C.hx @@ -0,0 +1,7 @@ +class C { + static function main() { + var err = Sys.stderr(); + err.writeString(A.some); + err.writeString(getSome()); + } +} diff --git a/tests/misc/projects/Issue1138/src1/D.hx b/tests/misc/projects/Issue1138/src1/D.hx new file mode 100644 index 00000000..a995e6f2 --- /dev/null +++ b/tests/misc/projects/Issue1138/src1/D.hx @@ -0,0 +1,5 @@ +class D { + static function main() { + 1.triple(); + } +} diff --git a/tests/misc/projects/Issue1138/src1/import.hx b/tests/misc/projects/Issue1138/src1/import.hx new file mode 100644 index 00000000..869928b0 --- /dev/null +++ b/tests/misc/projects/Issue1138/src1/import.hx @@ -0,0 +1,2 @@ +import p2.A; +import p2.A.getSome; diff --git a/tests/misc/projects/Issue1138/src1/p2/C2.hx b/tests/misc/projects/Issue1138/src1/p2/C2.hx new file mode 100644 index 00000000..8da1e289 --- /dev/null +++ b/tests/misc/projects/Issue1138/src1/p2/C2.hx @@ -0,0 +1,10 @@ +package p2; + +class C2 { + static function main() { + var err = Sys.stderr(); + err.writeString(A.some); + err.writeString(getSome()); + err.writeString(Std.string(1.triple())); + } +} diff --git a/tests/misc/projects/Issue1138/src1/p2/import.hx b/tests/misc/projects/Issue1138/src1/p2/import.hx new file mode 100644 index 00000000..dea5c6fb --- /dev/null +++ b/tests/misc/projects/Issue1138/src1/p2/import.hx @@ -0,0 +1 @@ +using B; diff --git a/tests/misc/projects/Issue1138/src2/B.hx b/tests/misc/projects/Issue1138/src2/B.hx new file mode 100644 index 00000000..75a26a7b --- /dev/null +++ b/tests/misc/projects/Issue1138/src2/B.hx @@ -0,0 +1,3 @@ +class B { + public static function triple(v:Int):Int return v * 3; +} \ No newline at end of file diff --git a/tests/misc/projects/Issue1138/src2/import.hx b/tests/misc/projects/Issue1138/src2/import.hx new file mode 100644 index 00000000..dea5c6fb --- /dev/null +++ b/tests/misc/projects/Issue1138/src2/import.hx @@ -0,0 +1 @@ +using B; diff --git a/tests/misc/projects/Issue1138/src2/p2/A.hx b/tests/misc/projects/Issue1138/src2/p2/A.hx new file mode 100644 index 00000000..1379bdcb --- /dev/null +++ b/tests/misc/projects/Issue1138/src2/p2/A.hx @@ -0,0 +1,8 @@ +package p2; + +class A { + public static var some = "some1"; + public static function getSome() { + return "some2"; + } +} diff --git a/tests/misc/projects/Issue1138/src3/Main.hx b/tests/misc/projects/Issue1138/src3/Main.hx new file mode 100644 index 00000000..b829491a --- /dev/null +++ b/tests/misc/projects/Issue1138/src3/Main.hx @@ -0,0 +1,3 @@ +class Main { + static function main() {} +} \ No newline at end of file diff --git a/tests/misc/projects/Issue1138/src3/import.hx b/tests/misc/projects/Issue1138/src3/import.hx new file mode 100644 index 00000000..283229ff --- /dev/null +++ b/tests/misc/projects/Issue1138/src3/import.hx @@ -0,0 +1 @@ +typedef A = {} diff --git a/tests/misc/projects/Issue1310/Main1.hx b/tests/misc/projects/Issue1310/Main1.hx new file mode 100644 index 00000000..a82760e6 --- /dev/null +++ b/tests/misc/projects/Issue1310/Main1.hx @@ -0,0 +1,20 @@ +enum ToString { + ToString(s:S, f:S->String); +} + +class Main1 { + static function main () { + var d1 = ToString(5, function (i:Int) return "" + i); + var d2 = ToString("bar", function (i:String) return i); + toString(d1); + toString(d2); + } + + public static function toString(x:ToString) { + switch (x) { + case ToString(a,f): + // at this point, we don't know the type of a and the parameter type of f, but we know that they are the same type and cannot be used with other types. + trace(f([1,2])); // shouldn't work here + } + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue1310/compile1-fail.hxml b/tests/misc/projects/Issue1310/compile1-fail.hxml new file mode 100644 index 00000000..d7a4672b --- /dev/null +++ b/tests/misc/projects/Issue1310/compile1-fail.hxml @@ -0,0 +1,2 @@ +-main Main1 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue1310/compile1-fail.hxml.stderr b/tests/misc/projects/Issue1310/compile1-fail.hxml.stderr new file mode 100644 index 00000000..de420f0b --- /dev/null +++ b/tests/misc/projects/Issue1310/compile1-fail.hxml.stderr @@ -0,0 +1,2 @@ +Main1.hx:17: characters 12-17 : Array should be ToString.S +Main1.hx:17: characters 12-17 : For function argument '' \ No newline at end of file diff --git a/tests/misc/projects/Issue1968/compile.hxml b/tests/misc/projects/Issue1968/compile.hxml index 0c498e13..08e3c45a 100644 --- a/tests/misc/projects/Issue1968/compile.hxml +++ b/tests/misc/projects/Issue1968/compile.hxml @@ -1 +1 @@ ---display Main.hx@147@position \ No newline at end of file +--display Main.hx@146@position \ No newline at end of file diff --git a/tests/misc/projects/Issue1968/compile.hxml.stderr b/tests/misc/projects/Issue1968/compile.hxml.stderr index 330ae3e7..d9eadf24 100644 --- a/tests/misc/projects/Issue1968/compile.hxml.stderr +++ b/tests/misc/projects/Issue1968/compile.hxml.stderr @@ -1,3 +1,3 @@ -$$normPath(::cwd::/Main.hx):4: characters 18-61 +$$normPath(::cwd::/Main.hx, true):4: characters 18-61 diff --git a/tests/misc/projects/Issue2087/Main.hx b/tests/misc/projects/Issue2087/Main.hx new file mode 100644 index 00000000..fd3396dc --- /dev/null +++ b/tests/misc/projects/Issue2087/Main.hx @@ -0,0 +1,5 @@ +class Main { + static function main() { + haxe.Resauce; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue3782/compile-fail.hxml b/tests/misc/projects/Issue2087/compile-fail.hxml similarity index 100% rename from tests/misc/projects/Issue3782/compile-fail.hxml rename to tests/misc/projects/Issue2087/compile-fail.hxml diff --git a/tests/misc/projects/Issue2087/compile-fail.hxml.stderr b/tests/misc/projects/Issue2087/compile-fail.hxml.stderr new file mode 100644 index 00000000..d3372a82 --- /dev/null +++ b/tests/misc/projects/Issue2087/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:3: characters 2-6 : Type not found : haxe.Resauce \ No newline at end of file diff --git a/tests/misc/projects/Issue2148/Main1.hx b/tests/misc/projects/Issue2148/Main1.hx new file mode 100644 index 00000000..c98e5f64 --- /dev/null +++ b/tests/misc/projects/Issue2148/Main1.hx @@ -0,0 +1,11 @@ +enum E { + CTor(i:Int); +} + +class Main { + static public function main() { + expectE(CTor(foo)); + } + + static function expectE(e:E) { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue2148/compile1-fail.hxml b/tests/misc/projects/Issue2148/compile1-fail.hxml new file mode 100644 index 00000000..d7a4672b --- /dev/null +++ b/tests/misc/projects/Issue2148/compile1-fail.hxml @@ -0,0 +1,2 @@ +-main Main1 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue2148/compile1-fail.hxml.stderr b/tests/misc/projects/Issue2148/compile1-fail.hxml.stderr new file mode 100644 index 00000000..74ad2257 --- /dev/null +++ b/tests/misc/projects/Issue2148/compile1-fail.hxml.stderr @@ -0,0 +1,2 @@ +Main1.hx:7: characters 21-24 : Unknown identifier : foo +Main1.hx:7: characters 21-24 : For function argument 'i' \ No newline at end of file diff --git a/tests/misc/projects/Issue2232/Main1.hx b/tests/misc/projects/Issue2232/Main1.hx new file mode 100644 index 00000000..3dd6ff26 --- /dev/null +++ b/tests/misc/projects/Issue2232/Main1.hx @@ -0,0 +1,8 @@ +class Main1 { + static function main() { + var v : Float = 0; + foo(v,v); + } + + static function foo(x=0,y=0) { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue2232/Main2.hx b/tests/misc/projects/Issue2232/Main2.hx new file mode 100644 index 00000000..60bc2cda --- /dev/null +++ b/tests/misc/projects/Issue2232/Main2.hx @@ -0,0 +1,8 @@ +class Main1 { + static function main() { + var v : Float = 0; + foo(v); + } + + static function foo(x=0,y:Float) { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue2232/compile1-fail.hxml b/tests/misc/projects/Issue2232/compile1-fail.hxml new file mode 100644 index 00000000..ccbedd46 --- /dev/null +++ b/tests/misc/projects/Issue2232/compile1-fail.hxml @@ -0,0 +1,3 @@ +-main Main1 +-swf swf.swf +--no-output \ No newline at end of file diff --git a/tests/misc/projects/Issue2232/compile1-fail.hxml.stderr b/tests/misc/projects/Issue2232/compile1-fail.hxml.stderr new file mode 100644 index 00000000..5285260e --- /dev/null +++ b/tests/misc/projects/Issue2232/compile1-fail.hxml.stderr @@ -0,0 +1,2 @@ +Main1.hx:4: characters 6-7 : Float should be Int +Main1.hx:4: characters 6-7 : For optional function argument 'x' \ No newline at end of file diff --git a/tests/misc/projects/Issue2232/compile2-fail.hxml b/tests/misc/projects/Issue2232/compile2-fail.hxml new file mode 100644 index 00000000..d12504ea --- /dev/null +++ b/tests/misc/projects/Issue2232/compile2-fail.hxml @@ -0,0 +1,3 @@ +-main Main2 +-swf swf.swf +--no-output \ No newline at end of file diff --git a/tests/misc/projects/Issue2232/compile2-fail.hxml.stderr b/tests/misc/projects/Issue2232/compile2-fail.hxml.stderr new file mode 100644 index 00000000..3ac7007e --- /dev/null +++ b/tests/misc/projects/Issue2232/compile2-fail.hxml.stderr @@ -0,0 +1 @@ +Main2.hx:4: characters 2-8 : Cannot skip non-nullable argument x \ No newline at end of file diff --git a/tests/misc/projects/Issue2263/import-completion.hxml.stderr b/tests/misc/projects/Issue2263/import-completion.hxml.stderr index 9ba95f2d..36136727 100644 --- a/tests/misc/projects/Issue2263/import-completion.hxml.stderr +++ b/tests/misc/projects/Issue2263/import-completion.hxml.stderr @@ -1,6 +1,6 @@ -Int -Void -> Void - - +Int +Void -> Void + + diff --git a/tests/misc/projects/Issue2263/subtype-static-completion.hxml.stderr b/tests/misc/projects/Issue2263/subtype-static-completion.hxml.stderr index 48b0ea14..fef24645 100644 --- a/tests/misc/projects/Issue2263/subtype-static-completion.hxml.stderr +++ b/tests/misc/projects/Issue2263/subtype-static-completion.hxml.stderr @@ -1,4 +1,4 @@ -Int -Void -> Void +Int +Void -> Void diff --git a/tests/misc/projects/Issue2263/type-completion.hxml.stderr b/tests/misc/projects/Issue2263/type-completion.hxml.stderr index 33a46cc1..5fd27778 100644 --- a/tests/misc/projects/Issue2263/type-completion.hxml.stderr +++ b/tests/misc/projects/Issue2263/type-completion.hxml.stderr @@ -1,4 +1,4 @@ - - + + diff --git a/tests/misc/projects/Issue2278/Macro.hx b/tests/misc/projects/Issue2278/Macro.hx new file mode 100644 index 00000000..c1f0fba3 --- /dev/null +++ b/tests/misc/projects/Issue2278/Macro.hx @@ -0,0 +1,21 @@ +import haxe.macro.Expr; +import haxe.macro.Context; + +class Macro { + macro static public function call(efun:ExprOfInt>, eval:Expr):Expr { + var vfun = Context.eval(efun); + var vval = Context.eval(eval); + var r = vfun(vval); + return macro $v{r}; + } + + macro static public function call2(efun:Int->Int, eval:Int):Expr { + var r = efun(eval); + return macro $v{r}; + } + + macro static public function call3(efun:Int->Int, eval:Expr):Expr { + var r = efun(Context.eval(eval)); + return macro $v{r}; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue2278/Main.hx b/tests/misc/projects/Issue2278/Main.hx new file mode 100644 index 00000000..960ea266 --- /dev/null +++ b/tests/misc/projects/Issue2278/Main.hx @@ -0,0 +1,19 @@ +using Macro; + +class Main { + static function main() { + write(Macro.call(function(x) return x * 3, 3)); + write(Macro.call(MyTools.double, 3)); + write(MyTools.double.call(3)); + write(Macro.call(MyTools.double, Macro.call(MyTools.double, 3))); + + write(Macro.call2(function(x) return x * 3, 3)); + write(Macro.call2(MyTools.double, 3)); + write(MyTools.double.call2(3)); + write(Macro.call3(MyTools.double, Macro.call(MyTools.double, 3))); + } + + static function write(i:Int) { + Sys.stderr().writeString(i + "\n"); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue2278/MyTools.hx b/tests/misc/projects/Issue2278/MyTools.hx new file mode 100644 index 00000000..4794255e --- /dev/null +++ b/tests/misc/projects/Issue2278/MyTools.hx @@ -0,0 +1,5 @@ +class MyTools { + static public function double(x:Int) { + return x * 2; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue2278/compile.hxml.disabled b/tests/misc/projects/Issue2278/compile.hxml.disabled new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue2278/compile.hxml.disabled @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue2278/compile.hxml.stderr b/tests/misc/projects/Issue2278/compile.hxml.stderr new file mode 100644 index 00000000..07b92d48 --- /dev/null +++ b/tests/misc/projects/Issue2278/compile.hxml.stderr @@ -0,0 +1,8 @@ +9 +6 +6 +12 +9 +6 +6 +12 \ No newline at end of file diff --git a/tests/misc/projects/Issue2508/Main.hx b/tests/misc/projects/Issue2508/Main.hx new file mode 100644 index 00000000..f2567c27 --- /dev/null +++ b/tests/misc/projects/Issue2508/Main.hx @@ -0,0 +1,70 @@ +enum Tree { + Leaf(t:T); + Node(l:Tree, r:Tree); +} + +class Main { + static function main() { + + } + + function testRedundance() { + switch(true) { + case false: + case true: + case false: // unused + } + + switch(true) { + case false | true: + case true: // unused + case false: // unused + } + + switch(true) { + case false + | false: // unused + case true: + } + + switch(Leaf("foo")) { + case Leaf(_) + | Leaf("foo"): // unused + case Node(l,r): + } + + switch({s:"foo"}) { + case { s : "foo" } : + case { s : a } : + } + + switch( { s:"foo", t:"bar" } ) { + case { s : "foo" }: + case { t : "bar" }: + case { s : "foo", t:"bar" }: // unused + case _: + } + + switch ("foo") { + case "foo": + case x = "foo": // unused + } + + switch ("foo") { + case x = "foo": + case "foo": // unused + } + + switch [true] { + case [true]: + case [true]: // unused + case [false]: + } + + switch [true] { + case [true] + | [true]: // unused + case [false]: + } + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue2508/compile.hxml b/tests/misc/projects/Issue2508/compile.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue2508/compile.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue2508/compile.hxml.stderr b/tests/misc/projects/Issue2508/compile.hxml.stderr new file mode 100644 index 00000000..3ed1959d --- /dev/null +++ b/tests/misc/projects/Issue2508/compile.hxml.stderr @@ -0,0 +1,10 @@ +Main.hx:15: characters 3-13 : Warning : This case is unused +Main.hx:20: characters 3-12 : Warning : This case is unused +Main.hx:21: characters 3-13 : Warning : This case is unused +Main.hx:26: characters 5-10 : Warning : This pattern is unused +Main.hx:32: characters 6-17 : Warning : This pattern is unused +Main.hx:44: characters 3-30 : Warning : This case is unused +Main.hx:50: characters 3-17 : Warning : This case is unused +Main.hx:55: characters 3-13 : Warning : This case is unused +Main.hx:60: characters 3-14 : Warning : This case is unused +Main.hx:66: characters 8-14 : Warning : This pattern is unused \ No newline at end of file diff --git a/tests/misc/projects/Issue2538/Main.hx b/tests/misc/projects/Issue2538/Main.hx new file mode 100644 index 00000000..05bbf02f --- /dev/null +++ b/tests/misc/projects/Issue2538/Main.hx @@ -0,0 +1,18 @@ +import haxe.ds.Option; + +class Main { + static function main(){ + function foo():Bool { return true; } + map(function(num:Int):Void { + if(foo()) 10; //VerifyError: Error #1030: Stack depth is unbalanced. 2 != 1. + //if(true) 10; //works + }); + } + inline //removing inline fixes. + public static function map(f:T->K):Void { + switch (None) { + case Some(t): Some(f(t)); + case None: None; + } + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue2538/compile-fail.hxml b/tests/misc/projects/Issue2538/compile-fail.hxml new file mode 100644 index 00000000..454d4728 --- /dev/null +++ b/tests/misc/projects/Issue2538/compile-fail.hxml @@ -0,0 +1,3 @@ +-main Main +-neko neko.n +--no-output \ No newline at end of file diff --git a/tests/misc/projects/Issue2538/compile-fail.hxml.stderr b/tests/misc/projects/Issue2538/compile-fail.hxml.stderr new file mode 100644 index 00000000..5eefe10a --- /dev/null +++ b/tests/misc/projects/Issue2538/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:7: characters 12-24 : Cannot use Void as value \ No newline at end of file diff --git a/tests/misc/projects/Issue2991/compile.hxml b/tests/misc/projects/Issue2991/compile.hxml index 3012f724..301eeac5 100644 --- a/tests/misc/projects/Issue2991/compile.hxml +++ b/tests/misc/projects/Issue2991/compile.hxml @@ -1 +1 @@ ---display Main.hx@115@position \ No newline at end of file +--display Main.hx@114@position \ No newline at end of file diff --git a/tests/misc/projects/Issue2991/compile.hxml.stderr b/tests/misc/projects/Issue2991/compile.hxml.stderr index 7585829e..3189760b 100644 --- a/tests/misc/projects/Issue2991/compile.hxml.stderr +++ b/tests/misc/projects/Issue2991/compile.hxml.stderr @@ -1,3 +1,3 @@ -$$normPath(::cwd::/Main.hx):6: characters 8-24 +$$normPath(::cwd::/Main.hx, true):6: characters 12-13 diff --git a/tests/misc/projects/Issue2993/compile.hxml b/tests/misc/projects/Issue2993/compile.hxml index 30889bf9..c38bf787 100644 --- a/tests/misc/projects/Issue2993/compile.hxml +++ b/tests/misc/projects/Issue2993/compile.hxml @@ -1 +1 @@ ---display Main.hx@76@position \ No newline at end of file +--display Main.hx@75@position \ No newline at end of file diff --git a/tests/misc/projects/Issue2993/compile.hxml.stderr b/tests/misc/projects/Issue2993/compile.hxml.stderr index bf46feec..e8a83b74 100644 --- a/tests/misc/projects/Issue2993/compile.hxml.stderr +++ b/tests/misc/projects/Issue2993/compile.hxml.stderr @@ -1,3 +1,3 @@ -$$normPath(::cwd::/Main.hx):2: lines 2-5 +$$normPath(::cwd::/Main.hx, true):2: characters 15-18 diff --git a/tests/misc/projects/Issue2995/position.hxml b/tests/misc/projects/Issue2995/position.hxml index 2dde3147..24a26538 100644 --- a/tests/misc/projects/Issue2995/position.hxml +++ b/tests/misc/projects/Issue2995/position.hxml @@ -1 +1 @@ ---display Main.hx@92@position \ No newline at end of file +--display Main.hx@91@position \ No newline at end of file diff --git a/tests/misc/projects/Issue2995/position.hxml.stderr b/tests/misc/projects/Issue2995/position.hxml.stderr index 40bde336..80b60c85 100644 --- a/tests/misc/projects/Issue2995/position.hxml.stderr +++ b/tests/misc/projects/Issue2995/position.hxml.stderr @@ -1,3 +1,3 @@ -$$normPath(::cwd::/Main.hx):2: characters 4-21 +$$normPath(::cwd::/Main.hx, true):2: characters 4-21 diff --git a/tests/misc/projects/Issue2995/usage.hxml b/tests/misc/projects/Issue2995/usage.hxml index 55831975..272d80f0 100644 --- a/tests/misc/projects/Issue2995/usage.hxml +++ b/tests/misc/projects/Issue2995/usage.hxml @@ -1 +1 @@ ---display Main.hx@92@usage \ No newline at end of file +--display Main.hx@91@usage \ No newline at end of file diff --git a/tests/misc/projects/Issue2995/usage.hxml.stderr b/tests/misc/projects/Issue2995/usage.hxml.stderr index 0e1ce6aa..48f99fff 100644 --- a/tests/misc/projects/Issue2995/usage.hxml.stderr +++ b/tests/misc/projects/Issue2995/usage.hxml.stderr @@ -1,4 +1,4 @@ -$$normPath(::cwd::/Main.hx):5: characters 16-26 -$$normPath(::cwd::/Main.hx):9: characters 8-18 +$$normPath(::cwd::/Main.hx, true):5: characters 16-26 +$$normPath(::cwd::/Main.hx, true):9: characters 8-18 diff --git a/tests/misc/projects/Issue2996/compile1.hxml.stderr b/tests/misc/projects/Issue2996/compile1.hxml.stderr index f6eb1a1d..e6d3abae 100644 --- a/tests/misc/projects/Issue2996/compile1.hxml.stderr +++ b/tests/misc/projects/Issue2996/compile1.hxml.stderr @@ -1,3 +1,3 @@ -$$normPath(::cwd::/A.hx):1: characters 0-8 +$$normPath(::cwd::/A.hx, true):1: characters 0-21 \ No newline at end of file diff --git a/tests/misc/projects/Issue2996/compile2.hxml.stderr b/tests/misc/projects/Issue2996/compile2.hxml.stderr index ffa975f2..7a9269e4 100644 --- a/tests/misc/projects/Issue2996/compile2.hxml.stderr +++ b/tests/misc/projects/Issue2996/compile2.hxml.stderr @@ -1,3 +1,3 @@ -$$normPath(::cwd::/pack/B.hx):3: characters 0-5 +$$normPath(::cwd::/pack/B.hx, true):3: characters 0-10 diff --git a/tests/misc/projects/Issue2997/Main.hx b/tests/misc/projects/Issue2997/Main.hx new file mode 100644 index 00000000..7f71b9db --- /dev/null +++ b/tests/misc/projects/Issue2997/Main.hx @@ -0,0 +1,12 @@ +@:enum abstract MyEnum(Int) { + var A = 1; + var B = 2; + var C = 3; +} + +class Main { + static function main() { + var a = A; + var b = MyEnum.B; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue2997/compile1.hxml b/tests/misc/projects/Issue2997/compile1.hxml new file mode 100644 index 00000000..af6028cf --- /dev/null +++ b/tests/misc/projects/Issue2997/compile1.hxml @@ -0,0 +1 @@ +--display Main.hx@136@position \ No newline at end of file diff --git a/tests/misc/projects/Issue2997/compile1.hxml.stderr b/tests/misc/projects/Issue2997/compile1.hxml.stderr new file mode 100644 index 00000000..5bebd1d2 --- /dev/null +++ b/tests/misc/projects/Issue2997/compile1.hxml.stderr @@ -0,0 +1,3 @@ + +$$normPath(::cwd::/Main.hx, true):2: characters 4-14 + \ No newline at end of file diff --git a/tests/misc/projects/Issue3192/Main1.hx b/tests/misc/projects/Issue3192/Main1.hx new file mode 100644 index 00000000..3dd9fe55 --- /dev/null +++ b/tests/misc/projects/Issue3192/Main1.hx @@ -0,0 +1,5 @@ +class Main { + static function main() { + var a:{a:Int} = { a: 1, b: 2 }; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue3192/compile1-fail.hxml b/tests/misc/projects/Issue3192/compile1-fail.hxml new file mode 100644 index 00000000..d7a4672b --- /dev/null +++ b/tests/misc/projects/Issue3192/compile1-fail.hxml @@ -0,0 +1,2 @@ +-main Main1 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue3192/compile1-fail.hxml.stderr b/tests/misc/projects/Issue3192/compile1-fail.hxml.stderr new file mode 100644 index 00000000..b5b1cdce --- /dev/null +++ b/tests/misc/projects/Issue3192/compile1-fail.hxml.stderr @@ -0,0 +1,3 @@ +Main1.hx:3: characters 18-32 : { b : Int, a : Int } has extra field b +Main1.hx:3: characters 2-33 : { b : Int, a : Int } should be { a : Int } +Main1.hx:3: characters 2-33 : { b : Int, a : Int } has extra field b \ No newline at end of file diff --git a/tests/misc/projects/Issue3238/default-value-fail.hxml.stderr b/tests/misc/projects/Issue3238/default-value-fail.hxml.stderr index e266668c..1634feb4 100644 --- a/tests/misc/projects/Issue3238/default-value-fail.hxml.stderr +++ b/tests/misc/projects/Issue3238/default-value-fail.hxml.stderr @@ -1 +1 @@ -DefaultValue.hx:2: characters 4-55 : Rest argument cannot have default value +DefaultValue.hx:2: characters 44-48 : Rest argument cannot have default value diff --git a/tests/misc/projects/Issue3238/non-extern-fail.hxml.stderr b/tests/misc/projects/Issue3238/non-extern-fail.hxml.stderr index 01bb3a6b..ee387e25 100644 --- a/tests/misc/projects/Issue3238/non-extern-fail.hxml.stderr +++ b/tests/misc/projects/Issue3238/non-extern-fail.hxml.stderr @@ -1 +1 @@ -NonExtern.hx:2: characters 11-57 : Rest argument are only supported for extern methods +NonExtern.hx:2: characters 22-23 : Rest argument are only supported for extern methods diff --git a/tests/misc/projects/Issue3238/not-last-fail.hxml.stderr b/tests/misc/projects/Issue3238/not-last-fail.hxml.stderr index 9de85896..8b8ec7dd 100644 --- a/tests/misc/projects/Issue3238/not-last-fail.hxml.stderr +++ b/tests/misc/projects/Issue3238/not-last-fail.hxml.stderr @@ -1 +1 @@ -NotLast.hx:2: characters 4-58 : Rest should only be used for the last function argument +NotLast.hx:2: characters 15-16 : Rest should only be used for the last function argument diff --git a/tests/misc/projects/Issue3238/optional-fail.hxml.stderr b/tests/misc/projects/Issue3238/optional-fail.hxml.stderr index 4fc1cf87..e293759b 100644 --- a/tests/misc/projects/Issue3238/optional-fail.hxml.stderr +++ b/tests/misc/projects/Issue3238/optional-fail.hxml.stderr @@ -1 +1 @@ -Optional.hx:2: characters 4-49 : Rest argument cannot be optional +Optional.hx:2: characters 16-17 : Rest argument cannot be optional diff --git a/tests/misc/projects/Issue3298/Test.hx b/tests/misc/projects/Issue3298/Test.hx index 73065660..525260d6 100644 --- a/tests/misc/projects/Issue3298/Test.hx +++ b/tests/misc/projects/Issue3298/Test.hx @@ -6,8 +6,8 @@ class Test { static function main() { var proc = new sys.io.Process("haxe", ["--display", "Main.hx@38@toplevel"]); - var exit = proc.exitCode(); var stderr = proc.stderr.readAll().toString(); + var exit = proc.exitCode(); if (exit != 0) error(stderr, exit); else if (stderr.indexOf("") != 0) diff --git a/tests/misc/projects/Issue3310/Test.hx b/tests/misc/projects/Issue3310/Test.hx index 38c756dd..2b0ed960 100644 --- a/tests/misc/projects/Issue3310/Test.hx +++ b/tests/misc/projects/Issue3310/Test.hx @@ -6,8 +6,8 @@ class Test { static function main() { var proc = new sys.io.Process("haxe", ["--display", "Main.hx@62@toplevel"]); - var exit = proc.exitCode(); var stderr = proc.stderr.readAll().toString(); + var exit = proc.exitCode(); if (exit != 0) error(stderr, exit); else if (stderr.indexOf("") != 0) diff --git a/tests/misc/projects/Issue3361/compile1-fail.hxml.stderr b/tests/misc/projects/Issue3361/compile1-fail.hxml.stderr index 6e24c232..0d7e46bc 100644 --- a/tests/misc/projects/Issue3361/compile1-fail.hxml.stderr +++ b/tests/misc/projects/Issue3361/compile1-fail.hxml.stderr @@ -1,3 +1,4 @@ Main.hx:5: lines 5-8 : Field v has different type than in I +Main.hx:2: characters 8-28 : Interface field is defined here Main.hx:5: lines 5-8 : String -> Void should be Dynamic -> Void Main.hx:5: lines 5-8 : String should be Dynamic \ No newline at end of file diff --git a/tests/misc/projects/Issue3361/compile2-fail.hxml.stderr b/tests/misc/projects/Issue3361/compile2-fail.hxml.stderr index 9630a64c..6f008abb 100644 --- a/tests/misc/projects/Issue3361/compile2-fail.hxml.stderr +++ b/tests/misc/projects/Issue3361/compile2-fail.hxml.stderr @@ -1,3 +1,4 @@ Main2.hx:6: characters 16-45 : Field f has different type than in I +Main2.hx:2: characters 16-43 : Interface field is defined here Main2.hx:6: characters 16-45 : s : String -> Void should be d : Dynamic -> Void Main2.hx:6: characters 16-45 : String should be Dynamic \ No newline at end of file diff --git a/tests/misc/projects/Issue3417/compile-fail.hxml.stderr b/tests/misc/projects/Issue3417/compile-fail.hxml.stderr index 36280f54..03227aff 100644 --- a/tests/misc/projects/Issue3417/compile-fail.hxml.stderr +++ b/tests/misc/projects/Issue3417/compile-fail.hxml.stderr @@ -1,2 +1,3 @@ Main.hx:6: characters 11-26 : Field f has different type than in I -Main.hx:6: characters 11-26 : Different number of function arguments +Main.hx:2: characters 4-27 : Interface field is defined here +Main.hx:6: characters 11-26 : Different number of function arguments \ No newline at end of file diff --git a/tests/misc/projects/Issue3621/Main1.hx b/tests/misc/projects/Issue3621/Main1.hx new file mode 100644 index 00000000..3eb7380d --- /dev/null +++ b/tests/misc/projects/Issue3621/Main1.hx @@ -0,0 +1,16 @@ +@:native("lol") +@:enum extern abstract E(String) { + var A; + var B; + var C; +} + +class Main1 { + static var a:E; + static function main() { + switch (a) { + case A: trace("hello"); + case B: trace("yo"); + } + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue3621/compile-fail.hxml b/tests/misc/projects/Issue3621/compile-fail.hxml new file mode 100644 index 00000000..f3f58b6c --- /dev/null +++ b/tests/misc/projects/Issue3621/compile-fail.hxml @@ -0,0 +1,3 @@ +-main Main1 +--no-output +-js js.js \ No newline at end of file diff --git a/tests/misc/projects/Issue3621/compile-fail.hxml.stderr b/tests/misc/projects/Issue3621/compile-fail.hxml.stderr new file mode 100644 index 00000000..f736cdd0 --- /dev/null +++ b/tests/misc/projects/Issue3621/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main1.hx:11: characters 16-17 : Unmatched patterns: E.C \ No newline at end of file diff --git a/tests/misc/projects/Issue3710/compile-1-fail.hxml.stderr b/tests/misc/projects/Issue3710/compile-1-fail.hxml.stderr index 0708bb16..780277f3 100644 --- a/tests/misc/projects/Issue3710/compile-1-fail.hxml.stderr +++ b/tests/misc/projects/Issue3710/compile-1-fail.hxml.stderr @@ -1 +1 @@ -Main1.hx:3: characters 2-23 : Invalid number of type parameters for A \ No newline at end of file +Main1.hx:3: characters 8-22 : Invalid number of type parameters for A \ No newline at end of file diff --git a/tests/misc/projects/Issue3710/compile-2-fail.hxml.stderr b/tests/misc/projects/Issue3710/compile-2-fail.hxml.stderr index d94a4804..dd81bd5f 100644 --- a/tests/misc/projects/Issue3710/compile-2-fail.hxml.stderr +++ b/tests/misc/projects/Issue3710/compile-2-fail.hxml.stderr @@ -1 +1 @@ -Main2.hx:3: characters 2-18 : Invalid number of type parameters for A \ No newline at end of file +Main2.hx:3: characters 8-17 : Invalid number of type parameters for A \ No newline at end of file diff --git a/tests/misc/projects/Issue3781/Main.hx b/tests/misc/projects/Issue3781/Main.hx index 298bccb6..03441858 100644 --- a/tests/misc/projects/Issue3781/Main.hx +++ b/tests/misc/projects/Issue3781/Main.hx @@ -2,7 +2,7 @@ enum E { E1(v:T); } -abstract Ab(String) to String {} +abstract Ab(String) {} class Main { static function main() { diff --git a/tests/misc/projects/Issue3782/compile-fail.hxml.disabled b/tests/misc/projects/Issue3782/compile-fail.hxml.disabled new file mode 100644 index 00000000..a86414bc --- /dev/null +++ b/tests/misc/projects/Issue3782/compile-fail.hxml.disabled @@ -0,0 +1,3 @@ +-main Main +--interp +-D no-analyzer \ No newline at end of file diff --git a/tests/misc/projects/Issue3802/Main.hx b/tests/misc/projects/Issue3802/Main.hx new file mode 100644 index 00000000..1508bfdb --- /dev/null +++ b/tests/misc/projects/Issue3802/Main.hx @@ -0,0 +1,7 @@ +class Main { + static function main() { + test(); + } + + static function test(i:Int, s:String) { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue3802/compile-fail.hxml b/tests/misc/projects/Issue3802/compile-fail.hxml new file mode 100644 index 00000000..6443a2fd --- /dev/null +++ b/tests/misc/projects/Issue3802/compile-fail.hxml @@ -0,0 +1 @@ +--run Main \ No newline at end of file diff --git a/tests/misc/projects/Issue3802/compile-fail.hxml.stderr b/tests/misc/projects/Issue3802/compile-fail.hxml.stderr new file mode 100644 index 00000000..d6958e1a --- /dev/null +++ b/tests/misc/projects/Issue3802/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:3: characters 2-8 : Not enough arguments, expected i:Int, s:String \ No newline at end of file diff --git a/tests/misc/projects/Issue3907/Main.hx b/tests/misc/projects/Issue3907/Main.hx new file mode 100644 index 00000000..1555ee2c --- /dev/null +++ b/tests/misc/projects/Issue3907/Main.hx @@ -0,0 +1,7 @@ +class Main { + static function doStuff(options:{a:Float, b:String}) {} + + static function main () { + doStuff({ + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue3907/compile.hxml b/tests/misc/projects/Issue3907/compile.hxml new file mode 100644 index 00000000..7d081018 --- /dev/null +++ b/tests/misc/projects/Issue3907/compile.hxml @@ -0,0 +1 @@ +--display Main.hx@121 \ No newline at end of file diff --git a/tests/misc/projects/Issue3907/compile.hxml.stderr b/tests/misc/projects/Issue3907/compile.hxml.stderr new file mode 100644 index 00000000..7108fd53 --- /dev/null +++ b/tests/misc/projects/Issue3907/compile.hxml.stderr @@ -0,0 +1,4 @@ + +Float +String + \ No newline at end of file diff --git a/tests/misc/projects/Issue3931/compile1.hxml.stderr b/tests/misc/projects/Issue3931/compile1.hxml.stderr index 09f4f181..bfde2d40 100644 --- a/tests/misc/projects/Issue3931/compile1.hxml.stderr +++ b/tests/misc/projects/Issue3931/compile1.hxml.stderr @@ -1,4 +1,4 @@ - - + + \ No newline at end of file diff --git a/tests/misc/projects/Issue3931/compile2.hxml.stderr b/tests/misc/projects/Issue3931/compile2.hxml.stderr index 346c89ba..7a6b7660 100644 --- a/tests/misc/projects/Issue3931/compile2.hxml.stderr +++ b/tests/misc/projects/Issue3931/compile2.hxml.stderr @@ -1,4 +1,4 @@ - - + + \ No newline at end of file diff --git a/tests/misc/projects/Issue3956/Main.hx b/tests/misc/projects/Issue3956/Main.hx new file mode 100644 index 00000000..6bbb4f7a --- /dev/null +++ b/tests/misc/projects/Issue3956/Main.hx @@ -0,0 +1,10 @@ +class Main { + static function main() { + var i = getInt(); + call(i++, i > 0 ? { call(0, 0); 1; } : 1); + } + + static function getInt() { return 0; } + + static function call(a:Int, b:Int) { Sys.stderr().writeString(a + " " + b + "\n"); } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue3956/compile.hxml b/tests/misc/projects/Issue3956/compile.hxml new file mode 100644 index 00000000..31c8a033 --- /dev/null +++ b/tests/misc/projects/Issue3956/compile.hxml @@ -0,0 +1,3 @@ +-main Main +-D analyzer +-x neko.n \ No newline at end of file diff --git a/tests/misc/projects/Issue3956/compile.hxml.stderr b/tests/misc/projects/Issue3956/compile.hxml.stderr new file mode 100644 index 00000000..316c35eb --- /dev/null +++ b/tests/misc/projects/Issue3956/compile.hxml.stderr @@ -0,0 +1,2 @@ +0 0 +0 1 \ No newline at end of file diff --git a/tests/misc/projects/Issue3975/Main.hx b/tests/misc/projects/Issue3975/Main.hx new file mode 100644 index 00000000..d113ca87 --- /dev/null +++ b/tests/misc/projects/Issue3975/Main.hx @@ -0,0 +1,6 @@ +class Main { + static function main() { + var a = ["a", "b"]; + var a2 : { var pop(get,never) : Void -> Void; } = a; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue3975/compile-fail.hxml b/tests/misc/projects/Issue3975/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue3975/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue3975/compile-fail.hxml.stderr b/tests/misc/projects/Issue3975/compile-fail.hxml.stderr new file mode 100644 index 00000000..1b788684 --- /dev/null +++ b/tests/misc/projects/Issue3975/compile-fail.hxml.stderr @@ -0,0 +1,2 @@ +Main.hx:4: characters 2-54 : Array should be { pop : Void -> Void } +Main.hx:4: characters 2-54 : Field pop is method but should be (get,never) \ No newline at end of file diff --git a/tests/misc/projects/Issue4114/Main1.hx b/tests/misc/projects/Issue4114/Main1.hx new file mode 100644 index 00000000..65ca6aea --- /dev/null +++ b/tests/misc/projects/Issue4114/Main1.hx @@ -0,0 +1,3 @@ +class Main { + static function main():String { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4114/Main2.hx b/tests/misc/projects/Issue4114/Main2.hx new file mode 100644 index 00000000..81537789 --- /dev/null +++ b/tests/misc/projects/Issue4114/Main2.hx @@ -0,0 +1,7 @@ +class Main { + static function main() { + if (Math.random() > 0.5) { + return (null : Dynamic); + } + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4114/compile1-fail.hxml b/tests/misc/projects/Issue4114/compile1-fail.hxml new file mode 100644 index 00000000..d7a4672b --- /dev/null +++ b/tests/misc/projects/Issue4114/compile1-fail.hxml @@ -0,0 +1,2 @@ +-main Main1 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4114/compile1-fail.hxml.stderr b/tests/misc/projects/Issue4114/compile1-fail.hxml.stderr new file mode 100644 index 00000000..90443b23 --- /dev/null +++ b/tests/misc/projects/Issue4114/compile1-fail.hxml.stderr @@ -0,0 +1 @@ +Main1.hx:2: characters 31-34 : Missing return: String \ No newline at end of file diff --git a/tests/misc/projects/Issue4114/compile2-fail.hxml b/tests/misc/projects/Issue4114/compile2-fail.hxml new file mode 100644 index 00000000..e51d8952 --- /dev/null +++ b/tests/misc/projects/Issue4114/compile2-fail.hxml @@ -0,0 +1,2 @@ +-main Main2 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4114/compile2-fail.hxml.stderr b/tests/misc/projects/Issue4114/compile2-fail.hxml.stderr new file mode 100644 index 00000000..f91c028f --- /dev/null +++ b/tests/misc/projects/Issue4114/compile2-fail.hxml.stderr @@ -0,0 +1 @@ +Main2.hx:3: lines 3-5 : Missing return: Unknown<0> \ No newline at end of file diff --git a/tests/misc/projects/Issue4160/compile.hxml b/tests/misc/projects/Issue4160/compile.hxml new file mode 100644 index 00000000..9dd0b4bc --- /dev/null +++ b/tests/misc/projects/Issue4160/compile.hxml @@ -0,0 +1,2 @@ +-main test.Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4160/compile.hxml.stderr b/tests/misc/projects/Issue4160/compile.hxml.stderr new file mode 100644 index 00000000..19102815 --- /dev/null +++ b/tests/misc/projects/Issue4160/compile.hxml.stderr @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/tests/misc/projects/Issue4160/test/Main.hx b/tests/misc/projects/Issue4160/test/Main.hx new file mode 100644 index 00000000..af6c0542 --- /dev/null +++ b/tests/misc/projects/Issue4160/test/Main.hx @@ -0,0 +1,51 @@ +package test; + +import haxe.macro.Context; +import haxe.macro.Expr; + +private class Bar { + public function new() { } + public function getValue() { + return "foo"; + } +} + +class Main +{ + static function main() + { + defineFooExtendsBarInLocalModule(); + #if !macro + var foo = new Foo(); + Sys.stderr().writeString(foo.getValue()); + #end + } + + macro static function defineFooExtendsBarInLocalModule(?e) + { + var infos = Context.getPosInfos(Context.currentPos()); + var position = Context.makePosition({min:0, max:0, file:infos.file}); + + var superTypePath:TypePath = + { + pack: [], + name: "Bar", + sub: null + } + + var kind:TypeDefKind = TypeDefKind.TDClass(superTypePath); + + var Foo:TypeDefinition = + { + name: "Foo", + pack: ["test"], + pos: position, + kind: kind, + fields: [] + } + + Context.defineModule(Context.getLocalModule(), [Foo]); + + return e; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4218/Main.hx b/tests/misc/projects/Issue4218/Main.hx new file mode 100644 index 00000000..b5bb20a7 --- /dev/null +++ b/tests/misc/projects/Issue4218/Main.hx @@ -0,0 +1,12 @@ +// This is in fact DCE related, so it should be compiled seperately... +class Main { + static function main() { + var i = 2; + i >>>= 1; + if (i != 1) + throw "i != 1"; + + if (StringTools.hex(1, 6) != "000001") + throw 'StringTools.hex(1, 6) != "000001"'; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4218/build.hxml b/tests/misc/projects/Issue4218/build.hxml new file mode 100644 index 00000000..07699b88 --- /dev/null +++ b/tests/misc/projects/Issue4218/build.hxml @@ -0,0 +1,3 @@ +-python Test.py +-main Main +-cmd python3 Test.py \ No newline at end of file diff --git a/tests/misc/projects/Issue4247/Main.hx b/tests/misc/projects/Issue4247/Main.hx new file mode 100644 index 00000000..591a8d3c --- /dev/null +++ b/tests/misc/projects/Issue4247/Main.hx @@ -0,0 +1,11 @@ +class Main1 { + static function main() { + var x:Dynamic; + if (Math.random() < 0.5) x=3; + else x = []; + switch(x) { + case 3 : trace(x); + case [] : trace(x); + } + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4247/compile-fail.hxml b/tests/misc/projects/Issue4247/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4247/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4247/compile-fail.hxml.stderr b/tests/misc/projects/Issue4247/compile-fail.hxml.stderr new file mode 100644 index 00000000..9b7d02ce --- /dev/null +++ b/tests/misc/projects/Issue4247/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:8: characters 3-21 : Incompatible pattern \ No newline at end of file diff --git a/tests/misc/projects/Issue4250/Main.hx b/tests/misc/projects/Issue4250/Main.hx new file mode 100644 index 00000000..2c6b557f --- /dev/null +++ b/tests/misc/projects/Issue4250/Main.hx @@ -0,0 +1,14 @@ +typedef Node = { parent: Node }; + +class SomeNode { + public var parent:SomeNode; + public function new() { } +} + +class Main { + static function main() { + var someNode = new SomeNode(); + var n:Node = someNode; + n.parent = { parent: null }; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4250/compile-fail.hxml b/tests/misc/projects/Issue4250/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4250/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4250/compile-fail.hxml.stderr b/tests/misc/projects/Issue4250/compile-fail.hxml.stderr new file mode 100644 index 00000000..150f69ec --- /dev/null +++ b/tests/misc/projects/Issue4250/compile-fail.hxml.stderr @@ -0,0 +1,5 @@ +Main.hx:11: characters 8-30 : SomeNode should be Node +Main.hx:11: characters 8-30 : SomeNode should be { parent : Node } +Main.hx:11: characters 8-30 : Invalid type for field parent : +Main.hx:11: characters 8-30 : SomeNode should be Node +Main.hx:11: characters 8-30 : SomeNode should be { parent : Node } \ No newline at end of file diff --git a/tests/misc/projects/Issue4265/Main.hx b/tests/misc/projects/Issue4265/Main.hx new file mode 100644 index 00000000..20e9432d --- /dev/null +++ b/tests/misc/projects/Issue4265/Main.hx @@ -0,0 +1,10 @@ +class Main { + static function main() { + var c = Std.int(Math.random() - 0.5); //0 + + Sys.stderr().writeString(switch (c) { + case 1: '1'; + default: 'analyzer removed this '; + }); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4265/compile.hxml b/tests/misc/projects/Issue4265/compile.hxml new file mode 100644 index 00000000..31c8a033 --- /dev/null +++ b/tests/misc/projects/Issue4265/compile.hxml @@ -0,0 +1,3 @@ +-main Main +-D analyzer +-x neko.n \ No newline at end of file diff --git a/tests/misc/projects/Issue4265/compile.hxml.stderr b/tests/misc/projects/Issue4265/compile.hxml.stderr new file mode 100644 index 00000000..c2a24a7e --- /dev/null +++ b/tests/misc/projects/Issue4265/compile.hxml.stderr @@ -0,0 +1 @@ +analyzer removed this \ No newline at end of file diff --git a/tests/misc/projects/Issue4270/EmptyString.hx b/tests/misc/projects/Issue4270/EmptyString.hx new file mode 100644 index 00000000..485959c6 --- /dev/null +++ b/tests/misc/projects/Issue4270/EmptyString.hx @@ -0,0 +1,5 @@ +class EmptyString { + static function main() { + "". + } +} diff --git a/tests/misc/projects/Issue4270/MultiChar.hx b/tests/misc/projects/Issue4270/MultiChar.hx new file mode 100644 index 00000000..67e6961a --- /dev/null +++ b/tests/misc/projects/Issue4270/MultiChar.hx @@ -0,0 +1,5 @@ +class MultiChar { + static function main() { + "ab". + } +} diff --git a/tests/misc/projects/Issue4270/SingleChar.hx b/tests/misc/projects/Issue4270/SingleChar.hx new file mode 100644 index 00000000..5532082c --- /dev/null +++ b/tests/misc/projects/Issue4270/SingleChar.hx @@ -0,0 +1,5 @@ +class SingleChar { + static function main() { + "a". + } +} diff --git a/tests/misc/projects/Issue4270/Test.hx b/tests/misc/projects/Issue4270/Test.hx new file mode 100644 index 00000000..2b8d7b18 --- /dev/null +++ b/tests/misc/projects/Issue4270/Test.hx @@ -0,0 +1,28 @@ +class Test { + static function error(msg, code) { + Sys.stderr().writeString(msg); + Sys.exit(code); + } + + static function test(file:String, pos:Int, shouldExist:Bool) { + var arg = '$file@$pos'; + var proc = new sys.io.Process("haxe", ["--display", arg]); + var stderr = proc.stderr.readAll().toString(); + var exit = proc.exitCode(); + if (exit != 0) { + error(arg + ":\n" + stderr, exit); + } else { + var exist = stderr.indexOf("(T) { + +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/OnClass.hx b/tests/misc/projects/Issue4293/OnClass.hx new file mode 100644 index 00000000..290a0eb0 --- /dev/null +++ b/tests/misc/projects/Issue4293/OnClass.hx @@ -0,0 +1,3 @@ +class OnClass { + static function main() { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/OnEnum.hx b/tests/misc/projects/Issue4293/OnEnum.hx new file mode 100644 index 00000000..5bd422d9 --- /dev/null +++ b/tests/misc/projects/Issue4293/OnEnum.hx @@ -0,0 +1,3 @@ +enum OnEnum { + +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/OnEnumCtor.hx b/tests/misc/projects/Issue4293/OnEnumCtor.hx new file mode 100644 index 00000000..2b748f2e --- /dev/null +++ b/tests/misc/projects/Issue4293/OnEnumCtor.hx @@ -0,0 +1,3 @@ +enum E { + C(); +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/OnField.hx b/tests/misc/projects/Issue4293/OnField.hx new file mode 100644 index 00000000..2f1ead1c --- /dev/null +++ b/tests/misc/projects/Issue4293/OnField.hx @@ -0,0 +1,3 @@ +class OnField { + static function main() { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/OnTypedef.hx b/tests/misc/projects/Issue4293/OnTypedef.hx new file mode 100644 index 00000000..99710c32 --- /dev/null +++ b/tests/misc/projects/Issue4293/OnTypedef.hx @@ -0,0 +1 @@ +typedef OnTypedef = Int; \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/compile-abstract-fail.hxml b/tests/misc/projects/Issue4293/compile-abstract-fail.hxml new file mode 100644 index 00000000..339eb30c --- /dev/null +++ b/tests/misc/projects/Issue4293/compile-abstract-fail.hxml @@ -0,0 +1 @@ +--run OnAbstract \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/compile-abstract-fail.hxml.stderr b/tests/misc/projects/Issue4293/compile-abstract-fail.hxml.stderr new file mode 100644 index 00000000..f8df10b8 --- /dev/null +++ b/tests/misc/projects/Issue4293/compile-abstract-fail.hxml.stderr @@ -0,0 +1 @@ +OnAbstract.hx:1: characters 23-24 : Duplicate type parameter name: T diff --git a/tests/misc/projects/Issue4293/compile-class-fail.hxml b/tests/misc/projects/Issue4293/compile-class-fail.hxml new file mode 100644 index 00000000..22ce876f --- /dev/null +++ b/tests/misc/projects/Issue4293/compile-class-fail.hxml @@ -0,0 +1 @@ +--run OnClass \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/compile-class-fail.hxml.stderr b/tests/misc/projects/Issue4293/compile-class-fail.hxml.stderr new file mode 100644 index 00000000..77cb5f52 --- /dev/null +++ b/tests/misc/projects/Issue4293/compile-class-fail.hxml.stderr @@ -0,0 +1 @@ +OnClass.hx:1: characters 17-18 : Duplicate type parameter name: T \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/compile-enum-ctor-fail.hxml b/tests/misc/projects/Issue4293/compile-enum-ctor-fail.hxml new file mode 100644 index 00000000..ba49480c --- /dev/null +++ b/tests/misc/projects/Issue4293/compile-enum-ctor-fail.hxml @@ -0,0 +1 @@ +--run OnEnumCtor \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/compile-enum-ctor-fail.hxml.stderr b/tests/misc/projects/Issue4293/compile-enum-ctor-fail.hxml.stderr new file mode 100644 index 00000000..be6c20e5 --- /dev/null +++ b/tests/misc/projects/Issue4293/compile-enum-ctor-fail.hxml.stderr @@ -0,0 +1 @@ +OnEnumCtor.hx:2: characters 6-7 : Duplicate type parameter name: T \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/compile-enum-fail.hxml b/tests/misc/projects/Issue4293/compile-enum-fail.hxml new file mode 100644 index 00000000..8fcfd688 --- /dev/null +++ b/tests/misc/projects/Issue4293/compile-enum-fail.hxml @@ -0,0 +1 @@ +--run OnEnum \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/compile-enum-fail.hxml.stderr b/tests/misc/projects/Issue4293/compile-enum-fail.hxml.stderr new file mode 100644 index 00000000..733358af --- /dev/null +++ b/tests/misc/projects/Issue4293/compile-enum-fail.hxml.stderr @@ -0,0 +1 @@ +OnEnum.hx:1: characters 15-16 : Duplicate type parameter name: T \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/compile-field-fail.hxml b/tests/misc/projects/Issue4293/compile-field-fail.hxml new file mode 100644 index 00000000..0c17c1bb --- /dev/null +++ b/tests/misc/projects/Issue4293/compile-field-fail.hxml @@ -0,0 +1 @@ +--run OnField \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/compile-field-fail.hxml.stderr b/tests/misc/projects/Issue4293/compile-field-fail.hxml.stderr new file mode 100644 index 00000000..63595ad1 --- /dev/null +++ b/tests/misc/projects/Issue4293/compile-field-fail.hxml.stderr @@ -0,0 +1 @@ +OnField.hx:2: characters 25-26 : Duplicate type parameter name: T \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/compile-typedef-fail.hxml b/tests/misc/projects/Issue4293/compile-typedef-fail.hxml new file mode 100644 index 00000000..bff9d721 --- /dev/null +++ b/tests/misc/projects/Issue4293/compile-typedef-fail.hxml @@ -0,0 +1 @@ +--run OnTypedef \ No newline at end of file diff --git a/tests/misc/projects/Issue4293/compile-typedef-fail.hxml.stderr b/tests/misc/projects/Issue4293/compile-typedef-fail.hxml.stderr new file mode 100644 index 00000000..e1992f66 --- /dev/null +++ b/tests/misc/projects/Issue4293/compile-typedef-fail.hxml.stderr @@ -0,0 +1 @@ +OnTypedef.hx:1: characters 21-22 : Duplicate type parameter name: T \ No newline at end of file diff --git a/tests/misc/projects/Issue4364/Main.hx b/tests/misc/projects/Issue4364/Main.hx new file mode 100644 index 00000000..7d1609a7 --- /dev/null +++ b/tests/misc/projects/Issue4364/Main.hx @@ -0,0 +1,24 @@ +class C { + public var value:String; + public function new() { + value = "foo"; + } +} + +abstract A(C) to C { + public function f() { + return "bar"; + } +} + +@:generic +class GVoid>> { + public function new() {} + public function make():T return new T(); +} + +class Main { + static function main() { + var g = new G(); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4364/compile-fail.hxml b/tests/misc/projects/Issue4364/compile-fail.hxml new file mode 100644 index 00000000..454d4728 --- /dev/null +++ b/tests/misc/projects/Issue4364/compile-fail.hxml @@ -0,0 +1,3 @@ +-main Main +-neko neko.n +--no-output \ No newline at end of file diff --git a/tests/misc/projects/Issue4364/compile-fail.hxml.stderr b/tests/misc/projects/Issue4364/compile-fail.hxml.stderr new file mode 100644 index 00000000..3140f336 --- /dev/null +++ b/tests/misc/projects/Issue4364/compile-fail.hxml.stderr @@ -0,0 +1,2 @@ +Main.hx:22: characters 14-18 : Constraint check failure for G.T +Main.hx:22: characters 14-18 : A should be haxe.Constructible Void> \ No newline at end of file diff --git a/tests/misc/projects/Issue4370/Test.hx b/tests/misc/projects/Issue4370/Test.hx new file mode 100644 index 00000000..92727a35 --- /dev/null +++ b/tests/misc/projects/Issue4370/Test.hx @@ -0,0 +1,12 @@ +class Test { + static function main() { + trace("Haxe is great!"); + var i = 2; + do{ + trace("Doing this"); + var x = 3; + var g = true; + }while(i--); + + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4370/compile-fail.hxml b/tests/misc/projects/Issue4370/compile-fail.hxml new file mode 100644 index 00000000..345e6aef --- /dev/null +++ b/tests/misc/projects/Issue4370/compile-fail.hxml @@ -0,0 +1 @@ +Test diff --git a/tests/misc/projects/Issue4370/compile-fail.hxml.stderr b/tests/misc/projects/Issue4370/compile-fail.hxml.stderr new file mode 100644 index 00000000..f14d3e28 --- /dev/null +++ b/tests/misc/projects/Issue4370/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Test.hx:9: characters 15-18 : Int should be Bool \ No newline at end of file diff --git a/tests/misc/projects/Issue4378/Main.hx b/tests/misc/projects/Issue4378/Main.hx new file mode 100644 index 00000000..092e4c35 --- /dev/null +++ b/tests/misc/projects/Issue4378/Main.hx @@ -0,0 +1,17 @@ +class Main implements I { + + function new() { } + + public function test(s:String) { + trace(s); + } + + static function main() { + var m:I = new Main(); + m.test(1); + } +} + +interface I { + function test(s:Dynamic):Void; +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4378/compile-fail.hxml b/tests/misc/projects/Issue4378/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4378/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4378/compile-fail.hxml.stderr b/tests/misc/projects/Issue4378/compile-fail.hxml.stderr new file mode 100644 index 00000000..5d3cd2e7 --- /dev/null +++ b/tests/misc/projects/Issue4378/compile-fail.hxml.stderr @@ -0,0 +1,4 @@ +Main.hx:5: lines 5-7 : Field test has different type than in I +Main.hx:16: characters 1-31 : Interface field is defined here +Main.hx:5: lines 5-7 : s : String -> Void should be s : Dynamic -> Void +Main.hx:5: lines 5-7 : String should be Dynamic \ No newline at end of file diff --git a/tests/misc/projects/Issue4399/Main.hx b/tests/misc/projects/Issue4399/Main.hx new file mode 100644 index 00000000..46714499 --- /dev/null +++ b/tests/misc/projects/Issue4399/Main.hx @@ -0,0 +1,19 @@ +class Main { + static function main() { + Sys.stderr().writeString("" + foo(2)); + } + + static var array:Array = [1,2,3,4,5]; + + static function foo(value:Int):Int { + var i:Int = 0; + var m:Int = 0; + while(i < array.length) { + if(array[i] == value) { + m = i; + } + ++i; + } + return m; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4399/compile.hxml b/tests/misc/projects/Issue4399/compile.hxml new file mode 100644 index 00000000..31c8a033 --- /dev/null +++ b/tests/misc/projects/Issue4399/compile.hxml @@ -0,0 +1,3 @@ +-main Main +-D analyzer +-x neko.n \ No newline at end of file diff --git a/tests/misc/projects/Issue4399/compile.hxml.stderr b/tests/misc/projects/Issue4399/compile.hxml.stderr new file mode 100644 index 00000000..56a6051c --- /dev/null +++ b/tests/misc/projects/Issue4399/compile.hxml.stderr @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/tests/misc/projects/Issue4404/compile1.hxml b/tests/misc/projects/Issue4404/compile1.hxml new file mode 100644 index 00000000..876b73ce --- /dev/null +++ b/tests/misc/projects/Issue4404/compile1.hxml @@ -0,0 +1,4 @@ +-cp src +-main Main +-js js.js +--no-output \ No newline at end of file diff --git a/tests/misc/projects/Issue4404/src/Base.hx b/tests/misc/projects/Issue4404/src/Base.hx new file mode 100644 index 00000000..15b04b4e --- /dev/null +++ b/tests/misc/projects/Issue4404/src/Base.hx @@ -0,0 +1,4 @@ +@:autoBuild(Macro.build()) +class Base +{ +} diff --git a/tests/misc/projects/Issue4404/src/Child.hx b/tests/misc/projects/Issue4404/src/Child.hx new file mode 100644 index 00000000..6270ef1f --- /dev/null +++ b/tests/misc/projects/Issue4404/src/Child.hx @@ -0,0 +1,3 @@ +class Child extends Base +{ +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4404/src/ChildChild.hx b/tests/misc/projects/Issue4404/src/ChildChild.hx new file mode 100644 index 00000000..c5685849 --- /dev/null +++ b/tests/misc/projects/Issue4404/src/ChildChild.hx @@ -0,0 +1,4 @@ +class ChildChild extends Child +{ + public function show() {} +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4404/src/ContainerBase.hx b/tests/misc/projects/Issue4404/src/ContainerBase.hx new file mode 100644 index 00000000..c7b94e5e --- /dev/null +++ b/tests/misc/projects/Issue4404/src/ContainerBase.hx @@ -0,0 +1,6 @@ +import ChildChild; + +class ContainerBase extends Base +{ + var childChild : ChildChild; +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4404/src/ContainerChild.hx b/tests/misc/projects/Issue4404/src/ContainerChild.hx new file mode 100644 index 00000000..931e9498 --- /dev/null +++ b/tests/misc/projects/Issue4404/src/ContainerChild.hx @@ -0,0 +1,7 @@ +class ContainerChild extends ContainerBase +{ + function test() + { + childChild.show(); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4404/src/Empty.hx b/tests/misc/projects/Issue4404/src/Empty.hx new file mode 100644 index 00000000..e69de29b diff --git a/tests/misc/projects/Issue4404/src/Macro.hx b/tests/misc/projects/Issue4404/src/Macro.hx new file mode 100644 index 00000000..622b175c --- /dev/null +++ b/tests/misc/projects/Issue4404/src/Macro.hx @@ -0,0 +1,19 @@ +import haxe.macro.Context; +import haxe.macro.Expr; + +class Macro +{ + static function build() : Array + { + Context.getModule("Empty"); + + /*var klass = Context.getLocalClass().get(); + if (klass.name == "ChildChild") + { + var fields = Context.getBuildFields(); + trace("\rChildChild fields:\r" + fields.map(function(f) return "\tField: " + f.name + " " + f.access).join("\r")); + }*/ + + return null; + } +} diff --git a/tests/misc/projects/Issue4404/src/Main.hx b/tests/misc/projects/Issue4404/src/Main.hx new file mode 100644 index 00000000..7807c42a --- /dev/null +++ b/tests/misc/projects/Issue4404/src/Main.hx @@ -0,0 +1,10 @@ +import ContainerChild; +import ContainerBase; +import Child; + +class Main +{ + static function main() + { + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4448/Main1.hx b/tests/misc/projects/Issue4448/Main1.hx new file mode 100644 index 00000000..2eb888fd --- /dev/null +++ b/tests/misc/projects/Issue4448/Main1.hx @@ -0,0 +1,21 @@ +abstract A(Int) { + function f() {} + + var v(get,never):Int; + function get_v() return this; + + var v2(get,never):Int; + inline function get_v2() return this; + + static function e() { + f(); // Not enough arguments, expected this:Int - should be just unavailable + v; // generates _$Main_A_$Impl_$.get_v(); + v2; // Invalid abstract implementation function + } +} + +class Main { + static function main() { + + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4448/compile1-fail.hxml b/tests/misc/projects/Issue4448/compile1-fail.hxml new file mode 100644 index 00000000..d7a4672b --- /dev/null +++ b/tests/misc/projects/Issue4448/compile1-fail.hxml @@ -0,0 +1,2 @@ +-main Main1 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4448/compile1-fail.hxml.stderr b/tests/misc/projects/Issue4448/compile1-fail.hxml.stderr new file mode 100644 index 00000000..7358f10f --- /dev/null +++ b/tests/misc/projects/Issue4448/compile1-fail.hxml.stderr @@ -0,0 +1,3 @@ +Main1.hx:11: characters 8-9 : Cannot access non-static field f from static method +Main1.hx:12: characters 8-9 : Cannot access non-static field v from static method +Main1.hx:13: characters 8-10 : Cannot access non-static field v2 from static method \ No newline at end of file diff --git a/tests/misc/projects/Issue4454/Main.hx b/tests/misc/projects/Issue4454/Main.hx new file mode 100644 index 00000000..dd732e7d --- /dev/null +++ b/tests/misc/projects/Issue4454/Main.hx @@ -0,0 +1,20 @@ +#if !macro +@:build(Main.build1()) +@:build(Main.build2()) +#end +class Main { + #if macro + static function build1() { + Sys.stderr().writeString("Build 1"); + return haxe.macro.Context.getBuildFields(); + } + + static function build2() { + Sys.stderr().writeString("Build 2"); + return haxe.macro.Context.getBuildFields(); + } + #end + + static function main() { + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4454/compile.hxml b/tests/misc/projects/Issue4454/compile.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4454/compile.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4454/compile.hxml.stderr b/tests/misc/projects/Issue4454/compile.hxml.stderr new file mode 100644 index 00000000..d1d333e8 --- /dev/null +++ b/tests/misc/projects/Issue4454/compile.hxml.stderr @@ -0,0 +1 @@ +Build 1Build 2 \ No newline at end of file diff --git a/tests/misc/projects/Issue4456/Main.hx b/tests/misc/projects/Issue4456/Main.hx new file mode 100644 index 00000000..e7277002 --- /dev/null +++ b/tests/misc/projects/Issue4456/Main.hx @@ -0,0 +1,34 @@ +class A { + public function f():Array { + return []; + } + + public function f2():A { + return this; + } +} + +@:generic +class BVoid>> { + var items:Map; + + public function new() { + items = new Map(); + } + + public function f():Array { + var a = []; + for (node in items) + a = a.concat(node.f()); + return a; + } +} + +class Main { + static function main() { + var b = new B
(); + Sys.stderr().writeString("" + b.f()); + } + + public function new() { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4456/compile.hxml b/tests/misc/projects/Issue4456/compile.hxml new file mode 100644 index 00000000..31c8a033 --- /dev/null +++ b/tests/misc/projects/Issue4456/compile.hxml @@ -0,0 +1,3 @@ +-main Main +-D analyzer +-x neko.n \ No newline at end of file diff --git a/tests/misc/projects/Issue4456/compile.hxml.stderr b/tests/misc/projects/Issue4456/compile.hxml.stderr new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/tests/misc/projects/Issue4456/compile.hxml.stderr @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/misc/projects/Issue4466/Main.hx b/tests/misc/projects/Issue4466/Main.hx new file mode 100644 index 00000000..9bea66fa --- /dev/null +++ b/tests/misc/projects/Issue4466/Main.hx @@ -0,0 +1,6 @@ +class Main { + static function main() { + var a; + var b = a + 1; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4466/compile-fail.hxml b/tests/misc/projects/Issue4466/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4466/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4466/compile-fail.hxml.stderr b/tests/misc/projects/Issue4466/compile-fail.hxml.stderr new file mode 100644 index 00000000..8f16a624 --- /dev/null +++ b/tests/misc/projects/Issue4466/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:4: characters 16-17 : Local variable a used without being initialized \ No newline at end of file diff --git a/tests/misc/projects/Issue4540/Main.hx b/tests/misc/projects/Issue4540/Main.hx new file mode 100644 index 00000000..44d09130 --- /dev/null +++ b/tests/misc/projects/Issue4540/Main.hx @@ -0,0 +1,7 @@ +class Main { + static function main() { + js.Promise.resolve(0).then(function(c) test(c)); + } + + static function test(a:{test:String}) {} +} diff --git a/tests/misc/projects/Issue4540/compile-fail.hxml b/tests/misc/projects/Issue4540/compile-fail.hxml new file mode 100644 index 00000000..f014a353 --- /dev/null +++ b/tests/misc/projects/Issue4540/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +-js Main.js \ No newline at end of file diff --git a/tests/misc/projects/Issue4540/compile-fail.hxml.stderr b/tests/misc/projects/Issue4540/compile-fail.hxml.stderr new file mode 100644 index 00000000..86d2aec3 --- /dev/null +++ b/tests/misc/projects/Issue4540/compile-fail.hxml.stderr @@ -0,0 +1,4 @@ +Main.hx:3: characters 35-54 : c : { test : String } -> Void should be Null> +Main.hx:3: characters 35-54 : c : { test : String } -> Void should be js.PromiseCallback +Main.hx:3: characters 35-54 : c : { test : String } -> Void should be haxe.extern.EitherType Void, Int -> js.Promise> +Main.hx:3: characters 35-54 : For function argument 'fulfillCallback' diff --git a/tests/misc/projects/Issue4563/Main.hx b/tests/misc/projects/Issue4563/Main.hx new file mode 100644 index 00000000..c30020b1 --- /dev/null +++ b/tests/misc/projects/Issue4563/Main.hx @@ -0,0 +1,15 @@ +class Main { + static function main() { + Sys.stderr().writeString("" + test(get(true))); + Sys.stderr().writeString("" + test(get(false))); + } + + static function get(b:Bool) return b; + + static inline function test(a:Bool):Int { + if (a) + return 42; + else + return 43; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4563/compile.hxml b/tests/misc/projects/Issue4563/compile.hxml new file mode 100644 index 00000000..31c8a033 --- /dev/null +++ b/tests/misc/projects/Issue4563/compile.hxml @@ -0,0 +1,3 @@ +-main Main +-D analyzer +-x neko.n \ No newline at end of file diff --git a/tests/misc/projects/Issue4563/compile.hxml.stderr b/tests/misc/projects/Issue4563/compile.hxml.stderr new file mode 100644 index 00000000..029d0855 --- /dev/null +++ b/tests/misc/projects/Issue4563/compile.hxml.stderr @@ -0,0 +1 @@ +4243 \ No newline at end of file diff --git a/tests/misc/projects/Issue4580/Main.hx b/tests/misc/projects/Issue4580/Main.hx new file mode 100644 index 00000000..f908e066 --- /dev/null +++ b/tests/misc/projects/Issue4580/Main.hx @@ -0,0 +1,3 @@ +class Main implements Main { + public static function main() {} +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4580/compile-fail.hxml b/tests/misc/projects/Issue4580/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4580/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4580/compile-fail.hxml.stderr b/tests/misc/projects/Issue4580/compile-fail.hxml.stderr new file mode 100644 index 00000000..c0483b93 --- /dev/null +++ b/tests/misc/projects/Issue4580/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:1: lines 1-3 : Recursive class \ No newline at end of file diff --git a/tests/misc/projects/Issue4651/CompServer.hx b/tests/misc/projects/Issue4651/CompServer.hx new file mode 100644 index 00000000..d5e8fc64 --- /dev/null +++ b/tests/misc/projects/Issue4651/CompServer.hx @@ -0,0 +1,16 @@ +class CompServer { + static function main() { + var port = 4000; + var server = new sys.io.Process("haxe", ["--wait", "" + port]); + var socket = new sys.net.Socket(); + socket.connect(new sys.net.Host("localhost"), port); + socket.write("--display Main.hx@43\n-D display-stdin"); + socket.write("\x01"); + socket.write(sys.io.File.getContent("Main.hx.stdin")); + socket.write("\x00"); + var out = socket.read(); + socket.close(); + Sys.stderr().writeString(out); + server.kill(); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4651/Main.hx b/tests/misc/projects/Issue4651/Main.hx new file mode 100644 index 00000000..5c7e0d6b --- /dev/null +++ b/tests/misc/projects/Issue4651/Main.hx @@ -0,0 +1,4 @@ +some + invalid + crap + :-) \ No newline at end of file diff --git a/tests/misc/projects/Issue4651/Main.hx.stdin b/tests/misc/projects/Issue4651/Main.hx.stdin new file mode 100644 index 00000000..3c783dcc --- /dev/null +++ b/tests/misc/projects/Issue4651/Main.hx.stdin @@ -0,0 +1 @@ +class Main { static function main() { Main. } } diff --git a/tests/misc/projects/Issue4651/compile-server.hxml.disabled b/tests/misc/projects/Issue4651/compile-server.hxml.disabled new file mode 100644 index 00000000..7f246faa --- /dev/null +++ b/tests/misc/projects/Issue4651/compile-server.hxml.disabled @@ -0,0 +1,4 @@ +# --run CompServer +-main CompServer +-neko CompServer.n +-cmd neko CompServer.n diff --git a/tests/misc/projects/Issue4651/compile-server.hxml.stderr b/tests/misc/projects/Issue4651/compile-server.hxml.stderr new file mode 100644 index 00000000..1637ed7c --- /dev/null +++ b/tests/misc/projects/Issue4651/compile-server.hxml.stderr @@ -0,0 +1,3 @@ + +Void -> Unknown<0> + diff --git a/tests/misc/projects/Issue4651/compile.hxml b/tests/misc/projects/Issue4651/compile.hxml new file mode 100644 index 00000000..10153305 --- /dev/null +++ b/tests/misc/projects/Issue4651/compile.hxml @@ -0,0 +1 @@ +-cmd cat Main.hx.stdin | haxe --display Main.hx@43 -D display-stdin \ No newline at end of file diff --git a/tests/misc/projects/Issue4651/compile.hxml.stderr b/tests/misc/projects/Issue4651/compile.hxml.stderr new file mode 100644 index 00000000..1637ed7c --- /dev/null +++ b/tests/misc/projects/Issue4651/compile.hxml.stderr @@ -0,0 +1,3 @@ + +Void -> Unknown<0> + diff --git a/tests/misc/projects/Issue4660/Include.hx b/tests/misc/projects/Issue4660/Include.hx new file mode 100644 index 00000000..f738186b --- /dev/null +++ b/tests/misc/projects/Issue4660/Include.hx @@ -0,0 +1,5 @@ +class Include { + static function use() { + haxe.macro.Compiler.includeFile("include.js", Top); + } +} diff --git a/tests/misc/projects/Issue4660/Test.hx b/tests/misc/projects/Issue4660/Test.hx new file mode 100644 index 00000000..35faf972 --- /dev/null +++ b/tests/misc/projects/Issue4660/Test.hx @@ -0,0 +1,22 @@ +class Test { + static function error(msg, code) { + Sys.stderr().writeString(msg); + Sys.exit(code); + } + + static function main() { + var proc = new sys.io.Process("haxe", [ + "-js", "out.js", + "--macro", "Include.use()" + ]); + var stderr = proc.stderr.readAll().toString(); + var exit = proc.exitCode(); + if (exit != 0) { + error(stderr, exit); + } else { + var out = sys.io.File.getContent("out.js"); + if (out.indexOf("THIS IS INCLUDED") == -1) + error("File is NOT included\n", 1); + } + } +} diff --git a/tests/misc/projects/Issue4660/compile.hxml b/tests/misc/projects/Issue4660/compile.hxml new file mode 100644 index 00000000..34c9a327 --- /dev/null +++ b/tests/misc/projects/Issue4660/compile.hxml @@ -0,0 +1 @@ +--run Test diff --git a/tests/misc/projects/Issue4660/include.js b/tests/misc/projects/Issue4660/include.js new file mode 100644 index 00000000..b66bb85d --- /dev/null +++ b/tests/misc/projects/Issue4660/include.js @@ -0,0 +1 @@ +"THIS IS INCLUDED"; \ No newline at end of file diff --git a/tests/misc/projects/Issue4662/Main.hx b/tests/misc/projects/Issue4662/Main.hx new file mode 100644 index 00000000..1ef24125 --- /dev/null +++ b/tests/misc/projects/Issue4662/Main.hx @@ -0,0 +1 @@ +class Main { static function main() { } } \ No newline at end of file diff --git a/tests/misc/projects/Issue4662/Test.hx b/tests/misc/projects/Issue4662/Test.hx new file mode 100644 index 00000000..12c14c5b --- /dev/null +++ b/tests/misc/projects/Issue4662/Test.hx @@ -0,0 +1,18 @@ +class Test { + static function error(msg, code) { + Sys.stderr().writeString(msg); + Sys.exit(code); + } + + static function main() { + var proc = new sys.io.Process("haxe", ["-cp", ".", "--display", "Main.hx@38@toplevel"]); + var stderr = proc.stderr.readAll().toString(); + var exit = proc.exitCode(); + if (exit != 0) { + error(stderr, exit); + } else { + if (stderr.indexOf('_pkg') != -1) + error("The package starting with `_` is not filtered out for completion:\n" + stderr, 1); + } + } +} diff --git a/tests/misc/projects/Issue4662/_pkg/A.hx b/tests/misc/projects/Issue4662/_pkg/A.hx new file mode 100644 index 00000000..10471e9b --- /dev/null +++ b/tests/misc/projects/Issue4662/_pkg/A.hx @@ -0,0 +1,3 @@ +package _pkg; + +class A {} diff --git a/tests/misc/projects/Issue4662/compile.hxml b/tests/misc/projects/Issue4662/compile.hxml new file mode 100644 index 00000000..34c9a327 --- /dev/null +++ b/tests/misc/projects/Issue4662/compile.hxml @@ -0,0 +1 @@ +--run Test diff --git a/tests/misc/projects/Issue4671/Main1.hx b/tests/misc/projects/Issue4671/Main1.hx new file mode 100644 index 00000000..1061b66d --- /dev/null +++ b/tests/misc/projects/Issue4671/Main1.hx @@ -0,0 +1,6 @@ +interface IFoo extends IBar{} +interface IBar extends IFoo{} + +class Main1 { + static function main() { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4671/Main2.hx b/tests/misc/projects/Issue4671/Main2.hx new file mode 100644 index 00000000..de8e60c3 --- /dev/null +++ b/tests/misc/projects/Issue4671/Main2.hx @@ -0,0 +1,6 @@ +class A extends B { } +class B extends A { } + +class Main1 { + static function main() { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4671/compile1-fail.hxml b/tests/misc/projects/Issue4671/compile1-fail.hxml new file mode 100644 index 00000000..d7a4672b --- /dev/null +++ b/tests/misc/projects/Issue4671/compile1-fail.hxml @@ -0,0 +1,2 @@ +-main Main1 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4671/compile1-fail.hxml.stderr b/tests/misc/projects/Issue4671/compile1-fail.hxml.stderr new file mode 100644 index 00000000..5b6a0b67 --- /dev/null +++ b/tests/misc/projects/Issue4671/compile1-fail.hxml.stderr @@ -0,0 +1 @@ +Main1.hx:1: characters 0-29 : Recursive class \ No newline at end of file diff --git a/tests/misc/projects/Issue4671/compile2-fail.hxml b/tests/misc/projects/Issue4671/compile2-fail.hxml new file mode 100644 index 00000000..e51d8952 --- /dev/null +++ b/tests/misc/projects/Issue4671/compile2-fail.hxml @@ -0,0 +1,2 @@ +-main Main2 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4671/compile2-fail.hxml.stderr b/tests/misc/projects/Issue4671/compile2-fail.hxml.stderr new file mode 100644 index 00000000..4abddcbd --- /dev/null +++ b/tests/misc/projects/Issue4671/compile2-fail.hxml.stderr @@ -0,0 +1 @@ +Main2.hx:1: characters 0-21 : Recursive class \ No newline at end of file diff --git a/tests/misc/projects/Issue4679/Main.hx b/tests/misc/projects/Issue4679/Main.hx new file mode 100644 index 00000000..921789a3 --- /dev/null +++ b/tests/misc/projects/Issue4679/Main.hx @@ -0,0 +1,32 @@ +extern class C { + static var PROXIMITY_BEGIN(default, never):String; + static var PROXIMITY_END(default, never):String; + static var PROXIMITY_MOVE(default, never):String; +} + +@:native("C") +@:keep +class NotC { + static var PROXIMITY_BEGIN = "PROXIMITY_BEGIN"; + static var PROXIMITY_END = "PROXIMITY_END"; + static var PROXIMITY_MOVE = "PROXIMITY_MOVE"; +} + +class Main { + static function main() { + function print(s:Dynamic) { + Sys.stderr().writeString(s + "\n"); + } + print(match(C.PROXIMITY_BEGIN)); + print(match(C.PROXIMITY_END)); + print(match(C.PROXIMITY_MOVE)); + } + + static function match(s:String) { + return switch (s) { + case C.PROXIMITY_BEGIN: 1; + case C.PROXIMITY_END: 2; + case _: 3; + } + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4679/compile.hxml b/tests/misc/projects/Issue4679/compile.hxml new file mode 100644 index 00000000..fbbea3aa --- /dev/null +++ b/tests/misc/projects/Issue4679/compile.hxml @@ -0,0 +1,2 @@ +-main Main +-x test \ No newline at end of file diff --git a/tests/misc/projects/Issue4679/compile.hxml.stderr b/tests/misc/projects/Issue4679/compile.hxml.stderr new file mode 100644 index 00000000..01e79c32 --- /dev/null +++ b/tests/misc/projects/Issue4679/compile.hxml.stderr @@ -0,0 +1,3 @@ +1 +2 +3 diff --git a/tests/misc/projects/Issue4689/Main.hx b/tests/misc/projects/Issue4689/Main.hx new file mode 100644 index 00000000..38082416 --- /dev/null +++ b/tests/misc/projects/Issue4689/Main.hx @@ -0,0 +1,21 @@ +class Main +{ + static function main() + { + test(Gadt.B); + } + + private static function test(a:Gadt) + { + var x = switch (a) + { + case A: + "test"; + } + } +} + +enum Gadt { + A:Gadt; + B:Gadt; +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4689/compile-fail.hxml b/tests/misc/projects/Issue4689/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4689/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4689/compile-fail.hxml.stderr b/tests/misc/projects/Issue4689/compile-fail.hxml.stderr new file mode 100644 index 00000000..800c07cd --- /dev/null +++ b/tests/misc/projects/Issue4689/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:10: characters 24-25 : Unmatched patterns: B \ No newline at end of file diff --git a/tests/misc/projects/Issue4712/Main.hx b/tests/misc/projects/Issue4712/Main.hx new file mode 100644 index 00000000..d6840f53 --- /dev/null +++ b/tests/misc/projects/Issue4712/Main.hx @@ -0,0 +1,12 @@ +class Main { + static function main() { + haxe.Log.trace = function(s,?p) { + Sys.stderr().writeString("" + s + " " + p.customParams[0]); + } + var n:UInt = -4; + if ( n > 0 ) + trace("positive", n); + else + trace("negative", n); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4712/compile.hxml b/tests/misc/projects/Issue4712/compile.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4712/compile.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4712/compile.hxml.stderr b/tests/misc/projects/Issue4712/compile.hxml.stderr new file mode 100644 index 00000000..075bb0f0 --- /dev/null +++ b/tests/misc/projects/Issue4712/compile.hxml.stderr @@ -0,0 +1 @@ +positive 4294967292 \ No newline at end of file diff --git a/tests/misc/projects/Issue4720/Main.hx b/tests/misc/projects/Issue4720/Main.hx new file mode 100644 index 00000000..41d36097 --- /dev/null +++ b/tests/misc/projects/Issue4720/Main.hx @@ -0,0 +1,70 @@ +class Main { + static function main() { + // deprecating type objects work + MyClass; + MyInterface; + MyEnum; + // MyAbstract; // this compiles when analyzer=yes, but is another issue + TClass; + TInterface; + TEnum; + // TAbstract; // this compiles when analyzer=yes, but is another issue + // TAnon; // this won't and shouldn't compile anyway + + // deprecating types instantiated work + new MyClass(); + MyEnum.None; + new MyAbstract(null); // but doesn't work on abstracts... + new TClass(); + TEnum.None; + new TAbstract(null); // neither + + // some physical access to deprecated API + deprecatedField; + deprecatedFunc(); + deprecatedProperty; // this won't show warnings + var x = deprecatedProperty; // this also + deprecatedGetSet; // however this will + var x = deprecatedGetSet; // this also + } + + // deprecating fields work + @:deprecated static var deprecatedField:String; + @:deprecated static function deprecatedFunc() return; + + // ... however deprecating getters and setters have some gotcha + @:deprecated static var deprecatedProperty(get, set):String; + static function get_deprecatedProperty():String return "0"; + static function set_deprecatedProperty(value):String return "0"; + + static var deprecatedGetSet(get, set):String; + @:deprecated static function get_deprecatedGetSet():String return "0"; + @:deprecated static function set_deprecatedGetSet(value):String return "0"; +} + +@:deprecated +class MyClass { public function new() {} } + +@:deprecated +interface MyInterface { } + +@:deprecated +enum MyEnum { None; } + +@:deprecated +abstract MyAbstract(String) { public function new(value:String) this = value; } + +@:deprecated +typedef TClass = MyClass; + +@:deprecated +typedef TInterface = MyInterface; + +@:deprecated +typedef TEnum = MyEnum; + +@:deprecated +typedef TAbstract = MyAbstract; + +@:deprecated +typedef TAnon = { a:String }; \ No newline at end of file diff --git a/tests/misc/projects/Issue4720/compile.hxml b/tests/misc/projects/Issue4720/compile.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4720/compile.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4720/compile.hxml.stderr b/tests/misc/projects/Issue4720/compile.hxml.stderr new file mode 100644 index 00000000..ada21cd5 --- /dev/null +++ b/tests/misc/projects/Issue4720/compile.hxml.stderr @@ -0,0 +1,18 @@ +Main.hx:8: characters 8-14 : Warning : Usage of this typedef is deprecated +Main.hx:9: characters 8-18 : Warning : Usage of this typedef is deprecated +Main.hx:10: characters 8-13 : Warning : Usage of this typedef is deprecated +Main.hx:19: characters 8-18 : Warning : Usage of this typedef is deprecated +Main.hx:4: characters 8-15 : Warning : Usage of this class is deprecated +Main.hx:5: characters 8-19 : Warning : Usage of this class is deprecated +Main.hx:6: characters 8-14 : Warning : Usage of this enum is deprecated +Main.hx:15: characters 8-21 : Warning : Usage of this class is deprecated +Main.hx:16: characters 8-19 : Warning : Usage of this enum is deprecated +Main.hx:17: characters 8-28 : Warning : Usage of this class is deprecated +Main.hx:18: characters 8-20 : Warning : Usage of this class is deprecated +Main.hx:20: characters 8-27 : Warning : Usage of this class is deprecated +Main.hx:23: characters 8-23 : Warning : Usage of this field is deprecated +Main.hx:24: characters 8-22 : Warning : Usage of this field is deprecated +Main.hx:25: characters 8-26 : Warning : Usage of this field is deprecated +Main.hx:26: characters 16-34 : Warning : Usage of this field is deprecated +Main.hx:27: characters 8-24 : Warning : Usage of this field is deprecated +Main.hx:28: characters 16-32 : Warning : Usage of this field is deprecated \ No newline at end of file diff --git a/tests/misc/projects/Issue4723/Test.hx b/tests/misc/projects/Issue4723/Test.hx new file mode 100644 index 00000000..3312d35e --- /dev/null +++ b/tests/misc/projects/Issue4723/Test.hx @@ -0,0 +1,9 @@ +class Test { + function new() {} + + dynamic function test() {} + + static function main() { + new Test().test(); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4723/compile.hxml b/tests/misc/projects/Issue4723/compile.hxml new file mode 100644 index 00000000..e5ddcfe1 --- /dev/null +++ b/tests/misc/projects/Issue4723/compile.hxml @@ -0,0 +1,3 @@ +-main Test +-php bin +-cmd php bin/index.php \ No newline at end of file diff --git a/tests/misc/projects/Issue4742/Main.hx b/tests/misc/projects/Issue4742/Main.hx new file mode 100644 index 00000000..121e488c --- /dev/null +++ b/tests/misc/projects/Issue4742/Main.hx @@ -0,0 +1,6 @@ +class Main { + static function main() { + f("Haxe is great!") + "abc"; // This must produce a error! + } + static function f(s) : Void trace(s); +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4742/compile-fail.hxml b/tests/misc/projects/Issue4742/compile-fail.hxml new file mode 100644 index 00000000..454d4728 --- /dev/null +++ b/tests/misc/projects/Issue4742/compile-fail.hxml @@ -0,0 +1,3 @@ +-main Main +-neko neko.n +--no-output \ No newline at end of file diff --git a/tests/misc/projects/Issue4742/compile-fail.hxml.stderr b/tests/misc/projects/Issue4742/compile-fail.hxml.stderr new file mode 100644 index 00000000..db1964c5 --- /dev/null +++ b/tests/misc/projects/Issue4742/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:3: characters 8-27 : Cannot use Void as value \ No newline at end of file diff --git a/tests/misc/projects/Issue4754/Main1.hx b/tests/misc/projects/Issue4754/Main1.hx new file mode 100644 index 00000000..1c65d403 --- /dev/null +++ b/tests/misc/projects/Issue4754/Main1.hx @@ -0,0 +1,5 @@ +class Main1 { + static function main() { + "" + var str = ""; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4754/compile1-fail.hxml b/tests/misc/projects/Issue4754/compile1-fail.hxml new file mode 100644 index 00000000..d7a4672b --- /dev/null +++ b/tests/misc/projects/Issue4754/compile1-fail.hxml @@ -0,0 +1,2 @@ +-main Main1 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4754/compile1-fail.hxml.stderr b/tests/misc/projects/Issue4754/compile1-fail.hxml.stderr new file mode 100644 index 00000000..a4dfe45e --- /dev/null +++ b/tests/misc/projects/Issue4754/compile1-fail.hxml.stderr @@ -0,0 +1 @@ +Main1.hx:3: characters 7-10 : Cannot use this expression as value \ No newline at end of file diff --git a/tests/misc/projects/Issue4761/Main1.hx b/tests/misc/projects/Issue4761/Main1.hx new file mode 100644 index 00000000..75638c66 --- /dev/null +++ b/tests/misc/projects/Issue4761/Main1.hx @@ -0,0 +1,6 @@ +typedef T = A; +abstract A(T) { } + +class Main1 { + static function main() { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4761/compile1-fail.hxml b/tests/misc/projects/Issue4761/compile1-fail.hxml new file mode 100644 index 00000000..d7a4672b --- /dev/null +++ b/tests/misc/projects/Issue4761/compile1-fail.hxml @@ -0,0 +1,2 @@ +-main Main1 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4761/compile1-fail.hxml.stderr b/tests/misc/projects/Issue4761/compile1-fail.hxml.stderr new file mode 100644 index 00000000..4ab6e511 --- /dev/null +++ b/tests/misc/projects/Issue4761/compile1-fail.hxml.stderr @@ -0,0 +1 @@ +Main1.hx:2: characters 0-17 : Abstract underlying type cannot be recursive \ No newline at end of file diff --git a/tests/misc/projects/Issue4764/Main1.hx b/tests/misc/projects/Issue4764/Main1.hx new file mode 100644 index 00000000..934834db --- /dev/null +++ b/tests/misc/projects/Issue4764/Main1.hx @@ -0,0 +1,12 @@ +class F { + @:generic + public static function makeVoid>>() { + return new T(); + } +} + +class Main1 { + static function main() { + F.make(); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4764/compile1-fail.hxml b/tests/misc/projects/Issue4764/compile1-fail.hxml new file mode 100644 index 00000000..d7a4672b --- /dev/null +++ b/tests/misc/projects/Issue4764/compile1-fail.hxml @@ -0,0 +1,2 @@ +-main Main1 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4764/compile1-fail.hxml.stderr b/tests/misc/projects/Issue4764/compile1-fail.hxml.stderr new file mode 100644 index 00000000..9d5d90f0 --- /dev/null +++ b/tests/misc/projects/Issue4764/compile1-fail.hxml.stderr @@ -0,0 +1 @@ +Main1.hx:4: characters 15-22 : Cannot construct haxe.Constructible Void> \ No newline at end of file diff --git a/tests/misc/projects/Issue4766/Main1.hx b/tests/misc/projects/Issue4766/Main1.hx new file mode 100644 index 00000000..373608c4 --- /dev/null +++ b/tests/misc/projects/Issue4766/Main1.hx @@ -0,0 +1,15 @@ +class C { + public function new(f) {} + public function f() {} +} + +abstract A(C) { + public function new() { + this = new C(this.f); + } +} + +class Main1 { + static function main() { + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4766/compile1-fail.hxml b/tests/misc/projects/Issue4766/compile1-fail.hxml new file mode 100644 index 00000000..d7a4672b --- /dev/null +++ b/tests/misc/projects/Issue4766/compile1-fail.hxml @@ -0,0 +1,2 @@ +-main Main1 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4766/compile1-fail.hxml.stderr b/tests/misc/projects/Issue4766/compile1-fail.hxml.stderr new file mode 100644 index 00000000..2b300d69 --- /dev/null +++ b/tests/misc/projects/Issue4766/compile1-fail.hxml.stderr @@ -0,0 +1 @@ +Main1.hx:8: characters 21-25 : Missing this = value \ No newline at end of file diff --git a/tests/misc/projects/Issue4775/Main1.hx b/tests/misc/projects/Issue4775/Main1.hx new file mode 100644 index 00000000..7fe6d4ec --- /dev/null +++ b/tests/misc/projects/Issue4775/Main1.hx @@ -0,0 +1,11 @@ +@:generic class Contain { + public function new(t:T) { } +} + +class Main1 { + static function main() { + new Contain(new Main1()); + } + + function new() { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4775/compile1-fail.hxml b/tests/misc/projects/Issue4775/compile1-fail.hxml new file mode 100644 index 00000000..d7a4672b --- /dev/null +++ b/tests/misc/projects/Issue4775/compile1-fail.hxml @@ -0,0 +1,2 @@ +-main Main1 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4775/compile1-fail.hxml.stderr b/tests/misc/projects/Issue4775/compile1-fail.hxml.stderr new file mode 100644 index 00000000..d81bcc17 --- /dev/null +++ b/tests/misc/projects/Issue4775/compile1-fail.hxml.stderr @@ -0,0 +1,2 @@ +Main1.hx:7: characters 2-26 : Constraint check failure for Contain.T +Main1.hx:7: characters 2-26 : Main1 should be String \ No newline at end of file diff --git a/tests/misc/projects/Issue4790/Main.hx b/tests/misc/projects/Issue4790/Main.hx new file mode 100644 index 00000000..78133cb8 --- /dev/null +++ b/tests/misc/projects/Issue4790/Main.hx @@ -0,0 +1,5 @@ +import user2.User2; + +class Main { + public static function main(){} +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4790/builder/Builder.hx b/tests/misc/projects/Issue4790/builder/Builder.hx new file mode 100644 index 00000000..4a11f68b --- /dev/null +++ b/tests/misc/projects/Issue4790/builder/Builder.hx @@ -0,0 +1,26 @@ +package builder; + +#if macro +import haxe.macro.Context; +import haxe.macro.Expr; +import haxe.macro.Type; +#end + +#if !macro +@:autoBuild(builder.Builder.build()) +#end +interface IBuilder {} + +class Builder { + macro static public function build():Array { + var cCur = Context.getLocalClass().get(); + + function loop(c:ClassType) { + var fs = c.fields.get(); + if (c.superClass != null) loop(c.superClass.t.get()); + } + loop(cCur); + + return null; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4790/compile.hxml.disabled b/tests/misc/projects/Issue4790/compile.hxml.disabled new file mode 100644 index 00000000..600ff249 --- /dev/null +++ b/tests/misc/projects/Issue4790/compile.hxml.disabled @@ -0,0 +1,3 @@ +-main Main +-js js.js +--no-output \ No newline at end of file diff --git a/tests/misc/projects/Issue4790/consts/Consts.hx b/tests/misc/projects/Issue4790/consts/Consts.hx new file mode 100644 index 00000000..5bfe3295 --- /dev/null +++ b/tests/misc/projects/Issue4790/consts/Consts.hx @@ -0,0 +1,5 @@ +package consts; + +class Consts { + public static var str:String = "TEST"; +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4790/user1/User1.hx b/tests/misc/projects/Issue4790/user1/User1.hx new file mode 100644 index 00000000..ff09158c --- /dev/null +++ b/tests/misc/projects/Issue4790/user1/User1.hx @@ -0,0 +1,13 @@ +package user1; + +import consts.Consts; +import builder.Builder; + +class User1 implements IBuilder { + var STR:String = Consts.str; + var STR2:String; + function f(){ + STR2 = Consts.str; + var STR3 = Consts.str; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4790/user2/User2.hx b/tests/misc/projects/Issue4790/user2/User2.hx new file mode 100644 index 00000000..1f914b4c --- /dev/null +++ b/tests/misc/projects/Issue4790/user2/User2.hx @@ -0,0 +1,5 @@ +package user2; + +import user1.User1; + +class User2 extends User1 { } \ No newline at end of file diff --git a/tests/misc/projects/Issue4803/Main.hx b/tests/misc/projects/Issue4803/Main.hx new file mode 100644 index 00000000..f1062202 --- /dev/null +++ b/tests/misc/projects/Issue4803/Main.hx @@ -0,0 +1,9 @@ +class Main { + static function main() { + var j = new js.jquery.JQuery(); + j.click(function(e) { + var p = { y : 3 }; + p = { x : 5 }; + }); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4803/compile-fail.hxml b/tests/misc/projects/Issue4803/compile-fail.hxml new file mode 100644 index 00000000..600ff249 --- /dev/null +++ b/tests/misc/projects/Issue4803/compile-fail.hxml @@ -0,0 +1,3 @@ +-main Main +-js js.js +--no-output \ No newline at end of file diff --git a/tests/misc/projects/Issue4803/compile-fail.hxml.stderr b/tests/misc/projects/Issue4803/compile-fail.hxml.stderr new file mode 100644 index 00000000..647dcb39 --- /dev/null +++ b/tests/misc/projects/Issue4803/compile-fail.hxml.stderr @@ -0,0 +1,7 @@ +Main.hx:4: lines 4-7 : Could not find a suitable overload, reasons follow +Main.hx:4: lines 4-7 : Overload resolution failed for Void -> js.jquery.JQuery +Main.hx:4: lines 4-7 : Too many arguments +Main.hx:4: lines 4-7 : Overload resolution failed for handler : (js.jquery.Event -> Void) -> js.jquery.JQuery +Main.hx:6: characters 7-16 : Object requires field y +Main.hx:6: characters 7-16 : For function argument 'handler' +Main.hx:4: lines 4-7 : End of overload failure reasons \ No newline at end of file diff --git a/tests/misc/projects/Issue4816/Main1.hx b/tests/misc/projects/Issue4816/Main1.hx new file mode 100644 index 00000000..10934d6b --- /dev/null +++ b/tests/misc/projects/Issue4816/Main1.hx @@ -0,0 +1,6 @@ +class Main { + static function main() { + var f = { f : { name : "hello" } }; + trace( macro $i{f.name} ); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4816/compile1-fail.hxml b/tests/misc/projects/Issue4816/compile1-fail.hxml new file mode 100644 index 00000000..d7a4672b --- /dev/null +++ b/tests/misc/projects/Issue4816/compile1-fail.hxml @@ -0,0 +1,2 @@ +-main Main1 +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4816/compile1-fail.hxml.stderr b/tests/misc/projects/Issue4816/compile1-fail.hxml.stderr new file mode 100644 index 00000000..21bd6df2 --- /dev/null +++ b/tests/misc/projects/Issue4816/compile1-fail.hxml.stderr @@ -0,0 +1 @@ +Main1.hx:4: characters 24-30 : { f : { name : String } } has no field name \ No newline at end of file diff --git a/tests/misc/projects/Issue4825/Macro.hx b/tests/misc/projects/Issue4825/Macro.hx new file mode 100644 index 00000000..e5ab1772 --- /dev/null +++ b/tests/misc/projects/Issue4825/Macro.hx @@ -0,0 +1,6 @@ +class Macro { + static function buildSomething() { + haxe.macro.Context.defineType(macro class K { }); + return null; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4825/Main.hx b/tests/misc/projects/Issue4825/Main.hx new file mode 100644 index 00000000..ddf37d0d --- /dev/null +++ b/tests/misc/projects/Issue4825/Main.hx @@ -0,0 +1,9 @@ +@:genericBuild(Macro.buildSomething()) +class C { } + +@:eager typedef T = C; + +class Main { + static var k:K; // Type not found : K + public static function main() { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4825/compile.hxml b/tests/misc/projects/Issue4825/compile.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4825/compile.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4904/Main.hx b/tests/misc/projects/Issue4904/Main.hx new file mode 100644 index 00000000..34700622 --- /dev/null +++ b/tests/misc/projects/Issue4904/Main.hx @@ -0,0 +1,10 @@ +class Main { + static function main() { + TestAbstract.f; + } +} + +@:enum +abstract TestAbstract(Int) { + private var f = 0; +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4904/compile-fail.hxml b/tests/misc/projects/Issue4904/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4904/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4904/compile-fail.hxml.stderr b/tests/misc/projects/Issue4904/compile-fail.hxml.stderr new file mode 100644 index 00000000..505065a4 --- /dev/null +++ b/tests/misc/projects/Issue4904/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:3: characters 2-16 : Cannot access private field f \ No newline at end of file diff --git a/tests/misc/projects/Issue4907/Main.hx b/tests/misc/projects/Issue4907/Main.hx new file mode 100644 index 00000000..0ba98131 --- /dev/null +++ b/tests/misc/projects/Issue4907/Main.hx @@ -0,0 +1,15 @@ +package; + +class Main { + static function main() { + var v:EnumAbstract; + switch (v) { + case VALUE: + } + } +} + +@:enum +abstract EnumAbstract(Int) { + public static var VALUE = 0; +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4907/compile-fail.hxml b/tests/misc/projects/Issue4907/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4907/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4907/compile-fail.hxml.stderr b/tests/misc/projects/Issue4907/compile-fail.hxml.stderr new file mode 100644 index 00000000..958af15d --- /dev/null +++ b/tests/misc/projects/Issue4907/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:7: characters 17-22 : Capture variables must be lower-case \ No newline at end of file diff --git a/tests/misc/projects/Issue4954/Main.hx b/tests/misc/projects/Issue4954/Main.hx new file mode 100644 index 00000000..a41c1f1a --- /dev/null +++ b/tests/misc/projects/Issue4954/Main.hx @@ -0,0 +1,9 @@ +class Main { + static var VALUE = 0; + + public static function main() { + switch (0) { + case Main.VALUE: + } + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4954/compile-fail.hxml b/tests/misc/projects/Issue4954/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4954/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4954/compile-fail.hxml.stderr b/tests/misc/projects/Issue4954/compile-fail.hxml.stderr new file mode 100644 index 00000000..584396cc --- /dev/null +++ b/tests/misc/projects/Issue4954/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:6: characters 17-27 : Only inline or read-only (default, never) fields can be used as a pattern \ No newline at end of file diff --git a/tests/misc/projects/Issue4957/Main.hx b/tests/misc/projects/Issue4957/Main.hx new file mode 100644 index 00000000..881198ec --- /dev/null +++ b/tests/misc/projects/Issue4957/Main.hx @@ -0,0 +1,18 @@ +enum E { + A(i:Int); + B; +} + +class Main { + static function main() { + var e = B; + + switch (e) { // Correct: Unmatched patterns: B + case A(10): + } + + var v = switch (e) { // Wrong: Unmatched patterns: A(_) + case A(10): null; + } + } +} diff --git a/tests/misc/projects/Issue4957/compile-fail.hxml b/tests/misc/projects/Issue4957/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4957/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4957/compile-fail.hxml.stderr b/tests/misc/projects/Issue4957/compile-fail.hxml.stderr new file mode 100644 index 00000000..39004555 --- /dev/null +++ b/tests/misc/projects/Issue4957/compile-fail.hxml.stderr @@ -0,0 +1,2 @@ +Main.hx:10: characters 16-17 : Unmatched patterns: B +Main.hx:14: characters 24-25 : Unmatched patterns: B diff --git a/tests/misc/projects/Issue4982/Main.hx b/tests/misc/projects/Issue4982/Main.hx new file mode 100644 index 00000000..8904b6f5 --- /dev/null +++ b/tests/misc/projects/Issue4982/Main.hx @@ -0,0 +1,9 @@ +class Main { + static function main() { + throw invalidChar(65); + } + + static public function invalidChar(c) { + throw "error"; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue4982/compile-fail.hxml b/tests/misc/projects/Issue4982/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue4982/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue4982/compile-fail.hxml.stderr b/tests/misc/projects/Issue4982/compile-fail.hxml.stderr new file mode 100644 index 00000000..cf9577db --- /dev/null +++ b/tests/misc/projects/Issue4982/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:3: characters 14-29 : Cannot use Void as value \ No newline at end of file diff --git a/tests/misc/projects/Issue5005/Main.hx b/tests/misc/projects/Issue5005/Main.hx new file mode 100644 index 00000000..6c69db95 --- /dev/null +++ b/tests/misc/projects/Issue5005/Main.hx @@ -0,0 +1,5 @@ +class Main { + static public function main() { + trace(haxe.rtti.Meta.Meta.getType(Main)); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5005/compile.hxml b/tests/misc/projects/Issue5005/compile.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue5005/compile.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue5010/Main.hx b/tests/misc/projects/Issue5010/Main.hx new file mode 100644 index 00000000..f15628e2 --- /dev/null +++ b/tests/misc/projects/Issue5010/Main.hx @@ -0,0 +1,15 @@ +class Main { + static function main() { + } + + function f(v:Int):String { + switch (v) { + case 1: + var f = function() return 1; + if (Math.random() > 0.5) + return ""; + default: + return null; + } + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5010/compile-fail.hxml b/tests/misc/projects/Issue5010/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue5010/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue5010/compile-fail.hxml.stderr b/tests/misc/projects/Issue5010/compile-fail.hxml.stderr new file mode 100644 index 00000000..474f60d1 --- /dev/null +++ b/tests/misc/projects/Issue5010/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:9: lines 9-10 : Missing return: String \ No newline at end of file diff --git a/tests/misc/projects/Issue5118/Main.hx b/tests/misc/projects/Issue5118/Main.hx new file mode 100644 index 00000000..68d81ff1 --- /dev/null +++ b/tests/misc/projects/Issue5118/Main.hx @@ -0,0 +1,11 @@ +import haxe.ds.Option; + +class Main { + static function main() { + var a = Some(10); + switch (a) { + case None: + case Some(v): + } + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5118/compile1.hxml b/tests/misc/projects/Issue5118/compile1.hxml new file mode 100644 index 00000000..2d506b09 --- /dev/null +++ b/tests/misc/projects/Issue5118/compile1.hxml @@ -0,0 +1 @@ +--display Main.hx@156@type diff --git a/tests/misc/projects/Issue5118/compile1.hxml.stderr b/tests/misc/projects/Issue5118/compile1.hxml.stderr new file mode 100644 index 00000000..65fd706d --- /dev/null +++ b/tests/misc/projects/Issue5118/compile1.hxml.stderr @@ -0,0 +1,3 @@ + +v : Int -> haxe.ds.Option<Int> + \ No newline at end of file diff --git a/tests/misc/projects/Issue5118/compile2.hxml b/tests/misc/projects/Issue5118/compile2.hxml new file mode 100644 index 00000000..f173f6e5 --- /dev/null +++ b/tests/misc/projects/Issue5118/compile2.hxml @@ -0,0 +1 @@ +--display Main.hx@133@type diff --git a/tests/misc/projects/Issue5118/compile2.hxml.stderr b/tests/misc/projects/Issue5118/compile2.hxml.stderr new file mode 100644 index 00000000..90cb3769 --- /dev/null +++ b/tests/misc/projects/Issue5118/compile2.hxml.stderr @@ -0,0 +1,3 @@ + +haxe.ds.Option<Int> + \ No newline at end of file diff --git a/tests/misc/projects/Issue5122/Main.hx b/tests/misc/projects/Issue5122/Main.hx new file mode 100644 index 00000000..91e74b60 --- /dev/null +++ b/tests/misc/projects/Issue5122/Main.hx @@ -0,0 +1,9 @@ +class Main { + static function main() { + inline function start() { + return "foo"; + } + + start(); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5122/compile.hxml b/tests/misc/projects/Issue5122/compile.hxml new file mode 100644 index 00000000..b745b3c3 --- /dev/null +++ b/tests/misc/projects/Issue5122/compile.hxml @@ -0,0 +1 @@ +--display Main.hx@126@type \ No newline at end of file diff --git a/tests/misc/projects/Issue5122/compile.hxml.stderr b/tests/misc/projects/Issue5122/compile.hxml.stderr new file mode 100644 index 00000000..d8857c08 --- /dev/null +++ b/tests/misc/projects/Issue5122/compile.hxml.stderr @@ -0,0 +1,3 @@ + +Void -> String + \ No newline at end of file diff --git a/tests/misc/projects/Issue5123/Main.hx b/tests/misc/projects/Issue5123/Main.hx new file mode 100644 index 00000000..0fb77bea --- /dev/null +++ b/tests/misc/projects/Issue5123/Main.hx @@ -0,0 +1,11 @@ +class Main { + static function main() { + var myShinyVar = 50; + + function doBeautifulThings(who:String) { + return who.length; + } + + doBeautifulThings(myShinyVar); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5123/compile.hxml b/tests/misc/projects/Issue5123/compile.hxml new file mode 100644 index 00000000..7bbe8b38 --- /dev/null +++ b/tests/misc/projects/Issue5123/compile.hxml @@ -0,0 +1 @@ +--display Main.hx@180@position \ No newline at end of file diff --git a/tests/misc/projects/Issue5123/compile.hxml.stderr b/tests/misc/projects/Issue5123/compile.hxml.stderr new file mode 100644 index 00000000..85c4556e --- /dev/null +++ b/tests/misc/projects/Issue5123/compile.hxml.stderr @@ -0,0 +1,3 @@ + +$$normPath(::cwd::/Main.hx, true):5: lines 5-7 + diff --git a/tests/misc/projects/Issue5125/Main.hx b/tests/misc/projects/Issue5125/Main.hx new file mode 100644 index 00000000..9a29b0cf --- /dev/null +++ b/tests/misc/projects/Issue5125/Main.hx @@ -0,0 +1,10 @@ +enum TextDocumentSyncKind { + Incremental; +} + +class Main { + public static inline var syncKind = TextDocumentSyncKind.Incremental; + static function main() { + trace(syncKind); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5125/compile.hxml b/tests/misc/projects/Issue5125/compile.hxml new file mode 100644 index 00000000..14377979 --- /dev/null +++ b/tests/misc/projects/Issue5125/compile.hxml @@ -0,0 +1 @@ +--display Main.hx@90@type \ No newline at end of file diff --git a/tests/misc/projects/Issue5125/compile.hxml.stderr b/tests/misc/projects/Issue5125/compile.hxml.stderr new file mode 100644 index 00000000..d90986d9 --- /dev/null +++ b/tests/misc/projects/Issue5125/compile.hxml.stderr @@ -0,0 +1,3 @@ + +TextDocumentSyncKind + \ No newline at end of file diff --git a/tests/misc/projects/Issue5126/Main.hx b/tests/misc/projects/Issue5126/Main.hx new file mode 100644 index 00000000..295a388c --- /dev/null +++ b/tests/misc/projects/Issue5126/Main.hx @@ -0,0 +1,4 @@ +class Main { + static var command:String = "(?'command'[a-zA-Z]+($|\s+))"; + static function main() { } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5126/compile-fail.hxml b/tests/misc/projects/Issue5126/compile-fail.hxml new file mode 100644 index 00000000..454d4728 --- /dev/null +++ b/tests/misc/projects/Issue5126/compile-fail.hxml @@ -0,0 +1,3 @@ +-main Main +-neko neko.n +--no-output \ No newline at end of file diff --git a/tests/misc/projects/Issue5126/compile-fail.hxml.stderr b/tests/misc/projects/Issue5126/compile-fail.hxml.stderr new file mode 100644 index 00000000..29d1eb83 --- /dev/null +++ b/tests/misc/projects/Issue5126/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:2: character 53 : Invalid escape sequence \s \ No newline at end of file diff --git a/tests/misc/projects/Issue5128/Main.hx b/tests/misc/projects/Issue5128/Main.hx new file mode 100644 index 00000000..1d6e01d2 --- /dev/null +++ b/tests/misc/projects/Issue5128/Main.hx @@ -0,0 +1,3 @@ +class Main { + static function main():Void {} +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5128/compile.hxml b/tests/misc/projects/Issue5128/compile.hxml new file mode 100644 index 00000000..1c03efad --- /dev/null +++ b/tests/misc/projects/Issue5128/compile.hxml @@ -0,0 +1 @@ +--display Main.hx@30@type \ No newline at end of file diff --git a/tests/misc/projects/Issue5128/compile.hxml.stderr b/tests/misc/projects/Issue5128/compile.hxml.stderr new file mode 100644 index 00000000..09b11470 --- /dev/null +++ b/tests/misc/projects/Issue5128/compile.hxml.stderr @@ -0,0 +1,3 @@ + +Void -> Void + \ No newline at end of file diff --git a/tests/misc/projects/Issue5134/Main.hx b/tests/misc/projects/Issue5134/Main.hx new file mode 100644 index 00000000..fd631631 --- /dev/null +++ b/tests/misc/projects/Issue5134/Main.hx @@ -0,0 +1,23 @@ +@:generic +class A { + var items:Array; + public function new() { + items = []; + } + inline public function get(_index:Int) : T { + return items[_index]; + } +} + +class Test { + + var a: A; + + function new() { + + } + static function main() { + trace("Haxe is great!"); + a. + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5134/compile-fail.hxml b/tests/misc/projects/Issue5134/compile-fail.hxml new file mode 100644 index 00000000..d25fbf33 --- /dev/null +++ b/tests/misc/projects/Issue5134/compile-fail.hxml @@ -0,0 +1 @@ +--display Main.hx@323 \ No newline at end of file diff --git a/tests/misc/projects/Issue5134/compile-fail.hxml.stderr b/tests/misc/projects/Issue5134/compile-fail.hxml.stderr new file mode 100644 index 00000000..06410203 --- /dev/null +++ b/tests/misc/projects/Issue5134/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:21: characters 8-9 : Cannot access a in static function \ No newline at end of file diff --git a/tests/misc/projects/Issue5145/Main.hx b/tests/misc/projects/Issue5145/Main.hx new file mode 100644 index 00000000..e58624a4 --- /dev/null +++ b/tests/misc/projects/Issue5145/Main.hx @@ -0,0 +1,69 @@ +import haxe.macro.Context; +import haxe.macro.Type; +import haxe.macro.Expr; +using haxe.macro.Tools; + +interface IA {} +interface IB {} +interface IC extends IA extends IB {} + +class Main { + + static function main() test(); + + macro static function test() { + + function get_type_path(ct:ComplexType) return switch ct { + case TPath(tp):tp; + case _:throw("bad"); + }; + + var td = macro class ID {}; + var ia = macro : Main.IA; + var ib = macro : Main.IB; + var ic = macro : Main.IC; + td.kind = TDClass(null,[ia,ib,ic].map(get_type_path),true); + Context.defineType(td); + var t = Context.getType("ID"); + switch t { + case TInst(_.get()=>tt,_): + if (tt.interfaces.length != 3) + Context.error("Number of extended interfaces must be 3",Context.currentPos()); + case _: + } + + var td = macro class IE {}; + var ia = macro : Main.IA; + var ib = macro : Main.IB; + var ic = macro : Main.IC; + + var ia_tpath = switch ia { + case TPath(tp):tp; + case _:Context.error("must be TPath",Context.currentPos()); + } + td.kind = TDClass(ia_tpath,[ib,ic].map(get_type_path),true); + Context.defineType(td); + + var t = Context.getType("IE"); + switch t { + case TInst(_.get()=>tt,_): + if (tt.interfaces.length != 3) + Context.error("Number of extended interfaces must be 3",Context.currentPos()); + case _: + } + + var reification = macro interface IF extends Main.IA extends Main.IB { + + }; + Context.defineType(reification); + var t = Context.getType("IF"); + switch t { + case TInst(_.get()=>tt,_): + if (tt.interfaces.length != 2){ + Context.error("Number of extended interfaces must be 2",Context.currentPos()); + } + case _: + } + return macro null; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5145/compile.hxml b/tests/misc/projects/Issue5145/compile.hxml new file mode 100644 index 00000000..df3c1759 --- /dev/null +++ b/tests/misc/projects/Issue5145/compile.hxml @@ -0,0 +1,2 @@ + +-main Main \ No newline at end of file diff --git a/tests/misc/projects/Issue5152/Main.hx b/tests/misc/projects/Issue5152/Main.hx new file mode 100644 index 00000000..e2eee30c --- /dev/null +++ b/tests/misc/projects/Issue5152/Main.hx @@ -0,0 +1,6 @@ +class Main { + static function main() { + var who = "world"; + 'hello, $who, how are you'; + } +} diff --git a/tests/misc/projects/Issue5152/compile.hxml b/tests/misc/projects/Issue5152/compile.hxml new file mode 100644 index 00000000..58f08e75 --- /dev/null +++ b/tests/misc/projects/Issue5152/compile.hxml @@ -0,0 +1 @@ +--display Main.hx@87@type \ No newline at end of file diff --git a/tests/misc/projects/Issue5152/compile.hxml.stderr b/tests/misc/projects/Issue5152/compile.hxml.stderr new file mode 100644 index 00000000..6e11be47 --- /dev/null +++ b/tests/misc/projects/Issue5152/compile.hxml.stderr @@ -0,0 +1,3 @@ + +String + \ No newline at end of file diff --git a/tests/misc/projects/Issue5206/Main.hx b/tests/misc/projects/Issue5206/Main.hx new file mode 100644 index 00000000..8ad78ef6 --- /dev/null +++ b/tests/misc/projects/Issue5206/Main.hx @@ -0,0 +1,18 @@ +typedef A = { var pos: Int; var len: Int; }; +typedef NOT_A = { var pos: Array; var len: Array; }; + +typedef X = { @:optional var x:Int; @:optional var y:Int; }; +typedef Y = { var x:Int; var y:Int; }; +typedef Z = { @:optional var pos:Array; @:optional var len:Array; }; + +class Main { + + static var a:A = { pos : 1, len : 2 }; + + static function main(){ + + var not_a:NOT_A = (((a:X):Y):Z); // !!! should obviously not compile + not_a.pos.push(""); + + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5206/compile-fail.hxml b/tests/misc/projects/Issue5206/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue5206/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue5206/compile-fail.hxml.stderr b/tests/misc/projects/Issue5206/compile-fail.hxml.stderr new file mode 100644 index 00000000..32017e21 --- /dev/null +++ b/tests/misc/projects/Issue5206/compile-fail.hxml.stderr @@ -0,0 +1,8 @@ +Main.hx:14: characters 28-33 : A should be X +Main.hx:14: characters 28-33 : { pos : Int, len : Int } should be X +Main.hx:14: characters 28-33 : { pos : Int, len : Int } should be { ?y : Null, ?x : Null } +Main.hx:14: characters 28-33 : { pos : Int, len : Int } has no field x +Main.hx:14: characters 26-39 : Y should be Z +Main.hx:14: characters 26-39 : { y : Int, x : Int } should be Z +Main.hx:14: characters 26-39 : { y : Int, x : Int } should be { ?pos : Null>, ?len : Null> } +Main.hx:14: characters 26-39 : { y : Int, x : Int } has no field len \ No newline at end of file diff --git a/tests/misc/projects/Issue5268/Main.hx b/tests/misc/projects/Issue5268/Main.hx new file mode 100644 index 00000000..66446e6b --- /dev/null +++ b/tests/misc/projects/Issue5268/Main.hx @@ -0,0 +1,19 @@ +import haxe.ds.Option; + +class Main { + public static function main() { + return switch outcome() { + case Some(v): + var value = switch v { + case 1: 1; + case m: return None; + } + value; + case None: + 2; + } + } + + static function outcome() + return Some(1); +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5268/compile-fail.hxml b/tests/misc/projects/Issue5268/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue5268/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue5268/compile-fail.hxml.stderr b/tests/misc/projects/Issue5268/compile-fail.hxml.stderr new file mode 100644 index 00000000..9390a864 --- /dev/null +++ b/tests/misc/projects/Issue5268/compile-fail.hxml.stderr @@ -0,0 +1,2 @@ +Main.hx:5: lines 5-14 : Int should be haxe.ds.Option> +Main.hx:5: lines 5-14 : Int should be haxe.ds.Option> \ No newline at end of file diff --git a/tests/misc/projects/Issue5321/Chest.hx b/tests/misc/projects/Issue5321/Chest.hx new file mode 100644 index 00000000..93055061 --- /dev/null +++ b/tests/misc/projects/Issue5321/Chest.hx @@ -0,0 +1 @@ +class Chest { } \ No newline at end of file diff --git a/tests/misc/projects/Issue5321/Main.hx b/tests/misc/projects/Issue5321/Main.hx new file mode 100644 index 00000000..00da0058 --- /dev/null +++ b/tests/misc/projects/Issue5321/Main.hx @@ -0,0 +1,5 @@ +class Main { + static function main(){ + Test.gt(CHEST); + } +} diff --git a/tests/misc/projects/Issue5321/Test.hx b/tests/misc/projects/Issue5321/Test.hx new file mode 100644 index 00000000..e0a42e1b --- /dev/null +++ b/tests/misc/projects/Issue5321/Test.hx @@ -0,0 +1,16 @@ +enum EnumA{ + EA0; + EA1; + EA2; +} + +enum EnumB{ + CHEST; + EB0; + EB1; + EB2; +} + +class Test{ + public static function gt(?a:EnumA, ?b:EnumB){ } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5321/compile.hxml b/tests/misc/projects/Issue5321/compile.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue5321/compile.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue5375/Main.hx b/tests/misc/projects/Issue5375/Main.hx new file mode 100644 index 00000000..e077603f --- /dev/null +++ b/tests/misc/projects/Issue5375/Main.hx @@ -0,0 +1,16 @@ +enum E { + A; + B( x : Int ); + C; +} + +class Main { + static function main() { + var e : E = null; + switch( e ) { + case A: + case B: + case C: + } + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5375/compile-fail.hxml b/tests/misc/projects/Issue5375/compile-fail.hxml new file mode 100644 index 00000000..c717a287 --- /dev/null +++ b/tests/misc/projects/Issue5375/compile-fail.hxml @@ -0,0 +1,2 @@ +-main Main +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue5375/compile-fail.hxml.stderr b/tests/misc/projects/Issue5375/compile-fail.hxml.stderr new file mode 100644 index 00000000..0b9db02c --- /dev/null +++ b/tests/misc/projects/Issue5375/compile-fail.hxml.stderr @@ -0,0 +1,2 @@ +Main.hx:12: characters 8-9 : x : Int -> E should be E +Main.hx:10: characters 10-11 : Invalid match: Not enough patterns \ No newline at end of file diff --git a/tests/misc/projects/Issue5559/Build.hx b/tests/misc/projects/Issue5559/Build.hx new file mode 100644 index 00000000..c267f89b --- /dev/null +++ b/tests/misc/projects/Issue5559/Build.hx @@ -0,0 +1,5 @@ +class Build { + public static function build() { + return null; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5559/Main.hx b/tests/misc/projects/Issue5559/Main.hx new file mode 100644 index 00000000..c125a223 --- /dev/null +++ b/tests/misc/projects/Issue5559/Main.hx @@ -0,0 +1,5 @@ +class Main { + public static function main() { + OtherClass.foo(); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5559/OtherClass.hx b/tests/misc/projects/Issue5559/OtherClass.hx new file mode 100644 index 00000000..5c7ada51 --- /dev/null +++ b/tests/misc/projects/Issue5559/OtherClass.hx @@ -0,0 +1,5 @@ +class OtherClass { + public static function foo() { + "".endsWith(""); + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5559/build.hxml b/tests/misc/projects/Issue5559/build.hxml new file mode 100644 index 00000000..b4125219 --- /dev/null +++ b/tests/misc/projects/Issue5559/build.hxml @@ -0,0 +1,4 @@ +-main Main +-cp source +--macro addMetadata('@:build(Build.build())', 'Main') +-neko run.n \ No newline at end of file diff --git a/tests/misc/projects/Issue5559/import.hx b/tests/misc/projects/Issue5559/import.hx new file mode 100644 index 00000000..04b6b882 --- /dev/null +++ b/tests/misc/projects/Issue5559/import.hx @@ -0,0 +1 @@ +#if !macro using StringTools; #end \ No newline at end of file diff --git a/tests/misc/projects/Issue5644/Main.hx b/tests/misc/projects/Issue5644/Main.hx new file mode 100644 index 00000000..e481acea --- /dev/null +++ b/tests/misc/projects/Issue5644/Main.hx @@ -0,0 +1,9 @@ +class Main { + static function main() { + return Gen.gen(Main, User); + } +} + +extern class Gen { + public static function gen(type:Dynamic, ?attrs:Dynamic, children:haxe.extern.Rest):Void; +} diff --git a/tests/misc/projects/Issue5644/User.hx b/tests/misc/projects/Issue5644/User.hx new file mode 100644 index 00000000..7d5ff3f0 --- /dev/null +++ b/tests/misc/projects/Issue5644/User.hx @@ -0,0 +1 @@ +class User extends ThisObviouslyDoesntExist {} \ No newline at end of file diff --git a/tests/misc/projects/Issue5644/compile-fail.hxml b/tests/misc/projects/Issue5644/compile-fail.hxml new file mode 100644 index 00000000..74d6c373 --- /dev/null +++ b/tests/misc/projects/Issue5644/compile-fail.hxml @@ -0,0 +1,3 @@ +-main Main +--no-output +-js js.js \ No newline at end of file diff --git a/tests/misc/projects/Issue5644/compile-fail.hxml.stderr b/tests/misc/projects/Issue5644/compile-fail.hxml.stderr new file mode 100644 index 00000000..8541e371 --- /dev/null +++ b/tests/misc/projects/Issue5644/compile-fail.hxml.stderr @@ -0,0 +1,2 @@ +User.hx:1: characters 19-46 : Type not found : ThisObviouslyDoesntExist +Main.hx:1: lines 1-5 : Defined in this class \ No newline at end of file diff --git a/tests/misc/projects/Issue5833/Main.hx b/tests/misc/projects/Issue5833/Main.hx new file mode 100644 index 00000000..f488bcbf --- /dev/null +++ b/tests/misc/projects/Issue5833/Main.hx @@ -0,0 +1,9 @@ +@:enum abstract A(Int) { + var Typo = 0; +} + +class Main { + static public function main() { + var a:A = Typi; + } +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5833/compile-fail.hxml b/tests/misc/projects/Issue5833/compile-fail.hxml new file mode 100644 index 00000000..74d6c373 --- /dev/null +++ b/tests/misc/projects/Issue5833/compile-fail.hxml @@ -0,0 +1,3 @@ +-main Main +--no-output +-js js.js \ No newline at end of file diff --git a/tests/misc/projects/Issue5833/compile-fail.hxml.stderr b/tests/misc/projects/Issue5833/compile-fail.hxml.stderr new file mode 100644 index 00000000..2c349f54 --- /dev/null +++ b/tests/misc/projects/Issue5833/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:7: characters 12-16 : Identifier 'Typi' is not part of A (Suggestion: Typo) \ No newline at end of file diff --git a/tests/misc/projects/Issue5856/Main.hx b/tests/misc/projects/Issue5856/Main.hx new file mode 100644 index 00000000..8ca8276f --- /dev/null +++ b/tests/misc/projects/Issue5856/Main.hx @@ -0,0 +1,11 @@ +class Main { + static function main() { + var hmm = new Hmm(); + trace(hmm); + } +} + +class Hmm { + public function new() {} + function toString() return 'Hmm!'; +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5856/compile.hxml b/tests/misc/projects/Issue5856/compile.hxml new file mode 100644 index 00000000..74d6c373 --- /dev/null +++ b/tests/misc/projects/Issue5856/compile.hxml @@ -0,0 +1,3 @@ +-main Main +--no-output +-js js.js \ No newline at end of file diff --git a/tests/misc/projects/Issue5888/Main.hx b/tests/misc/projects/Issue5888/Main.hx new file mode 100644 index 00000000..8e5174ab --- /dev/null +++ b/tests/misc/projects/Issue5888/Main.hx @@ -0,0 +1,11 @@ +using Main; + +class Main { + static function main() { + 0.bar(); //Should not compile. + } +} + +abstract Foo(Int) { + public function bar() {}; +} \ No newline at end of file diff --git a/tests/misc/projects/Issue5888/compile-fail.hxml b/tests/misc/projects/Issue5888/compile-fail.hxml new file mode 100644 index 00000000..74d6c373 --- /dev/null +++ b/tests/misc/projects/Issue5888/compile-fail.hxml @@ -0,0 +1,3 @@ +-main Main +--no-output +-js js.js \ No newline at end of file diff --git a/tests/misc/projects/Issue5888/compile-fail.hxml.stderr b/tests/misc/projects/Issue5888/compile-fail.hxml.stderr new file mode 100644 index 00000000..106becd9 --- /dev/null +++ b/tests/misc/projects/Issue5888/compile-fail.hxml.stderr @@ -0,0 +1 @@ +Main.hx:5: characters 2-7 : Int has no field bar \ No newline at end of file diff --git a/tests/misc/projects/display-package/compile1.hxml b/tests/misc/projects/display-package/compile1.hxml new file mode 100644 index 00000000..ef11ada1 --- /dev/null +++ b/tests/misc/projects/display-package/compile1.hxml @@ -0,0 +1,2 @@ +-cp src +--display src/C1.hx@0@package diff --git a/tests/misc/projects/display-package/compile1.hxml.stderr b/tests/misc/projects/display-package/compile1.hxml.stderr new file mode 100644 index 00000000..e69de29b diff --git a/tests/misc/projects/display-package/compile2.hxml b/tests/misc/projects/display-package/compile2.hxml new file mode 100644 index 00000000..8ed15bf5 --- /dev/null +++ b/tests/misc/projects/display-package/compile2.hxml @@ -0,0 +1,2 @@ +-cp src +--display src/pack/C2.hx@0@package diff --git a/tests/misc/projects/display-package/compile2.hxml.stderr b/tests/misc/projects/display-package/compile2.hxml.stderr new file mode 100644 index 00000000..33dbcf7f --- /dev/null +++ b/tests/misc/projects/display-package/compile2.hxml.stderr @@ -0,0 +1 @@ +pack diff --git a/tests/misc/projects/display-package/compile3.hxml b/tests/misc/projects/display-package/compile3.hxml new file mode 100644 index 00000000..329f3c10 --- /dev/null +++ b/tests/misc/projects/display-package/compile3.hxml @@ -0,0 +1 @@ +--display src/pack/C2.hx@0@package diff --git a/tests/misc/projects/display-package/compile3.hxml.stderr b/tests/misc/projects/display-package/compile3.hxml.stderr new file mode 100644 index 00000000..b2c2c1bf --- /dev/null +++ b/tests/misc/projects/display-package/compile3.hxml.stderr @@ -0,0 +1 @@ +src.pack diff --git a/tests/misc/projects/display-package/src/C1.hx b/tests/misc/projects/display-package/src/C1.hx new file mode 100644 index 00000000..e69de29b diff --git a/tests/misc/projects/display-package/src/pack/C2.hx b/tests/misc/projects/display-package/src/pack/C2.hx new file mode 100644 index 00000000..e69de29b diff --git a/tests/misc/projects/display-type/compile.hxml.stderr b/tests/misc/projects/display-type/compile.hxml.stderr index d649766b..06272747 100644 --- a/tests/misc/projects/display-type/compile.hxml.stderr +++ b/tests/misc/projects/display-type/compile.hxml.stderr @@ -1,3 +1,3 @@ - + String \ No newline at end of file diff --git a/tests/misc/src/Main.hx b/tests/misc/src/Main.hx index 12aff7e2..1d2775b8 100644 --- a/tests/misc/src/Main.hx +++ b/tests/misc/src/Main.hx @@ -20,13 +20,15 @@ class Main { macro static public function compileProjects():ExprOf { var count = 0; var failures = 0; + var filter = haxe.macro.Context.definedValue("MISC_TEST_FILTER"); + var filterRegex = filter == null ? ~/.*/ : new EReg(filter, ""); function browse(dirPath) { var dir = FileSystem.readDirectory(dirPath); for (file in dir) { var path = Path.join([dirPath, file]); if (FileSystem.isDirectory(path)) { browse(path); - } else if (file.endsWith(".hxml") && !file.endsWith("-each.hxml")) { + } else if (file.endsWith(".hxml") && !file.endsWith("-each.hxml") && filterRegex.match(path)) { var old = Sys.getCwd(); Sys.setCwd(dirPath); Sys.println('Running haxe $path'); @@ -61,12 +63,14 @@ class Main { return new haxe.Template(s).execute(context, macros); } - static function normPath(resolve, p:String):String { + static function normPath(resolve, p:String, properCase = false):String { if (Sys.systemName() == "Windows") { - // on windows, haxe returns lowercase paths with backslashes + // on windows, haxe returns lowercase paths with backslashes, drive letter uppercased + p = p.substr(0, 1).toUpperCase() + p.substr(1); p = p.replace("/", "\\"); - p = p.toLowerCase(); + if (!properCase) + p = p.toLowerCase(); } return p; } @@ -105,7 +109,7 @@ class Main { result = false; } } - + proc.close(); return result; } diff --git a/tests/optimization/run.hxml b/tests/optimization/run.hxml index 87118c7c..5792d910 100644 --- a/tests/optimization/run.hxml +++ b/tests/optimization/run.hxml @@ -1,5 +1,6 @@ -cp src --D analyzer +-D analyzer-optimize +-D analyzer-user-var-fusion --each -main TestAnalyzer @@ -7,6 +8,7 @@ --next -main TestNullChecker +-D analyzer-check-null --interp --next @@ -14,5 +16,5 @@ --macro Macro.register('Test') --macro Macro.register('TestJs') --macro Macro.register('TestLocalDce') -#--macro Macro.register('issues') +--macro Macro.register('issues') -dce std \ No newline at end of file diff --git a/tests/optimization/src/Macro.hx b/tests/optimization/src/Macro.hx index 7aaebbef..408ad22c 100644 --- a/tests/optimization/src/Macro.hx +++ b/tests/optimization/src/Macro.hx @@ -47,6 +47,9 @@ class Macro { case TInst(c, _): c.get(); case _: Context.error('$className should be a class', Context.currentPos()); } + #if !js_unflatten + className = className.replace(".", "_"); + #end var fields = []; function checkField(cf:ClassField) { if (cf.meta.has(":js")) { @@ -62,7 +65,9 @@ class Macro { ++tests; if (output != field.js) { ++failures; - Context.warning('$output should be ${field.js}', field.pos); + Context.warning('Test failed', field.pos); + Context.warning('Expected: ' + field.js, field.pos); + Context.warning('Actual : ' +output, field.pos); } } } diff --git a/tests/optimization/src/Test.hx b/tests/optimization/src/Test.hx index 1ae96149..153e91d0 100644 --- a/tests/optimization/src/Test.hx +++ b/tests/optimization/src/Test.hx @@ -13,9 +13,9 @@ class InlineCtor { } @:analyzer(no_local_dce) -@:analyzer(no_check_has_effect) +@:analyzer(no_user_var_fusion) class Test { - @:js('3;') + @:js('') static function testNoOpRemoval() { 1; 2; @@ -33,8 +33,9 @@ class Test { } @:js(' + var c_y; var c_x = 12; - var c_y = "foo"; + c_y = "foo"; var x = 12; c_x = 13; x = 13; @@ -50,10 +51,12 @@ class Test { @:js(' var a = 0; + var c_y; + var c_x; a = 1; a = 2; - var c_x = 12; - var c_y = "foo"; + c_x = 12; + c_y = "foo"; a = 12; ') static function testInlineCtor2() { @@ -68,11 +71,14 @@ class Test { @:js(' var a = 0; + var b_y; + var b_x; + var c_y; var c_x = 1; - var c_y = "c"; + c_y = "c"; a = 1; - var b_x = 2; - var b_y = "b"; + b_x = 2; + b_y = "b"; b_x = 1; ') static function testInlineCtor3() { @@ -86,8 +92,10 @@ class Test { } @:js(' - var x_foo = 1; - var x_bar = 2; + var x_foo; + var x_bar; + x_foo = 1; + x_bar = 2; var y = 1; var z = 2; ') @@ -100,7 +108,7 @@ class Test { var z = x.bar; } - @:js('var x = { \'oh-my\' : "god"};') + @:js('var x = { "oh-my" : "god"};') static function testStructureInlineInvalidField() { var x = { "oh-my": "god" @@ -119,24 +127,24 @@ class Test { @:js(' var a = [1,2]; - a[-1]; + var b = a[-1]; ') static function testArrayInlineCancelNegative() { var a = [1, 2]; - a[-1]; + var b = a[-1]; } @:js(' var a = [1,2]; - a[2]; + var b = a[2]; ') static function testArrayInlineCancelExceeds() { var a = [1, 2]; - a[2]; + var b = a[2]; } @:js(' - var s = "" + "a"; + var s = "a"; ') static function testAbstractOverStringBinop() { var s = "" + A; @@ -146,7 +154,6 @@ class Test { var a = true; var b = 0; b = 1; - b; ') static function testSwitch1() { var a = true; @@ -155,14 +162,12 @@ class Test { case true: b = 1; case false: b = 2; } - b; // TODO: this should become 1 } @:js(' var a = true; var b = 0; a = true; - a; ') static function testSwitch2() { var a = true; diff --git a/tests/optimization/src/TestAnalyzer.hx b/tests/optimization/src/TestAnalyzer.hx index 838662c0..80749638 100644 --- a/tests/optimization/src/TestAnalyzer.hx +++ b/tests/optimization/src/TestAnalyzer.hx @@ -104,38 +104,51 @@ class TestAnalyzer extends TestBase { assertEqualsConst(1, a); } - //function testUnop() { - //var a = 0; - //assertEqualsConst(0, a++); - //assertEqualsConst(1, a); - //assertEqualsConst(2, ++a); - //assertEqualsConst(2, a); - //if (cond1()) { - //a++; - //} - //assertEquals(3, a); - //} - - //function testMultiAssign() { - //var a; - //var b; - //var c = a = b = 1; - //assertEqualsConst(1, a); - //assertEqualsConst(1, b); - //assertEqualsConst(1, c); - //c = a = b = 2; - //assertEqualsConst(2, a); - //assertEqualsConst(2, b); - //assertEqualsConst(2, c); - //} + function testUnop() { + var a = 0; + assertEqualsConst(0, a++); + assertEqualsConst(1, a); + assertEqualsConst(2, ++a); + assertEqualsConst(2, a); + if (cond1()) { + a++; + } + assertEquals(3, a); + } + + function testOpAssignOp() { + var a = 0; + assertEqualsConst(0, a += a); + assertEqualsConst(0, a); + a += 3; + assertEqualsConst(6, a += a); + assertEqualsConst(6, a); + if (cond1()) { + a += 1; + } + assertEquals(7, a); + } + + function testMultiAssign() { + var a; + var b; + var c = a = b = 1; + assertEqualsConst(1, a); + assertEqualsConst(1, b); + assertEqualsConst(1, c); + c = a = b = 2; + assertEqualsConst(2, a); + assertEqualsConst(2, b); + assertEqualsConst(2, c); + } function testConst1() { var a = 1; a = 2; var b = a; assertEqualsConst(2, b); - //b++; - //assertEqualsConst(3, b); + b++; + assertEqualsConst(3, b); } function testConst2() { @@ -435,18 +448,17 @@ class TestAnalyzer extends TestBase { assertEquals(1, a); } - function testTry1() { - var a = 1; - try { + // function testTry1() { + // var a = 1; + // try { - } catch(e:Dynamic) { - assertEqualsConst(1, a); - a = 2; - assertEqualsConst(2, a); - } - // we do not check for unreachable catch cases at the moment - assertEquals(1, a); - } + // } catch(e:Dynamic) { + // assertEqualsConst(1, a); + // a = 2; + // assertEqualsConst(2, a); + // } + // assertEqualsConst(1, a); + // } function testTry2() { var a = 1; @@ -655,13 +667,13 @@ class TestAnalyzer extends TestBase { assertEquals(4, a); } - //function testMisc() { - //var a = 1; - //function call(a, b, c) { return a + b + c; } - //assertEquals(5, call(assertEqualsConst(1, a), assertEqualsConst(2, a = a + 1), assertEqualsConst(2, a))); - //assertEquals(22, call(assertEqualsConst(2, a++), assertEqualsConst(4, ++a), assertEqualsConst(16, a *= a))); - //assertEquals(50, call(a, a = a + 1, a)); - //} + function testMisc() { + var a = 1; + function call(a, b, c) { return a + b + c; } + assertEquals(5, call(assertEqualsConst(1, a), assertEqualsConst(2, a = a + 1), assertEqualsConst(2, a))); + assertEquals(23, call(assertEqualsConst(3, a = a + 1), assertEqualsConst(4, a = a + 1), assertEqualsConst(16, a = a * a))); + assertEquals(50, call(a, a = a + 1, a)); + } function testEnumValues() { var array = [1]; @@ -677,6 +689,8 @@ class TestAnalyzer extends TestBase { var b = B(0); switch (b) { case B(i): + // Null vs. Int, should not propagate + // Actually we can on dynamic targets. assertEqualsConst(0, i); case A(_): } @@ -694,6 +708,132 @@ class TestAnalyzer extends TestBase { assertEqualsConst(4., r2.y); } + function testApiInline() { + var i = 65; + var f = 3.5; + var s = "foo"; + var bTrue = true; + var bFalse = false; + var eBreak = haxe.macro.Expr.ExprDef.EBreak; + + var floor = Math.floor(f); + assertEqualsConst(3, floor); + + var ceil = Math.ceil(f); + assertEqualsConst(4, ceil); + + var int = Std.int(f); + assertEqualsConst(3, int); + + var string = Std.string(s); + assertEqualsConst("foo", string); + + var string = Std.string(bTrue); + assertEqualsConst("true", string); + + var string = Std.string(bFalse); + assertEqualsConst("false", string); + + var fromCharCode = String.fromCharCode(i); + assertEqualsConst("A", fromCharCode); + + var enumIndex = Type.enumIndex(eBreak); + assertEqualsConst(20, enumIndex); + } + + function testWhilePrune1() { + var a = 0; + while (a == 1) { + a = 1; + break; + } + assertEqualsConst(0, a); + } + + function testWhilePrune2() { + var a = 0; + while (a == 0) { + a = 1; + break; + } + assertEqualsConst(1, a); + } + + function testIfPrune() { + var a = 0; + if (a == 1) { + a = 2; + } + assertEqualsConst(0, a); + } + + function testElsePrune() { + var a = 1; + if (a == 1) { + a = 2; + } else { + a = 3; + } + assertEqualsConst(2, a); + } + + function testThenPrune() { + var a = 2; + if (a == 1) { + a = 2; + } else { + a = 3; + } + assertEqualsConst(3, a); + } + + function testComplexPrune1() { + var a = 0; + var b = 0; + while (b == 0) { + a = 1; + if (cond1()) { + break; + } + b = a - 1; + } + assertEqualsConst(1, a); + assertEqualsConst(0, b); + } + + function testComplexPrune2() { + var a = 0; + var b = 0; + while (true) { + a = 1; + if (b == 1) { + break; + } + a = 2; + if (b == 2) { + break; + } + a = 3; + if (b == 0) { + break; + } + b = a * 0; + } + assertEqualsConst(3, a); + assertEqualsConst(0, b); + } + + function testCapture1() { + var c = 0; + var a = [0, 1, 2]; + var f = function() { + return a[c++]; + } + assertEquals(0, f()); + assertEquals(1, f()); + assertEquals(2, f()); + } + function cond1() { append("cond1"); return true; diff --git a/tests/optimization/src/TestBaseMacro.hx b/tests/optimization/src/TestBaseMacro.hx index 68e26184..e8deb595 100644 --- a/tests/optimization/src/TestBaseMacro.hx +++ b/tests/optimization/src/TestBaseMacro.hx @@ -6,6 +6,8 @@ using StringTools; using haxe.macro.Tools; class TestBaseMacro { + static var numFailures = 0; + macro static public function run() { var c = Context.getLocalClass(); var fields = c.get().fields.get(); @@ -31,6 +33,9 @@ class TestBaseMacro { case _: } } + if (numFailures > 0) { + Sys.exit(1); + } } static function checkClass(c:ClassType) { @@ -45,9 +50,11 @@ class TestBaseMacro { switch [el[0].expr, el[1].expr] { case [TConst(tc1), TConst(tc2)]: if (!constEquals(tc1, tc2)) { + ++numFailures; Context.warning('$tc2 should be $tc1', e.pos); } case [e1, e2]: + ++numFailures; Context.warning('$e2 should be $e1', e.pos); } case TCall({ expr: TField(_, FInstance(_, _, _.get() => {name: "assertEquals"}))}, el): @@ -56,6 +63,7 @@ class TestBaseMacro { } switch (el[1].expr) { case (TConst(tc)): + ++numFailures; Context.warning('Unexpected constant $tc in assertEquals, use assertEqualsConst if this is intended', e.pos); case _: } diff --git a/tests/optimization/src/TestJs.hx b/tests/optimization/src/TestJs.hx index e5324ee8..e49b1df7 100644 --- a/tests/optimization/src/TestJs.hx +++ b/tests/optimization/src/TestJs.hx @@ -4,11 +4,25 @@ private enum Tree { } private enum Some { - one(s1:String); - pair(s1:String, s2:String); - triad(s1:String, s2:String, s3:String); + one(s1:String); + pair(s1:String, s2:String); + triad(s1:String, s2:String, s3:String); } +class Inl{ + public var x:Float; + public inline function new(f){ + x = f; + } +} + +private enum EnumFlagTest { + EA; + EB; + EC; +} + +@:analyzer(no_user_var_fusion) class TestJs { //@:js('var x = 10;"" + x;var x1 = 10;"" + x1;var x2 = 10.0;"" + x2;var x3 = "10";x3;var x4 = true;"" + x4;') //static function testStdString() { @@ -24,19 +38,21 @@ class TestJs { //Std.string(x); //} - @:js("var a = new List();var _g_head = a.h;var _g_val = null;while(_g_head != null) {var tmp;_g_val = _g_head[0];_g_head = _g_head[1];tmp = _g_val;}") + @:js("var a = new List();var _g_head = a.h;while(_g_head != null) _g_head = _g_head.next;") static function testListIteratorInline() { var a = new List(); for (v in a) { } } - @:js("var a = 1;var tmp;var v2 = a;tmp = a + v2;if(tmp > 0) {}") + @:js('var a = 1;var v2 = a;if(a + v2 > 0) {TestJs["use"](a);}') @:analyzer(no_const_propagation) - @:analyzer(no_check_has_effect) + @:analyzer(no_copy_propagation) @:analyzer(no_local_dce) static function testInlineWithArgumentUsedMoreThanOnce() { var a = 1; - if (_inlineWithArgumentUsedMoreThanOnce(a) > 0) { } + if (_inlineWithArgumentUsedMoreThanOnce(a) > 0) { + use(a); + } } inline static function _inlineWithArgumentUsedMoreThanOnce(v) { @@ -44,20 +60,19 @@ class TestJs { return v + v2; } - @:js("var a = [];var tmp;try {tmp = a[0];} catch( e ) {tmp = null;}if(tmp) {}") - @:analyzer(no_check_has_effect) + @:js("var a = [];var tmp;try {tmp = a[0];} catch( e ) {tmp = null;}tmp;") @:analyzer(no_local_dce) static function testInlineWithComplexExpr() { var a = []; if (_inlineWithComplexExpr(a, 0)) {} } - inline static function _inlineWithComplexExpr(a, i) { + inline static function _inlineWithComplexExpr(a:Array, i:Int) { return try a[i] catch (e:Dynamic) null; } - @:js("var a = { v : [{ b : 1}]};a;var tmp;switch(a.v.length) {case 1:switch(a.v[0].b) {case 1:tmp = true;break;default:tmp = false;}break;default:tmp = false;}if(tmp) {}") - @:analyzer(no_const_propagation, no_local_dce, no_check_has_effect) + @:js("var a = { v : [{ b : 1}]};a;a.v.length == 1 && a.v[0].b == 1;") + @:analyzer(no_const_propagation, no_local_dce) static function testDeepMatchingWithoutClosures() { var a = {v: [{b: 1}]}; a; @@ -74,8 +89,8 @@ class TestJs { forEach(function(x) trace(x + 2)); } - @:js('var a = "";var tmp;var __ex0 = a;var _g = __ex0.toLowerCase();switch(_g) {case "e":tmp = 0;break;default:throw new Error();}var e = tmp;') - @:analyzer(no_const_propagation, no_local_dce) + @:js('var a = "";var e;var _hx_tmp = a.toLowerCase();if(_hx_tmp == "e") {e = 0;} else {throw new Error();}') + @:analyzer(no_const_propagation, no_local_dce, no_copy_propagation) static function testRValueSwitchWithExtractors() { var a = ""; var e = switch (a) { @@ -94,7 +109,7 @@ class TestJs { } } - @:js('false;') + @:js('') static function testEnumValuePropagation2() { var v = pair("foo", "bar"); var x = switch (v) { @@ -107,7 +122,7 @@ class TestJs { static inline function verify(s1) return s1 == "foo"; @:js(' - var object = { \'hello\' : "world"}; + var object = { "hello" : "world"}; TestJs["use"](object); ') static function testQuotedStructureFields1() { @@ -118,7 +133,7 @@ class TestJs { } @:js(' - var object = { \'hello\' : "world", world : "hello", \'another\' : "quote"}; + var object = { "hello" : "world", world : "hello", "another" : "quote"}; TestJs["use"](object); ') static function testQuotedStructureFields2() { @@ -130,5 +145,386 @@ class TestJs { use(object); } - static function use(t:T) { } + @:js(' + var object = { "\'" : "world"}; + TestJs["use"](object); + ') + static function testQuotedStructureFields3() { + var object = { + "'": "world", + } + use(object); + } + + @:analyzer(no_local_dce) + @:js('var v0_x = 0;var v1_x = 1;var vRand_x = Math.random();') + // #4558 + static function testInlineFunctionNew() { + var v0 = new Inl(0); + var v1 = new Inl(1); + var vRand = new Inl(Math.random()); + } + + @:js("try {throw new js__$Boot_HaxeError(false);} catch( e ) {}") + static function testNoHaxeErrorUnwrappingWhenNotRequired() { + try throw false catch (e:Dynamic) {} + } + + @:js("try {throw new js__$Boot_HaxeError(false);} catch( e ) {if (e instanceof js__$Boot_HaxeError) e = e.val;console.log(e);}") + static function testHaxeErrorUnwrappingWhenUsed() { + try throw false catch (e:Dynamic) trace(e); + } + + @:js("try {throw new js__$Boot_HaxeError(false);} catch( e ) {if (e instanceof js__$Boot_HaxeError) e = e.val;if( js_Boot.__instanceof(e,Bool) ) {} else throw(e);}") + static function testHaxeErrorUnwrappingWhenTypeChecked() { + try throw false catch (e:Bool) {}; + } + + + @:js('TestJs["use"](2);') + static function testIssue3938() { + var a = 1; + if (a == 1) { + a = 2; + } else { + a = 3; + } + use(a); + } + + @:js(' + TestJs["use"](3); + ') + static function testBinop() { + var a = 1; + var b = 2; + use(a + b); + } + + @:js(' + TestJs["use"](false); + TestJs["use"](true); + TestJs["use"](true); + TestJs["use"](true); + TestJs["use"](false); + TestJs["use"](true); + TestJs["use"](true); + TestJs["use"](false); + TestJs["use"](false); + TestJs["use"](true); + TestJs["use"](false); + ') + static function testEnumValueFlags() { + var flags = new haxe.EnumFlags(); + use(flags.has(EA)); + flags = new haxe.EnumFlags(1); + use(flags.has(EA)); + + // set + flags.set(EB); + use(flags.has(EA)); + use(flags.has(EB)); + use(flags.has(EC)); + + // unset + flags.unset(EC); + use(flags.has(EA)); + use(flags.has(EB)); + use(flags.has(EC)); + flags.unset(EA); + use(flags.has(EA)); + use(flags.has(EB)); + use(flags.has(EC)); + } + + @:js(' + var map = new haxe_ds_StringMap(); + if(__map_reserved["some"] != null) {map.setReserved("some",2);} else {map.h["some"] = 2;} + TestJs["use"](2); + ') + static function testIssue4731() { + var map = new Map(); + var i = map["some"] = 2; + use(i); + } + + @:js(' + var x = TestJs.getInt(); + TestJs.getInt(); + TestJs.call([x,"foo"],TestJs.getInt()); + ') + static function testMightBeAffected1() { + var x = getInt(); + call([x, "foo"], { + getInt(); + getInt(); + }); + } + + @:js(' + var x = TestJs.getInt(); + var tmp = [x,"foo"]; + x = TestJs.getInt(); + TestJs.call(tmp,TestJs.getInt()); + ') + static function testMightBeAffected2() { + var x = getInt(); + call([x, "foo"], { + x = getInt(); + getInt(); + }); + } + + @:js(' + var x = TestJs.getInt(); + var x1 = x; + ++x; + TestJs.call(x1,TestJs.getInt()); + ') + static function testMightBeAffected3() { + var x = getInt(); + call(x, { + x++; + getInt(); + }); + } + + @:js(' + var a = 0; + if(Math.random() < 0.5) { + a = 2; + } + var b = ""; + if(Math.random() < 0.5) { + b = "hello"; + } + TestJs["use"](a); + TestJs["use"](b); + ') + static function testIssue4739() { + var a = 0; + if (Math.random() < 0.5) + a += 2; + + var b = ""; + if (Math.random() < 0.5) + b = b + "hello"; + + use(a); + use(b); + } + + @:js(' + var a = TestJs.getInt(); + TestJs["use"](a); + ') + static function testCopyPropagation1() { + var a = getInt(); + var b = a; + use(b); + } + + @:js(' + var a = TestJs.getInt(); + var b = a; + a = TestJs.getInt(); + TestJs["use"](b); + ') + static function testCopyPropagation2() { + var a = getInt(); + var b = a; + a = getInt(); + use(b); + } + + //@:js(' + //var b = TestJs.getInt(); + //TestJs["use"](b); + //') + //static function testCopyPropagation3() { + //var a; + //{ + //var b = getInt(); + //a = b; + //} + //use(a); + //} + + @:js(' + TestJs.getInt(); + if(TestJs.getInt() != 0) { + throw new js__$Boot_HaxeError("meh"); + } + ') + static function testIfInvert() { + var tmp; + var tmp2 = getInt(); + if (getInt() == 0) { + tmp = tmp2; + } else { + throw "meh"; + } + } + + @:js(' + var d1 = TestJs.intField; + TestJs.call(TestJs["use"](null),d1); + ') + static function testInlineRebuilding1() { + inlineCall(intField, use(null)); + } + + @:js(' + TestJs.call(TestJs["use"](null),TestJs.stringField); + ') + static function testInlineRebuilding2() { + inlineCall(stringField, use(null)); + } + + @:js(' + var a = TestJs.getArray(); + var d1 = a[0]++; + TestJs.call(a[1]++,d1); + ') + static function testInlineRebuilding3() { + var a = getArray(); + inlineCall(a[0]++, a[1]++); + } + + @:js(' + var a = TestJs.getArray(); + a[0] = 1; + a[1] = 2; + TestJs.call(2,1); + ') + static function testInlineRebuilding4() { + var a = getArray(); + inlineCall(a[0] = 1, a[1] = 2); + } + + @:js(' + var a = TestJs.getArray(); + var d1 = a[0] += 1; + TestJs.call(a[1] += 1,d1); + ') + static function testInlineRebuilding5() { + var a = getArray(); + inlineCall(a[0] += 1, a[1] += 1); + } + + @:js(' + var d1 = TestJs.call(1,2); + TestJs.call(TestJs.call(3,4),d1); + ') + static function testInlineRebuilding6() { + inlineCall(call(1, 2), call(3, 4)); + } + + @:js(' + var d1 = TestJs.call(1,2); + var d11 = TestJs.call(TestJs.call(3,4),d1); + var d12 = TestJs.call(5,6); + TestJs.call(TestJs.call(TestJs.call(7,8),d12),d11); + ') + static function testInlineRebuilding7() { + inlineCall(inlineCall(call(1, 2), call(3, 4)), inlineCall(call(5, 6), call(7, 8))); + } + + @:js(' + var d1 = TestJs.call(1,2); + var d11 = TestJs.call(TestJs.intField,d1); + var d12 = TestJs.intField; + TestJs.call(TestJs.call(TestJs.call(5,6),d12),d11); + ') + static function testInlineRebuilding8() { + inlineCall(inlineCall(call(1, 2), intField), inlineCall(intField, call(5, 6))); + } + + @:js(' + var d1 = TestJs.call(TestJs.stringField,TestJs.call(1,2)); + TestJs.call(TestJs.call(TestJs.call(5,6),TestJs.stringField),d1); + ') + static function testInlineRebuilding9() { + inlineCall(inlineCall(call(1, 2), stringField), inlineCall(stringField, call(5, 6))); + } + + @:js(' + var i = TestJs.getInt(); + var a = TestJs.getArray(); + a[i++] = i++; + ') + static function testAssignmentSideEffect() { + var i = getInt(); + var a = getArray(); + a[i++] = i++; + } + + @:js(' + var i = 5; + while(--i >= 0) TestJs["use"](i); + ') + static function testPrefixRebuilding() { + var i:Int = 5; + while (--i >= 0) use(i); + } + + static inline function inlineCall(d1:S, d2:T) { + return call(d2, d1); + } + + @:pure(false) + static function getInt(?d:Dynamic) { return 1; } + static function getArray() { return [0, 1]; } + @:pure(false) + static function call(d1:Dynamic, d2:Dynamic) { return d1; } + @:pure(false) + static function use(t:T) { return t; } + + static var intField = 12; + static var stringField(default, never) = "foo"; + + @:js(' + var _g = Type["typeof"](""); + var v = _g[1] == 6 && _g[2] == String; + TestJs["use"](v); + ') + static function testIssue4745() { + var o = ""; + var v = Type.typeof(o).match(TClass(String)); + use(v); + } + + @:js(' + var e = { }; + e["a"] = 30; + console.log(e); + ') + @:analyzer(user_var_fusion) + static function testIssue4948() { + var e = new haxe.DynamicAccess(); + e["a"] = 30; + trace(e); + } + + + @:js(' + var tmp = "foo"; + Extern.test(tmp); + var tmp1 = "bar"; + Extern.test(tmp1); + var closure = Extern.test; + var tmp2 = "baz"; + closure(tmp2); + ') + static function testAsVar() { + Extern.test("foo"); + var x = "bar"; + Extern.test(x); + var closure = Extern.test; + closure("baz"); + } } + +extern class Extern { + static public function test(e:haxe.extern.AsVar):Void; +} \ No newline at end of file diff --git a/tests/optimization/src/TestLocalDce.hx b/tests/optimization/src/TestLocalDce.hx index 3e64e7f2..a3baad93 100644 --- a/tests/optimization/src/TestLocalDce.hx +++ b/tests/optimization/src/TestLocalDce.hx @@ -13,7 +13,7 @@ private abstract MyEnum(String) to String { var A = "a"; } -@:analyzer(no_check_has_effect) +@:analyzer(no_user_var_fusion) class TestLocalDce { @:js('console.log(3);') static function testNoOpRemoval() { @@ -120,8 +120,7 @@ class TestLocalDce { } @:js(' - var s = "" + "a"; - console.log(s); + console.log("a"); ') static function testAbstractOverStringBinop() { var s = "" + A; @@ -195,5 +194,6 @@ class TestLocalDce { trace(s); } + @:pure(false) static function keep(v:Dynamic) { return v; } } \ No newline at end of file diff --git a/tests/optimization/src/TestNullChecker.hx b/tests/optimization/src/TestNullChecker.hx index f890354f..75c97b06 100644 --- a/tests/optimization/src/TestNullChecker.hx +++ b/tests/optimization/src/TestNullChecker.hx @@ -1,6 +1,5 @@ package ; -@:analyzer(no_check_has_effect) class TestNullChecker extends TestBase { static function main() { @@ -69,6 +68,76 @@ class TestNullChecker extends TestBase { @:analyzer(testIsNotNull) ns; } + function testReturn1() { + var ns = getNullString(); + if (ns == null) { + return; + } + @:analyzer(testIsNotNull) ns; + } + + function testReturn2() { + var ns = getNullString(); + if (ns != null) { + + } else { + return; + } + @:analyzer(testIsNotNull) ns; + } + + // doesn't work yet due to || transformation + //function testReturn3() { + //var ns = getNullString(); + //if (ns == null || getTrue()) { + //return; + //} + //@:analyzer(testIsNotNull) ns; + //} + + function testReturn4() { + var ns = getNullString(); + if (ns != null && getTrue()) { + + } else { + return; + } + @:analyzer(testIsNull) ns; + } + + function testBreak() { + var ns = getNullString(); + while (true) { + if (ns == null) { + break; + } + @:analyzer(testIsNotNull) ns; + } + @:analyzer(testIsNull) ns; + } + + function testContinue() { + var ns = getNullString(); + while (true) { + if (getTrue()) { + break; // to terminate + } + if (ns == null) { + continue; + } + @:analyzer(testIsNotNull) ns; + } + @:analyzer(testIsNull) ns; + } + + function testThrow() { + var ns = getNotNullString(); + if (ns == null) { + throw false; + } + @:analyzer(testIsNotNull) ns; + } + function getString() { return "foo"; } @@ -76,4 +145,16 @@ class TestNullChecker extends TestBase { function getNullString():Null { return null; } + + function getNotNullString():Null { + return "foo"; + } + + function getTrue() { + return true; + } + + function getFalse() { + return false; + } } \ No newline at end of file diff --git a/tests/optimization/src/issues/Issue2236.hx b/tests/optimization/src/issues/Issue2236.hx index 3aa70ca4..88ce1e4f 100644 --- a/tests/optimization/src/issues/Issue2236.hx +++ b/tests/optimization/src/issues/Issue2236.hx @@ -1,45 +1,42 @@ package issues; private class ArrayIterator { - var a : Array; - var pos : Int; - public inline function new(a) { - this.a = a; - this.pos = 0; - } - public inline function hasNext() { - return pos < a.length; - } - public inline function next() { - return a[pos++]; - } + var a : Array; + var pos : Int; + public inline function new(a) { + this.a = a; + this.pos = 0; + } + public inline function hasNext() { + return pos < a.length; + } + public inline function next() { + return a[pos++]; + } } private abstract ArrayRead(Array) { - public inline function new(a) { - this = a; - } + public inline function new(a) { + this = a; + } - function toArray() : Array { - return this; - } + function toArray() : Array { + return this; + } - public inline function iterator() : ArrayIterator { - return new ArrayIterator(this); - } + public inline function iterator() : ArrayIterator { + return new ArrayIterator(this); + } } class Issue2236 { @:js(' - var a = [0]; - var _g_a = a; - var _g_pos = 0; - while(_g_pos < _g_a.length) { - var x = _g_a[_g_pos++]; - x; - } + var _g_pos; + var _g_a = [0]; + _g_pos = 0; + while(_g_pos < _g_a.length) ++_g_pos; ') static function test() { var a = new ArrayRead([0]); diff --git a/tests/optimization/src/issues/Issue3713.hx b/tests/optimization/src/issues/Issue3713.hx index a8241556..9b52d9c2 100644 --- a/tests/optimization/src/issues/Issue3713.hx +++ b/tests/optimization/src/issues/Issue3713.hx @@ -4,6 +4,7 @@ private class A { public function new() {} } +@:native("BImpl") private abstract B(A) { public function new() this = new A(); public inline function f():C return new C(this); @@ -18,10 +19,10 @@ private class C { class Issue3713 { @:js(' - var b = issues._Issue3713.B_Impl_._new(); + var b = BImpl._new(); var c_x = 1; ') - @:analyzer(no_const_propagation, no_local_dce, no_check_has_effect) + @:analyzer(no_const_propagation, no_local_dce) static function test() { var b = new B(); var c = b.f(); diff --git a/tests/optimization/src/issues/Issue4223.hx b/tests/optimization/src/issues/Issue4223.hx new file mode 100644 index 00000000..476b64c6 --- /dev/null +++ b/tests/optimization/src/issues/Issue4223.hx @@ -0,0 +1,64 @@ +package issues; + +@:analyzer(no_local_dce) +class Issue4223 { + @:js('var a = 4;') + static function testCeilPos() { + var a = Math.ceil(3.6); + } + + @:js('var a = -3;') + static function testCeilNeg() { + var a = Math.ceil(-3.6); + } + + @:js('var a = 2147483647;') + static function testCeilMax() { + var a = Math.ceil(2147483646.5); + } + + @:js('var a = -2147483648;') + static function testCeilMin() { + var a = Math.ceil(-2147483648.5); + } + + @:js('var a = Math.ceil(2147483647.5);') + static function testCeilOver() { + var a = Math.ceil(2147483647.5); + } + + @:js('var a = Math.ceil(-2147483649.5);') + static function testCeilUnder() { + var a = Math.ceil(-2147483649.5); + } + + @:js('var a = 3;') + static function testFloorPos() { + var a = Math.floor(3.6); + } + + @:js('var a = -4;') + static function testFloorNeg() { + var a = Math.floor(-3.6); + } + + @:js('var a = 2147483647;') + static function testFloorMax() { + var a = Math.floor(2147483647.5); + } + + @:js('var a = -2147483648;') + static function testFloorMin() { + var a = Math.floor(-2147483647.5); + } + + @:js('Math.floor(2147483648.5);') + static function testFloorOver() { + Math.floor(2147483648.5); + } + + @:js('Math.ceil(-2147483649.5);') + static function testFloorUnder() { + Math.ceil(-2147483649.5); + } +} \ No newline at end of file diff --git a/tests/optimization/src/issues/Issue4690.hx b/tests/optimization/src/issues/Issue4690.hx new file mode 100644 index 00000000..12806b3f --- /dev/null +++ b/tests/optimization/src/issues/Issue4690.hx @@ -0,0 +1,52 @@ +package issues; + +class Parent { + public var x:Int; + public var y:String; + + public inline function new(x:Int, y:String) { + trace("Parent.new: Before assign"); + this.x = x; + this.y = y; + trace("Parent.new: After assign"); + } +} + +class Child extends Parent { + + public var z:Int; + + public inline function new(x:Int, y:Int, z:Int) { + trace("Child.new: Before super"); + super(x, Std.string(y)); + trace("Child.new: After super"); + this.z = z; + trace("Child new: After assign"); + } +} + +class Issue4690 { + @:js(' + var c_z; + var c_y; + var c_x; + console.log("Child.new: Before super"); + console.log("Parent.new: Before assign"); + c_x = 1; + c_y = "" + 2; + console.log("Parent.new: After assign"); + console.log("Child.new: After super"); + c_z = 3; + console.log("Child new: After assign"); + console.log(c_x); + console.log(c_y); + console.log(c_z); + ') + @:analyzer(no_const_propagation, no_fusion) + static function test() { + var c = new Child(1, 2, 3); + trace(c.x); + trace(c.y); + trace(c.z); + } +} \ No newline at end of file diff --git a/tests/optimization/src/issues/Issue5477.hx b/tests/optimization/src/issues/Issue5477.hx new file mode 100644 index 00000000..c3bbdc85 --- /dev/null +++ b/tests/optimization/src/issues/Issue5477.hx @@ -0,0 +1,16 @@ +package issues; + +class Issue5477 { + @:js(' + issues_Issue5477["use"](issues_Issue5477.pureUse(12) > 0.5 ? 1 : issues_Issue5477.pureUse(12)); + ') + static function testIssue5477() { + var v = pureUse(12); + use(pureUse(12) > 0.5 ? 1 : v); + } + + @:pure(false) + static function use(t:T) { return t; } + @:pure + static function pureUse(t:T) { return t; } +} diff --git a/tests/optimization/src/issues/Issue5509.hx b/tests/optimization/src/issues/Issue5509.hx new file mode 100644 index 00000000..f5217be6 --- /dev/null +++ b/tests/optimization/src/issues/Issue5509.hx @@ -0,0 +1,14 @@ +package issues; + +class Issue5509 { + @:js(' + issues_Issue5509["use"](); + ') + static function test() { + var v = "some"; + if (v != null) + use(); + } + + @:pure(false) static function use() { } +} \ No newline at end of file diff --git a/tests/optimization/src/issues/Issue5745.hx b/tests/optimization/src/issues/Issue5745.hx new file mode 100644 index 00000000..600349c0 --- /dev/null +++ b/tests/optimization/src/issues/Issue5745.hx @@ -0,0 +1,25 @@ +package issues; + +class Issue5745 { + @:js(' + var fn = "filename"; + var v = cat(fn); + runProgram.apply(undefined, ["rm",fn]); + console.log(v); + ') + static function test() { + var fn = 'filename'; + var v = Shell.cat(fn); + Shell.runProgram(['rm', fn]); + trace(v); + } +} + +class Shell { + public inline static function runProgram(args:Array):Int { + return untyped __js__('runProgram.apply(undefined, {0})', args); + } + public inline static function cat(v:String):String { + return untyped __js__('cat({0})', v); + } +} \ No newline at end of file diff --git a/tests/optimization/src/issues/Issue5855.hx b/tests/optimization/src/issues/Issue5855.hx new file mode 100644 index 00000000..15929511 --- /dev/null +++ b/tests/optimization/src/issues/Issue5855.hx @@ -0,0 +1,25 @@ +package issues; + +class C { + public var field:String; + public inline function new() { + if (Math.random() > 0.5) { + field = "foo"; + } + } +} + +class Issue5855 { + @:js(' + var c_field; + if(Math.random() > 0.5) { + c_field = "foo"; + } + console.log(c_field); + ') + @:analyzer(ignore) + static function main() { + var c = new C(); + trace(c.field); + } +} \ No newline at end of file diff --git a/tests/optimization/src/issues/Issue5931.hx b/tests/optimization/src/issues/Issue5931.hx new file mode 100644 index 00000000..da6d2a33 --- /dev/null +++ b/tests/optimization/src/issues/Issue5931.hx @@ -0,0 +1,23 @@ +package issues; + +class Issue5931 { + inline function something(arg:Int, func) { + var func1 = func; + func1(arg); + } + + function callback(arg:Int) { + trace('here1'); + } + + inline function new() { + something(1, callback); + } + + @:js(' + new issues_Issue5931(); + ') + static public function main() { + var x = new Issue5931(); + } +} \ No newline at end of file diff --git a/tests/sys/args.xml b/tests/sys/args.xml deleted file mode 100644 index 3fc42ee9..00000000 --- a/tests/sys/args.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - -]]> - ->]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/sys/compile-each.hxml b/tests/sys/compile-each.hxml index 4ad809bf..cb69b2be 100644 --- a/tests/sys/compile-each.hxml +++ b/tests/sys/compile-each.hxml @@ -1,3 +1,9 @@ --debug -cp src --resource args.xml \ No newline at end of file +-main ExitCode +-neko bin/neko/ExitCode.n +-cmd nekotools boot bin/neko/ExitCode.n + +--next + +-debug +-cp src \ No newline at end of file diff --git a/tests/sys/compile-hl.hxml b/tests/sys/compile-hl.hxml new file mode 100644 index 00000000..fa1557d0 --- /dev/null +++ b/tests/sys/compile-hl.hxml @@ -0,0 +1,13 @@ +compile-each.hxml +-main Main +-hl bin/hl/sys.hl + +--next +compile-each.hxml +-main TestArguments +-hl bin/hl/TestArguments.hl + +--next +compile-each.hxml +-main ExitCode +-hl bin/hl/ExitCode.hl \ No newline at end of file diff --git a/tests/sys/compile-lua.hxml b/tests/sys/compile-lua.hxml new file mode 100644 index 00000000..b49002b2 --- /dev/null +++ b/tests/sys/compile-lua.hxml @@ -0,0 +1,14 @@ + +compile-each.hxml +-main Main +-lua bin/lua/sys.lua + +--next +compile-each.hxml +-main TestArguments +-lua bin/lua/TestArguments.lua + +--next +compile-each.hxml +-main ExitCode +-lua bin/lua/ExitCode.lua diff --git a/tests/sys/compile-neko.hxml b/tests/sys/compile-neko.hxml index 7d2306e8..b8a2fa7f 100644 --- a/tests/sys/compile-neko.hxml +++ b/tests/sys/compile-neko.hxml @@ -7,7 +7,7 @@ compile-each.hxml -main TestArguments -neko bin/neko/TestArguments.n ---next -compile-each.hxml --main ExitCode --neko bin/neko/ExitCode.n \ No newline at end of file +# --next +# compile-each.hxml +# -main ExitCode +# -neko bin/neko/ExitCode.n diff --git a/tests/sys/compile-php7.hxml b/tests/sys/compile-php7.hxml new file mode 100644 index 00000000..54533cd0 --- /dev/null +++ b/tests/sys/compile-php7.hxml @@ -0,0 +1,16 @@ +compile-each.hxml +-main Main +-php bin/php7/Main +-D php7 + +--next +compile-each.hxml +-main TestArguments +-php bin/php7/TestArguments +-D php7 + +--next +compile-each.hxml +-main ExitCode +-php bin/php7/ExitCode +-D php7 \ No newline at end of file diff --git a/tests/sys/compile.hxml b/tests/sys/compile.hxml index 7c31ad43..6460bebf 100644 --- a/tests/sys/compile.hxml +++ b/tests/sys/compile.hxml @@ -7,3 +7,5 @@ --next compile-cs.hxml --next compile-java.hxml --next compile-php.hxml +--next compile-php7.hxml +--next compile-hl.hxml diff --git a/tests/sys/lua b/tests/sys/lua new file mode 120000 index 00000000..c8175f8a --- /dev/null +++ b/tests/sys/lua @@ -0,0 +1 @@ +/Users/jdonaldson/bin/lua \ No newline at end of file diff --git a/tests/sys/run.hxml b/tests/sys/run.hxml index fb243816..32a55afa 100644 --- a/tests/sys/run.hxml +++ b/tests/sys/run.hxml @@ -11,6 +11,7 @@ compile.hxml -cmd echo CS && mono bin/cs/bin/Main-Debug.exe -cmd echo Java && java -jar bin/java/Main-Debug.jar -cmd echo Php && php bin/php/Main/index.php +-cmd echo Php7 && php bin/php7/Main/index.php # Windows # --next diff --git a/tests/sys/src/ExitCode.c b/tests/sys/src/ExitCode.c new file mode 100644 index 00000000..f4486cf7 --- /dev/null +++ b/tests/sys/src/ExitCode.c @@ -0,0 +1,10 @@ +#include + +int main(int argc, char *argv[]) +{ + if (argc == 2) { + return atoi(argv[1]); + } else { + return -1; + } +} \ No newline at end of file diff --git a/tests/sys/src/ExitCode.hx b/tests/sys/src/ExitCode.hx index 6c01a37b..e1d69022 100644 --- a/tests/sys/src/ExitCode.hx +++ b/tests/sys/src/ExitCode.hx @@ -1,3 +1,7 @@ +import sys.*; +import sys.io.*; +import haxe.io.*; + /** This is intented to be used by TestSys and io.TestProcess. */ @@ -5,6 +9,8 @@ class ExitCode { static public var bin:String = #if neko "bin/neko/ExitCode.n"; + #elseif hl + "bin/hl/ExitCode.hl"; #elseif cpp #if debug "bin/cpp/ExitCode-debug"; @@ -25,13 +31,63 @@ class ExitCode { #end #elseif python "bin/python/ExitCode.py"; + #elseif php7 + "bin/php7/ExitCode/index.php"; #elseif php "bin/php/ExitCode/index.php"; + #elseif lua + "bin/lua/ExitCode.lua"; #else null; #end - + + static public function getNative():String { + // This is just a script that behaves like ExitCode.hx, + // which exits with the code same as the first given argument. + // var scriptContent = switch (Sys.systemName()) { + // case "Windows": + // '@echo off\nexit /b %1'; + // case "Mac", "Linux", _: + // '#!/bin/sh\nexit $1'; + // } + // var scriptExt = switch (Sys.systemName()) { + // case "Windows": + // ".bat"; + // case "Mac", "Linux", _: + // ".sh"; + // } + + var binExt = switch (Sys.systemName()) { + case "Windows": + ".exe"; + case "Mac", "Linux", _: + ""; + } + + var binPath = Path.join(["bin", "ExitCode"]) + binExt; + if (FileSystem.exists(binPath)) { + return binPath; + } + + if (!FileSystem.exists("bin")) + FileSystem.createDirectory("bin"); + + switch (Sys.systemName()) { + case "Windows": + // var gcc = Sys.command("cl", ["src/ExitCode.c", "/Fobin", "/link", "/out:bin/ExitCode.exe"]); + // if (gcc != 0) + // throw "cannot compile ExitCode"; + File.copy(Path.join(["bin", "neko", "ExitCode"]) + binExt, binPath); + case "Mac", "Linux", _: + var gcc = Sys.command("gcc", ["src/ExitCode.c", "-o", "bin/ExitCode"]); + if (gcc != 0) + throw "cannot compile ExitCode"; + } + + return binPath; + } + static function main():Void { Sys.exit(Std.parseInt(Sys.args()[0])); } -} \ No newline at end of file +} diff --git a/tests/sys/src/FileNames.hx b/tests/sys/src/FileNames.hx index 2b236ed5..a4c4a12a 100644 --- a/tests/sys/src/FileNames.hx +++ b/tests/sys/src/FileNames.hx @@ -1,15 +1,41 @@ class FileNames { static public var names(default, never) = [ "ok", + "ok2", + "ok3", + "ok4", // a space inside "two words", + // some valid seperators + "two-words", + "two_words", + "two,words", + "two.words", + "two;words", + "(two words)", + "[two words]", + // Chinese, Japanese - // "中文,にほんご", + #if !(cs || python || php || neko || cpp || java || lua) + "中文,にほんご", + #end - // "aaa...a" that has 255 characters - // 255 bytes is the max filename length according to http://en.wikipedia.org/wiki/Comparison_of_file_systems - // [for (i in 0...255) "a"].join("") - ]; -} \ No newline at end of file + // "aaa...a" + [for (i in 0...100) "a"].join(""), + ] + // long file name + .concat(switch (Sys.systemName()) { + case "Windows": + // http://stackoverflow.com/a/265782/267998 + []; + case _: + [ + // 255 bytes is the max filename length according to http://en.wikipedia.org/wiki/Comparison_of_file_systems + #if !(python || neko || cpp || java) + [for (i in 0...255) "a"].join(""), + #end + ]; + }); +} diff --git a/tests/sys/src/TestArguments.hx b/tests/sys/src/TestArguments.hx index f81aae7c..066e63bc 100644 --- a/tests/sys/src/TestArguments.hx +++ b/tests/sys/src/TestArguments.hx @@ -3,17 +3,71 @@ It will write the result to "temp/TestArguments.txt" (for debugging). */ class TestArguments extends haxe.unit.TestCase { - static public var expectedArgs(get, null):Array; - static function get_expectedArgs() { - return expectedArgs != null ? expectedArgs : expectedArgs = [ - for (arg in new haxe.xml.Fast(Xml.parse(haxe.Resource.getString("args.xml"))).node.args.nodes.arg) - arg.innerData + // We may compare and update the test cases of other popular langs/libs: https://gist.github.com/andyli/d55ae9ea1327bbbf749d + static public var expectedArgs(default, never):Array = [ + "foo", + "12", + + // symbols + "&", + "&&", + "|", + "||", + ".", + ",", + "<", + ">", + "<<", + ">>", + ":", + ";", + "(", + ")", + "( )", + + // backslashes + "\\", + "\\\\", + "\\\\\\", + + // single quote + "'", + // kind of an escaped single quote + "\\'", + + // double quote + '"', + // kind of an escaped double quote + '\\"', + + // space + " ", + // kind of an escaped space + "\\ ", + + // empty string + "", + + // complex stuff + "a b %PATH% $HOME c\\&<>[\\\"]#{}|%$\\\"\"", + ].concat(switch (Sys.systemName()) { + case "Windows": + []; + case _: + [ + // linebreak + "\n", + + // Chinese, Japanese + "中文,にほんご", ]; - } + }); static public var bin:String = #if neko "bin/neko/TestArguments.n"; + #elseif hl + "bin/hl/TestArguments.hl"; #elseif cpp #if debug "bin/cpp/TestArguments-debug"; @@ -34,8 +88,12 @@ class TestArguments extends haxe.unit.TestCase { #end #elseif python "bin/python/TestArguments.py"; + #elseif php7 + "bin/php7/TestArguments/index.php"; #elseif php "bin/php/TestArguments/index.php"; + #elseif lua + "bin/lua/TestArguments.lua"; #else null; #end @@ -44,7 +102,6 @@ class TestArguments extends haxe.unit.TestCase { function testArgs() { var args = Sys.args(); - // trace(args); for (i in 0...expectedArgs.length) { assertEquals(expectedArgs[i], args[i]); } @@ -64,4 +121,4 @@ class TestArguments extends haxe.unit.TestCase { log.close(); Sys.exit(code); } -} \ No newline at end of file +} diff --git a/tests/sys/src/TestCommandBase.hx b/tests/sys/src/TestCommandBase.hx new file mode 100644 index 00000000..5232e931 --- /dev/null +++ b/tests/sys/src/TestCommandBase.hx @@ -0,0 +1,153 @@ +import sys.*; +import haxe.io.*; + +class TestCommandBase extends haxe.unit.TestCase { + var runInfo:{out:String, err:String} = null; + function run(cmd:String, ?args:Array):Int { + throw "should be overridden"; + } + + function testCommand() { + var bin = FileSystem.absolutePath(TestArguments.bin); + var args = TestArguments.expectedArgs; + + #if !cs + var exitCode = run("haxe", ["compile-each.hxml", "--run", "TestArguments"].concat(args)); + if (exitCode != 0) + trace(sys.io.File.getContent(TestArguments.log)); + assertEquals(0, exitCode); + #end + + var exitCode = + #if (macro || interp) + run("haxe", ["compile-each.hxml", "--run", "TestArguments"].concat(args)); + #elseif cpp + run(bin, args); + #elseif cs + switch (Sys.systemName()) { + case "Windows": + run(bin, args); + case _: + run("mono", [bin].concat(args)); + } + #elseif java + run(Path.join([java.lang.System.getProperty("java.home"), "bin", "java"]), ["-jar", bin].concat(args)); + #elseif python + run(python.lib.Sys.executable, [bin].concat(args)); + #elseif neko + run("neko", [bin].concat(args)); + #elseif hl + run("hl", [bin].concat(args)); + #elseif php + run(untyped __php__("defined('PHP_BINARY') ? PHP_BINARY : 'php'"), [bin].concat(args)); + #elseif lua + if (untyped lua.jit != null){ + run("luajit", [bin].concat(args)); + } else { + run("lua", [bin].concat(args)); + } + #else + -1; + #end + if (exitCode != 0) + trace(sys.io.File.getContent(TestArguments.log)); + assertEquals(0, exitCode); + } + + function testCommandName() { + var binExt = switch (Sys.systemName()) { + case "Windows": + ".exe"; + case "Mac", "Linux", _: + ""; + } + + for (name in FileNames.names) { + if ((name + binExt).length < 256) { + var path = FileSystem.absolutePath("temp/" + name + binExt); + switch (Sys.systemName()) { + case "Windows": + sys.io.File.copy(ExitCode.getNative(), path); + case "Mac", "Linux", _: + var exitCode = run("cp", [ExitCode.getNative(), path]); + assertEquals(0, exitCode); + } + + Sys.sleep(0.1); + + var random = Std.random(256); + var exitCode = try { + run(path, [Std.string(random)]); + } catch (e:Dynamic) { + trace(e); + trace(name); + throw e; + } + if (exitCode != random) + trace(name); + assertEquals(random, exitCode); + FileSystem.deleteFile(path); + } + } + } + + function testExitCode() { + var bin = FileSystem.absolutePath(ExitCode.bin); + + // Just test only a few to save time. + // They have special meanings: http://tldp.org/LDP/abs/html/exitcodes.html + var codes = [0, 1, 2, 126, 127, 128, 130, 255]; + + for (code in codes) { + var args = [Std.string(code)]; + var exitCode = run(ExitCode.getNative(), args); + assertEquals(code, exitCode); + } + + for (code in codes) { + var args = [Std.string(code)]; + var exitCode = + #if (macro || interp) + run("haxe", ["compile-each.hxml", "--run", "ExitCode"].concat(args)); + #elseif cpp + run(bin, args); + #elseif cs + switch (Sys.systemName()) { + case "Windows": + run(bin, args); + case _: + run("mono", [bin].concat(args)); + } + #elseif java + run(Path.join([java.lang.System.getProperty("java.home"), "bin", "java"]), ["-jar", bin].concat(args)); + #elseif python + run(python.lib.Sys.executable, [bin].concat(args)); + #elseif neko + run("neko", [bin].concat(args)); + #elseif hl + run("hl", [bin].concat(args)); + #elseif php + run(untyped __php__("defined('PHP_BINARY') ? PHP_BINARY : 'php'"), [bin].concat(args)); + #elseif lua + if (untyped lua.jit != null){ + run("luajit", [bin].concat(args)); + } else { + run("lua", [bin].concat(args)); + } + #else + -1; + #end + if ((code != exitCode) && (runInfo != null)) { + trace(runInfo); + } + assertEquals(code, exitCode); + } + } + + function testRawCommand() { + var bin = sys.FileSystem.absolutePath(ExitCode.bin); + var native = sys.FileSystem.absolutePath(ExitCode.getNative()); + var exitCode = run('$native 1 || $native 0'); + assertEquals(0, exitCode); + } +} diff --git a/tests/sys/src/TestFileSystem.hx b/tests/sys/src/TestFileSystem.hx index d485326f..450fbcf8 100644 --- a/tests/sys/src/TestFileSystem.hx +++ b/tests/sys/src/TestFileSystem.hx @@ -91,4 +91,21 @@ class TestFileSystem extends haxe.unit.TestCase { FileSystem.deleteDirectory(dir + "complex"); } } + + function testWindowsSpecialCases() { + if (Sys.systemName() != "Windows" #if python || true #end) { + assertTrue(true); + return; + } + var withSlash = "C:/"; + var withBackslash = "C:\\"; + var without = "C:"; + + for (path in [withSlash, withBackslash, without]) { + assertTrue(FileSystem.exists(path)); + assertTrue(FileSystem.isDirectory(path)); + assertTrue(FileSystem.stat(path) != null); + assertTrue(FileSystem.readDirectory(path) != null); + } + } } \ No newline at end of file diff --git a/tests/sys/src/TestSys.hx b/tests/sys/src/TestSys.hx index a860ee68..afb16f1e 100644 --- a/tests/sys/src/TestSys.hx +++ b/tests/sys/src/TestSys.hx @@ -1,164 +1,51 @@ -class TestSys extends haxe.unit.TestCase { - #if !php //FIXME https://github.com/HaxeFoundation/haxe/issues/3603#issuecomment-86437474 - function testCommand() { - var bin = sys.FileSystem.absolutePath(TestArguments.bin); - var args = TestArguments.expectedArgs; - - var exitCode = Sys.command("haxe", ["compile-each.hxml", "--run", "TestArguments"].concat(args)); - if (exitCode != 0) - trace(sys.io.File.getContent(TestArguments.log)); - assertEquals(0, exitCode); - - var exitCode = - #if (macro || interp) - Sys.command("haxe", ["compile-each.hxml", "--run", "TestArguments"].concat(args)); - #elseif cpp - Sys.command(bin, args); - #elseif cs - switch (Sys.systemName()) { - case "Windows": - Sys.command(bin, args); - case _: - Sys.command("mono", [bin].concat(args)); - } - #elseif java - Sys.command("java", ["-jar", bin].concat(args)); - #elseif python - Sys.command("python3", [bin].concat(args)); - #elseif neko - Sys.command("neko", [bin].concat(args)); - #elseif php - Sys.command("php", [bin].concat(args)); - #else - -1; - #end - if (exitCode != 0) - trace(sys.io.File.getContent(TestArguments.log)); - assertEquals(0, exitCode); +class TestSys extends TestCommandBase { + override function run(cmd:String, ?args:Array):Int { + return Sys.command(cmd, args); } - #if !cs //FIXME - function testCommandName() { - // This is just a script that behaves like ExitCode.hx, - // which exits with the code same as the first given argument. - var scriptContent = switch (Sys.systemName()) { - case "Windows": - '@echo off\nexit /b %1'; - case "Mac", "Linux", _: - '#!/bin/sh\nexit $1'; - } - for (name in FileNames.names) { - //call with ext - var scriptExt = switch (Sys.systemName()) { - case "Windows": - ".bat"; - case "Mac", "Linux", _: - ".sh"; - } - var path = sys.FileSystem.absolutePath("temp/" + name + scriptExt); - sys.io.File.saveContent(path, scriptContent); - - switch (Sys.systemName()) { - case "Mac", "Linux": - var exitCode = Sys.command("chmod", ["a+x", path]); - assertEquals(0, exitCode); - case "Windows": - //pass - } - - var random = Std.random(256); - var exitCode = Sys.command(path, [Std.string(random)]); - if (exitCode != random) - trace(name); - assertEquals(random, exitCode); - sys.FileSystem.deleteFile(path); - - - - //call without ext - var scriptExt = switch (Sys.systemName()) { - case "Windows": - ".bat"; - case "Mac", "Linux", _: - ""; - } - var path = sys.FileSystem.absolutePath("temp/" + name + scriptExt); - sys.io.File.saveContent(path, scriptContent); - - switch (Sys.systemName()) { - case "Mac", "Linux": - var exitCode = Sys.command("chmod", ["a+x", path]); - assertEquals(0, exitCode); - case "Windows": - //pass - } - - var random = Std.random(256); - var exitCode = Sys.command(path, [Std.string(random)]); - if (exitCode != random) - trace(name); - assertEquals(random, exitCode); - sys.FileSystem.deleteFile(path); - } - } - #end //!cs - - function testExitCode() { - var bin = sys.FileSystem.absolutePath(ExitCode.bin); - - // Just test only a few to save time. - // They have special meanings: http://tldp.org/LDP/abs/html/exitcodes.html - var codes = [0, 1, 2, 126, 127, 128, 130, 255]; - - for (code in codes) { - var args = [Std.string(code)]; - var exitCode = Sys.command("haxe", ["compile-each.hxml", "--run", "ExitCode"].concat(args)); - assertEquals(code, exitCode); - } - - for (code in codes) { - var args = [Std.string(code)]; - var exitCode = - #if (macro || interp) - Sys.command("haxe", ["compile-each.hxml", "--run", "ExitCode"].concat(args)); - #elseif cpp - Sys.command(bin, args); - #elseif cs - switch (Sys.systemName()) { - case "Windows": - Sys.command(bin, args); - case _: - Sys.command("mono", [bin].concat(args)); - } - #elseif java - Sys.command("java", ["-jar", bin].concat(args)); - #elseif python - Sys.command("python3", [bin].concat(args)); - #elseif neko - Sys.command("neko", [bin].concat(args)); - #elseif php - Sys.command("php", [bin].concat(args)); - #else - -1; - #end - assertEquals(code, exitCode); - } - } - #end - function testEnv() { - #if !(java || php) + #if !(java || php || lua) Sys.putEnv("foo", "value"); assertEquals("value", Sys.getEnv("foo")); #end assertEquals(null, Sys.getEnv("doesn't exist")); - #if !(java || php) + #if !(java || php || lua) var env = Sys.environment(); assertEquals("value", env.get("foo")); #end } + function testProgramPath() { + var p = Sys.programPath(); + + assertTrue(haxe.io.Path.isAbsolute(p)); + assertTrue(sys.FileSystem.exists(p)); + + #if interp + assertTrue(StringTools.endsWith(p, "Main.hx")); + #elseif neko + assertTrue(StringTools.endsWith(p, "sys.n")); + #elseif cpp + switch (Sys.systemName()) { + case "Windows": + assertTrue(StringTools.endsWith(p, "Main-debug.exe")); + case _: + assertTrue(StringTools.endsWith(p, "Main-debug")); + } + #elseif cs + assertTrue(StringTools.endsWith(p, "Main-Debug.exe")); + #elseif java + assertTrue(StringTools.endsWith(p, "Main-Debug.jar")); + #elseif python + assertTrue(StringTools.endsWith(p, "sys.py")); + #elseif php + assertTrue(StringTools.endsWith(p, "index.php")); + #elseif lua + assertTrue(StringTools.endsWith(p, "sys.lua")); + #end + } + #if !java function testCwd() { var cur = Sys.getCwd(); diff --git a/tests/sys/src/io/TestProcess.hx b/tests/sys/src/io/TestProcess.hx index 3dc3a384..f8393732 100644 --- a/tests/sys/src/io/TestProcess.hx +++ b/tests/sys/src/io/TestProcess.hx @@ -2,154 +2,15 @@ package io; import sys.io.Process; -class TestProcess extends haxe.unit.TestCase { - #if !php //FIXME - function testArguments() { - var bin = sys.FileSystem.absolutePath(TestArguments.bin); - var args = TestArguments.expectedArgs; - - var process = new Process("haxe", ["compile-each.hxml", "--run", "TestArguments"].concat(args)); - var exitCode = process.exitCode(); - if (exitCode != 0) - trace(sys.io.File.getContent(TestArguments.log)); - assertEquals(0, exitCode); - - var process = - #if (macro || interp) - new Process("haxe", ["compile-each.hxml", "--run", "TestArguments"].concat(args)); - #elseif cpp - new Process(bin, args); - #elseif cs - switch (Sys.systemName()) { - case "Windows": - new Process(bin, args); - case _: - new Process("mono", [bin].concat(args)); - } - #elseif java - new Process("java", ["-jar", bin].concat(args)); - #elseif python - new Process("python3", [bin].concat(args)); - #elseif neko - new Process("neko", [bin].concat(args)); - #elseif php - new Process("php", [bin].concat(args)); - #else - null; - #end - var exitCode = process.exitCode(); - if (exitCode != 0) - trace(sys.io.File.getContent(TestArguments.log)); - assertEquals(0, exitCode); - } - - #if !(neko || cpp || cs) //FIXME - function testCommandName() { - // This is just a script that behaves like ExitCode.hx, - // which exits with the code same as the first given argument. - var scriptContent = switch (Sys.systemName()) { - case "Windows": - '@echo off\nexit /b %1'; - case "Mac", "Linux", _: - '#!/bin/sh\nexit $1'; - } - for (name in FileNames.names) { - //call with ext - var scriptExt = switch (Sys.systemName()) { - case "Windows": - ".bat"; - case "Mac", "Linux", _: - ".sh"; - } - var path = sys.FileSystem.absolutePath("temp/" + name + scriptExt); - sys.io.File.saveContent(path, scriptContent); - - switch (Sys.systemName()) { - case "Mac", "Linux": - var exitCode = Sys.command("chmod", ["a+x", path]); - assertEquals(0, exitCode); - case "Windows": - //pass - } - - var random = Std.random(256); - var exitCode = new Process(path, [Std.string(random)]).exitCode(); - if (exitCode != random) - trace(name); - assertEquals(random, exitCode); - sys.FileSystem.deleteFile(path); - - - - //call without ext - var scriptExt = switch (Sys.systemName()) { - case "Windows": - ".bat"; - case "Mac", "Linux", _: - ""; - } - var path = sys.FileSystem.absolutePath("temp/" + name + scriptExt); - sys.io.File.saveContent(path, scriptContent); - - switch (Sys.systemName()) { - case "Mac", "Linux": - var exitCode = Sys.command("chmod", ["a+x", path]); - assertEquals(0, exitCode); - case "Windows": - //pass - } - - var random = Std.random(256); - var exitCode = new Process(path, [Std.string(random)]).exitCode(); - if (exitCode != random) - trace(name); - assertEquals(random, exitCode); - sys.FileSystem.deleteFile(path); - } - } - #end //!neko - - #end //!php - - function testExitCode() { - var bin = sys.FileSystem.absolutePath(ExitCode.bin); - - // Just test only a few to save time. - // They have special meanings: http://tldp.org/LDP/abs/html/exitcodes.html - var codes = [0, 1, 2, 126, 127, 128, 130, 255]; - - for (code in codes) { - var args = [Std.string(code)]; - var process = new Process("haxe", ["compile-each.hxml", "--run", "ExitCode"].concat(args)); - assertEquals(code, process.exitCode()); - } - - for (code in codes) { - var args = [Std.string(code)]; - var process = - #if (macro || interp) - new Process("haxe", ["compile-each.hxml", "--run", "ExitCode"].concat(args)); - #elseif cpp - new Process(bin, args); - #elseif cs - switch (Sys.systemName()) { - case "Windows": - new Process(bin, args); - case _: - new Process("mono", [bin].concat(args)); - } - #elseif java - new Process("java", ["-jar", bin].concat(args)); - #elseif python - new Process("python3", [bin].concat(args)); - #elseif neko - new Process("neko", [bin].concat(args)); - #elseif php - new Process("php", [bin].concat(args)); - #else - null; - #end - assertEquals(code, process.exitCode()); - } +class TestProcess extends TestCommandBase { + override function run(cmd:String, ?args:Array):Int { + var p = new Process(cmd, args); + var exitCode = p.exitCode(); + runInfo = { + out: p.stdout.readAll().toString(), + err: p.stderr.readAll().toString(), + }; + p.close(); + return exitCode; } -} \ No newline at end of file +} diff --git a/tests/unit/compile-as3.hxml b/tests/unit/compile-as3.hxml index ae09966f..a74f0c6b 100644 --- a/tests/unit/compile-as3.hxml +++ b/tests/unit/compile-as3.hxml @@ -1,4 +1,4 @@ compile-each.hxml --main unit.Test +-main unit.TestMain -as3 bin/as3 -cmd mxmlc -static-link-runtime-shared-libraries=true -debug bin/as3/__main__.as --output bin/unit9_as3.swf \ No newline at end of file diff --git a/tests/unit/compile-cpp.hxml b/tests/unit/compile-cpp.hxml index 4593f40c..fe9a4a1b 100644 --- a/tests/unit/compile-cpp.hxml +++ b/tests/unit/compile-cpp.hxml @@ -1,4 +1,5 @@ compile-each.hxml --main unit.Test +-main unit.TestMain -cpp bin/cpp --D NO_PRECOMPILED_HEADERS \ No newline at end of file +-D HXCPP_NO_DEBUG_LINK +-lib record-macros diff --git a/tests/unit/compile-cppia-host.hxml b/tests/unit/compile-cppia-host.hxml index 458da551..82e7494c 100644 --- a/tests/unit/compile-cppia-host.hxml +++ b/tests/unit/compile-cppia-host.hxml @@ -4,3 +4,5 @@ -debug -dce no -cpp bin/cppia +-cp src +--macro include("scripthost") diff --git a/tests/unit/compile-cppia.hxml b/tests/unit/compile-cppia.hxml index f17dcbd8..21108aaa 100644 --- a/tests/unit/compile-cppia.hxml +++ b/tests/unit/compile-cppia.hxml @@ -1,6 +1,4 @@ compile-each.hxml --main unit.Test --cpp unit.cppia --D cppia --D NO_PRECOMPILED_HEADERS ---macro cpp.cppia.HostClasses.exclude() +-main unit.TestMain +-cppia bin/unit.cppia +-lib record-macros diff --git a/tests/unit/compile-cs-travis.hxml b/tests/unit/compile-cs-travis.hxml index cc2b19cd..02646f14 100644 --- a/tests/unit/compile-cs-travis.hxml +++ b/tests/unit/compile-cs-travis.hxml @@ -1,7 +1,8 @@ compile-cs.hxml -net-lib cs_drivers/System.Data.dll --net-lib cs_drivers/System.Xml.dll +-net-lib cs_drivers/System.Xml.dll@std -net-lib cs_drivers/Mono.Data.Sqlite.dll -D travis +-lib record-macros diff --git a/tests/unit/compile-cs-unsafe-travis.hxml b/tests/unit/compile-cs-unsafe-travis.hxml index 58529e2d..8667cd18 100644 --- a/tests/unit/compile-cs-unsafe-travis.hxml +++ b/tests/unit/compile-cs-unsafe-travis.hxml @@ -1,7 +1,7 @@ compile-cs-unsafe.hxml -net-lib cs_drivers/System.Data.dll --net-lib cs_drivers/System.Xml.dll +-net-lib cs_drivers/System.Xml.dll@std -net-lib cs_drivers/Mono.Data.Sqlite.dll -D travis diff --git a/tests/unit/compile-cs-unsafe.hxml b/tests/unit/compile-cs-unsafe.hxml index dd18b815..5f800332 100644 --- a/tests/unit/compile-cs-unsafe.hxml +++ b/tests/unit/compile-cs-unsafe.hxml @@ -4,7 +4,7 @@ --next compile-each.hxml --main unit.Test +-main unit.TestMain -D unsafe -cs bin/cs_unsafe -net-lib native_cs/bin/native_cs.dll diff --git a/tests/unit/compile-cs.hxml b/tests/unit/compile-cs.hxml index e9d4c18b..a015b5ef 100644 --- a/tests/unit/compile-cs.hxml +++ b/tests/unit/compile-cs.hxml @@ -4,6 +4,6 @@ --next compile-each.hxml --main unit.Test +-main unit.TestMain -cs bin/cs -net-lib native_cs/bin/native_cs.dll diff --git a/tests/unit/compile-each.hxml b/tests/unit/compile-each.hxml index 66523fb7..bb5c10af 100644 --- a/tests/unit/compile-each.hxml +++ b/tests/unit/compile-each.hxml @@ -5,4 +5,5 @@ -resource res1.txt@re/s?!%[]))("'1.txt -resource res2.bin@re/s?!%[]))("'1.bin -dce full -#-D analyzer +-D analyzer-optimize +-D analyzer-user-var-fusion \ No newline at end of file diff --git a/tests/unit/compile-flash9.hxml b/tests/unit/compile-flash9.hxml index 662a0739..611299ad 100644 --- a/tests/unit/compile-flash9.hxml +++ b/tests/unit/compile-flash9.hxml @@ -1,4 +1,4 @@ compile-each.hxml --main unit.Test +-main unit.TestMain -swf-version 11 -swf bin/unit9.swf \ No newline at end of file diff --git a/tests/unit/compile-hl.hxml b/tests/unit/compile-hl.hxml new file mode 100644 index 00000000..89cbcf8d --- /dev/null +++ b/tests/unit/compile-hl.hxml @@ -0,0 +1,5 @@ +compile-each.hxml +-main unit.TestMain +-hl bin/unit.hl +-D interp +-D hl-check diff --git a/tests/unit/compile-java.hxml b/tests/unit/compile-java.hxml index 00605193..82e75733 100644 --- a/tests/unit/compile-java.hxml +++ b/tests/unit/compile-java.hxml @@ -4,8 +4,9 @@ --next compile-each.hxml --main unit.Test +-main unit.TestMain -java bin/java -java-lib native_java/native.jar -java-lib java_drivers/mysql-connector-java-5.1.32-bin.jar -java-lib java_drivers/sqlite-jdbc-3.7.2.jar +-lib record-macros diff --git a/tests/unit/compile-js.hxml b/tests/unit/compile-js.hxml index 16667398..0e298e04 100644 --- a/tests/unit/compile-js.hxml +++ b/tests/unit/compile-js.hxml @@ -6,5 +6,5 @@ --next compile-each.hxml -unit.Test +unit.TestMain -js bin/unit.js \ No newline at end of file diff --git a/tests/unit/compile-lua.hxml b/tests/unit/compile-lua.hxml new file mode 100644 index 00000000..9c1ab5c5 --- /dev/null +++ b/tests/unit/compile-lua.hxml @@ -0,0 +1,3 @@ +compile-each.hxml +-main unit.TestMain +-lua bin/unit.lua diff --git a/tests/unit/compile-macro.hxml b/tests/unit/compile-macro.hxml index 094c8738..7a437456 100644 --- a/tests/unit/compile-macro.hxml +++ b/tests/unit/compile-macro.hxml @@ -1,3 +1,3 @@ compile-each.hxml --main unit.Test +-main unit.TestMain --interp \ No newline at end of file diff --git a/tests/unit/compile-neko.hxml b/tests/unit/compile-neko.hxml index c3cd2019..f569988d 100644 --- a/tests/unit/compile-neko.hxml +++ b/tests/unit/compile-neko.hxml @@ -1,4 +1,5 @@ compile-each.hxml -D neko_v2 --main unit.Test --neko bin/unit.n \ No newline at end of file +-main unit.TestMain +-neko bin/unit.n +-lib record-macros diff --git a/tests/unit/compile-php.hxml b/tests/unit/compile-php.hxml index 71ed464d..0a295c68 100644 --- a/tests/unit/compile-php.hxml +++ b/tests/unit/compile-php.hxml @@ -1,3 +1,4 @@ compile-each.hxml --main unit.Test --php bin/php \ No newline at end of file +-main unit.TestMain +-php bin/php +-lib record-macros diff --git a/tests/unit/compile-php7.hxml b/tests/unit/compile-php7.hxml new file mode 100644 index 00000000..72e0be11 --- /dev/null +++ b/tests/unit/compile-php7.hxml @@ -0,0 +1,5 @@ +compile-each.hxml +-main unit.TestMain +-lib record-macros +-php bin/php7 +-D php7 \ No newline at end of file diff --git a/tests/unit/compile-python.hxml b/tests/unit/compile-python.hxml index 4fcb80d0..60e66237 100644 --- a/tests/unit/compile-python.hxml +++ b/tests/unit/compile-python.hxml @@ -1,3 +1,3 @@ compile-each.hxml --main unit.Test +-main unit.TestMain -python bin/unit.py \ No newline at end of file diff --git a/tests/unit/compile-saucelabs-runner.hxml b/tests/unit/compile-saucelabs-runner.hxml index d1eb9f60..2fd3fc97 100644 --- a/tests/unit/compile-saucelabs-runner.hxml +++ b/tests/unit/compile-saucelabs-runner.hxml @@ -1,5 +1,5 @@ -cp src -js bin/RunSauceLabs.js -main RunSauceLabs --lib nodejs +-lib hxnodejs -debug \ No newline at end of file diff --git a/tests/unit/compile.hxml b/tests/unit/compile.hxml index 4bead634..4a90d859 100644 --- a/tests/unit/compile.hxml +++ b/tests/unit/compile.hxml @@ -16,8 +16,10 @@ compile-java-runner.hxml --next compile-flash9.hxml --next compile-js.hxml +--next compile-lua.hxml --next compile-neko.hxml --next compile-php.hxml +--next compile-php7.hxml --next compile-as3.hxml --next compile-cpp.hxml --next compile-java.hxml diff --git a/tests/unit/native_cs/src/haxe/test/Base.cs b/tests/unit/native_cs/src/haxe/test/Base.cs index 80a5a6d9..822665b0 100644 --- a/tests/unit/native_cs/src/haxe/test/Base.cs +++ b/tests/unit/native_cs/src/haxe/test/Base.cs @@ -3,6 +3,7 @@ namespace haxe.test public class Base { + ~Base() { someString = null; } //some haxe-specific keywords public static readonly int inline = 42; @@ -39,6 +40,13 @@ public class Base get { return i * 20; } } + public int Issue4325 { get; protected set; } + + public void setIssue4325(int val) + { + this.Issue4325 = val; + } + public int this[int i, int j] { get { return i * j; } @@ -81,6 +89,8 @@ public class Base public class InnerClass : Base { + ~InnerClass() { privateField = 0; } + private int privateField = 42; //protected override without explicit override tag diff --git a/tests/unit/native_cs/src/haxe/test/MyClass.cs b/tests/unit/native_cs/src/haxe/test/MyClass.cs index e4b5286f..acbde2b3 100644 --- a/tests/unit/native_cs/src/haxe/test/MyClass.cs +++ b/tests/unit/native_cs/src/haxe/test/MyClass.cs @@ -82,6 +82,7 @@ public class MyClass voidvoid2.Invoke(); } + public readonly int readonlyField = 5; } public delegate void VoidVoid(); diff --git a/tests/unit/native_cs/src/haxe/test/StaticAndInstanceClash.cs b/tests/unit/native_cs/src/haxe/test/StaticAndInstanceClash.cs index 4a92c1c1..f9a0ccbe 100644 --- a/tests/unit/native_cs/src/haxe/test/StaticAndInstanceClash.cs +++ b/tests/unit/native_cs/src/haxe/test/StaticAndInstanceClash.cs @@ -3,6 +3,7 @@ namespace haxe.test public class StaticAndInstanceClash : Base.InnerClass { + ~StaticAndInstanceClash() {} public static string someString; public class StaticAndInstanceClashSame : StaticAndInstanceClash diff --git a/tests/unit/src/RunSauceLabs.hx b/tests/unit/src/RunSauceLabs.hx index 12b653cf..8de87da4 100644 --- a/tests/unit/src/RunSauceLabs.hx +++ b/tests/unit/src/RunSauceLabs.hx @@ -25,6 +25,7 @@ private typedef Promise = { -browsers A list of browsers to test with in JSON format. Default: refer to source code When a test finishes, it should set `window.success` to a boolean. + For urls with the string `-es5`, IE <= 8 will be automatically skipped. */ class RunSauceLabs { static function successMsg(msg:String):Void { @@ -37,6 +38,12 @@ class RunSauceLabs { console.log('\x1b[36m' + msg + '\x1b[0m'); } + static function isEs5(b:Dynamic):Bool { + return + // not IE <= 8 + !(b.browserName == "internet explorer" && Std.parseInt(b.version) <= 8); + } + static function main():Void { var serveDomain = "localhost"; var servePort = "2000"; @@ -44,37 +51,46 @@ class RunSauceLabs { var connectPort = "4445"; var urls = []; + // hide "Stop running this script?" dialogs + // https://support.saucelabs.com/customer/portal/articles/2057026-how-to-hide-%22stop-running-this-script-%22-dialogs + // https://gist.github.com/andyli/948045e8f9d7b28104c2e2751d77d04a + var hideLongRunningScriptWarning = "https://gist.githubusercontent.com/andyli/948045e8f9d7b28104c2e2751d77d04a/raw/bfe5af9a94175c19d87131cc9bb059872e8d170f/IEMaxScriptStatements.bat"; + //https://saucelabs.com/platforms var browsers:Array = [ // { // "browserName": "internet explorer", // "platform": "Windows XP", - // "version": "6" + // "version": "6.0", + // "prerun": hideLongRunningScriptWarning // }, // { // "browserName": "internet explorer", // "platform": "Windows XP", - // "version": "7" + // "version": "7.0", + // "prerun": hideLongRunningScriptWarning // }, { "browserName": "internet explorer", "platform": "Windows XP", - "version": "8" + "version": "8.0", + "prerun": hideLongRunningScriptWarning }, { "browserName": "internet explorer", "platform": "Windows 7", - "version": "9" + "version": "9.0", + "prerun": hideLongRunningScriptWarning }, { "browserName": "internet explorer", "platform": "Windows 7", - "version": "10" + "version": "10.0" }, { "browserName": "internet explorer", "platform": "Windows 8.1", - "version": "11" + "version": "11.0" }, { "browserName": "chrome", @@ -87,47 +103,23 @@ class RunSauceLabs { { "browserName": "safari", "platform": "OS X 10.8", - "version": "6" + "version": "6.0" }, { "browserName": "safari", "platform": "OS X 10.9", - "version": "7" + "version": "7.0" }, { "browserName": "safari", "platform": "OS X 10.10", - "version": "8" + "version": "8.0" }, { "browserName": "safari", "platform": "OS X 10.11", - "version": "8.1" - }, - { - "browserName": "iphone", - "platform": "OS X 10.8", - "version": "6.1", - "device-orientation": "portrait" - }, - { - "browserName": "iphone", - "platform": "OS X 10.9", - "version": "8.1", - "device-orientation": "portrait" - }, - { - "browserName": "android", - "platform": "Linux", - "version": "4.0", - "device-orientation": "portrait" + "version": "9.0" }, - { - "browserName": "android", - "platform": "Linux", - "version": "4.3", - "device-orientation": "portrait" - } ]; var arg, args = process.argv.slice(2); @@ -190,8 +182,7 @@ class RunSauceLabs { .sauceJobUpdate({ passed: true, tags: tags.concat(["errored"]) }) .then(function() return browser.quit()) .timeout(commandTimeout * 1000) - .fail(onErrored) - .then(function() return testBrowser(caps, trials)); + .fin(function() return testBrowser(caps, trials)); } else { allSuccess = false; return null; @@ -211,6 +202,11 @@ class RunSauceLabs { } var browserSuccess = true; + var urls = if (!isEs5(caps)) { + urls.filter(function(url:String) return url.indexOf("js-es=3") != -1); + } else { + urls; + } return browser .init(caps) @@ -262,9 +258,9 @@ class RunSauceLabs { }) .then(function() return browser.sauceJobUpdate({ passed: browserSuccess })) + .fail(onErrored) .then(function() - return browser.quit()) - .fail(onErrored); + return browser.quit()); } browsers @@ -273,6 +269,9 @@ class RunSauceLabs { }, q()) .then(function() { Sys.exit(allSuccess ? 0 : 1); + }) + .fail(function() { + Sys.exit(1); }); } } diff --git a/tests/unit/src/scripthost/Issue5351.hx b/tests/unit/src/scripthost/Issue5351.hx new file mode 100644 index 00000000..f5a56eb4 --- /dev/null +++ b/tests/unit/src/scripthost/Issue5351.hx @@ -0,0 +1,41 @@ +package scripthost; + +@:keep class Issue5351 { + public function new() { + //initialize variables + } + + public function doTest1() { + return 'doTest1'; + } + + public function doTest2() { + return 'doTest2'; + } + + public static function callDoTest1(i:Issue5351) { + return i.doTest1(); + } + + public static function callDoTest2(i:Issue5351) { + return i.doTest2(); + } +} + +@:keep class Issue5351_2 extends Issue5351 { + public function doTest3() { + return 'doTest3'; + } + + public static function callDoTest1(i:Issue5351_2) { + return i.doTest1(); + } + + public static function callDoTest2(i:Issue5351_2) { + return i.doTest2(); + } + + public static function callDoTest3(i:Issue5351_2) { + return i.doTest3(); + } +} diff --git a/tests/unit/src/unit/HelperMacros.hx b/tests/unit/src/unit/HelperMacros.hx new file mode 100644 index 00000000..200c1028 --- /dev/null +++ b/tests/unit/src/unit/HelperMacros.hx @@ -0,0 +1,54 @@ +package unit; + +import haxe.macro.Expr; + +class HelperMacros { + static public macro function getCompilationDate() { + return macro $v { Std.string(Date.now()) }; + } + + static public macro function typedAs(actual:haxe.macro.Expr, expected:haxe.macro.Expr) { + var tExpected = haxe.macro.Context.typeof(expected); + var tActual = haxe.macro.Context.typeof(actual); + return haxe.macro.Context.parse("eq('" +Std.string(tActual) + "', '" +Std.string(tExpected) + "')", haxe.macro.Context.currentPos()); + } + + static public macro function typeError(e:haxe.macro.Expr) { + var result = try { + haxe.macro.Context.typeof(e); + "false"; + } catch (e:Dynamic) "true"; + return { pos: haxe.macro.Context.currentPos(), expr: haxe.macro.Expr.ExprDef.EConst(haxe.macro.Expr.Constant.CIdent(result)) }; + } + + static public macro function typeErrorText(e:haxe.macro.Expr) { + var result = try { + haxe.macro.Context.typeof(e); + null; + } catch (e:haxe.macro.Expr.Error) e.message; + return { + pos: haxe.macro.Context.currentPos(), + expr: if (result == null) + haxe.macro.Expr.ExprDef.EConst(haxe.macro.Expr.Constant.CIdent("null")) + else + haxe.macro.Expr.ExprDef.EConst(haxe.macro.Expr.Constant.CString(result)) + }; + } + + static public macro function getMeta(e) { + switch(e.expr) { + case EMeta(m, _): + return macro { name: $v{m.name}, args: $a{m.params} }; + default: + return macro report("Metadata expected"); + } + } + + static public macro function getErrorMessage(e:Expr) { + var result = try { + haxe.macro.Context.typeof(e); + "no error"; + } catch (e:Dynamic) Std.string(e.message); + return macro $v{result}; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/MyAbstract.hx b/tests/unit/src/unit/MyAbstract.hx index f4b38ac3..2bebbea7 100644 --- a/tests/unit/src/unit/MyAbstract.hx +++ b/tests/unit/src/unit/MyAbstract.hx @@ -2,17 +2,17 @@ package unit; abstract MyAbstract(Int) { - public inline function new(x) { - this = x; - } + public inline function new(x) { + this = x; + } - public inline function incr() { - return ++this; - } + public inline function incr() { + return ++this; + } - public inline function toInt() : Int { - return this; - } + public inline function toInt() : Int { + return this; + } } diff --git a/tests/unit/src/unit/MyClass.hx b/tests/unit/src/unit/MyClass.hx index 1450727b..307b86b0 100644 --- a/tests/unit/src/unit/MyClass.hx +++ b/tests/unit/src/unit/MyClass.hx @@ -197,7 +197,7 @@ class UsingChild2 extends UsingBase { class UsingUnrelated { static public function test() { - var err = TestType.typeError("foo".privFunc()); + var err = HelperMacros.typeError("foo".privFunc()); return err + "foo".pupFunc() + "foo".siblingFunc(); } } diff --git a/tests/unit/src/unit/MyMacro.hx b/tests/unit/src/unit/MyMacro.hx index 0a47d85c..25233688 100644 --- a/tests/unit/src/unit/MyMacro.hx +++ b/tests/unit/src/unit/MyMacro.hx @@ -1,6 +1,7 @@ package unit; import haxe.macro.Expr; +import haxe.macro.Context; class MyRestMacro { static public macro function testRest1(e:Expr, r:Array) { @@ -16,4 +17,22 @@ class MyRestMacro { ret.push(e); return macro $a{ret}; } -} \ No newline at end of file +} + +class MyMacroHelper +{ + static public macro function followWithAbstracts(e1:Expr):Expr + { + return macro $v{Context.followWithAbstracts(Context.typeof(e1)) + ""}; + } + + static public macro function followWithAbstractsOnce(e1:Expr):Expr + { + return macro $v{Context.followWithAbstracts(Context.typeof(e1),true) + ""}; + } + + static public macro function ttype(e1:Expr):Expr + { + return macro $v{Context.typeof(e1) + ""}; + } +} diff --git a/tests/unit/src/unit/MySpodClass.hx b/tests/unit/src/unit/MySpodClass.hx index 0654a2f1..1f245132 100644 --- a/tests/unit/src/unit/MySpodClass.hx +++ b/tests/unit/src/unit/MySpodClass.hx @@ -4,33 +4,44 @@ import sys.db.Types; @:keep class MySpodClass extends Object { - public var theId:SId; - public var int:SInt; - public var double:SFloat; - public var boolean:SBool; - public var string:SString<255>; - public var date:SDateTime; - public var binary:SBinary; + public var theId:SId; + public var int:SInt; + public var double:SFloat; + public var boolean:SBool; + public var string:SString<255>; + public var date:SDateTime; + public var binary:SBinary; public var abstractType:AbstractSpodTest; - public var nullInt:SNull; - public var enumFlags:SFlags; + public var nullInt:SNull; + public var enumFlags:SFlags; - @:relation(rid) public var relation:OtherSpodClass; - @:relation(rnid) public var relationNullable:Null; + @:relation(rid) public var relation:OtherSpodClass; + @:relation(rnid) public var relationNullable:Null; @:relation(spid) public var next:Null; - public var data:SData>; - public var anEnum:SEnum; + public var data:SData>; + public var anEnum:SEnum; + public var bytes:SBytes<2>; } @:keep class NullableSpodClass extends Object { public var theId:SId; - @:relation(rnid) public var relationNullable:Null; - public var data:Null>>; - public var abstractType:Null>; + @:relation(rnid) public var relationNullable:Null; + public var data:Null>>; public var anEnum:Null>; + + public var int:SNull; + public var double:SNull; + public var boolean:SNull; + public var string:SNull>; + public var date:SNull; + public var binary:SNull; + public var abstractType:SNull>; + + public var nullInt:SNull; + public var enumFlags:SNull>; } @:keep class ComplexClass @@ -71,7 +82,7 @@ abstract AbstractSpodTest(A) from A } @:id(name) -@:keep class ClassWithStringId extends Object + @:keep class ClassWithStringId extends Object { public var name:SString<255>; public var field:SInt; @@ -86,9 +97,9 @@ abstract AbstractSpodTest(A) from A //issue #3828 @:keep @:skip class BaseIssueC3828 extends sys.db.Object { - public var id : SInt; - @:relation(ruid) - public var refUser : SNull; + public var id : SInt; + @:relation(ruid) + public var refUser : SNull; } @:keep class IssueC3828 extends BaseIssueC3828 { diff --git a/tests/unit/src/unit/Test.hx b/tests/unit/src/unit/Test.hx index bc235c6d..3f6774b5 100644 --- a/tests/unit/src/unit/Test.hx +++ b/tests/unit/src/unit/Test.hx @@ -7,7 +7,6 @@ import cpp.link.StaticSqlite; import cpp.link.StaticZlib; #end -@:expose("unit.Test") @:keepSub #if as3 @:publicFields @@ -185,9 +184,9 @@ class Test { } static function logVerbose(msg:String) { - #if (cpp || neko || php) - Sys.println(msg); - #end + #if (cpp || neko || php) + Sys.println(msg); + #end } static var count = 0; @@ -252,7 +251,7 @@ class Test { } static function resetTimer() { - #if (neko || php || cpp || java || cs || python) + #if (neko || php || cpp || java || cs || python || hl || lua) #else if( timer != null ) timer.stop(); timer = new haxe.Timer(30000); @@ -273,136 +272,8 @@ class Test { success = false; reportInfos = null; trace("STACK :\n"+stack); +#if lua + Sys.exit(1); +#end } - - static function main() { - var verbose = #if ( cpp || neko || php ) Sys.args().indexOf("-v") >= 0 #else false #end; - - #if cs //"Turkey Test" - Issue #996 - cs.system.threading.Thread.CurrentThread.CurrentCulture = new cs.system.globalization.CultureInfo('tr-TR'); - cs.Lib.applyCultureChanges(); - #end - #if neko - if( neko.Web.isModNeko ) - neko.Web.setHeader("Content-Type","text/plain"); - #elseif php - if( php.Web.isModNeko ) - php.Web.setHeader("Content-Type","text/plain"); - #end - resetTimer(); - #if !macro - trace("Generated at: " + TestType.getCompilationDate()); - #end - trace("START"); - #if flash - var tf : flash.text.TextField = untyped flash.Boot.getTrace(); - tf.selectable = true; - tf.mouseEnabled = true; - #end - var classes = [ - new TestOps(), - new TestBasetypes(), - new TestBytes(), - new TestIO(), - new TestLocals(), - new TestEReg(), - new TestXML(), - new TestMisc(), - new TestJson(), - new TestResource(), - new TestInt64(), - new TestReflect(), - new TestSerialize(), - new TestMeta(), - new TestType(), - new TestOrder(), - new TestGADT(), - new TestGeneric(), - #if !no_pattern_matching - new TestMatch(), - #end - new TestSpecification(), - #if cs - new TestCSharp(), - #end - #if java - new TestJava(), - #end - #if python - new TestPython(), - #end - #if php - new TestPhp(), - #end - #if (java || cs) - new TestOverloads(), - #end - #if ((dce == "full") && !interp && !as3) - new TestDCE(), - #end - // #if ( (java || neko) && !macro && !interp) - // new TestThreads(), - // #end - //new TestUnspecified(), - //new TestRemoting(), - ]; - // SPOD tests - #if ( (neko || (php && (travis || php_sqlite)) || java || cpp || (cs && travis)) && !macro && !interp) - #if ( travis && !(cpp || cs) ) - if (Sys.getEnv("CI") != null && Sys.systemName() == "Linux") - { - classes.push(new TestSpod(sys.db.Mysql.connect({ - host : "localhost", - user : "travis", - pass : "", - port : 3306, - database : "haxe_test" }))); - } - #end - if (verbose) - logVerbose("Setup sqlite"); - classes.push(new TestSpod(sys.db.Sqlite.open("db.db3"))); - #end - TestIssues.addIssueClasses("src/unit/issues", "unit.issues"); - TestIssues.addIssueClasses("src/unit/hxcpp_issues", "unit.hxcpp_issues"); - var current = null; - #if (!fail_eager) - try - #end - { - asyncWaits.push(null); - for( inst in classes ) { - current = Type.getClass(inst); - if (verbose) - logVerbose("Class " + Std.string(current) ); - for( f in Type.getInstanceFields(current) ) - if( f.substr(0,4) == "test" ) { - if (verbose) - logVerbose(" " + f); - #if fail_eager - Reflect.callMethod(inst,Reflect.field(inst,f),[]); - #else - try { - Reflect.callMethod(inst,Reflect.field(inst,f),[]); - } - #if !as3 - catch( e : Dynamic ) { - onError(e,"EXCEPTION",Type.getClassName(current)+"."+f); - } - #end - #end - reportInfos = null; - } - } - asyncWaits.remove(null); - checkDone(); - } - #if (!as3 && !(fail_eager)) - catch( e : Dynamic ) { - asyncWaits.remove(null); - onError(e,"ABORTED",Type.getClassName(current)); - } - #end - } - } diff --git a/tests/unit/src/unit/TestBasetypes.hx b/tests/unit/src/unit/TestBasetypes.hx index 5f88e27d..97a9857c 100644 --- a/tests/unit/src/unit/TestBasetypes.hx +++ b/tests/unit/src/unit/TestBasetypes.hx @@ -448,13 +448,19 @@ class TestBasetypes extends Test { var v1:unit.MyAbstract.MyVector = new unit.MyAbstract.MyPoint3(1, 1, 1); var v2:unit.MyAbstract.MyVector = new unit.MyAbstract.MyPoint3(1, 2, 3); eq("(2,3,4)", v1 + v2); +#if !lua eq("(2,4,6)", v2 * 2.); +#end var v1Old = v1; v1 *= 2.; +#if !lua eq("(2,2,2)", v1); +#end eq(v1Old, v1); var v3 = v1 * 2.; +#if !lua eq("(4,4,4)", v3); +#end f(v1 == v3); var i:unit.MyAbstract.MyInt = 1; @@ -504,7 +510,9 @@ class TestBasetypes extends Test { eq(a.f, null); var i:Dynamic = 1; - var a:{?f:Int} = i; - unspec(function() a.f); + unspec(function() { + var a:{?f:Int} = i; // allowed to fail at runtime + unspec(function() a.f); + }); } } diff --git a/tests/unit/src/unit/TestBytes.hx b/tests/unit/src/unit/TestBytes.hx index c0bdfcda..a91c64b7 100644 --- a/tests/unit/src/unit/TestBytes.hx +++ b/tests/unit/src/unit/TestBytes.hx @@ -106,7 +106,6 @@ class TestBytes extends Test { eq(input.readAll().toString(), "One é accent"); } - #if !php // https://github.com/HaxeFoundation/haxe/issues/4060 function testFastGet() { var b = haxe.io.Bytes.alloc(10); var bd = b.getData(); @@ -138,5 +137,4 @@ class TestBytes extends Test { eq(b1.getString(0,2), b2.getString(0,2)); } - #end -} \ No newline at end of file +} diff --git a/tests/unit/src/unit/TestCSharp.hx b/tests/unit/src/unit/TestCSharp.hx index 243c13c0..03326339 100644 --- a/tests/unit/src/unit/TestCSharp.hx +++ b/tests/unit/src/unit/TestCSharp.hx @@ -24,6 +24,14 @@ class TestCSharp extends Test { #if cs + function testIssue4325() + { + var b = new Base(); + eq(b.Issue4325, 0); + b.setIssue4325(10); + eq(b.Issue4325, 10); + } + // -net-lib tests function testHaxeKeywords() { @@ -37,7 +45,7 @@ class TestCSharp extends Test function testIssue3474() { - var a:IEditableTextBuffer = null; + var a:IEditableTextBuffer = cast null; eq(a,null); var didRun = false; try @@ -248,7 +256,7 @@ class TestCSharp extends Test t(run); //var dyn:Dynamic = v; - //t(Std.is(dyn, haxe.test.VoidVoid)); + //t((dyn is haxe.test.VoidVoid)); } var didRun = false; @@ -389,6 +397,24 @@ class TestCSharp extends Test //issue #2308 var fn = getEnumValue; eq(0x100, Reflect.callMethod(null, fn, [TEnumWithValue.TVA])); + + var e = getTVA(); + switch(e) { + case TVA if (getEnumValue(e) == getEnumValue(getTVA())): + t(true); + case _: + t(false); + } + + var e = getTVB(); + switch(e) { + case TVA: + t(false); + case TVB if (getEnumValue(e) != getEnumValue(getTVA())): + t(true); + case _: + t(false); + } } static function getEnumValue(e:TEnumWithValue):Int @@ -766,47 +792,49 @@ private class TestMyClass extends haxe.test.MyClass private interface IEventIface { @:keep - @:event private var IfaceEvent1:Action_1; - function add_IfaceEvent1(cb:Action_1):Void; - function remove_IfaceEvent1(cb:Action_1):Void; - - @:keep - @:event private var IfaceEvent2:Action_1; - function add_IfaceEvent2(cb:Action_1):Void; - function remove_IfaceEvent2(cb:Action_1):Void; + @:event private var IfaceEvent1:Action_1; + function add_IfaceEvent1(cb:Action_1):Void; + function remove_IfaceEvent1(cb:Action_1):Void; + + @:keep + @:event private var IfaceEvent2:Action_1; + function add_IfaceEvent2(cb:Action_1):Void; + function remove_IfaceEvent2(cb:Action_1):Void; } @:publicFields private class EventClass implements IEventIface { function new() {} - @:event private var Event1:Action_1; - function add_Event1(cb:Action_1) {} - function remove_Event1(cb:Action_1) {} - function invokeEvent1(i) if (Event1 != null) Event1.Invoke(i); - - @:event private var Event2:Action_1; - var event2Counter = 0; - function add_Event2(cb:Action_1) event2Counter++; - function remove_Event2(cb:Action_1) event2Counter--; - - @:event private static var SEvent1:Action_1; - static function add_SEvent1(cb:Action_1) {} - static function remove_SEvent1(cb:Action_1) {} - static function invokeSEvent1(i) if (SEvent1 != null) SEvent1.Invoke(i); - - @:event private static var SEvent2:Action_1; - static var sEvent2Counter = 0; - static function add_SEvent2(cb:Action_1) sEvent2Counter++; - static function remove_SEvent2(cb:Action_1) sEvent2Counter--; - - @:event private var IfaceEvent1:Action_1; - function add_IfaceEvent1(cb:Action_1) {} - function remove_IfaceEvent1(cb:Action_1) {} - function invokeIfaceEvent1(i) if (IfaceEvent1 != null) IfaceEvent1.Invoke(i); - - @:event private var IfaceEvent2:Action_1; - var ifaceEvent2Counter = 0; - function add_IfaceEvent2(cb:Action_1) ifaceEvent2Counter++; - function remove_IfaceEvent2(cb:Action_1) ifaceEvent2Counter--; + @:event private var Event1:Action_1; + function add_Event1(cb:Action_1) {} + function remove_Event1(cb:Action_1) {} + function invokeEvent1(i) if (Event1 != null) Event1.Invoke(i); + + @:keep + @:event private var Event2:Action_1; + var event2Counter = 0; + function add_Event2(cb:Action_1) event2Counter++; + function remove_Event2(cb:Action_1) event2Counter--; + + @:event private static var SEvent1:Action_1; + static function add_SEvent1(cb:Action_1) {} + static function remove_SEvent1(cb:Action_1) {} + static function invokeSEvent1(i) if (SEvent1 != null) SEvent1.Invoke(i); + + @:keep + @:event private static var SEvent2:Action_1; + static var sEvent2Counter = 0; + static function add_SEvent2(cb:Action_1) sEvent2Counter++; + static function remove_SEvent2(cb:Action_1) sEvent2Counter--; + + @:event private var IfaceEvent1:Action_1; + function add_IfaceEvent1(cb:Action_1) {} + function remove_IfaceEvent1(cb:Action_1) {} + function invokeIfaceEvent1(i) if (IfaceEvent1 != null) IfaceEvent1.Invoke(i); + + @:event private var IfaceEvent2:Action_1; + var ifaceEvent2Counter = 0; + function add_IfaceEvent2(cb:Action_1) ifaceEvent2Counter++; + function remove_IfaceEvent2(cb:Action_1) ifaceEvent2Counter--; } diff --git a/tests/unit/src/unit/TestDCE.hx b/tests/unit/src/unit/TestDCE.hx index 06a47379..75a0f670 100644 --- a/tests/unit/src/unit/TestDCE.hx +++ b/tests/unit/src/unit/TestDCE.hx @@ -1,6 +1,6 @@ package unit; -@:analyzer(no_check_has_effect, no_local_dce) +@:analyzer(no_local_dce) class DCEClass { // used statics static function staticUsed() { } @@ -32,16 +32,16 @@ class DCEClass { function get_memberPropUnused() return 0; function set_memberPropUnused(i:Int) return 0; - static var c :Array = [null, unit.UsedReferenced2]; + static var c:Array = [null, unit.UsedReferenced2]; public function new() { staticUsed(); - staticVarUsed; + staticVarUsed = "foo"; staticPropUsed = 1; staticPropUsed; memberUsed(); - memberVarUsed; + memberVarUsed = 0; memberPropUsed = 2; memberPropUsed; @@ -50,10 +50,11 @@ class DCEClass { try cast (null, UsedReferenced) catch(e:Dynamic) { } new UsedAsBaseChild(); - c.length; + c.push(null); } } +@:analyzer(no_local_dce) class TestDCE extends Test { public function testFields() { @@ -117,13 +118,14 @@ class TestDCE extends Test { nhf(bc, "get_x"); } - #if (!cpp && !java && !cs) + // TODO: this should be possible in lua + #if (!cpp && !java && !cs && !lua) public function testProperty2() { - var a = new RemovePropertyKeepAccessors(); - a.test = 3; - eq(a.test, 3); - Reflect.setProperty(a, "test", 2); - eq(a.test, 2); + var a = new RemovePropertyKeepAccessors(); + a.test = 3; + eq(a.test, 3); + Reflect.setProperty(a, "test", 2); + eq(a.test, 2); var c = Type.resolveClass("unit.RemovePropertyKeepAccessors"); hf(c, "get_test"); @@ -236,11 +238,11 @@ class ThrownWithToString { class RemovePropertyKeepAccessors { - public function new() {} + public function new() {} - var _test:Float; - public var test(get, set):Float; + var _test:Float; + public var test(get, set):Float; - public function get_test():Float return _test; - public function set_test(a:Float):Float { _test = a; return _test; } -} \ No newline at end of file + public function get_test():Float return _test; + public function set_test(a:Float):Float { _test = a; return _test; } +} diff --git a/tests/unit/src/unit/TestGADT.hx b/tests/unit/src/unit/TestGADT.hx index 4a298789..fb8948cc 100644 --- a/tests/unit/src/unit/TestGADT.hx +++ b/tests/unit/src/unit/TestGADT.hx @@ -28,17 +28,17 @@ class TestGADT extends Test { var eadd = EBinop(OpAdd,e1,e2); var s = eval(eadd); - TestType.typedAs(s, ti); + HelperMacros.typedAs(s, ti); eq(s,20); var eeq = EBinop(OpEq,e1,e2); var s = eval(eeq); - TestType.typedAs(s, tb); + HelperMacros.typedAs(s, tb); eq(s,false); var eeq = EBinop(OpEq,e1,e3); var s = eval(eeq); - TestType.typedAs(s, tb); + HelperMacros.typedAs(s, tb); eq(s,true); } diff --git a/tests/unit/src/unit/TestGeneric.hx b/tests/unit/src/unit/TestGeneric.hx index ddd64b50..a00d76c5 100644 --- a/tests/unit/src/unit/TestGeneric.hx +++ b/tests/unit/src/unit/TestGeneric.hx @@ -43,22 +43,22 @@ class TestGeneric extends Test { function testBasic() { var mg = new MyGeneric(12); eq(mg.t, 12); - t(Std.is(mg.t, Int)); + t((mg.t is Int)); var mg = new MyGeneric("12"); eq(mg.t,"12"); - t(Std.is(mg.t, String)); + t((mg.t is String)); } function testExtends() { // basic class - //t(unit.TestType.typeError(new MyGeneric2())); + //t(unit.HelperMacros.typeError(new MyGeneric2())); // not a class - //t(unit.TestType.typeError(new MyGeneric2())); + //t(unit.HelperMacros.typeError(new MyGeneric2())); // no constructor - //t(unit.TestType.typeError(new MyGeneric2())); + //t(unit.HelperMacros.typeError(new MyGeneric2())); var mg = new MyGeneric2("foo"); eq("foo", mg.s); diff --git a/tests/unit/src/unit/TestHL.hx b/tests/unit/src/unit/TestHL.hx new file mode 100644 index 00000000..f51c5bf5 --- /dev/null +++ b/tests/unit/src/unit/TestHL.hx @@ -0,0 +1,25 @@ +package unit; + +class TestHL extends Test { + + //private function refTest(i:hl.types.Ref):Void + //{ + //i *= 2; + //} + + private function refTestAssign(i:hl.Ref):Void + { + i.set(2); + } + + public function testRef() + { + var i = 10; + refTestAssign(i); + eq(i, 2); + + //var i = 10; + //refTest(i); + //eq(i, 20); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/TestIO.hx b/tests/unit/src/unit/TestIO.hx index 5afa11de..14c19789 100644 --- a/tests/unit/src/unit/TestIO.hx +++ b/tests/unit/src/unit/TestIO.hx @@ -57,7 +57,6 @@ class TestIO extends Test { var str = "Héllo World !"; o.writeString(str); - eq(o.length, 86); o.writeInt16(-12345); diff --git a/tests/unit/src/unit/TestInt64.hx b/tests/unit/src/unit/TestInt64.hx index c383ee86..b4d96ee6 100644 --- a/tests/unit/src/unit/TestInt64.hx +++ b/tests/unit/src/unit/TestInt64.hx @@ -63,12 +63,34 @@ class TestInt64 extends Test { a.toInt(); } - public function testCopy() { - var a : Int64, b : Int64; - a = 1; - b = a.copy(); - ++b; - f( a == b ); + public function testIncrement() { + var a : Int64, b : Int64, c : Int64; + + // Int64 should act as a value type and be immutable. + // Increment ops should swap `this` to a new Int64 object. + a = 0; b = a; + a++; + f(a == b); + + a = 0; b = a; + ++a; + f(a == b); + + a = 0; b = a; + a--; + f(a == b); + + a = 0; b = a; + --a; + f(a == b); + + a = Int64.make(0,0xFFFFFFFF); + b = a; + c = Int64.make(1,0); + int64eq( a++, b ); + int64eq( a--, c ); + int64eq( ++a, c ); + int64eq( --a, b ); } public function testToString() { @@ -89,6 +111,16 @@ class TestInt64 extends Test { a = Int64.make(1,1); eq( a.toStr(), "4294967297" ); + + // set a to 2^63 (overflows to the smallest negative number) + a = Int64.ofInt(2); + for (i in 0...62) { + a = Int64.mul(a, 2); + } + + eq( Int64.add(a, -1).toStr(), "9223372036854775807" ); // largest positive + eq( Int64.add(a, 1).toStr(), "-9223372036854775807" ); // smallest negative - 1 + eq( a.toStr(), "-9223372036854775808" ); // smallest negative } public function testComparison() { @@ -139,16 +171,6 @@ class TestInt64 extends Test { } - public function testIncrement() { - var a = Int64.make(0,0xFFFFFFFF); - var b = a.copy(); - var c = Int64.make(1,0); - int64eq( a++, b ); - int64eq( a--, c ); - int64eq( ++a, c ); - int64eq( --a, b ); - } - public function testAddition() { var a : Int64, b : Int64; @@ -212,8 +234,8 @@ class TestInt64 extends Test { // Issue #1532 a = Int64.make(0xFFF21CDA, 0x972E8BA3); - b = Int64.make(0x0098C29B, 0x81000001); - int64eq( a*b, Int64.make(0xDDE8A2E8, 0xBA2E8BA3) ); + b = Int64.make(0x0098C29B, 0x81000001); + int64eq( a*b, Int64.make(0xDDE8A2E8, 0xBA2E8BA3) ); // Int64*Int a = Int64.make(0x01000000, 0x11131111); @@ -341,7 +363,7 @@ class TestInt64 extends Test { public function testCapture() { var a = Int64.make(0xFF00FF00,0xF0F0F0F0), - b = Int64.make(0xFF00FF00,0xF0F0F0F0); + b = Int64.make(0xFF00FF00,0xF0F0F0F0); eq(a.compare(b), 0); eq(a.high, 0xFF00FF00); function test() return Int64.compare(a,Int64.make(0xFF00FF00,0xF0F0F0F0)); @@ -378,7 +400,7 @@ class TestInt64 extends Test { public function testCompare() { var a = ofInt(2), - b = ofInt(3); + b = ofInt(3); t(a == a); t(b == b); eq(a.compare(a), 0); @@ -389,8 +411,8 @@ class TestInt64 extends Test { public function testBits() { var x = make(0xfedcba98,0x76543210); var y = x.and((ofInt(0xffff))), - z = x.or((ofInt(0xffff))), - w = x.xor((make(0xffffffff,0xffffffff))); + z = x.or((ofInt(0xffff))), + w = x.xor((make(0xffffffff,0xffffffff))); eq(y.toStr(), '12816'); eq(z.toStr(), '-81985529216434177'); eq(w.toStr(), '81985529216486895'); @@ -429,4 +451,104 @@ class TestInt64 extends Test { Test.success = false; } } + + public function testParseString() + { + for (v in ["0", "1", "-1", "9223372036854775807", "-9223372036854775807"]) { + eq(Std.string(parseString(v)), v); + } + + // trims the string: + eq("-23", Std.string(parseString(" -23 "))); + + + // overflow and underflow raise exceptions: + try + { + parseString("9223372036854775808"); + f(true); + } + catch (e:Dynamic) + { + // fine + } + + try + { + parseString("-9223372036854775809"); + f(true); + } + catch (e:Dynamic) + { + // fine + } + + try + { + parseString("--1"); + f(true); + } + catch (e:Dynamic) + { + // fine + } + + try + { + parseString("asd1"); + f(true); + } + catch (e:Dynamic) + { + // fine + } + + try + { + parseString("1asdf"); + f(true); + } + catch (e:Dynamic) + { + // fine + } + } + + public function testFromFloat() + { + for (v in [0.0, 1.0, -1.0, 9007199254740991, -9007199254740991]) { + eq(Std.parseFloat(Std.string(fromFloat(v))), v); + } + + try + { + fromFloat(9007199254740992); + f(true); + } + catch (e:Dynamic) + { + // fine + } + + try + { + fromFloat(-9007199254740992); + f(true); + } + catch (e:Dynamic) + { + // fine + } + + var nan = Math.NaN; + try + { + fromFloat(nan); + f(true); + } + catch (e:Dynamic) + { + // fine + } + } } \ No newline at end of file diff --git a/tests/unit/src/unit/TestJQuery.hx b/tests/unit/src/unit/TestJQuery.hx new file mode 100644 index 00000000..aa84d50a --- /dev/null +++ b/tests/unit/src/unit/TestJQuery.hx @@ -0,0 +1,39 @@ +package unit; + +import js.jquery.*; +import js.jquery.Helper.*; + +class TestJQuery extends Test { + + function testBasic() { + var j = new JQuery("
"); + eq(j.length, 1); + } + + function testRenamedStaticFields() { + JQuery.each([123], function(i, e) { + eq(i, 0); + eq(e, 123); + }); + } + + function testIterator() { + var div = Lambda.find(new JQuery("
"), function(ele) return ele.tagName.toLowerCase() == "div"); + eq(div.tagName.toLowerCase(), "div"); + } + + function testHelper() { + var j = J("
"); + j.each(function(i,e){ + eq(JTHIS.attr("id"), "test"); + }); + } + + function testVersion() { + var versionStr:String = JQuery.fn.jquery; + var v = versionStr.split("."); + eq(v.length, 3); + eq(haxe.macro.Compiler.getDefine("jquery_ver"), v[0] + StringTools.lpad(v[1], "0", 2) + StringTools.lpad(v[2], "0", 2)); + } + +} \ No newline at end of file diff --git a/tests/unit/src/unit/TestJava.hx b/tests/unit/src/unit/TestJava.hx index 6dde3588..9c8a3d16 100644 --- a/tests/unit/src/unit/TestJava.hx +++ b/tests/unit/src/unit/TestJava.hx @@ -17,16 +17,16 @@ class TestJava extends Test { function testException() { - var native = new NativeClass(); - var hx:NativeClass = new HxClass(); + var native = new NativeClass(); + var hx:NativeClass = new HxClass(); - exc(function() try native.excTest() catch (e:Dynamic) throw e); - var dyn:Dynamic = native; - exc(dyn.excTest); + exc(function() try native.excTest() catch (e:Dynamic) throw e); + var dyn:Dynamic = native; + exc(dyn.excTest); - try - hx.excTest() - catch(e:Dynamic) throw e; //shouldn't throw any exception + try + hx.excTest() + catch(e:Dynamic) throw e; //shouldn't throw any exception } public function testIssue2964() @@ -290,7 +290,7 @@ class TestJava extends Test function testMiscJavaLib() { //setting inline should be an error - t(TestType.typeError(Base.inlineNumber = 4)); + t(HelperMacros.typeError(Base.inlineNumber = 4)); } //TODO: @@ -354,7 +354,7 @@ private class TestMyClass extends haxe.test.MyClass @:throws("java.lang.Throwable") public function excTest():Void { - throw new java.lang.Throwable("test", null); + throw new java.lang.Throwable("test", null); } } diff --git a/tests/unit/src/unit/TestJson.hx b/tests/unit/src/unit/TestJson.hx index 83ec3e52..7c82b857 100644 --- a/tests/unit/src/unit/TestJson.hx +++ b/tests/unit/src/unit/TestJson.hx @@ -2,103 +2,103 @@ package unit; class TestJson extends Test { - function testNativeJson() { - var str = haxe.Json.stringify( { x : -4500, y : 1.456, a : ["hello", "wor'\"\n\t\rd"] } ); - str = str.substr(1, str.length - 2); // remove {} - var parts = str.split(","); - t( parts.remove('"x":-4500') ); - t( parts.remove('"y":1.456') ); - t( parts.remove('"a":["hello"') ); - t( parts.remove('"wor\'\\"\\n\\t\\rd"]') ); - eq( parts.join("#"), "" ); - - function id(v:Dynamic,?pos:haxe.PosInfos) eq(haxe.Json.parse(haxe.Json.stringify(v)),v, pos); - function deepId(v:Dynamic) { - var str = haxe.Json.stringify(v); - eq(haxe.Json.stringify(haxe.Json.parse(str)), str); - } - - id(true); - id(false); - id(null); - id(0); - id(145); - id( -145 ); - id(0.15461); - id( -485.15461); - id( 1e10 ); - id( -1e-10 ); - id( "" ); - id( "hello" ); - id( "he\n\r\t\\\\llo"); - - deepId( {field: 4} ); - deepId( { test: { nested: null }} ); - var mix : Array = [1, 2, 3, "str"]; - deepId( {array: mix} ); - - eq( haxe.Json.parse('"\\u00E9"'), "é" ); - - eq(haxe.Json.stringify(Math.POSITIVE_INFINITY), "null"); - eq(haxe.Json.stringify(Math.NEGATIVE_INFINITY), "null"); - eq(haxe.Json.stringify(Math.NaN), "null"); - - return; - } - - // TODO: test pretty-printing (also with objects with skipped function fields!) - function testHaxeJson() { - #if php - // php's haxe.Utf8 uses mbstring - if (untyped __call__("extension_loaded", "mbstring")) { - #end - - var str = haxe.format.JsonPrinter.print( { x : -4500, y : 1.456, a : ["hello", "wor'\"\n\t\rd"], b : function() {} } ); - str = str.substr(1, str.length - 2); // remove {} - var parts = str.split(","); - t( parts.remove('"x":-4500') ); - t( parts.remove('"y":1.456') ); - t( parts.remove('"a":["hello"') ); - t( parts.remove('"wor\'\\"\\n\\t\\rd"]') ); - eq( parts.join("#"), "" ); - - function id(v:Dynamic,?pos:haxe.PosInfos) eq(haxe.format.JsonParser.parse(haxe.format.JsonPrinter.print(v)),v); - function deepId(v:Dynamic) { - var str = haxe.format.JsonPrinter.print(v); - eq(haxe.format.JsonPrinter.print(haxe.format.JsonParser.parse(str)), str); - } - - id(true); - id(false); - id(null); - id(0); - id(145); - id( -145 ); - id(0.15461); - id( -485.15461); - id( 1e10 ); - id( -1e-10 ); - id( "" ); - id( "hello" ); - id( "he\n\r\t\\\\llo"); - - deepId( {field: 4} ); - deepId( { test: { nested: null }} ); - var mix : Array = [1, 2, 3, "str"]; - deepId( {array: mix} ); - - eq( haxe.format.JsonParser.parse('"\\u00E9"'), "é" ); - - eq(haxe.format.JsonPrinter.print(Math.POSITIVE_INFINITY), "null"); - eq(haxe.format.JsonPrinter.print(Math.NEGATIVE_INFINITY), "null"); - eq(haxe.format.JsonPrinter.print(Math.NaN), "null"); - eq(haxe.format.JsonPrinter.print(function() {}), "\"\""); - eq(haxe.format.JsonPrinter.print({a: function() {}, b: 1}), "{\"b\":1}"); - - #if php - } - #end - } + function testNativeJson() { + var str = haxe.Json.stringify( { x : -4500, y : 1.456, a : ["hello", "wor'\"\n\t\rd"] } ); + str = str.substr(1, str.length - 2); // remove {} + var parts = str.split(","); + t( parts.remove('"x":-4500') ); + t( parts.remove('"y":1.456') ); + t( parts.remove('"a":["hello"') ); + t( parts.remove('"wor\'\\"\\n\\t\\rd"]') ); + eq( parts.join("#"), "" ); + + function id(v:Dynamic,?pos:haxe.PosInfos) eq(haxe.Json.parse(haxe.Json.stringify(v)),v, pos); + function deepId(v:Dynamic) { + var str = haxe.Json.stringify(v); + eq(haxe.Json.stringify(haxe.Json.parse(str)), str); + } + + id(true); + id(false); + id(null); + id(0); + id(145); + id( -145 ); + id(0.15461); + id( -485.15461); + id( 1e10 ); + id( -1e-10 ); + id( "" ); + id( "hello" ); + id( "he\n\r\t\\\\llo"); + + deepId( {field: 4} ); + deepId( { test: { nested: null }} ); + var mix : Array = [1, 2, 3, "str"]; + deepId( {array: mix} ); + + eq( haxe.Json.parse('"\\u00E9"'), "é" ); + + eq(haxe.Json.stringify(Math.POSITIVE_INFINITY), "null"); + eq(haxe.Json.stringify(Math.NEGATIVE_INFINITY), "null"); + eq(haxe.Json.stringify(Math.NaN), "null"); + + return; + } + + // TODO: test pretty-printing (also with objects with skipped function fields!) + function testHaxeJson() { + #if php + // php's haxe.Utf8 uses mbstring + if (untyped __call__("extension_loaded", "mbstring")) { + #end + + var str = haxe.format.JsonPrinter.print( { x : -4500, y : 1.456, a : ["hello", "wor'\"\n\t\rd"], b : function() {} } ); + str = str.substr(1, str.length - 2); // remove {} + var parts = str.split(","); + t( parts.remove('"x":-4500') ); + t( parts.remove('"y":1.456') ); + t( parts.remove('"a":["hello"') ); + t( parts.remove('"wor\'\\"\\n\\t\\rd"]') ); + eq( parts.join("#"), "" ); + + function id(v:Dynamic,?pos:haxe.PosInfos) eq(haxe.format.JsonParser.parse(haxe.format.JsonPrinter.print(v)),v); + function deepId(v:Dynamic) { + var str = haxe.format.JsonPrinter.print(v); + eq(haxe.format.JsonPrinter.print(haxe.format.JsonParser.parse(str)), str); + } + + id(true); + id(false); + id(null); + id(0); + id(145); + id( -145 ); + id(0.15461); + id( -485.15461); + id( 1e10 ); + id( -1e-10 ); + id( "" ); + id( "hello" ); + id( "he\n\r\t\\\\llo"); + + deepId( {field: 4} ); + deepId( { test: { nested: null }} ); + var mix : Array = [1, 2, 3, "str"]; + deepId( {array: mix} ); + + eq( haxe.format.JsonParser.parse('"\\u00E9"'), "é" ); + + eq(haxe.format.JsonPrinter.print(Math.POSITIVE_INFINITY), "null"); + eq(haxe.format.JsonPrinter.print(Math.NEGATIVE_INFINITY), "null"); + eq(haxe.format.JsonPrinter.print(Math.NaN), "null"); + eq(haxe.format.JsonPrinter.print(function() {}), "\"\""); + eq(haxe.format.JsonPrinter.print({a: function() {}, b: 1}), "{\"b\":1}"); + + #if php + } + #end + } function test3690() { var strJson = haxe.Json.stringify( { x : -4500, y : 1.456, a : ["hello", "wor'\"\n\t\rd"] } ); @@ -106,4 +106,4 @@ class TestJson extends Test { eq( parsed.x, -4500 ); eq( parsed.y, 1.456 ); } -} \ No newline at end of file +} diff --git a/tests/unit/src/unit/TestLua.hx b/tests/unit/src/unit/TestLua.hx new file mode 100644 index 00000000..dc1ff712 --- /dev/null +++ b/tests/unit/src/unit/TestLua.hx @@ -0,0 +1,62 @@ +package unit; + +class TestLua extends Test { + function testMultiReturnWrap(){ + var multi : Multi = untyped MultiCall.doit(); + var l = lua.Lua.type(multi); + // test that the original multi variable was wrapped + eq(lua.Lua.type(untyped __lua__("multi")), "table"); + eq(l, "table"); + } + + function testMultiReturnPlainFunctionCall(){ + var multi : Multi = untyped MultiCall.doit(); + // this shouldn't box the result + eq(untyped __lua__("multi"), null); + } + + function testMultiReturnValue(){ + var multi : Multi = untyped MultiCall.doit(); + var l = lua.Lua.type(multi.b); + // test that the original multi wrapped variable was never created + eq(untyped __lua__("multi"), null); + eq(l, "string"); + } + + function testMultiReturnArgument(){ + // make sure multireturns passed as arguments are wrapped + eq(MultiCall.acceptMr(untyped MultiCall.doit()), true); + } + + function testMultiReturnValueHandled(){ + // make sure that multireturn is not wrapped if return values not used + var old_hx_box_mr = untyped _hx_box_mr; + var called = false; + untyped _hx_box_mr = function(){ + called = true; + } + var k = lua.NativeStringTools.find("foo bar", "foo"); + eq(called,false); + called = true; + // make sure that multireturn is wrapped if return values not used + var l = lua.NativeStringTools.find("foo bar", "foo"); + var m = l + ''; + eq(called, true); + untyped _hx_box_mr = old_hx_box_mr; + } + +} + +@:multiReturn extern class Multi { + var a : Int; + var b : String; +} + +class MultiCall { + public static function doit() : Dynamic { + return untyped __lua__("1,'hi'"); + } + public static function acceptMr(m:Multi){ + return lua.Lua.type(m) == "table"; + } +} diff --git a/tests/unit/src/unit/TestMain.hx b/tests/unit/src/unit/TestMain.hx new file mode 100644 index 00000000..70c602df --- /dev/null +++ b/tests/unit/src/unit/TestMain.hx @@ -0,0 +1,160 @@ +package unit; + +import unit.Test.*; + +@:access(unit.Test) +@:expose("unit.TestMain") +@:keep +class TestMain { + + static var asyncWaits = new Array(); + static var asyncCache = new Array Void>(); + + #if js + static function nodejsMain() { + main(); + (untyped process).exit(Test.success ? 0 : 1); + } + #end + + static function main() { + var verbose = #if ( cpp || neko || php ) Sys.args().indexOf("-v") >= 0 #else false #end; + + #if cs //"Turkey Test" - Issue #996 + cs.system.threading.Thread.CurrentThread.CurrentCulture = new cs.system.globalization.CultureInfo('tr-TR'); + cs.Lib.applyCultureChanges(); + #end + #if neko + if( neko.Web.isModNeko ) + neko.Web.setHeader("Content-Type","text/plain"); + #elseif php + if( php.Web.isModNeko ) + php.Web.setHeader("Content-Type","text/plain"); + #end + resetTimer(); + #if !macro + trace("Generated at: " + HelperMacros.getCompilationDate()); + #end + trace("START"); + #if flash + var tf : flash.text.TextField = untyped flash.Boot.getTrace(); + tf.selectable = true; + tf.mouseEnabled = true; + #end + var classes = [ + new TestOps(), + new TestBasetypes(), + new TestBytes(), + new TestIO(), + new TestLocals(), + new TestEReg(), + new TestXML(), + new TestMisc(), + new TestJson(), + new TestResource(), + new TestInt64(), + new TestReflect(), + new TestSerialize(), + new TestMeta(), + new TestType(), + new TestOrder(), + new TestGADT(), + new TestGeneric(), + #if !no_pattern_matching + new TestMatch(), + #end + new TestSpecification(), + #if cs + new TestCSharp(), + #end + #if java + new TestJava(), + #end + #if lua + new TestLua(), + #end + #if python + new TestPython(), + #end + #if hl + new TestHL(), + #end + #if php + new TestPhp(), + #end + #if (java || cs) + new TestOverloads(), + #end + // #if ((dce == "full") && !interp && !as3) + // new TestDCE(), + // #end + // #if ( (java || neko) && !macro && !interp) + // new TestThreads(), + // #end + //new TestUnspecified(), + //new TestRemoting(), + ]; + + + #if js + if (js.Browser.supported) { + classes.push(new TestJQuery()); + } + #end + + // SPOD tests + #if ( (neko || (php && (travis || appveyor || php_sqlite)) || java || cpp || (cs && (travis || appveyor))) && !macro && !interp) + #if ( (travis || appveyor) && !(cpp || cs) ) + classes.push(new TestSpod(sys.db.Mysql.connect({ + host : "127.0.0.1", + user : "travis", + pass : "", + port : 3306, + database : "haxe_test" }))); + #end + if (verbose) + logVerbose("Setup sqlite"); + classes.push(new TestSpod(sys.db.Sqlite.open("db.db3"))); + #end + TestIssues.addIssueClasses("src/unit/issues", "unit.issues"); + TestIssues.addIssueClasses("src/unit/hxcpp_issues", "unit.hxcpp_issues"); + var current = null; + #if (!fail_eager) + try + #end + { + asyncWaits.push(null); + for( inst in classes ) { + current = Type.getClass(inst); + if (verbose) + logVerbose("Class " + Std.string(current) ); + for( f in Type.getInstanceFields(current) ) + if( f.substr(0,4) == "test" ) { + if (verbose) + logVerbose(" " + f); + #if fail_eager + Reflect.callMethod(inst,Reflect.field(inst,f),[]); + #else + try { + Reflect.callMethod(inst,Reflect.field(inst,f),[]); + } + #if !as3 + catch( e : Dynamic ) { + onError(e,"EXCEPTION",Type.getClassName(current)+"."+f); + } + #end + #end + reportInfos = null; + } + } + asyncWaits.remove(null); + checkDone(); + } + #if (!as3 && !(fail_eager)) + catch( e : Dynamic ) { + asyncWaits.remove(null); + onError(e,"ABORTED",Type.getClassName(current)); + } + #end + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/TestMatch.hx b/tests/unit/src/unit/TestMatch.hx index a60fe8b2..0699f97f 100644 --- a/tests/unit/src/unit/TestMatch.hx +++ b/tests/unit/src/unit/TestMatch.hx @@ -1,6 +1,7 @@ package unit; import haxe.ds.Option; import haxe.macro.Expr; +import unit.HelperMacros.getErrorMessage; using unit.TestMatch; @@ -33,16 +34,6 @@ typedef MiniRef = { public function get():T; } -class TestMatchMacro { - static public macro function getErrorMessage(e:Expr) { - var result = try { - haxe.macro.Context.typeof(e); - "no error"; - } catch (e:Dynamic) Std.string(e.message); - return macro $v{result}; - } -} - class TestMatch extends Test { static function switchNormal(e:Expr):String { @@ -329,59 +320,60 @@ class TestMatch extends Test { } function testNonExhaustiveness() { - eq("Unmatched patterns: false", TestMatchMacro.getErrorMessage(switch(true) { + eq("Unmatched patterns: false", getErrorMessage(switch(true) { case true: })); - eq("Unmatched patterns: OpNegBits | OpNeg", TestMatchMacro.getErrorMessage(switch(OpIncrement) { + eq("Unmatched patterns: OpNeg | OpNegBits", getErrorMessage(switch(OpIncrement) { case OpIncrement: case OpDecrement: case OpNot: })); - eq("Unmatched patterns: Node(Leaf(_),_)", TestMatchMacro.getErrorMessage(switch(Leaf("foo")) { + eq("Unmatched patterns: Node(Node, _)", getErrorMessage(switch(Leaf("foo")) { case Node(Leaf("foo"), _): case Leaf(_): })); - eq("Unmatched patterns: Leaf(_)", TestMatchMacro.getErrorMessage(switch(Leaf("foo")) { + eq("Unmatched patterns: Leaf", getErrorMessage(switch(Leaf("foo")) { case Node(_, _): case Leaf(_) if (false): })); - eq("Unmatched patterns: Leaf(_)", TestMatchMacro.getErrorMessage(switch(Leaf("foo")) { + eq("Unmatched patterns: Leaf(_)", getErrorMessage(switch(Leaf("foo")) { case Node(_, _): case Leaf("foo"): })); - eq("Unmatched patterns: [_,false,_]", TestMatchMacro.getErrorMessage(switch [1, true, "foo"] { + eq("Unmatched patterns: false", getErrorMessage(switch [1, true, "foo"] { case [_, true, _]: })); //var x:Null = true; - //eq("Unmatched patterns: null", TestMatchMacro.getErrorMessage(switch x { + //eq("Unmatched patterns: null", getErrorMessage(switch x { //case true: //case false: //})); //var t:Null> = null; - //eq("Unmatched patterns: null", TestMatchMacro.getErrorMessage(switch t { + //eq("Unmatched patterns: null", getErrorMessage(switch t { //case Leaf(_): //case Node(_): //})); } function testInvalidBinding() { - eq("Variable y must appear exactly once in each sub-pattern", TestMatchMacro.getErrorMessage(switch(Leaf("foo")) { + eq("Variable y must appear exactly once in each sub-pattern", getErrorMessage(switch(Leaf("foo")) { case Leaf(x) | Leaf(y): })); - eq("Variable y must appear exactly once in each sub-pattern", TestMatchMacro.getErrorMessage(switch(Leaf("foo")) { + eq("Variable y must appear exactly once in each sub-pattern", getErrorMessage(switch(Leaf("foo")) { case Leaf(x) | Leaf(x) | Leaf(y): })); - eq("Variable x must appear exactly once in each sub-pattern", TestMatchMacro.getErrorMessage(switch(Leaf("foo")) { + eq("Variable x must appear exactly once in each sub-pattern", getErrorMessage(switch(Leaf("foo")) { case Leaf(x) | Leaf(x) | Leaf(_): })); - eq("Variable l must appear exactly once in each sub-pattern", TestMatchMacro.getErrorMessage(switch(Leaf("foo")) { + eq("Variable l must appear exactly once in each sub-pattern", getErrorMessage(switch(Leaf("foo")) { case Node(l = Leaf(x),_) | Node(Leaf(x), _): })); - eq("Variable l must appear exactly once in each sub-pattern", TestMatchMacro.getErrorMessage(switch(Leaf("foo")) { + eq("Variable l is bound multiple times", getErrorMessage(switch(Leaf("foo")) { case Node(l = Leaf(l), _): })); - eq("String should be unit.Tree", TestMatchMacro.getErrorMessage(switch(Leaf("foo")) { + eq("String should be unit.Tree", getErrorMessage(switch(Leaf("foo")) { case Node(l = Leaf(_), _) | Leaf(l): + case _: })); } @@ -452,7 +444,7 @@ class TestMatch extends Test { } eq(r, 1); - eq("Unmatched patterns: MethodNotAllowed", TestMatchMacro.getErrorMessage(switch(a) { + eq("Unmatched patterns: MethodNotAllowed", getErrorMessage(switch(a) { case NotFound: })); #end @@ -581,46 +573,4 @@ class TestMatch extends Test { } static function deref(ref:MiniRef) return ref.get(); - - #if false - //all lines marked as // unused should give an error - function testRedundance() { - switch(true) { - case false: - case true: - case false: // unused - } - - switch(true) { - case false | true: - case true: // unused - case false: // unused - } - - switch(true) { - case false - | false: // unused - case true: - } - - switch(Leaf(true)) { - case Leaf(true): - case Leaf(false): - case Leaf(x): // unused - case Node(_): - } - - switch({s:"foo"}) { - case { s : "foo" } : - case { s : a } : - } - - switch( { s:"foo", t:"bar" } ) { - case { s : "foo" }: - case { t : "bar" }: - case { s : "foo", t:"bar" }: // unused - case _: - } - } - #end } \ No newline at end of file diff --git a/tests/unit/src/unit/TestMeta.hx b/tests/unit/src/unit/TestMeta.hx index 39f84367..32d5cd87 100644 --- a/tests/unit/src/unit/TestMeta.hx +++ b/tests/unit/src/unit/TestMeta.hx @@ -1,5 +1,7 @@ package unit; +import unit.HelperMacros.getMeta; + @enumMeta private enum E { @a A; @b(0) B; @@ -67,13 +69,4 @@ package unit; eq(getMeta(@foo ("1")).args.length, 0); eq(getMeta(@foo("1") "2").args.length, 1); } - - static macro function getMeta(e) { - switch(e.expr) { - case EMeta(m, _): - return macro { name: $v{m.name}, args: $a{m.params} }; - default: - return macro report("Metadata expected"); - } - } } \ No newline at end of file diff --git a/tests/unit/src/unit/TestMisc.hx b/tests/unit/src/unit/TestMisc.hx index c5a81a73..6f81a3d8 100644 --- a/tests/unit/src/unit/TestMisc.hx +++ b/tests/unit/src/unit/TestMisc.hx @@ -380,14 +380,14 @@ class TestMisc extends Test { eq( opt3(7.4).y, 7.4 ); eq( opt4(), 11 ); - #if !(flash || cpp || cs || java) + #if !(flash || cpp || cs || java || hl) eq( opt4(null), 11 ); #end var opt4b : ?Int -> Null = opt4; eq( opt4b(), 11 ); eq( opt4b(3), 4 ); - #if !(flash || cpp || cs || java) + #if !(flash || cpp || cs || java || hl) eq( opt4b(null), 11 ); #end diff --git a/tests/unit/src/unit/TestOrder.hx b/tests/unit/src/unit/TestOrder.hx index f481f5fa..227c90a2 100644 --- a/tests/unit/src/unit/TestOrder.hx +++ b/tests/unit/src/unit/TestOrder.hx @@ -18,7 +18,7 @@ class TestOrder extends Test { // Latest enum should be used var c:E2 = E2.C1; - TestType.typedAs(C1, c); + HelperMacros.typedAs(C1, c); eq(c, C1); } } \ No newline at end of file diff --git a/tests/unit/src/unit/TestOverloads.hx b/tests/unit/src/unit/TestOverloads.hx index a29c0356..3558c8c8 100644 --- a/tests/unit/src/unit/TestOverloads.hx +++ b/tests/unit/src/unit/TestOverloads.hx @@ -1,7 +1,7 @@ package unit; import haxe.io.Bytes; -import unit.TestType.typeError; -import unit.TestType.typedAs; +import unit.HelperMacros.typeError; +import unit.HelperMacros.typedAs; using unit.TestOverloads.UsingTest2; using unit.TestOverloads.UsingTest3; diff --git a/tests/unit/src/unit/TestPhp.hx b/tests/unit/src/unit/TestPhp.hx index b77a41f2..4c4f28dd 100644 --- a/tests/unit/src/unit/TestPhp.hx +++ b/tests/unit/src/unit/TestPhp.hx @@ -1,5 +1,7 @@ package unit; +import php.*; + using StringTools; class TestPhp extends Test @@ -7,8 +9,7 @@ class TestPhp extends Test var list : Array; var list2 : Array; function empty() return true; - function testAbstractEnum() - { + function testAbstractEnum() { eq(Abstract.getName(), "Abstract"); var x = Const("foo"); var s = switch(x) { @@ -18,66 +19,139 @@ class TestPhp extends Test eq("foo", s); } - function testAbstractKeywordAsFunction() - { + function testAbstractKeywordAsFunction() { t(empty()); } - function testList2() - { + function testList2() { list2 = new Array(); for( l in list2 ) {} // fails here t(true); } - function testList() - { + function testList() { list = new Array(); for( l in list ) {} // fails here t(true); } - function testIssue1828() - { - var x = try { - throw "foo"; - } catch (e:String) { - true; - } - t(x); + function testIssue1828() { + var x = try { + throw "foo"; + } catch (e:String) { + true; + } + t(x); } - function testIssue1521() - { + function testIssue1521() { var pattern = "$a$b"; var result = pattern.replace("$a","A").replace("$b","B"); eq("AB", result); } - function testIssue2146() - { + function testIssue2146() { f(Class2146.test()); } + + function testStupidShit9000() { + var f = make(); + f.handle( function() { + eq("ok", "ok"); + }); + } + + inline static function make():FunctionCallerWrapper { + return new FunctionCaller(function(f) f()); + } + +#if php7 + /** + Check compiler will generate proper function signature with `Ref` arguments + **/ + function testRef() { + function modify(i:Ref) i = 10; //avoid inlining + + var i = 0; + modify(i); + eq(i, 10); + + var d = new DummyForRef(); + modify(d.getThis().field); + eq(d.field, 10); + } + + /** + Check compiler will not fuse `Ref` vars + **/ + // function testRefAsVar() { + // var modify = function(i:Ref) i = 10; + // var i = 0; + // modify(i); + // t(true); + // } + + function testAddOrConcat() { + var result = add(1, 'a'); + eq(result, '1a'); + + var result = add('a', 1); + eq(result, 'a1'); + + var result = add('a', 'b'); + eq(result, 'ab'); + + var result = add(1, null); + eq(result, 1); + + var result = add(null, 1); + eq(result, 1); + + var result = add('a', null); + eq(result, 'anull'); + + var result = add(null, 'b'); + eq(result, 'nullb'); + } + function add(a:Dynamic, b:Dynamic):Dynamic return a + b; +#end +} + +private class DummyForRef { + public var field:Int = 0; + public function new() {} + public function getThis() return this; } class Class2146 { - var array:Array; - function new() { - array = new Array(); - } - - public static function test() { - var a = new Class2146(); - var b = new Class2146(); - var c = new Class2146(); - a.array.push(b); - b.array.push(a); - c.array.push(a); - return Lambda.has(c.array,b); - } + var array:Array; + function new() { + array = new Array(); + } + + public static function test() { + var a = new Class2146(); + var b = new Class2146(); + var c = new Class2146(); + a.array.push(b); + b.array.push(a); + c.array.push(a); + return Lambda.has(c.array,b); + } } enum Annotation { Abstract; Const(i:String); +} + +private typedef Func = Void->Void; + +private abstract FunctionCaller(Func->Void) to Func->Void { + public function new(f:Func->Void) this = f; +} + +private abstract FunctionCallerWrapper( FunctionCaller ) from FunctionCaller to FunctionCaller { + public inline function handle(callback:Func):Void + return (this:Func->Void)(callback); } \ No newline at end of file diff --git a/tests/unit/src/unit/TestPython.hx b/tests/unit/src/unit/TestPython.hx index ce327307..1e1f2db2 100644 --- a/tests/unit/src/unit/TestPython.hx +++ b/tests/unit/src/unit/TestPython.hx @@ -81,7 +81,7 @@ private interface IA {} private class A implements IA { } private class B extends A { - public function new() {} + public function new() {} } class TestPython extends Test { @@ -144,8 +144,8 @@ class TestPython extends Test { } function testNativeClosures() { - var s = "foo"; - var f = s.toUpperCase; + var s = "foo"; + var f = s.toUpperCase; eq("FOO", f()); var a = []; @@ -332,17 +332,17 @@ class TestPython extends Test { function get_s3() return _s; function set_s3(s) return _s = s; - function testPropertyInit() { + function testPropertyInit() { s += "a"; s2 += "b"; s3 += "c"; eq("nulla", s); eq("nullb", s2); eq("nullc", s3); - } + } function testIsViaParentInterface() { - t(Std.is(new B(), IA)); + t((new B() is IA)); } @@ -423,4 +423,10 @@ class TestPython extends Test { eq(t.length, 3); } + function testVectorEquality() + { + var v = new haxe.ds.Vector(1); + var v2 = v.copy(); + eq(v == v2, false); + } } \ No newline at end of file diff --git a/tests/unit/src/unit/TestReflect.hx b/tests/unit/src/unit/TestReflect.hx index a466a39d..8c29e0ae 100644 --- a/tests/unit/src/unit/TestReflect.hx +++ b/tests/unit/src/unit/TestReflect.hx @@ -129,6 +129,10 @@ class TestReflect extends Test { is("false",String); is("",String); is([],Array); + is([1, 2], Array); + is([1.1, 2.2], Array); + is(["a", "b"], Array); + is((["a",2]:Array),Array); is(new List(),List); is(new haxe.ds.StringMap(),haxe.ds.StringMap); is(new MyClass(0),MyClass); @@ -150,7 +154,7 @@ class TestReflect extends Test { eq( Std.is(v,c), c != null && (c == t1 || c == t2) || (c == Dynamic), pos ); } infos(null); - t( Std.is(v,Dynamic), pos ); + t( (v is Dynamic), pos ); } public function testTypeEq() @@ -176,6 +180,10 @@ class TestReflect extends Test { typeof("Hello",TClass(String)); typeof("",TClass(String)); typeof([],TClass(Array)); + typeof([1, 2], TClass(Array)); + typeof([1., 2.], TClass(Array)); + typeof(["1", "2"], TClass(Array)); + typeof((["1",2]:Array),TClass(Array)); typeof(new List(),TClass(List)); typeof(new haxe.ds.StringMap(),TClass(haxe.ds.StringMap)); typeof(new MyClass(0),TClass(MyClass)); @@ -222,13 +230,13 @@ class TestReflect extends Test { function testCreate() { var i = Type.createInstance(MyClass,[33]); - t( Std.is(i,MyClass) ); + t( (i is MyClass) ); eq( i.get(), 33 ); eq( i.intValue, 55 ); var i = Type.createEmptyInstance(MyClass); - t( Std.is(i,MyClass) ); - eq( i.get(), #if (flash || cpp || java || cs) 0 #else null #end ); - eq( i.intValue, #if (flash || cpp || java || cs) 0 #else null #end ); + t( (i is MyClass) ); + eq( i.get(), #if (flash || cpp || java || cs || hl) 0 #else null #end ); + eq( i.intValue, #if (flash || cpp || java || cs || hl) 0 #else null #end ); var e : MyEnum = Type.createEnum(MyEnum,__unprotect__("A")); eq( e, MyEnum.A ); var e : MyEnum = Type.createEnum(MyEnum,__unprotect__("C"),[55,"hello"]); diff --git a/tests/unit/src/unit/TestResource.hx b/tests/unit/src/unit/TestResource.hx index 498c62c1..338745d3 100644 --- a/tests/unit/src/unit/TestResource.hx +++ b/tests/unit/src/unit/TestResource.hx @@ -31,6 +31,9 @@ class TestResource extends Test { eq( b.get(i), firsts[i]); for( i in 0...lasts.length ) eq( b.get(b.length - lasts.length + i), lasts[i] ); + + eq(haxe.Resource.getString("nope"), null); + eq(haxe.Resource.getBytes("nope"), null); } #if neko diff --git a/tests/unit/src/unit/TestSerialize.hx b/tests/unit/src/unit/TestSerialize.hx index 433fc70d..b5f7bb2c 100644 --- a/tests/unit/src/unit/TestSerialize.hx +++ b/tests/unit/src/unit/TestSerialize.hx @@ -26,7 +26,7 @@ class TestSerialize extends Test { // date var d = Date.now(); var d2 = id(d); - t( Std.is(d2,Date) ); + t( (d2 is Date) ); eq( d2.toString(), d.toString() ); // object @@ -41,7 +41,7 @@ class TestSerialize extends Test { c.intValue = 33; c.stringValue = "Hello"; var c2 = id(c); - t( Std.is(c2,MyClass) ); + t( (c2 is MyClass) ); f( c == c2 ); eq( c2.intValue, c.intValue ); eq( c2.stringValue, c.stringValue ); @@ -62,7 +62,7 @@ class TestSerialize extends Test { h.set("keya",2); h.set("kéyb",-465); var h2 = id(h); - t( Std.is(h2,haxe.ds.StringMap) ); + t( (h2 is haxe.ds.StringMap) ); eq( h2.get("keya"), 2 ); eq( h2.get("kéyb"), -465 ); eq( Lambda.count(h2), 2 ); @@ -72,7 +72,7 @@ class TestSerialize extends Test { h.set(55,2); h.set(-101,-465); var h2 = id(h); - t( Std.is(h2,haxe.ds.IntMap) ); + t( (h2 is haxe.ds.IntMap) ); eq( h2.get(55), 2 ); eq( h2.get(-101), -465 ); eq( Lambda.count(h2), 2 ); @@ -84,7 +84,7 @@ class TestSerialize extends Test { h.set(a, b); h.set(b, a); var h2 = id(h); - t(Std.is(h2, haxe.ds.ObjectMap)); + t((h2 is haxe.ds.ObjectMap)); // these are NOT the same objects f(h2.exists(a)); f(h2.exists(b)); @@ -137,7 +137,7 @@ class TestSerialize extends Test { var c = MyEnum.C(0,"hello"); t( Type.enumEq( id(c), c ) ); t( Type.enumEq( id(MyEnum.D(MyEnum.D(c))), MyEnum.D(MyEnum.D(c)) ) ); - t( Std.is(id(c),MyEnum) ); + t( (id(c) is MyEnum) ); t(switch( id(c) ) { case C(_,_): true; default: false; @@ -157,7 +157,7 @@ class TestSerialize extends Test { eq( a2[i], a[i] ); var l = Lambda.list(a); var l2 = id(l); - t( Std.is(l2,List) ); + t( (l2 is List) ); eq( l2.length, l.length ); var it = l.iterator(); for( x in l2 ) @@ -167,7 +167,7 @@ class TestSerialize extends Test { function doTestBytes( b : haxe.io.Bytes ) { var b2 = id(b); - t( Std.is(b2,haxe.io.Bytes) ); + t( (b2 is haxe.io.Bytes) ); eq( b2.length, b.length ); for( i in 0...b.length ) eq( b2.get(i), b.get(i) ); diff --git a/tests/unit/src/unit/TestSpecification.hx b/tests/unit/src/unit/TestSpecification.hx index 2d94a494..32c58471 100644 --- a/tests/unit/src/unit/TestSpecification.hx +++ b/tests/unit/src/unit/TestSpecification.hx @@ -127,10 +127,10 @@ class NonRttiClass { } @:rtti @:keepSub class RttiClass1 { - static var v:String; - public function f() { - return 33.0; - } + static var v:String; + public function f() { + return 33.0; + } } class RttiClass2 extends RttiClass1 { } diff --git a/tests/unit/src/unit/TestSpod.hx b/tests/unit/src/unit/TestSpod.hx index d507aae9..39e7cd8e 100644 --- a/tests/unit/src/unit/TestSpod.hx +++ b/tests/unit/src/unit/TestSpod.hx @@ -1,5 +1,7 @@ package unit; import sys.db.*; +import sys.db.Object; +import sys.db.Types; import haxe.io.Bytes; import haxe.EnumFlags; import sys.db.Connection; @@ -55,6 +57,7 @@ class TestSpod extends Test scls.enumFlags = EnumFlags.ofInt(0); scls.enumFlags.set(FirstValue); scls.enumFlags.set(ThirdValue); + scls.bytes = Bytes.ofString("\000a"); scls.data = [new ComplexClass( { name:"test", array:["this", "is", "a", "test"] } )]; scls.anEnum = SecondValue; @@ -62,6 +65,91 @@ class TestSpod extends Test return scls; } + function getDefaultNull() { + var scls = new NullableSpodClass(); + scls.int = 1; + scls.double = 2.0; + scls.boolean = true; + scls.string = "some string"; + scls.date = new Date(2012, 7, 30, 0, 0, 0); + scls.abstractType = "other string"; + + var bytes = Bytes.ofString("\x01\n\r'\x02"); + scls.binary = bytes; + scls.enumFlags = EnumFlags.ofInt(0); + scls.enumFlags.set(FirstValue); + scls.enumFlags.set(ThirdValue); + + scls.data = [new ComplexClass( { name:"test", array:["this", "is", "a", "test"] } )]; + scls.anEnum = SecondValue; + return scls; + } + + public function testNull() { + setManager(); + var n1 = getDefaultNull(); + n1.insert(); + var n2 = new NullableSpodClass(); + n2.insert(); + var id = n2.theId; + + n1 = null; n2 = null; + Manager.cleanup(); + + var nullVal = getNull(); + inline function checkReq(lst:List, ?nres=1, ?pos:haxe.PosInfos) { + eq(lst.length,nres, pos); + if (lst.length == 1) { + eq(lst.first().theId, id, pos); + } + } + + checkReq(NullableSpodClass.manager.search($relationNullable == null), 2); + checkReq(NullableSpodClass.manager.search($data == null)); + checkReq(NullableSpodClass.manager.search($anEnum == null)); + + checkReq(NullableSpodClass.manager.search($int == null)); + checkReq(NullableSpodClass.manager.search($double == null)); + checkReq(NullableSpodClass.manager.search($boolean == null)); + checkReq(NullableSpodClass.manager.search($string == null)); + checkReq(NullableSpodClass.manager.search($date == null)); + checkReq(NullableSpodClass.manager.search($binary == null)); + checkReq(NullableSpodClass.manager.search($abstractType == null)); + + checkReq(NullableSpodClass.manager.search($enumFlags == null)); + + + var relationNullable:Null = getNull(); + checkReq(NullableSpodClass.manager.search($relationNullable == relationNullable), 2); + var data:Null = getNull(); + checkReq(NullableSpodClass.manager.search($data == data)); + var anEnum:Null> = getNull(); + checkReq(NullableSpodClass.manager.search($anEnum == anEnum)); + + var int:Null = getNull(); + checkReq(NullableSpodClass.manager.search($int == int)); + var double:Null = getNull(); + checkReq(NullableSpodClass.manager.search($double == double)); + var boolean:Null = getNull(); + checkReq(NullableSpodClass.manager.search($boolean == boolean)); + var string:SNull> = getNull(); + checkReq(NullableSpodClass.manager.search($string == string)); + var date:SNull = getNull(); + checkReq(NullableSpodClass.manager.search($date == date)); + var binary:SNull = getNull(); + checkReq(NullableSpodClass.manager.search($binary == binary)); + var abstractType:SNull = getNull(); + checkReq(NullableSpodClass.manager.search($abstractType == abstractType)); + + for (val in NullableSpodClass.manager.all()) { + val.delete(); + } + } + + private function getNull():Null { + return null; + } + public function testIssue3828() { setManager(); @@ -290,28 +378,28 @@ class TestSpod extends Test f(cls1 == scls,pos()); scls = null; - t(Std.is(cls1.int, Int),pos()); + t((cls1.int is Int),pos()); eq(cls1.int, 1,pos()); - t(Std.is(cls1.double, Float),pos()); + t((cls1.double is Float),pos()); eq(cls1.double, 2.0,pos()); - t(Std.is(cls1.boolean, Bool),pos()); + t((cls1.boolean is Bool),pos()); eq(cls1.boolean, true,pos()); - t(Std.is(cls1.string, String),pos()); + t((cls1.string is String),pos()); eq(cls1.string, "some string",pos()); - t(Std.is(cls1.abstractType, String),pos()); + t((cls1.abstractType is String),pos()); eq(cls1.abstractType.get(), "other string",pos()); t(cls1.date != null,pos()); - t(Std.is(cls1.date, Date),pos()); + t((cls1.date is Date),pos()); eq(cls1.date.getTime(), new Date(2012, 7, 30, 0, 0, 0).getTime(),pos()); - t(Std.is(cls1.binary, Bytes),pos()); + t((cls1.binary is Bytes),pos()); eq(cls1.binary.compare(Bytes.ofString("\x01\n\r'\x02")), 0,pos()); t(cls1.enumFlags.has(FirstValue),pos()); f(cls1.enumFlags.has(SecondValue),pos()); t(cls1.enumFlags.has(ThirdValue),pos()); - t(Std.is(cls1.data, Array),pos()); - t(Std.is(cls1.data[0], ComplexClass),pos()); + t((cls1.data is Array),pos()); + t((cls1.data[0] is ComplexClass),pos()); eq(cls1.data[0].val.name, "test",pos()); eq(cls1.data[0].val.array.length, 4,pos()); @@ -321,7 +409,9 @@ class TestSpod extends Test eq(cls1.relationNullable.name, "second spod",pos()); eq(cls1.anEnum, SecondValue,pos()); - t(Std.is(cls1.anEnum, SpodEnum),pos()); + t((cls1.anEnum is SpodEnum),pos()); + + eq("\000a", cls1.bytes.toString()); eq(cls1, MySpodClass.manager.select($anEnum == SecondValue),pos()); diff --git a/tests/unit/src/unit/TestType.hx b/tests/unit/src/unit/TestType.hx index 311be36b..c5b7982b 100644 --- a/tests/unit/src/unit/TestType.hx +++ b/tests/unit/src/unit/TestType.hx @@ -1,6 +1,7 @@ package unit; import unit.MyEnum; import unit.MyClass; +import unit.HelperMacros.*; class TestType extends Test { @@ -12,43 +13,6 @@ class TestType extends Test { #end } - static public macro function getCompilationDate() { - return macro $v { Std.string(Date.now()) }; - } - - static public macro function typedAs(actual:haxe.macro.Expr, expected:haxe.macro.Expr) { - var tExpected = haxe.macro.Context.typeof(expected); - var tActual = haxe.macro.Context.typeof(actual); - return haxe.macro.Context.parse("eq('" +Std.string(tActual) + "', '" +Std.string(tExpected) + "')", haxe.macro.Context.currentPos()); - } - - static public macro function typeError(e:haxe.macro.Expr) { - var result = try { - haxe.macro.Context.typeof(e); - "false"; - } catch (e:Dynamic) "true"; - return { pos: haxe.macro.Context.currentPos(), expr: haxe.macro.Expr.ExprDef.EConst(haxe.macro.Expr.Constant.CIdent(result)) }; - } - - static public macro function typeErrorText(e:haxe.macro.Expr) { - var result = try { - haxe.macro.Context.typeof(e); - null; - } catch (e:haxe.macro.Expr.Error) e.message; - return { - pos: haxe.macro.Context.currentPos(), - expr: if (result == null) - haxe.macro.Expr.ExprDef.EConst(haxe.macro.Expr.Constant.CIdent("null")) - else - haxe.macro.Expr.ExprDef.EConst(haxe.macro.Expr.Constant.CString(result)) - }; - } - - static public macro function complete(e:String) : haxe.macro.Expr.ExprOf { - var str = new String(untyped haxe.macro.Context.load("display", 1)(e.__s)); - return { expr : EConst(CString(str)), pos : haxe.macro.Context.currentPos() }; - } - public function testType() { var name = u("unit")+"."+u("MyClass"); eq( Type.resolveClass(name), unit.MyClass ); @@ -296,7 +260,7 @@ class TestType extends Test { // TODO: this fails on flash 9 var foo = function(bar = 2) { return bar; }; - #if flash + #if (flash || hl) t(typeError(foo.bind(_))); #else var l = foo.bind(_); @@ -347,21 +311,21 @@ class TestType extends Test { // base class reference var br:Cov1 = c; typedAs(br.covariant(), b); - t(Std.is(br.covariant(), Child1)); + t((br.covariant() is Child1)); // interface reference var ir:CovI = c; typedAs(ir.covariant(), b); - t(Std.is(ir.covariant(), Child1)); + t((ir.covariant() is Child1)); // dynamic var dr:Dynamic = c; - t(Std.is(dr.covariant(), Child1)); + t((dr.covariant() is Child1)); // interface covariance var c3 = new Cov3(); typedAs(c3.covariant(), c2_1); - t(Std.is(c3.covariant(), Child2_1)); + t((c3.covariant() is Child2_1)); } function testContravariantArgs() @@ -513,16 +477,23 @@ class TestType extends Test { typedAs(inlineTest2([1]), var void:Void); } - @:analyzer(no_check_has_effect) inline function inlineTest1(map:Array) { map[0]; } - @:analyzer(no_check_has_effect) inline function inlineTest2(map:Array) { map[0]; } + public function testMacroFollowWithAbstracts() + { + #if !macro + eq(MyMacro.MyMacroHelper.followWithAbstracts(new Map()), "TInst(haxe.ds.StringMap,[TInst(String,[])])"); + eq(MyMacro.MyMacroHelper.followWithAbstractsOnce({ var x:TypedefToStringMap; x; }), "TAbstract(Map,[TInst(String,[]),TInst(String,[])])"); + eq(MyMacro.MyMacroHelper.followWithAbstracts(new TypedefToStringMap()), "TInst(haxe.ds.StringMap,[TInst(String,[])])"); + #end + } + public function testMacroRest() { #if !macro var r = MyMacro.MyRestMacro.testRest1(1, 2, 3); @@ -607,7 +578,7 @@ class TestType extends Test { return Std.string(a) + Std.string(b); } - @:generic static function gf3 < A:{function new(s:String):Void;}, B:Array
> (a:A, b:B) { + @:generic static function gf3 < A:haxe.Constraints.Constructible Void>, B:Array > (a:A, b:B) { var clone = new A("foo"); b.push(clone); return b; @@ -621,43 +592,6 @@ class TestType extends Test { return a + "foo"; } - function testCompletion() { - #if !macro - var s = { foo: 1 }; - eq(complete("s.|"), "foo:Int"); - eq(complete("var x : haxe.|"), "path(haxe)"); - eq(complete("var x : haxe.macro.Expr.|"), "path(haxe.macro:Expr)"); - - // could be improved by listing sub types - eq(complete("haxe.macro.Expr.|"), "error(haxe.macro.Expr is not a value)"); - - // know issue : the expr optimization will prevent inferring the array content - //eq(complete('{ - //var a = []; - //a.push(""); - //a[0].| - //}'),"Unknown<0>"); - - // could be improved : expr optimization assume that variable not in scope is a member - // so it will eliminate the assignement that would have forced it into the local context - // that would be useful when you want to write some code and add the member variable afterwards - eq(complete('{ - unknownVar = ""; - unknownVar.| - }'),"path(unknownVar)"); - - - for (k in [s].iterator()) { - eq(complete("k.|"), "foo:Int"); - } - - var f = function():Iterator<{foo:Int}> { - return [s].iterator(); - }; - eq(complete("for (k in f()) k.|"), "foo:Int"); - #end - } - function testSuperPropAccess() { var c = new ChildSuperProp(); eq(c.prop, 2); @@ -666,7 +600,6 @@ class TestType extends Test { eq(c.fProp(9), "test09"); } - @:analyzer(ignore) function testVoidFunc() { exc(function() { throw null; return 1; } ); exc(function() { throw null; return "foo"; } ); @@ -696,14 +629,14 @@ class TestType extends Test { var m = new Map(); var map = [1 => 2, 3 => 4]; typedAs(map, m); - t(Std.is(map, haxe.ds.IntMap)); + t((map is haxe.ds.IntMap)); eq(map.get(1), 2); eq(map.get(3), 4); var m = new Map(); var map = ["1" => 2, "3" => 4]; typedAs(map, m); - t(Std.is(map, haxe.ds.StringMap)); + t((map is haxe.ds.StringMap)); eq(map.get("1"), 2); eq(map.get("3"), 4); @@ -712,7 +645,7 @@ class TestType extends Test { var m = new Map(); var map = [a => 2, b => 4]; typedAs(map, m); - //t(Std.is(map, haxe.ds.IntMap)); + //t((map is haxe.ds.IntMap)); eq(map.get(a), 2); eq(map.get(b), 4); @@ -727,11 +660,11 @@ class TestType extends Test { function testAbstractGeneric() { var map = new Map(); map.set("foo", 1); - t(Std.is(map, haxe.ds.StringMap)); + t((map is haxe.ds.StringMap)); var map = new Map(); _mapMe(map); // infer from function call - t(Std.is(map, haxe.ds.IntMap)); + t((map is haxe.ds.IntMap)); var map = new Map(); var a = new unit.MyAbstract.ClassWithHashCode(1); @@ -740,7 +673,7 @@ class TestType extends Test { map.set(b, "bar"); eq(map.get(a), "foo"); eq(map.get(b), "bar"); - //t(Std.is(map, haxe.ds.IntMap)); + //t((map is haxe.ds.IntMap)); var map = new Map(); var a = new unit.MyAbstract.ClassWithoutHashCode(1); @@ -750,11 +683,11 @@ class TestType extends Test { eq(map.get(a), "foo"); eq(map.get(b), "bar"); // this may be specialized - //t(Std.is(map, haxe.ds.ObjectMap)); + //t((map is haxe.ds.ObjectMap)); //var map = new unit.MyAbstract.MyMap(); //map.set(new haxe.Template("foo"), 99); - //t(Std.is(map, unit.MyAbstract.PseudoObjectHash)); + //t((map is unit.MyAbstract.PseudoObjectHash)); // all these cause a compilation error, but we cannot typeError test that because it happens // during a post-process check @@ -775,12 +708,12 @@ class TestType extends Test { var msum = ms1 + ms2; eq(msum, "foobar"); typedAs(msum, ms1); - t(Std.is(msum, String)); + t((msum is String)); var msum2 = ms1 + 1; eq(msum2, "foo1"); typedAs(msum2, ms1); - t(Std.is(msum2, String)); + t((msum2 is String)); // operation is defined, but return type is not compatible t(typeError(ms1 + true)); @@ -876,3 +809,5 @@ class TestType extends Test { typedAs(unit.MyAbstract.GADTEnumAbstract.B, expectedB); } } + +typedef TypedefToStringMap = Map diff --git a/tests/unit/src/unit/TestUInt.hx b/tests/unit/src/unit/TestUInt.hx index caf7d3f6..3bc81b8e 100644 --- a/tests/unit/src/unit/TestUInt.hx +++ b/tests/unit/src/unit/TestUInt.hx @@ -6,31 +6,31 @@ class TestUInt extends TestCase function testFromFloat() { - inline function floatToInt(float:Float):Int - { - return cast float; - } - inline function intToFloat(int:Int):Float - { - return int; - } - inline function floatToUInt(float:Float):UInt - { - return cast float; - } - inline function uintToInt(uint:UInt):Int - { - return uint; - } - inline function uintToFloat(uint:UInt):Float - { - return uint; - } + inline function floatToInt(float:Float):Int + { + return cast float; + } + inline function intToFloat(int:Int):Float + { + return int; + } + inline function floatToUInt(float:Float):UInt + { + return cast float; + } + inline function uintToInt(uint:UInt):Int + { + return uint; + } + inline function uintToFloat(uint:UInt):Float + { + return uint; + } - assertEquals(-536870912, floatToInt(-536870912.0)); - assertEquals(-536870912, uintToInt(floatToUInt(-536870912.0))); - assertNotEquals(-536870912.0, uintToFloat(floatToUInt( -536870912.0))); - assertNotEquals(-536870911.0, floatToUInt(-536870912.0) + 1.0); + assertEquals(-536870912, floatToInt(-536870912.0)); + assertEquals(-536870912, uintToInt(floatToUInt(-536870912.0))); + assertNotEquals(-536870912.0, uintToFloat(floatToUInt( -536870912.0))); + assertNotEquals(-536870911.0, floatToUInt(-536870912.0) + 1.0); } function assertNotEquals( expected: T , actual: T, ?c : haxe.PosInfos ) : Void { @@ -45,53 +45,53 @@ class TestUInt extends TestCase function testMul() { - var m:UInt = 0xE0000001; - assertEquals(3221225473, m * m); - var i:Int = m; - assertEquals(-536870911, i); - assertEquals(-1073741823, i * m); - assertEquals( -1073741823, i * i); + var m:UInt = 0xE0000001; + assertEquals(3221225473, m * m); + var i:Int = m; + assertEquals(-536870911, i); + assertEquals(-1073741823, i * m); + assertEquals( -1073741823, i * i); } function testCompare() { - var u0:UInt = 0xE0000001; - var u1:UInt = 123; - assertTrue(u0 > u1); - assertTrue(u0 >= u1); - assertFalse(u0 < u1); - assertFalse(u0 <= u1); - var i0:Int = u0; - var i1:Int = u1; - assertTrue(i0 < i1); - assertTrue(i0 <= i1); - assertFalse(i0 > i1); - assertFalse(i0 >= i1); + var u0:UInt = 0xE0000001; + var u1:UInt = 123; + assertTrue(u0 > u1); + assertTrue(u0 >= u1); + assertFalse(u0 < u1); + assertFalse(u0 <= u1); + var i0:Int = u0; + var i1:Int = u1; + assertTrue(i0 < i1); + assertTrue(i0 <= i1); + assertFalse(i0 > i1); + assertFalse(i0 >= i1); } function testPostfixIncrement() { - var m:UInt = 0xE0000001; - var m0:UInt = 0xE0000001; - var m1:UInt = 0xE0000002; - assertEquals(m0, m++); - assertEquals(m1, m); + var m:UInt = 0xE0000001; + var m0:UInt = 0xE0000001; + var m1:UInt = 0xE0000002; + assertEquals(m0, m++); + assertEquals(m1, m); } function testPrefixIncrement() { - var m:UInt = 0xE0000000; - var m1:UInt = 0xE0000001; - assertEquals(m1, ++m); - assertEquals(m1, m); + var m:UInt = 0xE0000000; + var m1:UInt = 0xE0000001; + assertEquals(m1, ++m); + assertEquals(m1, m); } function testToInt() { - var m:UInt = 0xE0000001; - var i:Int = m; - var f:Float = m; - assertTrue(i != f); + var m:UInt = 0xE0000001; + var i:Int = m; + var f:Float = m; + assertTrue(i != f); } } diff --git a/tests/unit/src/unit/TestUnspecified.hx b/tests/unit/src/unit/TestUnspecified.hx index fbad39da..6a96840c 100644 --- a/tests/unit/src/unit/TestUnspecified.hx +++ b/tests/unit/src/unit/TestUnspecified.hx @@ -19,11 +19,11 @@ class TestUnspecified extends Test { var x : Array = ["4", 1]; #if (php || flash) - t(Std.is(x[0] + x[0], Int)); - t(Std.is(x[0] + x[1], Int)); + t((x[0] + x[0] is Int)); + t((x[0] + x[1] is Int)); #else - t(Std.is(x[0] + x[0], String)); - t(Std.is(x[0] + x[1], String)); + t((x[0] + x[0] is String)); + t((x[0] + x[1] is String)); #end } } \ No newline at end of file diff --git a/tests/unit/src/unit/TestXML.hx b/tests/unit/src/unit/TestXML.hx index 7a277a54..0af8b8e8 100644 --- a/tests/unit/src/unit/TestXML.hx +++ b/tests/unit/src/unit/TestXML.hx @@ -198,10 +198,10 @@ class TestXML extends Test { } function testIssue3058() { - var xml = Xml.createElement("node"); - xml.set("key", 'a"b\'&c>dd', xml.toString()); + var xml = Xml.createElement("node"); + xml.set("key", 'a"b\'&c>dd', xml.toString()); } function testIssue3630() { diff --git a/tests/unit/src/unit/UnitBuilder.hx b/tests/unit/src/unit/UnitBuilder.hx index 1f90ef48..5d1474b3 100644 --- a/tests/unit/src/unit/UnitBuilder.hx +++ b/tests/unit/src/unit/UnitBuilder.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2013 Haxe Foundation + * Copyright (C)2005-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"), diff --git a/tests/unit/src/unit/hxcpp_issues/Issue189.hx b/tests/unit/src/unit/hxcpp_issues/Issue189.hx index 0bf119b5..4c851a1f 100644 --- a/tests/unit/src/unit/hxcpp_issues/Issue189.hx +++ b/tests/unit/src/unit/hxcpp_issues/Issue189.hx @@ -3,7 +3,7 @@ package unit.hxcpp_issues; class Issue189 extends Test { dynamic function dynamicWidthDefaults(first=true, second=6, third=10.5) : Float { - return first ? second : third; + return first ? second : third; } function test() { eq(dynamicWidthDefaults(),6); diff --git a/tests/unit/src/unit/hxcpp_issues/Issue193.hx.disabled b/tests/unit/src/unit/hxcpp_issues/Issue193.hx.disabled index 1b245791..869be289 100644 --- a/tests/unit/src/unit/hxcpp_issues/Issue193.hx.disabled +++ b/tests/unit/src/unit/hxcpp_issues/Issue193.hx.disabled @@ -15,18 +15,18 @@ class Issue193 extends Test inline static function doInc(t:Issue193) t.incField(); macro public static function build ():Array { - var fields = Context.getBuildFields(); - var newField = macro { - doInc(null); - }; - fields.push ({ name: "genField", access: [ APublic ], kind: FFun({ args: [], expr: newField, params: [], ret: null }), pos: Context.currentPos() }); - return fields; + var fields = Context.getBuildFields(); + var newField = macro { + doInc(null); + }; + fields.push ({ name: "genField", access: [ APublic ], kind: FFun({ args: [], expr: newField, params: [], ret: null }), pos: Context.currentPos() }); + return fields; } function test() { - var field = Reflect.field(this,"genField"); - t(field!=null); + var field = Reflect.field(this,"genField"); + t(field!=null); } } diff --git a/tests/unit/src/unit/hxcpp_issues/Issue225.hx b/tests/unit/src/unit/hxcpp_issues/Issue225.hx index e92963ce..615ae8ac 100644 --- a/tests/unit/src/unit/hxcpp_issues/Issue225.hx +++ b/tests/unit/src/unit/hxcpp_issues/Issue225.hx @@ -9,11 +9,11 @@ interface InterfaceWithDefaultI64 { class Issue225 extends Test implements InterfaceWithDefaultI64 { function test() { - var i:InterfaceWithDefaultI64 = new Issue225(); - eq(i.optionalI64(), -1); - eq(i.optionalI64(Int64.make(0,1)), 1); + var i:InterfaceWithDefaultI64 = new Issue225(); + eq(i.optionalI64(), -1); + eq(i.optionalI64(Int64.make(0,1)), 1); } public function optionalI64(?i:Int64) - return i==null ? -1 : i.toInt(); + return i==null ? -1 : i.toInt(); } diff --git a/tests/unit/src/unit/hxcpp_issues/Issue352.hx b/tests/unit/src/unit/hxcpp_issues/Issue352.hx new file mode 100644 index 00000000..f2f00452 --- /dev/null +++ b/tests/unit/src/unit/hxcpp_issues/Issue352.hx @@ -0,0 +1,14 @@ +package unit.hxcpp_issues; + +class Issue352 extends Test { + #if (cpp && !cppia) + @:keep + static function onSample( buf : cpp.Pointer, len : Int ) { + var data : haxe.io.BytesData = []; + cpp.NativeArray.setUnmanagedData(data, buf.reinterpret(), len<<2); + foo( haxe.io.Float32Array.fromBytes(haxe.io.Bytes.ofData(data)) ); + } + + static function foo(d) { } + #end +} diff --git a/tests/unit/src/unit/hxcpp_issues/String.hx b/tests/unit/src/unit/hxcpp_issues/String.hx index 6bc6e18c..99556fad 100644 --- a/tests/unit/src/unit/hxcpp_issues/String.hx +++ b/tests/unit/src/unit/hxcpp_issues/String.hx @@ -5,7 +5,7 @@ class String extends Test { @:keep public var y:Float; @:keep public function z() return 1; function test() { - y = 1.0; + y = 1.0; t( Reflect.hasField(String, "x") ); eq( Reflect.field(this, "y"),1.0); eq( Reflect.field(this, "z")(),1); diff --git a/tests/unit/src/unit/issues/Issue1497.hx b/tests/unit/src/unit/issues/Issue1497.hx index a1aeb260..00063c16 100644 --- a/tests/unit/src/unit/issues/Issue1497.hx +++ b/tests/unit/src/unit/issues/Issue1497.hx @@ -2,7 +2,7 @@ package unit.issues; class Issue1497 extends Test { function test() { - unit.issues.misc.Issue1497Macro.run(); - eq(1, Issue1497DefinedClass.test()); + unit.issues.misc.Issue1497Macro.run(); + eq(1, Issue1497DefinedClass.test()); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue1827.hx b/tests/unit/src/unit/issues/Issue1827.hx new file mode 100644 index 00000000..c018ef3b --- /dev/null +++ b/tests/unit/src/unit/issues/Issue1827.hx @@ -0,0 +1,115 @@ +package unit.issues; + +private class C { + public var a:Int; + public var b:Int; + + public function new() { + a = 1; + b = 2; + } + + public inline function set(inA:Int, inB:Int) { + a = inA; + b = inB; + } +} + +private class D { + + public var i:Int; + + public function new() { + i = 0; + } +} + +private class E { + public var a:Int; + public var b:Int; + + public function new() { + a = 1; + b = 2; + } + + @:extern public inline function set(inA:Int, inB:Int) { + setA(inA); + setB(inB); + } + + public function setA(i:Int) a = i; + public function setB(i:Int) b = i; +} + + +class Issue1827 extends Test { + function test() { + var t = new C(); + t.set(t.b, t.a); + eq(2, t.a); + eq(1, t.b); + } + + static var i = 0; + + function test2() { + var k = callInline(i, i++); + eq(0, k); + eq(1, i); + + var i = 0; + var k = callInline(i, i++); + eq(0, k); + eq(1, i); + + var d = new D(); + var k = callInline(d.i, d.i++); + eq(0, k); + eq(1, d.i); + } + + function test3() { + var g = getInt(); + eq(1, call(g++, g)); + eq(1, g); + eq(0, call(g, g++)); + eq(2, g); + eq(1, call(g++, g++)); + eq(4, g); + eq(-1, call2(g++, g)); + eq(5, g); + eq(0, call2(g, g++)); + eq(6, g); + eq(-1, call2(g++, g++)); + eq(8, g); + } + + function test4() { + var t = new E(); + var t2 = alias(t); + t.set(t.b, t2.a); + eq(2, t.a); + eq(2, t2.a); + eq(1, t.b); + eq(1, t2.b); + } + + static function alias(t:E) return t; + + static inline function call(d1, d2) { + return d2 - d1; + } + + static inline function call2(d1, d2) { + return d1 - d2; + } + + static function getInt() { + return 0; + } + + @:extern static inline function callInline(i1, i2) { + return i1; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue1925.hx b/tests/unit/src/unit/issues/Issue1925.hx index fab54b8d..a799a36b 100644 --- a/tests/unit/src/unit/issues/Issue1925.hx +++ b/tests/unit/src/unit/issues/Issue1925.hx @@ -8,12 +8,12 @@ import cs.NativeArray; class Issue1925 extends Test { #if (java || cs) static var d2:Array>; - function test() { + function test() { var d = new NativeArray(10); d2 = [d]; d[0] = 10; eq(d2[0][0], 10); - } + } #end } diff --git a/tests/unit/src/unit/issues/Issue1997.hx b/tests/unit/src/unit/issues/Issue1997.hx index 7d7d8d10..4fca95d7 100644 --- a/tests/unit/src/unit/issues/Issue1997.hx +++ b/tests/unit/src/unit/issues/Issue1997.hx @@ -1,12 +1,12 @@ package unit.issues; class Issue1997 extends Test { - function test() { - var arr = []; - [1,2,3].map(arr.push); - eq(arr.length, 3); - eq(arr[0], 1); - eq(arr[1], 2); - eq(arr[2], 3); - } + function test() { + var arr = []; + [1,2,3].map(arr.push); + eq(arr.length, 3); + eq(arr[0], 1); + eq(arr[1], 2); + eq(arr[2], 3); + } } diff --git a/tests/unit/src/unit/issues/Issue2042.hx b/tests/unit/src/unit/issues/Issue2042.hx index d6e33c07..be87f81e 100644 --- a/tests/unit/src/unit/issues/Issue2042.hx +++ b/tests/unit/src/unit/issues/Issue2042.hx @@ -4,7 +4,6 @@ class Issue2042 extends Test { public function test() { - #if (!php && !as3) var m = haxe.rtti.Meta.getType(WithMeta); t(m.someMeta != null); eq(m.someMeta[0],1); @@ -12,7 +11,6 @@ class Issue2042 extends Test eq(m.otherMeta[0],2); t(haxe.rtti.Meta.getFields(WithMeta).testing != null); eq(haxe.rtti.Meta.getFields(WithMeta).testing.varMeta[0], 3); - #end } } diff --git a/tests/unit/src/unit/issues/Issue2044.hx b/tests/unit/src/unit/issues/Issue2044.hx index 93a71a2b..1f3779c4 100644 --- a/tests/unit/src/unit/issues/Issue2044.hx +++ b/tests/unit/src/unit/issues/Issue2044.hx @@ -2,7 +2,7 @@ package unit.issues; @:generic private class Gen { - public function new(t:T) { } + public function new(t:T) { } } class Issue2044 extends Test { diff --git a/tests/unit/src/unit/issues/Issue2061.hx.disabled b/tests/unit/src/unit/issues/Issue2061.hx similarity index 100% rename from tests/unit/src/unit/issues/Issue2061.hx.disabled rename to tests/unit/src/unit/issues/Issue2061.hx diff --git a/tests/unit/src/unit/issues/Issue2063.hx b/tests/unit/src/unit/issues/Issue2063.hx index d4010393..50959d4b 100644 --- a/tests/unit/src/unit/issues/Issue2063.hx +++ b/tests/unit/src/unit/issues/Issue2063.hx @@ -14,15 +14,15 @@ class Issue2063 extends Test { var y:{a:A} = {a:untyped 9}; var z:{a:B} = {a:untyped 9}; var w:{a:C} = {a:untyped 9}; - t(unit.TestType.typeError(x = y)); - t(unit.TestType.typeError(y = x)); - t(unit.TestType.typeError(x = z)); + t(unit.HelperMacros.typeError(x = y)); + t(unit.HelperMacros.typeError(y = x)); + t(unit.HelperMacros.typeError(x = z)); z = x; x = w; - t(unit.TestType.typeError(w = x)); + t(unit.HelperMacros.typeError(w = x)); // should fail (transitive cast) - t(unit.TestType.typeError(z = w)); + t(unit.HelperMacros.typeError(z = w)); // should succeed var p = {xs:[0,1,2]}; @@ -34,8 +34,8 @@ class Issue2063 extends Test { // should fail (transitive cast) var p = {xs:[0,1,2]}; - t(unit.TestType.typeError(var q:{xs:Arr} = p)); - t(unit.TestType.typeError(p = q)); + t(unit.HelperMacros.typeError(var q:{xs:Arr} = p)); + t(unit.HelperMacros.typeError(p = q)); // should succeed var p = {xs:[0,1,2]}; @@ -44,7 +44,7 @@ class Issue2063 extends Test { // should fail (wrong param) var p = {xs:[0.0,1.0,2.0]}; - t(unit.TestType.typeError(var q:{xs:Brr} = p)); - t(unit.TestType.typeError(p = q)); + t(unit.HelperMacros.typeError(var q:{xs:Brr} = p)); + t(unit.HelperMacros.typeError(p = q)); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2085.hx b/tests/unit/src/unit/issues/Issue2085.hx index 25e24eef..a5975b9a 100644 --- a/tests/unit/src/unit/issues/Issue2085.hx +++ b/tests/unit/src/unit/issues/Issue2085.hx @@ -4,15 +4,15 @@ private class Object extends Node> { } @:generic private class Node> { - public var ar:Array_t; + public var ar:Array_t; } @:generic private class Ar { - public var nongen:Array; - public function length():Void { - nongen.length; - } + public var nongen:Array; + public function length():Void { + nongen.length; + } } class Issue2085 extends Test { diff --git a/tests/unit/src/unit/issues/Issue2130.hx b/tests/unit/src/unit/issues/Issue2130.hx index a4fe2b0a..406865a5 100644 --- a/tests/unit/src/unit/issues/Issue2130.hx +++ b/tests/unit/src/unit/issues/Issue2130.hx @@ -1,40 +1,40 @@ package unit.issues; private abstract ZeroOneFloat(Float) to Float { - public inline function new(v:Float) { - this = v<0 ? 0. : (v>1 ? 1. : v); - } + public inline function new(v:Float) { + this = v<0 ? 0. : (v>1 ? 1. : v); + } - @:from public static inline function fromInt(v:Int) { - return new ZeroOneFloat(v); - } + @:from public static inline function fromInt(v:Int) { + return new ZeroOneFloat(v); + } - @:from public static inline function fromFloat(v:Float) { - return new ZeroOneFloat(v); - } + @:from public static inline function fromFloat(v:Float) { + return new ZeroOneFloat(v); + } - @:op(A *= B) public inline function umul_f(r:Float) : ZeroOneFloat { - return this = new ZeroOneFloat(this*r); - } + @:op(A *= B) public inline function umul_f(r:Float) : ZeroOneFloat { + return this = new ZeroOneFloat(this*r); + } - @:op(A * B) @:commutative public static inline function mul_i(l:ZeroOneFloat, r:Float) { + @:op(A * B) @:commutative public static inline function mul_i(l:ZeroOneFloat, r:Float) { return (l : Float) * r; } } class Issue2130 extends Test { function test() { - var f : ZeroOneFloat = 0.5; - feq(0.5, f); - f *= 2.; - feq(1, f); + var f : ZeroOneFloat = 0.5; + feq(0.5, f); + f *= 2.; + feq(1, f); - var f : ZeroOneFloat = 0.5; - var a : Float = 10.; + var f : ZeroOneFloat = 0.5; + var a : Float = 10.; feq(5, a * f); - a *= f; - feq(5, a); + a *= f; + feq(5, a); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2157.hx b/tests/unit/src/unit/issues/Issue2157.hx index accd2042..5df0218e 100644 --- a/tests/unit/src/unit/issues/Issue2157.hx +++ b/tests/unit/src/unit/issues/Issue2157.hx @@ -1,26 +1,26 @@ package unit.issues; private abstract Choice(Dynamic) { - private function new (x:Dynamic) this = x; + private function new (x:Dynamic) this = x; - @:from public static function fromX (x:X):Choice return new Choice(x); - @:from public static function fromY (y:Y):Choice return new Choice(y); + @:from public static function fromX (x:X):Choice return new Choice(x); + @:from public static function fromY (y:Y):Choice return new Choice(y); } private abstract False(Bool) { - inline function new (x:Bool) this = x; - @:from public static function fromBool (b:Bool) { - if (!b) { - throw "assert " + b + " should be false"; - } - return new False(b); - } + inline function new (x:Bool) this = x; + @:from public static function fromBool (b:Bool) { + if (!b) { + throw "assert " + b + " should be false"; + } + return new False(b); + } } class Issue2157 extends Test { function test() { var x : False = true; - t(unit.TestType.typeError(var z : Choice = true)); + t(unit.HelperMacros.typeError(var z : Choice = true)); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2184.hx b/tests/unit/src/unit/issues/Issue2184.hx index 9613eaa1..4ea12397 100644 --- a/tests/unit/src/unit/issues/Issue2184.hx +++ b/tests/unit/src/unit/issues/Issue2184.hx @@ -8,6 +8,6 @@ private abstract BoxedInt({ val : Int }) from { val : Int } { class Issue2184 extends Test { function test() { var test = function () return new BoxedInt({ val : 5 }); - t(unit.TestType.typeError(var z:Void->Int = test)); + t(unit.HelperMacros.typeError(var z:Void->Int = test)); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2224.hx b/tests/unit/src/unit/issues/Issue2224.hx index 25655fc9..fa4b70b1 100644 --- a/tests/unit/src/unit/issues/Issue2224.hx +++ b/tests/unit/src/unit/issues/Issue2224.hx @@ -11,20 +11,20 @@ class Issue2224 extends unit.Test { #end } - static function getEF1( ?opt : Null> ){ - return( 'opt=$opt' ); - } + static function getEF1( ?opt : Null> ){ + return( 'opt=$opt' ); + } - static function getEF2( ?opt : haxe.EnumFlags ){ - return( 'opt=$opt' ); - } + static function getEF2( ?opt : haxe.EnumFlags ){ + return( 'opt=$opt' ); + } - static function getInt( ?opt : Int ){ - return( 'opt=$opt' ); - } + static function getInt( ?opt : Int ){ + return( 'opt=$opt' ); + } - static function getClass( ?opt : MyClass ){ - return( 'opt=$opt' ); - } + static function getClass( ?opt : MyClass ){ + return( 'opt=$opt' ); + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2235.hx b/tests/unit/src/unit/issues/Issue2235.hx index cade3498..a49aeb10 100644 --- a/tests/unit/src/unit/issues/Issue2235.hx +++ b/tests/unit/src/unit/issues/Issue2235.hx @@ -2,16 +2,16 @@ package unit.issues; import unit.Test; private abstract A(Int) from Int { - function f() {} - static function fs() {} + function f() {} + static function fs() {} } class Issue2235 extends Test { function test() { - var a:A = 0; - t(unit.TestType.typeError(a.f())); - t(unit.TestType.typeError(a.f)); - t(unit.TestType.typeError(A.fs())); - t(unit.TestType.typeError(A.fs)); + var a:A = 0; + t(unit.HelperMacros.typeError(a.f())); + t(unit.HelperMacros.typeError(a.f)); + t(unit.HelperMacros.typeError(A.fs())); + t(unit.HelperMacros.typeError(A.fs)); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2236.hx b/tests/unit/src/unit/issues/Issue2236.hx index 43694943..837088ee 100644 --- a/tests/unit/src/unit/issues/Issue2236.hx +++ b/tests/unit/src/unit/issues/Issue2236.hx @@ -1,33 +1,33 @@ package unit.issues; private class ArrayIterator { - var a : Array; - var pos : Int; - public inline function new(a) { - this.a = a; - this.pos = 0; - } - public inline function hasNext() { - return pos < a.length; - } - public inline function next() { - return a[pos++]; - } + var a : Array; + var pos : Int; + public inline function new(a) { + this.a = a; + this.pos = 0; + } + public inline function hasNext() { + return pos < a.length; + } + public inline function next() { + return a[pos++]; + } } private abstract ArrayRead(Array) { - public inline function new(a) { - this = a; - } + public inline function new(a) { + this = a; + } - function toArray() : Array { - return this; - } + function toArray() : Array { + return this; + } - public inline function iterator() : ArrayIterator { - return new ArrayIterator(this); - } + public inline function iterator() : ArrayIterator { + return new ArrayIterator(this); + } } diff --git a/tests/unit/src/unit/issues/Issue2244.hx b/tests/unit/src/unit/issues/Issue2244.hx new file mode 100644 index 00000000..47c05e52 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue2244.hx @@ -0,0 +1,11 @@ +package unit.issues; + +import unit.Test; + +class Issue2244 extends Test{ + function test() { + var x = "foo"; + var y = '${ '${x}'}'; + eq("foo", y); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2281.hx b/tests/unit/src/unit/issues/Issue2281.hx index 6fc472e0..8d2ab87e 100644 --- a/tests/unit/src/unit/issues/Issue2281.hx +++ b/tests/unit/src/unit/issues/Issue2281.hx @@ -2,7 +2,7 @@ package unit.issues; class Issue2281 extends Test { - function test() { + function test() { var fint = new Foo(); fint.val = 0; eq(0, fint.val++); @@ -19,7 +19,7 @@ class Issue2281 extends Test eq(1,fint.val2); eq(2,++fint.val2); eq(12, fint.val2 += 10); - } + } } diff --git a/tests/unit/src/unit/issues/Issue2282.hx b/tests/unit/src/unit/issues/Issue2282.hx index fa17849c..35fac7b4 100644 --- a/tests/unit/src/unit/issues/Issue2282.hx +++ b/tests/unit/src/unit/issues/Issue2282.hx @@ -2,10 +2,10 @@ package unit.issues; class Issue2282 extends Test { - function test() { + function test() { var f = new Foo(); eq(null,f.val); - } + } } diff --git a/tests/unit/src/unit/issues/Issue2343.hx b/tests/unit/src/unit/issues/Issue2343.hx index b99059aa..b77cf2fb 100644 --- a/tests/unit/src/unit/issues/Issue2343.hx +++ b/tests/unit/src/unit/issues/Issue2343.hx @@ -1,14 +1,14 @@ package unit.issues; private abstract MyInt(Int) from Int { - public function work() return this; + public function work() return this; } private class Foo { public var result:Int; - public function new(val : T) { - result = val.work(); - } + public function new(val : T) { + result = val.work(); + } } class Issue2343 extends unit.Test { @@ -17,6 +17,6 @@ class Issue2343 extends unit.Test { eq(1, foo.result); // we cannot actually test this because it is delayed - //t(unit.TestType.typeError(var foo2 = new Foo("1"))); + //t(unit.HelperMacros.typeError(var foo2 = new Foo("1"))); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2380.hx b/tests/unit/src/unit/issues/Issue2380.hx index 305fd43e..d9cbc3a5 100644 --- a/tests/unit/src/unit/issues/Issue2380.hx +++ b/tests/unit/src/unit/issues/Issue2380.hx @@ -11,6 +11,6 @@ class Issue2380 extends unit.Test #if !cpp @:nativeGen #end private class SomeCls { - public function new():Void {} - @:keep public function test(v) return v == null; + public function new():Void {} + @:keep public function test(v) return v == null; } diff --git a/tests/unit/src/unit/issues/Issue2396.hx b/tests/unit/src/unit/issues/Issue2396.hx index c9fa0c92..ab301b4f 100644 --- a/tests/unit/src/unit/issues/Issue2396.hx +++ b/tests/unit/src/unit/issues/Issue2396.hx @@ -2,55 +2,55 @@ package unit.issues; private class AA { - public var x:Float; - public var y:Float; - - inline public function new(x:Float, y:Float) - { - this.x = x; - this.y = y; - } + public var x:Float; + public var y:Float; + + inline public function new(x:Float, y:Float) + { + this.x = x; + this.y = y; + } } private abstract BB(AA) { - public var x(get, set):Float; - public var y(get, set):Float; + public var x(get, set):Float; + public var y(get, set):Float; - inline public function get_x():Float return this.x; - inline public function get_y():Float return this.y; + inline public function get_x():Float return this.x; + inline public function get_y():Float return this.y; - inline public function set_x(v:Float):Float return this.x = v; - inline public function set_y(v:Float):Float return this.y = v; + inline public function set_x(v:Float):Float return this.x = v; + inline public function set_y(v:Float):Float return this.y = v; - public inline function new(x:Float = 0, y:Float = 0) - { - this = new AA(x, y); - } + public inline function new(x:Float = 0, y:Float = 0) + { + this = new AA(x, y); + } - @:commutative @:op(A*B) inline public static function opMulSF(a:BB, s:Float):BB - { - return new BB(a.x * s, a.y * s); - } + @:commutative @:op(A*B) inline public static function opMulSF(a:BB, s:Float):BB + { + return new BB(a.x * s, a.y * s); + } } class Issue2396 extends Test { function test() { - var a = new BB(10, 20); + var a = new BB(10, 20); - var t1 = 1.0; - var t2 = 2.0; + var t1 = 1.0; + var t2 = 2.0; - // !!! fails here - var fail = a * (t1 + t2); + // !!! fails here + var fail = a * (t1 + t2); feq(30, fail.x); feq(60, fail.y); - // ok here - var cacheSum = (t1 + t2); - var ok = a * cacheSum; + // ok here + var cacheSum = (t1 + t2); + var ok = a * cacheSum; feq(30, ok.x); feq(60, ok.y); } diff --git a/tests/unit/src/unit/issues/Issue2401.hx b/tests/unit/src/unit/issues/Issue2401.hx index 598335a9..bd0ce86e 100644 --- a/tests/unit/src/unit/issues/Issue2401.hx +++ b/tests/unit/src/unit/issues/Issue2401.hx @@ -2,8 +2,8 @@ package unit.issues; import unit.Test; private abstract Foo(Int) from Int { - public function toString() - return 'Foo: $this'; + public function toString() + return 'Foo: $this'; } class Issue2401 extends Test { diff --git a/tests/unit/src/unit/issues/Issue2409.hx b/tests/unit/src/unit/issues/Issue2409.hx index af20e4c5..473c3923 100644 --- a/tests/unit/src/unit/issues/Issue2409.hx +++ b/tests/unit/src/unit/issues/Issue2409.hx @@ -1,8 +1,8 @@ package unit.issues; private abstract Foo(Int) { - public function new(x:Int) this = x; - @:op(A+B) public static function add(a:Foo, b:Foo):Foo; + public function new(x:Int) this = x; + @:op(A+B) public static function add(a:Foo, b:Foo):Foo; public function get() { return this; } diff --git a/tests/unit/src/unit/issues/Issue2478.hx b/tests/unit/src/unit/issues/Issue2478.hx index cfb085c1..dc171062 100644 --- a/tests/unit/src/unit/issues/Issue2478.hx +++ b/tests/unit/src/unit/issues/Issue2478.hx @@ -1,16 +1,16 @@ package unit.issues; class Issue2478 extends Test { - function test() { + function test() { var o:Outcome = Success(5); switch (o) { case Success(v): - t(Std.is(v,Int)); + t((v is Int)); default: throw "assert"; } - } + } } private enum Outcome { diff --git a/tests/unit/src/unit/issues/Issue2508.hx.disabled b/tests/unit/src/unit/issues/Issue2508.hx.disabled index 8bd9ef45..864d9922 100644 --- a/tests/unit/src/unit/issues/Issue2508.hx.disabled +++ b/tests/unit/src/unit/issues/Issue2508.hx.disabled @@ -1,8 +1,8 @@ package unit.issues; enum Tree { - Leaf(v:T); - Node(l:Tree, r:Tree); + Leaf(v:T); + Node(l:Tree, r:Tree); } class Issue2508 extends unit.Test { diff --git a/tests/unit/src/unit/issues/Issue2521.hx b/tests/unit/src/unit/issues/Issue2521.hx index 194c94f1..93b215a4 100644 --- a/tests/unit/src/unit/issues/Issue2521.hx +++ b/tests/unit/src/unit/issues/Issue2521.hx @@ -2,11 +2,13 @@ package unit.issues; import unit.Test; class Issue2521 extends Test { + #if !macro function test() { eq("haxe.macro.Expr", getType("haxe.macro.Expr")); eq("haxe.macro.Expr", getType("haxe.macro.Expr.Expr")); eq("haxe.macro.ExprOf>", getType("haxe.macro.Expr.ExprOf")); } + #end macro static function getType(s:String) { var t = haxe.macro.Context.getType(s); diff --git a/tests/unit/src/unit/issues/Issue2540.hx b/tests/unit/src/unit/issues/Issue2540.hx index 97bce4ed..7ce683df 100644 --- a/tests/unit/src/unit/issues/Issue2540.hx +++ b/tests/unit/src/unit/issues/Issue2540.hx @@ -2,12 +2,12 @@ package unit.issues; class Issue2540 extends Test { - function test() { + function test() { var r = new T(); eq(42,r.whatever()); var r:Foo = new T(); eq(42,r.whatever()); - } + } } private interface Foo diff --git a/tests/unit/src/unit/issues/Issue2580.hx b/tests/unit/src/unit/issues/Issue2580.hx index a4911e94..35574a7c 100644 --- a/tests/unit/src/unit/issues/Issue2580.hx +++ b/tests/unit/src/unit/issues/Issue2580.hx @@ -1,8 +1,8 @@ package unit.issues; private enum T { - T1(x:Null); - T2(x:Int); + T1(x:Null); + T2(x:Int); } class Issue2580 extends Test { diff --git a/tests/unit/src/unit/issues/Issue2581.hx b/tests/unit/src/unit/issues/Issue2581.hx index d417e047..2dd27ff4 100644 --- a/tests/unit/src/unit/issues/Issue2581.hx +++ b/tests/unit/src/unit/issues/Issue2581.hx @@ -3,32 +3,32 @@ package unit.issues; @:generic private interface Arrayable { - public function toArray(?target:Array):Array; + public function toArray(?target:Array):Array; } @:generic private class KVPair { - public var key:K; - public var value:V; + public var key:K; + public var value:V; - public function new():Void - {} + public function new():Void + {} } @:generic private class MMap implements Arrayable> { - public function new():Void - {} + public function new():Void + {} - public function toArray(?target:Array>):Array> - { - if (target == null) { - target = new Array>(); - } - return target; - } + public function toArray(?target:Array>):Array> + { + if (target == null) { + target = new Array>(); + } + return target; + } } class Issue2581 extends Test { diff --git a/tests/unit/src/unit/issues/Issue2584.hx b/tests/unit/src/unit/issues/Issue2584.hx index e3f7a86a..29464a77 100644 --- a/tests/unit/src/unit/issues/Issue2584.hx +++ b/tests/unit/src/unit/issues/Issue2584.hx @@ -2,11 +2,11 @@ package unit.issues; import haxe.ds.Option; private abstract X (String) to String { - public function new (s:String) this = s; + public function new (s:String) this = s; } private abstract XX (String) { - public function new (s:String) this = s; + public function new (s:String) this = s; @:to function toString():String { return cast this; @@ -18,15 +18,15 @@ private abstract X2(X) to X {} private abstract XArr(Array) to Array {} private class A { - public var x : X; + public var x : X; } private typedef B = { - var x : String; + var x : String; } private typedef B1 = { - var x(default, null) : String; + var x(default, null) : String; } class Issue2584 extends Test { @@ -37,7 +37,7 @@ class Issue2584 extends Test { eq("foo", b.x); var a : { x: XX } = { x: new XX("foo") }; - t(unit.TestType.typeError((a : { x: String }))); + t(unit.HelperMacros.typeError((a : { x: String }))); } function test2() { @@ -63,6 +63,6 @@ class Issue2584 extends Test { var a : Array> = x; var xx : Array> = null; - t(unit.TestType.typeError((xx : Array>))); + t(unit.HelperMacros.typeError((xx : Array>))); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2587.hx b/tests/unit/src/unit/issues/Issue2587.hx new file mode 100644 index 00000000..5df9d669 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue2587.hx @@ -0,0 +1,25 @@ +package unit.issues; + +class Issue2587 extends Test { + var e:E; + function test() { + e = A; + if (e == B) return; + if (e == B) return; + var arr = [1, 2, 3, 4, 5]; + arr = arr.map(add.bind(_, "test")); + eq(5, arr.length); + eq(2, arr[0]); + eq(3, arr[1]); + eq(4, arr[2]); + eq(5, arr[3]); + eq(6, arr[4]); + } + + static function add(i:Int, s:String) return i + 1; +} + +private enum E { + A; + B; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2607.hx b/tests/unit/src/unit/issues/Issue2607.hx index 05245a90..5ac86f70 100644 --- a/tests/unit/src/unit/issues/Issue2607.hx +++ b/tests/unit/src/unit/issues/Issue2607.hx @@ -2,10 +2,10 @@ package unit.issues; class Issue2607 extends unit.Test { - inline static var CONST:Float = -1; + inline static var CONST:Float = -1; - function test(v = CONST) { - eq(v, -1); - t(Std.is(v, Float)); - } + function test(v = CONST) { + eq(v, -1); + t((v is Float)); + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2614.hx b/tests/unit/src/unit/issues/Issue2614.hx index 3f1f1cd8..6c0b5824 100644 --- a/tests/unit/src/unit/issues/Issue2614.hx +++ b/tests/unit/src/unit/issues/Issue2614.hx @@ -10,8 +10,8 @@ abstract Lazy(Void->T) { return this(); } - @:from static function ofConst(c:T):Lazy { - return new Lazy(function() return c); + @:from static function ofConst(c:T):Lazy { + return new Lazy(function() return c); } } @@ -22,11 +22,11 @@ class Issue2614 extends Test { var fFloat = lazy(2.); eq(fInt.evaluate(), 2); feq(fFloat.evaluate(), 2.); - unit.TestType.typedAs(fInt, (null : Lazy)); - unit.TestType.typedAs(fFloat, (null : Lazy)); + unit.HelperMacros.typedAs(fInt, (null : Lazy)); + unit.HelperMacros.typedAs(fFloat, (null : Lazy)); } static public function lazy(l:Lazy):Lazy { - return l; + return l; } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2619.hx b/tests/unit/src/unit/issues/Issue2619.hx index e8735ef5..d10fd8f4 100644 --- a/tests/unit/src/unit/issues/Issue2619.hx +++ b/tests/unit/src/unit/issues/Issue2619.hx @@ -25,7 +25,7 @@ class Issue2619 extends Test { } eq("foo", s); - t(unit.TestType.typeError( + t(unit.HelperMacros.typeError( try { } catch(e:A) { } catch(e:B) { } diff --git a/tests/unit/src/unit/issues/Issue2625.hx b/tests/unit/src/unit/issues/Issue2625.hx index 8709f243..ec974b3d 100644 --- a/tests/unit/src/unit/issues/Issue2625.hx +++ b/tests/unit/src/unit/issues/Issue2625.hx @@ -5,13 +5,13 @@ using unit.issues.Issue2625; class Issue2625 extends Test { function test() { - t(unit.TestType.typeError( + t(unit.HelperMacros.typeError( switch(1) { case (_.equals(2) => true) | (_.equals(3) => false): } )); - t(unit.TestType.typeError( + t(unit.HelperMacros.typeError( switch(1) { case (_.equals(2) => true), (_.equals(3) => false): } diff --git a/tests/unit/src/unit/issues/Issue2627.hx b/tests/unit/src/unit/issues/Issue2627.hx index 57a0a012..3e361609 100644 --- a/tests/unit/src/unit/issues/Issue2627.hx +++ b/tests/unit/src/unit/issues/Issue2627.hx @@ -4,12 +4,12 @@ class Issue2627 extends unit.Test { var field:Int; - function test1() { - var c = 0; - var s = staticAdd(c++, c++); + function test1() { + var c = 0; + var s = staticAdd(c++, c++); eq(s, -1); eq(c, 2); - } + } function test2() { field = 0; diff --git a/tests/unit/src/unit/issues/Issue2633.hx b/tests/unit/src/unit/issues/Issue2633.hx index 8f7cb3d6..37cf05a6 100644 --- a/tests/unit/src/unit/issues/Issue2633.hx +++ b/tests/unit/src/unit/issues/Issue2633.hx @@ -2,24 +2,24 @@ package unit.issues; import unit.Test; @:enum abstract WorldRegion(Int) { - static public var MiddleCenter = 1; + static public inline var MiddleCenter = 1; } class Issue2633 extends Test { function test() { - eq(1, match(0)); - eq(1, match(1)); - eq(2, match(2)); - eq(2, match(3)); + eq(1, match(0)); + eq(1, match(1)); + eq(2, match(2)); + eq(2, match(3)); } function match(i) { return switch [WorldRegion.MiddleCenter, i] { - case [WorldRegion.MiddleCenter, 1]|[WorldRegion.MiddleCenter, 0]: + case [WorldRegion.MiddleCenter, 1]|[WorldRegion.MiddleCenter, 0]: 1; - case _: - 2; - } + case _: + 2; + } } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2639.hx b/tests/unit/src/unit/issues/Issue2639.hx index d8c52193..820ac730 100644 --- a/tests/unit/src/unit/issues/Issue2639.hx +++ b/tests/unit/src/unit/issues/Issue2639.hx @@ -2,14 +2,14 @@ package unit.issues; import unit.Test; typedef Measurable = { - public var length(default, null):Int; + public var length(default, null):Int; } private abstract A(Int) { - public function new(i) this = i; - @:from static public inline function fromT(t:T) { - return new A(t.length); - } + public function new(i) this = i; + @:from static public inline function fromT(t:T) { + return new A(t.length); + } public function get() { return this; @@ -19,7 +19,7 @@ private abstract A(Int) { class Issue2639 extends Test { public function test() { var a:A; - t(unit.TestType.typeError(a = 0)); + t(unit.HelperMacros.typeError(a = 0)); var b:A = "foo"; eq(3, b.get()); } diff --git a/tests/unit/src/unit/issues/Issue2653.hx b/tests/unit/src/unit/issues/Issue2653.hx index d0c936a1..26521529 100644 --- a/tests/unit/src/unit/issues/Issue2653.hx +++ b/tests/unit/src/unit/issues/Issue2653.hx @@ -14,13 +14,13 @@ private class BasicTexture extends BasicAsset { public function new(i:Int, s:String) { super(s); this.i = i; - } + } } private class CanvasTexture extends BasicTexture { - public function new(i:Int, s:String) { + public function new(i:Int, s:String) { super(i, s); - } + } } class Issue2653 extends Test { diff --git a/tests/unit/src/unit/issues/Issue2661.hx b/tests/unit/src/unit/issues/Issue2661.hx index 37a5363d..4dbf3a8e 100644 --- a/tests/unit/src/unit/issues/Issue2661.hx +++ b/tests/unit/src/unit/issues/Issue2661.hx @@ -66,7 +66,7 @@ class Issue2661 extends Test { eq(10, new A1(i++) % new AChild(i++)); eq(12, i); - t(unit.TestType.typeError(new AChild(1) - new A1(0))); - t(unit.TestType.typeError(new AChild(1) % new A1(1))); + t(unit.HelperMacros.typeError(new AChild(1) - new A1(0))); + t(unit.HelperMacros.typeError(new AChild(1) % new A1(1))); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2664.hx b/tests/unit/src/unit/issues/Issue2664.hx index acf18ed4..43726076 100644 --- a/tests/unit/src/unit/issues/Issue2664.hx +++ b/tests/unit/src/unit/issues/Issue2664.hx @@ -3,19 +3,19 @@ import unit.Test; class Issue2664 extends Test { - function test() { - var i = 0; + function test() { + var i = 0; var buf = ""; - eq(-2,sub({buf += "a" + i; i++; },toABase({ buf += "b" + i; i++;}))); + eq(-2,sub({buf += "a" + i; i++; },toABase({ buf += "b" + i; i++;}))); eq("a0b1", buf.toString()); eq(2, i); - } + } - static function sub(a, b) { - return a - b; - } + static function sub(a, b) { + return a - b; + } - static function toABase(i) { - return i * 2; - } + static function toABase(i) { + return i * 2; + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2668.hx.disabled b/tests/unit/src/unit/issues/Issue2668.hx.disabled index 6a1775a7..f1a4bf27 100644 --- a/tests/unit/src/unit/issues/Issue2668.hx.disabled +++ b/tests/unit/src/unit/issues/Issue2668.hx.disabled @@ -1,7 +1,7 @@ package unit.issues; class Issue2688 extends Test { - function test() { + function test() { var called = false; function isCalled() { called = true; @@ -9,7 +9,7 @@ class Issue2688 extends Test { var child = new Child(test); child.task([1,2,3,4]); t(called); - } + } } @:nativeGen private class NativeGen diff --git a/tests/unit/src/unit/issues/Issue2675.hx b/tests/unit/src/unit/issues/Issue2675.hx index c4ac2703..6722a30e 100644 --- a/tests/unit/src/unit/issues/Issue2675.hx +++ b/tests/unit/src/unit/issues/Issue2675.hx @@ -5,22 +5,21 @@ private class Base { } private class Child extends Base {} -@:analyzer(no_check_has_effect) class Issue2675 extends Test { function test() { - t(unit.TestType.typeError( + t(unit.HelperMacros.typeError( try { } catch(e:Base) { } catch(e:Child) { } )); - t(unit.TestType.typeError( + t(unit.HelperMacros.typeError( try { } catch(e:Dynamic) { } catch(e:Child) { } )); - t(unit.TestType.typeError( + t(unit.HelperMacros.typeError( try { } catch(e:Dynamic) { } catch(e:Dynamic) { } diff --git a/tests/unit/src/unit/issues/Issue2685.hx b/tests/unit/src/unit/issues/Issue2685.hx index 93e35d4d..51541a8b 100644 --- a/tests/unit/src/unit/issues/Issue2685.hx +++ b/tests/unit/src/unit/issues/Issue2685.hx @@ -2,8 +2,8 @@ package unit.issues; import unit.Test; private abstract A({a:Int}) from {a:Int} { - @:to function toInt():Int return this.a * 4; - @:to function toDynamic():Dynamic return this.a * 2; + @:to function toInt():Int return this.a * 4; + @:to function toDynamic():Dynamic return this.a * 2; } class Issue2685 extends Test { diff --git a/tests/unit/src/unit/issues/Issue2696.hx b/tests/unit/src/unit/issues/Issue2696.hx index ea4421ee..9dd3049c 100644 --- a/tests/unit/src/unit/issues/Issue2696.hx +++ b/tests/unit/src/unit/issues/Issue2696.hx @@ -3,11 +3,11 @@ import unit.Test; class Issue2696 extends Test { - private static var value = 2; + private static var value = 2; - inline private static function func() :Int { - return -value; - } + inline private static function func() :Int { + return -value; + } function test() { eq(2, -func()); diff --git a/tests/unit/src/unit/issues/Issue2698.hx b/tests/unit/src/unit/issues/Issue2698.hx index f1dc7d43..31555474 100644 --- a/tests/unit/src/unit/issues/Issue2698.hx +++ b/tests/unit/src/unit/issues/Issue2698.hx @@ -2,8 +2,8 @@ package unit.issues; import unit.Test; private abstract IntString(String) { - @:from static function fromInt(i:Int):IntString return cast Std.string(i); - @:to function toInt():Int return Std.parseInt(this); + @:from static function fromInt(i:Int):IntString return cast Std.string(i); + @:to function toInt():Int return Std.parseInt(this); } class Issue2698 extends Test { @@ -12,22 +12,22 @@ class Issue2698 extends Test { var b:Int = 1; var c:IntString = 2; var d:Int = 2; - + t(a == a); t(a == b); f(a == c); f(a == d); - + t(b == a); t(b == b); f(b == c); f(b == d); - + f(c == a); f(c == b); t(c == c); t(c == d); - + f(d == a); f(d == b); t(d == c); diff --git a/tests/unit/src/unit/issues/Issue2712.hx b/tests/unit/src/unit/issues/Issue2712.hx index 1a6e8ac1..b758c9b9 100644 --- a/tests/unit/src/unit/issues/Issue2712.hx +++ b/tests/unit/src/unit/issues/Issue2712.hx @@ -4,17 +4,17 @@ import unit.Test; class Item implements Heapable {} interface Collection { - function contains(x:T):Bool; + function contains(x:T):Bool; } interface Heapable {} class Heap implements Collection { - public function new() {} + public function new() {} - public function contains(x:T):Bool { - return true; - } + public function contains(x:T):Bool { + return true; + } } class Issue2712 extends Test { diff --git a/tests/unit/src/unit/issues/Issue2735.hx b/tests/unit/src/unit/issues/Issue2735.hx index 57cea3bd..ba004dd1 100644 --- a/tests/unit/src/unit/issues/Issue2735.hx +++ b/tests/unit/src/unit/issues/Issue2735.hx @@ -3,8 +3,8 @@ import unit.Test; class Issue2735 extends Test { function test() { - var uint:UInt = 0xFFFFFFFF; - var f:Float = uint; - feq(4294967295., f); + var uint:UInt = 0xFFFFFFFF; + var f:Float = uint; + feq(4294967295., f); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2736.hx b/tests/unit/src/unit/issues/Issue2736.hx index 2abd5705..a28df703 100644 --- a/tests/unit/src/unit/issues/Issue2736.hx +++ b/tests/unit/src/unit/issues/Issue2736.hx @@ -4,33 +4,28 @@ import unit.Test; /** UInt not showing proper unsigned behavior */ class Issue2736 extends Test { function test() { - var a:UInt, b:UInt; + var a:UInt, b:UInt; - b = 50000; - a = b * b; + b = 50000; + a = b * b; - eq( a, b*b ); - eq( a/b, 50000 ); - eq(a % b, 0); + eq( a, b*b ); + eq( a/b, 50000 ); + eq(a % b, 0); - f(a == b); t(a != b); - t(a > b); t(a >= b); - f(a < b); f(a <= b); + f(a == b); t(a != b); + t(a > b); t(a >= b); + f(a < b); f(a <= b); - // UInt vs Float comparisons - f( a == 1.0 ); t( b == 50000.0 ); - t( a > 1.0 ); t( a >= 1.0 ); - f( a < -1.0 ); f( a <= 1.0 ); + // UInt vs Float comparisons + f( a == 1.0 ); t( b == 50000.0 ); + t( a > 1.0 ); t( a >= 1.0 ); + f( a < -1.0 ); f( a <= 1.0 ); - // Shift behavior - //eq( '${a >> 1}', "3397483648" ); // broken - - /* These are currently broken but should be fixed in the future: - * Currently we don't allow UInt vs Int comparisons. - * trace(a == -1794967296); - - * Shift on swf9 return as Int and not UInt - * trace(a >> 1); //-897483648 in flash, but 3397483648 in neko and js - */ + #if false // ? + var u:UInt = 2147483648; + eq(1073741824, u >> 1); + eq(1073741824, u >>> 1); + #end } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2750.hx b/tests/unit/src/unit/issues/Issue2750.hx index 93bddc37..c675271d 100644 --- a/tests/unit/src/unit/issues/Issue2750.hx +++ b/tests/unit/src/unit/issues/Issue2750.hx @@ -2,10 +2,10 @@ package unit.issues; import unit.Test; private class Parent extends Test { - function new() { + function new() { super(); } - + function foo() { return 1; } @@ -21,19 +21,19 @@ class Issue2750 extends Parent { function test() { new Issue2750(); } - - public function new() { - super(); + + public function new() { + super(); eq(3, foo()); eq(3, bind()); eq(3, match()); call(this); - t(unit.TestType.typeError(var x = super)); - t(unit.TestType.typeError(call(super))); - t(unit.TestType.typeError({ field: super })); - t(unit.TestType.typeError([super])); - } - + t(unit.HelperMacros.typeError(var x = super)); + t(unit.HelperMacros.typeError(call(super))); + t(unit.HelperMacros.typeError({ field: super })); + t(unit.HelperMacros.typeError([super])); + } + override function foo() { return 2 + super.foo(); } @@ -45,6 +45,6 @@ class Issue2750 extends Parent { override function match() { return 2 + super.match(); } - + function call(c:Parent) { } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2763.hx b/tests/unit/src/unit/issues/Issue2763.hx index 0bed7477..578faa49 100644 --- a/tests/unit/src/unit/issues/Issue2763.hx +++ b/tests/unit/src/unit/issues/Issue2763.hx @@ -16,7 +16,7 @@ class Issue2763 extends Test { acc += ";" + i; } while (call(i++) < call2(i++)); eq(";0;2;4", acc); - } + } static function call(i:Int) { return i; diff --git a/tests/unit/src/unit/issues/Issue2766.hx b/tests/unit/src/unit/issues/Issue2766.hx index a9f694b4..7e8c38d2 100644 --- a/tests/unit/src/unit/issues/Issue2766.hx +++ b/tests/unit/src/unit/issues/Issue2766.hx @@ -2,8 +2,8 @@ package unit.issues; import unit.Test; private class Foo { - public var foo = "foo"; - public function new () {} + public var foo = "foo"; + public function new () {} } class Issue2766 extends Test { @@ -11,8 +11,8 @@ class Issue2766 extends Test { function test() { eq("foo", getValue()); } - - macro static function getValue() { - return macro $v{new Foo().foo}; - } + + macro static function getValue() { + return macro $v{new Foo().foo}; + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2767.hx b/tests/unit/src/unit/issues/Issue2767.hx new file mode 100644 index 00000000..0b6e9592 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue2767.hx @@ -0,0 +1,24 @@ +package unit.issues; + +private abstract A(Array) { + public function new() { + this = []; + } + + public inline function add(i : Int) : Void { + this.push(i); + } + + public function get() { + return this.pop(); + } +} + +class Issue2767 extends Test { + function test() { + var a = new A(); + var f = a.add; + f(12); + eq(12, a.get()); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2776.hx b/tests/unit/src/unit/issues/Issue2776.hx index 7fd9e28a..93057399 100644 --- a/tests/unit/src/unit/issues/Issue2776.hx +++ b/tests/unit/src/unit/issues/Issue2776.hx @@ -1,7 +1,6 @@ package unit.issues; import unit.Test; -@:analyzer(no_check_has_effect) class Issue2776 extends Test { function test() { var type = null; @@ -9,17 +8,17 @@ class Issue2776 extends Test { case String: case Int: } - unit.TestType.typedAs(type, getClassT()); + unit.HelperMacros.typedAs(type, getClassT()); var type = null; switch(type) { case haxe.macro.Expr.ExprDef: case haxe.macro.Expr.Constant: } - unit.TestType.typedAs(type, getEnumT()); + unit.HelperMacros.typedAs(type, getEnumT()); var type = null; - t(unit.TestType.typeError(switch(type) { + t(unit.HelperMacros.typeError(switch(type) { case String: case haxe.macro.Expr.ExprDef: })); diff --git a/tests/unit/src/unit/issues/Issue2778.hx b/tests/unit/src/unit/issues/Issue2778.hx index 3f603a96..cd03d23c 100644 --- a/tests/unit/src/unit/issues/Issue2778.hx +++ b/tests/unit/src/unit/issues/Issue2778.hx @@ -1,8 +1,8 @@ package unit.issues; enum E { - BoolLit(b:Bool):E; - IntLit(i:Int):E; + BoolLit(b:Bool):E; + IntLit(i:Int):E; } class Issue2778 extends Test { @@ -13,14 +13,14 @@ class Issue2778 extends Test { eq(false, sameType(BoolLit(true), BoolLit(false))); eq(false, sameType(BoolLit(false), BoolLit(false))); eq(12, sameType(IntLit(1), IntLit(11))); - t(unit.TestType.typeError(sameType(IntLit(1), BoolLit(true)))); - t(unit.TestType.typeError(sameType(BoolLit(true), IntLit(1)))); + t(unit.HelperMacros.typeError(sameType(IntLit(1), BoolLit(true)))); + t(unit.HelperMacros.typeError(sameType(BoolLit(true), IntLit(1)))); } - static function sameType(o1:E, o2:E):S { - return switch [o1, o2] { - case [BoolLit(b1), BoolLit(b2)]: b1 && b2; - case [IntLit(i1), IntLit(i2)]: i1 + i2; - } - } + static function sameType(o1:E, o2:E):S { + return switch [o1, o2] { + case [BoolLit(b1), BoolLit(b2)]: b1 && b2; + case [IntLit(i1), IntLit(i2)]: i1 + i2; + } + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2786.hx b/tests/unit/src/unit/issues/Issue2786.hx index f31f2ef6..4c520594 100644 --- a/tests/unit/src/unit/issues/Issue2786.hx +++ b/tests/unit/src/unit/issues/Issue2786.hx @@ -2,31 +2,31 @@ package unit.issues; @:enum private abstract E(Int) to Int { - var A = 1; - var B = 2; - @:op(a | b) static function or(a:E, b:E):E; + var A = 1; + var B = 2; + @:op(a | b) static function or(a:E, b:E):E; } @:enum private abstract E2(Int) to Int { - var A = 1; - var B = 2; - @:op(a | b) static function or(a:E2, b:E2):E2; - @:op(a | b) static function or2(a:E2, b:E2):E2; + var A = 1; + var B = 2; + @:op(a | b) static function or(a:E2, b:E2):E2; + @:op(a | b) static function or2(a:E2, b:E2):E2; } @:enum private abstract E3(Int) to Int { - var A = 1; - var B = 2; - @:op(a | b) static function or(a:E3, b:E3):E3; - @:op(a | b) static function or2(a:E3, b:E3):E3; + var A = 1; + var B = 2; + @:op(a | b) static function or(a:E3, b:E3):E3; + @:op(a | b) static function or2(a:E3, b:E3):E3; } class Issue2786 extends Test { function test() { var a:E = A | B; eq(3, a); - t(unit.TestType.typeError((A | B : E2))); + t(unit.HelperMacros.typeError((A | B : E2))); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2792.hx b/tests/unit/src/unit/issues/Issue2792.hx index f28ff005..d9aae20c 100644 --- a/tests/unit/src/unit/issues/Issue2792.hx +++ b/tests/unit/src/unit/issues/Issue2792.hx @@ -2,44 +2,44 @@ package unit.issues; import unit.Test; private class Obj { - public var w:Float; - public var h:Float; - public function new(w:Float = 0, h:Float = 0) { - this.w = w; - this.h = h; - } + public var w:Float; + public var h:Float; + public function new(w:Float = 0, h:Float = 0) { + this.w = w; + this.h = h; + } } private class Node { - public var obj:Obj; + public var obj:Obj; - public function new() { } + public function new() { } - public inline function canPlace(w:Float, h:Float):Bool { - return (obj.w == w && obj.h == h); - } + public inline function canPlace(w:Float, h:Float):Bool { + return (obj.w == w && obj.h == h); + } } private class Root { - public var left:Node; - public var right:Node; + public var left:Node; + public var right:Node; - public function new() {} + public function new() {} } class Issue2792 extends Test { function test() { - var root:Root = new Root(); - root.left = new Node(); - root.left.obj = new Obj(); - var check1:Bool = (root.right != null && root.right.canPlace(0, 0)) && (root.left != null && root.left.canPlace(0, 0)); - eq(false, check1); - var check2:Bool = (root.left != null && root.left.canPlace(0, 0)) && (root.right != null && root.right.canPlace(0, 0)); - eq(false, check2); - var right:Bool = (root.right != null && root.right.canPlace(0, 0)); - var left:Bool = (root.left != null && root.left.canPlace(0, 0)); - var both:Bool = right && left; - eq(false, both); + var root:Root = new Root(); + root.left = new Node(); + root.left.obj = new Obj(); + var check1:Bool = (root.right != null && root.right.canPlace(0, 0)) && (root.left != null && root.left.canPlace(0, 0)); + eq(false, check1); + var check2:Bool = (root.left != null && root.left.canPlace(0, 0)) && (root.right != null && root.right.canPlace(0, 0)); + eq(false, check2); + var right:Bool = (root.right != null && root.right.canPlace(0, 0)); + var left:Bool = (root.left != null && root.left.canPlace(0, 0)); + var both:Bool = right && left; + eq(false, both); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2809.hx b/tests/unit/src/unit/issues/Issue2809.hx index 0590553c..4b28e887 100644 --- a/tests/unit/src/unit/issues/Issue2809.hx +++ b/tests/unit/src/unit/issues/Issue2809.hx @@ -13,6 +13,7 @@ class Issue2809 extends Test { switch(val) { case MyEnum.SomeValue: x = "bar"; + case _: } eq("foo", x); } diff --git a/tests/unit/src/unit/issues/Issue2810.hx b/tests/unit/src/unit/issues/Issue2810.hx index dfb2680f..b49918d4 100644 --- a/tests/unit/src/unit/issues/Issue2810.hx +++ b/tests/unit/src/unit/issues/Issue2810.hx @@ -2,23 +2,23 @@ package unit.issues; import unit.Test; private abstract A(Array) { - public inline function new(a) { - this = a; - } - @:arrayAccess inline function read(i) { - return this[i]; - } - @:arrayAccess inline function write(i,v) { - return this[i] = v; - } + public inline function new(a) { + this = a; + } + @:arrayAccess inline function read(i) { + return this[i]; + } + @:arrayAccess inline function write(i,v) { + return this[i] = v; + } } class Issue2810 extends Test { function test() { - var a = new A([5]); - var x = a[0]; - a[0] = 6; - a[0] += 3; + var a = new A([5]); + var x = a[0]; + a[0] = 6; + a[0] += 3; eq(9, a[0]); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2813.hx b/tests/unit/src/unit/issues/Issue2813.hx index 7fcfb8e9..36d42d49 100644 --- a/tests/unit/src/unit/issues/Issue2813.hx +++ b/tests/unit/src/unit/issues/Issue2813.hx @@ -18,7 +18,7 @@ class Issue2813 extends Test { var f = Ext.test2; eq("foo", f()); - t(unit.TestType.typeError({ + t(unit.HelperMacros.typeError({ var e = new Ext(); var f = e.test; })); diff --git a/tests/unit/src/unit/issues/Issue2844.hx b/tests/unit/src/unit/issues/Issue2844.hx index 316a19f3..aacece74 100644 --- a/tests/unit/src/unit/issues/Issue2844.hx +++ b/tests/unit/src/unit/issues/Issue2844.hx @@ -3,7 +3,7 @@ import unit.Test; class Issue2844 extends Test { function test() { - t(unit.TestType.typeError({ + t(unit.HelperMacros.typeError({ var a:Array = []; var b:Array = a; })); diff --git a/tests/unit/src/unit/issues/Issue2859.hx b/tests/unit/src/unit/issues/Issue2859.hx index fe83c70c..64e5402f 100644 --- a/tests/unit/src/unit/issues/Issue2859.hx +++ b/tests/unit/src/unit/issues/Issue2859.hx @@ -1,20 +1,20 @@ package unit.issues; private abstract Error(String) { - public function new(message:String) { - this = message; - } + public function new(message:String) { + this = message; + } } class Issue2859 extends Test { function test() { - try { - throw new Error("hello"); - } catch (e:Error) { - unit.TestType.typedAs(e, (null:Error)); - func(e); - } - } + try { + throw new Error("hello"); + } catch (e:Error) { + unit.HelperMacros.typedAs(e, (null:Error)); + func(e); + } + } - static function func(e:Error) { } + static function func(e:Error) { } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2861.hx b/tests/unit/src/unit/issues/Issue2861.hx index d558adff..024ad845 100644 --- a/tests/unit/src/unit/issues/Issue2861.hx +++ b/tests/unit/src/unit/issues/Issue2861.hx @@ -2,7 +2,7 @@ package unit.issues; class Issue2861 extends Test { -#if (flash || neko || cpp || java) +#if (flash || neko || cpp || java || php) public function test() { var b = haxe.io.Bytes.alloc(2048); diff --git a/tests/unit/src/unit/issues/Issue2871.hx b/tests/unit/src/unit/issues/Issue2871.hx index 9a5dce71..7dee0dc8 100644 --- a/tests/unit/src/unit/issues/Issue2871.hx +++ b/tests/unit/src/unit/issues/Issue2871.hx @@ -1,9 +1,9 @@ package unit.issues; class Issue2871 extends Test { - function call(myUInt:Null = null):Int { - return myUInt == null ? 0 : myUInt; - } + function call(myUInt:Null = null):Int { + return myUInt == null ? 0 : myUInt; + } function test() { eq(0, call(null)); diff --git a/tests/unit/src/unit/issues/Issue2902.hx b/tests/unit/src/unit/issues/Issue2902.hx index 833f3d02..f9b56fd9 100644 --- a/tests/unit/src/unit/issues/Issue2902.hx +++ b/tests/unit/src/unit/issues/Issue2902.hx @@ -6,10 +6,10 @@ private class G { public function new(t:T) { this.t = t; } - public function f(){ - haxe.Log; + public function f(){ + haxe.Log; return t; - } + } } private class G2 extends G { } diff --git a/tests/unit/src/unit/issues/Issue2907.hx b/tests/unit/src/unit/issues/Issue2907.hx index 4e044e84..ebfbc6ef 100644 --- a/tests/unit/src/unit/issues/Issue2907.hx +++ b/tests/unit/src/unit/issues/Issue2907.hx @@ -17,7 +17,7 @@ class Issue2907 extends Test { } function test() { - t(unit.TestType.typeError( + t(unit.HelperMacros.typeError( try { } catch(e:T) { } )); diff --git a/tests/unit/src/unit/issues/Issue2914.hx b/tests/unit/src/unit/issues/Issue2914.hx index b64be6cd..33cdf92f 100644 --- a/tests/unit/src/unit/issues/Issue2914.hx +++ b/tests/unit/src/unit/issues/Issue2914.hx @@ -4,7 +4,7 @@ class Issue2914 extends Test { function test() { var o:Null = 0; - t(unit.TestType.typeError({ + t(unit.HelperMacros.typeError({ var x = switch o { case x if (x > 1): x; } diff --git a/tests/unit/src/unit/issues/Issue2937.hx b/tests/unit/src/unit/issues/Issue2937.hx index 6120bbef..8de2c023 100644 --- a/tests/unit/src/unit/issues/Issue2937.hx +++ b/tests/unit/src/unit/issues/Issue2937.hx @@ -4,7 +4,7 @@ package unit.issues; class Issue2937 extends Test { function test() { var f = Reflect.makeVarArgs(function(args:Array) { - t(Std.is(args, Array)); // false, but should be true + t((args is Array)); // false, but should be true }); f(1,2,3); } diff --git a/tests/unit/src/unit/issues/Issue2939.hx b/tests/unit/src/unit/issues/Issue2939.hx index 4734faf7..87ed64a8 100644 --- a/tests/unit/src/unit/issues/Issue2939.hx +++ b/tests/unit/src/unit/issues/Issue2939.hx @@ -12,6 +12,6 @@ class Issue2939 extends Test { function test() { eq(1, a); eq(2, b); - t(unit.TestType.typeError(c)); + t(unit.HelperMacros.typeError(c)); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2951.hx b/tests/unit/src/unit/issues/Issue2951.hx index 03862449..74fc807c 100644 --- a/tests/unit/src/unit/issues/Issue2951.hx +++ b/tests/unit/src/unit/issues/Issue2951.hx @@ -14,32 +14,32 @@ class Issue2951 extends Test{ } public static function getLast(x:Dynamic) { - return true; + return true; } public static function exists(x:Dynamic) { - return true; + return true; } public function test () { - var last = null; - var args = []; - var HxString = { - charCodeAt : function (a:Array, i:Int) { - return 1; - } - }; - if ((if ((if ((exists(last)))getLast(last) else false)){ - if ((! (args.length < 2))){ - var _g = HxString.charCodeAt(args[args.length - 2],0); - var _g1 = 45; - _g != _g1; - } else true; - } else false)){ - if ((args.length == 0)) true else false; - setCwd(last); - }; + var last = null; + var args = []; + var HxString = { + charCodeAt : function (a:Array, i:Int) { + return 1; + } + }; + if ((if ((if ((exists(last)))getLast(last) else false)){ + if ((! (args.length < 2))){ + var _g = HxString.charCodeAt(args[args.length - 2],0); + var _g1 = 45; + _g != _g1; + } else true; + } else false)){ + if ((args.length == 0)) true else false; + setCwd(last); + }; } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2958.hx b/tests/unit/src/unit/issues/Issue2958.hx index 98738d6a..96450984 100644 --- a/tests/unit/src/unit/issues/Issue2958.hx +++ b/tests/unit/src/unit/issues/Issue2958.hx @@ -1,19 +1,19 @@ package unit.issues; -private typedef Asset = String; +private typedef Asset<@:const T> = String; class Issue2958 extends Test { - function test() { - eq( - typeString((null : Asset<["test", 1]>)), - "unit.issues._Issue2958.Asset<[\"test\",1]>" - ); - } + function test() { + eq( + typeString((null : Asset<["test", 1]>)), + "unit.issues._Issue2958.Asset<[\"test\", 1]>" + ); + } - static macro function typeString(e) - { - var typed = haxe.macro.Context.typeExpr(e); - var s = haxe.macro.TypeTools.toString(typed.t); - return macro $v{s}; - } + static macro function typeString(e) + { + var typed = haxe.macro.Context.typeExpr(e); + var s = haxe.macro.TypeTools.toString(typed.t); + return macro $v{s}; + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2963.hx b/tests/unit/src/unit/issues/Issue2963.hx index 3cf25b46..56df7d15 100644 --- a/tests/unit/src/unit/issues/Issue2963.hx +++ b/tests/unit/src/unit/issues/Issue2963.hx @@ -17,6 +17,6 @@ class Issue2963 extends Test { } private abstract A(Dynamic>) from Dynamic> { - public inline function new() this = {} - public inline function get(k:String):Null return Reflect.field(this, k); + public inline function new() this = {} + public inline function get(k:String):Null return Reflect.field(this, k); } diff --git a/tests/unit/src/unit/issues/Issue2979.hx b/tests/unit/src/unit/issues/Issue2979.hx index f9bb32d8..b0489e69 100644 --- a/tests/unit/src/unit/issues/Issue2979.hx +++ b/tests/unit/src/unit/issues/Issue2979.hx @@ -3,15 +3,15 @@ package unit.issues; private class A {} private abstract B(T) { - public function toA():A return null; - public function a() return toA(); + public function toA():A return null; + public function a() return toA(); } class Issue2979 extends Test { function test() { - var b:B = null; - var a:A; - unit.TestType.typedAs(a, b.a()); - unit.TestType.typedAs(a, b.toA()); + var b:B = null; + var a:A; + unit.HelperMacros.typedAs(a, b.a()); + unit.HelperMacros.typedAs(a, b.toA()); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2980.hx b/tests/unit/src/unit/issues/Issue2980.hx index f7f135fc..812865e1 100644 --- a/tests/unit/src/unit/issues/Issue2980.hx +++ b/tests/unit/src/unit/issues/Issue2980.hx @@ -4,7 +4,7 @@ class Issue2980 extends Test { #if python function a(?args:python.KwArgs) {} - function b(?args:python.VarArgs) {} + function b(?args:python.VarArgs) {} function test() { a(); diff --git a/tests/unit/src/unit/issues/Issue2982.hx b/tests/unit/src/unit/issues/Issue2982.hx index 7c6444f9..4a3488ae 100644 --- a/tests/unit/src/unit/issues/Issue2982.hx +++ b/tests/unit/src/unit/issues/Issue2982.hx @@ -6,10 +6,10 @@ class Issue2982 extends Test { eq(12, run()); } - static macro function run() { - var map:Map = new Map(); + static macro function run() { + var map:Map = new Map(); map["foo"] = 12; - var sMap:haxe.ds.StringMap = map; // Test.hx:8: characters 2-40 : Map should be haxe.ds.StringMap - return macro $v{sMap.get("foo")}; - } + var sMap:haxe.ds.StringMap = map; // Test.hx:8: characters 2-40 : Map should be haxe.ds.StringMap + return macro $v{sMap.get("foo")}; + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2988.hx b/tests/unit/src/unit/issues/Issue2988.hx index 4d4ae2ac..4983c56e 100644 --- a/tests/unit/src/unit/issues/Issue2988.hx +++ b/tests/unit/src/unit/issues/Issue2988.hx @@ -1,18 +1,19 @@ package unit.issues; private enum MyEnum2 { - MyEnumValue(p:String); + MyEnumValue(p:String); } class Issue2988 extends Test { function test() { - var a : Dynamic = MyEnumValue("foo"); + var a : Dynamic = MyEnumValue("foo"); var s = ""; - if( Std.is(a, MyEnum2) ){ - switch( a ){ - case MyEnumValue(s1): s = s1; - } - } + if( (a is MyEnum2) ){ + switch( a ){ + case MyEnumValue(s1): s = s1; + case _: + } + } eq("foo", s); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue2989.hx b/tests/unit/src/unit/issues/Issue2989.hx index 5933b989..0ba88b5c 100644 --- a/tests/unit/src/unit/issues/Issue2989.hx +++ b/tests/unit/src/unit/issues/Issue2989.hx @@ -4,7 +4,8 @@ class Issue2989 extends Test { public function test() { - Std.is(null,Array); + var n = null; + (n is Array); new haxe.ds.Vector(10); } } diff --git a/tests/unit/src/unit/issues/Issue2999.hx b/tests/unit/src/unit/issues/Issue2999.hx index 4d22a921..28af2bfd 100644 --- a/tests/unit/src/unit/issues/Issue2999.hx +++ b/tests/unit/src/unit/issues/Issue2999.hx @@ -1,6 +1,5 @@ package unit.issues; -@:analyzer(no_check_has_effect) class Issue2999 extends Test { function test1() { var a = [1, 2]; diff --git a/tests/unit/src/unit/issues/Issue3005.hx b/tests/unit/src/unit/issues/Issue3005.hx index 73e4bb69..83486711 100644 --- a/tests/unit/src/unit/issues/Issue3005.hx +++ b/tests/unit/src/unit/issues/Issue3005.hx @@ -2,8 +2,8 @@ package unit.issues; @:generic private class A { - public function new() {} - private function foo() { + public function new() {} + private function foo() { var b = new B(); b.foo(); } @@ -19,7 +19,7 @@ private class B { class Issue3005 extends Test { @:access(unit.issues.A) function test() { - var a = new A(); - a.foo(); + var a = new A(); + a.foo(); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3008.hx b/tests/unit/src/unit/issues/Issue3008.hx index c009ca24..86863ee2 100644 --- a/tests/unit/src/unit/issues/Issue3008.hx +++ b/tests/unit/src/unit/issues/Issue3008.hx @@ -3,6 +3,6 @@ package unit.issues; class Issue3008 extends Test { function test() { var t = new unit.issues.misc.Issue3008Class("foo"); - t.call(); + t.call(); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3023.hx b/tests/unit/src/unit/issues/Issue3023.hx index 1d4038a1..67ee3e29 100644 --- a/tests/unit/src/unit/issues/Issue3023.hx +++ b/tests/unit/src/unit/issues/Issue3023.hx @@ -1,7 +1,7 @@ package unit.issues; class Issue3023 extends Test { - function test() { + function test() { var x:Array>> = []; x.push([ 0 => new CTest() ]); eq(x[0].get(0).x, 10); diff --git a/tests/unit/src/unit/issues/Issue3024.hx b/tests/unit/src/unit/issues/Issue3024.hx index 59df78d6..e6789d44 100644 --- a/tests/unit/src/unit/issues/Issue3024.hx +++ b/tests/unit/src/unit/issues/Issue3024.hx @@ -1,5 +1,13 @@ package unit.issues; +#if hl + +// no support for recursive types atm +class Issue3024 extends Test { +} + +#else + import haxe.ds.StringMap; import haxe.ds.Vector; @@ -21,4 +29,6 @@ class Issue3024 extends Test { this.myVector = myVector; this.myMap = myMap; } -} \ No newline at end of file +} + +#end \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3029.hx b/tests/unit/src/unit/issues/Issue3029.hx index b98e1215..8c004cdb 100644 --- a/tests/unit/src/unit/issues/Issue3029.hx +++ b/tests/unit/src/unit/issues/Issue3029.hx @@ -4,8 +4,8 @@ private abstract TemplateData({}) from {} to {} { } class Issue3029 extends Test { function test() { - var t1:TemplateData = {}; - var t2:TemplateData = { name: "jason" }; + var t1:TemplateData = {}; + var t2:TemplateData = { name: "jason" }; eq("jason", Reflect.field(t2,"name")); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3033.hx.disabled b/tests/unit/src/unit/issues/Issue3033.hx.disabled index e9a49b61..68456ebf 100644 --- a/tests/unit/src/unit/issues/Issue3033.hx.disabled +++ b/tests/unit/src/unit/issues/Issue3033.hx.disabled @@ -11,15 +11,15 @@ class Issue3033 extends Test public static function guessReturnType() { - var result = new Ref(); - function tt(r:Ref):T return dynamicReturnType(); - if (Math.random() < 0.5) result.t = tt(new Ref()); - return result; + var result = new Ref(); + function tt(r:Ref):T return dynamicReturnType(); + if (Math.random() < 0.5) result.t = tt(new Ref()); + return result; } public static function dynamicReturnType():Dynamic { - return guessReturnType(); + return guessReturnType(); } } diff --git a/tests/unit/src/unit/issues/Issue3042.hx b/tests/unit/src/unit/issues/Issue3042.hx index 351cabcc..e597dd69 100644 --- a/tests/unit/src/unit/issues/Issue3042.hx +++ b/tests/unit/src/unit/issues/Issue3042.hx @@ -1,12 +1,12 @@ package unit.issues; private abstract MyAbstract(Int) { - public var inlineProp(get, set):Int; + public var inlineProp(get, set):Int; - public function new() {this = 0;} + public function new() {this = 0;} - private inline function get_inlineProp():Int {return this;} - private inline function set_inlineProp(value:Int):Int {return this = value;} + private inline function get_inlineProp():Int {return this;} + private inline function set_inlineProp(value:Int):Int {return this = value;} } class Issue3042 extends Test { diff --git a/tests/unit/src/unit/issues/Issue3054.hx b/tests/unit/src/unit/issues/Issue3054.hx index 0562cb07..70aaa02f 100644 --- a/tests/unit/src/unit/issues/Issue3054.hx +++ b/tests/unit/src/unit/issues/Issue3054.hx @@ -10,7 +10,6 @@ private enum MyOtherEnum { B; } -@:analyzer(no_check_has_effect) class Issue3054 extends Test { function test() { var myValue:Null = A; @@ -20,7 +19,7 @@ class Issue3054 extends Test { } var myOtherValue:Null = B; - t(unit.TestType.typeError(switch(myOtherValue) { + t(unit.HelperMacros.typeError(switch(myOtherValue) { case A(A): case A(B): case B: diff --git a/tests/unit/src/unit/issues/Issue3061.hx b/tests/unit/src/unit/issues/Issue3061.hx index 15c4227b..0b6ce822 100644 --- a/tests/unit/src/unit/issues/Issue3061.hx +++ b/tests/unit/src/unit/issues/Issue3061.hx @@ -1,11 +1,11 @@ package unit.issues; private enum MyEnum1 { - A; + A; } private enum MyEnum2 { - A; + A; B; } diff --git a/tests/unit/src/unit/issues/Issue3063.hx b/tests/unit/src/unit/issues/Issue3063.hx index 5870ca84..f6771020 100644 --- a/tests/unit/src/unit/issues/Issue3063.hx +++ b/tests/unit/src/unit/issues/Issue3063.hx @@ -2,12 +2,12 @@ package unit.issues; @:enum private abstract AString(String) to String { - var CTOR1 = "foo"; + var CTOR1 = "foo"; } @:enum private abstract AInt(Int) to Int { - var CTOR2 = 12; + var CTOR2 = 12; } class Issue3063 extends Test { @@ -15,11 +15,11 @@ class Issue3063 extends Test { var a = new Map(); a.set(CTOR1, 1); eq(1, a.get(CTOR1)); - t(Std.is(a, haxe.ds.StringMap)); + t((a is haxe.ds.StringMap)); var b = new Map(); b.set(CTOR2, 1); eq(1, b.get(CTOR2)); - t(Std.is(b, haxe.ds.IntMap)); + t((b is haxe.ds.IntMap)); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3071.hx b/tests/unit/src/unit/issues/Issue3071.hx index a5e7d721..66c55b66 100644 --- a/tests/unit/src/unit/issues/Issue3071.hx +++ b/tests/unit/src/unit/issues/Issue3071.hx @@ -4,53 +4,53 @@ import unit.Test; class Issue3071 extends Test { - function test() { - // join - var a : { function join (s:String):String; } = [1,2]; - eq("1,2", a.join(",")); - - var a : Dynamic = [1,2]; - eq("1,2", a.join(",")); - - // pop - var a : { function pop ():Int; } = [1,2]; - a.pop(); - var a : Array = cast a; - eq(1, a.length); - eq(a[0], 1); - - var a : Dynamic = [1,2]; - a.pop(); - var a : Array = cast a; - eq(1, a.length); - eq(a[0], 1); - - // push - var a : { function push (x:Int):Int; } = []; - a.push(1); - var a : Array = cast a; - eq(1, a.length); - eq(a[0], 1); - - var a : Dynamic = []; - a.push(1); - var a : Array = cast a; - eq(1, a.length); - eq(a[0], 1); - - // shift - var a : { function shift ():Int; } = [1,2]; - a.shift(); - var a : Array = cast a; - eq(1, a.length); - eq(a[0], 2); - - var a : Dynamic = [1,2]; - a.shift(); - var a : Array = cast a; - eq(1, a.length); - eq(a[0], 2); - - } + function test() { + // join + var a : { function join (s:String):String; } = [1,2]; + eq("1,2", a.join(",")); + + var a : Dynamic = [1,2]; + eq("1,2", a.join(",")); + + // pop + var a : { function pop ():Int; } = [1,2]; + a.pop(); + var a : Array = cast a; + eq(1, a.length); + eq(a[0], 1); + + var a : Dynamic = [1,2]; + a.pop(); + var a : Array = cast a; + eq(1, a.length); + eq(a[0], 1); + + // push + var a : { function push (x:Int):Int; } = []; + a.push(1); + var a : Array = cast a; + eq(1, a.length); + eq(a[0], 1); + + var a : Dynamic = []; + a.push(1); + var a : Array = cast a; + eq(1, a.length); + eq(a[0], 1); + + // shift + var a : { function shift ():Int; } = [1,2]; + a.shift(); + var a : Array = cast a; + eq(1, a.length); + eq(a[0], 2); + + var a : Dynamic = [1,2]; + a.shift(); + var a : Array = cast a; + eq(1, a.length); + eq(a[0], 2); + + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3081.hx b/tests/unit/src/unit/issues/Issue3081.hx index 5705e83a..3204124e 100644 --- a/tests/unit/src/unit/issues/Issue3081.hx +++ b/tests/unit/src/unit/issues/Issue3081.hx @@ -1,17 +1,17 @@ package unit.issues; private typedef T1 = { - function foo():T; + function foo():T; } private typedef T2 = { - function foo():String; + function foo():String; } private typedef T3 = { - > T1, - > T2, - function bar():Int; + > T1, + > T2, + function bar():Int; function foo():String; } diff --git a/tests/unit/src/unit/issues/Issue3088.hx b/tests/unit/src/unit/issues/Issue3088.hx index fac38d1a..2f63e4fc 100644 --- a/tests/unit/src/unit/issues/Issue3088.hx +++ b/tests/unit/src/unit/issues/Issue3088.hx @@ -19,33 +19,33 @@ private class C { } private typedef PublicationData = { - year:Int, - artist:String, - name:String, - type:String, - ?tracks:Array, - ?bSide:String + year:Int, + artist:String, + name:String, + type:String, + ?tracks:Array, + ?bSide:String } private abstract Publication(PublicationData) from PublicationData { - public var year(get, never):Int; - public var artist(get, never):String; - public var name(get, never):String; - public var kind(get, never):PublicationKind; - inline function get_year() return this.year; - inline function get_artist() return this.artist; - inline function get_name() return this.name; - inline function get_kind() - return - if (this.type == 'album') - Album(this.tracks); - else - Single(this.bSide); + public var year(get, never):Int; + public var artist(get, never):String; + public var name(get, never):String; + public var kind(get, never):PublicationKind; + inline function get_year() return this.year; + inline function get_artist() return this.artist; + inline function get_name() return this.name; + inline function get_kind() + return + if (this.type == 'album') + Album(this.tracks); + else + Single(this.bSide); } private enum PublicationKind { - Album(tracks:Array); - Single(bSide:String); + Album(tracks:Array); + Single(bSide:String); } class Issue3088 extends Test { @@ -54,45 +54,45 @@ class Issue3088 extends Test { } function testCrazyJuraj() { - var publications:Array = [ - { - year : 1967, - artist : "The Jimi Hendrix Experience", - name : "Are You Experienced?", - type : "album", - tracks : [/* ... */], - }, - { - year : 1978, - artist : "Bob Marley and the Wailers", - name : "Babylon by Bus", - type : "album", - tracks : [/* ... */], - }, - { - year : 1962, - artist : "John Lee Hooker", - name : "Boom Boom", - type : "single", - bSide : "Drug Store Woman", - }, - ]; - var albumsBefore1970 = []; - for (p in publications) - switch p { - case { - year : _ < 1970 => true, - name : name, - kind : kind = Album(tracks) - }: - albumsBefore1970.push({ - name : name, - kind : kind - }); - default: - } + var publications:Array = [ + { + year : 1967, + artist : "The Jimi Hendrix Experience", + name : "Are You Experienced?", + type : "album", + tracks : [/* ... */], + }, + { + year : 1978, + artist : "Bob Marley and the Wailers", + name : "Babylon by Bus", + type : "album", + tracks : [/* ... */], + }, + { + year : 1962, + artist : "John Lee Hooker", + name : "Boom Boom", + type : "single", + bSide : "Drug Store Woman", + }, + ]; + var albumsBefore1970 = []; + for (p in publications) + switch p { + case { + year : _ < 1970 => true, + name : name, + kind : kind = Album(tracks) + }: + albumsBefore1970.push({ + name : name, + kind : kind + }); + default: + } - eq(1, albumsBefore1970.length); - eq("Are You Experienced?", albumsBefore1970[0].name); + eq(1, albumsBefore1970.length); + eq("Are You Experienced?", albumsBefore1970[0].name); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3089.hx b/tests/unit/src/unit/issues/Issue3089.hx index 0a2de38f..31f23eda 100644 --- a/tests/unit/src/unit/issues/Issue3089.hx +++ b/tests/unit/src/unit/issues/Issue3089.hx @@ -7,8 +7,8 @@ private class GenericBuild { } class Issue3089 extends Test { function test() { - unit.TestType.typedAs((null:GenericBuild), (null:GenericBuildResult<"">)); - unit.TestType.typedAs((null:GenericBuild), (null:GenericBuildResult<"String">)); - unit.TestType.typedAs((null:GenericBuild), (null:GenericBuildResult<"String_Int_Float">)); + unit.HelperMacros.typedAs((null:GenericBuild), (null:GenericBuildResult<"">)); + unit.HelperMacros.typedAs((null:GenericBuild), (null:GenericBuildResult<"String">)); + unit.HelperMacros.typedAs((null:GenericBuild), (null:GenericBuildResult<"String_Int_Float">)); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3090.hx b/tests/unit/src/unit/issues/Issue3090.hx index df824fc9..71b40c74 100644 --- a/tests/unit/src/unit/issues/Issue3090.hx +++ b/tests/unit/src/unit/issues/Issue3090.hx @@ -2,7 +2,7 @@ package unit.issues; import haxe.xml.Printer; @:generic private class A{ - public function new(){} + public function new(){} } class Issue3090 extends Test { diff --git a/tests/unit/src/unit/issues/Issue3110.hx b/tests/unit/src/unit/issues/Issue3110.hx index 192737f1..339026d8 100644 --- a/tests/unit/src/unit/issues/Issue3110.hx +++ b/tests/unit/src/unit/issues/Issue3110.hx @@ -5,7 +5,7 @@ private abstract MyOpaciteInt(Int) {} class Issue3110 extends Test { function test() { var o:List = null; - t(unit.TestType.typeError({ + t(unit.HelperMacros.typeError({ var u:List = o; })); } diff --git a/tests/unit/src/unit/issues/Issue3113.hx b/tests/unit/src/unit/issues/Issue3113.hx index 3864c444..1c0c4128 100644 --- a/tests/unit/src/unit/issues/Issue3113.hx +++ b/tests/unit/src/unit/issues/Issue3113.hx @@ -9,9 +9,9 @@ class Issue3113 extends Test t = cast B; eq( t.func(1, 2), 1 ); // runtime: Unhandled Exception: - // Haxe Exception: Method 'func' not found on type B - // [ERROR] FATAL UNHANDLED EXCEPTION: Haxe Exception: Method 'func' not found on type B - // -> because of B having type parameter + // Haxe Exception: Method 'func' not found on type B + // [ERROR] FATAL UNHANDLED EXCEPTION: Haxe Exception: Method 'func' not found on type B + // -> because of B having type parameter } } @@ -20,10 +20,10 @@ private class Base {} @:keep private class A { - public static function func(x:G, y:G):G { return x; } + public static function func(x:G, y:G):G { return x; } } @:keep private class B extends Base { - public static function func(x:G, y:G):G { return x; } + public static function func(x:G, y:G):G { return x; } } diff --git a/tests/unit/src/unit/issues/Issue3115.hx b/tests/unit/src/unit/issues/Issue3115.hx index 4b02c686..92491811 100644 --- a/tests/unit/src/unit/issues/Issue3115.hx +++ b/tests/unit/src/unit/issues/Issue3115.hx @@ -2,13 +2,13 @@ package unit.issues; class Issue3115 extends Test { function test() { - var k = 0; - var i = 0; - do { - i++; - if (i & 1 == 0) continue; - k++; - } while (i++ < 10); + var k = 0; + var i = 0; + do { + i++; + if (i & 1 == 0) continue; + k++; + } while (i++ < 10); eq(12, i); eq(6, k); } diff --git a/tests/unit/src/unit/issues/Issue3132.hx b/tests/unit/src/unit/issues/Issue3132.hx index e5f7a69c..780de313 100644 --- a/tests/unit/src/unit/issues/Issue3132.hx +++ b/tests/unit/src/unit/issues/Issue3132.hx @@ -4,7 +4,7 @@ class Issue3132 extends unit.Test { function test() { var a:Array<{a:Int, ?b:Int}> = [{a:1}, {a:1, b:2}]; var a:Array<{a:Int, ?b:Int}> = [{a:1, b:2}, {a:1}]; - //t(unit.TestType.typeError([{a:1}, {a:1, b:2}])); - //t(unit.TestType.typeError([{a:1, b:2}, {a:1}])); + //t(unit.HelperMacros.typeError([{a:1}, {a:1, b:2}])); + //t(unit.HelperMacros.typeError([{a:1, b:2}, {a:1}])); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3133.hx b/tests/unit/src/unit/issues/Issue3133.hx index cbf7c952..4689b2dd 100644 --- a/tests/unit/src/unit/issues/Issue3133.hx +++ b/tests/unit/src/unit/issues/Issue3133.hx @@ -1,14 +1,14 @@ package unit.issues; private class Child extends unit.issues.misc.Issue3133Class { - override function test(unit:String) { - super.test(unit); - } + override function test(unit:String) { + super.test(unit); + } } class Issue3133 extends Test { function test() { - var t = new Child(); - t.test("foo"); + var t = new Child(); + t.test("foo"); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3138.hx b/tests/unit/src/unit/issues/Issue3138.hx index 9a74a780..a16c14f2 100644 --- a/tests/unit/src/unit/issues/Issue3138.hx +++ b/tests/unit/src/unit/issues/Issue3138.hx @@ -12,25 +12,25 @@ class Issue3138 extends Test } private class A { - public function new(a) {} + public function new(a) {} } private class B extends A { - public function new(?a = 1) { - super(a); // error CS0030: Cannot convert type 'int' to 'haxe.lang.Null' - } + public function new(?a = 1) { + super(a); // error CS0030: Cannot convert type 'int' to 'haxe.lang.Null' + } } #if (cs || java) private class C { - public function new(a) {} + public function new(a) {} } private class D extends C { - public function new(?a:Single = 1) { - super(a); // error CS0030: Cannot convert type 'int' to 'haxe.lang.Null' - } + public function new(?a:Single = 1) { + super(a); // error CS0030: Cannot convert type 'int' to 'haxe.lang.Null' + } } #end diff --git a/tests/unit/src/unit/issues/Issue3150.hx b/tests/unit/src/unit/issues/Issue3150.hx index e9777e42..f02b081f 100644 --- a/tests/unit/src/unit/issues/Issue3150.hx +++ b/tests/unit/src/unit/issues/Issue3150.hx @@ -2,7 +2,7 @@ package unit.issues; class Issue3150 extends Test { function test() { - t(unit.TestType.typeError( + t(unit.HelperMacros.typeError( var d = switch (2) { case 3: 90; case f if (f == 0 | 2): -135; diff --git a/tests/unit/src/unit/issues/Issue3181.hx b/tests/unit/src/unit/issues/Issue3181.hx index 7a7843d5..f9b5a9a8 100644 --- a/tests/unit/src/unit/issues/Issue3181.hx +++ b/tests/unit/src/unit/issues/Issue3181.hx @@ -5,7 +5,7 @@ package unit.issues; class Issue3181 extends Test { function test() { var a:Null = cast 1; - t(unit.TestType.typeError( + t(unit.HelperMacros.typeError( switch(a) { } )); } diff --git a/tests/unit/src/unit/issues/Issue3183.hx b/tests/unit/src/unit/issues/Issue3183.hx index 5b420084..4cfdb376 100644 --- a/tests/unit/src/unit/issues/Issue3183.hx +++ b/tests/unit/src/unit/issues/Issue3183.hx @@ -6,17 +6,17 @@ class MyTuple { } class Issue3183 extends Test { function test() { var t = new MyTuple("foo", 12); - unit.TestType.typedAs(t, (null : MyTuple)); + unit.HelperMacros.typedAs(t, (null : MyTuple)); eq("foo", t.v0); eq(12, t.v1); var t = new MyTuple("foo", 12); - unit.TestType.typedAs(t, (null : MyTuple)); + unit.HelperMacros.typedAs(t, (null : MyTuple)); eq("foo", t.v0); eq(12, t.v1); var t:MyTuple = new MyTuple("foo", 12); - unit.TestType.typedAs(t, (null : MyTuple)); + unit.HelperMacros.typedAs(t, (null : MyTuple)); eq("foo", t.v0); eq(12, t.v1); } diff --git a/tests/unit/src/unit/issues/Issue3192.hx b/tests/unit/src/unit/issues/Issue3192.hx new file mode 100644 index 00000000..e49b10b3 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3192.hx @@ -0,0 +1,17 @@ +package unit.issues; + +class Issue3192 extends Test { + function test() { + var x1 = {x:1, y:2}; + var x2 = ({x:1, y:2}:{x:Int,y:Int}); + var x3:{x:Int,y:Int} = {x:1, y:2}; + var y1:{} = x1; + var y2:{} = x2; + var y3:{} = x3; + // var z1:{x:Int} = x1; + var z2:{x:Int} = x2; + var z3:{x:Int} = x3; + eq(1, x1.x); + eq(2, x1.y); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3197.hx b/tests/unit/src/unit/issues/Issue3197.hx index a88e0a7b..30955d68 100644 --- a/tests/unit/src/unit/issues/Issue3197.hx +++ b/tests/unit/src/unit/issues/Issue3197.hx @@ -2,18 +2,18 @@ package unit.issues; class Issue3197 extends Test { function test() { - var v = "good"; - for (i in 0...10) { - v = if (i == 1) "bad" else break; - } - eq(v, "good"); + var v = "good"; + for (i in 0...10) { + v = if (i == 1) "bad" else break; + } + eq(v, "good"); - var a = []; - for (i in 0...10) { - var v = if (i == 1) i else continue; - a.push(v); - } - eq(a.length, 1); - eq(a[0], 1); + var a = []; + for (i in 0...10) { + var v = if (i == 1) i else continue; + a.push(v); + } + eq(a.length, 1); + eq(a[0], 1); } } diff --git a/tests/unit/src/unit/issues/Issue3198.hx b/tests/unit/src/unit/issues/Issue3198.hx index c31f06c3..18a1245e 100644 --- a/tests/unit/src/unit/issues/Issue3198.hx +++ b/tests/unit/src/unit/issues/Issue3198.hx @@ -10,24 +10,24 @@ private typedef C = {>A,} private typedef D = {>A, >B,} class Issue3198 extends Test { - function test() { - eq(getExtends((null : C)), "A"); - eq(getExtends((null : D)), "A,B"); - } + function test() { + eq(getExtends((null : C)), "A"); + eq(getExtends((null : D)), "A,B"); + } - static macro function getExtends(e) { - switch (Context.follow(Context.typeof(e))) { - case TAnonymous(_.get() => {status: AExtend(_.get() => tl)}): - var p = []; - for (t in tl) switch (t) { - case TType(_.get() => dt, []): - p.push(dt.name); - default: - throw false; - } - return macro $v{p.join(",")}; - default: - throw false; - } - } + static macro function getExtends(e) { + switch (Context.follow(Context.typeof(e))) { + case TAnonymous(_.get() => {status: AExtend(_.get() => tl)}): + var p = []; + for (t in tl) switch (t) { + case TType(_.get() => dt, []): + p.push(dt.name); + default: + throw false; + } + return macro $v{p.join(",")}; + default: + throw false; + } + } } diff --git a/tests/unit/src/unit/issues/Issue3214.hx b/tests/unit/src/unit/issues/Issue3214.hx index 5928ce33..e671ec3e 100644 --- a/tests/unit/src/unit/issues/Issue3214.hx +++ b/tests/unit/src/unit/issues/Issue3214.hx @@ -26,7 +26,7 @@ class Issue3214 extends unit.Test { function test() { var a = Int64.make(1,2); var b = Int64.make(3,4); - var c = a * b; + var c = a * b; eq(21, c.get().get()); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3217.hx b/tests/unit/src/unit/issues/Issue3217.hx index bf46343b..9ddfd4ca 100644 --- a/tests/unit/src/unit/issues/Issue3217.hx +++ b/tests/unit/src/unit/issues/Issue3217.hx @@ -4,11 +4,11 @@ class Issue3217 extends Test { public function test() { - #if (cpp && !cppia) + #if (cpp && !cppia) var t:NativeClassStruct = null; - #else + #else var t:{ test:Int } = new NativeClass(); - #end + #end t.test = 10; eq(t.test,10); } diff --git a/tests/unit/src/unit/issues/Issue3218.hx b/tests/unit/src/unit/issues/Issue3218.hx index a89abbec..783062b7 100644 --- a/tests/unit/src/unit/issues/Issue3218.hx +++ b/tests/unit/src/unit/issues/Issue3218.hx @@ -9,6 +9,6 @@ class Issue3218 extends Test { eq(2, a(1)); var f:haxe.Constraints.Function = function(){ return 12; } - eq(12, f()); + eq(12, f()); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3244.hx b/tests/unit/src/unit/issues/Issue3244.hx index b6709077..2b4eec3a 100644 --- a/tests/unit/src/unit/issues/Issue3244.hx +++ b/tests/unit/src/unit/issues/Issue3244.hx @@ -1,11 +1,11 @@ package unit.issues; private abstract A(String) from String { - @:from static function fromInt(v:Int):A return "abc"; + @:from static function fromInt(v:Int):A return "abc"; } private class TestClass { - static public var a:A = 1; + static public var a:A = 1; public var b:A = 1; public function new() { } diff --git a/tests/unit/src/unit/issues/Issue3254.hx b/tests/unit/src/unit/issues/Issue3254.hx new file mode 100644 index 00000000..3f89df53 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3254.hx @@ -0,0 +1,14 @@ +package unit.issues; + +private class Data { + static public function test() { return 12; } +} + +@:forwardStatics +private abstract AData(Data) { } + +class Issue3254 extends Test { + function test() { + eq(12, AData.test()); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3280.hx b/tests/unit/src/unit/issues/Issue3280.hx index f436df0b..94e54876 100644 --- a/tests/unit/src/unit/issues/Issue3280.hx +++ b/tests/unit/src/unit/issues/Issue3280.hx @@ -2,16 +2,16 @@ package unit.issues; class Issue3280 extends Test { - static function recurse( i : Int, param : String ) { - if( i > 0 ) { + static function recurse( i : Int, param : String ) { + if( i > 0 ) { param += iter(i, recurse.bind(_,param)); } return param; - } + } - static function iter( v : Int, f) { - return f(v-1); - } + static function iter( v : Int, f) { + return f(v-1); + } function test() { eq("aaaa", recurse(3, "a")); diff --git a/tests/unit/src/unit/issues/Issue3292.hx b/tests/unit/src/unit/issues/Issue3292.hx index f9985b70..5957845b 100644 --- a/tests/unit/src/unit/issues/Issue3292.hx +++ b/tests/unit/src/unit/issues/Issue3292.hx @@ -1,36 +1,36 @@ package unit.issues; private class Component { - public static var TYPE : String = "type"; - public function doSomething() { return TYPE; }; - public function new() { }; + public static var TYPE : String = "type"; + public function doSomething() { return TYPE; }; + public function new() { }; } private class A { - var _components : Map; + var _components : Map; - public function new() { - _components = new Map(); - _components.set( Component.TYPE, new Component() ); - } + public function new() { + _components = new Map(); + _components.set( Component.TYPE, new Component() ); + } - @:generic public function get( classType : Class ) : T { - return cast _components.get( Reflect.field( classType, "TYPE" ) ); - } + @:generic public function get( classType : Class ) : T { + return cast _components.get( Reflect.field( classType, "TYPE" ) ); + } } private class B extends A { - public function new() { - super(); - } + public function new() { + super(); + } } class Issue3292 extends Test { function test() { - var a : A = new A(); - eq("type", a.get( Component ).doSomething()); + var a : A = new A(); + eq("type", a.get( Component ).doSomething()); - var b : B = new B(); - eq("type", b.get( Component ).doSomething()); + var b : B = new B(); + eq("type", b.get( Component ).doSomething()); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3333.hx b/tests/unit/src/unit/issues/Issue3333.hx index 848bfa14..fb9e08f4 100644 --- a/tests/unit/src/unit/issues/Issue3333.hx +++ b/tests/unit/src/unit/issues/Issue3333.hx @@ -1,13 +1,13 @@ package unit.issues; private abstract MyString(String) to String { - public function new (url:String) this = url; + public function new (url:String) this = url; public inline function get() return this; } class Issue3333 extends Test { function test() { - var f = MyString.new.bind("hey"); + var f = MyString.new.bind("hey"); eq("hey", f().get()); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3338.hx b/tests/unit/src/unit/issues/Issue3338.hx index 641c5472..121bde5d 100644 --- a/tests/unit/src/unit/issues/Issue3338.hx +++ b/tests/unit/src/unit/issues/Issue3338.hx @@ -2,22 +2,22 @@ package unit.issues; class Issue3338 extends Test { function test() { - var e:TestEnum = null; - + var e:TestEnum = null; + match(Val1, 0); match(null, 1); match(Val2, 2); } - + function match(e:TestEnum, expected:Int) { var matched:Int = -1; - + matched = switch (e) { case Val1: 0; case null: 1; case _: 2; } - + eq(matched, expected); } } diff --git a/tests/unit/src/unit/issues/Issue3344.hx b/tests/unit/src/unit/issues/Issue3344.hx index d1e57b18..9fdea6e6 100644 --- a/tests/unit/src/unit/issues/Issue3344.hx +++ b/tests/unit/src/unit/issues/Issue3344.hx @@ -2,13 +2,13 @@ package unit.issues; class Issue3344 extends unit.Test { - static function hello() { + static function hello() { return "ok"; - } + } function test() { - eq("ok", Issue3344.hello()); - var Issue3344 = 10; + eq("ok", Issue3344.hello()); + var Issue3344 = 10; eq(10, Issue3344); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3345.hx b/tests/unit/src/unit/issues/Issue3345.hx index 33b01b10..b1ae7dfe 100644 --- a/tests/unit/src/unit/issues/Issue3345.hx +++ b/tests/unit/src/unit/issues/Issue3345.hx @@ -28,11 +28,15 @@ class Issue3345 extends Test { var acc:Meters = .0; for (i in 0...10) acc += 10; +#if !lua eq("100(m)", acc); +#end var acc:Meters = .0; for (i in 0...10) acc -= 10; +#if !lua eq("-100(m)", acc); +#end } -} \ No newline at end of file +} diff --git a/tests/unit/src/unit/issues/Issue3346.hx b/tests/unit/src/unit/issues/Issue3346.hx index 711a0a2f..2f32a961 100644 --- a/tests/unit/src/unit/issues/Issue3346.hx +++ b/tests/unit/src/unit/issues/Issue3346.hx @@ -1,9 +1,9 @@ package unit.issues; private abstract IntKey(String) { - function new(s) this = s; - @:to function toInt():Int return Std.parseInt(this); - @:from static function fromInt(v:Int):IntKey return new IntKey(Std.string(v)); + function new(s) this = s; + @:to function toInt():Int return Std.parseInt(this); + @:from static function fromInt(v:Int):IntKey return new IntKey(Std.string(v)); } @@ -12,10 +12,10 @@ class Issue3346 extends Test { t(m()); } - static macro function m() { - var actualType = haxe.macro.Context.typeof(macro 1); - var expectedType = haxe.macro.Context.typeof(macro (null : IntKey)); - var unify = haxe.macro.Context.unify(actualType, expectedType); - return macro $v{unify}; - } + static macro function m() { + var actualType = haxe.macro.Context.typeof(macro 1); + var expectedType = haxe.macro.Context.typeof(macro (null : IntKey)); + var unify = haxe.macro.Context.unify(actualType, expectedType); + return macro $v{unify}; + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3347.hx b/tests/unit/src/unit/issues/Issue3347.hx index 199ab07b..1304e459 100644 --- a/tests/unit/src/unit/issues/Issue3347.hx +++ b/tests/unit/src/unit/issues/Issue3347.hx @@ -1,25 +1,25 @@ package unit.issues; private abstract IntMap(Dynamic) { - public function new() this = {}; - @:arrayAccess public function get(k:IntKey):V return Reflect.field(this, k); - @:arrayAccess public function set(k:IntKey, i:V):Void Reflect.setField(this, k, i); + public function new() this = {}; + @:arrayAccess public function get(k:IntKey):V return Reflect.field(this, k); + @:arrayAccess public function set(k:IntKey, i:V):Void Reflect.setField(this, k, i); } private abstract IntMap2(Dynamic) { - public function new() this = {}; - @:arrayAccess public function get(k:T):V return Reflect.field(this, cast k); - @:arrayAccess public function set(k:T, i:V):Void Reflect.setField(this, cast k, i); + public function new() this = {}; + @:arrayAccess public function get(k:T):V return Reflect.field(this, cast k); + @:arrayAccess public function set(k:T, i:V):Void Reflect.setField(this, cast k, i); } abstract IntMap3(Dynamic) { - static public var called = false; + static public var called = false; public function new() this = {}; - @:arrayAccess function get(k:IntKey):V return { + @:arrayAccess function get(k:IntKey):V return { called = true; Reflect.field(this, k); } - @:arrayAccess function getInt(k:Int):V return Reflect.field(this, Std.string(k)); + @:arrayAccess function getInt(k:Int):V return Reflect.field(this, Std.string(k)); } private abstract IntKey(String) to String { @@ -48,15 +48,15 @@ class Issue3347 extends Test { eq("0;0;0;0;0;2;", IntKey.fromList); eq(4, m[0]); - t(unit.TestType.typeError(m["1"] = 1)); - t(unit.TestType.typeError(m[1] = "1")); + t(unit.HelperMacros.typeError(m["1"] = 1)); + t(unit.HelperMacros.typeError(m[1] = "1")); - var m2 = new IntMap2(); + var m2 = new IntMap2(); // should fail because constraints unify without casts - t(unit.TestType.typeError(m2[1])); + t(unit.HelperMacros.typeError(m2[1])); - var m3 = new IntMap3(); - var v = m3[0]; + var m3 = new IntMap3(); + var v = m3[0]; t(IntMap3.called); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3360.hx b/tests/unit/src/unit/issues/Issue3360.hx index 6ba7171a..c1852130 100644 --- a/tests/unit/src/unit/issues/Issue3360.hx +++ b/tests/unit/src/unit/issues/Issue3360.hx @@ -1,29 +1,29 @@ package unit.issues; private abstract Vec3(Array) from Array to Array { - inline public function new(_x:Float, _y:Float, _z:Float):Vec3 - this = _alloc(_x, _y, _z); + inline public function new(_x:Float, _y:Float, _z:Float):Vec3 + this = _alloc(_x, _y, _z); inline private static function _alloc(_x:Float, _y:Float, _z:Float):Array - return [_x, _y, _z]; + return [_x, _y, _z]; } private abstract Quat(Array) from Array to Array { - inline public function new(_x:Float, _y:Float, _z:Float, _w:Float):Quat - this = _alloc(_x, _y, _z, _w); + inline public function new(_x:Float, _y:Float, _z:Float, _w:Float):Quat + this = _alloc(_x, _y, _z, _w); inline private static function _alloc(_x:Float, _y:Float, _z:Float, _w:Float):Array - return [_x, _y, _z, _w]; + return [_x, _y, _z, _w]; - @:op(A * B) - inline public static function transformVec3(lhs:Quat, rhs:Vec3):Vec3 { - return new Vec3(1,2,3); - } + @:op(A * B) + inline public static function transformVec3(lhs:Quat, rhs:Vec3):Vec3 { + return new Vec3(1,2,3); + } - @:op(A * B) + @:op(A * B) inline public static function mult(lhs:Quat, rhs:Quat):Quat { - return new Quat(1,2,3,1); - } + return new Quat(1,2,3,1); + } } private abstract Kilometer(Float) from Float to Float { } @@ -31,23 +31,23 @@ private abstract Meter(Float) from Float { } class Issue3360 extends Test { function test() { - var v = new Vec3(0,0,0); - var q0 = new Quat(0,0,0,1); - var q1 = new Quat(0,0,0,1); + var v = new Vec3(0,0,0); + var q0 = new Quat(0,0,0,1); + var q1 = new Quat(0,0,0,1); - var res = q0 * v; - unit.TestType.typedAs(res, (null : Vec3)); + var res = q0 * v; + unit.HelperMacros.typedAs(res, (null : Vec3)); feq(1, res[0]); feq(2, res[1]); feq(3, res[2]); - var res = q0 * q1; - unit.TestType.typedAs(res, (null : Quat)); + var res = q0 * q1; + unit.HelperMacros.typedAs(res, (null : Quat)); feq(1, res[0]); feq(2, res[1]); feq(3, res[2]); feq(1, res[3]); var k:Kilometer = 1; - t(unit.TestType.typeError(var m:Meter = k)); + t(unit.HelperMacros.typeError(var m:Meter = k)); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3361.hx b/tests/unit/src/unit/issues/Issue3361.hx new file mode 100644 index 00000000..9345f2f7 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3361.hx @@ -0,0 +1,33 @@ +package unit.issues; + +private interface I { + public var v(default, never):Float; +} + +private class C implements I { + public var v:Int; + public function new() { } +} + +private interface I2 { + public var v(never, default):Int; +} + +private class C2 implements I2 { + public var v:Float; + public function new() { } +} + +class Issue3361 extends Test { + function test() { + var c = new C(); + var i:I = c; + c.v = 12; + feq(12., i.v); + + var c2 = new C2(); + var i2:I2 = c2; + i2.v = 12; + feq(12., c.v); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3365.hx b/tests/unit/src/unit/issues/Issue3365.hx index 360d13e4..a9118f82 100644 --- a/tests/unit/src/unit/issues/Issue3365.hx +++ b/tests/unit/src/unit/issues/Issue3365.hx @@ -1,7 +1,7 @@ package unit.issues; private abstract IntKey(String) { - @:from inline static function fromInt(v:Int):IntKey return cast ""; + @:from inline static function fromInt(v:Int):IntKey return cast ""; } class Issue3365 extends Test { @@ -10,10 +10,10 @@ class Issue3365 extends Test { t(func()); } - static macro function func() { - var t1 = haxe.macro.Context.typeof(macro 1); - var t2 = haxe.macro.Context.typeof(macro (null : IntKey)); - var r = haxe.macro.Context.unify(t1, t2); + static macro function func() { + var t1 = haxe.macro.Context.typeof(macro 1); + var t2 = haxe.macro.Context.typeof(macro (null : IntKey)); + var r = haxe.macro.Context.unify(t1, t2); return macro $v{r}; - } + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3370.hx b/tests/unit/src/unit/issues/Issue3370.hx index 8259d34f..3ee3714c 100644 --- a/tests/unit/src/unit/issues/Issue3370.hx +++ b/tests/unit/src/unit/issues/Issue3370.hx @@ -3,32 +3,32 @@ package unit.issues; import haxe.Int64; abstract FunInt64(Int64) { - public static var NEGATIVE_ONE(default, null) : FunInt64 = FunInt64.make(0xffffffff, 0xffffffff); - public static var ZERO(default, null) : FunInt64 = FunInt64.make(0x00000000, 0x00000000); + public static var NEGATIVE_ONE(default, null) : FunInt64 = FunInt64.make(0xffffffff, 0xffffffff); + public static var ZERO(default, null) : FunInt64 = FunInt64.make(0x00000000, 0x00000000); - public static inline function make(high : Int, low : Int) : FunInt64 - { - return new FunInt64(Int64.make(high, low)); - } + public static inline function make(high : Int, low : Int) : FunInt64 + { + return new FunInt64(Int64.make(high, low)); + } - @:op(A>>B) public static inline function shrs_i(j : FunInt64, k : Int) - { - if (k >= 63) - { - return ((j : Int64).high < 0) ? NEGATIVE_ONE : ZERO; - } - return new FunInt64(Int64.shr(j, k)); - } + @:op(A>>B) public static inline function shrs_i(j : FunInt64, k : Int) + { + if (k >= 63) + { + return ((j : Int64).high < 0) ? NEGATIVE_ONE : ZERO; + } + return new FunInt64(Int64.shr(j, k)); + } - public inline function new(a : Int64) : Int64 - { - this = a; - } + public inline function new(a : Int64) : Int64 + { + this = a; + } - @:to public inline function toInt64() - { - return this; - } + @:to public inline function toInt64() + { + return this; + } } class Issue3370 extends unit.Test { diff --git a/tests/unit/src/unit/issues/Issue3383.hx b/tests/unit/src/unit/issues/Issue3383.hx index efa28367..64691e05 100644 --- a/tests/unit/src/unit/issues/Issue3383.hx +++ b/tests/unit/src/unit/issues/Issue3383.hx @@ -11,6 +11,7 @@ class Issue3383 extends Test { ui:UInt = cast null, n:cs.system.Nullable_1 = null; + #if !(erase_generics && !fast_cast) eq(i, cast null); eq(f, cast null); eq(s, cast null); @@ -18,6 +19,9 @@ class Issue3383 extends Test { eq(span, null); eq(ui, cast null); eq(n, null); + #else + Sys.stderr().writeString("https://github.com/HaxeFoundation/haxe/issues/5503 pending\n"); + #end } #end } diff --git a/tests/unit/src/unit/issues/Issue3387.hx b/tests/unit/src/unit/issues/Issue3387.hx index 62280a54..7d57a4c7 100644 --- a/tests/unit/src/unit/issues/Issue3387.hx +++ b/tests/unit/src/unit/issues/Issue3387.hx @@ -1,12 +1,12 @@ package unit.issues; class Issue3387 extends unit.Test { - function test() { - eq("#pos(some:1: lines 1-4)", getPos("{\n1;\n2;\n3;}", "some")); - } + function test() { + eq("#pos(some:1: lines 1-4)", getPos("{\n1;\n2;\n3;}", "some")); + } - static macro function getPos(source:String, file:String) { - var e = haxe.macro.Context.parseInlineString(source, haxe.macro.Context.makePosition({min: 0, max: 0, file: file})); - return macro $v{Std.string(e.pos)}; - } + static macro function getPos(source:String, file:String) { + var e = haxe.macro.Context.parseInlineString(source, haxe.macro.Context.makePosition({min: 0, max: 0, file: file})); + return macro $v{Std.string(e.pos)}; + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3388.hx b/tests/unit/src/unit/issues/Issue3388.hx index f26d10b6..a343dc88 100644 --- a/tests/unit/src/unit/issues/Issue3388.hx +++ b/tests/unit/src/unit/issues/Issue3388.hx @@ -1,22 +1,22 @@ package unit.issues; private abstract A(Array) { - public inline function new(a:Array) { - this = a; - } + public inline function new(a:Array) { + this = a; + } #if java @:impl - @:overload @:extern + @:overload @:extern static inline public function sum(a:Array) { - return "sum of ints"; - } + return "sum of ints"; + } - @:overload @:extern + @:overload @:extern @:impl static inline public function sum(a:Array) { - return "sum of strings"; - } + return "sum of strings"; + } #end } diff --git a/tests/unit/src/unit/issues/Issue3390.hx b/tests/unit/src/unit/issues/Issue3390.hx index 1da2d07e..9155a192 100644 --- a/tests/unit/src/unit/issues/Issue3390.hx +++ b/tests/unit/src/unit/issues/Issue3390.hx @@ -1,19 +1,19 @@ package unit.issues; private class A { - static function a() Issue3390.privMethod(); + static function a() Issue3390.privMethod(); } private class B { - static function b() Issue3390.privMethod(); + static function b() Issue3390.privMethod(); } @:access(unit.issues.A, unit.issues.B) @:allow(unit.issues.A, unit.issues.B) class Issue3390 extends Test { - static function privMethod() {} - function test() { - A.a(); - B.b(); - } + static function privMethod() {} + function test() { + A.a(); + B.b(); + } } diff --git a/tests/unit/src/unit/issues/Issue3391.hx b/tests/unit/src/unit/issues/Issue3391.hx index 00fbdbbe..30d839c4 100644 --- a/tests/unit/src/unit/issues/Issue3391.hx +++ b/tests/unit/src/unit/issues/Issue3391.hx @@ -2,8 +2,8 @@ package unit.issues; class Issue3391 extends Test { function test() { - var v = false; - t(unit.TestType.typeError( + var v = false; + t(unit.HelperMacros.typeError( var a:Int = switch (v) { case true: case false: diff --git a/tests/unit/src/unit/issues/Issue3396.hx b/tests/unit/src/unit/issues/Issue3396.hx index bff8d60c..847ed8ef 100644 --- a/tests/unit/src/unit/issues/Issue3396.hx +++ b/tests/unit/src/unit/issues/Issue3396.hx @@ -2,13 +2,13 @@ package unit.issues; class Issue3396 extends Test { function test() { - var r = null; - var f = function(arr:Array) return r; + var r = null; + var f = function(arr:Array) return r; var f2 = function(arr:Array):Void {} - Reflect.makeVarArgs(f); - Reflect.makeVarArgs(f2); + Reflect.makeVarArgs(f); + Reflect.makeVarArgs(f2); var s:String = f([]); - unit.TestType.typedAs(r, (r:String)); - unit.TestType.typedAs(f2([]), (null:Void)); + unit.HelperMacros.typedAs(r, (r:String)); + unit.HelperMacros.typedAs(f2([]), (null:Void)); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3400.hx b/tests/unit/src/unit/issues/Issue3400.hx index 8702d6ce..08248834 100644 --- a/tests/unit/src/unit/issues/Issue3400.hx +++ b/tests/unit/src/unit/issues/Issue3400.hx @@ -13,11 +13,11 @@ class Issue3400 extends Test #if java private abstract AbstractList(java.util.ArrayList) { - function new(a:T) - { - this = new java.util.ArrayList(); - this.add(a); - } - public static inline function empty() return new AbstractList((cast null:T)); + function new(a:T) + { + this = new java.util.ArrayList(); + this.add(a); + } + public static inline function empty() return new AbstractList((cast null:T)); } #end diff --git a/tests/unit/src/unit/issues/Issue3431.hx b/tests/unit/src/unit/issues/Issue3431.hx index 2488968f..ab2c983d 100644 --- a/tests/unit/src/unit/issues/Issue3431.hx +++ b/tests/unit/src/unit/issues/Issue3431.hx @@ -1,16 +1,16 @@ package unit.issues; private typedef A = { - ?f:Array, + ?f:Array, } class Issue3431 extends Test { function test() { - var v:A = {}; - var r = switch (v) { - case {f: [a,b]}: 1; - default: 2; - } + var v:A = {}; + var r = switch (v) { + case {f: [a,b]}: 1; + default: 2; + } eq(2, r); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3440.hx b/tests/unit/src/unit/issues/Issue3440.hx index 6a557903..fc666ccf 100644 --- a/tests/unit/src/unit/issues/Issue3440.hx +++ b/tests/unit/src/unit/issues/Issue3440.hx @@ -1,6 +1,5 @@ package unit.issues; -@:analyzer(no_check_has_effect) class Issue3440 extends Test { function test() { var a = "foo"; diff --git a/tests/unit/src/unit/issues/Issue3448.hx b/tests/unit/src/unit/issues/Issue3448.hx index 29712d7b..eda294e6 100644 --- a/tests/unit/src/unit/issues/Issue3448.hx +++ b/tests/unit/src/unit/issues/Issue3448.hx @@ -5,9 +5,9 @@ class Issue3448 extends Test { t(f1() != null); } - static function f1(?pos) { - return f2(pos); - } + static function f1(?pos) { + return f2(pos); + } static function f2(?p:haxe.PosInfos) { return p; diff --git a/tests/unit/src/unit/issues/Issue3450.hx b/tests/unit/src/unit/issues/Issue3450.hx new file mode 100644 index 00000000..f032cc54 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3450.hx @@ -0,0 +1,16 @@ +package unit.issues; + +@:generic class X<@:const T, @:const S> { + public function new() { } + + public function getString() { + return T + " " + S; + } +} + +class Issue3450 extends Test { + function test() { + var c = new X<'foo', 12>(); + eq("foo 12", c.getString()); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3460.hx b/tests/unit/src/unit/issues/Issue3460.hx new file mode 100644 index 00000000..89e26efc --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3460.hx @@ -0,0 +1,13 @@ +package unit.issues; + +private class MyClass { + @:overload(function (x:Int):String {}) + @:overload(function (x:String, y:Bool):Int {}) + function test() { } +} + +class Issue3460 extends Test { + function test() { + eq("x : Int -> String, x : String -> y : Bool -> Int", unit.issues.misc.Issue3460Macro.getOverloadString((null : MyClass))); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3461.hx b/tests/unit/src/unit/issues/Issue3461.hx index a230afaf..d3690bff 100644 --- a/tests/unit/src/unit/issues/Issue3461.hx +++ b/tests/unit/src/unit/issues/Issue3461.hx @@ -4,8 +4,8 @@ private abstract E(Dynamic) from T1 to T1 {} class Issue3461 extends Test { function test() { - var a:E> = { value: "foo" }; - var b:Dynamic = a; + var a:E> = { value: "foo" }; + var b:Dynamic = a; a = b; eq("foo", b.value); } diff --git a/tests/unit/src/unit/issues/Issue3480.hx b/tests/unit/src/unit/issues/Issue3480.hx index 5123a66d..32d675ab 100644 --- a/tests/unit/src/unit/issues/Issue3480.hx +++ b/tests/unit/src/unit/issues/Issue3480.hx @@ -1,10 +1,10 @@ package unit.issues; class Issue3480 extends Test { - function test() { - #if js - if (!js.Browser.supported || js.Browser.navigator.userAgent.indexOf('MSIE 8') == -1) // IE8 doesn't like toString fields at all - eq("{\n\ttoString : 1\n}", Std.string({toString: 1})); - #end - } + function test() { + #if js + if (!js.Browser.supported || js.Browser.navigator.userAgent.indexOf('MSIE 8') == -1) // IE8 doesn't like toString fields at all + eq("{\n\ttoString : 1\n}", Std.string({toString: 1})); + #end + } } diff --git a/tests/unit/src/unit/issues/Issue3486.hx b/tests/unit/src/unit/issues/Issue3486.hx index 081699ec..7a9ebe54 100644 --- a/tests/unit/src/unit/issues/Issue3486.hx +++ b/tests/unit/src/unit/issues/Issue3486.hx @@ -2,11 +2,11 @@ package unit.issues; class Issue3486 extends Test { function test() { - var l = new List(); - flatMap(l); + var l = new List(); + flatMap(l); } - static public function flatMap(a:List) { - for (x in a) {} - } + static public function flatMap(a:List) { + for (x in a) {} + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3494.hx b/tests/unit/src/unit/issues/Issue3494.hx index 8240f049..fed9fb98 100644 --- a/tests/unit/src/unit/issues/Issue3494.hx +++ b/tests/unit/src/unit/issues/Issue3494.hx @@ -9,32 +9,32 @@ private abstract E3(Dynamic) from T1 from T2 to T1 to T2 { - @:from inline static public function _from2, _T2:E3>(e:E3<_T1,_T2>):E3 { - return untyped e; - } + @:from inline static public function _from2, _T2:E3>(e:E3<_T1,_T2>):E3 { + return untyped e; + } } class Issue3494 extends Test { function test() { - var v1:E2 = 1; - var v2:E2 = 2; - v1 = v2; + var v1:E2 = 1; + var v2:E2 = 2; + v1 = v2; eq(2, v1); eq(2, v2); } function test2() { - var v1:E3 = 1; - var v2:E3 = 2; - v1 = v2; + var v1:E3 = 1; + var v2:E3 = 2; + v1 = v2; eq(2, v1); eq(2, v2); } function test3() { - var v1:E3 = 1; - var v2:E3 = 2; - v1 = E3._from2(v2); + var v1:E3 = 1; + var v2:E3 = 2; + v1 = E3._from2(v2); eq(2, v1); eq(2, v2); } diff --git a/tests/unit/src/unit/issues/Issue3499.hx b/tests/unit/src/unit/issues/Issue3499.hx new file mode 100644 index 00000000..90e7e9a1 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3499.hx @@ -0,0 +1,17 @@ +package unit.issues; + +#if js + +private typedef PathSimple = haxe.extern.EitherType; +private typedef Path = haxe.extern.EitherType>; + +#end + +class Issue3499 extends Test { + #if js + function test() { + var a:Path = ["", new js.RegExp("")]; + eq("", a[0]); + } + #end +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3504.hx b/tests/unit/src/unit/issues/Issue3504.hx index f9de4705..3cb9f6b6 100644 --- a/tests/unit/src/unit/issues/Issue3504.hx +++ b/tests/unit/src/unit/issues/Issue3504.hx @@ -12,9 +12,9 @@ private class B extends A { } private class C extends A { - public function new(a:Null = false) { - super(a ? 1 : 0); - } + public function new(a:Null = false) { + super(a ? 1 : 0); + } } class Issue3504 extends Test { diff --git a/tests/unit/src/unit/issues/Issue3507.hx b/tests/unit/src/unit/issues/Issue3507.hx index 519a988e..a363edea 100644 --- a/tests/unit/src/unit/issues/Issue3507.hx +++ b/tests/unit/src/unit/issues/Issue3507.hx @@ -26,10 +26,19 @@ private class C extends B { class Issue3507 extends Test { function test() { var c = new C("foo", 12, false); - var s = switch (c) { + var c2 = new C("foo", 12, true); + var c3 = new C("foo", 13, false); + var c4 = new C("bar", 12, false); + eq("ok", match(c)); + eq("not ok", match(c2)); + eq("not ok", match(c3)); + eq("not ok", match(c4)); + } + + function match(c:C) { + return switch (c) { case { t1:'foo', t2:12, t3:false } : "ok"; case _: "not ok"; } - eq("ok", s); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3512.hx b/tests/unit/src/unit/issues/Issue3512.hx index 710f9572..f316e635 100644 --- a/tests/unit/src/unit/issues/Issue3512.hx +++ b/tests/unit/src/unit/issues/Issue3512.hx @@ -5,19 +5,19 @@ class Issue3512 extends Test { { arr = getArr(); eq(arr[0], 1); - t(Std.is(arr[0],Int)); + t((arr[0] is Int)); var arr2:Array = getArr(); eq(arr2[0], 1); - t(Std.is(arr2[0], Int)); + t((arr2[0] is Int)); arr2 = getArr(); eq(arr2[0], 1); - t(Std.is(arr2[0], Int)); + t((arr2[0] is Int)); var arr3:Array = getArr(); eq(arr3[0], 1); - t(Std.is(arr3[0], Float)); + t((arr3[0] is Float)); arr3 = getArr(); eq(arr3[0], 1); - t(Std.is(arr3[0], Float)); + t((arr3[0] is Float)); } static var arr:Array; diff --git a/tests/unit/src/unit/issues/Issue3513.hx b/tests/unit/src/unit/issues/Issue3513.hx index dcb3fcd9..792eb63a 100644 --- a/tests/unit/src/unit/issues/Issue3513.hx +++ b/tests/unit/src/unit/issues/Issue3513.hx @@ -1,8 +1,8 @@ package unit.issues; private enum Either { - Left(l:L); - Right(r:R); + Left(l:L); + Right(r:R); } private abstract LazyGenerator(Void->Either) from Void->Either { @@ -15,10 +15,10 @@ private abstract LazyGenerator(Void->Either) from Void->Ei class Issue3513 extends Test { function test() { - var count = 0; - function counter() return count++; - var gen:LazyGenerator = counter; - var gen:LazyGenerator = function ():Int return count++; + var count = 0; + function counter() return count++; + var gen:LazyGenerator = counter; + var gen:LazyGenerator = function ():Int return count++; eq(0, getValue(gen.next())); eq(1, getValue(gen.next())); } diff --git a/tests/unit/src/unit/issues/Issue3516.hx b/tests/unit/src/unit/issues/Issue3516.hx index 528b7cf4..efc9a640 100644 --- a/tests/unit/src/unit/issues/Issue3516.hx +++ b/tests/unit/src/unit/issues/Issue3516.hx @@ -6,16 +6,16 @@ class Issue3516 extends Test { var b = new B(); var c = b.uniqueFieldName(C); - t(Std.is(c, C)); + t((c is C)); t(c != null); } } private class A { - public function new() {} - public function uniqueFieldName(c:Class):T { - return Type.createInstance(c, []); - } + public function new() {} + public function uniqueFieldName(c:Class):T { + return Type.createInstance(c, []); + } } private class B extends A {} @@ -23,6 +23,6 @@ private class B extends A {} private class C { @:keep public function new() {} } class TestMain { - static function main() { - } + static function main() { + } } diff --git a/tests/unit/src/unit/issues/Issue3528.hx b/tests/unit/src/unit/issues/Issue3528.hx new file mode 100644 index 00000000..014273c0 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3528.hx @@ -0,0 +1,23 @@ +package unit.issues; + +private abstract Optional(haxe.ds.Option) from haxe.ds.Option {} + +class Issue3528 extends Test { + function test() { + var x = test1(Some(4)); + + test2(Some(4)); + switch test2(x) { + case Some(v): + case None: + } + } + + static function test1(v:haxe.ds.Option) { + return v; + } + + static function test2(v:Optional) { + return v; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3535.hx b/tests/unit/src/unit/issues/Issue3535.hx new file mode 100644 index 00000000..73e5e445 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3535.hx @@ -0,0 +1,55 @@ +package unit.issues; + +@:generic +private class IndexedItemIterator +{ + var items:Array; + var i:Int = 0; + + public inline function new(items:Array) + { + this.items = items; + } + + public inline function hasNext() + { + return i < items.length; + } + + public inline function next() + { + return new IndexedItemObject(i, items[i++]); + } +} + +@:generic +private class IndexedItemObject +{ + public var index:Int; + public var item:T; + + public inline function new(index:Int, item:T) + { + this.index = index; + this.item = item; + } +} + +class Issue3535 extends Test { + function test() { + var list = ["111","222","333"]; + var buf = new StringBuf(); + for(value in new IndexedItemIterator(list)) { + buf.add(value.index + ":" + value.item); + } + + eq("0:1111:2222:333", buf.toString()); + + var list2 = [3,4,5,7]; + var buf = new StringBuf(); + for(value in new IndexedItemIterator(list2)) { + buf.add(value.index + ":" + value.item); + } + eq("0:31:42:53:7", buf.toString()); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3543.hx b/tests/unit/src/unit/issues/Issue3543.hx index 573698e6..81a431a3 100644 --- a/tests/unit/src/unit/issues/Issue3543.hx +++ b/tests/unit/src/unit/issues/Issue3543.hx @@ -1,8 +1,8 @@ package unit.issues; class Issue3543 extends Test { - function test() { - var a = Std.int((3 : UInt) / 2); - eq(1, a); - } + function test() { + var a = Std.int((3 : UInt) / 2); + eq(1, a); + } } diff --git a/tests/unit/src/unit/issues/Issue3554.hx b/tests/unit/src/unit/issues/Issue3554.hx index 4cec49f7..49bc8966 100644 --- a/tests/unit/src/unit/issues/Issue3554.hx +++ b/tests/unit/src/unit/issues/Issue3554.hx @@ -2,14 +2,14 @@ package unit.issues; private abstract A(Int) { - public static var a(get,never):Int; - private static function get_a() - return(1 << x); + public static var a(get,never):Int; + private static function get_a() + return(1 << x); - public static var x(get,never):Int; - static var _x:Int = 4; - inline static function get_x() - return _x; + public static var x(get,never):Int; + static var _x:Int = 4; + inline static function get_x() + return _x; } diff --git a/tests/unit/src/unit/issues/Issue3557.hx b/tests/unit/src/unit/issues/Issue3557.hx index c612541c..0933dfbc 100644 --- a/tests/unit/src/unit/issues/Issue3557.hx +++ b/tests/unit/src/unit/issues/Issue3557.hx @@ -13,7 +13,7 @@ private class MyClass extends Generic { private interface Interface {} @:generic -private class Generic +private class GenericVoid>> extends Default implements Interface {} diff --git a/tests/unit/src/unit/issues/Issue3560.hx b/tests/unit/src/unit/issues/Issue3560.hx new file mode 100644 index 00000000..fe20bd2b --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3560.hx @@ -0,0 +1,15 @@ +package unit.issues; + +import String; +import haxe.Template as T; +import haxe.macro.*; + +class Issue3560 extends Test { + function test() { + var s = unit.issues.misc.Issue3560Macro.getImportString(); + // the order isn't really defined, but whatever + eq("IAll:haxe.macro", s[0]); + eq("IAsName(T):haxe.Template", s[1]); + eq("INormal:String", s[2]); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3563.hx b/tests/unit/src/unit/issues/Issue3563.hx new file mode 100644 index 00000000..59554e28 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3563.hx @@ -0,0 +1,23 @@ +package unit.issues; + +private class FinalTest { + public static var hello = "Hello"; + public static var someValue = getSomeValue(); + public static var someValue2 = getSomeValue2(); + + static public function getSomeValue() { + return hello; + } + + static public function getSomeValue2() { + return someValue; + } +} + +class Issue3563 extends Test { + function test() { + eq("Hello", FinalTest.someValue); + eq("Hello", FinalTest.getSomeValue()); + eq("Hello", FinalTest.getSomeValue2()); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3577.hx b/tests/unit/src/unit/issues/Issue3577.hx index 0e57514d..58bea8bc 100644 --- a/tests/unit/src/unit/issues/Issue3577.hx +++ b/tests/unit/src/unit/issues/Issue3577.hx @@ -1,16 +1,16 @@ package unit.issues; class Issue3577 extends Test { - function test() { - eq(testNull(2), 4); - } + function test() { + eq(testNull(2), 4); + } - function testNull(?x:Int=0) : Int { - var y:Int = x; - function anon() { - y *= 2; - } - anon(); - return y; - } + function testNull(?x:Int=0) : Int { + var y:Int = x; + function anon() { + y *= 2; + } + anon(); + return y; + } } diff --git a/tests/unit/src/unit/issues/Issue3585.hx b/tests/unit/src/unit/issues/Issue3585.hx index 223f11cf..a4304d5f 100644 --- a/tests/unit/src/unit/issues/Issue3585.hx +++ b/tests/unit/src/unit/issues/Issue3585.hx @@ -2,20 +2,20 @@ package unit.issues; import unit.Test; class Issue3585 extends Test { - #if (flash || java || cs || cpp) // this is only relevant on static platforms - function test() { - var v = inlineUnwrap(); - eq(getType(v), "Int"); - } + #if (flash || java || cs || cpp) // this is only relevant on static platforms + function test() { + var v = inlineUnwrap(); + eq(getType(v), "Int"); + } - inline function inlineUnwrap():Int { - var tmp:Null = 1; - return tmp; - } - #end + inline function inlineUnwrap():Int { + var tmp:Null = 1; + return tmp; + } + #end - static macro function getType(v:haxe.macro.Expr) { - var t = haxe.macro.Context.typeof(v); - return macro $v{haxe.macro.TypeTools.toString(t)}; - } + static macro function getType(v:haxe.macro.Expr) { + var t = haxe.macro.Context.typeof(v); + return macro $v{haxe.macro.TypeTools.toString(t)}; + } } diff --git a/tests/unit/src/unit/issues/Issue3586.hx b/tests/unit/src/unit/issues/Issue3586.hx index 612ca7e8..b168d4ae 100644 --- a/tests/unit/src/unit/issues/Issue3586.hx +++ b/tests/unit/src/unit/issues/Issue3586.hx @@ -1,16 +1,16 @@ package unit.issues; private class C { - public var f:Array; - public inline function new(v) f = [v]; + public var f:Array; + public inline function new(v) f = [v]; } @:forward(f) private abstract A(C) from C {} class Issue3586 extends unit.Test { - function test() { - var a:A = new C(15); - eq(a.f[0], 15); - } + function test() { + var a:A = new C(15); + eq(a.f[0], 15); + } } diff --git a/tests/unit/src/unit/issues/Issue3588.hx b/tests/unit/src/unit/issues/Issue3588.hx index dedaf4b9..e4cb593c 100644 --- a/tests/unit/src/unit/issues/Issue3588.hx +++ b/tests/unit/src/unit/issues/Issue3588.hx @@ -1,16 +1,16 @@ package unit.issues; private class Foo { - public var fooField:T; + public var fooField:T; - public function new(fooField:T) { - this.fooField = fooField; - } + public function new(fooField:T) { + this.fooField = fooField; + } } class Issue3588 extends Test { function test() { - var foo = new Foo>(null); - eq(null, foo.fooField); + var foo = new Foo>(null); + eq(null, foo.fooField); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3592.hx b/tests/unit/src/unit/issues/Issue3592.hx index 4bc239dd..343711ad 100644 --- a/tests/unit/src/unit/issues/Issue3592.hx +++ b/tests/unit/src/unit/issues/Issue3592.hx @@ -1,36 +1,36 @@ package unit.issues; private class A { - public function new() {} - @:generic - public function foo(x : T) { - return 'A ${x}'; - } + public function new() {} + @:generic + public function foo(x : T) { + return 'A ${x}'; + } - @:generic + @:generic @:extern // easy way of testing if things inline - public inline function inlineFoo(x : T) { - return 'inline A ${x}'; - } + public inline function inlineFoo(x : T) { + return 'inline A ${x}'; + } } private class B extends A { - public function new() { - super(); - } + public function new() { + super(); + } - @:generic - override public function foo(x : T) { - return 'B ${x}'; - } + @:generic + override public function foo(x : T) { + return 'B ${x}'; + } } class Issue3592 extends Test { function test() { - var a = new A(); - var b = new B(); - eq("A foo", a.foo("foo")); - eq("B foo", b.foo("foo")); + var a = new A(); + var b = new B(); + eq("A foo", a.foo("foo")); + eq("B foo", b.foo("foo")); eq("inline A foo", a.inlineFoo("foo")); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3596.hx b/tests/unit/src/unit/issues/Issue3596.hx index 74a9eb14..9439fedc 100644 --- a/tests/unit/src/unit/issues/Issue3596.hx +++ b/tests/unit/src/unit/issues/Issue3596.hx @@ -47,8 +47,8 @@ private class ClassWithConstructorThatCallsChild extends ClassWithConstructorTha class Issue3596 extends Test { function test() { - t(unit.TestType.typeError(new ClassWithInitButNoConstructor())); - t(unit.TestType.typeError(new ClassWithInitButNoConstructorChild())); + t(unit.HelperMacros.typeError(new ClassWithInitButNoConstructor())); + t(unit.HelperMacros.typeError(new ClassWithInitButNoConstructorChild())); //var c = new ClassWithInitAndConstructorChild(); //eq(1, c.a); diff --git a/tests/unit/src/unit/issues/Issue3615.hx b/tests/unit/src/unit/issues/Issue3615.hx index 5de70c5a..439ef16a 100644 --- a/tests/unit/src/unit/issues/Issue3615.hx +++ b/tests/unit/src/unit/issues/Issue3615.hx @@ -3,20 +3,20 @@ package unit.issues; @:generic private class BaseClass { - public function new() - { - haxe.Log; - } + public function new() + { + haxe.Log; + } } private class SubClassOne extends BaseClass { - public function new() { super(); haxe.Log; } + public function new() { super(); haxe.Log; } } private class SubClassTwo extends BaseClass { - public function new() { super(); haxe.Log; } + public function new() { super(); haxe.Log; } } class Issue3615 extends Test { diff --git a/tests/unit/src/unit/issues/Issue3616.hx b/tests/unit/src/unit/issues/Issue3616.hx index c791a140..5dbb46bc 100644 --- a/tests/unit/src/unit/issues/Issue3616.hx +++ b/tests/unit/src/unit/issues/Issue3616.hx @@ -1,30 +1,30 @@ package unit.issues; private abstract A(Null) { - public static function f(v:Int):Void {} - public static function z():Void {} + public static function f(v:Int):Void {} + public static function z():Void {} } private abstract B(T) { - public static function f(v:T):B return cast v; + public static function f(v:T):B return cast v; } private abstract C(Null) { - public static var f(get,set):Int; - static function get_f() return 1; - static function set_f(value) return 1; + public static var f(get,set):Int; + static function get_f() return 1; + static function set_f(value) return 1; } class Issue3616 extends Test { function test() { - var v:A = null; - eq(unit.TestType.typeErrorText(v.f(1)), "Invalid call to static function f through abstract instance"); + var v:A = null; + eq(unit.HelperMacros.typeErrorText(v.f(1)), "Invalid call to static function f through abstract instance"); var v = B.f(10); - eq(unit.TestType.typeErrorText(v.f()), "Invalid call to static function f through abstract instance"); + eq(unit.HelperMacros.typeErrorText(v.f()), "Invalid call to static function f through abstract instance"); - var v:C = null; - eq(unit.TestType.typeErrorText(v.f), "Invalid call to static function f through abstract instance"); - eq(unit.TestType.typeErrorText(v.f = 5), "Invalid call to static function f through abstract instance"); + var v:C = null; + eq(unit.HelperMacros.typeErrorText(v.f), "Invalid call to static function f through abstract instance"); + eq(unit.HelperMacros.typeErrorText(v.f = 5), "Invalid call to static function f through abstract instance"); } } diff --git a/tests/unit/src/unit/issues/Issue3635.hx b/tests/unit/src/unit/issues/Issue3635.hx index 568b747c..3b43a748 100644 --- a/tests/unit/src/unit/issues/Issue3635.hx +++ b/tests/unit/src/unit/issues/Issue3635.hx @@ -17,7 +17,7 @@ class Issue3635 extends Test { dB.key = { x: 10 }; dB = { key: b }; - t(unit.TestType.typeError(dA = { key: { y: 120 } })); - t(unit.TestType.typeError(dB = { key: { y: 120 } })); + t(unit.HelperMacros.typeError(dA = { key: { y: 120 } })); + t(unit.HelperMacros.typeError(dB = { key: { y: 120 } })); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3639.hx b/tests/unit/src/unit/issues/Issue3639.hx index 2a612bfc..0b1fe56b 100644 --- a/tests/unit/src/unit/issues/Issue3639.hx +++ b/tests/unit/src/unit/issues/Issue3639.hx @@ -25,6 +25,7 @@ private class MyClass { } class Issue3639 extends Test { + @:analyzer(no_local_dce) function test() { MyClass.testStatic(1); MyClass.eachStatic(0...5, function(x) return x); diff --git a/tests/unit/src/unit/issues/Issue3680.hx b/tests/unit/src/unit/issues/Issue3680.hx index 452a063c..0fdcaee6 100644 --- a/tests/unit/src/unit/issues/Issue3680.hx +++ b/tests/unit/src/unit/issues/Issue3680.hx @@ -1,24 +1,24 @@ package unit.issues; private class Node { - public var cur:T; - public var next:Null>; - public function new(cur) - { - this.cur = cur; - } + public var cur:T; + public var next:Null>; + public function new(cur) + { + this.cur = cur; + } } class Issue3680 extends Test { function test() { var a = ""; - switch (new Node(1)) - { - case { cur: 1, next: ({ cur : 2 }) }: - a = "assert"; - default: - a = 'correct'; - } + switch (new Node(1)) + { + case { cur: 1, next: ({ cur : 2 }) }: + a = "assert"; + default: + a = 'correct'; + } eq("correct", a); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3681.hx b/tests/unit/src/unit/issues/Issue3681.hx index 70909360..aff31ba5 100644 --- a/tests/unit/src/unit/issues/Issue3681.hx +++ b/tests/unit/src/unit/issues/Issue3681.hx @@ -2,26 +2,26 @@ package unit.issues; private class Node { - public var cur:T; - public var next:Null>; - public function new(cur,?next) - { - this.cur = cur; - this.next = next; - } + public var cur:T; + public var next:Null>; + public function new(cur,?next) + { + this.cur = cur; + this.next = next; + } } class Issue3681 extends Test { function test() { - var i:Null = null; - var nodes = new Node(i,new Node(1,new Node(2, new Node(i)))); - var matches = switch (nodes) - { - case { cur : null, next : ({ cur : 1, next : _ }) }: - true; - case _: - false; - } - t(matches); + var i:Null = null; + var nodes = new Node(i,new Node(1,new Node(2, new Node(i)))); + var matches = switch (nodes) + { + case { cur : null, next : ({ cur : 1, next : _ }) }: + true; + case _: + false; + } + t(matches); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3702.hx b/tests/unit/src/unit/issues/Issue3702.hx new file mode 100644 index 00000000..71009368 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3702.hx @@ -0,0 +1,32 @@ +package unit.issues; + +class Issue3702 extends Test { + + static var state = 0; + + function test() { + var m = ["hello" => 0]; + eq(state, 0); + var x = m[getKey()]++; + eq(0, x); + eq(1, state); + eq(1, m["hello"]); + var x = ++m[getKey()]; + eq(2, x); + eq(2, state); + eq(2, m["hello"]); + var x = m[getKey()]--; + eq(2, x); + eq(3, state); + eq(1, m["hello"]); + var x = --m[getKey()]; + eq(0, x); + eq(4, state); + eq(0, m["hello"]); + } + + static function getKey() { + ++state; + return "hello"; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3711.hx b/tests/unit/src/unit/issues/Issue3711.hx index f280e731..32162075 100644 --- a/tests/unit/src/unit/issues/Issue3711.hx +++ b/tests/unit/src/unit/issues/Issue3711.hx @@ -1,15 +1,15 @@ package unit.issues; private abstract A(haxe.DynamicAccess) { - public function f():Array return []; + public function f():Array return []; } class Issue3711 extends Test { - public function test() + public function test() { var a:A = null; var k = a.f(); eq(k[0],null); eq(k.length,0); - } + } } diff --git a/tests/unit/src/unit/issues/Issue3713.hx b/tests/unit/src/unit/issues/Issue3713.hx index 74e35eec..d67b7cae 100644 --- a/tests/unit/src/unit/issues/Issue3713.hx +++ b/tests/unit/src/unit/issues/Issue3713.hx @@ -1,21 +1,21 @@ package unit.issues; private class A { - public function new() {} + public function new() {} } private abstract B(A) { - public inline function new() this = new A(); - public inline function f():C return new C(this); + public inline function new() this = new A(); + public inline function f():C return new C(this); } private class C { - public inline function new(d:A) {} + public inline function new(d:A) {} } class Issue3713 extends Test { function test() { - var b = new B(); - var c = b.f(); + var b = new B(); + var c = b.f(); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3714.hx b/tests/unit/src/unit/issues/Issue3714.hx index b896b843..bc6a47a9 100644 --- a/tests/unit/src/unit/issues/Issue3714.hx +++ b/tests/unit/src/unit/issues/Issue3714.hx @@ -1,15 +1,15 @@ package unit.issues; private class A { - static var a:Int; - static function f(a:Int) {} + static var a:Int; + static function f(a:Int) {} } class Issue3714 extends Test { - function test() { - eq(unit.TestType.typeErrorText(A.f), "Cannot access private field f"); - eq(unit.TestType.typeErrorText(@:privateAccess A.f), null); - eq(unit.TestType.typeErrorText(@:privateAccess A.f(A.a)), null); - eq(unit.TestType.typeErrorText(@:privateAccess A.f(@:noPrivateAccess A.a)), "Cannot access private field a"); - } + function test() { + eq(unit.HelperMacros.typeErrorText(A.f), "Cannot access private field f"); + eq(unit.HelperMacros.typeErrorText(@:privateAccess A.f), null); + eq(unit.HelperMacros.typeErrorText(@:privateAccess A.f(A.a)), null); + eq(unit.HelperMacros.typeErrorText(@:privateAccess A.f(@:noPrivateAccess A.a)), "Cannot access private field a\nFor function argument 'a'"); + } } diff --git a/tests/unit/src/unit/issues/Issue3717.hx b/tests/unit/src/unit/issues/Issue3717.hx index 1e4b1578..bdcda530 100644 --- a/tests/unit/src/unit/issues/Issue3717.hx +++ b/tests/unit/src/unit/issues/Issue3717.hx @@ -25,20 +25,20 @@ class Issue3717 extends unit.Test { @:forward private abstract Metric (MetricCore) from MetricCore to MetricCore { - @:from static function fromFloat(v:Float) { - var m = new MetricCore(); - m.dip = v; - return m; - } - @:to function toFloat() return this.dip; + @:from static function fromFloat(v:Float) { + var m = new MetricCore(); + m.dip = v; + return m; + } + @:to function toFloat() return this.dip; - @:op(A += B) static function AincBf (a:Metric, b:Float) return a.dip += b; + @:op(A += B) static function AincBf (a:Metric, b:Float) return a.dip += b; } private class MetricCore { - public var dip : Float = 0; + public var dip : Float = 0; - public function new () : Void {} + public function new () : Void {} } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3732.hx b/tests/unit/src/unit/issues/Issue3732.hx index 56eefafe..c9ea05a6 100644 --- a/tests/unit/src/unit/issues/Issue3732.hx +++ b/tests/unit/src/unit/issues/Issue3732.hx @@ -3,7 +3,7 @@ package unit.issues; class Issue3732 extends Test { function test() { var a; - var b = a = try 1 catch (_:Dynamic) 2; + var b = a = try 1 catch (_:Dynamic) 2; eq(1, a); eq(1, b); } diff --git a/tests/unit/src/unit/issues/Issue3753.hx b/tests/unit/src/unit/issues/Issue3753.hx index b7c6ac98..ae50c0b2 100644 --- a/tests/unit/src/unit/issues/Issue3753.hx +++ b/tests/unit/src/unit/issues/Issue3753.hx @@ -9,7 +9,7 @@ private abstract A(Map) from Map { private abstract B(Map) from Map { @:resolve - static function resolve(lhs:B, name:String) { + static function resolve2(lhs:B, name:String) { return lhs.get()[name]; } @@ -29,7 +29,7 @@ private abstract C(Map) from Map { } private abstract D(Map) from Map { - @:resolve + @:op(a.b) macro static function resolve(ethis:haxe.macro.Expr, name:String) { var s = switch (name) { case "foo": "bar"; @@ -42,20 +42,20 @@ private abstract D(Map) from Map { class Issue3753 extends Test { function test() { - //var a:A = ["foo" => "bar", "bar" => "baz"]; - //eq("bar", a.foo); - //eq("baz", a.bar); -// - //var a:B = ["foo" => "bar", "bar" => "baz"]; - //eq("bar", a.foo); - //eq("baz", a.bar); -// - //var a:C = ["foo" => "bar", "bar" => "baz"]; - //eq("bar", a.foo); - //eq("baz", a.bar); -// - //var a:D = ["foo" => "bar", "bar" => "baz"]; - //eq("bar", a.foo); - //eq("baz", a.bar); + var a:A = ["foo" => "bar", "bar" => "baz"]; + eq("bar", a.foo); + eq("baz", a.bar); + + var a:B = ["foo" => "bar", "bar" => "baz"]; + eq("bar", a.foo); + eq("baz", a.bar); + + var a:C = ["foo" => "bar", "bar" => "baz"]; + eq("bar", a.foo); + eq("baz", a.bar); + + var a:D = ["foo" => "bar", "bar" => "baz"]; + eq("bar", a.foo); + eq("baz", a.bar); } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3762.hx b/tests/unit/src/unit/issues/Issue3762.hx new file mode 100644 index 00000000..ca3c9d38 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3762.hx @@ -0,0 +1,30 @@ +package unit.issues; +import unit.Test; +import haxe.ds.IntMap; + +class Issue3762 extends Test +{ + function test() + { + // test fast iterators against normal keys + var d = new IntMap(); + var keys = [1, 2, 3]; + for (i in 0...keys.length) { + var k = keys[i]; + d.set(k, i); + } + var keyCount:Int = 0; + for (k in d.keys()) { + f( keys.indexOf(k) == -1 ); // key missing from keys iterator + keyCount++; + } + f( keyCount != keys.length ); // keys missing + var keyCount:Int = 0; + for (v in d) { + f(v < 0 || v >= keys.length); // bad value iterated + keyCount++; + } + f(keyCount != keys.length); // values missing + + } +} diff --git a/tests/unit/src/unit/issues/Issue3777.hx b/tests/unit/src/unit/issues/Issue3777.hx index 1cc9a011..98cd47d4 100644 --- a/tests/unit/src/unit/issues/Issue3777.hx +++ b/tests/unit/src/unit/issues/Issue3777.hx @@ -1,17 +1,17 @@ package unit.issues; private class A { - public function new() f(); - function f():Map throw "not implemented"; + public function new() f(); + function f():Map throw "not implemented"; } private class B extends A { - override function f() return ["a" => 1]; + override function f() return ["a" => 1]; } class Issue3777 extends unit.Test { - function test() { - // if it compiles, it works - new B(); - } + function test() { + // if it compiles, it works + new B(); + } } diff --git a/tests/unit/src/unit/issues/Issue3781.hx b/tests/unit/src/unit/issues/Issue3781.hx new file mode 100644 index 00000000..909f1d46 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3781.hx @@ -0,0 +1,22 @@ +package unit.issues; + +private enum E { + E1(v:T); +} + +private abstract Ab(String) to String { + public function new() { + this = "foo"; + } +} + +class Issue3781 extends Test { + + function test() { + call(new Ab()); + } + + static function call(v:T) { + E1(v); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3804.hx b/tests/unit/src/unit/issues/Issue3804.hx new file mode 100644 index 00000000..e0457dec --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3804.hx @@ -0,0 +1,12 @@ +package unit.issues; + +@:generic +private class C { + public function new() {} +} + +class Issue3804 extends Test { + function test() { + var v:C = new C(); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3806.hx b/tests/unit/src/unit/issues/Issue3806.hx index 4c64ace2..53c40693 100644 --- a/tests/unit/src/unit/issues/Issue3806.hx +++ b/tests/unit/src/unit/issues/Issue3806.hx @@ -1,20 +1,20 @@ package unit.issues; private abstract Pointer(Int) from Int { - @:op(A - B) + @:op(A - B) public static function subP(lhs:Pointer, rhs:Pointer):Pointer { return lhs.value() - rhs.value(); } - public inline function value() { - return this; - } + public inline function value() { + return this; + } } class Issue3806 extends Test { function test() { - var p:Pointer = 12; - var p2:Pointer = 5; + var p:Pointer = 12; + var p2:Pointer = 5; var i = (cast (p - p2).value()); eq(7, i); } diff --git a/tests/unit/src/unit/issues/Issue3846.hx b/tests/unit/src/unit/issues/Issue3846.hx index 53266408..2110e95b 100644 --- a/tests/unit/src/unit/issues/Issue3846.hx +++ b/tests/unit/src/unit/issues/Issue3846.hx @@ -10,11 +10,11 @@ private class Extern { return a; } - @:overload( function (a:Int):Dynamic {}) + @:overload( function (a:Int):Dynamic {}) @:extern - inline public static function test(a:String):Dynamic { - return mytest(a); - } + inline public static function test(a:String):Dynamic { + return mytest(a); + } } #end @@ -22,8 +22,8 @@ private class Extern { class Issue3846 extends Test { function test() { #if (!java && !cs) - eq("coucou", Extern.test("coucou")); - eq(1, Extern.test(1)); + eq("coucou", Extern.test("coucou")); + eq(1, Extern.test(1)); #end } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3852.hx b/tests/unit/src/unit/issues/Issue3852.hx index 7ed9e465..a240bd6c 100644 --- a/tests/unit/src/unit/issues/Issue3852.hx +++ b/tests/unit/src/unit/issues/Issue3852.hx @@ -1,64 +1,64 @@ package unit.issues; class Issue3852 extends Test { - @:analyzer(no_const_propagation) - function test() { - var u:UInt = 4; - var i:Int = 3; - var d:Float = 3; + @:analyzer(no_const_propagation) + function test() { + var u:UInt = 4; + var i:Int = 3; + var d:Float = 3; - eq(u + i, 7); - eq(u + d, 7); - eq(i + u, 7); - eq(d + u, 7); + eq(u + i, 7); + eq(u + d, 7); + eq(i + u, 7); + eq(d + u, 7); - eq(u * i, 12); - eq(u * d, 12); - eq(i * u, 12); - eq(d * u, 12); + eq(u * i, 12); + eq(u * d, 12); + eq(i * u, 12); + eq(d * u, 12); - eq(u % i, 1); - eq(u % d, 1); - eq(i % u, 3); - eq(d % u, 3); + eq(u % i, 1); + eq(u % d, 1); + eq(i % u, 3); + eq(d % u, 3); - eq(u - i, 1); - eq(u - d, 1); - eq(i - u, (-1 : UInt)); - eq(d - u, -1); + eq(u - i, 1); + eq(u - d, 1); + eq(i - u, (-1 : UInt)); + eq(d - u, -1); - #if !flash // flash generator errors on these - t(u > i); - t(u > d); - f(i > u); - f(d > u); - t(u >= i); - t(u >= d); - f(i >= u); - f(d >= u); + #if !flash // flash generator errors on these + t(u > i); + t(u > d); + f(i > u); + f(d > u); + t(u >= i); + t(u >= d); + f(i >= u); + f(d >= u); - f(u < i); - f(u < d); - t(i < u); - t(d < u); - f(u <= i); - f(u <= d); - t(i <= u); - t(d <= u); - #end + f(u < i); + f(u < d); + t(i < u); + t(d < u); + f(u <= i); + f(u <= d); + t(i <= u); + t(d <= u); + #end - i = 5; - d = 5; - eq(u / i, 0.8); - eq(u / d, 0.8); - eq(i / u, 1.25); - eq(d / u, 1.25); + i = 5; + d = 5; + eq(u / i, 0.8); + eq(u / d, 0.8); + eq(i / u, 1.25); + eq(d / u, 1.25); - u = 8; - i = 2; - eq(u << i, 32); - eq(i << u, 512); - eq(u >> i, 2); - eq(i >> u, 0); - } + u = 8; + i = 2; + eq(u << i, 32); + eq(i << u, 512); + eq(u >> i, 2); + eq(i >> u, 0); + } } diff --git a/tests/unit/src/unit/issues/Issue3860.hx b/tests/unit/src/unit/issues/Issue3860.hx index 06095592..d09d2a4b 100644 --- a/tests/unit/src/unit/issues/Issue3860.hx +++ b/tests/unit/src/unit/issues/Issue3860.hx @@ -5,12 +5,12 @@ class Issue3860 extends Test public function test() { var a = ETest.A; - t(Std.is(a,ETest)); - f(Std.is(a,Int)); + t((a is ETest)); + f((a is Int)); var dyn:Dynamic = a; - t(Std.is(dyn,ETest)); - f(Std.is(dyn,Int)); + t((dyn is ETest)); + f((dyn is Int)); } } diff --git a/tests/unit/src/unit/issues/Issue3861.hx b/tests/unit/src/unit/issues/Issue3861.hx index 2a4019ff..6dc72022 100644 --- a/tests/unit/src/unit/issues/Issue3861.hx +++ b/tests/unit/src/unit/issues/Issue3861.hx @@ -2,11 +2,9 @@ package unit.issues; class Issue3861 extends unit.Test { function test() { - #if analyzer var a; var b = function() return a; a = 2; eq(2, b()); - #end } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3892.hx b/tests/unit/src/unit/issues/Issue3892.hx index e2d9cbf4..471df73b 100644 --- a/tests/unit/src/unit/issues/Issue3892.hx +++ b/tests/unit/src/unit/issues/Issue3892.hx @@ -1,8 +1,8 @@ package unit.issues; abstract MyBool(Bool) { - public inline function new(x:Bool) this = x; - public inline function toString():String return "asString: " + this; + public inline function new(x:Bool) this = x; + public inline function toString():String return "asString: " + this; } class Issue3892 extends Test { diff --git a/tests/unit/src/unit/issues/Issue3894.hx b/tests/unit/src/unit/issues/Issue3894.hx index 84fc42d8..b36af796 100644 --- a/tests/unit/src/unit/issues/Issue3894.hx +++ b/tests/unit/src/unit/issues/Issue3894.hx @@ -4,7 +4,7 @@ class Issue3894 extends Test { function test() { #if (flash || cs || java || cpp) // this doesn't actually error until post-processing so we cannot test it like this - //t(unit.TestType.typeError((null : haxe.Int64))); + //t(unit.HelperMacros.typeError((null : haxe.Int64))); #end } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3914.hx b/tests/unit/src/unit/issues/Issue3914.hx index 69e649b5..d09292d4 100644 --- a/tests/unit/src/unit/issues/Issue3914.hx +++ b/tests/unit/src/unit/issues/Issue3914.hx @@ -1,61 +1,61 @@ package unit.issues; class Issue3914 extends Test { - #if macro - static var storedExpr:haxe.macro.Expr; - #end - - function test() { - storeExpr(function(a:Array) { - for (i in a) { - try throw i catch (v:Dynamic) { - var v2 = v; - return v2; - } - } - throw false; - }); - eq(getStoredExpr()([3,2,1]), 3); - } - - function test2() { - storeExpr(function(a:Array) { - for (i in a) { - try throw i catch (v:Dynamic) { - var v2 = v; - return v2; - } - } - throw false; - }); - check2(); - } - - function check2() { - eq(getStoredExpr()([3,2,1]), 3); - } - - function test3() { - store3(); - eq(getStoredExpr()([3,2,1]), 3); - } - - function store3() { - storeExpr(function(a:Array) { - for (i in a) { - try throw i catch (v:Dynamic) { - var v2 = v; - return v2; - } - } - throw false; - }); - } - - static macro function storeExpr(e) { - storedExpr = haxe.macro.Context.storeTypedExpr(haxe.macro.Context.typeExpr(e)); - return macro {}; - } - - static macro function getStoredExpr() return storedExpr; + #if macro + static var storedExpr:haxe.macro.Expr; + #end + + function test() { + storeExpr(function(a:Array) { + for (i in a) { + try throw i catch (v:Dynamic) { + var v2 = v; + return v2; + } + } + throw false; + }); + eq(getStoredExpr()([3,2,1]), 3); + } + + function test2() { + storeExpr(function(a:Array) { + for (i in a) { + try throw i catch (v:Dynamic) { + var v2 = v; + return v2; + } + } + throw false; + }); + check2(); + } + + function check2() { + eq(getStoredExpr()([3,2,1]), 3); + } + + function test3() { + store3(); + eq(getStoredExpr()([3,2,1]), 3); + } + + function store3() { + storeExpr(function(a:Array) { + for (i in a) { + try throw i catch (v:Dynamic) { + var v2 = v; + return v2; + } + } + throw false; + }); + } + + static macro function storeExpr(e) { + storedExpr = haxe.macro.Context.storeTypedExpr(haxe.macro.Context.typeExpr(e)); + return macro {}; + } + + static macro function getStoredExpr() return storedExpr; } diff --git a/tests/unit/src/unit/issues/Issue3921.hx b/tests/unit/src/unit/issues/Issue3921.hx index 4b128661..8ec088ac 100644 --- a/tests/unit/src/unit/issues/Issue3921.hx +++ b/tests/unit/src/unit/issues/Issue3921.hx @@ -1,17 +1,17 @@ package unit.issues; class Issue3921 extends Test { - function test() { - eq(mb(), 3); - } + function test() { + eq(mb(), 3); + } - macro static function mb() { - return macro { - @:mergeBlock { - var v = 1; - } - v += 2; - v; - } - } + macro static function mb() { + return macro { + @:mergeBlock { + var v = 1; + } + v += 2; + v; + } + } } diff --git a/tests/unit/src/unit/issues/Issue3935.hx b/tests/unit/src/unit/issues/Issue3935.hx new file mode 100644 index 00000000..75915b5f --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3935.hx @@ -0,0 +1,34 @@ +package unit.issues; + +private class MyClass { + public function new() { } +} + +class Issue3935 extends Test { + function test() { + var c:haxe.ds.IntMap = [1=>2, 3=>"4"]; + var c:haxe.ds.StringMap = ["1"=>2, "3"=>"4"]; + var m = new MyClass(); + var m2 = new MyClass(); + var c:haxe.ds.ObjectMap = [m => 1, m2 => "1"]; + var c:haxe.ds.EnumValueMap = [EBreak => 1, EContinue => "2"]; + } + + function testMap() { + var c:Map = [1=>2, 3=>"4"]; + var c:Map = ["1"=>2, "3"=>"4"]; + var m = new MyClass(); + var m2 = new MyClass(); + var c:Map = [m => 1, m2 => "1"]; + var c:Map = [EBreak => 1, EContinue => "2"]; + } + + function testFail() { + t(unit.HelperMacros.typeError([1=>2, 3=>"4"])); + t(unit.HelperMacros.typeError(["1"=>2, "3"=>"4"])); + var m = new MyClass(); + var m2 = new MyClass(); + t(unit.HelperMacros.typeError([m => 1, m2 => "1"])); + t(unit.HelperMacros.typeError([EBreak => 1, EContinue => "2"])); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue3946.hx b/tests/unit/src/unit/issues/Issue3946.hx index 3af91295..a6c48d6c 100644 --- a/tests/unit/src/unit/issues/Issue3946.hx +++ b/tests/unit/src/unit/issues/Issue3946.hx @@ -1,12 +1,12 @@ package unit.issues; class Issue3946 extends Test { - #if cs - function test() { - var arr = cs.Lib.arrayAlloc(10); - eq(arr.length, 10); + #if cs + function test() { + var arr = cs.Lib.arrayAlloc(10); + eq(arr.length, 10); arr[0] = 5; eq(arr[0],5); - } - #end + } + #end } diff --git a/tests/unit/src/unit/issues/Issue3967.hx b/tests/unit/src/unit/issues/Issue3967.hx index 3b4bff39..5f2e52cc 100644 --- a/tests/unit/src/unit/issues/Issue3967.hx +++ b/tests/unit/src/unit/issues/Issue3967.hx @@ -11,8 +11,8 @@ private class A { class Issue3967 extends Test { function testAndy() { - var a = ["a", "b"]; - var b = a.copy(); + var a = ["a", "b"]; + var b = a.copy(); eq("a", b[0]); eq("b", b[1]); f(a == b); diff --git a/tests/unit/src/unit/issues/Issue3987.hx b/tests/unit/src/unit/issues/Issue3987.hx new file mode 100644 index 00000000..a571183e --- /dev/null +++ b/tests/unit/src/unit/issues/Issue3987.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue3987 extends Test { +#if java + public function test() { + var int = java.lang.Integer.valueOf(123); + eq(int.intValue(), 123); + t(java.lang.Integer.MIN_VALUE < 0); + t(java.lang.Integer.MAX_VALUE > 0); + eq(java.lang.Integer.SIZE, 32); + } +#end +} diff --git a/tests/unit/src/unit/issues/Issue4002.hx b/tests/unit/src/unit/issues/Issue4002.hx index 8914cab0..1c08881f 100644 --- a/tests/unit/src/unit/issues/Issue4002.hx +++ b/tests/unit/src/unit/issues/Issue4002.hx @@ -1,17 +1,17 @@ package unit.issues; private class A { - public var a = 5; - public function new() {} + public var a = 5; + public function new() {} } class Issue4002 extends Test { - function test() { - eq(fail(new A()), 5); - } + function test() { + eq(fail(new A()), 5); + } - function fail(v:T):Int { - var x = function() return v.a; - return x(); - } + function fail(v:T):Int { + var x = function() return v.a; + return x(); + } } diff --git a/tests/unit/src/unit/issues/Issue4045.hx b/tests/unit/src/unit/issues/Issue4045.hx index c2c7cee7..085fa1c8 100644 --- a/tests/unit/src/unit/issues/Issue4045.hx +++ b/tests/unit/src/unit/issues/Issue4045.hx @@ -15,31 +15,31 @@ class Issue4045 extends Test #if cs private abstract TestS(TestClass) { - inline public function new() - { - this = new TestClass(0); - } + inline public function new() + { + this = new TestClass(0); + } - public var a(get,set):Int; + public var a(get,set):Int; - inline private function get_a() - { - return this.a; - } + inline private function get_a() + { + return this.a; + } - inline private function set_a(v:Int) - { - return this.a = v; - } + inline private function set_a(v:Int) + { + return this.a = v; + } } @:nativeGen @:struct private class TestClass { - public var a:Int; + public var a:Int; - public function new(av) - { - this.a = av; - } + public function new(av) + { + this.a = av; + } } #end diff --git a/tests/unit/src/unit/issues/Issue4084.hx b/tests/unit/src/unit/issues/Issue4084.hx deleted file mode 100644 index e3dbcba2..00000000 --- a/tests/unit/src/unit/issues/Issue4084.hx +++ /dev/null @@ -1,17 +0,0 @@ -package unit.issues; - -class Issue4084 extends Test { - function test() { - var x = Xml.parse("
Hello!
"); - var v = switch x.nodeType { - case Xml.ProcessingInstruction: 0; - case Xml.DocType: 1; - case Xml.Document: 2; - case Xml.CData: 3; - case Xml.PCData: 4; - case Xml.Element: 5; - case Xml.Comment: 6; - } - eq(2, v); - } -} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4085.hx b/tests/unit/src/unit/issues/Issue4085.hx index 94af815c..bc2736b6 100644 --- a/tests/unit/src/unit/issues/Issue4085.hx +++ b/tests/unit/src/unit/issues/Issue4085.hx @@ -1,12 +1,12 @@ package unit.issues; class Issue4085 extends Test { - #if js - function test() { - function throwError() throw "hello, world"; - var msg = null; - untyped __js__("try { throwError(); } catch (e) { msg = e.message; }"); - eq(msg, "hello, world"); - } - #end + #if js + function test() { + function throwError() throw "hello, world"; + var msg = null; + untyped __js__("try { throwError(); } catch (e) { msg = e.message; }"); + eq(msg, "hello, world"); + } + #end } diff --git a/tests/unit/src/unit/issues/Issue4086.hx b/tests/unit/src/unit/issues/Issue4086.hx new file mode 100644 index 00000000..89c4f42b --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4086.hx @@ -0,0 +1,17 @@ +package unit.issues; + +private typedef GroceryItem = { name: String } +private typedef FruitItem = { name: String, count: Int }; + +class Issue4086 extends Test { + function test() { + check(apply3("apple", 5)); + } + + static function check(item:GroceryItem) { } + + static inline function apply3(name: String, count: Int): FruitItem { + return { name: name, count: count }; + } + +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4089.hx b/tests/unit/src/unit/issues/Issue4089.hx new file mode 100644 index 00000000..367f089b --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4089.hx @@ -0,0 +1,16 @@ +package unit.issues; +import unit.Test; + +class Issue4089 extends Test { + static var timestamp = 1.0; + + function test() { + function printTime(time:Float) { + return time; + } + var p1 = printTime.bind(timestamp); + feq(1.0, p1()); + timestamp = 2.0; + feq(1.0, p1()); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4094.hx b/tests/unit/src/unit/issues/Issue4094.hx index e106aa98..468b164c 100644 --- a/tests/unit/src/unit/issues/Issue4094.hx +++ b/tests/unit/src/unit/issues/Issue4094.hx @@ -2,46 +2,46 @@ package unit.issues; import unit.Test; class Issue4094 extends Test { - function test() { - var div = Xml.parse("
").firstElement(); - var nodes = Xml.parse("Text1Span
Div
Text2"); + function test() { + var div = Xml.parse("
").firstElement(); + var nodes = Xml.parse("Text1Span
Div
Text2"); - // Test insertChild() moves the nodes correctly. - var text1 = nodes.firstChild(); - var span = nodes.firstElement(); + // Test insertChild() moves the nodes correctly. + var text1 = nodes.firstChild(); + var span = nodes.firstElement(); - div.insertChild( text1, 0 ); - div.insertChild( span, 1 ); + div.insertChild( text1, 0 ); + div.insertChild( span, 1 ); - eq( div.toString(), '
Text1Span
' ); - eq( nodes.toString(), '
Div
Text2' ); - eq( text1.parent, div ); - eq( span.parent, div ); + eq( div.toString(), '
Text1Span
' ); + eq( nodes.toString(), '
Div
Text2' ); + eq( text1.parent, div ); + eq( span.parent, div ); - // Test removeChild() removes the nodes correctly - var divText = nodes.firstElement().firstChild(); + // Test removeChild() removes the nodes correctly + var divText = nodes.firstElement().firstChild(); - nodes.firstElement().removeChild( divText ); - eq( divText.parent, null ); - eq( nodes.toString(), '
Text2' ); + nodes.firstElement().removeChild( divText ); + eq( divText.parent, null ); + eq( nodes.toString(), '
Text2' ); - // Test addChild() moves the nodes correctly. - var comment = nodes.firstChild(); - var innerDiv = nodes.firstElement(); + // Test addChild() moves the nodes correctly. + var comment = nodes.firstChild(); + var innerDiv = nodes.firstElement(); - div.addChild( comment ); - div.addChild( innerDiv ); - div.addChild( divText ); + div.addChild( comment ); + div.addChild( innerDiv ); + div.addChild( divText ); - eq( div.toString(), '
Text1Span
Div
' ); - eq( nodes.toString(), 'Text2' ); - eq( comment.parent, div ); - eq( innerDiv.parent, div ); - eq( divText.parent, div ); + eq( div.toString(), '
Text1Span
Div
' ); + eq( nodes.toString(), 'Text2' ); + eq( comment.parent, div ); + eq( innerDiv.parent, div ); + eq( divText.parent, div ); - // Test addChild() moves a current child to the end. + // Test addChild() moves a current child to the end. - div.addChild( span ); - eq( div.toString(), '
Text1
DivSpan
' ); - } + div.addChild( span ); + eq( div.toString(), '
Text1
DivSpan
' ); + } } diff --git a/tests/unit/src/unit/issues/Issue4103.hx b/tests/unit/src/unit/issues/Issue4103.hx new file mode 100644 index 00000000..a1d84038 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4103.hx @@ -0,0 +1,16 @@ +package unit.issues; + +@:enum +private abstract IntAbstract(Int) from Int to Int { + public static var value = 5; + + var var1 = 1; + var var2 = 2; +} + +class Issue4103 extends Test { + function test() { + var value = IntAbstract.value; + eq(5, value); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4121.hx b/tests/unit/src/unit/issues/Issue4121.hx new file mode 100644 index 00000000..1607357d --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4121.hx @@ -0,0 +1,21 @@ +package unit.issues; + +import unit.issues.misc.Issue4121Macro.wrap; + +private typedef P2 = { + var hidden(null, null):Int; +} + +class Issue4121 extends Test { + function test() { + eq("(@:test ((x) = (1)))", wrap(@:test x = 1)); + eq("(@:test (@:test2 ((x) = (@:test3 (1)))))", wrap(@:test @:test2 x = @:test3 1)); + + var p2:P2 = { hidden: 12 }; + t(unit.HelperMacros.typeError(p2.hidden)); + eq(12, @:privateAccess p2.hidden); + t(unit.HelperMacros.typeError(p2.hidden = 13)); + @:privateAccess p2.hidden = 13; + eq(13, @:privateAccess p2.hidden); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4122.hx b/tests/unit/src/unit/issues/Issue4122.hx new file mode 100644 index 00000000..d4ac928c --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4122.hx @@ -0,0 +1,24 @@ +package unit.issues; + +@:enum +private abstract Test2(Int) to Int { + var PROP = 123; +} + +private abstract Test3(Int) { + static public var PROP = 123; +} + +class Issue4122 extends Test { + function test() { + eq(130, Test2.PROP + 7); + unit.HelperMacros.typedAs(Test2.PROP + 7, 7); + feq(130.5, Test2.PROP + 7.5); + unit.HelperMacros.typedAs(Test2.PROP + 7.5, 7.5); + + eq(130, Test3.PROP + 7); + unit.HelperMacros.typedAs(Test3.PROP + 7, 7); + feq(130.5, Test3.PROP + 7.5); + unit.HelperMacros.typedAs(Test3.PROP + 7.5, 7.5); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4130.hx b/tests/unit/src/unit/issues/Issue4130.hx index baa24fc4..d842e743 100644 --- a/tests/unit/src/unit/issues/Issue4130.hx +++ b/tests/unit/src/unit/issues/Issue4130.hx @@ -12,87 +12,87 @@ class Issue4130 extends Test #if cpp public function test() { - var val64 = Int64.make(42,24); - - var int2Int64 = new haxe.ds.IntMap(); - int2Int64.set( 42, val64); - var key:Dynamic = 43; - int2Int64.set( key, val64); - eq(int2Int64.get(42),val64); - eq(int2Int64.get(43),val64); - - - var string2Int64 = new haxe.ds.StringMap(); - string2Int64.set( "42", val64 ); - var key:Dynamic = "43"; - string2Int64.set( "43", val64 ); - eq( string2Int64.get("42"), val64 ); - eq( string2Int64.get(key), val64 ); - - - var key = new TestKey(); - var obj2Int64 = new haxe.ds.ObjectMap(); - obj2Int64.set( key, val64); - eq( obj2Int64.get(key), val64 ); - - var weak2Int64 = new haxe.ds.WeakMap(); - weak2Int64.set( key, val64); - eq( weak2Int64.get(key),val64 ); - - #if !cppia - var a = [1]; - var valPtr = cpp.Pointer.arrayElem(a,0); - - var int2Ptr = new haxe.ds.IntMap< cpp.Pointer >(); - int2Ptr.set( 42, valPtr ); - var key:Dynamic = 42; - int2Ptr.set( key, valPtr ); - eq( int2Ptr.get(42), valPtr); - eq( int2Ptr.get(key), valPtr); - - var string2Ptr = new haxe.ds.StringMap< cpp.Pointer >(); - string2Ptr.set( "42", valPtr ); - var key:Dynamic = "42"; - string2Ptr.set( key, valPtr ); - eq( string2Ptr.get("42"), valPtr ); - eq( string2Ptr.get(key), valPtr ); - - var key = new TestKey(); - var obj2Ptr = new haxe.ds.ObjectMap >(); - obj2Ptr.set( key, valPtr ); - eq( obj2Ptr.get(key), valPtr ); - - var weak2Ptr = new haxe.ds.WeakMap >(); - weak2Ptr.set( key, valPtr ); - eq( weak2Ptr.get(key), valPtr ); - - // Functions - var valFunc = cpp.Callable.fromStaticFunction( someFunc ); - - var int2Func = new haxe.ds.IntMap< cpp.CallableInt> >(); - int2Func.set( 42, valFunc ); - var key:Dynamic = 42; - int2Func.set( key, valFunc ); - eq( int2Func.get(42), valFunc); - eq( int2Func.get(key), valFunc); - - var string2Func = new haxe.ds.StringMap< cpp.CallableInt> >(); - string2Func.set( "42", valFunc ); - var key:Dynamic = "42"; - string2Func.set( key, valFunc ); - eq( string2Func.get("42"), valFunc ); - eq( string2Func.get(key), valFunc ); - - var key = new TestKey(); - var obj2Func = new haxe.ds.ObjectMapInt> >(); - obj2Func.set( key, valFunc ); - eq( obj2Func.get(key), valFunc ); - - var weak2Func = new haxe.ds.WeakMapInt> >(); - weak2Func.set( key, valFunc ); - eq( weak2Func.get(key), valFunc ); - - #end + var val64 = Int64.make(42,24); + + var int2Int64 = new haxe.ds.IntMap(); + int2Int64.set( 42, val64); + var key:Dynamic = 43; + int2Int64.set( key, val64); + eq(int2Int64.get(42),val64); + eq(int2Int64.get(43),val64); + + + var string2Int64 = new haxe.ds.StringMap(); + string2Int64.set( "42", val64 ); + var key:Dynamic = "43"; + string2Int64.set( "43", val64 ); + eq( string2Int64.get("42"), val64 ); + eq( string2Int64.get(key), val64 ); + + + var key = new TestKey(); + var obj2Int64 = new haxe.ds.ObjectMap(); + obj2Int64.set( key, val64); + eq( obj2Int64.get(key), val64 ); + + var weak2Int64 = new haxe.ds.WeakMap(); + weak2Int64.set( key, val64); + eq( weak2Int64.get(key),val64 ); + + #if !cppia + var a = [1]; + var valPtr = cpp.Pointer.arrayElem(a,0); + + var int2Ptr = new haxe.ds.IntMap< cpp.Pointer >(); + int2Ptr.set( 42, valPtr ); + var key:Dynamic = 42; + int2Ptr.set( key, valPtr ); + eq( int2Ptr.get(42), valPtr); + eq( int2Ptr.get(key), valPtr); + + var string2Ptr = new haxe.ds.StringMap< cpp.Pointer >(); + string2Ptr.set( "42", valPtr ); + var key:Dynamic = "42"; + string2Ptr.set( key, valPtr ); + eq( string2Ptr.get("42"), valPtr ); + eq( string2Ptr.get(key), valPtr ); + + var key = new TestKey(); + var obj2Ptr = new haxe.ds.ObjectMap >(); + obj2Ptr.set( key, valPtr ); + eq( obj2Ptr.get(key), valPtr ); + + var weak2Ptr = new haxe.ds.WeakMap >(); + weak2Ptr.set( key, valPtr ); + eq( weak2Ptr.get(key), valPtr ); + + // Functions + var valFunc = cpp.Callable.fromStaticFunction( someFunc ); + + var int2Func = new haxe.ds.IntMap< cpp.CallableInt> >(); + int2Func.set( 42, valFunc ); + var key:Dynamic = 42; + int2Func.set( key, valFunc ); + eq( int2Func.get(42), valFunc); + eq( int2Func.get(key), valFunc); + + var string2Func = new haxe.ds.StringMap< cpp.CallableInt> >(); + string2Func.set( "42", valFunc ); + var key:Dynamic = "42"; + string2Func.set( key, valFunc ); + eq( string2Func.get("42"), valFunc ); + eq( string2Func.get(key), valFunc ); + + var key = new TestKey(); + var obj2Func = new haxe.ds.ObjectMapInt> >(); + obj2Func.set( key, valFunc ); + eq( obj2Func.get(key), valFunc ); + + var weak2Func = new haxe.ds.WeakMapInt> >(); + weak2Func.set( key, valFunc ); + eq( weak2Func.get(key), valFunc ); + + #end } static function someFunc(a:Int) : Int return a; diff --git a/tests/unit/src/unit/issues/Issue4158.hx b/tests/unit/src/unit/issues/Issue4158.hx new file mode 100644 index 00000000..1005c8f9 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4158.hx @@ -0,0 +1,23 @@ +package unit.issues; + +@:forward @:native("Short") +private abstract TestAbstract(TestClass) from TestClass to TestClass { + public inline function new() { + this = new TestClass(); + } + public function getValue2() { + return this.value * 2; + } +} + +private class TestClass { + public var value:Int = 1; + public function new() { } +} + +class Issue4158 extends Test { + function test() { + var o = new TestAbstract(); + eq(2, o.getValue2()); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4180.hx b/tests/unit/src/unit/issues/Issue4180.hx new file mode 100644 index 00000000..0db085e6 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4180.hx @@ -0,0 +1,26 @@ +package unit.issues; + +private abstract A(Int) { + public function new(v) this = v; + @:op(A-B) function _(a:Int):A; + public function get() return this; +} + +class Issue4180 extends Test { + @:isVar static var a(get,set):A; + static function set_a(value:A):A return a = value; + static function get_a():A return a; + + static var a2(default,set):A; + static function set_a2(value:A):A return a2 = value; + + function test() { + a = new A(0); + a -= 5; + eq(-5, a.get()); + + a2 = new A(0); + a2 -= 5; + eq(-5, a2.get()); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4196.hx b/tests/unit/src/unit/issues/Issue4196.hx new file mode 100644 index 00000000..551eb912 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4196.hx @@ -0,0 +1,12 @@ +package unit.issues; + +class Issue4196 extends Test { + function test() { + var f = [ + 'a' => {"id": { "deep" : 5 }}, + 'b' => {"id": {}} + ]; + var a:Map; + unit.HelperMacros.typedAs(f, a); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4203.hx b/tests/unit/src/unit/issues/Issue4203.hx new file mode 100644 index 00000000..57941ccd --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4203.hx @@ -0,0 +1,28 @@ +package unit.issues; + +class Issue4203 extends Test { + public function test() { + var thing = new Thing1(true); + t(thing.getIt()); + var ni:NativeItem = thing; + t(ni.getIt()); + } +} + +#if (java || cs) +@:nativeGen +#end +private interface NativeItem { + public function getIt() : T; +} + +private class Thing1 implements NativeItem { + var value: Bool; + public function new(value) { + this.value = value; + } + + public function getIt() : Bool { + return value; + } +} diff --git a/tests/unit/src/unit/issues/Issue4203.hx.disabled b/tests/unit/src/unit/issues/Issue4203.hx.disabled new file mode 100644 index 00000000..3fcee8da --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4203.hx.disabled @@ -0,0 +1,29 @@ +package unit.issues; + +class Issue4203 extends Test { + public function test() { +#if !cpp + var val = new Thing1(true); + eq(val.getIt(), true); + t(val.getIt()); +#end + } +} + +#if !cpp +@:nativeGen +private interface NativeItem { + public function getIt() : T; +} + +private class Thing1 implements NativeItem { + var value: Bool; + public function new(value) { + this.value = value; + } + + public function getIt() : Bool { + return value; + } +} +#end diff --git a/tests/unit/src/unit/issues/Issue4222.hx b/tests/unit/src/unit/issues/Issue4222.hx new file mode 100644 index 00000000..bf4ff92b --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4222.hx @@ -0,0 +1,22 @@ +package unit.issues; + +private class Base { + public function new() { } + public function covariant():Base { + return this; + } +} + +private class Child extends Base { + public override function covariant():Child { + return this; + } +} + + +class Issue4222 extends Test { + function test() { + var c = new Child(); + var v = c.covariant(); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4232.hx b/tests/unit/src/unit/issues/Issue4232.hx new file mode 100644 index 00000000..3fc01330 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4232.hx @@ -0,0 +1,18 @@ +package unit.issues; + +@:keep +class Issue4232CreateMe { + public var value:String; + public function new(a1:String, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) { + value = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14; + } +} + +class Issue4232 extends Test { + function test() { + #if !hl + var c:Issue4232CreateMe = Type.createInstance(Issue4232CreateMe, [for (i in 1...15) "" + i]); + eq("1234567891011121314", c.value); + #end + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4246.hx b/tests/unit/src/unit/issues/Issue4246.hx new file mode 100644 index 00000000..bd484faa --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4246.hx @@ -0,0 +1,10 @@ +package unit.issues; + +class Issue4246 extends Test { + public static function and() { } + public static function _and() { } + function test() { + and(); + _and(); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4254.hx b/tests/unit/src/unit/issues/Issue4254.hx new file mode 100644 index 00000000..85774fc6 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4254.hx @@ -0,0 +1,9 @@ +package unit.issues; + +class Issue4254 extends Test { + var px:Int = Math.floor(20); + + function test() { + eq(20, px); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4260.hx b/tests/unit/src/unit/issues/Issue4260.hx new file mode 100644 index 00000000..6e1e220c --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4260.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue4260 extends unit.Test { + var floatValue:Float = 0.0; + var intValue:Float = 0; + var nullValue:Null; + + function test() { + t(intValue == floatValue); + f(intValue == nullValue); + f(floatValue == nullValue); + } +} diff --git a/tests/unit/src/unit/issues/Issue4273.hx b/tests/unit/src/unit/issues/Issue4273.hx new file mode 100644 index 00000000..bef99db3 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4273.hx @@ -0,0 +1,17 @@ +package unit.issues; + +@:generic +private class Value { + public var v :T; + + public function new (v :T) { + this.v = v; + } +} + +class Issue4273 extends Test { + function test() { + var anything = new Value(666); + eq(666, anything.v); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4277.hx b/tests/unit/src/unit/issues/Issue4277.hx new file mode 100644 index 00000000..9e375165 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4277.hx @@ -0,0 +1,12 @@ +package unit.issues; + +class Issue4277 extends Test { + function test() { + t(unit.HelperMacros.typeError(fancyInlineMethod)); + } + + @:extern private inline static function fancyInlineMethod(y:Int = 3):Int { + var x = 5; + return x + (x += x) - y; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4284.hx b/tests/unit/src/unit/issues/Issue4284.hx new file mode 100644 index 00000000..309ff567 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4284.hx @@ -0,0 +1,19 @@ +package unit.issues; + +private abstract A(String) { + public inline function new(s) this = s; + + @:op(A!) function opNot() { + return this.toUpperCase(); + } +} + +class Issue4284 extends Test { + function test() { + var a = new A("foo"); + eq("FOO", a!); + + var b = true; + t(unit.HelperMacros.typeError(b!)); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4285.hx b/tests/unit/src/unit/issues/Issue4285.hx new file mode 100644 index 00000000..4c1fa234 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4285.hx @@ -0,0 +1,12 @@ +package unit.issues; + +class Issue4285 extends Test { + function test() { + var a = [1, 2, 3]; + t(myIs(a, Array)); + } + + static function myIs(d:Dynamic, t:Dynamic) { + return Std.is(d, t); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4295.hx b/tests/unit/src/unit/issues/Issue4295.hx new file mode 100644 index 00000000..d47e3618 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4295.hx @@ -0,0 +1,10 @@ +package unit.issues; + +class Issue4295 extends Test { + function test() { + + var dc:Dynamic> = {a: [0]}; + eq(dc.a[0], 0); + eq(dc.a[0] = 1, 1); + } +} diff --git a/tests/unit/src/unit/issues/Issue4306.hx b/tests/unit/src/unit/issues/Issue4306.hx new file mode 100644 index 00000000..234d97c5 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4306.hx @@ -0,0 +1,42 @@ +package unit.issues; + +import unit.issues.misc.Issue4306Macro.TypeName; +import unit.issues.misc.Issue4306Macro.Arity; +import unit.issues.misc.Issue4306Macro.EnumListener; + +private enum E { + Message(s:String); + NoMessage; +} + +class Issue4306 extends Test { + function test() { + eq("String", getTypeName("foo")); + eq("Int", getTypeName(12)); + eq("haxe.Template", getTypeName(new haxe.Template("foo"))); + + eq(0, getArity(test)); + eq(1, getArity(getTypeName)); + eq(2, getArity(function(x, y) { })); + + function onMessage(s:String) { } + function onNoMessage() { } + + eq("Message", addEnumListener(Message, onMessage)); + t(unit.HelperMacros.typeError(addEnumListener(Message, onNoMessage))); + eq("NoMessage", addEnumListener(NoMessage, onNoMessage)); + t(unit.HelperMacros.typeError(addEnumListener(NoMessage, onMessage))); + } + + static function getTypeName(t:TypeName) { + return t; + } + + static function getArity(a:Arity) { + return a; + } + + static function addEnumListener(e:EnumListener, f:T) { + return e; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4310.hx b/tests/unit/src/unit/issues/Issue4310.hx new file mode 100644 index 00000000..64681fce --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4310.hx @@ -0,0 +1,14 @@ +package unit.issues; + +class BaseClass { + public function new() {} +} + +class Child1 extends BaseClass {} + +class Issue4310 extends Test { + function test() { + var child1:BaseClass = new Child1(); + cast(child1, BaseClass); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4312.hx b/tests/unit/src/unit/issues/Issue4312.hx new file mode 100644 index 00000000..3e0f1c51 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4312.hx @@ -0,0 +1,12 @@ +package unit.issues; + +class Issue4312 extends Test { + function test():Void { + var a = getValue(); + if (!a) return null; + } + + static function getValue() { + return false; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4313.hx b/tests/unit/src/unit/issues/Issue4313.hx new file mode 100644 index 00000000..6868fbf4 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4313.hx @@ -0,0 +1,27 @@ +package unit.issues; + +class Issue4313 extends Test { + function test():Void { + aeq(["myMeta1", "myMeta2", "myMeta3"], m("fun")); + } + + static function fun(@myMeta1 @myMeta2 a:Int, @myMeta3 b:String, c:Bool) {} + + static macro function m(name:String) { + var cl = haxe.macro.Context.getLocalClass().get(); + for (f in cl.statics.get()) { + if (f.name == name) switch (f.expr().expr) { + case TFunction({args: args}): + var result = []; + for (arg in args) { + for (entry in arg.v.meta.get()) + result.push(entry.name); + } + return macro $v{result}; + default: + } + } + haxe.macro.Context.error("no such method: " + name, cl.pos); + return null; + } +} diff --git a/tests/unit/src/unit/issues/Issue4322.hx b/tests/unit/src/unit/issues/Issue4322.hx new file mode 100644 index 00000000..de36ce11 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4322.hx @@ -0,0 +1,20 @@ +package unit.issues; + +private class InlineTest { + public var a: Int; + public var b: Int; + + @:extern + public inline function new(a: Int, b: Int) { + this.a = a; + this.b = b; + } +} + +class Issue4322 extends Test { + function test() { + var c = new InlineTest(3, 4); + eq(3, c.a); + eq(4, c.b); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4323.hx b/tests/unit/src/unit/issues/Issue4323.hx new file mode 100644 index 00000000..c9992074 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4323.hx @@ -0,0 +1,20 @@ +package unit.issues; + +class Issue4323 extends Test { + + function test() { + setB(); + t(b); + } + + function setB() { + return doSetB(); + } + + static var b = false; + + static inline function doSetB() { + b = true; + } + +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4324.hx b/tests/unit/src/unit/issues/Issue4324.hx new file mode 100644 index 00000000..b47006c4 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4324.hx @@ -0,0 +1,20 @@ +package unit.issues; + +class Issue4324 extends Test { + + function test() { + eq(1, getInt()); + } + + static inline function getInt() { + switch (getTrue()) { + case true: return 1; + case false: return 2; + } + } + + static function getTrue() { + return true; + } + +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4327.hx.disabled b/tests/unit/src/unit/issues/Issue4327.hx.disabled new file mode 100644 index 00000000..c2c75327 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4327.hx.disabled @@ -0,0 +1,18 @@ +package unit.issues; + +@:callable +abstract Example(Void->String) { + public function new() { + this = fun; + } + + function fun() { + return "foo"; + } +} + +class Issue4327 extends Test { + function test() { + eq("foo", new Example()()); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4329.hx b/tests/unit/src/unit/issues/Issue4329.hx new file mode 100644 index 00000000..2ed99949 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4329.hx @@ -0,0 +1,18 @@ +package unit.issues; + +class Issue4329 extends Test { + + static function foo(x:Int) { + var r = switch( x ) { + case 5: 3; + default: + return bar(); + } + } + + static function bar() { } + + function test() { + foo(12); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4337.hx b/tests/unit/src/unit/issues/Issue4337.hx new file mode 100644 index 00000000..38cf0b0b --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4337.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue4337 extends Test { + + function test() { + eq("goto", goto()); + } + + static function goto(){ + return "goto"; + } + +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4343.hx b/tests/unit/src/unit/issues/Issue4343.hx new file mode 100644 index 00000000..c0362729 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4343.hx @@ -0,0 +1,22 @@ +package unit.issues; + +class Issue4343 extends Test { + function test() { + (new SomeObject() : ISomeObject).call(); + } +} + +class SomeObject implements ISomeObject { + public function new() {} + public function call():Void {} +} + +interface ISomeObject extends IEmtpyExtendsCallable extends IEmpty {} + +interface IEmpty {} + +interface IEmtpyExtendsCallable extends ICallable {} + +interface ICallable { + public function call():Void; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4353.hx b/tests/unit/src/unit/issues/Issue4353.hx new file mode 100644 index 00000000..8e0f7cd1 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4353.hx @@ -0,0 +1,37 @@ +package unit.issues; + +private class Iter1 { + public var i : Int; + public var e : Int; + public inline function new(i, e) {this.i = i; this.e = e;} + public inline function hasNext() return i < e; + public inline function next() {var j = i; i++; return j;} +} + +private class Iter2 { + public var i : Int; + public var e : Int; + var j : Int; + public inline function new(i, e) {this.i = i; this.e = e;} + public inline function hasNext() return i < e; + public inline function next() {j = i; i++; return j;} +} + + +class Issue4353 extends Test { + function test() { + var s = 0; + for (i in new Iter1(0, 10)) { + s += i; + } + eq(45, s); + } + + function test2() { + var s = 0; + for (i in new Iter2(0, 10)) { + s += i; + } + eq(45, s); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4357.hx b/tests/unit/src/unit/issues/Issue4357.hx new file mode 100644 index 00000000..adf4e957 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4357.hx @@ -0,0 +1,13 @@ +package unit.issues; + +private abstract MyAbstract(Array) from Array { + @:op(++A) public function pre() + return "pre"; +} + +class Issue4357 extends Test { + function test() { + var a:MyAbstract = [123]; + eq("pre", ++a); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4359.hx b/tests/unit/src/unit/issues/Issue4359.hx new file mode 100644 index 00000000..e8c4c80a --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4359.hx @@ -0,0 +1,8 @@ +package unit.issues; + +private extern class E { + @:require(false) static public inline var x = 1; +} + + +class Issue4359 extends Test { } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4360.hx b/tests/unit/src/unit/issues/Issue4360.hx new file mode 100644 index 00000000..eda6374f --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4360.hx @@ -0,0 +1,21 @@ +package unit.issues; + +class Issue4360 extends Test { + public function test() { + //this fails + var t : Abstr = new Abstr(); + //but this works + // var t : Abstr = new Abstr(new Test()); + eq(t, null); + } +} + +private abstract Abstr(Issue4360) to Issue4360 { + public function new (inst:Issue4360 = null) : Void { + this = inst; + } +} + +private class Item { + public function new () : Void { } +} diff --git a/tests/unit/src/unit/issues/Issue4384.hx b/tests/unit/src/unit/issues/Issue4384.hx new file mode 100644 index 00000000..5d3b3297 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4384.hx @@ -0,0 +1,20 @@ +package unit.issues; + +private class MyTest { + var v:T; + public function new(v:T):Void { + this.v = v; + } + public function a():T + return v; + + inline public function test():T + return a(); +} + +class Issue4384 extends Test { + function test() { + var t = new MyTest([123]); + eq(123, t.test()[0]); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4388.hx b/tests/unit/src/unit/issues/Issue4388.hx new file mode 100644 index 00000000..a81c7878 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4388.hx @@ -0,0 +1,22 @@ +package unit.issues; +import haxe.Int64; + +class Issue4388 extends Test +{ + public function test() + { + var test = new PTest(); + test.x |= 2; + t(test.x == 3); + } +} + +private class PTest +{ + public var x(default, set) : Int64; + inline function set_x(i:Int64) : Int64 { + return this.x = i; + } + + public function new() { this.x = 1; } +} diff --git a/tests/unit/src/unit/issues/Issue4397.hx b/tests/unit/src/unit/issues/Issue4397.hx new file mode 100644 index 00000000..b8878977 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4397.hx @@ -0,0 +1,15 @@ +package unit.issues; + +using unit.issues.Issue4397; + +class Issue4397 extends Test { + #if js + function test() { + 0.toFixed(); + } + + static inline function toFixed(f:Float):String { + return (cast f).toFixed(); + } + #end +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4407.hx b/tests/unit/src/unit/issues/Issue4407.hx index 933dcaea..ce43db90 100644 --- a/tests/unit/src/unit/issues/Issue4407.hx +++ b/tests/unit/src/unit/issues/Issue4407.hx @@ -12,5 +12,5 @@ class Issue4407 extends Test private enum Example { - NullParam(first:Null, second:String); + NullParam(first:Null, second:String); } diff --git a/tests/unit/src/unit/issues/Issue4419.hx b/tests/unit/src/unit/issues/Issue4419.hx new file mode 100644 index 00000000..0dff4f82 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4419.hx @@ -0,0 +1,23 @@ +package unit.issues; + +#if js +@:native("Issue4419External") +private extern class External { + static function __init__():Void { + haxe.macro.Compiler.includeFile("unit/issues/misc/Issue4419External.js"); + } +} + +private class SubExt extends External { + public function new():Void {} + public function hello() return "hello"; +} +#end + +class Issue4419 extends Test { + #if js + function test() { + eq("hello", new SubExt().hello()); + } + #end +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4421.hx b/tests/unit/src/unit/issues/Issue4421.hx new file mode 100644 index 00000000..756b2f03 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4421.hx @@ -0,0 +1,21 @@ +package unit.issues; + +class Issue4421 extends Test { + function test() { + var buf = haxe.io.UInt8Array.fromArray([for (i in 0...20) i]); + var match = 0; + var cur_match = 0; + var scan_end = 20; + + do { + match = cur_match; + + if (buf[match + 1] != scan_end || + buf[++match] != buf[scan_end - 1]) { + continue; + } + + } while (((cur_match = buf[++cur_match]) < 10)); + eq(10, cur_match); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4426.hx b/tests/unit/src/unit/issues/Issue4426.hx new file mode 100644 index 00000000..6baba303 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4426.hx @@ -0,0 +1,50 @@ +package unit.issues; + +private class Vector2Base { + public var x:Float; + public var y:Float; + + public inline function new(x:Float, y:Float) { + this.x = x; + this.y = y; + } + + public function toString() { + return '($x, $y)'; + } +} + +@:forward(x, y) +private abstract Vector2(Vector2Base) from Vector2Base to Vector2Base { + + public inline function new(x:Float = 0.0, y:Float = 0.0) { + this = new Vector2Base(x, y); + } + + @:op(A + B) + public static inline function Add(a:Vector2, b:Vector2):Vector2 + { + return new Vector2(a.x + b.x, a.y + b.y); + } +} + +private class Transform { + public var position(default, set):Vector2 = new Vector2(0.0, 0.0); + + public function new() { + } + + function set_position(newPosition:Vector2):Vector2 { + position = newPosition; + return position; + } +} + +class Issue4426 extends Test { + function test() { + var transform = new Transform(); + transform.position += new Vector2(1.0, 0.0); + feq(1., transform.position.x); + feq(0., transform.position.y); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4436.hx b/tests/unit/src/unit/issues/Issue4436.hx new file mode 100644 index 00000000..19eb48ef --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4436.hx @@ -0,0 +1,19 @@ +package unit.issues; + +import haxe.Int64; + +class Issue4436 extends Test { + function test() { + nullableValue = 29; + t(checkNull(29)); + } + + var nullableValue:Null; + + private function checkNull(value:Int64) { + if (nullableValue == value) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4445.hx b/tests/unit/src/unit/issues/Issue4445.hx new file mode 100644 index 00000000..924b3371 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4445.hx @@ -0,0 +1,17 @@ +package unit.issues; + +#if php +@:rtti +@somemeta +class ClassWithRttiMeta { + +} +#end + +class Issue4445 extends Test { + #if php + function test() { + eq(true, haxe.rtti.Rtti.hasRtti(ClassWithRttiMeta)); + } + #end +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4450.hx b/tests/unit/src/unit/issues/Issue4450.hx new file mode 100644 index 00000000..551d0c7d --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4450.hx @@ -0,0 +1,8 @@ +package unit.issues; + +class Issue4450 extends Test { + function test() { + @meta var some = 1; + eq(1, some); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4457.hx b/tests/unit/src/unit/issues/Issue4457.hx index 10773d32..0a951e94 100644 --- a/tests/unit/src/unit/issues/Issue4457.hx +++ b/tests/unit/src/unit/issues/Issue4457.hx @@ -5,7 +5,7 @@ private class A { } @:generic -private class B extends A { +private class BVoid>> extends A { } class Issue4457 extends Test diff --git a/tests/unit/src/unit/issues/Issue4466.hx b/tests/unit/src/unit/issues/Issue4466.hx new file mode 100644 index 00000000..6333fb90 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4466.hx @@ -0,0 +1,10 @@ +package unit.issues; + +class Issue4466 extends Test { + function test() { + var x; + function init(y) x = y; + init(2); + eq(2, x); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4473.hx b/tests/unit/src/unit/issues/Issue4473.hx new file mode 100644 index 00000000..5c21ace0 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4473.hx @@ -0,0 +1,67 @@ +package unit.issues; + +class Issue4473 extends Test { + function test1() { + var results = [ + "home" => [ + 1 => 1, + 2 => 3 + ], + "home2" => [ + 1 => 3, + 2 => 2 + ], + "contact" => [ + 1 => 3, + 2 => 3 + ] + ]; + var scenes = ["home", "home2", "contact"]; + var indices = [1, 2]; + + for (scene in scenes) { + for (index in indices) { + eq(results[scene][index], f1(scene, index)); + } + } + } + + function test2() { + var results = [ + "home" => [ + 1 => 1, + 2 => 2 + ], + "home2" => [ + 1 => 3, + 2 => 3 + ] + ]; + var scenes = ["home", "home2"]; + var indices = [1, 2]; + + for (scene in scenes) { + for (index in indices) { + eq(results[scene][index], f2(scene, index)); + } + } + } + + static function f1(scene:String, index:Int) { + var x = switch(scene) { + case "home" if (index < 2): 1; + case "home2" if (index >= 2): 2; + case _: 3; + } + return x; + } + + static function f2(scene:String, index:Int) { + var x = switch(scene) { + case "home" if (index < 2): 1; + case "home" if (index >= 2): 2; + case _: 3; + } + return x; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4501.hx b/tests/unit/src/unit/issues/Issue4501.hx new file mode 100644 index 00000000..8e002ccc --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4501.hx @@ -0,0 +1,11 @@ +package unit.issues; + +private class Dummy { + public function new (arg:Null) {} +} + +class Issue4501 extends Test { + function test() { + new Dummy(null); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4526.hx b/tests/unit/src/unit/issues/Issue4526.hx new file mode 100644 index 00000000..2f94bbc5 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4526.hx @@ -0,0 +1,68 @@ +package unit.issues; + +@:structInit +private class Struct1 { + var x:Int; + var y:Int; + public function get() { + return x + " " + y; + } +} + +@:structInit +private class Struct2 { + @:optional var x:Int; + var y:Int; + public function get() { + return x + " " + y; + } +} + +@:structInit +private class Struct3 { + @:optional var x:Int; + @:optional var y:Int; + public function get() { + return x + " " + y; + } +} + +@:structInit +private class Struct4 { + var x:Int; + var y:Int; + var z:Int; + public function get() { + return x + " " + y + " " + z; + } +} + +class Issue4526 extends Test { + function test() { + var fieldNull = #if (cpp || flash || java || cs || hl) 0 #else null #end; + + var s1:Struct1 = { x: 12, y: 13 }; + eq("12 13", s1.get()); + t(unit.HelperMacros.typeError(({x:12} : Struct1))); + t(unit.HelperMacros.typeError(({y:12} : Struct1))); + + var s2:Struct2 = { x: 12, y: 13 }; + eq("12 13", s2.get()); + var s2:Struct2 = { y: 13 }; + eq(fieldNull + " 13", s2.get()); + t(unit.HelperMacros.typeError(({x:12} : Struct2))); + + var s3:Struct3 = { x: 12, y: 13 }; + eq("12 13", s3.get()); + var s3:Struct3 = { y: 13 }; + eq(fieldNull + " 13", s3.get()); + var s3:Struct3 = { }; + eq(fieldNull + " " + fieldNull, s3.get()); + } + + function testOrder() { + var i = 0; + var s4:Struct4 = { y: i++, x: i++, z: i++ }; + eq("1 0 2", s4.get()); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4535.hx b/tests/unit/src/unit/issues/Issue4535.hx new file mode 100644 index 00000000..06a44ac5 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4535.hx @@ -0,0 +1,6 @@ +package unit.issues; + +@:someMeta(haxe.extern.macro.Type) +class Issue4535 extends Test { + +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4551.hx b/tests/unit/src/unit/issues/Issue4551.hx new file mode 100644 index 00000000..7b04f983 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4551.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue4551 extends Test { + #if js + function test() { + try { + try throw "yay!" catch (e:Dynamic) js.Lib.rethrow(); + } catch (e:Dynamic) { + eq(e, "yay!"); + } + } + #end +} diff --git a/tests/unit/src/unit/issues/Issue4557.hx b/tests/unit/src/unit/issues/Issue4557.hx new file mode 100644 index 00000000..4526d6be --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4557.hx @@ -0,0 +1,25 @@ +package unit.issues; + +private class Ghost { + public var value:String; + public function new(value) { + this.value = value; + } +} + +private class A { + public var ghost = new Ghost("booh!"); +} + +private class B extends A { } + +private class C extends B { + public function new() { } +} + +class Issue4557 extends Test { + function test() { + var c = new C(); + eq("booh!", c.ghost.value); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4564.hx.disabled b/tests/unit/src/unit/issues/Issue4564.hx.disabled new file mode 100644 index 00000000..59960150 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4564.hx.disabled @@ -0,0 +1,22 @@ +package unit.issues; + +class Issue4564 extends Test { + function test() { + inline function test(str:String, ?pos:haxe.PosInfos) { + eq(StringTools.urlDecode(StringTools.urlEncode(str)), str, pos); + } + eq(StringTools.urlEncode('me@home.com'), 'me%40home.com'); + test('me@home.com'); + eq(StringTools.urlEncode('Email Address'), 'Email%20Address'); + test('Email Address'); + eq(StringTools.urlEncode('Email Address!'), 'Email%20Address!'); + test('Email Address!'); + eq(StringTools.urlEncode('Email Address('), 'Email%20Address('); + test('Email Address('); + test('ção'); + test('a%a'); + test('a%20'); + test('a%20a'); + test('a%20a%'); + } +} diff --git a/tests/unit/src/unit/issues/Issue4578.hx b/tests/unit/src/unit/issues/Issue4578.hx new file mode 100644 index 00000000..f9d6c9d8 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4578.hx @@ -0,0 +1,43 @@ +package unit.issues; + +private class TList {} +private class TCons extends TList {} +private class TNil extends TList {} + +private enum Stack { + Nil: Stack; + Cons(x: X, xs: Stack): Stack>; +} + +private interface Instr { + function denote(s: Stack): Stack; +} + +private class IUnOp implements Instr,TCons> { + var f: X->Y; + + public function new(f) { + this.f = f; + } + + public function denote(s: Stack>): Stack> { + return switch(s) { + case Cons(x, s): + Cons(f(x), s); + } + } +} + +class Issue4578 extends Test { + function test() { + var i = new IUnOp(function(x) return x * 2); + var v = i.denote(Cons(10, Nil)); + eq(20, getHead(v)); + } + + static function getHead(s:Stack>):S { + return switch (s) { + case Cons(x, _): x; + } + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4579.hx b/tests/unit/src/unit/issues/Issue4579.hx new file mode 100644 index 00000000..5cb0528f --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4579.hx @@ -0,0 +1,20 @@ +package unit.issues; + +class Issue4579 extends Test { + #if js + function test() { + var stringMap1:Map = [ + 'string-key-1'=> 42 + ]; + + var stringMap2:Map = [ + 'string-key-1'=> 42, + 'string-key-2'=> {a:1} + ]; + + //count commas in toString() + eq(stringMap1.toString().split(',').length - 1, 0); + eq(stringMap2.toString().split(',').length - 1, 1); + } + #end +} diff --git a/tests/unit/src/unit/issues/Issue4581.hx b/tests/unit/src/unit/issues/Issue4581.hx new file mode 100644 index 00000000..43b18957 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4581.hx @@ -0,0 +1,11 @@ +package unit.issues; + +class Issue4581 extends unit.Test { + #if php + function test() { + var host = new sys.net.Host('google.com'); + var socket = new php.net.SslSocket(); + socket.connect(host, 443); + } + #end +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4591.hx b/tests/unit/src/unit/issues/Issue4591.hx new file mode 100644 index 00000000..904a56e6 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4591.hx @@ -0,0 +1,9 @@ +package unit.issues; + +class Issue4591 extends Test { + public function test() { + var x:C> = null; + } +} + +abstract C(T) from T to T { } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4592.hx b/tests/unit/src/unit/issues/Issue4592.hx new file mode 100644 index 00000000..b748f505 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4592.hx @@ -0,0 +1,15 @@ +package unit.issues; + +import haxe.Json; + +class Issue4592 extends unit.Test { + function test() { + var json = 'hello":"world"'; + try { + Json.parse(json); + t(false); + } catch(e:Dynamic) { + t(true); + } + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4593.hx b/tests/unit/src/unit/issues/Issue4593.hx new file mode 100644 index 00000000..1bcebf7d --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4593.hx @@ -0,0 +1,15 @@ +package unit.issues; + +class Issue4593 extends Test { + public function test() { + var a:Foo = 1; + var b = "value is " + a; + eq("value is INT 1", b); + } +} + +abstract Foo(Int) from Int { + @:to function print():String { + return 'INT $this'; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4608.hx b/tests/unit/src/unit/issues/Issue4608.hx new file mode 100644 index 00000000..1535d2ac --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4608.hx @@ -0,0 +1,15 @@ +package unit.issues; + +class Issue4608 extends Test { + function test() { + var s = "𩸽あëa"; + var b = false; + switch s { + case "𩸽あëa": + b = true; + case "a": + case _: + } + t(b); + } +} diff --git a/tests/unit/src/unit/issues/Issue4617.hx b/tests/unit/src/unit/issues/Issue4617.hx new file mode 100644 index 00000000..2b034a51 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4617.hx @@ -0,0 +1,42 @@ +package unit.issues; + +import haxe.ds.ObjectMap; + +private class CTest +{ + var map:ObjectMap>; + + public function new() + { + map = new ObjectMap(); + } + + public function set(k:T) + { + map.set(k, [true]); + } + + public function check(keys:Array) + { + var value; + + var s = ""; + for (k in keys) + { + value = map.get(k); + s += (value == null); + } + return s; + } +} + +class Issue4617 extends Test { + function test() { + var t:CTest<{test:Int}> = new CTest(); + + var key1 = { test:1 }; + var key2 = { test:2 }; + t.set(key1); + eq("falsetrue", t.check([key1, key2])); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4644.hx b/tests/unit/src/unit/issues/Issue4644.hx new file mode 100644 index 00000000..e212702a --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4644.hx @@ -0,0 +1,24 @@ +package unit.issues; + +class Issue4644 extends Test { + function test() { + #if js + var isHaxeError; + untyped __js__( + "try {{ + {0}; + }} catch (e) {{ + {1} = (e instanceof {2}); + }}", + throw (new js.Error() : Dynamic), + isHaxeError, + #if js_unflatten + __js__("js._Boot.HaxeError") + #else + __js__("js__$Boot_HaxeError") + #end + ); + f(isHaxeError); + #end + } +} diff --git a/tests/unit/src/unit/issues/Issue4653.hx b/tests/unit/src/unit/issues/Issue4653.hx new file mode 100644 index 00000000..e82ad02a --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4653.hx @@ -0,0 +1,29 @@ +package unit.issues; + +@:genericBuild(unit.issues.misc.Issue4653Macro.getType()) +private class C { } + +@:genericBuild(unit.issues.misc.Issue4653Macro.getStringType()) +private class C2 { } + +@:genericBuild(unit.issues.misc.Issue4666Macro.getType()) +private class C3 { } + +private class NotString { + static public function fromCharCode(i:Int) { + return String.fromCharCode(i); + } +} + +class Issue4653 extends Test { + function test() { + var s = C; + eq("A", s.fromCharCode(65)); + + var s2 = cast("foo", C2); + eq("FOO", s2.toUpperCase()); + + var d = C3; + // no idea how to test this properly + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4666.hx b/tests/unit/src/unit/issues/Issue4666.hx new file mode 100644 index 00000000..661670f1 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4666.hx @@ -0,0 +1,11 @@ +package unit.issues; + +@:genericBuild(unit.issues.misc.Issue4666Macro.getType()) +private class C { } + +class Issue4666 extends Test { + public function test() { + var c:C; + unit.HelperMacros.typedAs(c, (null:Dynamic)); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4667.hx b/tests/unit/src/unit/issues/Issue4667.hx new file mode 100644 index 00000000..aff3a3a6 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4667.hx @@ -0,0 +1,9 @@ +package unit.issues; + +class Issue4667 extends Test { + @:analyzer(no_fusion) + function test() { + var s = String; + eq("A", s.fromCharCode(65)); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4668.hx b/tests/unit/src/unit/issues/Issue4668.hx new file mode 100644 index 00000000..69665c28 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4668.hx @@ -0,0 +1,22 @@ +package unit.issues; + +private class GenericTestVoid>> { + public function new(){} + + @:generic + public function getInstance(arg:String):S { + return new S(arg); + } +} + +class Issue4668 extends Test { + function test() { + var gen = new GenericTest(); + var t = gen.getInstance("my ::template::"); + eq("my foo", t.execute({template: "foo"})); + + var gen = new GenericTest(); + var t = gen.getInstance("my string"); + eq("my string", t); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4672.hx b/tests/unit/src/unit/issues/Issue4672.hx new file mode 100644 index 00000000..46d08821 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4672.hx @@ -0,0 +1,24 @@ +package unit.issues; + +@:generic +private class C { + public function new() { } + public function test(s:S) { } +} + +@:generic +private class C2 { + public function new() { } + @:generic + public function test(s:S) { } +} + +class Issue4672 extends Test { + function test() { + var x = new C(); + x.test("foo"); + + var x = new C2(); + x.test("foo"); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4675.hx b/tests/unit/src/unit/issues/Issue4675.hx new file mode 100644 index 00000000..2a7f77fa --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4675.hx @@ -0,0 +1,14 @@ +package unit.issues; + +class Issue4675 extends Test { + function test() { + var m: Map = new Map(); + m.set("a", 1); + eq(1, someFunction(m)); + } + + public static function someFunction(arg: Dynamic) { + var map: Map = cast(arg, Map); + return map["a"]; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4677.hx b/tests/unit/src/unit/issues/Issue4677.hx new file mode 100644 index 00000000..95152c3b --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4677.hx @@ -0,0 +1,10 @@ +package unit.issues; + +class Issue4677 extends Test { + function test() { + var x = switch ("foo") { + case _1: _1; + } + eq("foo", x); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4681.hx b/tests/unit/src/unit/issues/Issue4681.hx new file mode 100644 index 00000000..0665b386 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4681.hx @@ -0,0 +1,115 @@ +package unit.issues; + +private abstract A(Int) { + public function new(i) { + this = i; + } + + public function get() { + return this; + } + + @:op(A + B) + static function add(x:A, x2:Int) { + return new A(x.get() + x2); + } + + @:op(A * B) + @:commutative + static function multiply(x:A, x2:Int) { + return x.get() * x2; + } +} + +class Issue4681 extends unit.Test { + + var array:Array
; + var field:A; + var array2:Array; + var field2:Int; + + function getArray() { + return array; + } + + function getArray2() { + return array2; + } + + function getThis(i:Int) { + return this; + } + + function getA() { + return new A(0); + } + + function setup() { + array = [new A(0)]; + field = new A(0); + array2 = [2]; + field2 = 2; + } + + public function testNormal() { + setup(); + var a = new A(0); + a += 1; + eq(1, a.get()); + } + + public function testNormal2() { + setup(); + var a = 2; + a *= new A(3); + eq(6, a); + } + + public function testArray() { + setup(); + var x = 0; + getArray()[x++] += 1; + eq(1, array[0].get()); + eq(1, x); + } + + public function testArray2() { + setup(); + var x = 0; + getArray2()[x++] *= new A(3); + eq(6, array2[0]); + eq(1, x); + } + + public function testField() { + setup(); + var x = 0; + getThis(x++).field += 1; + eq(1, x); + eq(1, field.get()); + } + + public function testField2() { + setup(); + var x = 0; + getThis(x++).field2 *= new A(3); + eq(1, x); + eq(6, field2); + } + + public function testNested() { + setup(); + var x = 0; + getArray()[(getArray()[x++] += 1).get() - 1] += 1; + eq(2, array[0].get()); + eq(1, x); + } + + public function testNested2() { + setup(); + var x = 0; + getArray2()[(getArray2()[x++] *= new A(3)) - 6] *= new A(3); + eq(18, array2[0]); + eq(1, x); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4690.hx b/tests/unit/src/unit/issues/Issue4690.hx new file mode 100644 index 00000000..9a41b7ee --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4690.hx @@ -0,0 +1,18 @@ +package unit.issues; + +private class Parent { + public var x:Int; + + public inline function new(x:Int) { + this.x = x; + } +} + +private class Child extends Parent { } + +class Issue4690 extends Test { + function test() { + var x = new Child(12); + eq(12, x.x); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4695.hx b/tests/unit/src/unit/issues/Issue4695.hx new file mode 100644 index 00000000..ddee85b8 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4695.hx @@ -0,0 +1,27 @@ +package unit.issues; + +class Issue4695 extends unit.Test { + + function eqCheck(v1:T, v2:T) { + return v1 == v2; + } + + public function testNull() { + f("" == null); + f(eqCheck("", null)); + #if !(cpp || flash9 || as3 || java || cs || hl) + f(false == null); + f(eqCheck(false, null)); + #end + } + + #if php + public function testNativeArray() { + var a1 = (untyped __php__)('array("f1" => 1, "f2" => 2, "f3" => 3)'); + var a2 = (untyped __php__)('array("f1" => true, "f2" => "2", "f3" => 3)'); + f(a1 == a2); + f(eqCheck(a1, a2)); + } + #end + +} diff --git a/tests/unit/src/unit/issues/Issue4702.hx b/tests/unit/src/unit/issues/Issue4702.hx new file mode 100644 index 00000000..0ab27f52 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4702.hx @@ -0,0 +1,12 @@ +package unit.issues; + +class Issue4702 extends Test { + function test() { + var t = 5; + var s = ""; + for (i in 0...t) { + s += "," + t--; + } + eq(",5,4,3,2,1", s); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4703.hx b/tests/unit/src/unit/issues/Issue4703.hx new file mode 100644 index 00000000..7a984d31 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4703.hx @@ -0,0 +1,25 @@ +package unit.issues; + +private class C { + public var x:Int; + public var y:Int; + + public inline function new(x:Int) { + this.x = 1; + } +} + +class Issue4703 extends Test { + + function test() { + var m = new C(12); + if (Math.random() > 0.5) { + m.y = 1; + } else { + m.y = 2; + } + useeeee(m.y); + } + + static function useeeee(d:Dynamic) { } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4723.hx b/tests/unit/src/unit/issues/Issue4723.hx new file mode 100644 index 00000000..f644bbac --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4723.hx @@ -0,0 +1,25 @@ +package unit.issues; + +import haxe.Json; + +class Issue4723 extends unit.Test { + function test() { + var t = new NoNormalMethods(); + eq(10, t.test()); + + var t = new HasNormalMethod(); + eq(10, t.test()); + eq(20, t.test2()); + } +} + +private class NoNormalMethods { + public function new() {} + public dynamic function test() return 10; +} + +private class HasNormalMethod { + public function new() {} + public dynamic function test() return 10; + public function test2() return 20; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4729.hx b/tests/unit/src/unit/issues/Issue4729.hx new file mode 100644 index 00000000..e2529899 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4729.hx @@ -0,0 +1,18 @@ +package unit.issues; + +class Issue4729 extends Test { + function test() { + var raw = "Hello world !!!"; + + var cursor:Int = 0; + inline function adv(char:String = " ", ?start:Int) { + cursor = raw.indexOf(char, start); + return cursor = (cursor > -1 ? cursor : raw.length) + char.length; + } + + var hello = raw.substring(0, adv()); + var world = raw.substring(cursor, adv(cursor)); + eq("Hello ", hello); + eq("world ", world); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4740.hx b/tests/unit/src/unit/issues/Issue4740.hx new file mode 100644 index 00000000..ee8b3179 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4740.hx @@ -0,0 +1,14 @@ +package unit.issues; + +private abstract Maybe(Null) from Null { + public inline function or(def:T):T { + return if (this != null) this else def; + } +} + +class Issue4740 extends Test { + function test() { + var session:Int = (null : Maybe>).or(0); + eq(0, session); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4743.hx b/tests/unit/src/unit/issues/Issue4743.hx new file mode 100644 index 00000000..2bad56bf --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4743.hx @@ -0,0 +1,20 @@ +package unit.issues; + +import unit.Test; + +/** + * ... + * @author + */ +class Issue4743 extends Test{ + static var i(default, set):Int = 0; + static function set_i(value) return i = value; + + static var j:Int = 0; + + public function test() { + i = j = 1; + eq(1, i); + eq(1, j); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4751.hx b/tests/unit/src/unit/issues/Issue4751.hx new file mode 100644 index 00000000..d5f230e4 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4751.hx @@ -0,0 +1,29 @@ +package unit.issues; + +import unit.Test; + +private abstract O(Int) { + public inline function get():Int return this; +} + +class Issue4751 extends Test{ + static function func(v:Float) {} + + function testNadako() { + var o:{?v:O} = {}; + func(if (cond()) o.v.get() else throw "oh"); + } + + function testGama() { + var dx:Float = Math.random(); + var dy:Float = Math.random(); + { + var t = dx; + dx = -dy; + dy = t; + }; + func(dy * 1.1); + } + + static function cond() return true; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4757.hx b/tests/unit/src/unit/issues/Issue4757.hx new file mode 100644 index 00000000..df7b6c50 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4757.hx @@ -0,0 +1,31 @@ +package unit.issues; + +class Issue4757 extends Test { + + function test() { + eq('ca: 2, cb: 1', cunion(1, 2)); + } + + function test2() { + var cb = getInt(); + var result = ""; + try { + throw 1; + } catch (ca:Int) { + var tmp = ca; + ca = cb; + cb = tmp; + result = 'ca: $ca, cb: $cb'; + } + eq('ca: 2, cb: 1', result); + } + + static function getInt() return 2; + + static function cunion(ca:Int, cb:Int) { + var tmp = ca; + ca = cb; + cb = tmp; + return 'ca: $ca, cb: $cb'; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4772.hx b/tests/unit/src/unit/issues/Issue4772.hx new file mode 100644 index 00000000..9478d3ed --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4772.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue4772 extends Test { + macro static function testMacro(){ + var a : Null = null; + var b = a && true; + return macro $v{b}; + } + + function test() { + f(testMacro()); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4777.hx b/tests/unit/src/unit/issues/Issue4777.hx new file mode 100644 index 00000000..78758683 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4777.hx @@ -0,0 +1,11 @@ +package unit.issues; + +private abstract A(String) from String {} + +class Issue4777 extends Test { + function test() { + var map:Map = new Map(); + map["foo"] = "bar"; + eq("bar", map["foo"]); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4798.hx b/tests/unit/src/unit/issues/Issue4798.hx new file mode 100644 index 00000000..a2ab7344 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4798.hx @@ -0,0 +1,18 @@ +package unit.issues; + +private abstract Lazy(Void->T) { + inline function new(r) this = r; + + @:to public inline function get():T + return (this)(); + + @:from static inline function ofConst(c:T) + return new Lazy(function () return c); +} + +class Issue4798 extends Test { + public static var INIT: Lazy = 'b'; + function test() { + eq("b", (INIT: String)); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4809.hx b/tests/unit/src/unit/issues/Issue4809.hx new file mode 100644 index 00000000..67011e4f --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4809.hx @@ -0,0 +1,14 @@ +package unit.issues; + +private abstract Iter(Iterator) from Iterator to Iterator {} + +class Issue4809 extends Test { + function test() { + var list:Iter = [1, 2, 3].iterator(); + var acc = ""; + for (item in list) { + acc += item; + } + eq("123", acc); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4810.hx b/tests/unit/src/unit/issues/Issue4810.hx new file mode 100644 index 00000000..ce231f20 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4810.hx @@ -0,0 +1,10 @@ +package unit.issues; + +class Issue4810 extends Test { + static public var DEFAULT(get, null): Bool; + static function get_DEFAULT() + return true; + function test() { + eq(true, DEFAULT); + } +} diff --git a/tests/unit/src/unit/issues/Issue4819.hx b/tests/unit/src/unit/issues/Issue4819.hx new file mode 100644 index 00000000..52bc99d3 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4819.hx @@ -0,0 +1,31 @@ +package unit.issues; + +@:enum +private abstract Enum1(Int) from Int to Int { + var AA = 16; +} + +@:enum +private abstract Enum2(Int) from Int to Int { + var BShl = Enum1.AA << 1; + var BShr = Enum1.AA >> 1; + var BUShr = Enum1.AA >>> 1; + var BOr = Enum1.AA | 1; + var BAnd = Enum1.AA & 1; + var BXor = Enum1.AA ^ 1; + var BNeg = -Enum1.AA; + var BNegBits = ~Enum1.AA; +} + +class Issue4819 extends Test { + function test() { + eq(32, BShl); + eq(8, BShr); + eq(8, BUShr); + eq(17, BOr); + eq(0, BAnd); + eq(17, BXor); + eq(-16, BNeg); + eq(-17, BNegBits); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4841.hx b/tests/unit/src/unit/issues/Issue4841.hx new file mode 100644 index 00000000..ce1d0c0a --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4841.hx @@ -0,0 +1,10 @@ +package unit.issues; + +private abstract NullAbstract(Null) { } + +class Issue4841 extends Test { + function test() { + var null64:NullAbstract = null; + t(null64 == null); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4842.hx b/tests/unit/src/unit/issues/Issue4842.hx new file mode 100644 index 00000000..aba4e852 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4842.hx @@ -0,0 +1,16 @@ +package unit.issues; + +class Issue4842 extends Test { + function test() { + var i:Int = 0; + f(isNull(i)); + var u:UInt = 0; + f(isNull(u)); + var i64:haxe.Int64 = haxe.Int64.make(0, 0); + f(isNull(i64)); + } + + static inline function isNull(maybeNull:Null):Bool return { + maybeNull == null; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4843.hx b/tests/unit/src/unit/issues/Issue4843.hx new file mode 100644 index 00000000..728ec385 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4843.hx @@ -0,0 +1,13 @@ +package unit.issues; + +private abstract A({}) from {} { + @:from static function fromB(b:{a:Int}):A { + return null; + } +} + +class Issue4843 extends Test { + function test() { + var a:A = {}; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4862.hx b/tests/unit/src/unit/issues/Issue4862.hx new file mode 100644 index 00000000..3a51d043 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4862.hx @@ -0,0 +1,28 @@ +package unit.issues; + +#if js +@:native("__issue4862__http_status") +@:enum private extern abstract HttpStatus(Int) to Int { + var Ok; + var NotFound; + + static function __init__():Void { + untyped __js__("var __issue4862__http_status = {Ok: 200, NotFound: 404};"); + } +} +#end + +class Issue4862 extends Test { + #if js + function test() { + var a = Ok; + eq(200, a); + var b = HttpStatus.NotFound; + eq(404, b); + t(switch (a) { case HttpStatus.Ok: true; default: false; }); + t(switch (b) { case HttpStatus.NotFound: true; default: false; }); + t(switch (a) { case Ok: true; default: false; }); + t(switch (b) { case NotFound: true; default: false; }); + } + #end +} diff --git a/tests/unit/src/unit/issues/Issue4867.hx b/tests/unit/src/unit/issues/Issue4867.hx new file mode 100644 index 00000000..182b5e3c --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4867.hx @@ -0,0 +1,21 @@ +package unit.issues; + +@:enum +private abstract EnumAbstract(Int) to Int { + var a = 0; + var b = 1; + + @:from + public static function fromString(s:String):EnumAbstract { + if (s == "b") + return b; + return a; + } +} + +class Issue4867 extends Test { + function test() { + var b:EnumAbstract = "b"; + eq(1, b); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4870.hx b/tests/unit/src/unit/issues/Issue4870.hx new file mode 100644 index 00000000..d5711657 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4870.hx @@ -0,0 +1,11 @@ +package unit.issues; + +class Issue4870 extends Test { + @:keep static inline var VALUE:UInt = 0x9747b28c; + @:keep static var VALUE2:UInt = 0x9747b28c; + function test() { + t(VALUE == 0x9747b28c); + t(VALUE2 > 0); + } +} + diff --git a/tests/unit/src/unit/issues/Issue4878.hx b/tests/unit/src/unit/issues/Issue4878.hx new file mode 100644 index 00000000..6f0d2829 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4878.hx @@ -0,0 +1,24 @@ +package unit.issues; +#if java +import java.vm.Thread; +import java.vm.Mutex; +#end + +class Issue4878 extends Test { + function test() { +#if java + var mutex = new Mutex(); + var thread = Thread.create(function() { + mutex.acquire(); + mutex.acquire(); + mutex.release(); + Sys.sleep(.2); + mutex.release(); + }); + Sys.sleep(0.05); + f(mutex.tryAcquire()); + Sys.sleep(.3); + t(mutex.tryAcquire()); +#end + } +} diff --git a/tests/unit/src/unit/issues/Issue4885.hx b/tests/unit/src/unit/issues/Issue4885.hx new file mode 100644 index 00000000..76c5bc67 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4885.hx @@ -0,0 +1,23 @@ +package unit.issues; + +private class Context { + + public var name:String; + + public function new(n:String):Void { + name = n; + } + +} + +class Issue4885 extends Test { + function test() { + var + raw:String = "My name is ::name::.", + context:Context = new Context("Joan"), + template:haxe.Template = new haxe.Template(raw), + output:String = template.execute(context) + ; + eq("My name is Joan.", output); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4886.hx b/tests/unit/src/unit/issues/Issue4886.hx new file mode 100644 index 00000000..8817bb14 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4886.hx @@ -0,0 +1,22 @@ +package unit.issues; + +private class C { + @:extern inline function get() { + var intStruct = { i: 0 }; + return intStruct; + } + + var a = [get(), get(), get()]; + + public var b:Bool; + public function new() { + b = a[0] == a[1]; + } +} + +class Issue4886 extends Test { + function test() { + var c = new C(); + f(c.b); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4889.hx b/tests/unit/src/unit/issues/Issue4889.hx new file mode 100644 index 00000000..a62891d2 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4889.hx @@ -0,0 +1,12 @@ +package unit.issues; + +class Issue4889 extends Test { + function test() { + var f = getFloat(); + t(!(f > Math.NaN)); + } + + static function getFloat() { + return 1.0; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4904.hx b/tests/unit/src/unit/issues/Issue4904.hx new file mode 100644 index 00000000..5a24ad1f --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4904.hx @@ -0,0 +1,22 @@ +package unit.issues; + +class Issue4904 extends Test { + function test() { + eq(("A" : TestAbstract), TestAbstract.A); + eq(("B" : TestAbstract), TestAbstract.B); + eq((("C" : TestAbstract) : Int), -1); + } +} + +@:enum +abstract TestAbstract(Int) to Int { + var A = 0; + var B = 1; + private var Invalid = -1; + + @:from public static function fromString(s:String) { + if (s == "A") return A; + if (s == "B") return B; + return Invalid; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4910.hx b/tests/unit/src/unit/issues/Issue4910.hx new file mode 100644 index 00000000..37cc8201 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4910.hx @@ -0,0 +1,27 @@ +package unit.issues; + +private class C { + public static function f(i:Int){ return "f"; } +} + +private typedef TD = { + function f(v:Int):String; +} + +@:analyzer(no_fusion) +class Issue4910 extends Test { + function test() { + var t:TD = C; + eq("f", t.f(1)); + eq("f", tf(C)); + eq("f", tfd(C)); + } + + static function tf(t:TD){ + return t.f(1); + } + + static function tfd(t:Dynamic){ + return t.f(1); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4917.hx b/tests/unit/src/unit/issues/Issue4917.hx new file mode 100644 index 00000000..4d188a14 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4917.hx @@ -0,0 +1,25 @@ +package unit.issues; + +class Issue4917 extends Test { + static function throwing(expected:Dynamic):Bool { + switch(Type.typeof(expected)) { + case TClass(c): + Std.string(expected); + return true; + case TEnum(e) : + Std.string(expected); + return true; + case _ : + throw "Unable to compare two unknown types"; + } + throw "Unable to compare values: " + expected; + } + + function test() { + t(throwing(new C())); + } +} + +private class C { + public function new() { } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4918.hx b/tests/unit/src/unit/issues/Issue4918.hx new file mode 100644 index 00000000..7c4bfe27 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4918.hx @@ -0,0 +1,15 @@ +package unit.issues; + +class Issue4918 extends Test { + static var p:{ ?opt:Bool } = { opt: true }; + function test() { + var hasOpt = false, minParams = 0; + if( p.opt ) + hasOpt = true; + else + minParams++; + var f = function() { + trace(minParams); + }; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4940.hx b/tests/unit/src/unit/issues/Issue4940.hx new file mode 100644 index 00000000..15168e1d --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4940.hx @@ -0,0 +1,39 @@ +package unit.issues; + +private enum Kind { + KA; + KB; +} + +private class Base { + public function new() {} +} + +private class A extends Base {} +private class B extends Base {} + +@:enum +private abstract K(Int) { + var grav = 19; + var other = 2; +} + +class Issue4940 extends Test { + function test() { + var kind = KA; + var base = switch (kind) { + case KA: new A(); + case KB: new B(); + } + unit.HelperMacros.typedAs(new Base(), base); + } + + function testResolutionOrder() { + var grav = "string"; + var x = switch (other) { + case grav: 1; + case other: 2; + } + eq(2, x); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4949.hx b/tests/unit/src/unit/issues/Issue4949.hx new file mode 100644 index 00000000..d85a04a1 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4949.hx @@ -0,0 +1,20 @@ +package unit.issues; + +class Issue4949 extends Test { + var gems = [1,2,3]; + + public function foo() { + function onEnd(b) { + next(b); + } + var f = function() { + var ids = [for (i in 0...gems.length) if(gems[i]> 5) i]; // Main has no field push + } + } + + function next(d) { } + + function test() { + foo(); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4953.hx b/tests/unit/src/unit/issues/Issue4953.hx new file mode 100644 index 00000000..7be6ac34 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4953.hx @@ -0,0 +1,21 @@ +package unit.issues; + +private enum E { + Foo( v : Int ); + Other; +} + +class Issue4953 extends Test { + + function foo() { + return Foo; + } + + function test() { + switch( foo()(5) ) { + case Foo(v): eq(v,5); + default: t(false); + } + } + +} diff --git a/tests/unit/src/unit/issues/Issue4962.hx b/tests/unit/src/unit/issues/Issue4962.hx new file mode 100644 index 00000000..56540129 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4962.hx @@ -0,0 +1,15 @@ +package unit.issues; + +private class C { + public function new() { } + @:keep function toString():String return toString(); +} + +class Issue4962 extends Test { + function test() { + var int:Dynamic = Int; + f(Std.is(new C(), int)); + + f(Std.is(new C(), Int)); + } +} diff --git a/tests/unit/src/unit/issues/Issue4966.hx b/tests/unit/src/unit/issues/Issue4966.hx new file mode 100644 index 00000000..361293c7 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4966.hx @@ -0,0 +1,37 @@ +package unit.issues; + +import haxe.ds.Either; + +private abstract PhysicalType(Either, Enum>) { + + public function new(v) { + this = v; + } + + public function toString() { + return switch this { + case Left(c): Type.getClassName(c); + case Right(e): Type.getEnumName(e); + } + } + + static public function fromClass(c:Class) { + return new PhysicalType(Left(c)); + } + + static public function fromEnum(en:Enum) { + return new PhysicalType(Right(en)); + } +} + +class Issue4966 extends Test { + + function test() { + eq("type: unit.Test", throws(PhysicalType.fromClass(Test))); + eq("type: haxe.macro.ExprDef", throws(PhysicalType.fromEnum(haxe.macro.Expr.ExprDef))); + } + + function throws(t:PhysicalType) { + return 'type: $t'; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4969.hx b/tests/unit/src/unit/issues/Issue4969.hx new file mode 100644 index 00000000..8e574443 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4969.hx @@ -0,0 +1,33 @@ +package unit.issues; + +class Issue4969 extends Test { + + @:keep + static function test1() { + var __return = function(x:Dynamic) { return 1; } + __return(throw null); // Cannot use this expression as value + } + + @:keep + static function test2() { + var __return = function(x:Dynamic) { return 1; } + __return(return null); // Cannot use this expression as value + return null; + } + + @:keep + static function test3() { + var __return = function(x:Dynamic) { return 1; } + while (true) { + __return(break); // Cannot use this expression as value + } + } + + @:keep + static function test4() { + var __return = function(x:Dynamic) { return 1; } + while (true) { + __return(continue); // Cannot use this expression as value + } + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4973.hx b/tests/unit/src/unit/issues/Issue4973.hx new file mode 100644 index 00000000..1672296f --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4973.hx @@ -0,0 +1,11 @@ +package unit.issues; + +class Issue4973 extends Test { + #if php + function test() { + try sys.io.File.getContent("not-existant") + catch(exc:php.Exception) t(untyped __php__("{0} instanceof \\Exception", exc)) + catch(exc:Dynamic) t(untyped __php__("{0} instanceof Exception", exc)); + } + #end +} diff --git a/tests/unit/src/unit/issues/Issue4977.hx b/tests/unit/src/unit/issues/Issue4977.hx new file mode 100644 index 00000000..3b6e7170 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4977.hx @@ -0,0 +1,31 @@ +package unit.issues; + +private abstract Progress(Int) to Int { + public var isEof(get, never):Bool; + + inline function get_isEof() + return this < 0; + + public var bytes(get, never):Int; + + inline function get_bytes():Int + return (this < 0) ? 0 : this; + + inline function new(v) this = v; + + static public inline function by(amount:Int) + return new Progress(amount); + + @:to inline function toBool():Bool + return this > 0; + + static public inline var EOF:Progress = new Progress(-1); + static public inline var NONE:Progress = new Progress(0); +} + +class Issue4977 extends Test { + function test() { + eq(-1, Progress.EOF); + eq(0, Progress.NONE); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4979.hx b/tests/unit/src/unit/issues/Issue4979.hx new file mode 100644 index 00000000..27873c57 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4979.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue4979 extends Test { + function test() { + var vec = new haxe.ds.Vector(10); + var arr = run(vec.toArray()); + eq(arr.length, 10); + } + + static public function run(items:Array) { + return items; + } +} diff --git a/tests/unit/src/unit/issues/Issue4986.hx b/tests/unit/src/unit/issues/Issue4986.hx new file mode 100644 index 00000000..70f21621 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4986.hx @@ -0,0 +1,12 @@ +package unit.issues; + +class Issue4986 extends Test { + function test() { + try { + var v = new haxe.ds.Vector>(1); + foo(v[0].length); + } catch (e:Dynamic) {} + } + + function foo(_) {} +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4987.hx b/tests/unit/src/unit/issues/Issue4987.hx new file mode 100644 index 00000000..386b78d4 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4987.hx @@ -0,0 +1,18 @@ +package unit.issues; + +class Issue4987 extends Test implements ISetter implements ISetter2 { + public var property(default, set):Int; + function set_property(i) return 0; + + function test() { + property = 0; + } +} + +interface ISetter { + var property(default, set):Int; +} + +interface ISetter2 { + var property(default, set):Int; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue4988.hx b/tests/unit/src/unit/issues/Issue4988.hx new file mode 100644 index 00000000..05e80fac --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4988.hx @@ -0,0 +1,20 @@ +package unit.issues; + +class Issue4988 extends Test { + static var value:Dynamic; + static var actuallyRunCode = false; + + function test() { + if (actuallyRunCode) { + try { + var d:{i:Null} = null; + value = (d.i > 0); + t(false); + } catch(e:Dynamic) { + t(true); + } + } else { + t(true); + } + } +} diff --git a/tests/unit/src/unit/issues/Issue4997.hx b/tests/unit/src/unit/issues/Issue4997.hx new file mode 100644 index 00000000..c12b3894 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue4997.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue4997 extends Test { + function test() { + var b = true; + if (b) { + return; + } + + var a = []; + a[0] = true; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5000.hx b/tests/unit/src/unit/issues/Issue5000.hx new file mode 100644 index 00000000..02d54815 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5000.hx @@ -0,0 +1,8 @@ +package unit.issues; + +class Issue5000 extends Test { + function test() { + var a = {"a\n b": 1}; + eq(1, Reflect.field(a, "a\n b")); + } +} diff --git a/tests/unit/src/unit/issues/Issue5015.hx b/tests/unit/src/unit/issues/Issue5015.hx new file mode 100644 index 00000000..6aebd627 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5015.hx @@ -0,0 +1,9 @@ +package unit.issues; + +using haxe.Json; + +class Issue5015 extends Test { + function test() { + eq('{}'.parse().stringify(), '{}'); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5016.hx b/tests/unit/src/unit/issues/Issue5016.hx new file mode 100644 index 00000000..f11376bd --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5016.hx @@ -0,0 +1,11 @@ +package unit.issues; + +class Issue5016 extends Test { + function test() { + #if !cpp + var obj = {abc:null, def:1} + Reflect.deleteField(obj, 'def'); + f(Reflect.hasField(obj, 'def')); + #end + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5025.hx b/tests/unit/src/unit/issues/Issue5025.hx new file mode 100644 index 00000000..ce169156 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5025.hx @@ -0,0 +1,22 @@ +package unit.issues; + +class Issue5025 extends Test { + function test() { + // nothing to do here, we just want to see if the switch (null) compiles + } + + function shouldCompile() { + #if !(java || cs || as3 || lua) + try { + switch (null) { + case Value(i): + trace(i); + } + } catch (e:Dynamic) {} + #end + } +} + +enum SomeEnum { + Value(i:Int); +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5027.hx b/tests/unit/src/unit/issues/Issue5027.hx new file mode 100644 index 00000000..0378b8a4 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5027.hx @@ -0,0 +1,8 @@ +package unit.issues; + +class Issue5027 extends Test { + function test() { + var f:Void->Void = function() return null; + f(); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5028.hx b/tests/unit/src/unit/issues/Issue5028.hx new file mode 100644 index 00000000..e7b29369 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5028.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue5028 extends Test { + var data:Data = { f: -1 }; + + function test() { + t(Math.random() > data.f); + } +} + +typedef Data = { + ?f:Float +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5029.hx b/tests/unit/src/unit/issues/Issue5029.hx new file mode 100644 index 00000000..0a3b25f6 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5029.hx @@ -0,0 +1,10 @@ +package unit.issues; + +class Issue5029 extends Test { + function test() { + var template = ""; + var f = function() template = "some"; + f(); + eq("some", template); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5030.hx b/tests/unit/src/unit/issues/Issue5030.hx new file mode 100644 index 00000000..3b5b343e --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5030.hx @@ -0,0 +1,23 @@ +package unit.issues; + +class Issue5030 extends Test { + function test() { + t(isX()); + } + + @:analyzer(no_const_propagation) + function isX() { + var input:Input = { axis: X }; + var b:Bool = true; + return (input.axis == X) ? b: false; + } +} + +enum XY { + X; + Y; +} + +typedef Input = { + var axis:XY; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5031.hx b/tests/unit/src/unit/issues/Issue5031.hx new file mode 100644 index 00000000..3763e90f --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5031.hx @@ -0,0 +1,38 @@ +package unit.issues; + +private enum E { + A; + B; +} + +private enum MPEGVersion { + MPEG_Reserved; +} + +private typedef MP3Header = { + public var version : MPEGVersion; +} + +class Issue5031 extends Test { + static function getE() { + return A; + } + + function testHscriptProblem() { + while (true) { + switch (getE()) { + case A: + break; + case B: + } + } + } + + function isInvalidFrameHeader(hdr:MP3Header) { + return hdr.version != MPEG_Reserved; + } + + function testFormatProblem() { + f(isInvalidFrameHeader({version: MPEG_Reserved})); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5044.hx b/tests/unit/src/unit/issues/Issue5044.hx new file mode 100644 index 00000000..c775d464 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5044.hx @@ -0,0 +1,14 @@ +package unit.issues; + +class Issue5044 extends Test { + function test() { + var i = Int(5); + eq(5, switch (i) { + case Int(v): v; + }); + } +} + +enum TokenDef { + Int(v:Int); +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5053.hx b/tests/unit/src/unit/issues/Issue5053.hx new file mode 100644 index 00000000..24a1bc90 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5053.hx @@ -0,0 +1,20 @@ +package unit.issues; + +private class C { + public var field:String; + + public function new(b:Bool) { + if (b) { + field = ""; + } + } +} + +class Issue5053 extends unit.Test { + function test() { + var c = new C(true); + eq("", c.field); + var c2 = new C(false); + eq(null, c2.field); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5064.hx b/tests/unit/src/unit/issues/Issue5064.hx new file mode 100644 index 00000000..0e186380 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5064.hx @@ -0,0 +1,24 @@ +package unit.issues; + +import haxe.ds.Option; + +private enum GADT { + AnInt(p: Bool): GADT; + AString(p: Bool): GADT; +} + +class Issue5064 extends Test { + public static function broken(gadt: GADT): Option { + return switch gadt { + case AnInt(p): if (p) Some(1) else None; + case AString(p): if (p) Some("a") else None; + }; + } + + function test() { + t(Type.enumEq(Some(1), broken(AnInt(true)))); + t(None == broken(AnInt(false))); + t(Type.enumEq(Some("a"), broken(AString(true)))); + t(None == broken(AString(false))); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5073.hx b/tests/unit/src/unit/issues/Issue5073.hx new file mode 100644 index 00000000..6662458e --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5073.hx @@ -0,0 +1,15 @@ +package unit.issues; + +class Issue5073 extends Test { + function test() { + function dontRunMe() { + var done = false; + while (!done) { + trace(Math.random() - 1); + } + } + pretendToRun(dontRunMe); + } + + static function pretendToRun(f) { } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5078.hx b/tests/unit/src/unit/issues/Issue5078.hx new file mode 100644 index 00000000..b3a1c007 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5078.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue5078 extends Test { + #if !(js || php || lua) + static function getToLower() return "ABC".toLowerCase; + #end + + function test() { + #if !(js || php || lua) + eq(getToLower()(), "abc"); + #end + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5082.hx b/tests/unit/src/unit/issues/Issue5082.hx new file mode 100644 index 00000000..4b5f4a27 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5082.hx @@ -0,0 +1,37 @@ +package unit.issues; + +private enum E { + Tiles(x:Dynamic); + TileInstances(x:Dynamic); +} + +@:keep +private class Content { + public var find:String -> Content; + public function new() { + find = function(s:String) return this; + } + + public function spectrum(s:String, d:Dynamic) { + return this; + } + + public function closest(s:String) { + return this; + } + + public function css(s:Dynamic) { + return "foo"; + } +} + +class Issue5082 extends unit.Test { + function test() { + var l = {data: Tiles([]), props:{color:""}, idToIndex: null}; + var content = new Content(); + var x = (untyped content.find("[name=color]")).spectrum("set", toColor(l.props.color)).closest(".item").css( { display : l.idToIndex == null && !l.data.match(Tiles(_) | TileInstances(_)) ? "" : "none" } ); + eq("foo", x); + } + + static function toColor(d:Dynamic) return d; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5086.hx b/tests/unit/src/unit/issues/Issue5086.hx new file mode 100644 index 00000000..3932fec1 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5086.hx @@ -0,0 +1,26 @@ +package unit.issues; + +private class StringOutput extends haxe.io.Output { + var buf:StringBuf; + + public function new() { + buf = new StringBuf(); + } + + override public function writeByte( c : Int ) : Void { + buf.addChar(c); + } + + public function toString() : String { + return buf.toString(); + } +} + +class Issue5086 extends Test { + function test() { + var so = new StringOutput(); + var input = "Hello. I think Haxe is great!"; + so.writeString(input); + eq(so.toString(), input); + } +} diff --git a/tests/unit/src/unit/issues/Issue5090.hx b/tests/unit/src/unit/issues/Issue5090.hx new file mode 100644 index 00000000..7c348486 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5090.hx @@ -0,0 +1,8 @@ +package unit.issues; + +class Issue5090 extends Test { + public function test() { + eq(haxe.crypto.Sha1.encode('olá'), '3e16889d494632f3c528fb3a3756435f8aa88788'); + eq(haxe.crypto.Sha1.encode('𝄞'), 'e4a5ca681e4b2fa112844dca54e7b868086aee0b'); + } +} diff --git a/tests/unit/src/unit/issues/Issue5108.hx b/tests/unit/src/unit/issues/Issue5108.hx new file mode 100644 index 00000000..b19e2c56 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5108.hx @@ -0,0 +1,20 @@ +package unit.issues; + +class Issue5108 extends Test { + function test() { + // nothing to do here + } +} + +class Signal implements ISignal { + public function add(listener:Void->Void):Void {} + public function destroy():Void {} +} + +interface ISignal extends IDestroyable2 { + public function add(listener:Void->Void):Void; +} + +interface IDestroyable2 { + public function destroy():Void; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5110.hx.disabled b/tests/unit/src/unit/issues/Issue5110.hx.disabled new file mode 100644 index 00000000..18aef9d6 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5110.hx.disabled @@ -0,0 +1,18 @@ +package unit.issues; + +class Issue5110 extends Test { + public function test() { +#if cs + var lst:List = cast new cs.system.collections.generic.List_1(); + eq(lst.get_Item(0), 0); +#end + } +} + +#if cs +private abstract List(cs.system.collections.generic.List_1) { + public function get_Item(n:Int):T { + return this.get_Item(n); + } +} +#end diff --git a/tests/unit/src/unit/issues/Issue5113.hx b/tests/unit/src/unit/issues/Issue5113.hx new file mode 100644 index 00000000..265c86e7 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5113.hx @@ -0,0 +1,41 @@ +package unit.issues; + +private class Node { + + var parentNode:Node; + + public function new() { } + + public function getParent():Node { + return parentNode; + } + + public function addChild(node:Node) { + node.parentNode = this; + } +} + + +private class Element extends Node { + + public var children:Array = []; + + public function new() { + super(); + } + + override public function getParent():Element { + return cast parentNode; + } +} + +class Issue5113 extends unit.Test { + function test() { + var childEl = new Element(); + var parentEl = new Element(); + var parentNode = new Node(); + + parentEl.addChild(childEl); + eq(0, childEl.getParent().children.length); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5124.hx b/tests/unit/src/unit/issues/Issue5124.hx new file mode 100644 index 00000000..7d12e5f4 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5124.hx @@ -0,0 +1,24 @@ +package unit.issues; + +class Issue5124 extends Test { + static var dblValue = 1.665; + function test() + { + run((1.5555:R)); + eq((1.5555:R), 1); + run((dblValue:R)); + eq((dblValue:R), 1); + } + + dynamic function run(t:Dynamic) { + eq(t,1); + } +} + +private abstract R(Float) to Float { + private inline function new(v:Float) + this = Std.int(v); + @:from + public static inline function fromFloat(v:Float):R + return new R(v); +} diff --git a/tests/unit/src/unit/issues/Issue5135.hx b/tests/unit/src/unit/issues/Issue5135.hx new file mode 100644 index 00000000..0a8e18f8 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5135.hx @@ -0,0 +1,21 @@ +package unit.issues; + +class Issue5135 extends unit.Test { + var obj2:Object2; + function test() { + try { + obj2 = cast(new Object1(), Object2); + t(false); + } catch(e:Dynamic) { + t(true); + } + } +} + +private class Object1 { + public function new() {} +} + +private class Object2 { + public function new() {} +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5162.hx b/tests/unit/src/unit/issues/Issue5162.hx new file mode 100644 index 00000000..1d5845ea --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5162.hx @@ -0,0 +1,25 @@ +package unit.issues; + +import haxe.macro.Expr; + +class Issue5162 extends unit.Test { + function test() { + var tp = { + name: "Array", + pack: [], + sub: null + } + var ct = macro : $tp; + t(ct.match(TPath({params: [TPType(TPath({name: "Int"}))]}))); + + var tp = { + name: "Map", + pack: [], + sub: null + } + var param1 = macro : Int; + var param2 = macro : String; + var ct = macro : $tp<$param1, $param2>; + t(ct.match(TPath({params: [TPType(TPath({name: "Int"})), TPType(TPath({name: "String"}))]}))); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5179.hx b/tests/unit/src/unit/issues/Issue5179.hx new file mode 100644 index 00000000..7a3e3a37 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5179.hx @@ -0,0 +1,21 @@ +package unit.issues; + +@:enum +private abstract TP_KIND(Int) { + + public function new () this = 0; + + var TP_REF = 0; + var TP_V08 = 1; + var TP_V16 = 2; + var TP_V32 = 3; + var TP_V64 = 4; + var TP_UNKNOWN = 5; + var ___ = -1; +} + +class Issue5179 extends unit.Test { + function test() { + + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5184.hx b/tests/unit/src/unit/issues/Issue5184.hx new file mode 100644 index 00000000..121ccaf8 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5184.hx @@ -0,0 +1,38 @@ +package unit.issues; + +#if !flash + +class Issue5184 extends unit.Test { } + +#else + +import flash.display.StageQuality; + +class Issue5184 extends unit.Test { + function test() { + eq(0, getQ(BEST)); + eq(1, getQ(HIGH)); + //eq(2, getQ(HIGH_16X16)); + //eq(3, getQ(HIGH_16X16_LINEAR)); + //eq(4, getQ(HIGH_8X8)); + //eq(5, getQ(HIGH_8X8_LINEAR)); + eq(6, getQ(LOW)); + eq(7, getQ(MEDIUM)); + } + + function getQ(q:flash.display.StageQuality) { + return switch (q) { + case BEST: 0; + case HIGH: 1; + // case HIGH_16X16: 2; + // case HIGH_16X16_LINEAR: 3; + // case HIGH_8X8: 4; + // case HIGH_8X8_LINEAR: 5; + case LOW: 6; + case MEDIUM: 7; + case _: throw "unknown value"; + } + } +} + +#end \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5192.hx b/tests/unit/src/unit/issues/Issue5192.hx new file mode 100644 index 00000000..ca68ee42 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5192.hx @@ -0,0 +1,9 @@ +package unit.issues; +import unit.issues.Issue5192_Test; + +class Issue5192 extends Test { + public function test() { + var x:String = Issue5192_Test_Abstract.doSomething(); + eq(x,null); + } +} diff --git a/tests/unit/src/unit/issues/Issue5192_Test.hx b/tests/unit/src/unit/issues/Issue5192_Test.hx new file mode 100644 index 00000000..8c5636fb --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5192_Test.hx @@ -0,0 +1,10 @@ +package unit.issues; + +class Issue5192_Test extends Test { +} + +abstract Issue5192_Test_Abstract(Int) { + @:generic public static function doSomething():T { + return cast null; + } +} diff --git a/tests/unit/src/unit/issues/Issue5218.hx b/tests/unit/src/unit/issues/Issue5218.hx new file mode 100644 index 00000000..f9566498 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5218.hx @@ -0,0 +1,12 @@ +package unit.issues; + +class Issue5218 extends unit.Test { + function test() { + var a = [["a"],["b"]]; + var x = a.shift(); + a[0].push(x[0]); + eq(2, a[0].length); + eq("b", a[0][0]); + eq("a", a[0][1]); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5221.hx b/tests/unit/src/unit/issues/Issue5221.hx new file mode 100644 index 00000000..4967e92b --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5221.hx @@ -0,0 +1,11 @@ +package unit.issues; + +class Issue5221 extends unit.Test { + static var ip(default,default):Int = -1; + function test() { + var ip2 = ip; + ip2 = ip = 0; + eq(0, ip2); + eq(0, ip); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5226.hx b/tests/unit/src/unit/issues/Issue5226.hx new file mode 100644 index 00000000..e36b1584 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5226.hx @@ -0,0 +1,33 @@ +package unit.issues; + +class Issue5226 extends unit.Test { + function test() { + var from:HasFrom = 10; + eq("20", from.get()); + var f:HasField = {}; + f.hasFrom = 20; + eq("30", f.hasFrom.get()); + } +} + +private abstract HasFrom(String) from String { + @:from public static function fromInt(i:Int):HasFrom { + return (i + 10) + ''; + } + + public function get() { + return this; + } +} + +private abstract HasField(Dynamic) from Dynamic { + public var hasFrom(get,set):HasFrom; + + private function get_hasFrom():HasFrom { + return this.hasFrom; + } + + private function set_hasFrom(f:HasFrom):HasFrom { + return this.hasFrom = f; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5231.hx b/tests/unit/src/unit/issues/Issue5231.hx new file mode 100644 index 00000000..9bd1c3c3 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5231.hx @@ -0,0 +1,25 @@ +package unit.issues; +using unit.issues.Issue5231; + +class Issue5231 extends Test { + public function test() { + t(getTest().doesItWork(getTest())); + } + + public static function getTest():Test1 { + return cast {}; + } +} + +private abstract Test2(Dynamic) { +} + +@:forward +private abstract Test1(Test2) { +} + +class I5231_Using { + public static function doesItWork(t:Test1, t2:Test1):Bool { + return true; + } +} diff --git a/tests/unit/src/unit/issues/Issue5234.hx b/tests/unit/src/unit/issues/Issue5234.hx new file mode 100644 index 00000000..3bdb008c --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5234.hx @@ -0,0 +1,15 @@ +package unit.issues; + +class Issue5234 extends Test { + function test() { + var f = function(error){ + throw error; + } + try{ + f('test'); + t(false); + } catch(e:Dynamic){ + t(true); + } + } +} diff --git a/tests/unit/src/unit/issues/Issue5242.hx b/tests/unit/src/unit/issues/Issue5242.hx new file mode 100644 index 00000000..11314ec8 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5242.hx @@ -0,0 +1,47 @@ +package unit.issues; + +class Issue5242 extends unit.Test { + function test() { + state = 0; + var buf = new StringBuf(); + for (i in 0...5) { + switch (next()) { + case "0": + buf.add("0"); + case "1": + buf.add("1"); + case "2": + buf.add("2"); + default: + buf.add("" + state); + } + } + eq("01245", buf.toString()); + } + + function test2() { + state = 0; + var buf = new StringBuf(); + for (i in 0...5) { + var v = next(); + switch (v) { + case "0": + buf.add("0"); + case "1": + buf.add("1"); + case "2": + buf.add("2"); + default: + buf.add("" + state); + } + } + eq("01245", buf.toString()); + } + + static var state = 0; + + static function next() { + return "" + state++; + } + +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5248.hx b/tests/unit/src/unit/issues/Issue5248.hx new file mode 100644 index 00000000..aa6b5d2a --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5248.hx @@ -0,0 +1,23 @@ +package unit.issues; +class Issue5248 extends Test{ + function test(){ + var f1 = new Issue5248Foo(); + eq(f1.saved, "123"); + } +} + +class Issue5248Foo { + var processData:Array->Array; + public var saved : String; + + + public function new():Void { + var arr = [1,2,3]; + this.processData = _processData; + saved = processData(arr).join(""); + } + + function _processData(arr:Array):Array { + return arr; + } +} diff --git a/tests/unit/src/unit/issues/Issue5249.hx b/tests/unit/src/unit/issues/Issue5249.hx new file mode 100644 index 00000000..b3b78068 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5249.hx @@ -0,0 +1,15 @@ +package unit.issues; + +class Issue5249 extends unit.Test { + static function value() return 123; + static function that() return 321; + + function test() { + unit.issues.misc.Issue5429Macro.mb(); + @:mergeBlock { + var a = value(); + var b = that(); + } + eq(444, a + b); // not in scope + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5253.hx b/tests/unit/src/unit/issues/Issue5253.hx new file mode 100644 index 00000000..77090f53 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5253.hx @@ -0,0 +1,12 @@ +package unit.issues; + +class Issue5253 extends Test { + static var a:Null = 1; + static var b:Null = 2; + + function test() + { + var doubleValue:Float = a / b; + eq(doubleValue, 0.5); + } +} diff --git a/tests/unit/src/unit/issues/Issue5260.hx b/tests/unit/src/unit/issues/Issue5260.hx new file mode 100644 index 00000000..01aa895a --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5260.hx @@ -0,0 +1,8 @@ +package unit.issues; + +class Issue5260 extends unit.Test { + function test() { + inline function foo( ?value : Dynamic = true ) return value; + t(foo()); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5270.hx b/tests/unit/src/unit/issues/Issue5270.hx new file mode 100644 index 00000000..c7596573 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5270.hx @@ -0,0 +1,19 @@ +package unit.issues; + +import php.*; + +class Issue5270 extends unit.Test { +#if php + function test() { + untyped __php__(" + $_SERVER['CONTENT_TYPE'] = 'type'; + $_SERVER['HTTP_USER_AGENT'] = 'browser'; + $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] = 'auth1'; + "); + + eq(Web.getClientHeader('Content-Type'), 'type'); + eq(Web.getClientHeader('User-Agent'), 'browser'); + eq(Web.getClientHeader('Authorization'), 'auth1'); + } +#end +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5274.hx b/tests/unit/src/unit/issues/Issue5274.hx new file mode 100644 index 00000000..cf43b02d --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5274.hx @@ -0,0 +1,16 @@ +package unit.issues; + +class Issue5274 extends unit.Test { + function test() { + eq("null", doMatch(null)); + eq("foobar", doMatch("foo,bar")); + } + + static function doMatch(s:String) { + return switch (s) { + case null: "null"; + case _.split(",") => [s1, s2]: s1 + s2; + default: "default"; + } + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5288.hx b/tests/unit/src/unit/issues/Issue5288.hx new file mode 100644 index 00000000..4d5b3dcf --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5288.hx @@ -0,0 +1,9 @@ +package unit.issues; + +class Issue5288 extends Test { + function test() { + var n : UInt = 3; + var c = -cast(n & 1, Int); + eq(-1, c); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5290.hx b/tests/unit/src/unit/issues/Issue5290.hx new file mode 100644 index 00000000..d8d09914 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5290.hx @@ -0,0 +1,17 @@ +package unit.issues; + +class Issue5290 extends unit.Test { + function test() { + var options = createFromPrototype({month: 0}); + eq(2016, options.year); + } + + public static inline function createFromPrototype( + options: { ?year: Int, ?month: Int }) { + + if(null == options.year) + options.year = 2016; + + return options; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5293.hx b/tests/unit/src/unit/issues/Issue5293.hx new file mode 100644 index 00000000..22ba3591 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5293.hx @@ -0,0 +1,8 @@ +package unit.issues; + +class Issue5293 extends unit.Test { + function test() { + var template = new haxe.Template("::foreach names:: hello ::__current__:: ::end::"); + eq(" hello wwx2016 ", template.execute({names:["wwx2016"]})); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5303.hx b/tests/unit/src/unit/issues/Issue5303.hx new file mode 100644 index 00000000..8c677f24 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5303.hx @@ -0,0 +1,9 @@ +package unit.issues; + +class Issue5303 extends unit.Test { + function test() { + var a:Int = 0; + a = -2147483648 - a; + // we only care if this type-checks + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5309.hx b/tests/unit/src/unit/issues/Issue5309.hx new file mode 100644 index 00000000..a0eb18a1 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5309.hx @@ -0,0 +1,15 @@ +package unit.issues; + +class Issue5309 extends unit.Test { + function test() { + eq(25, f2b(0.1)); + } + + public static inline function clamp( f : Float, min = 0., max = 1. ) { + return f < min ? min : f > max ? max : f; + } + + public static function f2b( v:Float ) : Int { + return Std.int(clamp(v) * 255.0); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5322.hx b/tests/unit/src/unit/issues/Issue5322.hx new file mode 100644 index 00000000..47d5dbc3 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5322.hx @@ -0,0 +1,36 @@ +package unit.issues; + +import unit.HelperMacros.typeErrorText; +import unit.HelperMacros.typedAs; + +private abstract A(String) from String {} + +class Issue5322 extends unit.Test { + function test() { + // unifies! + var a:Any = 1; + + // no fields! + eq("Any has no field f", typeErrorText(a.f)); + + // no array access! + eq("Array access is not allowed on Any", typeErrorText(a[0])); + + // no comparison! + eq("Cannot compare Any and Int", typeErrorText(a > 1)); + + // kept as the return type! + typedAs(something(), (1:Any)); + + // promotes to another type successfully! + eq("HELLO", (something() : String).toUpperCase()); + + // can be used for array of mixed types! + var a:Array = [1,false,"hey",{}]; + eq("hey", (a[2] : String)); + + eq("hello", ((("hello" : A) : Any) : String)); + } + + function something():Any return "hello"; +} diff --git a/tests/unit/src/unit/issues/Issue5323.hx b/tests/unit/src/unit/issues/Issue5323.hx new file mode 100644 index 00000000..b9ae1672 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5323.hx @@ -0,0 +1,17 @@ +package unit.issues; +class Issue5323 extends Test{ + function new() super(); + function test() { + var expected = 1; + var actual = new Issue5323().doStuff(function() return 0); + eq(actual, expected); + } + + function doStuff(self) { + return doOtherStuff(); + } + + function doOtherStuff() { + return 1; + } +} diff --git a/tests/unit/src/unit/issues/Issue5340.hx b/tests/unit/src/unit/issues/Issue5340.hx new file mode 100644 index 00000000..368058d7 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5340.hx @@ -0,0 +1,31 @@ +package unit.issues; + +private class Vector{ + public var x : Float = 0; + + public var inverse(get, never) : Vector; + + public inline function new(?x : Float = 0.) { + this.x = x; + } + inline function get_inverse() return new Vector(-x); + public function toString() return 'Vec($x)'; +} + +private class Matrix { + public var m : Array< Float > = [0.11, 0.33]; + + public function new() {} + public inline function back() return new Vector(m[0]); + public inline function fwd() return back().inverse; +} + +class Issue5340 extends unit.Test { + function test() { + var m = new Matrix(); + m.m[0] = 0.22; + var dir = m.fwd(); + + eq("Vec(-0.22)", "" + dir); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5351.hx b/tests/unit/src/unit/issues/Issue5351.hx new file mode 100644 index 00000000..1f2ef72b --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5351.hx @@ -0,0 +1,50 @@ +package unit.issues; +import scripthost.Issue5351; + +class Issue5351 extends Test { +#if !as3 + public function test() { + var t3:Issue5351_2 = Type.createInstance(Type.resolveClass('unit.issues.Issue5351_3'), []); + eq(t3.doTest1(), 'doTest1 override'); + eq(t3.doTest2(), 'doTest2 override'); + eq(t3.doTest3(), 'doTest3 override'); + + eq(scripthost.Issue5351.callDoTest1(t3), 'doTest1 override'); + eq(scripthost.Issue5351.callDoTest2(t3), 'doTest2 override'); + eq(scripthost.Issue5351_2.callDoTest1(t3), 'doTest1 override'); + eq(scripthost.Issue5351_2.callDoTest2(t3), 'doTest2 override'); + eq(scripthost.Issue5351_2.callDoTest3(t3), 'doTest3 override'); + + var t3 = new Issue5351_3(); + eq(t3.doTest1(), 'doTest1 override'); + eq(t3.doTest2(), 'doTest2 override'); + eq(t3.doTest3(), 'doTest3 override'); + + eq(scripthost.Issue5351.callDoTest1(t3), 'doTest1 override'); + eq(scripthost.Issue5351.callDoTest2(t3), 'doTest2 override'); + eq(scripthost.Issue5351_2.callDoTest1(t3), 'doTest1 override'); + eq(scripthost.Issue5351_2.callDoTest2(t3), 'doTest2 override'); + eq(scripthost.Issue5351_2.callDoTest3(t3), 'doTest3 override'); + + eq(t3.doTest4(), 'doTest4'); + } +#end +} + +@:keep class Issue5351_3 extends Issue5351_2 { + override public function doTest1() { + return 'doTest1 override'; + } + + override public function doTest2() { + return 'doTest2 override'; + } + + override public function doTest3() { + return 'doTest3 override'; + } + + public function doTest4() { + return 'doTest4'; + } +} diff --git a/tests/unit/src/unit/issues/Issue5358.hx b/tests/unit/src/unit/issues/Issue5358.hx new file mode 100644 index 00000000..25feaf85 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5358.hx @@ -0,0 +1,15 @@ +package unit.issues; + +class Issue5358 extends unit.Test { + + static var example = if (veryRandom() > 0.5) 1 else 2; + + function test() { + eq(example, 1); + } + + static function veryRandom() { + return 4; + } + +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5383.hx b/tests/unit/src/unit/issues/Issue5383.hx new file mode 100644 index 00000000..4c6a3cdb --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5383.hx @@ -0,0 +1,19 @@ +package unit.issues; + +class Issue5383 extends unit.Test { +#if php + static var issue = Issue5383; + + function test() { + //Should generate instance access + issue.doStuff(); + issue.issue.doStuff(); + t(true); + } + + static var anchor:Float; + static function doStuff() { + anchor = Math.random(); + } +#end +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5385.hx b/tests/unit/src/unit/issues/Issue5385.hx new file mode 100644 index 00000000..72ac70ae --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5385.hx @@ -0,0 +1,26 @@ +package unit.issues; + +class Issue5385 extends unit.Test { + function test() { + var refs:Refs = ["1"]; + var myIter:MyIterator = refs; + t(myIter.hasNext()); + eq("1", myIter.next()); + } +} + +private abstract MyIterator(Iterator) from Iterator to Iterator { + @:from public static inline function fromIterable(i:Iterable) + return (i.iterator():MyIterator); + + public inline function hasNext() { + return this.hasNext(); + } + + public inline function next() { + return this.next(); + } +} + +@:forward +private abstract Refs(Array) from Array to Array {} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5389.hx b/tests/unit/src/unit/issues/Issue5389.hx new file mode 100644 index 00000000..5d0ec42d --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5389.hx @@ -0,0 +1,17 @@ +package unit.issues; + +@test +private class C { +} + +private class C1 { + @test function f() {} +} + +class Issue5389 extends unit.Test { + function test() { + eq(0, Reflect.fields(haxe.rtti.Meta.getFields(C)).length); + eq(0, Reflect.fields(haxe.rtti.Meta.getStatics(C)).length); + eq(0, Reflect.fields(haxe.rtti.Meta.getType(C1)).length); + } +} diff --git a/tests/unit/src/unit/issues/Issue5392.hx b/tests/unit/src/unit/issues/Issue5392.hx new file mode 100644 index 00000000..12344700 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5392.hx @@ -0,0 +1,16 @@ +package unit.issues; + +private abstract A(Int) from Int { + public function size() { + return switch (this) { + case size: size; + } + } +} + +class Issue5392 extends unit.Test { + function test() { + var a = (10 : A); + eq(10, a.size()); + } +} diff --git a/tests/unit/src/unit/issues/Issue5425.hx b/tests/unit/src/unit/issues/Issue5425.hx new file mode 100644 index 00000000..ef31e9c7 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5425.hx @@ -0,0 +1,10 @@ +package unit.issues; + +class Issue5425 extends unit.Test { + function test() { + var self = 1; + function f() self = 2; + f(); + eq(2, self); + } +} diff --git a/tests/unit/src/unit/issues/Issue5432.hx b/tests/unit/src/unit/issues/Issue5432.hx new file mode 100644 index 00000000..c2a1453c --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5432.hx @@ -0,0 +1,25 @@ +package unit.issues; + +class Issue5432 extends unit.Test { + function test() { + var pt = new Point(); + + function closure() + { + pt.x = pt.x + pt.y; + } + + closure(); + feq(3., pt.x); + feq(2., pt.y); + } + +} + +private class Point +{ + public var x:Float = 1; + public var y:Float = 2; + + @:extern inline public function new() {} +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5455.hx b/tests/unit/src/unit/issues/Issue5455.hx new file mode 100644 index 00000000..1c349b6b --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5455.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue5455 extends unit.Test { + function test() { + var s = protect('"foo"'); + var p = protect(0); + var c = s.charAt(p++); + var n = s.substring(p, s.indexOf(c, p)); + eq("foo", n); + } + + static function protect(v:T):T return v; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5466.hx b/tests/unit/src/unit/issues/Issue5466.hx new file mode 100644 index 00000000..1b677b2e --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5466.hx @@ -0,0 +1,17 @@ +package unit.issues; + +class Issue5466 extends Test { + function test() { + var test:Base = (Math.random() > 0.5) ? new A() : new B(); + t(Std.is(test, A) || Std.is(test, B)); + } +} + +private class Base { + public function new() {} +} + +private class A extends Base { +} +private class B extends Base { +} diff --git a/tests/unit/src/unit/issues/Issue5469.hx b/tests/unit/src/unit/issues/Issue5469.hx new file mode 100644 index 00000000..0000ce25 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5469.hx @@ -0,0 +1,15 @@ +package unit.issues; + +class Issue5469 extends unit.Test { + function test() { + var foo : Dynamic = new Foo(); + foo.bar( StringTools.urlDecode('') ); + t(true); + } +} + +@:keep +private class Foo { + public function new() {} + public function bar(p: String) {} +} diff --git a/tests/unit/src/unit/issues/Issue5470.hx b/tests/unit/src/unit/issues/Issue5470.hx new file mode 100644 index 00000000..219fdbea --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5470.hx @@ -0,0 +1,10 @@ +package unit.issues; + +class Issue5470 extends unit.Test { + var cb:Void->Void; + + function test() { + eq(new Issue5470().cb, null); + } + +} diff --git a/tests/unit/src/unit/issues/Issue5477.hx b/tests/unit/src/unit/issues/Issue5477.hx new file mode 100644 index 00000000..5ab92443 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5477.hx @@ -0,0 +1,167 @@ +package unit.issues; + +private class C { + public var hash:Array; + public function new() { + hash = [1, 2, 3]; + } + + public function add(x) { + hash[0] = x; + return x; + } +} + +private class D { + public var field:{value1: Int, value2: Int}; + public function new() { + field = { value1: 1, value2: 2 }; + } + + public function set(x) { + field.value1 = x; + return x; + } +} + +private class StupidStringBuf { + public var b:String; + + public inline function new() { + b = ""; + } + + public inline function add(s:String) { + b += s; + } +} + +class Issue5477 extends unit.Test { + static var idCounter = 0; + + function testArray() { + idCounter = 0; + + var c = new C(); + almostId(c).hash[0] = c.add(4); + eq(4, c.hash[0]); + eq(1, idCounter); + + var c = new C(); + c.hash[0] += c.add(4); + eq(5, c.hash[0]); + + var c = new C(); + c.hash[1] = almostId(c).hash[0] += { + var x = c.add(4); + x; + } + eq(5, c.hash[0]); + eq(5, c.hash[1]); + eq(2, idCounter); + + var c = new C(); + almostId(c).hash[1] += ({eq(3, idCounter); almostId(c);}).hash[0] += { + var x = c.add(4); + x; + } + eq(5, c.hash[0]); + eq(7, c.hash[1]); + eq(4, idCounter); + + var c = new C(); + c.hash[1] += c.hash[0] = { + var x = c.add(4); + x; + } + eq(4, c.hash[0]); + eq(6, c.hash[1]); + + var c = new C(); + var tmp = c.add(4); + c.hash[0] += tmp; + eq(8, c.hash[0]); + } + + function testField() { + idCounter = 0; + + var d = new D(); + almostId(d).field.value1 = d.set(4); + eq(4, d.field.value1); + eq(1, idCounter); + + var d = new D(); + d.field.value1 += d.set(4); + eq(5, d.field.value1); + + var d = new D(); + d.field.value2 = almostId(d).field.value1 += { + var x = d.set(4); + x; + } + eq(5, d.field.value1); + eq(5, d.field.value2); + eq(2, idCounter); + + var d = new D(); + almostId(d).field.value2 += ({eq(3, idCounter); almostId(d);}).field.value1 += { + var x = d.set(4); + x; + } + eq(5, d.field.value1); + eq(7, d.field.value2); + eq(4, idCounter); + + var d = new D(); + d.field.value2 += d.field.value2 = { + var x = d.set(4); + x; + } + eq(4, d.field.value1); + eq(6, d.field.value2); + + var d = new D(); + var tmp = d.set(4); + d.field.value1 += tmp; + eq(8, d.field.value1); + } + + function testStringBuf() { + var buf = new StupidStringBuf(); + buf.add("1"); + buf.add(messUp(buf)); + eq("23", buf.b); + + var buf = new StupidStringBuf(); + buf.add("1"); + buf.b += messUp(buf); + eq("13", buf.b); + } + + function test() { + var a = g(); + var b = ff() + a; + eq(3, b); + } + + static var x = 1; + + static function ff() { + return x = 2; + } + + static function g() { + return x; + } + + static function messUp(buf:StupidStringBuf) { + buf.b = "2"; + return "3"; + } + + static function almostId(c:T) { + ++idCounter; + return c; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5481.hx b/tests/unit/src/unit/issues/Issue5481.hx new file mode 100644 index 00000000..25bf829d --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5481.hx @@ -0,0 +1,17 @@ +package unit.issues; + +@:nativeGen +private class Some { + public var s:String; + public function new() s = "hello"; +} + +class Issue5481 extends Test { + #if !cpp + function test() { + var o = new Some(); + Reflect.setField(o, "s", null); + eq(o.s, null); + } + #end +} diff --git a/tests/unit/src/unit/issues/Issue5505.hx b/tests/unit/src/unit/issues/Issue5505.hx new file mode 100644 index 00000000..d44b8691 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5505.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue5505 extends Test { + function test() { +#if (java || cs) + eq(StringTools.urlEncode('~'), '~'); + eq(StringTools.urlDecode(StringTools.urlEncode('~')), '~'); + eq(StringTools.urlDecode(StringTools.urlEncode('-')), '-'); + eq(StringTools.urlDecode('%7E'), '~'); + eq(StringTools.urlDecode('%7e'), '~'); +#end + } +} diff --git a/tests/unit/src/unit/issues/Issue5507.hx b/tests/unit/src/unit/issues/Issue5507.hx new file mode 100644 index 00000000..7f99908c --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5507.hx @@ -0,0 +1,15 @@ +package unit.issues; + +private abstract S(String) to String { + @:from static inline function fromString(s:String):S return cast s.toUpperCase(); +} + +class Issue5507 extends unit.Test { + #if (cs || java) + @:readOnly static var a(default,never):S = "hello"; + + function test() { + eq("HELLO", a); + } + #end +} diff --git a/tests/unit/src/unit/issues/Issue5508.hx b/tests/unit/src/unit/issues/Issue5508.hx new file mode 100644 index 00000000..46de51aa --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5508.hx @@ -0,0 +1,28 @@ +package unit.issues; + +private class C { + public var f:Int; + public function new() { + f = 1; + } +} + +class Issue5508 extends unit.Test { + var i = 2; + static var c = new C(); + + function test() { + eq(~mask(i), -5); + eq(nPure(c).f, 1); + } + + @:pure + inline static function mask(i:Int):Int { + return 0x1 << i; + } + + @:pure + static inline function nPure(a:C) { + return if (a == null) a else a; + } +} diff --git a/tests/unit/src/unit/issues/Issue5520.hx b/tests/unit/src/unit/issues/Issue5520.hx new file mode 100644 index 00000000..121718a1 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5520.hx @@ -0,0 +1,27 @@ +package unit.issues; + +private class A extends B { + public function new() { + super([ + "sample" => C.E + ]); + } +} + +private class B { + public var map:Map; + public function new(str:Map) { + map = str; + } +} + +private enum C { + E; +} + +class Issue5520 extends unit.Test { + function test() { + var a = new A(); + eq(C.E, a.map["sample"]); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5540.hx b/tests/unit/src/unit/issues/Issue5540.hx new file mode 100644 index 00000000..42eb3842 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5540.hx @@ -0,0 +1,16 @@ +package unit.issues; + +class Issue5540 extends unit.Test { + function test() { + eq(1, get().propertySet -= 1); + } + + static function get() return { propertySet:new Signal(2) }; +} + +private abstract Signal(Int) { + public function new(i) this = i; + + @:op(A -= B) + public function opRemove(i:Int) return this - i; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5543.hx b/tests/unit/src/unit/issues/Issue5543.hx new file mode 100644 index 00000000..03934f7b --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5543.hx @@ -0,0 +1,17 @@ +package unit.issues; + +class Issue5543 extends Test { + function test() { + f1({ i: 5 }); + } + + static function f1(n:NullableInt) { + f2(n.i); + } + + static function f2(i:Int = 0) {} +} + +typedef NullableInt = { + ?i:Int +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5544.hx b/tests/unit/src/unit/issues/Issue5544.hx new file mode 100644 index 00000000..e49947fe --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5544.hx @@ -0,0 +1,31 @@ +package unit.issues; + +private extern class C { + public inline function inlineMe():String { + return "I'm inlined!"; + } +} + +private typedef T = { + function inlineMe():String; +} + +@:multiType +private abstract A(T) { + + public function new(); + + @:to @:extern inline function toC():C { + return null; + } + + public inline function get(s:String) { + return this.inlineMe(); + } +} + +class Issue5544 extends unit.Test { + function test() { + eq("I'm inlined!", new A().get("foo")); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5555.hx b/tests/unit/src/unit/issues/Issue5555.hx new file mode 100644 index 00000000..cb5e312d --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5555.hx @@ -0,0 +1,46 @@ +package unit.issues; + +class Issue5555 extends unit.Test { + static var flag = false; + + function testStateWrite() { + var call1 = pureCall(); + var call2 = impureCall(); + f(call1 && call2); + t(flag); + } + + function testVarWrite() { + var x = getInt(); + var call1 = pureCall(); + var y = x++; + f(call1 && (y == 0)); + eq(1, x); + } + + function testFieldWrite() { + var o = getObject(); + var call1 = pureCall(); + var y = o.value = (getInt() + 1); + f(call1 && (y == 0)); + eq(1, o.value); + } + + static function pureCall() { + return false; + } + + @:pure(false) + static function impureCall() { + flag = true; + return false; + } + + static function getInt() { + return 0; + } + + static function getObject() { + return { value: 0 }; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5556.hx b/tests/unit/src/unit/issues/Issue5556.hx new file mode 100644 index 00000000..ac829e57 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5556.hx @@ -0,0 +1,17 @@ +package unit.issues; + +class Issue5556 extends unit.Test { + function test() { + var x = dynamicFunc(randomCall()); + #if (!flash && !js) + eq(1, x); + #end + } + + static function randomCall() { + dynamicFunc = function(x:Int) return x * 2; + return 1; + } + + static dynamic function dynamicFunc(x) return x; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5557.hx b/tests/unit/src/unit/issues/Issue5557.hx new file mode 100644 index 00000000..7dc9addc --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5557.hx @@ -0,0 +1,11 @@ +package unit.issues; + +class Issue5557 extends unit.Test { + function test() { + var a = ["foo"]; + var v = a.pop(); + for (o in a) + throw o; + eq("foo", v); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5558.hx b/tests/unit/src/unit/issues/Issue5558.hx new file mode 100644 index 00000000..f6a3db56 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5558.hx @@ -0,0 +1,19 @@ +package unit.issues; + +private class O { + public var f(default,null):Int; + public function new() f = 1; + public function mutate() f = 2; +} + +class Issue5558 extends unit.Test { + function test() { + fun(new O()); + } + + function fun(o:O) { + var oldF = o.f; + o.mutate(); + eq(1, oldF); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5565.hx b/tests/unit/src/unit/issues/Issue5565.hx new file mode 100644 index 00000000..eafa04a1 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5565.hx @@ -0,0 +1,9 @@ +package unit.issues; + +class Issue5565 extends Test { + function test() { + #if php + t(Std.is(untyped __php__('[]'), php.NativeArray)); + #end + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5569.hx b/tests/unit/src/unit/issues/Issue5569.hx new file mode 100644 index 00000000..597f590f --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5569.hx @@ -0,0 +1,18 @@ +package unit.issues; + +import haxe.Constraints; + +class Issue5569 extends unit.Test { + function test() { + var namesToFunctions:Map = new Map(); + var noArgs:String = "noArgs"; + var withArgs:String = "withArgs"; + namesToFunctions.set(noArgs, function() {}); + namesToFunctions.set(withArgs, function(a:Int) {}); + + namesToFunctions.get(noArgs)(); + namesToFunctions.get(withArgs)(1); + + t(true); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5572.hx b/tests/unit/src/unit/issues/Issue5572.hx new file mode 100644 index 00000000..48d79cc6 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5572.hx @@ -0,0 +1,29 @@ +package unit.issues; + +class Issue5572 extends unit.Test { + // these two fields have the same hash value + static var field1 = "baseReward"; + static var field2 = "user_3235_65290"; + + function test() { + #if !(neko || hl) + var o = {}; + Reflect.setField(o, field1, 1); // first, goes into hashes array + Reflect.setField(o, field2, 2); // second, added to object's "conflicts" + Reflect.setField(o, field2, 3); // should find one from "conflicts" and change the value + eq(Reflect.field(o, field1), 1); // retrieved from the hashes array + eq(Reflect.field(o, field2), 3); // retreived from "conflicts" + var expectedFields = [field1, field2]; + for (field in Reflect.fields(o)) { + if (!expectedFields.remove(field)) + t(false); + } + eq(expectedFields.length, 0); + Reflect.deleteField(o, field1); // removed from hashes array + Reflect.deleteField(o, field2); // removed from "conflicts" + eq(Reflect.field(o, field1), null); + eq(Reflect.field(o, field2), null); + eq(Reflect.fields(o).length, 0); + #end + } +} diff --git a/tests/unit/src/unit/issues/Issue5584.hx b/tests/unit/src/unit/issues/Issue5584.hx new file mode 100644 index 00000000..30f2ceae --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5584.hx @@ -0,0 +1,17 @@ +package unit.issues; + +import cpp.Callable; +import cpp.Object; +import haxe.io.Bytes; + +class Issue5584 extends Test { + function test() { + var callable = new CallableObject>(cffi_decompress); + var bytes = Bytes.alloc (100); + var data:Dynamic = callable.call (bytes); + } + + function cffi_decompress(a:Dynamic):Dynamic { + return null; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5608.hx b/tests/unit/src/unit/issues/Issue5608.hx new file mode 100644 index 00000000..a8d41f5d --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5608.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue5608 extends unit.Test implements Dynamic { + var fields:Array; + + function test() { + //should not throw + fields = Reflect.fields(Issue5608); + t(true); + } + + public function resolve( name ) return true; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5693.hx b/tests/unit/src/unit/issues/Issue5693.hx new file mode 100644 index 00000000..8e5713e7 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5693.hx @@ -0,0 +1,19 @@ +package unit.issues; +import haxe.io.*; +class Issue5693 extends Test{ + function test(){ + var original:Float = 0.012755102040816; + var btOutput:BytesOutput = new BytesOutput(); + btOutput.writeDouble(original); + + var byteArray:Bytes = btOutput.getBytes(); + + var btInput:BytesInput = new BytesInput(byteArray); + var copyVal:Float = btInput.readDouble(); + +#if !lua +//TODO + eq(original, copyVal); +#end + } +} diff --git a/tests/unit/src/unit/issues/Issue5705.hx b/tests/unit/src/unit/issues/Issue5705.hx new file mode 100644 index 00000000..cbfa1323 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5705.hx @@ -0,0 +1,17 @@ +package unit.issues; + +class Issue5705 extends Test { + static function foo(baseClass:BaseClass_):Int { + return cast(baseClass, IInterface).z; + } +} + +class BaseClass_ {} + +interface IInterface { + public var z:Int; +} + +class ImplementingClass extends BaseClass_ implements IInterface { + public var z:Int; +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5737.hx b/tests/unit/src/unit/issues/Issue5737.hx new file mode 100644 index 00000000..ce0feb4e --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5737.hx @@ -0,0 +1,22 @@ +package unit.issues; + +#if python +private class C { + public var v:Array; + public var k:{a:Int}; + public function new(v:python.VarArgs, k:python.KwArgs<{a:Int}>) { + this.v = v.toArray(); + this.k = k.typed(); + } +} +#end + +class Issue5737 extends Test { + #if python + function test(){ + var c = new C([1,2,3], {a: 42}); + aeq(c.v, [1,2,3]); + eq(c.k.a, 42); + } + #end +} diff --git a/tests/unit/src/unit/issues/Issue5742.hx b/tests/unit/src/unit/issues/Issue5742.hx new file mode 100644 index 00000000..75ab778e --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5742.hx @@ -0,0 +1,21 @@ +package unit.issues; + +class Issue5742 extends Test { +#if sys + function test(){ + try { + sys.FileSystem.deleteFile('nonexistent.file'); + t(false); + } catch(e:Dynamic) { + t(true); + } + + try { + sys.FileSystem.deleteDirectory('nonexistent.directory'); + t(false); + } catch(e:Dynamic) { + t(true); + } + } +#end +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5747.hx b/tests/unit/src/unit/issues/Issue5747.hx new file mode 100644 index 00000000..65fda8d4 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5747.hx @@ -0,0 +1,10 @@ +package unit.issues; + +class Issue5747 extends Test { + #if (cs && !erase_generics) + function test() { + var a = [1,2,3]; + eq(@:privateAccess a.__a[0], 1); + } + #end +} diff --git a/tests/unit/src/unit/issues/Issue5757.hx b/tests/unit/src/unit/issues/Issue5757.hx new file mode 100644 index 00000000..be991ea8 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5757.hx @@ -0,0 +1,19 @@ +package unit.issues; + +#if sys +import sys.db.Types; +import sys.db.Object; + +class SpodRtti extends Object { + public var id : SId; +} +#end + +class Issue5757 extends unit.Test { +#if sys + function test() { + var rtti = haxe.rtti.Meta.getType( SpodRtti ).rtti; + t(rtti != null); + } +#end +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5764.hx b/tests/unit/src/unit/issues/Issue5764.hx new file mode 100644 index 00000000..ef7bad6e --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5764.hx @@ -0,0 +1,11 @@ +package unit.issues; + +class Issue5764 extends unit.Test { + @:analyzer(no_local_dce) + function test() { + var f:Float; + f = 0; + --f; + feq(-1., f); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5783.hx b/tests/unit/src/unit/issues/Issue5783.hx new file mode 100644 index 00000000..db52c423 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5783.hx @@ -0,0 +1,13 @@ +package unit.issues; + +private abstract I(Int) from Int to Int { + @:from + public static function fromString(v:String):I return Std.parseInt(v); +} + +class Issue5783 extends unit.Test { + function test() { + function add(i:I) return i + 1; + var f = add.bind('1'); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5848.hx b/tests/unit/src/unit/issues/Issue5848.hx new file mode 100644 index 00000000..514842a5 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5848.hx @@ -0,0 +1,40 @@ +package unit.issues; + +private abstract Degree(Float) { + public inline function new (f:Float) { + this = f; + } + @:from // removing this line makes it compile + public static function fromRadian (d:Radian):Degree { + return new Degree(d.float()); + } + public inline function float ():Float return this; +} + +private abstract Radian(Float) { + public inline function new (f:Float) { + this = f; + } + + @:from static inline function fromDegree (d:Degree):Radian { + return new Radian(d.float()); + } + + public inline function float ():Float return this; +} + +private class Vec2s { + public static function foo (radian:Radian) { + return 1; + } +} + +class Issue5848 extends unit.Test { + function test():Void { + ff(new Degree(90)); + } + + static public function ff(r:Radian) { + Vec2s.foo(r); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5851.hx b/tests/unit/src/unit/issues/Issue5851.hx new file mode 100644 index 00000000..ae5258e3 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5851.hx @@ -0,0 +1,12 @@ +package unit.issues; + +class Issue5851 extends unit.Test { + function test() { + try { + return ""; + } catch ( s : Dynamic ) { + return ""; + } + return ""; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5873.hx b/tests/unit/src/unit/issues/Issue5873.hx new file mode 100644 index 00000000..e55c5f17 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5873.hx @@ -0,0 +1,25 @@ +package unit.issues; + +class Issue5873 extends unit.Test { + function test() { + eq(1, foo("foo", "eot")); + eq(2, foo("LF", "x")); + eq(2, foo("LF", "LF")); + eq(2, foo("x", "LF")); + eq(3, foo("LV", "V")); + eq(3, foo("LV", "T")); + eq(3, foo("V", "T")); + eq(3, foo("V", "V")); + eq(4, foo("V", "x")); + } + + static function foo(prev, next) { + return switch([prev,next]) { + case [_, 'eot'] : 1; //A + case ['LF', _] + | [_, 'LF'] : 2; //B + case ['LV' | 'V', 'V'|'T']: 3; //C + case _: 4; + } + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5894.hx b/tests/unit/src/unit/issues/Issue5894.hx new file mode 100644 index 00000000..4090bb15 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5894.hx @@ -0,0 +1,19 @@ +package unit.issues; + +class Issue5894 extends unit.Test { + function test() { + var recursed = false; + function local(o:Array) { + for(e in o) { + if(!recursed) { + recursed = true; + return local(e); + } else { + return e; + } + } + return 0; + } + eq(1, local([[1], 2])); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5911.hx b/tests/unit/src/unit/issues/Issue5911.hx new file mode 100644 index 00000000..9058472c --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5911.hx @@ -0,0 +1,13 @@ +package unit.issues; + +class Issue5911 extends unit.Test { + function test() { + var x = 5; + var advance = function () { + x++; + }; + var cur = x; + advance(); + eq(5, cur); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5919.hx b/tests/unit/src/unit/issues/Issue5919.hx new file mode 100644 index 00000000..89f8c463 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5919.hx @@ -0,0 +1,11 @@ +package unit.issues; + +class Issue5919 extends unit.Test { +#if php + function test() { + untyped __php__("$_TEST_VAR = ['test' => 12]"); + t(untyped __call__("is_array", untyped __var__("_TEST_VAR"))); + eq(untyped __var__("_TEST_VAR", "test"), 12); + } +#end +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5923.hx b/tests/unit/src/unit/issues/Issue5923.hx new file mode 100644 index 00000000..1b375177 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5923.hx @@ -0,0 +1,18 @@ +package unit.issues; + +#if php7 +import php.Syntax.*; +#end + +class Issue5923 extends unit.Test { +#if php7 + function test() { + //These expressions should not fail at runtime + binop({}, '??', null).value = 1; + object(arrayDecl()).value = 1; + array({})['value'] = 1; + + t(true); + } +#end +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5945.hx b/tests/unit/src/unit/issues/Issue5945.hx new file mode 100644 index 00000000..98c096e7 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5945.hx @@ -0,0 +1,11 @@ +package unit.issues; + +import haxe.ds.StringMap; +class Issue5945 extends Test { + function test() { + var test_map : StringMap = new StringMap(); + var test_key : String = "key"; + test_map.set(test_key, "Hello world"); + eq(test_map.exists(test_key) == false, false); + } +} diff --git a/tests/unit/src/unit/issues/Issue5957.hx b/tests/unit/src/unit/issues/Issue5957.hx new file mode 100644 index 00000000..e90b909d --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5957.hx @@ -0,0 +1,17 @@ +package unit.issues; + +import haxe.ds.Vector; + +class Issue5957 extends Test { + static var foo:Vector> = { + var vec = new Vector>(10); + vec[0] = new Vector(2); + vec[0][0] = 0; + vec; + } + + public function test() { + foo[0][0] += 1; + eq(1, foo[0][0]); + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/Issue5973.hx b/tests/unit/src/unit/issues/Issue5973.hx new file mode 100644 index 00000000..889ea257 --- /dev/null +++ b/tests/unit/src/unit/issues/Issue5973.hx @@ -0,0 +1,38 @@ +package unit.issues; +class Issue5973 extends Test{ + public function test(){ + var foo = new Issue5973Foo(); + var bar = new Issue5973Bar(); + var foobar = new Issue5973FooBar(); + t(Std.is(foo , Issue5973IFoo)); + f(Std.is(foo , Issue5973IBar)); + f(Std.is(bar , Issue5973IFoo)); + t(Std.is(bar , Issue5973IBar)); + t(Std.is(foobar , Issue5973IFoo)); + t(Std.is(foobar , Issue5973IBar)); + } +} + +interface Issue5973IFoo { + function foo() : Void; +} + +interface Issue5973IBar { + function bar() : Void; +} + +class Issue5973Foo implements Issue5973IFoo { + public function new() {} + public function foo() {} +} + +class Issue5973Bar implements Issue5973IBar { + public function new() {} + public function bar() {} +} + +class Issue5973FooBar implements Issue5973IFoo implements Issue5973IBar { + public function new() {} + public function foo() {} + public function bar() {} +} diff --git a/tests/unit/src/unit/issues/misc/Issue1497Macro.hx b/tests/unit/src/unit/issues/misc/Issue1497Macro.hx index 4b8049da..36284f50 100644 --- a/tests/unit/src/unit/issues/misc/Issue1497Macro.hx +++ b/tests/unit/src/unit/issues/misc/Issue1497Macro.hx @@ -1,13 +1,13 @@ package unit.issues.misc; class Issue1497Macro { - macro public static function run() { - var cl = macro class Issue1497DefinedClass { - macro public static function test() { - return macro 1; - } - }; - haxe.macro.Context.defineType(cl); - return macro null; - } + macro public static function run() { + var cl = macro class Issue1497DefinedClass { + macro public static function test() { + return macro 1; + } + }; + haxe.macro.Context.defineType(cl); + return macro null; + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/misc/Issue2003Macro.hx b/tests/unit/src/unit/issues/misc/Issue2003Macro.hx index 26492876..8ae74b89 100644 --- a/tests/unit/src/unit/issues/misc/Issue2003Macro.hx +++ b/tests/unit/src/unit/issues/misc/Issue2003Macro.hx @@ -3,22 +3,22 @@ package unit.issues.misc; import haxe.macro.Expr; class Issue2003Macro { - public function new() {} + public function new() {} - public function callMe( cb:Void->Void ) { - cb(); - return this; - } + public function callMe( cb:Void->Void ) { + cb(); + return this; + } - public static function create() { - return new Issue2003Macro(); - } + public static function create() { + return new Issue2003Macro(); + } - macro public function testMacro( ethis : Expr ) : Expr { - var vname = "_____ref"; - var vdecl = macro var $vname = $ethis; - var v = { expr : EConst(CIdent(vname)), pos : haxe.macro.Context.currentPos() }; - var eret = macro (function() { $vdecl; return $v; })(); - return eret; - } + macro public function testMacro( ethis : Expr ) : Expr { + var vname = "_____ref"; + var vdecl = macro var $vname = $ethis; + var v = { expr : EConst(CIdent(vname)), pos : haxe.macro.Context.currentPos() }; + var eret = macro (function() { $vdecl; return $v; })(); + return eret; + } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/misc/Issue3008Class.hx b/tests/unit/src/unit/issues/misc/Issue3008Class.hx index b1f4452f..0b5f6e68 100644 --- a/tests/unit/src/unit/issues/misc/Issue3008Class.hx +++ b/tests/unit/src/unit/issues/misc/Issue3008Class.hx @@ -1,6 +1,6 @@ package unit.issues.misc; class Issue3008Class { - public function new(unit:String) { } - public function call() { } + public function new(unit:String) { } + public function call() { } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/misc/Issue3133Class.hx b/tests/unit/src/unit/issues/misc/Issue3133Class.hx index e31094d2..b9828252 100644 --- a/tests/unit/src/unit/issues/misc/Issue3133Class.hx +++ b/tests/unit/src/unit/issues/misc/Issue3133Class.hx @@ -1,6 +1,6 @@ package unit.issues.misc; class Issue3133Class { - public function new() { } - public function test(unit:String) { } + public function new() { } + public function test(unit:String) { } } \ No newline at end of file diff --git a/tests/unit/src/unit/issues/misc/Issue3183Macro.hx b/tests/unit/src/unit/issues/misc/Issue3183Macro.hx index a877cc63..7a4056f6 100644 --- a/tests/unit/src/unit/issues/misc/Issue3183Macro.hx +++ b/tests/unit/src/unit/issues/misc/Issue3183Macro.hx @@ -80,7 +80,8 @@ class Issue3183Macro { name: field.name, type: null, opt: false, - value: null + value: null, + meta: [] } }) }) diff --git a/tests/unit/src/unit/issues/misc/Issue3460Macro.hx b/tests/unit/src/unit/issues/misc/Issue3460Macro.hx new file mode 100644 index 00000000..e00bb819 --- /dev/null +++ b/tests/unit/src/unit/issues/misc/Issue3460Macro.hx @@ -0,0 +1,16 @@ +package unit.issues.misc; + +import haxe.macro.Context; +import haxe.macro.Expr; + +class Issue3460Macro { + macro static public function getOverloadString(e:Expr) { + var c = switch (Context.typeof(e)) { + case TInst(c, _): c.get(); + case _: throw "Something went wrong"; + } + var cf = c.fields.get()[0]; + var s = cf.overloads.get().map(function (cf) return haxe.macro.TypeTools.toString(cf.type)).join(", "); + return macro $v{s}; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/misc/Issue3560Macro.hx b/tests/unit/src/unit/issues/misc/Issue3560Macro.hx new file mode 100644 index 00000000..c2a9f0eb --- /dev/null +++ b/tests/unit/src/unit/issues/misc/Issue3560Macro.hx @@ -0,0 +1,11 @@ +package unit.issues.misc; + +class Issue3560Macro { + macro static public function getImportString() { + var imports = haxe.macro.Context.getLocalImports(); + var s = imports.map(function (i) { + return Std.string(i.mode) + ":" + i.path.map(function(p) return p.name).join("."); + }); + return macro $v{s}; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/misc/Issue4121Macro.hx b/tests/unit/src/unit/issues/misc/Issue4121Macro.hx new file mode 100644 index 00000000..47ffe267 --- /dev/null +++ b/tests/unit/src/unit/issues/misc/Issue4121Macro.hx @@ -0,0 +1,14 @@ +package unit.issues.misc; + +import haxe.macro.Expr; +using haxe.macro.Tools; + +class Issue4121Macro { + macro static public function wrap(e:Expr) { + function addParens(e:Expr) { + return macro (${e.map(addParens)}); + } + var e = addParens(e); + return macro $v{e.toString()}; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/misc/Issue4306Macro.hx b/tests/unit/src/unit/issues/misc/Issue4306Macro.hx new file mode 100644 index 00000000..b23acac5 --- /dev/null +++ b/tests/unit/src/unit/issues/misc/Issue4306Macro.hx @@ -0,0 +1,44 @@ +package unit.issues.misc; + +import haxe.macro.Expr; +import haxe.macro.Context; +import haxe.macro.Type; + +using haxe.macro.Tools; + +abstract TypeName(String) to String { + @:from static macro function fromE(e:Expr) { + return macro $v{Context.typeof(e).toString()}; + } +} + +abstract Arity(Int) to Int { + @:from static macro function fromE(e:Expr) { + return switch (Context.typeof(e).follow()) { + case TFun(tl, _): macro $v{tl.length}; + case _: Context.error("Expected function type", e.pos); + } + } +} + +abstract EnumListener(String) to String { + @:from static macro function fromE(e:Expr) { + var e = Context.typeExpr(e); + var ef = switch (e.expr) { + case TField(_, FEnum(_, ef)): ef; + case _: Context.error("Expected enum constructor", e.pos); + } + var t = switch (Context.getExpectedType().follow()) { + case TAbstract(_, [t]): t; + case _: Context.error("Something went wrong", e.pos); + } + var tvoid = Context.typeof(macro (null : Void)); + var t2 = switch (e.t.follow()) { + case TFun(tl, _): TFun(tl, tvoid); + case TEnum(_): TFun([], tvoid); + case _: Context.error("Something went wrong, again", e.pos); + } + Context.unify(t, t2); + return macro $v{ef.name}; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/misc/Issue4419External.js b/tests/unit/src/unit/issues/misc/Issue4419External.js new file mode 100644 index 00000000..6b8db83c --- /dev/null +++ b/tests/unit/src/unit/issues/misc/Issue4419External.js @@ -0,0 +1 @@ +var Issue4419External = function() { }; \ No newline at end of file diff --git a/tests/unit/src/unit/issues/misc/Issue4653Macro.hx b/tests/unit/src/unit/issues/misc/Issue4653Macro.hx new file mode 100644 index 00000000..00f6893c --- /dev/null +++ b/tests/unit/src/unit/issues/misc/Issue4653Macro.hx @@ -0,0 +1,11 @@ +package unit.issues.misc; + +class Issue4653Macro { + static public function getType() { + return macro : NotString; + } + + static public function getStringType() { + return macro : String; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/misc/Issue4666Macro.hx b/tests/unit/src/unit/issues/misc/Issue4666Macro.hx new file mode 100644 index 00000000..b248092d --- /dev/null +++ b/tests/unit/src/unit/issues/misc/Issue4666Macro.hx @@ -0,0 +1,7 @@ +package unit.issues.misc; + +class Issue4666Macro { + static public function getType() { + return macro : Dynamic; + } +} \ No newline at end of file diff --git a/tests/unit/src/unit/issues/misc/Issue5429Macro.hx b/tests/unit/src/unit/issues/misc/Issue5429Macro.hx new file mode 100644 index 00000000..136b29de --- /dev/null +++ b/tests/unit/src/unit/issues/misc/Issue5429Macro.hx @@ -0,0 +1,14 @@ +package unit.issues.misc; + +class Issue5429Macro { + macro static public function mb(){ + return macro { + + @:mergeBlock { + var a = value(); + var b = that(); + } + eq(444, a + b); // not in scope + }; + } +} \ No newline at end of file diff --git a/tests/unit/src/unitstd/Array.unit.hx b/tests/unit/src/unitstd/Array.unit.hx index cdbdee5b..91add125 100644 --- a/tests/unit/src/unitstd/Array.unit.hx +++ b/tests/unit/src/unitstd/Array.unit.hx @@ -276,6 +276,6 @@ values == [1, 3, 5]; var a : Dynamic = [0,1,2]; var b : Dynamic = a.filter(function(x) return x & 1 == 0).map(function(x) return x * 10); b.length == 2; -b[0] = 0; -b[1] = 20; +b[0] == 0; +b[1] == 20; #end \ No newline at end of file diff --git a/tests/unit/src/unitstd/Date.unit.hx b/tests/unit/src/unitstd/Date.unit.hx index 3e693801..2bd98bd4 100644 --- a/tests/unit/src/unitstd/Date.unit.hx +++ b/tests/unit/src/unitstd/Date.unit.hx @@ -8,4 +8,18 @@ date.getMonth() == 10; date.getDate() == 10; date.getDay() == 3; //date.getTime() == 405781340000.; -date.toString() == "1982-11-10 14:02:20"; \ No newline at end of file +date.toString() == "1982-11-10 14:02:20"; + +var date = Date.fromTime(date.getTime()); +date.getHours() == 14; +date.getMinutes() == 2; +date.getSeconds() == 20; +date.getFullYear() == 1982; +date.getMonth() == 10; +date.getDate() == 10; +date.getDay() == 3; +//date.getTime() == 405781340000.; +date.toString() == "1982-11-10 14:02:20"; + +var date = Date.fromTime(405781340000); +date.getTime() == 405781340000; diff --git a/tests/unit/src/unitstd/EReg.unit.hx b/tests/unit/src/unitstd/EReg.unit.hx index 6f6ed1f9..a685a3b8 100644 --- a/tests/unit/src/unitstd/EReg.unit.hx +++ b/tests/unit/src/unitstd/EReg.unit.hx @@ -87,6 +87,7 @@ pos.len == 2; ~/a/g.replace("bab", "z") == "bzb"; ~/a/g.replace("baba", "z") == "bzbz"; +#if !(hl && interp) // not allowed in local interpreter, still allowed in hl runtime // replace + $ ~/href="(.*?)"/.replace('lead href="foo" trail',"$1") == "lead foo trail"; //~/href="(.*?)"/.replace('lead href="foo" trail',"$2") == "lead $2 trail"; @@ -95,6 +96,11 @@ pos.len == 2; ~/href="(.*?)"/g.replace('lead href="foo" href="bar" trail',"$1") == "lead foo bar trail"; ~/href="(.*?)"/g.replace('lead href="foo" href="bar" trail',"$$$1$$") == "lead $foo$ $bar$ trail"; //~/href="(.*?)"/g.replace('lead href="foo" href="bar" trail',"$$$2$$") == "lead $$2$ $$2$ trail"; +#end + +~/a(b)c/g.replace("abcabc", "$1") == "bb"; +~/(a)|(b)/.replace("abc", '*') == "*bc"; +~/(a)|(b)/g.replace("abc", '*') == "**c"; // map ~/(Hello)/.map("Hello World", function(e) return "Hallo") == "Hallo World"; diff --git a/tests/unit/src/unitstd/EvaluationOrder.unit.hx b/tests/unit/src/unitstd/EvaluationOrder.unit.hx index 62743fc8..f718eb29 100644 --- a/tests/unit/src/unitstd/EvaluationOrder.unit.hx +++ b/tests/unit/src/unitstd/EvaluationOrder.unit.hx @@ -115,4 +115,34 @@ function idx(x, y) { var end = begin(); var _ = (arr(a(), b()))[idx(c(), d())]; -eq(end(), "1_2_3_4"); \ No newline at end of file +eq(end(), "1_2_3_4"); + +function f1() { + buf.push(1); + return function(i) { }; +} + +function f2() { + buf.push(2); + return 2; +} + +var end = begin(); +f1()(f2()); +eq(end(), "1_2"); + +var d:Dynamic = { f1: f1 }; + +function f3() { + buf.push(3); + d.f1 = function(i) { + buf.push(4); + return 4; + } + return 3; +} + +var end = begin(); +d.f1()(f3()); +d.f1(f2()); +eq(end(), "1_3_2_4"); \ No newline at end of file diff --git a/tests/unit/src/unitstd/Float.unit.hx b/tests/unit/src/unitstd/Float.unit.hx new file mode 100644 index 00000000..7e16cbef --- /dev/null +++ b/tests/unit/src/unitstd/Float.unit.hx @@ -0,0 +1,53 @@ +var nan = Math.NaN; +var pinf = Math.POSITIVE_INFINITY; +var ninf = Math.NEGATIVE_INFINITY; +var fl:Float = 0.0; + +fl > nan == false; +fl < nan == false; +fl >= nan == false; +fl <= nan == false; +fl == nan == false; +fl != nan == true; + +nan > nan == false; +nan < nan == false; +nan >= nan == false; +nan <= nan == false; +nan == nan == false; +nan != nan == true; + +pinf > nan == false; +pinf < nan == false; +pinf >= nan == false; +pinf <= nan == false; +pinf == nan == false; +pinf != nan == true; + +ninf > nan == false; +ninf < nan == false; +ninf >= nan == false; +ninf <= nan == false; +ninf == nan == false; +ninf != nan == true; + +nan > fl == false; +nan < fl == false; +nan >= fl == false; +nan <= fl == false; +nan == fl == false; +nan != fl == true; + +nan > pinf == false; +nan < pinf == false; +nan >= pinf == false; +nan <= pinf == false; +nan == pinf == false; +nan != pinf == true; + +nan > ninf == false; +nan < ninf == false; +nan >= ninf == false; +nan <= ninf == false; +nan == ninf == false; +nan != ninf == true; \ No newline at end of file diff --git a/tests/unit/src/unitstd/Https.unit.hx b/tests/unit/src/unitstd/Https.unit.hx new file mode 100644 index 00000000..00b7550c --- /dev/null +++ b/tests/unit/src/unitstd/Https.unit.hx @@ -0,0 +1,4 @@ +#if (cpp || (neko && !macro && !interp)) +var r = haxe.Http.requestUrl("https://raw.githubusercontent.com/HaxeFoundation/haxe/development/tests/unit/res1.txt"); +r == "Héllo World !"; +#end diff --git a/tests/unit/src/unitstd/Issue3067.hx b/tests/unit/src/unitstd/Issue3067.hx index 70299678..fa572d67 100644 --- a/tests/unit/src/unitstd/Issue3067.hx +++ b/tests/unit/src/unitstd/Issue3067.hx @@ -2,17 +2,17 @@ package unit.unitstd; private abstract TestAbstract(Int) from Int to Int { - public var property(get, set):Int; + public var property(get, set):Int; - function get_property():Int - { - return 5; - } + function get_property():Int + { + return 5; + } - function set_property(i:Int):Int - { - return i; - } + function set_property(i:Int):Int + { + return i; + } function manipulateProperty():Void { diff --git a/tests/unit/src/unitstd/Map.unit.hx b/tests/unit/src/unitstd/Map.unit.hx index b35ec1ee..dde4bda5 100644 --- a/tests/unit/src/unitstd/Map.unit.hx +++ b/tests/unit/src/unitstd/Map.unit.hx @@ -9,7 +9,7 @@ var dynmap:Dynamic = map; var map2:haxe.Constraints.IMap = dynmap; var map3:haxe.Constraints.IMap = dynmap; var map4:haxe.Constraints.IMap = dynmap; -Std.is(map, haxe.ds.StringMap) == true; +(map is haxe.ds.StringMap) == true; map.exists("foo") == true; map.exists("bar") == true; map.exists("baz") == true; @@ -49,7 +49,7 @@ map.get(1) == null; map.set(1, 1); map.set(2, 2); map.set(3, 3); -Std.is(map, haxe.ds.IntMap) == true; +(map is haxe.ds.IntMap) == true; map.exists(1) == true; map.exists(2) == true; map.exists(3) == true; diff --git a/tests/unit/src/unitstd/Math.unit.hx b/tests/unit/src/unitstd/Math.unit.hx index c9f4e50c..848285b4 100644 --- a/tests/unit/src/unitstd/Math.unit.hx +++ b/tests/unit/src/unitstd/Math.unit.hx @@ -46,14 +46,14 @@ Math.POSITIVE_INFINITY / one == Math.POSITIVE_INFINITY; Math.NEGATIVE_INFINITY / one == Math.NEGATIVE_INFINITY; //Math.POSITIVE_INFINITY / zero == Math.POSITIVE_INFINITY; //Math.NEGATIVE_INFINITY / zero == Math.NEGATIVE_INFINITY; -Math.isNaN(Math.POSITIVE_INFINITY / Math.POSITIVE_INFINITY); -Math.isNaN(Math.POSITIVE_INFINITY / Math.NEGATIVE_INFINITY); -Math.isNaN(Math.NEGATIVE_INFINITY / Math.POSITIVE_INFINITY); -Math.isNaN(Math.NEGATIVE_INFINITY / Math.NEGATIVE_INFINITY); -Math.isNaN(Math.NaN / Math.POSITIVE_INFINITY); -Math.isNaN(Math.POSITIVE_INFINITY / Math.NaN); -Math.isNaN(Math.NaN / Math.POSITIVE_INFINITY); -Math.isNaN(Math.NEGATIVE_INFINITY / Math.NaN); +Math.isNaN(Math.POSITIVE_INFINITY / Math.POSITIVE_INFINITY) == true; +Math.isNaN(Math.POSITIVE_INFINITY / Math.NEGATIVE_INFINITY) == true; +Math.isNaN(Math.NEGATIVE_INFINITY / Math.POSITIVE_INFINITY) == true; +Math.isNaN(Math.NEGATIVE_INFINITY / Math.NEGATIVE_INFINITY) == true; +Math.isNaN(Math.NaN / Math.POSITIVE_INFINITY) == true; +Math.isNaN(Math.POSITIVE_INFINITY / Math.NaN) == true; +Math.isNaN(Math.NaN / Math.POSITIVE_INFINITY) == true; +Math.isNaN(Math.NEGATIVE_INFINITY / Math.NaN) == true; // abs Math.abs(-1.223) == 1.223; @@ -139,9 +139,7 @@ Math.log(Math.POSITIVE_INFINITY) == Math.POSITIVE_INFINITY; // exp + log var floats = [1.33, 12.0, -112.999992, 0.0, Math.NEGATIVE_INFINITY, Math.POSITIVE_INFINITY]; for (f in floats) { - #if !php feq(Math.log(Math.exp(f)), f); - #end } // sqrt @@ -273,14 +271,14 @@ math.POSITIVE_INFINITY / one == math.POSITIVE_INFINITY; math.NEGATIVE_INFINITY / one == math.NEGATIVE_INFINITY; //math.POSITIVE_INFINITY / zero == math.POSITIVE_INFINITY; //math.NEGATIVE_INFINITY / zero == math.NEGATIVE_INFINITY; -math.isNaN(math.POSITIVE_INFINITY / math.POSITIVE_INFINITY); -math.isNaN(math.POSITIVE_INFINITY / math.NEGATIVE_INFINITY); -math.isNaN(math.NEGATIVE_INFINITY / math.POSITIVE_INFINITY); -math.isNaN(math.NEGATIVE_INFINITY / math.NEGATIVE_INFINITY); -math.isNaN(math.NaN / math.POSITIVE_INFINITY); -math.isNaN(math.POSITIVE_INFINITY / math.NaN); -math.isNaN(math.NaN / math.POSITIVE_INFINITY); -math.isNaN(math.NEGATIVE_INFINITY / math.NaN); +math.isNaN(math.POSITIVE_INFINITY / math.POSITIVE_INFINITY) == true; +math.isNaN(math.POSITIVE_INFINITY / math.NEGATIVE_INFINITY) == true; +math.isNaN(math.NEGATIVE_INFINITY / math.POSITIVE_INFINITY) == true; +math.isNaN(math.NEGATIVE_INFINITY / math.NEGATIVE_INFINITY) == true; +math.isNaN(math.NaN / math.POSITIVE_INFINITY) == true; +math.isNaN(math.POSITIVE_INFINITY / math.NaN) == true; +math.isNaN(math.NaN / math.POSITIVE_INFINITY) == true; +math.isNaN(math.NEGATIVE_INFINITY / math.NaN) == true; // abs math.abs(-1.223) == 1.223; @@ -434,6 +432,3 @@ math.isNaN(math.POSITIVE_INFINITY) == false; math.isNaN(math.NEGATIVE_INFINITY) == false; math.isNaN(math.NaN) == true; math.isNaN(0.0) == false; - - - diff --git a/tests/unit/src/unitstd/Reflect.unit.hx b/tests/unit/src/unitstd/Reflect.unit.hx index b74cbeee..55b2fe09 100644 --- a/tests/unit/src/unitstd/Reflect.unit.hx +++ b/tests/unit/src/unitstd/Reflect.unit.hx @@ -1,4 +1,3 @@ -#if !php // hasField var x = { a: 1, b: null }; Reflect.hasField(x, "a") == true; @@ -15,7 +14,8 @@ Reflect.field(c, "prop") == "prop"; Reflect.field(c, "func")() == "foo"; // As3 invokes the getter Reflect.field(c, "propAcc") == #if as3 "1" #else "0" #end; -Reflect.field(null, null) == null; +var n = null; +Reflect.field(n, n) == null; Reflect.field(1, "foo") == null; // setField @@ -35,7 +35,7 @@ c.v == "bar"; var c = new C2(); Reflect.getProperty(c, "v") == "var"; Reflect.getProperty(c, "prop") == "prop"; -//Reflect.getProperty(c, "func")() == "foo"; +Reflect.getProperty(c, "func")() == "foo"; Reflect.getProperty(c, "propAcc") == "1"; //Reflect.getProperty(null, "a") == null; //Reflect.getProperty(null, null) == null; @@ -48,10 +48,6 @@ Reflect.field(x, "c") == "foo"; var c = new C2(); Reflect.setProperty(c, "v", "bar"); c.v == "bar"; -//Reflect.setProperty(c, "v2", "bar2"); -//c.v2 == "bar"; -//Reflect.setProperty(c, "func2", function() return "x"); -//Reflect.field(c, "func2")() == "x"; Reflect.setProperty(c, "propAcc", "abc"); #if !as3 // not supported on AS3 @@ -153,4 +149,3 @@ Reflect.isEnumValue(true) == false; Reflect.isEnumValue(null) == false; var x:C = null; Reflect.isEnumValue(x) == false; -#end \ No newline at end of file diff --git a/tests/unit/src/unitstd/Ssl.unit.hx b/tests/unit/src/unitstd/Ssl.unit.hx new file mode 100644 index 00000000..e97ae0ce --- /dev/null +++ b/tests/unit/src/unitstd/Ssl.unit.hx @@ -0,0 +1,105 @@ +#if (cpp || (neko && !macro && !interp)) +// Digest +var bin = haxe.io.Bytes.ofString("Hello World!"); +var bin2 = haxe.io.Bytes.ofString("Hello World?"); +sys.ssl.Digest.make( bin, sys.ssl.DigestAlgorithm.MD5 ).toHex().toLowerCase() == "ed076287532e86365e841e92bfc50d8c"; +sys.ssl.Digest.make( bin, sys.ssl.DigestAlgorithm.SHA1 ).toHex().toLowerCase() == "2ef7bde608ce5404e97d5f042f95f89f1c232871"; +sys.ssl.Digest.make( bin, sys.ssl.DigestAlgorithm.SHA224 ).toHex().toLowerCase() == "4575bb4ec129df6380cedde6d71217fe0536f8ffc4e18bca530a7a1b"; +sys.ssl.Digest.make( bin, sys.ssl.DigestAlgorithm.SHA256 ).toHex().toLowerCase() == "7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069"; +sys.ssl.Digest.make( bin, sys.ssl.DigestAlgorithm.SHA384 ).toHex().toLowerCase() == "bfd76c0ebbd006fee583410547c1887b0292be76d582d96c242d2a792723e3fd6fd061f9d5cfd13b8f961358e6adba4a"; +sys.ssl.Digest.make( bin, sys.ssl.DigestAlgorithm.SHA512 ).toHex().toLowerCase() == "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8"; +sys.ssl.Digest.make( bin, sys.ssl.DigestAlgorithm.RIPEMD160 ).toHex().toLowerCase() == "8476ee4631b9b30ac2754b0ee0c47e161d3f724c"; + +// Key loading +var privkey = sys.ssl.Key.readPEM("-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,AE34A89AA63FDD47 + +/kUM/ePW36lW0pg7X6bujFLISlf6r2u28VJ6sZ2TzS4o6x6o8imzX7q0lmTMYCJa +fpjWp9DJPhY6p1a6uEJoyuIJIWKeb1Hc40cpyrC216kHSkdbizlkcqBVGvSZfL1f +KTuLgM3JvRi/i0YYxI6FlLZcAHPQ5mIwr7Jf45azcotNHKlEf0y5RJEzoOGfAAgK +wsVTU7tvJ7E0NJy+DxTuNKzja95jDiCA/DtCqOHVBRkw1sFSOQEISza5HnPce9PG +/bjwI/I9c/UV0hSRo2clSOslljnH3HsroZw94Ek9OJbHWSTcY7/YHyXVI5bbcU9d +fOATh3RLuaRQ6NxgHGLVbcJL6cM+ZqSnLDEAft3UFfxd1KOFDKj6XCJtnJd/UZYv +rq4hEY6RJI8SzbUs3LVnVrNaZjLop+tCK45a2kwWuZztGGMGPZSn3VP0VAts2Iyo +221a9NN+gzQ2CekU/cz1hi8SiRN6g7zwZwwcFZwFUzTdt4ARZTDbf0GSBaqp9QFK +t8LpPR0SsKOFcrpyFDTJ0Ik0YS9K0hruvYWa1g2bcYVRK5hI1qVPgBP46+CwocPA +bUOdenpC3wpAeqrPsRY9jCYc1yeClZaceLe7aRUJkOggyrzRzDn6kbO20IuSRXBS +CSgYNOnoQD2tSqEXq5ui2Ti/JL7qybHYNG4GMhz3waKyyOl1JdmyvqxI91kp2Iwh +SwG1KfWejIvL1UUvuyZI4qrzUnub498vEmqe2l3U7yS8ggu6D3k6lT42LQ6Rzgey +SqOvWugED/b91dP5AXPq0VJAT1A0Rn75YYYpBuq8SFZRfXmFr5K3qgeCFA3hB+TD +qVHxjirxIGM6umV8tJXWeRLWgIPRoBjTi6zYvckhy5hDCw17GCgwe9jHb3xDfpyx +uoTYcPADk4kwq0ylsp4HIsfZ5AjPMDEXi+2A0a9wREJpK8jAF56SaSHRIAfQNeGn +iuihj9fqM6pDL4jx0lIAMH4c8vypraGFTWO4amMtd/67tVMhO4V1el5w61U5qXXl +RYFVQ6TExpX3uKXgomIcWvs214c1ZOdmpC/OZciqv1ga8+zaswQ4zsIuAQD8BYRe +TBEwNUhRg5PqE0Z6I+beWtkD1giLeaKweJ0Dymh9D2mhX7e1WJIuI9j0m8+kT6/k +jURamNaQYLDnIOpUDPm4TqQ4kH6PYX/I7XHx78cfL+Ki58tyCR0Kgk8TJH4o05pZ +hujvigWTp7WM4bL/0GGVTTsGGT36a300rronkOJGh1gWX9HtSAk3QdnxiNJqrhP6 +ZP3mWHaa/qZUr2tfvk5pg7vQ9u1Qny9Xo7JkrNWMUCfvgimYE37BgO8uGsKwjx1a +IMsFlGStF+KKUeCrt2nI+JUFPvQtu//kmnHuqP4dNvr3GTHigS7t2MFYHzKpyIsC +ObNZXrv+q5eMpineWTTetTwfMXX/4oVfAED415i2frAbDeGEH7MFEZcJmkcQY88M +wuvjR5hB9UTMYQPZvRVysrTzCBskKVafMarAeGat42gHVDBKTc5FJ3D4FeQnHN9T +LidMKXdXhV2XNArLSksIaqO3HWiCVwHCsXhwNuYaHuwi2/S2pS6uuzur74fQLYjw +-----END RSA PRIVATE KEY----- +", false, "testpassword"); + +var pub64 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+P8DyzLT52TQ6v7Z8eScRP6QaTQUUa7kyN9mDi2GgvELZB2caBC8uNDNkovLSzMMnM2c3aMkNmKz0NN+IsMV8uFMX2mIiTBDzGuvR6NfEiUIenfcn1ZeX7cWsu0DpJtPCME8nc7MH6FxvK2zZalXO2a2cIDUicI0a4Z1kRaRym2UE+2V6hoT/g5/1e9AxAdCmDzMj4RMhWjRP2XVAZN/6toYMfLmu1aWZr6KJscsS4mG+xDPs3DuCtswLAaMLIrdLNT75ULN170PggUbMSbN/U/SPBjVokq1AX9eVg+0ncrMH/wKA3XosK9Wl10eAnPlnnLm6Wo6T59wJVfOI0xQIDAQAB"; +var pubkey = sys.ssl.Key.readDER(haxe.crypto.Base64.decode(pub64), true); + +// Digest sign / verify +var validSignature = haxe.crypto.Base64.decode("xLuiR9cnoJ3wGcFw1cbo/MC/FsRhTDwIuiMymNrKXj2a5HyUQe4TMSqA4E0KYnJ5kgNk7HDH2fnkNb+avXmA3SSDZf0SIki+SuDxfzyq67XsPnOXKQ7a7uGPl83hCf0pxeUFmRUdhvE6j7dlWZtAx7JFfuCDrk3uibGeEVzlYBUnYpEGY62Bz+299aZwxt+OLxzXafFiM4miirwdXDvCZYPN47xWsQPk3dWav5h1BM/tFswFDVVpef308NI0AAlx7JV+V6aIHQ1gyd2Ul8h0dRLsZ4dGYKjJ1KjGx2jTwSu7kjlEbC8xDsWPvXtS9T4BDDcRKj24nUca0At+vf9XDQ"); + +sys.ssl.Digest.sign( bin, privkey, SHA256 ).toHex() == validSignature.toHex(); +sys.ssl.Digest.verify( bin, validSignature, pubkey, SHA256 ) == true; +sys.ssl.Digest.verify( bin2, validSignature, pubkey, SHA256 ) == false; + +// Certificate loading +var cert = sys.ssl.Certificate.fromString("-----BEGIN CERTIFICATE----- +MIIC5DCCAcygAwIBAgIJAJWLSmriPMaaMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNV +BAoMC1Rlc3QgRGV2IENBMB4XDTE2MDQwNTE5MzE0NVoXDTE3MDQwNTE5MzE0NVow +EjEQMA4GA1UEAwwHZm9vLmJhcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAOPjbM5TJTt6jw6Uc7Yz9/60Krl9zK2Ym1iwO72dXyMKhE+PgxbVPzk4rW+G +yzZ1f3FsOhR/eYNjnYFzf3Zy6sQSZYAGgN50pEBp/toHJOEZs226x6b9TzkG5iTf +3LQocdQKJ4QiMWPah6pktin+3QShIku6Re3AGQd1SvierdaHZog5iolxhj79xIKn +NTTwIC1G5MPSp3GR+V/QK+OtKcWq1UK2gW/Er5EcwpqIkipGmDO6NfhEsaMNeavl +McjyByacnlcgfAbYZjjAR7Ai14538Pac/GElhj8NAu9iz9+ZZknqjtIEPEMDDKbN +lDH6LSEAwM5eWF7C/2FWQ5R3CMECAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8E +BAMCBeAwHQYDVR0RBBYwFIIHZm9vLmJhcoIJKi5mb28uYmFyMA0GCSqGSIb3DQEB +CwUAA4IBAQDXNBkh3eX8le0sCThAixyiz1JuHbL8Tafe2wIg4HyMzyIjuXpxWfW7 +jyev8uyCygi0pf8TyNsKody7HFiQoOVWRnC0LbePyqR2h1p7vT2BgGsIiaSIHbW4 +rQoKt0y/KdWiGJLUSMHLEVgWPklGiA9ishReDOGvCVgVd304fvUP6ZV/mxf4ELMT +Np5OwAWm5fI34hFaiE0r0RrIH5+8w/gVHSfd/rIjj8fDOY+sVtfzqrKPQphCyGLF +n/v3xUnxsxxifJh/2MRYfE/O2u30/ykqA1y7X4eIABCbgCC+rz9TVZ/DyjD4BygV +28oMByzQLr93aM98ckvjO5wxRy6Mo71K +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC6jCCAdKgAwIBAgIJAJWLSmriPMaZMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNV +BAoMC1Rlc3QgRGV2IENBMB4XDTE2MDQwNTE5MzE0NVoXDTE3MDQwNTE5MzE0NVow +FDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA0VoP00HD8xWuUIgwWBrBPX1Gnbja8fhSvmnNV/jOuM2MXqvFNkuAyQFF +1SpwkIy1ooRLoBdo8choXe9BjPjTC2YH+Vwemn0J+cIV9aIZnXpmHS5ZCLBW+HDa +2b0AhaabwsxBA1vG+FR8o/BRFkv66NvGbLcsIzu1QioEm2Sd2/oPiyDTmrjPPcEM +a2aZiupJTZ+3KCpLwiU+BysHOkGlrKyjw82UPjN1LQAMuh25MMR+RsupQvACK8Zh +PxWrNK8mrXW8riRhtOk/IVNYlZzNQDn6OiRaVSJ8qGkCPqm7MnHN6WMpFBK3wQ02 +2y3NNbeFjp4jYbeQHOEzlHtK6g9YCwIDAQABoz0wOzAJBgNVHRMEAjAAMAsGA1Ud +DwQEAwIF4DAhBgNVHREEGjAYgglsb2NhbGhvc3SCCyoubG9jYWxob3N0MA0GCSqG +SIb3DQEBCwUAA4IBAQD1msPYV9RtW38bt8lpPQMF4Y4BdAJLn4pOVAD055vIWNVw +aBUxLWwcbrQaumBW3umC431htJ5tNNAJotO948j6lXXbRh9VJ4+MOW8XOr+/1zND +/5V3Cz5H4164pNnDpHZ5rW+TqzGSxsrTZ0FERxoCFhQo0oEN+AYV8B6eIddpiNWt +MccLWmDU6orMFKgr00yCrXEaGTii6WDxp4EvY+cu/a7XgABJ/OFFe+zEw0gZR1IC +SNEHn0VdnXaqmzA95EK7N0bBQ/95InK1DGU91UdTeERGM2hDxTTfV9VLHqHSgwWC +0unMCkyljEla27PLNyDnNEFc77cscjtUUEt2V0Jv +-----END CERTIFICATE----- +"); + +cert.commonName == "foo.bar"; +cert.altNames[0] == "foo.bar"; +cert.altNames[1] == "*.foo.bar"; +cert.notBefore.getFullYear() == 2016; +cert.notAfter.getFullYear() == 2017; +cert.issuer("O") == "Test Dev CA"; + +var cert2 = cert.next(); +cert2.commonName == "localhost"; + +#end diff --git a/tests/unit/src/unitstd/Std.unit.hx b/tests/unit/src/unitstd/Std.unit.hx index 985ffcfb..14b59305 100644 --- a/tests/unit/src/unitstd/Std.unit.hx +++ b/tests/unit/src/unitstd/Std.unit.hx @@ -1,19 +1,19 @@ // is var known:String = null; -Std.is(known, String) == false; +(known is String) == false; var unknown = null; -Std.is(unknown, String) == false; -Std.is(null, String) == false; -Std.is("foo", null) == false; +(unknown is String) == false; +(null is String) == false; +//("foo" is null) == false; -Std.is("", String) == true; -Std.is(false, Bool) == true; -Std.is(1, Int) == true; -Std.is(1.5, Int) == false; -Std.is(1.5, Float) == true; -Std.is([], Array) == true; -Std.is(cast unit.MyEnum.A, Array) == false; +("" is String) == true; +(false is Bool) == true; +(1 is Int) == true; +(1.5 is Int) == false; +(1.5 is Float) == true; +([] is Array) == true; +(cast unit.MyEnum.A is Array) == false; // instance #if !js diff --git a/tests/unit/src/unitstd/String.unit.hx b/tests/unit/src/unitstd/String.unit.hx index 594541e4..f2f95b5b 100644 --- a/tests/unit/src/unitstd/String.unit.hx +++ b/tests/unit/src/unitstd/String.unit.hx @@ -151,6 +151,8 @@ s.substring(0, 100) == "xfooxfooxxbarxbarxx"; s.substring(100, 120) == ""; s.substring(100, 0) == "xfooxfooxxbarxbarxx"; s.substring(120, 100) == ""; +s.substring(5, 8) == "foo"; +s.substring(8, 5) == "foo"; // fromCharCode String.fromCharCode(65) == "A"; diff --git a/tests/unit/src/unitstd/StringTools.unit.hx b/tests/unit/src/unitstd/StringTools.unit.hx index 96933b0c..4ed46d4b 100644 --- a/tests/unit/src/unitstd/StringTools.unit.hx +++ b/tests/unit/src/unitstd/StringTools.unit.hx @@ -133,7 +133,7 @@ StringTools.isEof(StringTools.fastCodeAt(str, 3)) == true; StringTools.isEof(StringTools.fastCodeAt("", 0)) == true; // isEOF -#if neko +#if (neko || lua) StringTools.isEof(null) == true; #elseif (cs || java || python) StringTools.isEof( -1) == true; diff --git a/tests/unit/src/unitstd/Type.unit.hx b/tests/unit/src/unitstd/Type.unit.hx index 54f6f324..960b9c10 100644 --- a/tests/unit/src/unitstd/Type.unit.hx +++ b/tests/unit/src/unitstd/Type.unit.hx @@ -104,6 +104,7 @@ var requiredFields = ["func", "v", "prop"]; for (f in fields) t(requiredFields.remove(f)); requiredFields == []; +#if !hl // no support for implements Dynamic yet var cdyn = new CDyn(); cdyn.foo = "1"; Reflect.setField(cdyn, "bar", 1); @@ -111,6 +112,7 @@ var fields = Type.getInstanceFields(Type.getClass(cdyn)); var requiredFields = ["func", "v", "prop"]; for (f in fields) t(requiredFields.remove(f)); +#end requiredFields == []; var fields = Type.getClassFields(C); var requiredFields = #if as3 ["staticVar"] #else ["staticFunc", "staticVar", "staticProp"] #end; diff --git a/tests/unit/src/unitstd/haxe/CallStack.unit.hx b/tests/unit/src/unitstd/haxe/CallStack.unit.hx index 641e95b5..ddf33f9d 100644 --- a/tests/unit/src/unitstd/haxe/CallStack.unit.hx +++ b/tests/unit/src/unitstd/haxe/CallStack.unit.hx @@ -1,20 +1,20 @@ var stack = haxe.CallStack.callStack(); -Std.is(stack, Array) == true; +(stack is Array) == true; var stack = haxe.CallStack.exceptionStack(); -Std.is(stack, Array) == true; +(stack is Array) == true; try { - throw false; + throw false; } catch (_:Dynamic) { - var stack = haxe.CallStack.exceptionStack(); - Std.is(stack, Array) == true; + var stack = haxe.CallStack.exceptionStack(); + (stack is Array) == true; } #if js var old = @:privateAccess haxe.CallStack.lastException; @:privateAccess haxe.CallStack.lastException = null; var stack = haxe.CallStack.exceptionStack(); -Std.is(stack, Array) == true; +(stack is Array) == true; stack.length == 0; @:privateAccess haxe.CallStack.lastException = old; #end \ No newline at end of file diff --git a/tests/unit/src/unitstd/haxe/DynamicAccess.unit.hx b/tests/unit/src/unitstd/haxe/DynamicAccess.unit.hx index 275edf57..20809ca2 100644 --- a/tests/unit/src/unitstd/haxe/DynamicAccess.unit.hx +++ b/tests/unit/src/unitstd/haxe/DynamicAccess.unit.hx @@ -12,7 +12,7 @@ map.get("bar") == 2; map.get("baz") == 3; var values = []; for (key in map.keys()) { - values.push(map[key]); + values.push(map[key]); } values.length == 3; values[0] in [1, 2, 3]; @@ -20,7 +20,7 @@ values[1] in [1, 2, 3]; values[2] in [1, 2, 3]; var keys = ["foo", "bar", "baz"]; for (key in map.keys()) { - t(keys.remove(key)); + t(keys.remove(key)); } keys == []; map.remove("bar") == true; diff --git a/tests/unit/src/unitstd/haxe/Utf8.unit.hx b/tests/unit/src/unitstd/haxe/Utf8.unit.hx index c5324eb6..bc2876a4 100644 --- a/tests/unit/src/unitstd/haxe/Utf8.unit.hx +++ b/tests/unit/src/unitstd/haxe/Utf8.unit.hx @@ -30,6 +30,8 @@ haxe.Utf8.length(str) == 3; haxe.Utf8.charCodeAt(str, 0) == 0x3042; haxe.Utf8.charCodeAt(str, 1) == 0xE9; haxe.Utf8.charCodeAt(str, 2) == 0x3044; +var big = new haxe.Utf8(10); +big.toString().length == 0; var buf = new haxe.Utf8(); buf.addChar(0x3042); buf.addChar(0xE9); @@ -44,7 +46,20 @@ haxe.Utf8.compare(haxe.Utf8.sub(str, 1, 0), "") == 0; // unspecify outside of range Utf8.sub // haxe.Utf8.compare(haxe.Utf8.sub(str, 9, 0), "") == 0; +// #if (neko || php || cpp || lua || macro) +// TODO neko, cpp, macro +#if (php || lua) +haxe.Utf8.validate("\xf0\xa9\xb8\xbd\xe3\x81\x82\xc3\xab\x61") == true; +haxe.Utf8.validate("\xed\x9f\xbf") == true; +haxe.Utf8.validate("\xee\x80\x80") == true; +haxe.Utf8.validate("\xf4\x8f\xbf\xbf") == true; +haxe.Utf8.validate("\xf0\xa9\xb8\xbd\xe3\x81\xc3\xab\x61") == false; +haxe.Utf8.validate("\xc0\xaf") == false; // redundant sequence +haxe.Utf8.validate("\xed\xa0\x80") == false; // surrogate byte sequence +haxe.Utf8.validate("\xed\xbf\xbf") == false; // surrogate byte sequence +haxe.Utf8.validate("\xf4\x90\x80\x80") == false; // U+110000 +#end #if php } -#end \ No newline at end of file +#end diff --git a/tests/unit/src/unitstd/haxe/ds/Vector.unit.hx b/tests/unit/src/unitstd/haxe/ds/Vector.unit.hx index 4d0401b7..8eed5327 100644 --- a/tests/unit/src/unitstd/haxe/ds/Vector.unit.hx +++ b/tests/unit/src/unitstd/haxe/ds/Vector.unit.hx @@ -1,7 +1,7 @@ var vec = new haxe.ds.Vector(3); -var vNullInt = #if (flash || cpp || java || cs) 0 #else null #end; -var vNullBool = #if (flash || cpp || java || cs) false #else null #end; -var vNullFloat = #if (flash || cpp || java || cs) 0.0 #else null #end; +var vNullInt = #if (flash || cpp || java || cs || hl) 0 #else null #end; +var vNullBool = #if (flash || cpp || java || cs || hl) false #else null #end; +var vNullFloat = #if (flash || cpp || java || cs || hl) 0.0 #else null #end; vec.length == 3; vec.get(0) == vNullInt; @@ -31,7 +31,7 @@ vec.get(2) == vNullBool; // fromArray var arr = ["1", "2", "3"]; var vec:haxe.ds.Vector = haxe.ds.Vector.fromArrayCopy(arr); -#if (!flash && !neko && !cs && !java) +#if (!flash && !neko && !cs && !java && !lua) arr != vec.toData(); #end vec.length == 3; @@ -89,6 +89,30 @@ vec3[4] == 4; vec3[5] == 5; vec3[6] == 6; +var vec5 = haxe.ds.Vector.fromArrayCopy([0,1,2,3,4]); +haxe.ds.Vector.blit(vec5, 0, vec5, 1, 4); +vec5[0] == 0; +vec5[1] == 0; +vec5[2] == 1; +vec5[3] == 2; +vec5[4] == 3; + +var vec5 = haxe.ds.Vector.fromArrayCopy([0,1,2,3,4]); +haxe.ds.Vector.blit(vec5, 1, vec5, 0, 4); +vec5[0] == 1; +vec5[1] == 2; +vec5[2] == 3; +vec5[3] == 4; +vec5[4] == 4; + +var vec5 = haxe.ds.Vector.fromArrayCopy([0,1,2,3,4]); +haxe.ds.Vector.blit(vec5, 0, vec5, 0, 5); +vec5[0] == 0; +vec5[1] == 1; +vec5[2] == 2; +vec5[3] == 3; +vec5[4] == 4; + // test iteration var vec1 = new haxe.ds.Vector(2); @@ -100,3 +124,65 @@ for (e in vec1) { } eq(3, res); +// copy + +var i0 = new IntWrap(1); +var i1 = new IntWrap(1); +var i2 = new IntWrap(5); + +var vec = new haxe.ds.Vector(3); +vec[0] = i0; +vec[1] = i1; +vec[2] = i2; +var vec2 = vec.copy(); +f(vec == vec2); +vec[0] == vec2[0]; +vec[1] == vec2[1]; +vec[2] == vec2[2]; + +// join + +var vec = new haxe.ds.Vector(0); +vec.join(",") == ""; + +var vec = new haxe.ds.Vector(1); +vec.join(",") == "null"; + +var vec = new haxe.ds.Vector(2); +vec.join(",") == "null,null"; + +var vec = new haxe.ds.Vector(2); +vec[0] = "foo"; +vec[1] = "bar"; +vec.join(", ") == "foo, bar"; + + +// map + +var vec = new haxe.ds.Vector(0); +vec.map(function(i) { + throw false; + return null; +}); + +var vec = new haxe.ds.Vector(2); +vec[0] = 12; +vec[1] = 13; +var vec2 = vec.map(function(i) return "value: " +i); +vec2[0] == "value: 12"; +vec2[1] == "value: 13"; + +// sort + +#if !(neko || cs || java) +var vec = new haxe.ds.Vector(4); +vec[0] = 99; +vec[1] = 101; +vec[2] = -12; +vec[3] = 0; +vec.sort(Reflect.compare); +vec[0] == -12; +vec[1] == 0; +vec[2] == 99; +vec[3] == 101; +#end diff --git a/tests/unit/src/unitstd/haxe/extern/EitherType.unit.hx b/tests/unit/src/unitstd/haxe/extern/EitherType.unit.hx index cbb7c0b6..8b30be1a 100644 --- a/tests/unit/src/unitstd/haxe/extern/EitherType.unit.hx +++ b/tests/unit/src/unitstd/haxe/extern/EitherType.unit.hx @@ -4,5 +4,5 @@ s == "string"; e = 1; var i:Int = e; i == 1; -TestType.typeError(e = false) == true; -TestType.typeError(e = 1.5) == true; +HelperMacros.typeError(e = false) == true; +HelperMacros.typeError(e = 1.5) == true; diff --git a/tests/unit/src/unitstd/haxe/io/BytesBuffer.unit.hx b/tests/unit/src/unitstd/haxe/io/BytesBuffer.unit.hx index d35981c2..4095d241 100644 --- a/tests/unit/src/unitstd/haxe/io/BytesBuffer.unit.hx +++ b/tests/unit/src/unitstd/haxe/io/BytesBuffer.unit.hx @@ -25,16 +25,20 @@ out.addByte(42); out.addFloat(1.3); out.addDouble(2.4); out.addInt64(haxe.Int64.make(0xABCDEF00,0xCAFFEED1)); +out.addDouble(Math.POSITIVE_INFINITY); +out.addDouble(Math.NEGATIVE_INFINITY); var b = out.getBytes(); -b.length == 25; +b.length == 41; b.getInt32(0) == 0xABCDEF00; b.get(4) == 42; b.getFloat(5) == 1.2999999523162842; b.getDouble(9) == 2.4; t(b.getInt64(17) == haxe.Int64.make(0xABCDEF00,0xCAFFEED1)); +b.getDouble(25) == Math.POSITIVE_INFINITY; +b.getDouble(33) == Math.NEGATIVE_INFINITY; // check correct low endian encoding b.get(3) == 0xAB; diff --git a/tests/unit/src/unitstd/haxe/io/FPHelper.unit.hx b/tests/unit/src/unitstd/haxe/io/FPHelper.unit.hx new file mode 100644 index 00000000..924fa25f --- /dev/null +++ b/tests/unit/src/unitstd/haxe/io/FPHelper.unit.hx @@ -0,0 +1,11 @@ +function fp32( f : Float ) : Float { + return haxe.io.FPHelper.i32ToFloat(haxe.io.FPHelper.floatToI32(f)); +} + +fp32( -1.3 ) == -1.2999999523162842; +fp32( 15.999999 ) == 15.999999046325684; +fp32( 15.999999999 ) == 16; +fp32( 16 ) == 16; +fp32( 16.000000001 ) == 16; +fp32( 16.000001 ) == 16.000001907348633; + diff --git a/tests/unit/src/unitstd/haxe/zip/Compress.unit.hx b/tests/unit/src/unitstd/haxe/zip/Compress.unit.hx new file mode 100644 index 00000000..a5f6fbcf --- /dev/null +++ b/tests/unit/src/unitstd/haxe/zip/Compress.unit.hx @@ -0,0 +1,33 @@ +// not supported in js/python/cs yet +#if (cpp || php || java || neko || flash) +var b = haxe.io.Bytes.ofString("test"); +var c = haxe.zip.Compress.run(b, 9); + +c.length == 12; +c.get(0) == 120; +c.get(1) == 218; +c.get(2) == 43; +c.get(3) == 73; +c.get(4) == 45; +c.get(5) == 46; +c.get(6) == 1; +c.get(7) == 0; +c.get(8) == 4; +c.get(9) == 93; +c.get(10) == 1; +c.get(11) == 193; + +var b = haxe.io.Bytes.alloc(0); +var c = haxe.zip.Compress.run(b, 9); + +c.length == 8; +c.get(0) == 120; +c.get(1) == 218; +c.get(2) == 3; +c.get(3) == 0; +c.get(4) == 0; +c.get(5) == 0; +c.get(6) == 0; +c.get(7) == 1; + +#end diff --git a/tests/unit/unit-js.html b/tests/unit/unit-js.html index 5f23fded..7b3a7d33 100644 --- a/tests/unit/unit-js.html +++ b/tests/unit/unit-js.html @@ -7,7 +7,22 @@ - - + + \ No newline at end of file diff --git a/tests/unit/unit.html b/tests/unit/unit.html index 50771eee..71da94f6 100644 --- a/tests/unit/unit.html +++ b/tests/unit/unit.html @@ -47,6 +47,10 @@ iframe {
Neko
+
+
Lua
+
+
Php
diff --git a/tests/unit/unit.hxproj b/tests/unit/unit.hxproj index e712f226..d975ccb9 100644 --- a/tests/unit/unit.hxproj +++ b/tests/unit/unit.hxproj @@ -62,7 +62,7 @@ - "$(CompilerPath)/haxe" compile$(TargetBuild).hxml + "$(CompilerPath)/haxe.exe" compile$(TargetBuild).hxml diff --git a/extra/haxelib_src/site.hxproj b/tests/unit/unit_hl.hxproj similarity index 64% rename from extra/haxelib_src/site.hxproj rename to tests/unit/unit_hl.hxproj index 1e5c08ee..3bde5bdd 100644 --- a/extra/haxelib_src/site.hxproj +++ b/tests/unit/unit_hl.hxproj @@ -1,52 +1,57 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + haxe compile-hl.hxml -D fail_eager -D dump + + + + + + + \ No newline at end of file diff --git a/typecore.ml b/typecore.ml deleted file mode 100644 index 7b740a83..00000000 --- a/typecore.ml +++ /dev/null @@ -1,525 +0,0 @@ -(* - * Copyright (C)2005-2013 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. - *) - -open Common -open Type - -type with_type = - | NoValue - | Value - | WithType of t - | WithTypeResume of t - -type type_patch = { - mutable tp_type : Ast.complex_type option; - mutable tp_remove : bool; - mutable tp_meta : Ast.metadata; -} - -type current_fun = - | FunMember - | FunStatic - | FunConstructor - | FunMemberAbstract - | FunMemberClassLocal - | FunMemberAbstractLocal - -type macro_mode = - | MExpr - | MBuild - | MMacroType - - -type typer_pass = - | PBuildModule (* build the module structure and setup module type parameters *) - | PBuildClass (* build the class structure *) - | PTypeField (* type the class field, allow access to types structures *) - | PCheckConstraint (* perform late constraint checks with inferred types *) - | PForce (* usually ensure that lazy have been evaluated *) - | PFinal (* not used, only mark for finalize *) - -type typer_globals = { - types_module : (path, path) Hashtbl.t; - modules : (path , module_def) Hashtbl.t; - mutable delayed : (typer_pass * (unit -> unit) list) list; - mutable debug_delayed : (typer_pass * ((unit -> unit) * string * typer) list) list; - doinline : bool; - mutable core_api : typer option; - mutable macros : ((unit -> unit) * typer) option; - mutable std : module_def; - mutable hook_generate : (unit -> unit) list; - type_patches : (path, (string * bool, type_patch) Hashtbl.t * type_patch) Hashtbl.t; - mutable global_metadata : (string list * Ast.metadata_entry * (bool * bool * bool)) list; - mutable get_build_infos : unit -> (module_type * t list * Ast.class_field list) option; - delayed_macros : (unit -> unit) DynArray.t; - mutable global_using : tclass list; - (* api *) - do_inherit : typer -> Type.tclass -> Ast.pos -> Ast.class_flag -> bool; - do_create : Common.context -> typer; - do_macro : typer -> macro_mode -> path -> string -> Ast.expr list -> Ast.pos -> Ast.expr option; - do_load_module : typer -> path -> pos -> module_def; - do_optimize : typer -> texpr -> texpr; - do_build_instance : typer -> module_type -> pos -> ((string * t) list * path * (t list -> t)); -} - -and typer_module = { - curmod : module_def; - mutable module_types : module_type list; - mutable module_using : tclass list; - mutable module_globals : (string, (module_type * string)) PMap.t; - mutable wildcard_packages : string list list; -} - -and typer = { - (* shared *) - com : context; - t : basic_types; - g : typer_globals; - mutable meta : metadata; - mutable this_stack : texpr list; - mutable with_type_stack : with_type list; - mutable call_argument_stack : Ast.expr list list; - (* variable *) - mutable pass : typer_pass; - (* per-module *) - mutable m : typer_module; - (* per-class *) - mutable curclass : tclass; - mutable tthis : t; - mutable type_params : (string * t) list; - (* per-function *) - mutable curfield : tclass_field; - mutable untyped : bool; - mutable in_super_call : bool; - mutable in_loop : bool; - mutable in_display : bool; - mutable in_macro : bool; - mutable macro_depth : int; - mutable curfun : current_fun; - mutable ret : t; - mutable locals : (string, tvar) PMap.t; - mutable opened : anon_status ref list; - mutable vthis : tvar option; - (* events *) - mutable on_error : typer -> string -> pos -> unit; -} - -type call_error = - | Not_enough_arguments - | Too_many_arguments - | Could_not_unify of error_msg - | Cannot_skip_non_nullable of string - -and error_msg = - | Module_not_found of path - | Type_not_found of path * string - | Unify of unify_error list - | Custom of string - | Unknown_ident of string - | Stack of error_msg * error_msg - | Call_error of call_error - -exception Fatal_error of string * Ast.pos - -exception Forbid_package of (string * path * pos) * pos list * string - -exception Error of error_msg * pos - -exception DisplayTypes of t list - -exception DisplayPosition of Ast.pos list - -let make_call_ref : (typer -> texpr -> texpr list -> t -> pos -> texpr) ref = ref (fun _ _ _ _ _ -> assert false) -let type_expr_ref : (typer -> Ast.expr -> with_type -> texpr) ref = ref (fun _ _ _ -> assert false) -let type_module_type_ref : (typer -> module_type -> t list option -> pos -> texpr) ref = ref (fun _ _ _ _ -> assert false) -let unify_min_ref : (typer -> texpr list -> t) ref = ref (fun _ _ -> assert false) -let match_expr_ref : (typer -> Ast.expr -> (Ast.expr list * Ast.expr option * Ast.expr option) list -> Ast.expr option option -> with_type -> Ast.pos -> decision_tree) ref = ref (fun _ _ _ _ _ _ -> assert false) -let get_pattern_locals_ref : (typer -> Ast.expr -> Type.t -> (string, tvar * pos) PMap.t) ref = ref (fun _ _ _ -> assert false) -let get_constructor_ref : (typer -> tclass -> t list -> Ast.pos -> (t * tclass_field)) ref = ref (fun _ _ _ _ -> assert false) -let cast_or_unify_ref : (typer -> t -> texpr -> Ast.pos -> texpr) ref = ref (fun _ _ _ _ -> assert false) -let find_array_access_raise_ref : (typer -> tabstract -> tparams -> texpr -> texpr option -> pos -> (tclass_field * t * t * texpr * texpr option)) ref = ref (fun _ _ _ _ _ _ -> assert false) - -(* Source: http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#OCaml *) -let levenshtein a b = - let x = Array.init (String.length a) (fun i -> a.[i]) in - let y = Array.init (String.length b) (fun i -> b.[i]) in - let minimum (x:int) y z = - let m' (a:int) b = if a < b then a else b in - m' (m' x y) z - in - let init_matrix n m = - let init_col = Array.init m in - Array.init n (function - | 0 -> init_col (function j -> j) - | i -> init_col (function 0 -> i | _ -> 0) - ) - in - match Array.length x, Array.length y with - | 0, n -> n - | m, 0 -> m - | m, n -> - let matrix = init_matrix (m + 1) (n + 1) in - for i = 1 to m do - let s = matrix.(i) and t = matrix.(i - 1) in - for j = 1 to n do - let cost = abs (compare x.(i - 1) y.(j - 1)) in - s.(j) <- minimum (t.(j) + 1) (s.(j - 1) + 1) (t.(j - 1) + cost) - done - done; - matrix.(m).(n) - -let string_error_raise s sl msg = - if sl = [] then msg else - let cl = List.map (fun s2 -> s2,levenshtein s s2) sl in - let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in - let rec loop sl = match sl with - | (s2,i) :: sl when i <= (min (String.length s) (String.length s2)) / 3 -> s2 :: loop sl - | _ -> [] - in - match loop cl with - | [] -> raise Not_found - | [s] -> Printf.sprintf "%s (Suggestion: %s)" msg s - | sl -> Printf.sprintf "%s (Suggestions: %s)" msg (String.concat ", " sl) - -let string_error s sl msg = - try string_error_raise s sl msg - with Not_found -> msg - -let string_source t = match follow t with - | TInst(c,_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_fields - | TAnon a -> PMap.fold (fun cf acc -> cf.cf_name :: acc) a.a_fields [] - | TAbstract({a_impl = Some c},_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_statics - | _ -> [] - -let short_type ctx t = - let tstr = s_type ctx t in - if String.length tstr > 150 then String.sub tstr 0 147 ^ "..." else tstr - -let unify_error_msg ctx = function - | Cannot_unify (t1,t2) -> - s_type ctx t1 ^ " should be " ^ s_type ctx t2 - | Invalid_field_type s -> - "Invalid type for field " ^ s ^ " :" - | Has_no_field (t,n) -> - string_error n (string_source t) (short_type ctx t ^ " has no field " ^ n) - | Has_no_runtime_field (t,n) -> - s_type ctx t ^ "." ^ n ^ " is not accessible at runtime" - | Has_extra_field (t,n) -> - short_type ctx t ^ " has extra field " ^ n - | Invalid_kind (f,a,b) -> - (match a, b with - | Var va, Var vb -> - let name, stra, strb = if va.v_read = vb.v_read then - "setter", s_access false va.v_write, s_access false vb.v_write - else if va.v_write = vb.v_write then - "getter", s_access true va.v_read, s_access true vb.v_read - else - "access", "(" ^ s_access true va.v_read ^ "," ^ s_access false va.v_write ^ ")", "(" ^ s_access true vb.v_read ^ "," ^ s_access false vb.v_write ^ ")" - in - "Inconsistent " ^ name ^ " for field " ^ f ^ " : " ^ stra ^ " should be " ^ strb - | _ -> - "Field " ^ f ^ " is " ^ s_kind a ^ " but should be " ^ s_kind b) - | Invalid_visibility n -> - "The field " ^ n ^ " is not public" - | Not_matching_optional n -> - "Optional attribute of parameter " ^ n ^ " differs" - | Cant_force_optional -> - "Optional parameters can't be forced" - | Invariant_parameter _ -> - "Type parameters are invariant" - | Constraint_failure name -> - "Constraint check failure for " ^ name - | Missing_overload (cf, t) -> - cf.cf_name ^ " has no overload for " ^ s_type ctx t - | Unify_custom msg -> - msg - -let rec error_msg = function - | Module_not_found m -> "Type not found : " ^ Ast.s_type_path m - | Type_not_found (m,t) -> "Module " ^ Ast.s_type_path m ^ " does not define type " ^ t - | Unify l -> - let ctx = print_context() in - String.concat "\n" (List.map (unify_error_msg ctx) l) - | Unknown_ident s -> "Unknown identifier : " ^ s - | Custom s -> s - | Stack (m1,m2) -> error_msg m1 ^ "\n" ^ error_msg m2 - | Call_error err -> s_call_error err - -and s_call_error = function - | Not_enough_arguments -> "Not enough arguments" - | Too_many_arguments -> "Too many arguments" - | Could_not_unify err -> error_msg err - | Cannot_skip_non_nullable s -> "Cannot skip non-nullable argument " ^ s - -let pass_name = function - | PBuildModule -> "build-module" - | PBuildClass -> "build-class" - | PTypeField -> "type-field" - | PCheckConstraint -> "check-constraint" - | PForce -> "force" - | PFinal -> "final" - -let display_error ctx msg p = ctx.on_error ctx msg p - -let error msg p = raise (Error (Custom msg,p)) - -let make_call ctx e el t p = (!make_call_ref) ctx e el t p - -let type_expr ctx e with_type = (!type_expr_ref) ctx e with_type - -let unify_min ctx el = (!unify_min_ref) ctx el - -let match_expr ctx e cases def with_type p = !match_expr_ref ctx e cases def with_type p - -let make_static_call ctx c cf map args t p = - let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in - let ethis = mk (TTypeExpr (TClassDecl c)) ta p in - let monos = List.map (fun _ -> mk_mono()) cf.cf_params in - let map t = map (apply_params cf.cf_params monos t) in - let ef = mk (TField (ethis,(FStatic (c,cf)))) (map cf.cf_type) p in - make_call ctx ef args (map t) p - -let unify ctx t1 t2 p = - try - Type.unify t1 t2 - with - Unify_error l -> - if not ctx.untyped then display_error ctx (error_msg (Unify l)) p - -let unify_raise ctx t1 t2 p = - try - Type.unify t1 t2 - with - Unify_error l -> - (* no untyped check *) - raise (Error (Unify l,p)) - -let save_locals ctx = - let locals = ctx.locals in - (fun() -> ctx.locals <- locals) - -let add_local ctx n t = - let v = alloc_var n t in - ctx.locals <- PMap.add n v ctx.locals; - v - -let gen_local_prefix = "`" - -let gen_local ctx t = - (* ensure that our generated local does not mask an existing one *) - let rec loop n = - let nv = (if n = 0 then gen_local_prefix else gen_local_prefix ^ string_of_int n) in - if PMap.mem nv ctx.locals then - loop (n+1) - else - nv - in - add_local ctx (loop 0) t - -let is_gen_local v = - String.unsafe_get v.v_name 0 = String.unsafe_get gen_local_prefix 0 - -let not_opened = ref Closed -let mk_anon fl = TAnon { a_fields = fl; a_status = not_opened; } - -let delay ctx p f = - let rec loop = function - | [] -> [p,[f]] - | (p2,l) :: rest -> - if p2 = p then - (p, f :: l) :: rest - else if p2 < p then - (p2,l) :: loop rest - else - (p,[f]) :: (p2,l) :: rest - in - ctx.g.delayed <- loop ctx.g.delayed - -let rec flush_pass ctx p (where:string) = - match ctx.g.delayed with - | (p2,l) :: rest when p2 <= p -> - (match l with - | [] -> - ctx.g.delayed <- rest; - | f :: l -> - ctx.g.delayed <- (p2,l) :: rest; - f()); - flush_pass ctx p where - | _ -> - () - -let make_pass ctx f = f - -let init_class_done ctx = - ctx.pass <- PTypeField - -let exc_protect ctx f (where:string) = - let rec r = ref (fun() -> - try - f r - with - | Error (m,p) -> - raise (Fatal_error ((error_msg m),p)) - ) in - r - -let fake_modules = Hashtbl.create 0 -let create_fake_module ctx file = - let file = Common.unique_full_path file in - let mdep = (try Hashtbl.find fake_modules file with Not_found -> - let mdep = { - m_id = alloc_mid(); - m_path = (["$DEP"],file); - m_types = []; - m_extra = module_extra file (Common.get_signature ctx.com) (file_time file) MFake; - } in - Hashtbl.add fake_modules file mdep; - mdep - ) in - Hashtbl.replace ctx.g.modules mdep.m_path mdep; - mdep - -(* -------------- debug functions to activate when debugging typer passes ------------------------------- *) -(*/* - -let delay_tabs = ref "" - -let context_ident ctx = - if Common.defined ctx.com Common.Define.CoreApi then - " core " - else if Common.defined ctx.com Common.Define.Macro then - "macro " - else - " out " - -let debug ctx str = - if Common.raw_defined ctx.com "cdebug" then prerr_endline (context_ident ctx ^ !delay_tabs ^ str) - -let init_class_done ctx = - debug ctx ("init_class_done " ^ Ast.s_type_path ctx.curclass.cl_path); - init_class_done ctx - -let ctx_pos ctx = - let inf = Ast.s_type_path ctx.m.curmod.m_path in - let inf = (match snd ctx.curclass.cl_path with "" -> inf | n when n = snd ctx.m.curmod.m_path -> inf | n -> inf ^ "." ^ n) in - let inf = (match ctx.curfield.cf_name with "" -> inf | n -> inf ^ ":" ^ n) in - inf - -let pass_infos ctx p = - let inf = pass_name p ^ " (" ^ ctx_pos ctx ^ ")" in - let inf = if ctx.pass > p then inf ^ " ??CURPASS=" ^ pass_name ctx.pass else inf in - inf - -let delay ctx p f = - let inf = pass_infos ctx p in - let rec loop = function - | [] -> [p,[f,inf,ctx]] - | (p2,l) :: rest -> - if p2 = p then - (p, (f,inf,ctx) :: l) :: rest - else if p2 < p then - (p2,l) :: loop rest - else - (p,[f,inf,ctx]) :: (p2,l) :: rest - in - ctx.g.debug_delayed <- loop ctx.g.debug_delayed; - debug ctx ("add " ^ inf) - -let pending_passes ctx = - let rec loop acc = function - | (p,l) :: pl when p < ctx.pass -> loop (acc @ l) pl - | _ -> acc - in - match loop [] ctx.g.debug_delayed with - | [] -> "" - | l -> " ??PENDING[" ^ String.concat ";" (List.map (fun (_,i,_) -> i) l) ^ "]" - -let display_error ctx msg p = - debug ctx ("ERROR " ^ msg); - display_error ctx msg p - -let make_pass ?inf ctx f = - let inf = (match inf with None -> pass_infos ctx ctx.pass | Some inf -> inf) in - (fun v -> - debug ctx ("run " ^ inf ^ pending_passes ctx); - let old = !delay_tabs in - delay_tabs := !delay_tabs ^ "\t"; - let t = (try - f v - with - | Fatal_error (e,p) -> - delay_tabs := old; - raise (Fatal_error (e,p)) - | exc when not (Common.raw_defined ctx.com "stack") -> - debug ctx ("FATAL " ^ Printexc.to_string exc); - delay_tabs := old; - raise exc - ) in - delay_tabs := old; - t - ) - -let rec flush_pass ctx p where = - let rec loop() = - match ctx.g.debug_delayed with - | (p2,l) :: rest when p2 <= p -> - (match l with - | [] -> - ctx.g.debug_delayed <- rest - | (f,inf,ctx2) :: l -> - ctx.g.debug_delayed <- (p2,l) :: rest; - match p2 with - | PTypeField | PBuildClass -> f() - | _ -> (make_pass ~inf ctx f)()); - loop() - | _ -> - () - in - match ctx.g.debug_delayed with - | (p2,_) :: _ when p2 <= p -> - let old = !delay_tabs in - debug ctx ("flush " ^ pass_name p ^ "(" ^ where ^ ")"); - delay_tabs := !delay_tabs ^ "\t"; - loop(); - delay_tabs := old; - debug ctx "flush-done"; - | _ -> - () - -let make_where ctx where = - where ^ " (" ^ ctx_pos ctx ^ ")" - -let exc_protect ctx f (where:string) = - let f = make_pass ~inf:(make_where ctx where) ctx f in - let rec r = ref (fun() -> - try - f r - with - | Error (m,p) -> - raise (Fatal_error (error_msg m,p)) - ) in - r - -*/*) -(* --------------------------------------------------- *) - - diff --git a/typeload.ml b/typeload.ml deleted file mode 100644 index 2e1ca3ca..00000000 --- a/typeload.ml +++ /dev/null @@ -1,3277 +0,0 @@ -(* - * Copyright (C)2005-2013 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. - *) - -open Ast -open Type -open Common -open Typecore - -let locate_macro_error = ref true - -(* - Build module structure : should be atomic - no type loading is possible -*) -let make_module ctx mpath file tdecls loadp = - let decls = ref [] in - let make_path name priv = - if List.exists (fun (t,_) -> snd (t_path t) = name) !decls then error ("Type name " ^ name ^ " is already defined in this module") loadp; - if priv then (fst mpath @ ["_" ^ snd mpath], name) else (fst mpath, name) - in - let m = { - m_id = alloc_mid(); - m_path = mpath; - m_types = []; - m_extra = module_extra (Common.unique_full_path file) (Common.get_signature ctx.com) (file_time file) (if ctx.in_macro then MMacro else MCode); - } in - let pt = ref None in - let rec make_decl acc decl = - let p = snd decl in - let acc = (match fst decl with - | EImport _ | EUsing _ -> - (match !pt with - | None -> acc - | Some pt -> - display_error ctx "import and using may not appear after a type declaration" p; - error "Previous type declaration found here" pt) - | EClass d -> - if String.length d.d_name > 0 && d.d_name.[0] = '$' then error "Type names starting with a dollar are not allowed" p; - pt := Some p; - let priv = List.mem HPrivate d.d_flags in - let path = make_path d.d_name priv in - let c = mk_class m path p in - c.cl_module <- m; - c.cl_private <- priv; - c.cl_doc <- d.d_doc; - c.cl_meta <- d.d_meta; - decls := (TClassDecl c, decl) :: !decls; - acc - | EEnum d -> - if String.length d.d_name > 0 && d.d_name.[0] = '$' then error "Type names starting with a dollar are not allowed" p; - pt := Some p; - let priv = List.mem EPrivate d.d_flags in - let path = make_path d.d_name priv in - let e = { - e_path = path; - e_module = m; - e_pos = p; - e_doc = d.d_doc; - e_meta = d.d_meta; - e_params = []; - e_private = priv; - e_extern = List.mem EExtern d.d_flags; - e_constrs = PMap.empty; - e_names = []; - e_type = { - t_path = [], "Enum<" ^ (s_type_path path) ^ ">"; - t_module = m; - t_doc = None; - t_pos = p; - t_type = mk_mono(); - t_private = true; - t_params = []; - t_meta = []; - }; - } in - decls := (TEnumDecl e, decl) :: !decls; - acc - | ETypedef d -> - if String.length d.d_name > 0 && d.d_name.[0] = '$' then error "Type names starting with a dollar are not allowed" p; - pt := Some p; - let priv = List.mem EPrivate d.d_flags in - let path = make_path d.d_name priv in - let t = { - t_path = path; - t_module = m; - t_pos = p; - t_doc = d.d_doc; - t_private = priv; - t_params = []; - t_type = mk_mono(); - t_meta = d.d_meta; - } in - decls := (TTypeDecl t, decl) :: !decls; - acc - | EAbstract d -> - if String.length d.d_name > 0 && d.d_name.[0] = '$' then error "Type names starting with a dollar are not allowed" p; - let priv = List.mem APrivAbstract d.d_flags in - let path = make_path d.d_name priv in - let a = { - a_path = path; - a_private = priv; - a_module = m; - a_pos = p; - a_doc = d.d_doc; - a_params = []; - a_meta = d.d_meta; - a_from = []; - a_to = []; - a_from_field = []; - a_to_field = []; - a_ops = []; - a_unops = []; - a_impl = None; - a_array = []; - a_this = mk_mono(); - } in - decls := (TAbstractDecl a, decl) :: !decls; - match d.d_data with - | [] when Meta.has Meta.CoreType a.a_meta -> - a.a_this <- t_dynamic; - acc - | fields -> - let a_t = - let params = List.map (fun t -> TPType (CTPath { tname = t.tp_name; tparams = []; tsub = None; tpackage = [] })) d.d_params in - CTPath { tpackage = []; tname = d.d_name; tparams = params; tsub = None } - in - let rec loop = function - | [] -> a_t - | AIsType t :: _ -> t - | _ :: l -> loop l - in - let this_t = loop d.d_flags in - let fields = List.map (fun f -> - let stat = List.mem AStatic f.cff_access in - let p = f.cff_pos in - match f.cff_kind with - | FProp (("get" | "never"),("set" | "never"),_,_) when not stat -> - (* TODO: hack to avoid issues with abstract property generation on As3 *) - if Common.defined ctx.com Define.As3 then f.cff_meta <- (Meta.Extern,[],p) :: f.cff_meta; - { f with cff_access = AStatic :: f.cff_access; cff_meta = (Meta.Impl,[],p) :: f.cff_meta } - | FProp _ when not stat -> - display_error ctx "Member property accessors must be get/set or never" p; - f - | FFun fu when f.cff_name = "new" && not stat -> - let init p = (EVars ["this",Some this_t,None],p) in - let cast e = (ECast(e,None)),pos e in - let check_type e ct = (ECheckType(e,ct)),pos e in - let ret p = (EReturn (Some (cast (EConst (Ident "this"),p))),p) in - if Meta.has Meta.MultiType a.a_meta then begin - if List.mem AInline f.cff_access then error "MultiType constructors cannot be inline" f.cff_pos; - if fu.f_expr <> None then error "MultiType constructors cannot have a body" f.cff_pos; - end; - let has_call e = - let rec loop e = match fst e with - | ECall _ -> raise Exit - | _ -> Ast.map_expr loop e - in - try ignore(loop e); false with Exit -> true - in - let fu = { - fu with - f_expr = (match fu.f_expr with - | None -> if Meta.has Meta.MultiType a.a_meta then Some (EConst (Ident "null"),p) else None - | Some (EBlock [EBinop (OpAssign,(EConst (Ident "this"),_),e),_],_ | EBinop (OpAssign,(EConst (Ident "this"),_),e),_) when not (has_call e) -> - Some (EReturn (Some (cast (check_type e this_t))), pos e) - | Some (EBlock el,p) -> Some (EBlock (init p :: el @ [ret p]),p) - | Some e -> Some (EBlock [init p;e;ret p],p) - ); - f_type = Some a_t; - } in - { f with cff_name = "_new"; cff_access = AStatic :: f.cff_access; cff_kind = FFun fu; cff_meta = (Meta.Impl,[],p) :: f.cff_meta } - | FFun fu when not stat -> - if Meta.has Meta.From f.cff_meta then error "@:from cast functions must be static" f.cff_pos; - let fu = { fu with f_args = (if List.mem AMacro f.cff_access then fu.f_args else ("this",false,Some this_t,None) :: fu.f_args) } in - { f with cff_kind = FFun fu; cff_access = AStatic :: f.cff_access; cff_meta = (Meta.Impl,[],p) :: f.cff_meta } - | _ -> - f - ) fields in - let meta = ref [] in - if has_meta Meta.Dce a.a_meta then meta := (Meta.Dce,[],p) :: !meta; - let acc = make_decl acc (EClass { d_name = d.d_name ^ "_Impl_"; d_flags = [HPrivate]; d_data = fields; d_doc = None; d_params = []; d_meta = !meta },p) in - (match !decls with - | (TClassDecl c,_) :: _ -> - List.iter (fun m -> match m with - | ((Meta.Build | Meta.CoreApi | Meta.Allow | Meta.Access | Meta.Enum | Meta.Dce),_,_) -> - c.cl_meta <- m :: c.cl_meta; - | _ -> - () - ) a.a_meta; - a.a_impl <- Some c; - c.cl_kind <- KAbstractImpl a - | _ -> assert false); - acc - ) in - decl :: acc - in - let tdecls = List.fold_left make_decl [] tdecls in - let decls = List.rev !decls in - m.m_types <- List.map fst decls; - m, decls, List.rev tdecls - -let parse_file com file p = - let ch = (try open_in_bin file with _ -> error ("Could not open " ^ file) p) in - let t = Common.timer "parsing" in - Lexer.init file true; - incr stats.s_files_parsed; - let data = (try Parser.parse com (Lexing.from_channel ch) with e -> close_in ch; t(); raise e) in - close_in ch; - t(); - Common.log com ("Parsed " ^ file); - data - -let parse_hook = ref parse_file -let type_module_hook = ref (fun _ _ _ -> None) -let type_function_params_rec = ref (fun _ _ _ _ -> assert false) -let return_partial_type = ref false - -let type_function_arg ctx t e opt p = - if opt then - let e = (match e with None -> Some (EConst (Ident "null"),p) | _ -> e) in - ctx.t.tnull t, e - else - let t = match e with Some (EConst (Ident "null"),p) -> ctx.t.tnull t | _ -> t in - t, e - -let type_var_field ctx t e stat p = - if stat then ctx.curfun <- FunStatic else ctx.curfun <- FunMember; - let e = type_expr ctx e (WithType t) in - let e = (!cast_or_unify_ref) ctx t e p in - match t with - | TType ({ t_path = ([],"UInt") },[]) | TAbstract ({ a_path = ([],"UInt") },[]) when stat -> { e with etype = t } - | _ -> e - -let apply_macro ctx mode path el p = - let cpath, meth = (match List.rev (ExtString.String.nsplit path ".") with - | meth :: name :: pack -> (List.rev pack,name), meth - | _ -> error "Invalid macro path" p - ) in - ctx.g.do_macro ctx mode cpath meth el p - -(** since load_type_def and load_instance are used in PASS2, they should not access the structure of a type **) - -(* - load a type or a subtype definition -*) -let rec load_type_def ctx p t = - let no_pack = t.tpackage = [] in - let tname = (match t.tsub with None -> t.tname | Some n -> n) in - try - if t.tsub <> None then raise Not_found; - List.find (fun t2 -> - let tp = t_path t2 in - tp = (t.tpackage,tname) || (no_pack && snd tp = tname) - ) (ctx.m.curmod.m_types @ ctx.m.module_types) - with - Not_found -> - let next() = - let t, m = (try - t, ctx.g.do_load_module ctx (t.tpackage,t.tname) p - with Error (Module_not_found _,p2) as e when p == p2 -> - match t.tpackage with - | "std" :: l -> - let t = { t with tpackage = l } in - t, ctx.g.do_load_module ctx (t.tpackage,t.tname) p - | _ -> raise e - ) in - let tpath = (t.tpackage,tname) in - try - List.find (fun t -> not (t_infos t).mt_private && t_path t = tpath) m.m_types - with - Not_found -> raise (Error (Type_not_found (m.m_path,tname),p)) - in - (* lookup in wildcard imported packages *) - try - if not no_pack then raise Exit; - let rec loop = function - | [] -> raise Exit - | wp :: l -> - try - load_type_def ctx p { t with tpackage = wp } - with - | Error (Module_not_found _,p2) - | Error (Type_not_found _,p2) when p == p2 -> loop l - in - loop ctx.m.wildcard_packages - with Exit -> - (* lookup in our own package - and its upper packages *) - let rec loop = function - | [] -> raise Exit - | (_ :: lnext) as l -> - try - load_type_def ctx p { t with tpackage = List.rev l } - with - | Error (Module_not_found _,p2) - | Error (Type_not_found _,p2) when p == p2 -> loop lnext - in - try - if not no_pack then raise Exit; - (match fst ctx.m.curmod.m_path with - | [] -> raise Exit - | x :: _ -> - (* this can occur due to haxe remoting : a module can be - already defined in the "js" package and is not allowed - to access the js classes *) - try - (match PMap.find x ctx.com.package_rules with - | Forbidden -> raise Exit - | _ -> ()) - with Not_found -> ()); - loop (List.rev (fst ctx.m.curmod.m_path)); - with - Exit -> next() - -let check_param_constraints ctx types t pl c p = - match follow t with - | TMono _ -> () - | _ -> - let ctl = (match c.cl_kind with KTypeParameter l -> l | _ -> []) in - List.iter (fun ti -> - let ti = apply_params types pl ti in - let ti = (match follow ti with - | TInst ({ cl_kind = KGeneric } as c,pl) -> - (* if we solve a generic contraint, let's substitute with the actual generic instance before unifying *) - let _,_, f = ctx.g.do_build_instance ctx (TClassDecl c) p in - f pl - | _ -> ti - ) in - try - unify_raise ctx t ti p - with Error(Unify l,p) -> - if not ctx.untyped then display_error ctx (error_msg (Unify (Constraint_failure (s_type_path c.cl_path) :: l))) p; - ) ctl - -let requires_value_meta com co = - Common.defined com Define.DocGen || (match co with - | None -> false - | Some c -> c.cl_extern || Meta.has Meta.Rtti c.cl_meta) - -let generate_value_meta com co cf args = - if requires_value_meta com co then begin - let values = List.fold_left (fun acc (name,_,_,eo) -> match eo with Some e -> (name,e) :: acc | _ -> acc) [] args in - match values with - | [] -> () - | _ -> cf.cf_meta <- ((Meta.Value,[EObjectDecl values,cf.cf_pos],cf.cf_pos) :: cf.cf_meta) - end - -(* build an instance from a full type *) -let rec load_instance ctx t p allow_no_params = - try - if t.tpackage <> [] || t.tsub <> None then raise Not_found; - let pt = List.assoc t.tname ctx.type_params in - if t.tparams <> [] then error ("Class type parameter " ^ t.tname ^ " can't have parameters") p; - pt - with Not_found -> - let mt = load_type_def ctx p t in - let is_generic,is_generic_build = match mt with - | TClassDecl {cl_kind = KGeneric} -> true,false - | TClassDecl {cl_kind = KGenericBuild _} -> false,true - | _ -> false,false - in - let types , path , f = ctx.g.do_build_instance ctx mt p in - let is_rest = is_generic_build && (match types with ["Rest",_] -> true | _ -> false) in - if allow_no_params && t.tparams = [] && not is_rest then begin - let pl = ref [] in - pl := List.map (fun (name,t) -> - match follow t with - | TInst (c,_) -> - let t = mk_mono() in - if c.cl_kind <> KTypeParameter [] || is_generic then delay ctx PCheckConstraint (fun() -> check_param_constraints ctx types t (!pl) c p); - t; - | _ -> assert false - ) types; - f (!pl) - end else if path = ([],"Dynamic") then - match t.tparams with - | [] -> t_dynamic - | [TPType t] -> TDynamic (load_complex_type ctx p t) - | _ -> error "Too many parameters for Dynamic" p - else begin - if not is_rest && List.length types <> List.length t.tparams then error ("Invalid number of type parameters for " ^ s_type_path path) p; - let tparams = List.map (fun t -> - match t with - | TPExpr e -> - let name = (match fst e with - | EConst (String s) -> "S" ^ s - | EConst (Int i) -> "I" ^ i - | EConst (Float f) -> "F" ^ f - | _ -> "Expr" - ) in - let c = mk_class null_module ([],name) p in - c.cl_kind <- KExpr e; - TInst (c,[]) - | TPType t -> load_complex_type ctx p t - ) t.tparams in - let rec loop tl1 tl2 is_rest = match tl1,tl2 with - | t :: tl1,(name,t2) :: tl2 -> - let isconst = (match t with TInst ({ cl_kind = KExpr _ },_) -> true | _ -> false) in - if isconst <> (name = "Const") && t != t_dynamic && name <> "Rest" then error (if isconst then "Constant value unexpected here" else "Constant value excepted as type parameter") p; - let is_rest = is_rest || name = "Rest" && is_generic_build in - let t = match follow t2 with - | TInst ({ cl_kind = KTypeParameter [] }, []) when not is_generic -> - t - | TInst (c,[]) -> - let r = exc_protect ctx (fun r -> - r := (fun() -> t); - delay ctx PCheckConstraint (fun() -> check_param_constraints ctx types t tparams c p); - t - ) "constraint" in - delay ctx PForce (fun () -> ignore(!r())); - TLazy r - | _ -> assert false - in - t :: loop tl1 tl2 is_rest - | [],[] -> - [] - | [],["Rest",_] when is_generic_build -> - [] - | [],_ -> - error ("Not enough type parameters for " ^ s_type_path path) p - | t :: tl,[] -> - if is_rest then - t :: loop tl [] true - else - error ("Too many parameters for " ^ s_type_path path) p - in - let params = loop tparams types false in - f params - end -(* - build an instance from a complex type -*) -and load_complex_type ctx p t = - match t with - | CTParent t -> load_complex_type ctx p t - | CTPath t -> load_instance ctx t p false - | CTOptional _ -> error "Optional type not allowed here" p - | CTExtend (tl,l) -> - (match load_complex_type ctx p (CTAnonymous l) with - | TAnon a as ta -> - let is_redefined cf1 a2 = - try - let cf2 = PMap.find cf1.cf_name a2.a_fields in - let st = s_type (print_context()) in - if not (type_iseq cf1.cf_type cf2.cf_type) then begin - display_error ctx ("Cannot redefine field " ^ cf1.cf_name ^ " with different type") p; - display_error ctx ("First type was " ^ (st cf1.cf_type)) cf1.cf_pos; - error ("Second type was " ^ (st cf2.cf_type)) cf2.cf_pos - end else - true - with Not_found -> - false - in - let mk_extension t = - match follow t with - | TInst ({cl_kind = KTypeParameter _},_) -> - error "Cannot structurally extend type parameters" p - | TInst (c,tl) -> - ctx.com.warning "Structurally extending classes is deprecated and will be removed" p; - let c2 = mk_class null_module (fst c.cl_path,"+" ^ snd c.cl_path) p in - c2.cl_private <- true; - PMap.iter (fun f _ -> - try - ignore(class_field c tl f); - error ("Cannot redefine field " ^ f) p - with - Not_found -> () - ) a.a_fields; - (* do NOT tag as extern - for protect *) - c2.cl_kind <- KExtension (c,tl); - c2.cl_super <- Some (c,tl); - c2.cl_fields <- a.a_fields; - TInst (c2,[]) - | TMono _ -> - error "Loop found in cascading signatures definitions. Please change order/import" p - | TAnon a2 -> - PMap.iter (fun _ cf -> ignore(is_redefined cf a2)) a.a_fields; - TAnon { a_fields = (PMap.foldi PMap.add a.a_fields a2.a_fields); a_status = ref (Extend [t]); } - | _ -> error "Can only extend classes and structures" p - in - let loop t = match follow t with - | TAnon a2 -> - PMap.iter (fun f cf -> - if not (is_redefined cf a) then - a.a_fields <- PMap.add f cf a.a_fields - ) a2.a_fields - | _ -> - error "Multiple structural extension is only allowed for structures" p - in - let il = List.map (fun t -> load_instance ctx t p false) tl in - let tr = ref None in - let t = TMono tr in - let r = exc_protect ctx (fun r -> - r := (fun _ -> t); - tr := Some (match il with - | [i] -> - mk_extension i - | _ -> - List.iter loop il; - a.a_status := Extend il; - ta); - t - ) "constraint" in - delay ctx PForce (fun () -> ignore(!r())); - TLazy r - | _ -> assert false) - | CTAnonymous l -> - let rec loop acc f = - let n = f.cff_name in - let p = f.cff_pos in - if PMap.mem n acc then error ("Duplicate field declaration : " ^ n) p; - let topt = function - | None -> error ("Explicit type required for field " ^ n) p - | Some t -> load_complex_type ctx p t - in - let no_expr = function - | None -> () - | Some (_,p) -> error "Expression not allowed here" p - in - let pub = ref true in - let dyn = ref false in - let params = ref [] in - List.iter (fun a -> - match a with - | APublic -> () - | APrivate -> pub := false; - | ADynamic when (match f.cff_kind with FFun _ -> true | _ -> false) -> dyn := true - | AStatic | AOverride | AInline | ADynamic | AMacro -> error ("Invalid access " ^ Ast.s_access a) p - ) f.cff_access; - let t , access = (match f.cff_kind with - | FVar (Some (CTPath({tpackage=[];tname="Void"})), _) | FProp (_,_,Some (CTPath({tpackage=[];tname="Void"})),_) -> - error "Fields of type Void are not allowed in structures" p - | FVar (t, e) -> - no_expr e; - topt t, Var { v_read = AccNormal; v_write = AccNormal } - | FFun fd -> - params := (!type_function_params_rec) ctx fd f.cff_name p; - no_expr fd.f_expr; - let old = ctx.type_params in - ctx.type_params <- !params @ old; - let args = List.map (fun (name,o,t,e) -> no_expr e; name, o, topt t) fd.f_args in - let t = TFun (args,topt fd.f_type), Method (if !dyn then MethDynamic else MethNormal) in - ctx.type_params <- old; - t - | FProp (i1,i2,t,e) -> - no_expr e; - let access m get = - match m with - | "null" -> AccNo - | "never" -> AccNever - | "default" -> AccNormal - | "dynamic" -> AccCall - | "get" when get -> AccCall - | "set" when not get -> AccCall - | x when get && x = "get_" ^ n -> AccCall - | x when not get && x = "set_" ^ n -> AccCall - | _ -> - error "Custom property access is no longer supported in Haxe 3" f.cff_pos; - in - let t = (match t with None -> error "Type required for structure property" p | Some t -> t) in - load_complex_type ctx p t, Var { v_read = access i1 true; v_write = access i2 false } - ) in - let t = if Meta.has Meta.Optional f.cff_meta then ctx.t.tnull t else t in - let cf = { - cf_name = n; - cf_type = t; - cf_pos = p; - cf_public = !pub; - cf_kind = access; - cf_params = !params; - cf_expr = None; - cf_doc = f.cff_doc; - cf_meta = f.cff_meta; - cf_overloads = []; - } in - init_meta_overloads ctx None cf; - PMap.add n cf acc - in - mk_anon (List.fold_left loop PMap.empty l) - | CTFunction (args,r) -> - match args with - | [CTPath { tpackage = []; tparams = []; tname = "Void" }] -> - TFun ([],load_complex_type ctx p r) - | _ -> - TFun (List.map (fun t -> - let t, opt = (match t with CTOptional t -> t, true | _ -> t,false) in - "",opt,load_complex_type ctx p t - ) args,load_complex_type ctx p r) - -and init_meta_overloads ctx co cf = - let overloads = ref [] in - let filter_meta m = match m with - | ((Meta.Overload | Meta.Value),_,_) -> false - | _ -> true - in - let cf_meta = List.filter filter_meta cf.cf_meta in - cf.cf_meta <- List.filter (fun m -> - match m with - | (Meta.Overload,[(EFunction (fname,f),p)],_) -> - if fname <> None then error "Function name must not be part of @:overload" p; - (match f.f_expr with Some (EBlock [], _) -> () | _ -> error "Overload must only declare an empty method body {}" p); - let old = ctx.type_params in - (match cf.cf_params with - | [] -> () - | l -> ctx.type_params <- List.filter (fun t -> not (List.mem t l)) ctx.type_params); - let params = (!type_function_params_rec) ctx f cf.cf_name p in - ctx.type_params <- params @ ctx.type_params; - let topt = function None -> error "Explicit type required" p | Some t -> load_complex_type ctx p t in - let args = List.map (fun (a,opt,t,_) -> a,opt,topt t) f.f_args in - let cf = { cf with cf_type = TFun (args,topt f.f_type); cf_params = params; cf_meta = cf_meta} in - generate_value_meta ctx.com co cf f.f_args; - overloads := cf :: !overloads; - ctx.type_params <- old; - false - | (Meta.Overload,[],_) when ctx.com.config.pf_overload -> - let topt (n,_,t) = match t with | TMono t when !t = None -> error ("Explicit type required for overload functions\nFor function argument '" ^ n ^ "'") cf.cf_pos | _ -> () in - (match follow cf.cf_type with - | TFun (args,_) -> List.iter topt args - | _ -> () (* could be a variable *)); - true - | (Meta.Overload,[],p) -> - error "This platform does not support this kind of overload declaration. Try @:overload(function()... {}) instead" p - | (Meta.Overload,_,p) -> - error "Invalid @:overload metadata format" p - | _ -> - true - ) cf.cf_meta; - cf.cf_overloads <- (List.rev !overloads) - -let hide_params ctx = - let old_m = ctx.m in - let old_type_params = ctx.type_params in - let old_deps = ctx.g.std.m_extra.m_deps in - ctx.m <- { - curmod = ctx.g.std; - module_types = []; - module_using = []; - module_globals = PMap.empty; - wildcard_packages = []; - }; - ctx.type_params <- []; - (fun() -> - ctx.m <- old_m; - ctx.type_params <- old_type_params; - (* restore dependencies that might be have been wronly inserted *) - ctx.g.std.m_extra.m_deps <- old_deps; - ) - -(* - load a type while ignoring the current imports or local types -*) -let load_core_type ctx name = - let show = hide_params ctx in - let t = load_instance ctx { tpackage = []; tname = name; tparams = []; tsub = None; } null_pos false in - show(); - add_dependency ctx.m.curmod (match t with - | TInst (c,_) -> c.cl_module - | TType (t,_) -> t.t_module - | TAbstract (a,_) -> a.a_module - | TEnum (e,_) -> e.e_module - | _ -> assert false); - t - -let t_iterator ctx = - let show = hide_params ctx in - match load_type_def ctx null_pos { tpackage = []; tname = "Iterator"; tparams = []; tsub = None } with - | TTypeDecl t -> - show(); - add_dependency ctx.m.curmod t.t_module; - if List.length t.t_params <> 1 then assert false; - let pt = mk_mono() in - apply_params t.t_params [pt] t.t_type, pt - | _ -> - assert false - -(* - load either a type t or Null if not defined -*) -let load_type_opt ?(opt=false) ctx p t = - let t = (match t with None -> mk_mono() | Some t -> load_complex_type ctx p t) in - if opt then ctx.t.tnull t else t - -(* ---------------------------------------------------------------------- *) -(* Structure check *) - -let valid_redefinition ctx f1 t1 f2 t2 = - let valid t1 t2 = - Type.unify t1 t2; - if is_null t1 <> is_null t2 then raise (Unify_error [Cannot_unify (t1,t2)]); - in - let t1, t2 = (match f1.cf_params, f2.cf_params with - | [], [] -> t1, t2 - | l1, l2 when List.length l1 = List.length l2 -> - let to_check = ref [] in - let monos = List.map2 (fun (name,p1) (_,p2) -> - (match follow p1, follow p2 with - | TInst ({ cl_kind = KTypeParameter ct1 } as c1,pl1), TInst ({ cl_kind = KTypeParameter ct2 } as c2,pl2) -> - (match ct1, ct2 with - | [], [] -> () - | _, _ when List.length ct1 = List.length ct2 -> - (* if same constraints, they are the same type *) - let check monos = - List.iter2 (fun t1 t2 -> - try - let t1 = apply_params l1 monos (apply_params c1.cl_params pl1 t1) in - let t2 = apply_params l2 monos (apply_params c2.cl_params pl2 t2) in - type_eq EqStrict t1 t2 - with Unify_error l -> - raise (Unify_error (Unify_custom "Constraints differ" :: l)) - ) ct1 ct2 - in - to_check := check :: !to_check; - | _ -> - raise (Unify_error [Unify_custom "Different number of constraints"])) - | _ -> ()); - TInst (mk_class null_module ([],name) Ast.null_pos,[]) - ) l1 l2 in - List.iter (fun f -> f monos) !to_check; - apply_params l1 monos t1, apply_params l2 monos t2 - | _ -> - (* ignore type params, will create other errors later *) - t1, t2 - ) in - match f1.cf_kind,f2.cf_kind with - | Method m1, Method m2 when not (m1 = MethDynamic) && not (m2 = MethDynamic) -> - begin match follow t1, follow t2 with - | TFun (args1,r1) , TFun (args2,r2) -> ( - if not (List.length args1 = List.length args2) then raise (Unify_error [Unify_custom "Different number of function arguments"]); - try - List.iter2 (fun (n,o1,a1) (_,o2,a2) -> - if o1 <> o2 then raise (Unify_error [Not_matching_optional n]); - (try valid a2 a1 with Unify_error _ -> raise (Unify_error [Cannot_unify(a1,a2)])) - ) args1 args2; - valid r1 r2 - with Unify_error l -> - raise (Unify_error (Cannot_unify (t1,t2) :: l))) - | _ -> - assert false - end - | _,(Var { v_write = AccNo | AccNever }) -> - (* write variance *) - valid t2 t1 - | _,(Var { v_read = AccNo | AccNever }) -> - (* read variance *) - valid t1 t2 - | _ , _ -> - (* in case args differs, or if an interface var *) - type_eq EqStrict t1 t2; - if is_null t1 <> is_null t2 then raise (Unify_error [Cannot_unify (t1,t2)]) - -let copy_meta meta_src meta_target sl = - let meta = ref meta_target in - List.iter (fun (m,e,p) -> - if List.mem m sl then meta := (m,e,p) :: !meta - ) meta_src; - !meta - -let same_overload_args ?(get_vmtype) t1 t2 f1 f2 = - let get_vmtype = match get_vmtype with - | None -> (fun f -> f) - | Some f -> f - in - if List.length f1.cf_params <> List.length f2.cf_params then - false - else - let rec follow_skip_null t = match t with - | TMono r -> - (match !r with - | Some t -> follow_skip_null t - | _ -> t) - | TLazy f -> - follow_skip_null (!f()) - | TType ({ t_path = [],"Null" } as t, [p]) -> - TType(t,[follow p]) - | TType (t,tl) -> - follow_skip_null (apply_params t.t_params tl t.t_type) - | _ -> t - in - let same_arg t1 t2 = - let t1 = get_vmtype (follow_skip_null t1) in - let t2 = get_vmtype (follow_skip_null t2) in - match t1, t2 with - | TType _, TType _ -> type_iseq t1 t2 - | TType _, _ - | _, TType _ -> false - | _ -> type_iseq t1 t2 - in - - match follow (apply_params f1.cf_params (List.map (fun (_,t) -> t) f2.cf_params) t1), follow t2 with - | TFun(a1,_), TFun(a2,_) -> - (try - List.for_all2 (fun (_,_,t1) (_,_,t2) -> - same_arg t1 t2) a1 a2 - with | Invalid_argument("List.for_all2") -> - false) - | _ -> assert false - -(** retrieves all overloads from class c and field i, as (Type.t * tclass_field) list *) -let rec get_overloads c i = - let ret = try - let f = PMap.find i c.cl_fields in - match f.cf_kind with - | Var _ -> - (* @:libType may generate classes that have a variable field in a superclass of an overloaded method *) - [] - | Method _ -> - (f.cf_type, f) :: (List.map (fun f -> f.cf_type, f) f.cf_overloads) - with | Not_found -> [] - in - let rsup = match c.cl_super with - | None when c.cl_interface -> - let ifaces = List.concat (List.map (fun (c,tl) -> - List.map (fun (t,f) -> apply_params c.cl_params tl t, f) (get_overloads c i) - ) c.cl_implements) in - ret @ ifaces - | None -> ret - | Some (c,tl) -> - ret @ ( List.map (fun (t,f) -> apply_params c.cl_params tl t, f) (get_overloads c i) ) - in - ret @ (List.filter (fun (t,f) -> not (List.exists (fun (t2,f2) -> same_overload_args t t2 f f2) ret)) rsup) - - -let check_overloads ctx c = - (* check if field with same signature was declared more than once *) - List.iter (fun f -> - if Meta.has Meta.Overload f.cf_meta then - List.iter (fun f2 -> - try - ignore (List.find (fun f3 -> f3 != f2 && same_overload_args f2.cf_type f3.cf_type f2 f3) (f :: f.cf_overloads)); - display_error ctx ("Another overloaded field of same signature was already declared : " ^ f2.cf_name) f2.cf_pos - with | Not_found -> () - ) (f :: f.cf_overloads)) (c.cl_ordered_fields @ c.cl_ordered_statics) - -let check_overriding ctx c = - match c.cl_super with - | None -> - (match c.cl_overrides with - | [] -> () - | i :: _ -> - display_error ctx ("Field " ^ i.cf_name ^ " is declared 'override' but doesn't override any field") i.cf_pos) - | _ when c.cl_extern && Meta.has Meta.CsNative c.cl_meta -> () (* -net-lib specific: do not check overrides on extern CsNative classes *) - | Some (csup,params) -> - PMap.iter (fun i f -> - let p = f.cf_pos in - let check_field f get_super_field is_overload = try - (if is_overload && not (Meta.has Meta.Overload f.cf_meta) then - display_error ctx ("Missing @:overload declaration for field " ^ i) p); - let t, f2 = get_super_field csup i in - (* allow to define fields that are not defined for this platform version in superclass *) - (match f2.cf_kind with - | Var { v_read = AccRequire _ } -> raise Not_found; - | _ -> ()); - if ctx.com.config.pf_overload && (Meta.has Meta.Overload f2.cf_meta && not (Meta.has Meta.Overload f.cf_meta)) then - display_error ctx ("Field " ^ i ^ " should be declared with @:overload since it was already declared as @:overload in superclass") p - else if not (List.memq f c.cl_overrides) then - display_error ctx ("Field " ^ i ^ " should be declared with 'override' since it is inherited from superclass " ^ Ast.s_type_path csup.cl_path) p - else if not f.cf_public && f2.cf_public then - display_error ctx ("Field " ^ i ^ " has less visibility (public/private) than superclass one") p - else (match f.cf_kind, f2.cf_kind with - | _, Method MethInline -> - display_error ctx ("Field " ^ i ^ " is inlined and cannot be overridden") p - | a, b when a = b -> () - | Method MethInline, Method MethNormal -> - () (* allow to redefine a method as inlined *) - | _ -> - display_error ctx ("Field " ^ i ^ " has different property access than in superclass") p); - if has_meta Meta.Final f2.cf_meta then display_error ctx ("Cannot override @:final method " ^ i) p; - try - let t = apply_params csup.cl_params params t in - valid_redefinition ctx f f.cf_type f2 t - with - Unify_error l -> - display_error ctx ("Field " ^ i ^ " overloads parent class with different or incomplete type") p; - display_error ctx (error_msg (Unify l)) p; - with - Not_found -> - if List.memq f c.cl_overrides then - let msg = if is_overload then - ("Field " ^ i ^ " is declared 'override' but no compatible overload was found") - else - ("Field " ^ i ^ " is declared 'override' but doesn't override any field") - in - display_error ctx msg p - in - if ctx.com.config.pf_overload && Meta.has Meta.Overload f.cf_meta then begin - let overloads = get_overloads csup i in - List.iter (fun (t,f2) -> - (* check if any super class fields are vars *) - match f2.cf_kind with - | Var _ -> - display_error ctx ("A variable named '" ^ f2.cf_name ^ "' was already declared in a superclass") f.cf_pos - | _ -> () - ) overloads; - List.iter (fun f -> - (* find the exact field being overridden *) - check_field f (fun csup i -> - List.find (fun (t,f2) -> - same_overload_args f.cf_type (apply_params csup.cl_params params t) f f2 - ) overloads - ) true - ) (f :: f.cf_overloads) - end else - check_field f (fun csup i -> - let _, t, f2 = raw_class_field (fun f -> f.cf_type) csup params i in - t, f2) false - ) c.cl_fields - -let class_field_no_interf c i = - try - let f = PMap.find i c.cl_fields in - f.cf_type , f - with Not_found -> - match c.cl_super with - | None -> - raise Not_found - | Some (c,tl) -> - (* rec over class_field *) - let _, t , f = raw_class_field (fun f -> f.cf_type) c tl i in - apply_params c.cl_params tl t , f - -let rec check_interface ctx c intf params = - let p = c.cl_pos in - let rec check_field i f = - (if ctx.com.config.pf_overload then - List.iter (function - | f2 when f != f2 -> - check_field i f2 - | _ -> ()) f.cf_overloads); - let is_overload = ref false in - try - let t2, f2 = class_field_no_interf c i in - let t2, f2 = - if ctx.com.config.pf_overload && (f2.cf_overloads <> [] || Meta.has Meta.Overload f2.cf_meta) then - let overloads = get_overloads c i in - is_overload := true; - let t = (apply_params intf.cl_params params f.cf_type) in - List.find (fun (t1,f1) -> same_overload_args t t1 f f1) overloads - else - t2, f2 - in - - ignore(follow f2.cf_type); (* force evaluation *) - let p = (match f2.cf_expr with None -> p | Some e -> e.epos) in - let mkind = function - | MethNormal | MethInline -> 0 - | MethDynamic -> 1 - | MethMacro -> 2 - in - if f.cf_public && not f2.cf_public && not (Meta.has Meta.CompilerGenerated f.cf_meta) then - display_error ctx ("Field " ^ i ^ " should be public as requested by " ^ s_type_path intf.cl_path) p - else if not (unify_kind f2.cf_kind f.cf_kind) || not (match f.cf_kind, f2.cf_kind with Var _ , Var _ -> true | Method m1, Method m2 -> mkind m1 = mkind m2 | _ -> false) then - display_error ctx ("Field " ^ i ^ " has different property access than in " ^ s_type_path intf.cl_path ^ " (" ^ s_kind f2.cf_kind ^ " should be " ^ s_kind f.cf_kind ^ ")") p - else try - valid_redefinition ctx f2 t2 f (apply_params intf.cl_params params f.cf_type) - with - Unify_error l -> - if not (Meta.has Meta.CsNative c.cl_meta && c.cl_extern) then begin - display_error ctx ("Field " ^ i ^ " has different type than in " ^ s_type_path intf.cl_path) p; - display_error ctx (error_msg (Unify l)) p; - end - with - | Not_found when not c.cl_interface -> - let msg = if !is_overload then - let ctx = print_context() in - let args = match follow f.cf_type with | TFun(args,_) -> String.concat ", " (List.map (fun (n,o,t) -> (if o then "?" else "") ^ n ^ " : " ^ (s_type ctx t)) args) | _ -> assert false in - "No suitable overload for " ^ i ^ "( " ^ args ^ " ), as needed by " ^ s_type_path intf.cl_path ^ " was found" - else - ("Field " ^ i ^ " needed by " ^ s_type_path intf.cl_path ^ " is missing") - in - display_error ctx msg p - | Not_found -> () - in - PMap.iter check_field intf.cl_fields; - List.iter (fun (i2,p2) -> - check_interface ctx c i2 (List.map (apply_params intf.cl_params params) p2) - ) intf.cl_implements - -let check_interfaces ctx c = - match c.cl_path with - | "Proxy" :: _ , _ -> () - | _ when c.cl_extern && Meta.has Meta.CsNative c.cl_meta -> () - | _ -> - List.iter (fun (intf,params) -> check_interface ctx c intf params) c.cl_implements - -let rec return_flow ctx e = - let error() = display_error ctx "A return is missing here" e.epos; raise Exit in - let return_flow = return_flow ctx in - match e.eexpr with - | TReturn _ | TThrow _ -> () - | TParenthesis e | TMeta(_,e) -> - return_flow e - | TBlock el -> - let rec loop = function - | [] -> error() - | [e] -> return_flow e - | { eexpr = TReturn _ } :: _ | { eexpr = TThrow _ } :: _ -> () - | _ :: l -> loop l - in - loop el - | TIf (_,e1,Some e2) -> - return_flow e1; - return_flow e2; - | TSwitch (v,cases,Some e) -> - List.iter (fun (_,e) -> return_flow e) cases; - return_flow e - | TSwitch ({eexpr = TMeta((Meta.Exhaustive,_,_),_)},cases,None) -> - List.iter (fun (_,e) -> return_flow e) cases; - | TTry (e,cases) -> - return_flow e; - List.iter (fun (_,e) -> return_flow e) cases; - | TWhile({eexpr = (TConst (TBool true))},e,_) -> - (* a special case for "inifite" while loops that have no break *) - let rec loop e = match e.eexpr with - (* ignore nested loops to not accidentally get one of its breaks *) - | TWhile _ | TFor _ -> () - | TBreak -> error() - | _ -> Type.iter loop e - in - loop e - | _ -> - error() - -(* ---------------------------------------------------------------------- *) -(* PASS 1 & 2 : Module and Class Structure *) - -let is_generic_parameter ctx c = - (* first check field parameters, then class parameters *) - try - ignore (List.assoc (snd c.cl_path) ctx.curfield.cf_params); - Meta.has Meta.Generic ctx.curfield.cf_meta - with Not_found -> try - ignore(List.assoc (snd c.cl_path) ctx.type_params); - (match ctx.curclass.cl_kind with | KGeneric -> true | _ -> false); - with Not_found -> - false - -let check_extends ctx c t p = match follow t with - | TInst ({ cl_path = [],"Array"; cl_extern = basic_extern },_) - | TInst ({ cl_path = [],"String"; cl_extern = basic_extern },_) - | TInst ({ cl_path = [],"Date"; cl_extern = basic_extern },_) - | TInst ({ cl_path = [],"Xml"; cl_extern = basic_extern },_) when not (c.cl_extern && basic_extern) -> - error "Cannot extend basic class" p; - | TInst (csup,params) -> - if is_parent c csup then error "Recursive class" p; - begin match csup.cl_kind with - | KTypeParameter _ when not (is_generic_parameter ctx csup) -> error "Cannot extend non-generic type parameters" p - | _ -> csup,params - end - | _ -> error "Should extend by using a class" p - -let type_function_arg_value ctx t c = - match c with - | None -> None - | Some e -> - let p = pos e in - let e = ctx.g.do_optimize ctx (type_expr ctx e (WithType t)) in - unify ctx e.etype t p; - let rec loop e = match e.eexpr with - | TConst c -> Some c - | TCast(e,None) -> loop e - | _ -> display_error ctx "Parameter default value should be constant" p; None - in - loop e - -(**** strict meta ****) -let get_native_repr md pos = - let path, meta = match md with - | TClassDecl cl -> cl.cl_path, cl.cl_meta - | TEnumDecl e -> e.e_path, e.e_meta - | TTypeDecl t -> t.t_path, t.t_meta - | TAbstractDecl a -> a.a_path, a.a_meta - in - let rec loop acc = function - | (Meta.JavaCanonical,[EConst(String pack),_; EConst(String name),_],_) :: _ -> - ExtString.String.nsplit pack ".", name - | (Meta.Native,[EConst(String name),_],_) :: meta -> - loop (Ast.parse_path name) meta - | _ :: meta -> - loop acc meta - | [] -> - acc - in - let pack, name = loop path meta in - match pack with - | [] -> - (EConst(Ident(name)), pos) - | hd :: tl -> - let rec loop pack expr = match pack with - | hd :: tl -> - loop tl (EField(expr,hd),pos) - | [] -> - (EField(expr,name),pos) - in - loop tl (EConst(Ident(hd)),pos) - -let rec process_meta_argument ?(toplevel=true) ctx expr = match expr.eexpr with - | TField(e,f) -> - (EField(process_meta_argument ~toplevel:false ctx e,field_name f),expr.epos) - | TConst(TInt i) -> - (EConst(Int (Int32.to_string i)), expr.epos) - | TConst(TFloat f) -> - (EConst(Float f), expr.epos) - | TConst(TString s) -> - (EConst(String s), expr.epos) - | TConst TNull -> - (EConst(Ident "null"), expr.epos) - | TConst(TBool b) -> - (EConst(Ident (string_of_bool b)), expr.epos) - | TCast(e,_) | TMeta(_,e) | TParenthesis(e) -> - process_meta_argument ~toplevel ctx e - | TTypeExpr md when toplevel -> - let p = expr.epos in - if ctx.com.platform = Cs then - (ECall( (EConst(Ident "typeof"), p), [get_native_repr md expr.epos] ), p) - else - (EField(get_native_repr md expr.epos, "class"), p) - | TTypeExpr md -> - get_native_repr md expr.epos - | _ -> - display_error ctx "This expression is too complex to be a strict metadata argument" expr.epos; - (EConst(Ident "null"), expr.epos) - -let make_meta ctx texpr extra = - match texpr.eexpr with - | TNew(c,_,el) -> - ECall(get_native_repr (TClassDecl c) texpr.epos, (List.map (process_meta_argument ctx) el) @ extra), texpr.epos - | TTypeExpr(md) -> - ECall(get_native_repr md texpr.epos, extra), texpr.epos - | _ -> - display_error ctx "Unexpected expression" texpr.epos; assert false - -let field_to_type_path ctx e = - let rec loop e pack name = match e with - | EField(e,f),p when Char.lowercase (String.get f 0) <> String.get f 0 -> (match name with - | [] | _ :: [] -> - loop e pack (f :: name) - | _ -> (* too many name paths *) - display_error ctx ("Unexpected " ^ f) p; - raise Exit) - | EField(e,f),_ -> - loop e (f :: pack) name - | EConst(Ident f),_ -> - let pack, name, sub = match name with - | [] -> - let fchar = String.get f 0 in - if Char.uppercase fchar = fchar then - pack, f, None - else begin - display_error ctx "A class name must start with an uppercase character" (snd e); - raise Exit - end - | [name] -> - f :: pack, name, None - | [name; sub] -> - f :: pack, name, Some sub - | _ -> - assert false - in - { tpackage=pack; tname=name; tparams=[]; tsub=sub } - | _,pos -> - display_error ctx "Unexpected expression when building strict meta" pos; - raise Exit - in - loop e [] [] - -let handle_fields ctx fields_to_check with_type_expr = - List.map (fun (name,expr) -> - let pos = snd expr in - let field = (EField(with_type_expr,name), pos) in - let fieldexpr = (EConst(Ident name),pos) in - let left_side = match ctx.com.platform with - | Cs -> field - | Java -> (ECall(field,[]),pos) - | _ -> assert false - in - - let left = type_expr ctx left_side NoValue in - let right = type_expr ctx expr (WithType left.etype) in - unify ctx left.etype right.etype (snd expr); - (EBinop(Ast.OpAssign,fieldexpr,process_meta_argument ctx right), pos) - ) fields_to_check - -let get_strict_meta ctx params pos = - let pf = ctx.com.platform in - let changed_expr, fields_to_check, ctype = match params with - | [ECall(ef, el),p] -> - (* check last argument *) - let el, fields = match List.rev el with - | (EObjectDecl(decl),_) :: el -> - List.rev el, decl - | _ -> - el, [] - in - let tpath = field_to_type_path ctx ef in - if pf = Cs then - (ENew(tpath, el), p), fields, CTPath tpath - else - ef, fields, CTPath tpath - | [EConst(Ident i),p as expr] -> - let tpath = { tpackage=[]; tname=i; tparams=[]; tsub=None } in - if pf = Cs then - (ENew(tpath, []), p), [], CTPath tpath - else - expr, [], CTPath tpath - | [ (EField(_),p as field) ] -> - let tpath = field_to_type_path ctx field in - if pf = Cs then - (ENew(tpath, []), p), [], CTPath tpath - else - field, [], CTPath tpath - | _ -> - display_error ctx "A @:strict metadata must contain exactly one parameter. Please check the documentation for more information" pos; - raise Exit - in - let texpr = type_expr ctx changed_expr NoValue in - let with_type_expr = (ECheckType( (EConst (Ident "null"), pos), ctype ), pos) in - let extra = handle_fields ctx fields_to_check with_type_expr in - Meta.Meta, [make_meta ctx texpr extra], pos - -let check_strict_meta ctx metas = - let pf = ctx.com.platform in - match pf with - | Cs | Java -> - let ret = ref [] in - List.iter (function - | Meta.Strict,params,pos -> (try - ret := get_strict_meta ctx params pos :: !ret - with | Exit -> ()) - | _ -> () - ) metas; - !ret - | _ -> [] - -(**** end of strict meta handling *****) - -let rec add_constructor ctx c force_constructor p = - match c.cl_constructor, c.cl_super with - | None, Some ({ cl_constructor = Some cfsup } as csup,cparams) when not c.cl_extern && not (Meta.has Meta.CompilerGenerated cfsup.cf_meta) -> - let cf = { - cfsup with - cf_pos = p; - cf_meta = []; - cf_doc = None; - cf_expr = None; - } in - let r = exc_protect ctx (fun r -> - let t = mk_mono() in - r := (fun() -> t); - let ctx = { ctx with - curfield = cf; - pass = PTypeField; - } in - ignore (follow cfsup.cf_type); (* make sure it's typed *) - (if ctx.com.config.pf_overload then List.iter (fun cf -> ignore (follow cf.cf_type)) cf.cf_overloads); - let map_arg (v,def) = - (* - let's optimize a bit the output by not always copying the default value - into the inherited constructor when it's not necessary for the platform - *) - match ctx.com.platform, def with - | _, Some _ when not ctx.com.config.pf_static -> v, (Some TNull) - | Flash, Some (TString _) -> v, (Some TNull) - | Cpp, Some (TString _) -> v, def - | Cpp, Some _ -> { v with v_type = ctx.t.tnull v.v_type }, (Some TNull) - | _ -> v, def - in - let args = (match cfsup.cf_expr with - | Some { eexpr = TFunction f } -> - List.map map_arg f.tf_args - | _ -> - let values = get_value_meta cfsup.cf_meta in - match follow cfsup.cf_type with - | TFun (args,_) -> - List.map (fun (n,o,t) -> - let def = try type_function_arg_value ctx t (Some (PMap.find n values)) with Not_found -> if o then Some TNull else None in - map_arg (alloc_var n (if o then ctx.t.tnull t else t),def) - ) args - | _ -> assert false - ) in - let p = c.cl_pos in - let vars = List.map (fun (v,def) -> alloc_var v.v_name (apply_params csup.cl_params cparams v.v_type), def) args in - let super_call = mk (TCall (mk (TConst TSuper) (TInst (csup,cparams)) p,List.map (fun (v,_) -> mk (TLocal v) v.v_type p) vars)) ctx.t.tvoid p in - let constr = mk (TFunction { - tf_args = vars; - tf_type = ctx.t.tvoid; - tf_expr = super_call; - }) (TFun (List.map (fun (v,c) -> v.v_name, c <> None, v.v_type) vars,ctx.t.tvoid)) p in - cf.cf_expr <- Some constr; - cf.cf_type <- t; - unify ctx t constr.etype p; - t - ) "add_constructor" in - cf.cf_type <- TLazy r; - c.cl_constructor <- Some cf; - delay ctx PForce (fun() -> ignore((!r)())); - | None,_ when force_constructor -> - let constr = mk (TFunction { - tf_args = []; - tf_type = ctx.t.tvoid; - tf_expr = mk (TBlock []) ctx.t.tvoid p; - }) (tfun [] ctx.t.tvoid) p in - let cf = mk_field "new" constr.etype p in - cf.cf_expr <- Some constr; - cf.cf_type <- constr.etype; - cf.cf_meta <- [Meta.CompilerGenerated,[],p]; - cf.cf_kind <- Method MethNormal; - c.cl_constructor <- Some cf; - | _ -> - (* nothing to do *) - () - -let set_heritance ctx c herits p = - let is_lib = Meta.has Meta.LibType c.cl_meta in - let ctx = { ctx with curclass = c; type_params = c.cl_params; } in - let old_meta = c.cl_meta in - let process_meta csup = - List.iter (fun m -> - match m with - | Meta.Final, _, _ -> if not (Meta.has Meta.Hack c.cl_meta || (match c.cl_kind with KTypeParameter _ -> true | _ -> false)) then error "Cannot extend a final class" p; - | Meta.AutoBuild, el, p -> c.cl_meta <- (Meta.Build,el,p) :: m :: c.cl_meta - | _ -> () - ) csup.cl_meta - in - let cancel_build csup = - (* for macros reason, our super class is not yet built - see #2177 *) - (* let's reset our build and delay it until we are done *) - c.cl_meta <- old_meta; - c.cl_array_access <- None; - c.cl_dynamic <- None; - c.cl_implements <- []; - c.cl_super <- None; - raise Exit - in - let has_interf = ref false in - let rec loop = function - | HPrivate | HExtern | HInterface -> - () - | HExtends t -> - if c.cl_super <> None then error "Cannot extend several classes" p; - let t = load_instance ctx t p false in - let csup,params = check_extends ctx c t p in - if not (csup.cl_build()) then cancel_build csup; - process_meta csup; - if c.cl_interface then begin - if not csup.cl_interface then error "Cannot extend by using a class" p; - c.cl_implements <- (csup,params) :: c.cl_implements; - if not !has_interf then begin - if not is_lib then delay ctx PForce (fun() -> check_interfaces ctx c); - has_interf := true; - end - end else begin - if csup.cl_interface then error "Cannot extend by using an interface" p; - c.cl_super <- Some (csup,params) - end - | HImplements t -> - let t = load_instance ctx t p false in - (match follow t with - | TInst ({ cl_path = [],"ArrayAccess"; cl_extern = true; },[t]) -> - if c.cl_array_access <> None then error "Duplicate array access" p; - c.cl_array_access <- Some t - | TInst (intf,params) -> - if not (intf.cl_build()) then cancel_build intf; - if is_parent c intf then error "Recursive class" p; - if c.cl_interface then error "Interfaces cannot implement another interface (use extends instead)" p; - if not intf.cl_interface then error "You can only implement an interface" p; - process_meta intf; - c.cl_implements <- (intf, params) :: c.cl_implements; - if not !has_interf && not is_lib && not (Meta.has (Meta.Custom "$do_not_check_interf") c.cl_meta) then begin - delay ctx PForce (fun() -> check_interfaces ctx c); - has_interf := true; - end - | TDynamic t -> - if c.cl_dynamic <> None then error "Cannot have several dynamics" p; - c.cl_dynamic <- Some t - | _ -> error "Should implement by using an interface" p) - in - (* - resolve imports before calling build_inheritance, since it requires full paths. - that means that typedefs are not working, but that's a fair limitation - *) - let rec resolve_imports t = - match t.tpackage with - | _ :: _ -> t - | [] -> - try - let find = List.find (fun lt -> snd (t_path lt) = t.tname) in - let lt = try find ctx.m.curmod.m_types with Not_found -> find ctx.m.module_types in - { t with tpackage = fst (t_path lt) } - with - Not_found -> t - in - let herits = List.map (function - | HExtends t -> HExtends (resolve_imports t) - | HImplements t -> HImplements (resolve_imports t) - | h -> h - ) herits in - List.iter loop (List.filter (ctx.g.do_inherit ctx c p) herits) - -let rec type_type_params ?(enum_constructor=false) ctx path get_params p tp = - let n = tp.tp_name in - let c = mk_class ctx.m.curmod (fst path @ [snd path],n) p in - c.cl_params <- List.map (type_type_params ctx c.cl_path get_params p) tp.tp_params; - c.cl_kind <- KTypeParameter []; - if enum_constructor then c.cl_meta <- (Meta.EnumConstructorParam,[],c.cl_pos) :: c.cl_meta; - let t = TInst (c,List.map snd c.cl_params) in - match tp.tp_constraints with - | [] -> - n, t - | _ -> - let r = exc_protect ctx (fun r -> - r := (fun _ -> t); - let ctx = { ctx with type_params = ctx.type_params @ get_params() } in - let constr = List.map (load_complex_type ctx p) tp.tp_constraints in - (* check against direct recursion *) - let rec loop t = - match follow t with - | TInst (c2,_) when c == c2 -> error "Recursive constraint parameter is not allowed" p - | TInst ({ cl_kind = KTypeParameter cl },_) -> - List.iter loop cl - | _ -> - () - in - List.iter loop constr; - c.cl_kind <- KTypeParameter constr; - t - ) "constraint" in - delay ctx PForce (fun () -> ignore(!r())); - n, TLazy r - -let type_function_params ctx fd fname p = - let params = ref [] in - params := List.map (fun tp -> - type_type_params ctx ([],fname) (fun() -> !params) p tp - ) fd.f_params; - !params - -let find_enclosing com e = - let display_pos = ref (!Parser.resume_display) in - let mk_null p = (EDisplay(((EConst(Ident "null")),p),false),p) in - let encloses_display_pos p = - if p.pmin <= !display_pos.pmin && p.pmax >= !display_pos.pmax then begin - let p = !display_pos in - display_pos := { pfile = ""; pmin = -2; pmax = -2 }; - Some p - end else - None - in - let rec loop e = match fst e with - | EBlock el -> - let p = pos e in - (* We want to find the innermost block which contains the display position. *) - let el = List.map loop el in - let el = match encloses_display_pos p with - | None -> - el - | Some p2 -> - let b,el = List.fold_left (fun (b,el) e -> - let p = pos e in - if b || p.pmax <= p2.pmin then begin - (b,e :: el) - end else begin - let e_d = (EDisplay(mk_null p,false)),p in - (true,e :: e_d :: el) - end - ) (false,[]) el in - let el = if b then - el - else begin - mk_null p :: el - end in - List.rev el - in - (EBlock el),(pos e) - | _ -> - Ast.map_expr loop e - in - loop e - -let find_before_pos com e = - let display_pos = ref (!Parser.resume_display) in - let is_annotated p = - if p.pmax = !display_pos.pmin - 1 then begin - display_pos := { pfile = ""; pmin = -2; pmax = -2 }; - true - end else - false - in - let rec loop e = - if is_annotated (pos e) then - (EDisplay(e,false),(pos e)) - else - e - in - let rec map e = - loop (Ast.map_expr map e) - in - map e - -let type_function ctx args ret fmode f do_display p = - let locals = save_locals ctx in - let fargs = List.map (fun (n,c,t) -> - if n.[0] = '$' then error "Function argument names starting with a dollar are not allowed" p; - let c = type_function_arg_value ctx t c in - let v,c = add_local ctx n t, c in - if n = "this" then v.v_meta <- (Meta.This,[],p) :: v.v_meta; - v,c - ) args in - let old_ret = ctx.ret in - let old_fun = ctx.curfun in - let old_opened = ctx.opened in - ctx.curfun <- fmode; - ctx.ret <- ret; - ctx.opened <- []; - let e = match f.f_expr with None -> error "Function body required" p | Some e -> e in - let e = if not do_display then - type_expr ctx e NoValue - else begin - let e = match ctx.com.display with - | DMToplevel -> find_enclosing ctx.com e - | DMPosition | DMUsage | DMType -> find_before_pos ctx.com e - | _ -> e - in - try - if Common.defined ctx.com Define.NoCOpt then raise Exit; - type_expr ctx (Optimizer.optimize_completion_expr e) NoValue - with - | Parser.TypePath (_,None,_) | Exit -> - type_expr ctx e NoValue - | DisplayTypes [t] when (match follow t with TMono _ -> true | _ -> false) -> - type_expr ctx (if ctx.com.display = DMToplevel then find_enclosing ctx.com e else e) NoValue - end in - let e = match e.eexpr with - | TMeta((Meta.MergeBlock,_,_), ({eexpr = TBlock el} as e1)) -> e1 - | _ -> e - in - let rec loop e = - match e.eexpr with - | TReturn (Some e) -> (match follow e.etype with TAbstract({a_path = [],"Void"},[]) -> () | _ -> raise Exit) - | TFunction _ -> () - | _ -> Type.iter loop e - in - let have_ret = (try loop e; false with Exit -> true) in - if have_ret then - (try return_flow ctx e with Exit -> ()) - else (try type_eq EqStrict ret ctx.t.tvoid with Unify_error _ -> - match e.eexpr with - (* accept final throw (issue #1923) *) - | TThrow _ -> () - | TBlock el when (match List.rev el with ({eexpr = TThrow _} :: _) -> true | _ -> false) -> () - | _ -> display_error ctx ("Missing return " ^ (s_type (print_context()) ret)) p); - let rec loop e = - match e.eexpr with - | TCall ({ eexpr = TConst TSuper },_) -> raise Exit - | TFunction _ -> () - | _ -> Type.iter loop e - in - let has_super_constr() = - match ctx.curclass.cl_super with - | None -> - None - | Some (csup,tl) -> - try - let _,cf = get_constructor (fun f->f.cf_type) csup in - Some (Meta.has Meta.CompilerGenerated cf.cf_meta,TInst(csup,tl)) - with Not_found -> - None - in - let e = if fmode <> FunConstructor then - e - else match has_super_constr() with - | Some (was_forced,t_super) -> - (try - loop e; - if was_forced then - let e_super = mk (TConst TSuper) t_super e.epos in - let e_super_call = mk (TCall(e_super,[])) ctx.t.tvoid e.epos in - concat e_super_call e - else begin - display_error ctx "Missing super constructor call" p; - e - end - with - Exit -> e); - | None -> - e - in - locals(); - let e = match ctx.curfun, ctx.vthis with - | (FunMember|FunConstructor), Some v -> - let ev = mk (TVar (v,Some (mk (TConst TThis) ctx.tthis p))) ctx.t.tvoid p in - (match e.eexpr with - | TBlock l -> { e with eexpr = TBlock (ev::l) } - | _ -> mk (TBlock [ev;e]) e.etype p) - | _ -> e - in - List.iter (fun r -> r := Closed) ctx.opened; - ctx.ret <- old_ret; - ctx.curfun <- old_fun; - ctx.opened <- old_opened; - e , fargs - -let load_core_class ctx c = - let ctx2 = (match ctx.g.core_api with - | None -> - let com2 = Common.clone ctx.com in - com2.defines <- PMap.empty; - Common.define com2 Define.CoreApi; - Common.define com2 Define.Sys; - if ctx.in_macro then Common.define com2 Define.Macro; - com2.class_path <- ctx.com.std_path; - let ctx2 = ctx.g.do_create com2 in - ctx.g.core_api <- Some ctx2; - ctx2 - | Some c -> - c - ) in - let tpath = match c.cl_kind with - | KAbstractImpl a -> { tpackage = fst a.a_path; tname = snd a.a_path; tparams = []; tsub = None; } - | _ -> { tpackage = fst c.cl_path; tname = snd c.cl_path; tparams = []; tsub = None; } - in - let t = load_instance ctx2 tpath c.cl_pos true in - flush_pass ctx2 PFinal "core_final"; - match t with - | TInst (ccore,_) | TAbstract({a_impl = Some ccore}, _) -> - ccore - | _ -> - assert false - -let init_core_api ctx c = - let ccore = load_core_class ctx c in - begin try - List.iter2 (fun (n1,t1) (n2,t2) -> match follow t1, follow t2 with - | TInst({cl_kind = KTypeParameter l1},_),TInst({cl_kind = KTypeParameter l2},_) -> - begin try - List.iter2 (fun t1 t2 -> type_eq EqCoreType t2 t1) l1 l2 - with - | Invalid_argument _ -> - error "Type parameters must have the same number of constraints as core type" c.cl_pos - | Unify_error l -> - display_error ctx ("Type parameter " ^ n2 ^ " has different constraint than in core type") c.cl_pos; - display_error ctx (error_msg (Unify l)) c.cl_pos - end - | t1,t2 -> - Printf.printf "%s %s" (s_type (print_context()) t1) (s_type (print_context()) t2); - assert false - ) ccore.cl_params c.cl_params; - with Invalid_argument _ -> - error "Class must have the same number of type parameters as core type" c.cl_pos - end; - (match c.cl_doc with - | None -> c.cl_doc <- ccore.cl_doc - | Some _ -> ()); - let compare_fields f f2 = - let p = (match f2.cf_expr with None -> c.cl_pos | Some e -> e.epos) in - (try - type_eq EqCoreType (apply_params ccore.cl_params (List.map snd c.cl_params) f.cf_type) f2.cf_type - with Unify_error l -> - display_error ctx ("Field " ^ f.cf_name ^ " has different type than in core type") p; - display_error ctx (error_msg (Unify l)) p); - if f2.cf_public <> f.cf_public then error ("Field " ^ f.cf_name ^ " has different visibility than core type") p; - (match f2.cf_doc with - | None -> f2.cf_doc <- f.cf_doc - | Some _ -> ()); - if f2.cf_kind <> f.cf_kind then begin - match f2.cf_kind, f.cf_kind with - | Method MethInline, Method MethNormal -> () (* allow to add 'inline' *) - | Method MethNormal, Method MethInline -> () (* allow to disable 'inline' *) - | _ -> - error ("Field " ^ f.cf_name ^ " has different property access than core type") p; - end; - (match follow f.cf_type, follow f2.cf_type with - | TFun (pl1,_), TFun (pl2,_) -> - if List.length pl1 != List.length pl2 then error "Argument count mismatch" p; - List.iter2 (fun (n1,_,_) (n2,_,_) -> - if n1 <> n2 then error ("Method parameter name '" ^ n2 ^ "' should be '" ^ n1 ^ "'") p; - ) pl1 pl2; - | _ -> ()); - in - let check_fields fcore fl = - PMap.iter (fun i f -> - if not f.cf_public then () else - let f2 = try PMap.find f.cf_name fl with Not_found -> error ("Missing field " ^ i ^ " required by core type") c.cl_pos in - compare_fields f f2; - ) fcore; - PMap.iter (fun i f -> - let p = (match f.cf_expr with None -> c.cl_pos | Some e -> e.epos) in - if f.cf_public && not (Meta.has Meta.Hack f.cf_meta) && not (PMap.mem f.cf_name fcore) && not (List.memq f c.cl_overrides) then error ("Public field " ^ i ^ " is not part of core type") p; - ) fl; - in - check_fields ccore.cl_fields c.cl_fields; - check_fields ccore.cl_statics c.cl_statics; - (match ccore.cl_constructor, c.cl_constructor with - | None, None -> () - | Some { cf_public = false }, _ -> () - | Some f, Some f2 -> compare_fields f f2 - | None, Some { cf_public = false } -> () - | _ -> error "Constructor differs from core type" c.cl_pos) - -let check_global_metadata ctx f_add mpath tpath so = - let sl1 = if mpath = tpath then - (fst tpath) @ [snd tpath] - else - (fst mpath) @ [snd mpath;snd tpath] - in - let sl1,field_mode = match so with None -> sl1,false | Some s -> sl1 @ [s],true in - List.iter (fun (sl2,m,(recursive,to_types,to_fields)) -> - let rec loop sl1 sl2 = match sl1,sl2 with - | [],[] -> - true - (* always recurse into types of package paths *) - | (s1 :: s11 :: _),[s2] when is_lower_ident s2 && not (is_lower_ident s11)-> - s1 = s2 - | [_],[""] -> - true - | _,([] | [""]) -> - recursive - | [],_ -> - false - | (s1 :: sl1),(s2 :: sl2) -> - s1 = s2 && loop sl1 sl2 - in - let add = ((field_mode && to_fields) || (not field_mode && to_types)) && (loop sl1 sl2) in - if add then f_add m - ) ctx.g.global_metadata - -let patch_class ctx c fields = - let path = match c.cl_kind with - | KAbstractImpl a -> a.a_path - | _ -> c.cl_path - in - let h = (try Some (Hashtbl.find ctx.g.type_patches path) with Not_found -> None) in - match h with - | None -> fields - | Some (h,hcl) -> - c.cl_meta <- c.cl_meta @ hcl.tp_meta; - let rec loop acc = function - | [] -> acc - | f :: l -> - (* patch arguments types *) - (match f.cff_kind with - | FFun ff -> - let param ((n,opt,t,e) as p) = - try - let t2 = (try Hashtbl.find h (("$" ^ f.cff_name ^ "__" ^ n),false) with Not_found -> Hashtbl.find h (("$" ^ n),false)) in - n, opt, t2.tp_type, e - with Not_found -> - p - in - f.cff_kind <- FFun { ff with f_args = List.map param ff.f_args } - | _ -> ()); - (* other patches *) - match (try Some (Hashtbl.find h (f.cff_name,List.mem AStatic f.cff_access)) with Not_found -> None) with - | None -> loop (f :: acc) l - | Some { tp_remove = true } -> loop acc l - | Some p -> - f.cff_meta <- f.cff_meta @ p.tp_meta; - (match p.tp_type with - | None -> () - | Some t -> - f.cff_kind <- match f.cff_kind with - | FVar (_,e) -> FVar (Some t,e) - | FProp (get,set,_,eo) -> FProp (get,set,Some t,eo) - | FFun f -> FFun { f with f_type = Some t }); - loop (f :: acc) l - in - List.rev (loop [] fields) - -let string_list_of_expr_path (e,p) = - try string_list_of_expr_path_raise (e,p) - with Exit -> error "Invalid path" p - -let build_enum_abstract ctx c a fields p = - List.iter (fun field -> - match field.cff_kind with - | FVar(ct,eo) when not (List.mem AStatic field.cff_access) -> - field.cff_access <- [AStatic;APublic;AInline]; - field.cff_meta <- (Meta.Enum,[],field.cff_pos) :: (Meta.Impl,[],field.cff_pos) :: field.cff_meta; - let e = match eo with - | None -> error "Value required" field.cff_pos - | Some e -> (ECast(e,None),field.cff_pos) - in - field.cff_kind <- FVar(ct,Some e) - | _ -> - () - ) fields; - EVars ["",Some (CTAnonymous fields),None],p - -let is_java_native_function meta = try - match Meta.get Meta.Native meta with - | (Meta.Native,[],_) -> true - | _ -> false - with | Not_found -> false - -let build_module_def ctx mt meta fvars context_init fbuild = - let rec loop = function - | (Meta.Build,args,p) :: l -> - let epath, el = (match args with - | [ECall (epath,el),p] -> epath, el - | _ -> error "Invalid build parameters" p - ) in - let s = try String.concat "." (List.rev (string_list_of_expr_path epath)) with Error (_,p) -> error "Build call parameter must be a class path" p in - if ctx.in_macro then error "You cannot use @:build inside a macro : make sure that your enum is not used in macro" p; - let old = ctx.g.get_build_infos in - ctx.g.get_build_infos <- (fun() -> Some (mt, List.map snd (t_infos mt).mt_params, fvars())); - context_init(); - let r = try apply_macro ctx MBuild s el p with e -> ctx.g.get_build_infos <- old; raise e in - ctx.g.get_build_infos <- old; - (match r with - | None -> error "Build failure" p - | Some e -> fbuild e; loop l) - | (Meta.Enum,_,p) :: l -> - begin match mt with - | TClassDecl ({cl_kind = KAbstractImpl a} as c) -> - context_init(); - let e = build_enum_abstract ctx c a (fvars()) p in - fbuild e; - loop l - | _ -> - loop l - end - | _ :: l -> loop l - | [] -> () - in - (* let errors go through to prevent resume if build fails *) - loop meta - -let init_class ctx c p context_init herits fields = - (* a lib type will skip most checks *) - let is_lib = Meta.has Meta.LibType c.cl_meta in - if is_lib && not c.cl_extern then ctx.com.error "@:libType can only be used in extern classes" c.cl_pos; - (* a native type will skip one check: the static vs non-static field *) - let is_native = Meta.has Meta.JavaNative c.cl_meta || Meta.has Meta.CsNative c.cl_meta in - - let ctx = { - ctx with - curclass = c; - type_params = c.cl_params; - pass = PBuildClass; - tthis = (match c.cl_kind with - | KAbstractImpl a -> - (match a.a_this with - | TMono r when !r = None -> TAbstract (a,List.map snd c.cl_params) - | t -> t) - | _ -> TInst (c,List.map snd c.cl_params)); - on_error = (fun ctx msg ep -> - ctx.com.error msg ep; - (* macros expressions might reference other code, let's recall which class we are actually compiling *) - if !locate_macro_error && (ep.pfile <> c.cl_pos.pfile || ep.pmax < c.cl_pos.pmin || ep.pmin > c.cl_pos.pmax) then ctx.com.error "Defined in this class" c.cl_pos - ); - } in - locate_macro_error := true; - incr stats.s_classes_built; - let fields = patch_class ctx c fields in - let fields = ref fields in - let get_fields() = !fields in - build_module_def ctx (TClassDecl c) c.cl_meta get_fields context_init (fun (e,p) -> - match e with - | EVars [_,Some (CTAnonymous f),None] -> - List.iter (fun f -> - if List.mem AMacro f.cff_access then - (match ctx.g.macros with - | Some (_,mctx) when Hashtbl.mem mctx.g.types_module c.cl_path -> - (* assume that if we had already a macro with the same name, it has not been changed during the @:build operation *) - if not (List.exists (fun f2 -> f2.cff_name = f.cff_name && List.mem AMacro f2.cff_access) (!fields)) then - error "Class build macro cannot return a macro function when the class has already been compiled into the macro context" p - | _ -> ()) - ) f; - fields := f - | _ -> error "Class build macro must return a single variable with anonymous fields" p - ); - let fields = !fields in - let core_api = Meta.has Meta.CoreApi c.cl_meta in - let is_class_macro = Meta.has Meta.Macro c.cl_meta in - if is_class_macro then display_error ctx "Macro classes are no longer allowed in haxe 3" p; - let fields, herits = if is_class_macro && not ctx.in_macro then begin - c.cl_extern <- true; - List.filter (fun f -> List.mem AStatic f.cff_access) fields, [] - end else fields, herits in - if core_api && ctx.com.display = DMNone then delay ctx PForce (fun() -> init_core_api ctx c); - let rec extends_public c = - Meta.has Meta.PublicFields c.cl_meta || - match c.cl_super with - | None -> false - | Some (c,_) -> extends_public c - in - let extends_public = extends_public c in - let is_public access parent = - if List.mem APrivate access then - false - else if List.mem APublic access then - true - else match parent with - | Some { cf_public = p } -> p - | _ -> c.cl_extern || c.cl_interface || extends_public - in - let rec get_parent c name = - match c.cl_super with - | None -> None - | Some (csup,_) -> - try - Some (PMap.find name csup.cl_fields) - with - Not_found -> get_parent csup name - in - let type_opt ctx p t = - match t with - | None when c.cl_extern || c.cl_interface -> - display_error ctx "Type required for extern classes and interfaces" p; - t_dynamic - | None when core_api -> - display_error ctx "Type required for core api classes" p; - t_dynamic - | _ -> - load_type_opt ctx p t - in - let rec has_field f = function - | None -> false - | Some (c,_) -> - PMap.exists f c.cl_fields || has_field f c.cl_super || List.exists (fun i -> has_field f (Some i)) c.cl_implements - in - - let rec get_declared f = function - | None -> None - | Some (c,a) when PMap.exists f c.cl_fields -> - Some (c,a) - | Some (c,_) -> - let ret = get_declared f c.cl_super in - match ret with - | Some r -> Some r - | None -> - let rec loop ifaces = match ifaces with - | [] -> None - | i :: ifaces -> match get_declared f (Some i) with - | Some r -> Some r - | None -> loop ifaces - in - loop c.cl_implements - in - - if not is_lib then (match c.cl_super with None -> () | Some _ -> delay ctx PForce (fun() -> check_overriding ctx c)); - if ctx.com.config.pf_overload && not is_lib then delay ctx PForce (fun() -> check_overloads ctx c); - - (* ----------------------- COMPLETION ----------------------------- *) - - let display_file = match ctx.com.display with - | DMNone -> false - | DMResolve s -> - let mt = load_type_def ctx p {tname = s; tpackage = []; tsub = None; tparams = []} in - let p = (t_infos mt).mt_pos in - raise (DisplayPosition [p]); - | _ -> - Common.unique_full_path p.pfile = (!Parser.resume_display).pfile - in - - let cp = !Parser.resume_display in - - let delayed_expr = ref [] in - - let rec is_full_type t = - match t with - | TFun (args,ret) -> is_full_type ret && List.for_all (fun (_,_,t) -> is_full_type t) args - | TMono r -> (match !r with None -> false | Some t -> is_full_type t) - | TAbstract _ | TInst _ | TEnum _ | TLazy _ | TDynamic _ | TAnon _ | TType _ -> true - in - let bind_type ctx cf r p macro = - if ctx.com.display <> DMNone then begin - let cp = !Parser.resume_display in - if display_file && (cp.pmin = 0 || (p.pmin <= cp.pmin && p.pmax >= cp.pmax)) then begin - if macro && not ctx.in_macro then - (* force macro system loading of this class in order to get completion *) - delay ctx PTypeField (fun() -> ignore(ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name [] p)) - else begin - cf.cf_type <- TLazy r; - delayed_expr := (ctx,Some r) :: !delayed_expr; - end - end else begin - if not (is_full_type cf.cf_type) then begin - delayed_expr := (ctx, None) :: !delayed_expr; - cf.cf_type <- TLazy r; - end; - end - end else if macro && not ctx.in_macro then - () - else begin - cf.cf_type <- TLazy r; - (* is_lib ? *) - delayed_expr := (ctx,Some r) :: !delayed_expr; - end - in - - let force_constructor = ref false in - - let bind_var ctx cf e stat inline = - let p = cf.cf_pos in - if not stat && not is_lib then begin match get_declared cf.cf_name c.cl_super with - | None -> () - | Some (csup,_) -> - (* this can happen on -net-lib generated classes if a combination of explicit interfaces and variables with the same name happens *) - if not (csup.cl_interface && Meta.has Meta.CsNative c.cl_meta) then - error ("Redefinition of variable " ^ cf.cf_name ^ " in subclass is not allowed. Previously declared at " ^ (Ast.s_type_path csup.cl_path) ) p - end; - let t = cf.cf_type in - - match e with - | None -> () - | Some e -> - if requires_value_meta ctx.com (Some c) then cf.cf_meta <- ((Meta.Value,[e],cf.cf_pos) :: cf.cf_meta); - let check_cast e = - (* insert cast to keep explicit field type (issue #1901) *) - if type_iseq e.etype cf.cf_type then - e - else begin match e.eexpr,follow cf.cf_type with - | TConst (TInt i),TAbstract({a_path=[],"Float"},_) -> - (* turn int constant to float constant if expected type is float *) - {e with eexpr = TConst (TFloat (Int32.to_string i))} - | _ -> - mk_cast e cf.cf_type e.epos - end - in - let r = exc_protect ctx (fun r -> - (* type constant init fields (issue #1956) *) - if not !return_partial_type || (match fst e with EConst _ -> true | _ -> false) then begin - r := (fun() -> t); - context_init(); - if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.in_macro then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ cf.cf_name); - let e = type_var_field ctx t e stat p in - let require_constant_expression e msg = match Optimizer.make_constant_expression ctx e with - | Some e -> e - | None -> display_error ctx msg p; e - in - let e = (match cf.cf_kind with - | Var v when c.cl_extern || Meta.has Meta.Extern cf.cf_meta -> - if not stat then begin - display_error ctx "Extern non-static variables may not be initialized" p; - e - end else if v.v_read <> AccInline then begin - display_error ctx "Extern non-inline variables may not be initialized" p; - e - end else require_constant_expression e "Extern variable initialization must be a constant value" - | Var v when is_extern_field cf -> - (* disallow initialization of non-physical fields (issue #1958) *) - display_error ctx "This field cannot be initialized because it is not a real variable" p; e - | Var v when not stat -> - let e = match Optimizer.make_constant_expression ctx e with - | Some e -> e - | None -> - let rec has_this e = match e.eexpr with - | TConst TThis -> - display_error ctx "Cannot access this or other member field in variable initialization" e.epos; - | TLocal v when (match ctx.vthis with Some v2 -> v == v2 | None -> false) -> - display_error ctx "Cannot access this or other member field in variable initialization" e.epos; - | _ -> - Type.iter has_this e - in - has_this e; - e - in - e - | Var v when v.v_read = AccInline -> - let e = require_constant_expression e "Inline variable initialization must be a constant value" in - begin match c.cl_kind with - | KAbstractImpl a when Meta.has Meta.Enum cf.cf_meta && Meta.has Meta.Enum a.a_meta -> - unify ctx t (TAbstract(a,(List.map (fun _ -> mk_mono()) a.a_params))) p; - begin match e.eexpr with - | TCast(e1,None) -> unify ctx e1.etype a.a_this e1.epos - | _ -> assert false - end - | _ -> - () - end; - e - | _ -> - e - ) in - let e = check_cast e in - cf.cf_expr <- Some e; - cf.cf_type <- t; - end; - t - ) "bind_var" in - if not stat then force_constructor := true; - bind_type ctx cf r (snd e) false - in - - (* ----------------------- FIELD INIT ----------------------------- *) - - let loop_cf f = - let name = f.cff_name in - check_global_metadata ctx (fun m -> f.cff_meta <- m :: f.cff_meta) c.cl_module.m_path c.cl_path (Some name); - let p = f.cff_pos in - if name.[0] = '$' && ctx.com.display = DMNone then error "Field names starting with a dollar are not allowed" p; - let stat = List.mem AStatic f.cff_access in - let extern = Meta.has Meta.Extern f.cff_meta || c.cl_extern in - let is_abstract,allow_inline = - match c.cl_kind, f.cff_kind with - | KAbstractImpl _, _ -> true,true - |_, FFun _ -> false,ctx.g.doinline || extern - | _ -> false,true - in - let inline = List.mem AInline f.cff_access && allow_inline in - let override = List.mem AOverride f.cff_access in - let is_macro = Meta.has Meta.Macro f.cff_meta in - if is_macro then ctx.com.warning "@:macro should now be 'macro' accessor" p; - let is_macro = is_macro || List.mem AMacro f.cff_access in - List.iter (fun acc -> - match (acc, f.cff_kind) with - | APublic, _ | APrivate, _ | AStatic, _ -> () - | ADynamic, FFun _ | AOverride, FFun _ | AMacro, FFun _ | AInline, FFun _ | AInline, FVar _ -> () - | _, FVar _ -> error ("Invalid accessor '" ^ Ast.s_access acc ^ "' for variable " ^ name) p - | _, FProp _ -> error ("Invalid accessor '" ^ Ast.s_access acc ^ "' for property " ^ name) p - ) f.cff_access; - if override then (match c.cl_super with None -> error ("Invalid override on field '" ^ f.cff_name ^ "': class has no super class") p | _ -> ()); - (* build the per-field context *) - let ctx = { - ctx with - pass = PBuildClass; (* will be set later to PTypeExpr *) - } in - match f.cff_kind with - | FVar (t,e) -> - if not stat && is_abstract then error (f.cff_name ^ ": Cannot declare member variable in abstract") p; - if inline && not stat then error (f.cff_name ^ ": Inline variable must be static") p; - if inline && e = None then error (f.cff_name ^ ": Inline variable must be initialized") p; - - let t = (match t with - | None when not stat && e = None -> - error ("Type required for member variable " ^ name) p; - | None -> - mk_mono() - | Some t -> - (* TODO is_lib: only load complex type if needed *) - let old = ctx.type_params in - if stat then ctx.type_params <- []; - let t = load_complex_type ctx p t in - if stat then ctx.type_params <- old; - t - ) in - let cf = { - cf_name = name; - cf_doc = f.cff_doc; - cf_meta = f.cff_meta; - cf_type = t; - cf_pos = f.cff_pos; - cf_kind = Var (if inline then { v_read = AccInline ; v_write = AccNever } else { v_read = AccNormal; v_write = AccNormal }); - cf_expr = None; - cf_public = is_public f.cff_access None; - cf_params = []; - cf_overloads = []; - } in - ctx.curfield <- cf; - bind_var ctx cf e stat inline; - f, false, cf, true - | FFun fd -> - let params = type_function_params ctx fd f.cff_name p in - if inline && c.cl_interface then error (f.cff_name ^ ": You can't declare inline methods in interfaces") p; - if Meta.has Meta.Generic f.cff_meta then begin - if params = [] then error (f.cff_name ^ ": Generic functions must have type parameters") p; - end; - let is_macro = is_macro || (is_class_macro && stat) in - let f, stat, fd = if not is_macro || stat then - f, stat, fd - else if ctx.in_macro then - (* non-static macros methods are turned into static when we are running the macro *) - { f with cff_access = AStatic :: f.cff_access }, true, fd - else - (* remove display of first argument which will contain the "this" expression *) - f, stat, { fd with f_args = match fd.f_args with [] -> [] | _ :: l -> l } - in - let fd = if not is_macro then - fd - else begin - if ctx.in_macro then begin - (* a class with a macro cannot be extern in macro context (issue #2015) *) - c.cl_extern <- false; - let texpr = CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = None } in - (* ExprOf type parameter might contain platform-specific type, let's replace it by Expr *) - let no_expr_of = function - | CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some ("ExprOf"); tparams = [TPType _] } - | CTPath { tpackage = []; tname = ("ExprOf"); tsub = None; tparams = [TPType _] } -> Some texpr - | t -> Some t - in - { - f_params = fd.f_params; - f_type = (match fd.f_type with None -> Some texpr | Some t -> no_expr_of t); - f_args = List.map (fun (a,o,t,e) -> a,o,(match t with None -> Some texpr | Some t -> no_expr_of t),e) fd.f_args; - f_expr = fd.f_expr; - } - end else - let tdyn = Some (CTPath { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None }) in - let to_dyn = function - | { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some ("ExprOf"); tparams = [TPType t] } -> Some t - | { tpackage = []; tname = ("ExprOf"); tsub = None; tparams = [TPType t] } -> Some t - | { tpackage = ["haxe"]; tname = ("PosInfos"); tsub = None; tparams = [] } -> error "haxe.PosInfos is not allowed on macro functions, use Context.currentPos() instead" p - | _ -> tdyn - in - { - f_params = fd.f_params; - f_type = (match fd.f_type with Some (CTPath t) -> to_dyn t | _ -> tdyn); - f_args = List.map (fun (a,o,t,_) -> a,o,(match t with Some (CTPath t) -> to_dyn t | _ -> tdyn),None) fd.f_args; - f_expr = None; - } - end in - let parent = (if not stat then get_parent c name else None) in - let dynamic = List.mem ADynamic f.cff_access || (match parent with Some { cf_kind = Method MethDynamic } -> true | _ -> false) in - if inline && dynamic then error (f.cff_name ^ ": You can't have both 'inline' and 'dynamic'") p; - ctx.type_params <- (match c.cl_kind with - | KAbstractImpl a when Meta.has Meta.Impl f.cff_meta -> - params @ a.a_params - | _ -> - if stat then params else params @ ctx.type_params); - let constr = (name = "new") in - (* TODO is_lib: avoid forcing the return type to be typed *) - let ret = if constr then ctx.t.tvoid else type_opt ctx p fd.f_type in - let rec loop args = match args with - | (name,opt,t,ct) :: args -> - (* TODO is_lib: avoid forcing the field to be typed *) - let t, ct = type_function_arg ctx (type_opt ctx p t) ct opt p in - delay ctx PTypeField (fun() -> match follow t with - | TAbstract({a_path = ["haxe";"extern"],"Rest"},_) -> - if not c.cl_extern then error "Rest argument are only supported for extern methods" p; - if opt then error "Rest argument cannot be optional" p; - if ct <> None then error "Rest argument cannot have default value" p; - if args <> [] then error "Rest should only be used for the last function argument" p; - | _ -> - () - ); - (name, ct, t) :: (loop args) - | [] -> - [] - in - let args = loop fd.f_args in - let t = TFun (fun_args args,ret) in - if c.cl_interface && not stat && fd.f_expr <> None then error (f.cff_name ^ ": An interface method cannot have a body") p; - if constr then begin - if c.cl_interface then error "An interface cannot have a constructor" p; - if stat then error "A constructor must not be static" p; - match fd.f_type with - | None | Some (CTPath { tpackage = []; tname = "Void" }) -> () - | _ -> error "A class constructor can't have a return value" p - end; - let cf = { - cf_name = name; - cf_doc = f.cff_doc; - cf_meta = f.cff_meta; - cf_type = t; - cf_pos = f.cff_pos; - cf_kind = Method (if is_macro then MethMacro else if inline then MethInline else if dynamic then MethDynamic else MethNormal); - cf_expr = None; - cf_public = is_public f.cff_access parent; - cf_params = params; - cf_overloads = []; - } in - generate_value_meta ctx.com (Some c) cf fd.f_args; - let do_bind = ref (((not c.cl_extern || inline) && not c.cl_interface) || cf.cf_name = "__init__") in - let do_add = ref true in - (match c.cl_kind with - | KAbstractImpl a -> - let m = mk_mono() in - let ta = TAbstract(a, List.map (fun _ -> mk_mono()) a.a_params) in - let tthis = if Meta.has Meta.Impl f.cff_meta || Meta.has Meta.To f.cff_meta then monomorphs a.a_params a.a_this else a.a_this in - let check_bind () = - if fd.f_expr = None then begin - if inline then error (f.cff_name ^ ": Inline functions must have an expression") f.cff_pos; - begin match fd.f_type with - | None -> error (f.cff_name ^ ": Functions without expressions must have an explicit return type") f.cff_pos - | Some _ -> () - end; - cf.cf_meta <- (Meta.NoExpr,[],cf.cf_pos) :: cf.cf_meta; - do_add := false; - do_bind := false; - end - in - let rec loop ml = match ml with - | (Meta.From,_,_) :: _ -> - if is_macro then error (f.cff_name ^ ": Macro cast functions are not supported") p; - let r = fun () -> - (* the return type of a from-function must be the abstract, not the underlying type *) - (try type_eq EqStrict ret ta with Unify_error l -> error (error_msg (Unify l)) p); - match t with - | TFun([_,_,t],_) -> t - | _ -> error (f.cff_name ^ ": @:from cast functions must accept exactly one argument") p - in - a.a_from_field <- (TLazy (ref r),cf) :: a.a_from_field; - | (Meta.To,_,_) :: _ -> - if is_macro then error (f.cff_name ^ ": Macro cast functions are not supported") p; - if not (Meta.has Meta.Impl cf.cf_meta) then cf.cf_meta <- (Meta.Impl,[],cf.cf_pos) :: cf.cf_meta; - let resolve_m args = - (try unify_raise ctx t (tfun (tthis :: args) m) f.cff_pos with Error (Unify l,p) -> error (error_msg (Unify l)) p); - match follow m with - | TMono _ when (match cf.cf_type with TFun(_,r) -> r == t_dynamic | _ -> false) -> t_dynamic - | m -> m - in - let r = exc_protect ctx (fun r -> - let args = if Meta.has Meta.MultiType a.a_meta then begin - let ctor = try - PMap.find "_new" c.cl_statics - with Not_found -> - error "Constructor of multi-type abstract must be defined before the individual @:to-functions are" cf.cf_pos - in - (* delay ctx PFinal (fun () -> unify ctx m tthis f.cff_pos); *) - let args = match follow (monomorphs a.a_params ctor.cf_type) with - | TFun(args,_) -> List.map (fun (_,_,t) -> t) args - | _ -> assert false - in - args - end else - [] - in - let t = resolve_m args in - r := (fun() -> t); - t - ) "@:to" in - delay ctx PForce (fun() -> ignore ((!r)())); - a.a_to_field <- (TLazy r, cf) :: a.a_to_field - | (Meta.ArrayAccess,_,_) :: _ -> - if is_macro then error (f.cff_name ^ ": Macro array-access functions are not supported") p; - a.a_array <- cf :: a.a_array; - if Meta.has Meta.CoreType a.a_meta then check_bind(); - | (Meta.Op,[EBinop(op,_,_),_],_) :: _ -> - if is_macro then error (f.cff_name ^ ": Macro operator functions are not supported") p; - let targ = if Meta.has Meta.Impl f.cff_meta then tthis else ta in - let left_eq,right_eq = match follow t with - | TFun([(_,_,t1);(_,_,t2)],_) -> - type_iseq targ t1,type_iseq targ t2 - | _ -> - if Meta.has Meta.Impl cf.cf_meta then - error (f.cff_name ^ ": Member @:op functions must accept exactly one argument") cf.cf_pos - else - error (f.cff_name ^ ": Static @:op functions must accept exactly two arguments") cf.cf_pos - in - if not (left_eq || right_eq) then error (f.cff_name ^ ": The left or right argument type must be " ^ (s_type (print_context()) targ)) f.cff_pos; - if right_eq && Meta.has Meta.Commutative f.cff_meta then error (f.cff_name ^ ": @:commutative is only allowed if the right argument is not " ^ (s_type (print_context()) targ)) f.cff_pos; - a.a_ops <- (op,cf) :: a.a_ops; - check_bind(); - | (Meta.Op,[EUnop(op,flag,_),_],_) :: _ -> - if is_macro then error (f.cff_name ^ ": Macro operator functions are not supported") p; - let targ = if Meta.has Meta.Impl f.cff_meta then tthis else ta in - (try type_eq EqStrict t (tfun [targ] (mk_mono())) with Unify_error l -> raise (Error ((Unify l),f.cff_pos))); - a.a_unops <- (op,flag,cf) :: a.a_unops; - check_bind(); - | (Meta.Impl,_,_) :: ml when f.cff_name <> "_new" && not is_macro -> - begin match follow t with - | TFun((_,_,t1) :: _, _) when type_iseq tthis t1 -> - () - | _ -> - display_error ctx ("First argument of implementation function must be " ^ (s_type (print_context()) tthis)) f.cff_pos - end; - loop ml -(* | (Meta.Resolve,_,_) :: _ -> - let targ = if Meta.has Meta.Impl f.cff_meta then tthis else ta in - begin match follow t with - | TFun([(_,_,t1);(_,_,t2)],_) -> - if not is_macro then begin - if not (type_iseq targ t1) then error ("First argument type must be " ^ (s_type (print_context()) targ)) f.cff_pos; - if not (type_iseq ctx.t.tstring t2) then error ("Second argument type must be String") f.cff_pos - end - | _ -> - error ("Field type of resolve must be " ^ (s_type (print_context()) targ) ^ " -> String -> T") f.cff_pos - end *) - | _ :: ml -> - loop ml - | [] -> - () - in - loop f.cff_meta; - if f.cff_name = "_new" && Meta.has Meta.MultiType a.a_meta then do_bind := false; - | _ -> - ()); - init_meta_overloads ctx (Some c) cf; - ctx.curfield <- cf; - let r = exc_protect ctx (fun r -> - if not !return_partial_type then begin - r := (fun() -> t); - context_init(); - incr stats.s_methods_typed; - if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.in_macro then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ name); - let fmode = (match c.cl_kind with - | KAbstractImpl _ -> - (match args with - | ("this",_,_) :: _ -> FunMemberAbstract - | _ when name = "_new" -> FunMemberAbstract - | _ -> FunStatic) - | _ -> - if constr then FunConstructor else if stat then FunStatic else FunMember - ) in - let display_field = display_file && (f.cff_pos.pmin <= cp.pmin && f.cff_pos.pmax >= cp.pmax) in - match ctx.com.platform with - | Java when is_java_native_function cf.cf_meta -> - if fd.f_expr <> None then - ctx.com.warning "@:native function definitions shouldn't include an expression. This behaviour is deprecated." cf.cf_pos; - cf.cf_expr <- None; - cf.cf_type <- t - | _ -> - let e , fargs = type_function ctx args ret fmode fd display_field p in - let f = { - tf_args = fargs; - tf_type = ret; - tf_expr = e; - } in - if stat && name = "__init__" then - (match e.eexpr with - | TBlock [] | TBlock [{ eexpr = TConst _ }] | TConst _ | TObjectDecl [] -> () - | _ -> c.cl_init <- Some e); - cf.cf_expr <- Some (mk (TFunction f) t p); - cf.cf_type <- t; - end; - t - ) "type_fun" in - if !do_bind then bind_type ctx cf r (match fd.f_expr with Some e -> snd e | None -> f.cff_pos) is_macro; - f, constr, cf, !do_add - | FProp (get,set,t,eo) -> - (match c.cl_kind with - | KAbstractImpl a when Meta.has Meta.Impl f.cff_meta -> - ctx.type_params <- a.a_params; - | _ -> ()); - (* TODO is_lib: lazify load_complex_type *) - let ret = (match t, eo with - | None, None -> error (f.cff_name ^ ": Property must either define a type or a default value") p; - | None, _ -> mk_mono() - | Some t, _ -> load_complex_type ctx p t - ) in - let t_get,t_set = match c.cl_kind with - | KAbstractImpl a when Meta.has Meta.Impl f.cff_meta -> - if Meta.has Meta.IsVar f.cff_meta then error (f.cff_name ^ ": Abstract properties cannot be real variables") f.cff_pos; - let ta = apply_params a.a_params (List.map snd a.a_params) a.a_this in - tfun [ta] ret, tfun [ta;ret] ret - | _ -> tfun [] ret, TFun(["value",false,ret],ret) - in - let check_method m t req_name = - if ctx.com.display <> DMNone then () else - try - let overloads = - (* on pf_overload platforms, the getter/setter may have been defined as an overloaded function; get all overloads *) - if ctx.com.config.pf_overload then - if stat then - let f = PMap.find m c.cl_statics in - (f.cf_type, f) :: (List.map (fun f -> f.cf_type, f) f.cf_overloads) - else - get_overloads c m - else - [ if stat then - let f = PMap.find m c.cl_statics in - f.cf_type, f - else match class_field c (List.map snd c.cl_params) m with - | _, t,f -> t,f ] - in - (* choose the correct overload if and only if there is more than one overload found *) - let rec get_overload overl = match overl with - | [tf] -> tf - | (t2,f2) :: overl -> - if type_iseq t t2 then - (t2,f2) - else - get_overload overl - | [] -> - if c.cl_interface then - raise Not_found - else - raise (Error (Custom - (Printf.sprintf "No overloaded method named %s was compatible with the property %s with expected type %s" m name (s_type (print_context()) t) - ), p)) - in - let t2, f2 = get_overload overloads in - (* accessors must be public on As3 (issue #1872) *) - if Common.defined ctx.com Define.As3 then f2.cf_meta <- (Meta.Public,[],p) :: f2.cf_meta; - (match f2.cf_kind with - | Method MethMacro -> - display_error ctx (f2.cf_name ^ ": Macro methods cannot be used as property accessor") p; - display_error ctx (f2.cf_name ^ ": Accessor method is here") f2.cf_pos; - | _ -> ()); - unify_raise ctx t2 t f2.cf_pos; - if (Meta.has Meta.Impl f.cff_meta && not (Meta.has Meta.Impl f2.cf_meta)) || (Meta.has Meta.Impl f2.cf_meta && not (Meta.has Meta.Impl f.cff_meta)) then - display_error ctx "Mixing abstract implementation and static properties/accessors is not allowed" f2.cf_pos; - (match req_name with None -> () | Some n -> display_error ctx ("Please use " ^ n ^ " to name your property access method") f2.cf_pos); - with - | Error (Unify l,p) -> raise (Error (Stack (Custom ("In method " ^ m ^ " required by property " ^ name),Unify l),p)) - | Not_found -> - if req_name <> None then display_error ctx (f.cff_name ^ ": Custom property accessor is no longer supported, please use get/set") p else - if c.cl_interface then begin - let cf = mk_field m t p in - cf.cf_meta <- [Meta.CompilerGenerated,[],p]; - cf.cf_kind <- Method MethNormal; - c.cl_fields <- PMap.add cf.cf_name cf c.cl_fields; - c.cl_ordered_fields <- cf :: c.cl_ordered_fields; - end else if not c.cl_extern then begin - try - let _, _, f2 = (if not stat then let f = PMap.find m c.cl_statics in None, f.cf_type, f else class_field c (List.map snd c.cl_params) m) in - display_error ctx (Printf.sprintf "Method %s is no valid accessor for %s because it is %sstatic" m name (if stat then "not " else "")) f2.cf_pos - with Not_found -> - display_error ctx ("Method " ^ m ^ " required by property " ^ name ^ " is missing") p - end - in - let get = (match get with - | "null" -> AccNo - | "dynamic" -> AccCall - | "never" -> AccNever - | "default" -> AccNormal - | _ -> - let get = if get = "get" then "get_" ^ name else get in - if not is_lib then delay ctx PTypeField (fun() -> check_method get t_get (if get <> "get" && get <> "get_" ^ name then Some ("get_" ^ name) else None)); - AccCall - ) in - let set = (match set with - | "null" -> - (* standard flash library read-only variables can't be accessed for writing, even in subclasses *) - if c.cl_extern && (match c.cl_path with "flash" :: _ , _ -> true | _ -> false) && ctx.com.platform = Flash then - AccNever - else - AccNo - | "never" -> AccNever - | "dynamic" -> AccCall - | "default" -> AccNormal - | _ -> - let set = if set = "set" then "set_" ^ name else set in - if not is_lib then delay ctx PTypeField (fun() -> check_method set t_set (if set <> "set" && set <> "set_" ^ name then Some ("set_" ^ name) else None)); - AccCall - ) in - if set = AccNormal && (match get with AccCall -> true | _ -> false) then error (f.cff_name ^ ": Unsupported property combination") p; - let cf = { - cf_name = name; - cf_doc = f.cff_doc; - cf_meta = f.cff_meta; - cf_pos = f.cff_pos; - cf_kind = Var { v_read = get; v_write = set }; - cf_expr = None; - cf_type = ret; - cf_public = is_public f.cff_access None; - cf_params = []; - cf_overloads = []; - } in - ctx.curfield <- cf; - bind_var ctx cf eo stat inline; - f, false, cf, true - in - let rec check_require = function - | [] -> None - | (Meta.Require,conds,_) :: l -> - let rec loop = function - | [] -> check_require l - | e :: l -> - let sc = match fst e with - | EConst (Ident s) -> s - | EBinop ((OpEq|OpNotEq|OpGt|OpGte|OpLt|OpLte) as op,(EConst (Ident s),_),(EConst ((Int _ | Float _ | String _) as c),_)) -> s ^ s_binop op ^ s_constant c - | _ -> "" - in - if not (Parser.is_true (Parser.eval ctx.com e)) then - Some (sc,(match List.rev l with (EConst (String msg),_) :: _ -> Some msg | _ -> None)) - else - loop l - in - loop conds - | _ :: l -> - check_require l - in - let cl_req = check_require c.cl_meta in - List.iter (fun f -> - let p = f.cff_pos in - try - let fd , constr, f, do_add = loop_cf f in - let is_static = List.mem AStatic fd.cff_access in - if (is_static || constr) && c.cl_interface && f.cf_name <> "__init__" && not is_lib then error "You can't declare static fields in interfaces" p; - begin try - let _,args,_ = Meta.get Meta.IfFeature f.cf_meta in - List.iter (fun e -> match fst e with - | EConst(String s) -> - ctx.m.curmod.m_extra.m_if_feature <- (s,(c,f,is_static)) :: ctx.m.curmod.m_extra.m_if_feature; - | _ -> - error "String expected" (pos e) - ) args - with Not_found -> () end; - let req = check_require fd.cff_meta in - let req = (match req with None -> if is_static || constr then cl_req else None | _ -> req) in - (match req with - | None -> () - | Some r -> f.cf_kind <- Var { v_read = AccRequire (fst r, snd r); v_write = AccRequire (fst r, snd r) }); - if constr then begin - match c.cl_constructor with - | None -> - c.cl_constructor <- Some f - | Some ctor when ctx.com.config.pf_overload -> - if Meta.has Meta.Overload f.cf_meta && Meta.has Meta.Overload ctor.cf_meta then - ctor.cf_overloads <- f :: ctor.cf_overloads - else - display_error ctx ("If using overloaded constructors, all constructors must be declared with @:overload") (if Meta.has Meta.Overload f.cf_meta then ctor.cf_pos else f.cf_pos) - | Some ctor -> - display_error ctx "Duplicate constructor" p - end else if not is_static || f.cf_name <> "__init__" then begin - let dup = if is_static then PMap.exists f.cf_name c.cl_fields || has_field f.cf_name c.cl_super else PMap.exists f.cf_name c.cl_statics in - if not is_native && dup then error ("Same field name can't be use for both static and instance : " ^ f.cf_name) p; - if List.mem AOverride fd.cff_access then c.cl_overrides <- f :: c.cl_overrides; - let is_var f = match f.cf_kind with | Var _ -> true | _ -> false in - if PMap.mem f.cf_name (if is_static then c.cl_statics else c.cl_fields) then - if ctx.com.config.pf_overload && Meta.has Meta.Overload f.cf_meta && not (is_var f) then - let mainf = PMap.find f.cf_name (if is_static then c.cl_statics else c.cl_fields) in - if is_var mainf then display_error ctx "Cannot declare a variable with same name as a method" mainf.cf_pos; - (if not (Meta.has Meta.Overload mainf.cf_meta) then display_error ctx ("Overloaded methods must have @:overload metadata") mainf.cf_pos); - mainf.cf_overloads <- f :: mainf.cf_overloads - else - display_error ctx ("Duplicate class field declaration : " ^ f.cf_name) p - else - if not do_add then - () - else if is_static then begin - c.cl_statics <- PMap.add f.cf_name f c.cl_statics; - c.cl_ordered_statics <- f :: c.cl_ordered_statics; - end else begin - c.cl_fields <- PMap.add f.cf_name f c.cl_fields; - c.cl_ordered_fields <- f :: c.cl_ordered_fields; - end; - end - with Error (Custom str,p2) when p = p2 -> - display_error ctx str p - ) fields; - (match c.cl_kind with - | KAbstractImpl a -> - a.a_to_field <- List.rev a.a_to_field; - a.a_from_field <- List.rev a.a_from_field; - a.a_ops <- List.rev a.a_ops; - a.a_unops <- List.rev a.a_unops; - a.a_array <- List.rev a.a_array; - | _ -> ()); - c.cl_ordered_statics <- List.rev c.cl_ordered_statics; - c.cl_ordered_fields <- List.rev c.cl_ordered_fields; - (* - make sure a default contructor with same access as super one will be added to the class structure at some point. - *) - (* add_constructor does not deal with overloads correctly *) - if not ctx.com.config.pf_overload then add_constructor ctx c !force_constructor p; - (* check overloaded constructors *) - (if ctx.com.config.pf_overload && not is_lib then match c.cl_constructor with - | Some ctor -> - delay ctx PTypeField (fun() -> - List.iter (fun f -> - try - (* TODO: consider making a broader check, and treat some types, like TAnon and type parameters as Dynamic *) - ignore(List.find (fun f2 -> f != f2 && same_overload_args f.cf_type f2.cf_type f f2) (ctor :: ctor.cf_overloads)); - display_error ctx ("Another overloaded field of same signature was already declared : " ^ f.cf_name) f.cf_pos; - with Not_found -> () - ) (ctor :: ctor.cf_overloads) - ) - | _ -> ()); - (* push delays in reverse order so they will be run in correct order *) - List.iter (fun (ctx,r) -> - init_class_done ctx; - (match r with - | None -> () - | Some r -> delay ctx PTypeField (fun() -> ignore((!r)()))) - ) !delayed_expr - -let resolve_typedef t = - match t with - | TClassDecl _ | TEnumDecl _ | TAbstractDecl _ -> t - | TTypeDecl td -> - match follow td.t_type with - | TEnum (e,_) -> TEnumDecl e - | TInst (c,_) -> TClassDecl c - | TAbstract (a,_) -> TAbstractDecl a - | _ -> t - -let add_module ctx m p = - let decl_type t = - let t = t_infos t in - try - let m2 = Hashtbl.find ctx.g.types_module t.mt_path in - if m.m_path <> m2 && String.lowercase (s_type_path m2) = String.lowercase (s_type_path m.m_path) then error ("Module " ^ s_type_path m2 ^ " is loaded with a different case than " ^ s_type_path m.m_path) p; - error ("Type name " ^ s_type_path t.mt_path ^ " is redefined from module " ^ s_type_path m2) p - with - Not_found -> - Hashtbl.add ctx.g.types_module t.mt_path m.m_path - in - List.iter decl_type m.m_types; - Hashtbl.add ctx.g.modules m.m_path m - -(* - In this pass, we can access load and access other modules types, but we cannot follow them or access their structure - since they have not been setup. We also build a context_init list that will be evaluated the first time we evaluate - an expression into the context -*) -let rec init_module_type ctx context_init do_init (decl,p) = - let get_type name = - try List.find (fun t -> snd (t_infos t).mt_path = name) ctx.m.curmod.m_types with Not_found -> assert false - in - match decl with - | EImport (path,mode) -> - let rec loop acc = function - | x :: l when is_lower_ident (fst x) -> loop (x::acc) l - | rest -> List.rev acc, rest - in - let pack, rest = loop [] path in - (match rest with - | [] -> - (match mode with - | IAll -> - ctx.m.wildcard_packages <- List.map fst pack :: ctx.m.wildcard_packages - | _ -> - (match List.rev path with - | [] -> assert false - | (_,p) :: _ -> error "Module name must start with an uppercase letter" p)) - | (tname,p2) :: rest -> - let p1 = (match pack with [] -> p2 | (_,p1) :: _ -> p1) in - let p_type = punion p1 p2 in - let md = ctx.g.do_load_module ctx (List.map fst pack,tname) p_type in - let types = md.m_types in - let no_private t = not (t_infos t).mt_private in - let chk_private t p = if (t_infos t).mt_private then error "You can't import a private type" p in - let has_name name t = snd (t_infos t).mt_path = name in - let get_type tname = - let t = (try List.find (has_name tname) types with Not_found -> error (string_error tname (List.map (fun mt -> snd (t_infos mt).mt_path) types) ("Module " ^ s_type_path md.m_path ^ " does not define type " ^ tname)) p_type) in - chk_private t p_type; - t - in - let rebind t name = - if not (name.[0] >= 'A' && name.[0] <= 'Z') then - error "Type aliases must start with an uppercase letter" p; - let _, _, f = ctx.g.do_build_instance ctx t p_type in - (* create a temp private typedef, does not register it in module *) - TTypeDecl { - t_path = (fst md.m_path @ ["_" ^ snd md.m_path],name); - t_module = md; - t_pos = p; - t_private = true; - t_doc = None; - t_meta = []; - t_params = (t_infos t).mt_params; - t_type = f (List.map snd (t_infos t).mt_params); - } - in - let add_static_init t name s = - let name = (match name with None -> s | Some n -> n) in - match resolve_typedef t with - | TClassDecl c -> - ignore(c.cl_build()); - ignore(PMap.find s c.cl_statics); - ctx.m.module_globals <- PMap.add name (TClassDecl c,s) ctx.m.module_globals - | TEnumDecl e -> - ignore(PMap.find s e.e_constrs); - ctx.m.module_globals <- PMap.add name (TEnumDecl e,s) ctx.m.module_globals - | _ -> - raise Not_found - in - (match mode with - | INormal | IAsName _ -> - let name = (match mode with IAsName n -> Some n | _ -> None) in - (match rest with - | [] -> - (match name with - | None -> - ctx.m.module_types <- List.filter no_private types @ ctx.m.module_types - | Some newname -> - ctx.m.module_types <- rebind (get_type tname) newname :: ctx.m.module_types); - | [tsub,p2] -> - let p = punion p1 p2 in - (try - let tsub = List.find (has_name tsub) types in - chk_private tsub p; - ctx.m.module_types <- (match name with None -> tsub | Some n -> rebind tsub n) :: ctx.m.module_types - with Not_found -> - (* this might be a static property, wait later to check *) - let tmain = get_type tname in - context_init := (fun() -> - try - add_static_init tmain name tsub - with Not_found -> - error (s_type_path (t_infos tmain).mt_path ^ " has no field or subtype " ^ tsub) p - ) :: !context_init) - | (tsub,p2) :: (fname,p3) :: rest -> - (match rest with - | [] -> () - | (n,p) :: _ -> error ("Unexpected " ^ n) p); - let tsub = get_type tsub in - context_init := (fun() -> - try - add_static_init tsub name fname - with Not_found -> - error (s_type_path (t_infos tsub).mt_path ^ " has no field " ^ fname) (punion p p3) - ) :: !context_init; - ) - | IAll -> - let t = (match rest with - | [] -> get_type tname - | [tsub,_] -> get_type tsub - | _ :: (n,p) :: _ -> error ("Unexpected " ^ n) p - ) in - context_init := (fun() -> - match resolve_typedef t with - | TClassDecl c - | TAbstractDecl {a_impl = Some c} -> - ignore(c.cl_build()); - PMap.iter (fun _ cf -> if not (has_meta Meta.NoImportGlobal cf.cf_meta) then ctx.m.module_globals <- PMap.add cf.cf_name (TClassDecl c,cf.cf_name) ctx.m.module_globals) c.cl_statics - | TEnumDecl e -> - PMap.iter (fun _ c -> if not (has_meta Meta.NoImportGlobal c.ef_meta) then ctx.m.module_globals <- PMap.add c.ef_name (TEnumDecl e,c.ef_name) ctx.m.module_globals) e.e_constrs - | _ -> - error "No statics to import from this type" p - ) :: !context_init - )) - | EUsing t -> - (* do the import first *) - let types = (match t.tsub with - | None -> - let md = ctx.g.do_load_module ctx (t.tpackage,t.tname) p in - let types = List.filter (fun t -> not (t_infos t).mt_private) md.m_types in - ctx.m.module_types <- types @ ctx.m.module_types; - types - | Some _ -> - let t = load_type_def ctx p t in - ctx.m.module_types <- t :: ctx.m.module_types; - [t] - ) in - (* delay the using since we need to resolve typedefs *) - let filter_classes types = - let rec loop acc types = match types with - | td :: l -> - (match resolve_typedef td with - | TClassDecl c | TAbstractDecl({a_impl = Some c}) -> - loop (c :: acc) l - | td -> - loop acc l) - | [] -> - acc - in - loop [] types - in - context_init := (fun() -> ctx.m.module_using <- filter_classes types @ ctx.m.module_using) :: !context_init - | EClass d -> - let c = (match get_type d.d_name with TClassDecl c -> c | _ -> assert false) in - check_global_metadata ctx (fun m -> c.cl_meta <- m :: c.cl_meta) c.cl_module.m_path c.cl_path None; - let herits = d.d_flags in - if Meta.has Meta.Generic c.cl_meta && c.cl_params <> [] then c.cl_kind <- KGeneric; - if Meta.has Meta.GenericBuild c.cl_meta then c.cl_kind <- KGenericBuild d.d_data; - if c.cl_path = (["haxe";"macro"],"MacroType") then c.cl_kind <- KMacroType; - c.cl_extern <- List.mem HExtern herits; - c.cl_interface <- List.mem HInterface herits; - let rec build() = - c.cl_build <- (fun()-> false); - try - set_heritance ctx c herits p; - init_class ctx c p do_init d.d_flags d.d_data; - c.cl_build <- (fun()-> true); - List.iter (fun (_,t) -> ignore(follow t)) c.cl_params; - true; - with Exit -> - c.cl_build <- make_pass ctx build; - delay ctx PTypeField (fun() -> ignore(c.cl_build())); (* delay after PBuildClass, not very good but better than forgotten *) - false - | exn -> - c.cl_build <- (fun()-> true); - raise exn - in - ctx.pass <- PBuildClass; - ctx.curclass <- c; - c.cl_build <- make_pass ctx build; - ctx.pass <- PBuildModule; - ctx.curclass <- null_class; - delay ctx PBuildClass (fun() -> ignore(c.cl_build())); - if (ctx.com.platform = Java || ctx.com.platform = Cs) && not c.cl_extern then - delay ctx PTypeField (fun () -> - let metas = check_strict_meta ctx c.cl_meta in - if metas <> [] then c.cl_meta <- metas @ c.cl_meta; - let rec run_field cf = - let metas = check_strict_meta ctx cf.cf_meta in - if metas <> [] then cf.cf_meta <- metas @ cf.cf_meta; - List.iter run_field cf.cf_overloads - in - List.iter run_field c.cl_ordered_statics; - List.iter run_field c.cl_ordered_fields; - match c.cl_constructor with - | Some f -> run_field f - | _ -> () - ); - | EEnum d -> - let e = (match get_type d.d_name with TEnumDecl e -> e | _ -> assert false) in - let ctx = { ctx with type_params = e.e_params } in - let h = (try Some (Hashtbl.find ctx.g.type_patches e.e_path) with Not_found -> None) in - check_global_metadata ctx (fun m -> e.e_meta <- m :: e.e_meta) e.e_module.m_path e.e_path None; - (match h with - | None -> () - | Some (h,hcl) -> - Hashtbl.iter (fun _ _ -> error "Field type patch not supported for enums" e.e_pos) h; - e.e_meta <- e.e_meta @ hcl.tp_meta); - let constructs = ref d.d_data in - let get_constructs() = - List.map (fun c -> - { - cff_name = c.ec_name; - cff_doc = c.ec_doc; - cff_meta = c.ec_meta; - cff_pos = c.ec_pos; - cff_access = []; - cff_kind = (match c.ec_args, c.ec_params with - | [], [] -> FVar (c.ec_type,None) - | _ -> FFun { f_params = c.ec_params; f_type = c.ec_type; f_expr = None; f_args = List.map (fun (n,o,t) -> n,o,Some t,None) c.ec_args }); - } - ) (!constructs) - in - let init () = List.iter (fun f -> f()) !context_init in - build_module_def ctx (TEnumDecl e) e.e_meta get_constructs init (fun (e,p) -> - match e with - | EVars [_,Some (CTAnonymous fields),None] -> - constructs := List.map (fun f -> - let args, params, t = (match f.cff_kind with - | FVar (t,None) -> [], [], t - | FFun { f_params = pl; f_type = t; f_expr = (None|Some (EBlock [],_)); f_args = al } -> - let al = List.map (fun (n,o,t,_) -> match t with None -> error "Missing function parameter type" f.cff_pos | Some t -> n,o,t) al in - al, pl, t - | _ -> - error "Invalid enum constructor in @:build result" p - ) in - { - ec_name = f.cff_name; - ec_doc = f.cff_doc; - ec_meta = f.cff_meta; - ec_pos = f.cff_pos; - ec_args = args; - ec_params = params; - ec_type = t; - } - ) fields - | _ -> error "Enum build macro must return a single variable with anonymous object fields" p - ); - let et = TEnum (e,List.map snd e.e_params) in - let names = ref [] in - let index = ref 0 in - let is_flat = ref true in - let fields = ref PMap.empty in - List.iter (fun c -> - let p = c.ec_pos in - let params = ref [] in - params := List.map (fun tp -> type_type_params ~enum_constructor:true ctx ([],c.ec_name) (fun() -> !params) c.ec_pos tp) c.ec_params; - let params = !params in - let ctx = { ctx with type_params = params @ ctx.type_params } in - let rt = (match c.ec_type with - | None -> et - | Some t -> - let t = load_complex_type ctx p t in - (match follow t with - | TEnum (te,_) when te == e -> - () - | _ -> - error "Explicit enum type must be of the same enum type" p); - t - ) in - let t = (match c.ec_args with - | [] -> rt - | l -> - is_flat := false; - let pnames = ref PMap.empty in - TFun (List.map (fun (s,opt,t) -> - (match t with CTPath({tpackage=[];tname="Void"}) -> error "Arguments of type Void are not allowed in enum constructors" c.ec_pos | _ -> ()); - if PMap.mem s (!pnames) then error ("Duplicate parameter '" ^ s ^ "' in enum constructor " ^ c.ec_name) p; - pnames := PMap.add s () (!pnames); - s, opt, load_type_opt ~opt ctx p (Some t) - ) l, rt) - ) in - if PMap.mem c.ec_name e.e_constrs then error ("Duplicate constructor " ^ c.ec_name) p; - let f = { - ef_name = c.ec_name; - ef_type = t; - ef_pos = p; - ef_doc = c.ec_doc; - ef_index = !index; - ef_params = params; - ef_meta = c.ec_meta; - } in - let cf = { - cf_name = f.ef_name; - cf_public = true; - cf_type = f.ef_type; - cf_kind = (match follow f.ef_type with - | TFun _ -> Method MethNormal - | _ -> Var { v_read = AccNormal; v_write = AccNo } - ); - cf_pos = e.e_pos; - cf_doc = None; - cf_meta = no_meta; - cf_expr = None; - cf_params = f.ef_params; - cf_overloads = []; - } in - e.e_constrs <- PMap.add f.ef_name f e.e_constrs; - fields := PMap.add cf.cf_name cf !fields; - incr index; - names := c.ec_name :: !names; - ) (!constructs); - e.e_names <- List.rev !names; - e.e_extern <- e.e_extern; - e.e_type.t_params <- e.e_params; - e.e_type.t_type <- TAnon { - a_fields = !fields; - a_status = ref (EnumStatics e); - }; - if !is_flat then e.e_meta <- (Meta.FlatEnum,[],e.e_pos) :: e.e_meta; - - if (ctx.com.platform = Java || ctx.com.platform = Cs) && not e.e_extern then - delay ctx PTypeField (fun () -> - let metas = check_strict_meta ctx e.e_meta in - e.e_meta <- metas @ e.e_meta; - PMap.iter (fun _ ef -> - let metas = check_strict_meta ctx ef.ef_meta in - if metas <> [] then ef.ef_meta <- metas @ ef.ef_meta - ) e.e_constrs - ); - | ETypedef d -> - let t = (match get_type d.d_name with TTypeDecl t -> t | _ -> assert false) in - check_global_metadata ctx (fun m -> t.t_meta <- m :: t.t_meta) t.t_module.m_path t.t_path None; - let ctx = { ctx with type_params = t.t_params } in - let tt = load_complex_type ctx p d.d_data in - (* - we exceptionnaly allow follow here because we don't care the type we get as long as it's not our own - *) - (match d.d_data with - | CTExtend _ -> () - | _ -> - if t.t_type == follow tt then error "Recursive typedef is not allowed" p); - (match t.t_type with - | TMono r -> - (match !r with - | None -> r := Some tt; - | Some _ -> assert false); - | _ -> assert false); - if ctx.com.platform = Cs && t.t_meta <> [] then - delay ctx PTypeField (fun () -> - let metas = check_strict_meta ctx t.t_meta in - if metas <> [] then t.t_meta <- metas @ t.t_meta; - ); - | EAbstract d -> - let a = (match get_type d.d_name with TAbstractDecl a -> a | _ -> assert false) in - check_global_metadata ctx (fun m -> a.a_meta <- m :: a.a_meta) a.a_module.m_path a.a_path None; - let ctx = { ctx with type_params = a.a_params } in - let is_type = ref false in - let load_type t from = - let t = load_complex_type ctx p t in - let t = if not (Meta.has Meta.CoreType a.a_meta) then begin - if !is_type then begin - let r = exc_protect ctx (fun r -> - r := (fun() -> t); - let at = monomorphs a.a_params a.a_this in - (try (if from then Type.unify t at else Type.unify at t) with Unify_error _ -> error "You can only declare from/to with compatible types" p); - t - ) "constraint" in - delay ctx PForce (fun () -> ignore(!r())); - TLazy r - end else - error "Missing underlying type declaration or @:coreType declaration" p; - end else begin - if Meta.has Meta.Callable a.a_meta then - error "@:coreType abstracts cannot be @:callable" p; - t - end in - t - in - List.iter (function - | AFromType t -> a.a_from <- (load_type t true) :: a.a_from - | AToType t -> a.a_to <- (load_type t false) :: a.a_to - | AIsType t -> - if a.a_impl = None then error "Abstracts with underlying type must have an implementation" a.a_pos; - if Meta.has Meta.CoreType a.a_meta then error "@:coreType abstracts cannot have an underlying type" p; - let at = load_complex_type ctx p t in - (match at with TAbstract(a2,_) when a == a2 -> error "Abstract underlying type cannot be recursive" a.a_pos | _ -> ()); - a.a_this <- at; - is_type := true; - | APrivAbstract -> () - ) d.d_flags; - if not !is_type then begin - if Meta.has Meta.CoreType a.a_meta then - a.a_this <- TAbstract(a,List.map snd a.a_params) - else - error "Abstract is missing underlying type declaration" a.a_pos - end - -let type_module ctx m file ?(is_extern=false) tdecls p = - let m, decls, tdecls = make_module ctx m file tdecls p in - if is_extern then m.m_extra.m_kind <- MExtern; - add_module ctx m p; - (* define the per-module context for the next pass *) - let ctx = { - com = ctx.com; - g = ctx.g; - t = ctx.t; - m = { - curmod = m; - module_types = ctx.g.std.m_types; - module_using = []; - module_globals = PMap.empty; - wildcard_packages = []; - }; - meta = []; - this_stack = []; - with_type_stack = []; - call_argument_stack = []; - pass = PBuildModule; - on_error = (fun ctx msg p -> ctx.com.error msg p); - macro_depth = ctx.macro_depth; - curclass = null_class; - curfield = null_field; - tthis = ctx.tthis; - ret = ctx.ret; - locals = PMap.empty; - type_params = []; - curfun = FunStatic; - untyped = false; - in_super_call = false; - in_macro = ctx.in_macro; - in_display = false; - in_loop = false; - opened = []; - vthis = None; - } in - if ctx.g.std != null_module then begin - add_dependency m ctx.g.std; - (* this will ensure both String and (indirectly) Array which are basic types which might be referenced *) - ignore(load_core_type ctx "String"); - end; - (* here is an additional PASS 1 phase, which define the type parameters for all module types. - Constraints are handled lazily (no other type is loaded) because they might be recursive anyway *) - List.iter (fun d -> - match d with - | (TClassDecl c, (EClass d, p)) -> - c.cl_params <- List.map (type_type_params ctx c.cl_path (fun() -> c.cl_params) p) d.d_params; - | (TEnumDecl e, (EEnum d, p)) -> - e.e_params <- List.map (type_type_params ctx e.e_path (fun() -> e.e_params) p) d.d_params; - | (TTypeDecl t, (ETypedef d, p)) -> - t.t_params <- List.map (type_type_params ctx t.t_path (fun() -> t.t_params) p) d.d_params; - | (TAbstractDecl a, (EAbstract d, p)) -> - a.a_params <- List.map (type_type_params ctx a.a_path (fun() -> a.a_params) p) d.d_params; - | _ -> - assert false - ) decls; - (* setup module types *) - let context_init = ref [] in - let do_init() = - match !context_init with - | [] -> () - | l -> context_init := []; List.iter (fun f -> f()) (List.rev l) - in - List.iter (init_module_type ctx context_init do_init) tdecls; - m - - -let resolve_module_file com m remap p = - let forbid = ref false in - let file = (match m with - | [] , name -> name - | x :: l , name -> - let x = (try - match PMap.find x com.package_rules with - | Forbidden -> forbid := true; x - | Directory d -> d - | Remap d -> remap := d :: l; d - with Not_found -> x - ) in - String.concat "/" (x :: l) ^ "/" ^ name - ) ^ ".hx" in - let file = Common.find_file com file in - let file = (match String.lowercase (snd m) with - | "con" | "aux" | "prn" | "nul" | "com1" | "com2" | "com3" | "lpt1" | "lpt2" | "lpt3" when Sys.os_type = "Win32" -> - (* these names are reserved by the OS - old DOS legacy, such files cannot be easily created but are reported as visible *) - if (try (Unix.stat file).Unix.st_size with _ -> 0) > 0 then file else raise Not_found - | _ -> file - ) in - (* if we try to load a std.xxxx class and resolve a real std file, the package name is not valid, ignore *) - (match fst m with - | "std" :: _ -> - let file = Common.unique_full_path file in - if List.exists (fun path -> ExtString.String.starts_with file (try Common.unique_full_path path with _ -> path)) com.std_path then raise Not_found; - | _ -> ()); - if !forbid then begin - let _, decls = (!parse_hook) com file p in - let rec loop decls = match decls with - | ((EImport _,_) | (EUsing _,_)) :: decls -> loop decls - | (EClass d,_) :: _ -> d.d_meta - | (EEnum d,_) :: _ -> d.d_meta - | (EAbstract d,_) :: _ -> d.d_meta - | (ETypedef d,_) :: _ -> d.d_meta - | [] -> [] - in - let meta = loop decls in - if not (Meta.has Meta.NoPackageRestrict meta) then begin - let x = (match fst m with [] -> assert false | x :: _ -> x) in - raise (Forbid_package ((x,m,p),[],if Common.defined com Define.Macro then "macro" else platform_name com.platform)); - end; - end; - file - -let parse_module ctx m p = - let remap = ref (fst m) in - let file = resolve_module_file ctx.com m remap p in - let pack, decls = (!parse_hook) ctx.com file p in - if pack <> !remap then begin - let spack m = if m = [] then "" else String.concat "." m in - if p == Ast.null_pos then - display_error ctx ("Invalid commandline class : " ^ s_type_path m ^ " should be " ^ s_type_path (pack,snd m)) p - else - display_error ctx ("Invalid package : " ^ spack (fst m) ^ " should be " ^ spack pack) p - end; - file, if !remap <> fst m then - (* build typedefs to redirect to real package *) - List.rev (List.fold_left (fun acc (t,p) -> - let build f d = - let priv = List.mem f d.d_flags in - (ETypedef { - d_name = d.d_name; - d_doc = None; - d_meta = []; - d_params = d.d_params; - d_flags = if priv then [EPrivate] else []; - d_data = CTPath (if priv then { tpackage = []; tname = "Dynamic"; tparams = []; tsub = None; } else - { - tpackage = !remap; - tname = d.d_name; - tparams = List.map (fun tp -> - TPType (CTPath { tpackage = []; tname = tp.tp_name; tparams = []; tsub = None; }) - ) d.d_params; - tsub = None; - }); - },p) :: acc - in - match t with - | EClass d -> build HPrivate d - | EEnum d -> build EPrivate d - | ETypedef d -> build EPrivate d - | EAbstract d -> build APrivAbstract d - | EImport _ | EUsing _ -> acc - ) [(EImport (List.map (fun s -> s,null_pos) (!remap @ [snd m]),INormal),null_pos)] decls) - else - decls - -let load_module ctx m p = - let m2 = (try - Hashtbl.find ctx.g.modules m - with - Not_found -> - match !type_module_hook ctx m p with - | Some m -> m - | None -> - let is_extern = ref false in - let file, decls = (try - parse_module ctx m p - with Not_found -> - let rec loop = function - | [] -> - raise (Error (Module_not_found m,p)) - | load :: l -> - match load m p with - | None -> loop l - | Some (file,(_,a)) -> file, a - in - is_extern := true; - loop ctx.com.load_extern_type - ) in - let is_extern = !is_extern in - try - type_module ctx m file ~is_extern decls p - with Forbid_package (inf,pl,pf) when p <> Ast.null_pos -> - raise (Forbid_package (inf,p::pl,pf)) - ) in - add_dependency ctx.m.curmod m2; - if ctx.pass = PTypeField then flush_pass ctx PBuildClass "load_module"; - m2 - -;; -type_function_params_rec := type_function_params -- GitLab From e80289a62a84a924f260725cd967077a811ee2b1 Mon Sep 17 00:00:00 2001 From: Andy Li Date: Wed, 1 Feb 2017 17:54:52 +0800 Subject: [PATCH 2/8] update changelog, d/watch, and get-orig-source --- debian/changelog | 10 ++++++++++ debian/rules | 7 ++----- debian/watch | 4 ++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/debian/changelog b/debian/changelog index c0a79ae6..9d9cca53 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +haxe (1:3.4.0) unstable; urgency=low + + * New upstream version. + + Depends on PCRE. + + There is no bundled jQuery source file, thus, remove +dfsg tag. + + Remove upstream applied patch. + * Update d/watch and get-orig-source target (no +dfsg). + + -- Andy Li Wed, 01 Feb 2017 17:25:01 +0800 + haxe (1:3.2.1+dfsg-1) unstable; urgency=low * New upstream version. diff --git a/debian/rules b/debian/rules index 8912f4ba..e483abc8 100755 --- a/debian/rules +++ b/debian/rules @@ -6,9 +6,7 @@ PKD = $(abspath $(dir $(MAKEFILE_LIST))) PKG = haxe -UVER = $(shell dpkg-parsechangelog -l$(PKD)/changelog | perl -ne 'print $$1 if m{^Version:\s+(?:\d+:)?(\d.*)(?:\-\d+.*)};') -DTYPE = +dfsg -VER ?= $(subst $(DTYPE),,$(UVER)) +VER = $(shell dpkg-parsechangelog -l$(PKD)/changelog | perl -ne 'print $$1 if m{^Version:\s+(?:\d+:)?(\d.*)};') override_dh_auto_configure: @@ -28,6 +26,5 @@ get-orig-source: # create tar manually from git, in order to get submodules and remove js source files git clone --branch $(VER) --depth 1 --recursive https://github.com/HaxeFoundation/haxe.git orig-source cd orig-source && \ - rm std/js/*.js && git commit -am "removed js source files for debian" && \ python $(CURDIR)/debian/git-archive-all ../../$(PKG)_$(VER)$(DTYPE).orig.tar.gz - rm -rf orig-source \ No newline at end of file + rm -rf orig-source diff --git a/debian/watch b/debian/watch index 19989bdf..19d902e3 100644 --- a/debian/watch +++ b/debian/watch @@ -1,3 +1,3 @@ version=3 -opts="dversionmangle=s/\+dfsg//,uversionmangle=s/-/~/g,repacksuffix=+dfsg"\ - https://github.com/HaxeFoundation/haxe/releases .*/(\d\S*)\.tar\.gz \ No newline at end of file +opts="uversionmangle=s/-/~/g"\ + https://github.com/HaxeFoundation/haxe/releases .*/(\d\S*)\.tar\.gz -- GitLab From 9ba4474616e840b5853bd70eed5491c172152738 Mon Sep 17 00:00:00 2001 From: Andy Li Date: Wed, 1 Feb 2017 18:13:48 +0800 Subject: [PATCH 3/8] minor fixes --- debian/changelog | 2 +- debian/rules | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 9d9cca53..c19cce74 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -haxe (1:3.4.0) unstable; urgency=low +haxe (1:3.4.0-1) unstable; urgency=low * New upstream version. + Depends on PCRE. diff --git a/debian/rules b/debian/rules index e483abc8..e223851a 100755 --- a/debian/rules +++ b/debian/rules @@ -23,7 +23,7 @@ override_dh_strip: dh_strip --exclude=haxelib get-orig-source: - # create tar manually from git, in order to get submodules and remove js source files + # create tar manually from git, in order to get submodules git clone --branch $(VER) --depth 1 --recursive https://github.com/HaxeFoundation/haxe.git orig-source cd orig-source && \ python $(CURDIR)/debian/git-archive-all ../../$(PKG)_$(VER)$(DTYPE).orig.tar.gz -- GitLab From 499b7dfa4308c024bdf3ea9e446412c7c34e80a9 Mon Sep 17 00:00:00 2001 From: Andy Li Date: Thu, 2 Feb 2017 01:04:04 +0800 Subject: [PATCH 4/8] Bump Standards-Version to 3.9.8 (no changes). --- debian/changelog | 3 ++- debian/control | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index c19cce74..621f23aa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,8 +5,9 @@ haxe (1:3.4.0-1) unstable; urgency=low + There is no bundled jQuery source file, thus, remove +dfsg tag. + Remove upstream applied patch. * Update d/watch and get-orig-source target (no +dfsg). + * Bump Standards-Version to 3.9.8 (no changes). - -- Andy Li Wed, 01 Feb 2017 17:25:01 +0800 + -- Andy Li Thu, 02 Feb 2017 01:03:21 +0800 haxe (1:3.2.1+dfsg-1) unstable; urgency=low diff --git a/debian/control b/debian/control index ef4f98a2..5c67617b 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: haxe Section: devel Priority: optional Maintainer: Andy Li -Standards-Version: 3.9.6 +Standards-Version: 3.9.8 Build-Depends: camlp4 (>= 3.11), debhelper (>= 9), libxml-light-ocaml-dev, -- GitLab From e2daee7b43d62652144e0270053938a1759d3f57 Mon Sep 17 00:00:00 2001 From: Andy Li Date: Thu, 2 Feb 2017 01:17:13 +0800 Subject: [PATCH 5/8] Update d/copyright --- debian/changelog | 3 ++- debian/copyright | 24 ++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/debian/changelog b/debian/changelog index 621f23aa..3fe14cf2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,10 +4,11 @@ haxe (1:3.4.0-1) unstable; urgency=low + Depends on PCRE. + There is no bundled jQuery source file, thus, remove +dfsg tag. + Remove upstream applied patch. + + Update d/copyright. * Update d/watch and get-orig-source target (no +dfsg). * Bump Standards-Version to 3.9.8 (no changes). - -- Andy Li Thu, 02 Feb 2017 01:03:21 +0800 + -- Andy Li Thu, 02 Feb 2017 01:15:54 +0800 haxe (1:3.2.1+dfsg-1) unstable; urgency=low diff --git a/debian/copyright b/debian/copyright index 1149ec7b..d9430b15 100644 --- a/debian/copyright +++ b/debian/copyright @@ -2,10 +2,9 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: The Haxe Foundation Upstream-Contact: http://haxe.org/foundation/contact.html Source: https://github.com/HaxeFoundation/haxe -Files-Excluded: std/js/jquery-latest.min.js std/js/swfobject-1.5.js Files: * -Copyright: 2005-2013, Haxe Foundation +Copyright: 2005-2017, Haxe Foundation License: Expat Files: debian/* @@ -21,14 +20,6 @@ Files: libs/* Copyright: 2004-2008, Nicolas Cannasse License: GPL-2+ -Files: libs/extc/zlib/* -Copyright: 1995-2005, Jean-loup Gailly and Mark Adler -License: Zlib - -Files: libs/extc/zlib/zconf.h -Copyright: 1995-2005, Jean-loup Gailly -License: Zlib - Files: libs/extlib/* Copyright: 201, 2003, 2004, 2012, Nicolas Cannasse License: LGPL-2.1+ @@ -94,6 +85,10 @@ Copyright: 2003, Nicolas Cannasse (ncannasse@motion-twin.com) 2003, Jacques Garrigue License: LGPL-2.1+ +Files: libs/pcre/* +Copyright: 1999, Markus Mottl (markus.mottl@gmail.com) +License: LGPL-2+ + License: Expat The MIT License . @@ -140,6 +135,15 @@ License: LGPL-2.1+ On Debian systems, the complete text of version 2.1 of the GNU Lesser General Public License can be found in `/usr/share/common-licenses/LGPL-2.1'. +License: LGPL-2+ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + . + On Debian systems, the complete text of version 2 of the GNU Lesser + General Public License can be found in `/usr/share/common-licenses/LGPL-2'. + License: Zlib The zlib License . -- GitLab From 6cb23baa347625c03ecbe037d27097663501c9db Mon Sep 17 00:00:00 2001 From: Andy Li Date: Thu, 2 Feb 2017 01:21:42 +0800 Subject: [PATCH 6/8] fix get-orig-source --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index e223851a..e3955633 100755 --- a/debian/rules +++ b/debian/rules @@ -6,7 +6,7 @@ PKD = $(abspath $(dir $(MAKEFILE_LIST))) PKG = haxe -VER = $(shell dpkg-parsechangelog -l$(PKD)/changelog | perl -ne 'print $$1 if m{^Version:\s+(?:\d+:)?(\d.*)};') +VER = $(shell dpkg-parsechangelog -l$(PKD)/changelog | perl -ne 'print $$1 if m{^Version:\s+(?:\d+:)?(\d.*)(?:\-\d+.*)};') override_dh_auto_configure: -- GitLab From 422210310ca864e9693e490434f148c95ce8d2b2 Mon Sep 17 00:00:00 2001 From: Andy Li Date: Thu, 2 Feb 2017 01:30:35 +0800 Subject: [PATCH 7/8] removed redundent zlib license --- debian/copyright | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/debian/copyright b/debian/copyright index d9430b15..98061fb1 100644 --- a/debian/copyright +++ b/debian/copyright @@ -144,24 +144,3 @@ License: LGPL-2+ On Debian systems, the complete text of version 2 of the GNU Lesser General Public License can be found in `/usr/share/common-licenses/LGPL-2'. -License: Zlib - The zlib License - . - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - . - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - . - 1. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - . - 2. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - . - 3. This notice may not be removed or altered from any source - distribution. -- GitLab From ae20376aac280f4c799a3c0649194c738747f0e9 Mon Sep 17 00:00:00 2001 From: Andy Li Date: Thu, 2 Feb 2017 09:30:02 +0800 Subject: [PATCH 8/8] Remove dependencies of libjs-jquery and libjs-swfobject. --- debian/changelog | 3 ++- debian/control | 4 +--- debian/haxe.links | 2 -- 3 files changed, 3 insertions(+), 6 deletions(-) delete mode 100644 debian/haxe.links diff --git a/debian/changelog b/debian/changelog index 3fe14cf2..efd44e69 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,12 +3,13 @@ haxe (1:3.4.0-1) unstable; urgency=low * New upstream version. + Depends on PCRE. + There is no bundled jQuery source file, thus, remove +dfsg tag. + + Remove dependencies of libjs-jquery and libjs-swfobject. + Remove upstream applied patch. + Update d/copyright. * Update d/watch and get-orig-source target (no +dfsg). * Bump Standards-Version to 3.9.8 (no changes). - -- Andy Li Thu, 02 Feb 2017 01:15:54 +0800 + -- Andy Li Thu, 02 Feb 2017 09:27:56 +0800 haxe (1:3.2.1+dfsg-1) unstable; urgency=low diff --git a/debian/control b/debian/control index 5c67617b..5c7b5a8f 100644 --- a/debian/control +++ b/debian/control @@ -19,9 +19,7 @@ Homepage: http://haxe.org Package: haxe Architecture: any -Depends: libjs-jquery, - libjs-swfobject, - neko (>= 2.0.0), +Depends: neko (>= 2.0.0), ${misc:Depends}, ${ocaml:Depends}, ${shlibs:Depends} diff --git a/debian/haxe.links b/debian/haxe.links deleted file mode 100644 index 02fb9480..00000000 --- a/debian/haxe.links +++ /dev/null @@ -1,2 +0,0 @@ -usr/share/javascript/jquery/jquery.min.js usr/share/haxe/std/js/jquery-latest.min.js -usr/share/javascript/swfobject/swfobject.js usr/share/haxe/std/js/swfobject-1.5.js -- GitLab